diff --git a/CMakeLists.txt b/CMakeLists.txt index c13ba7110..cb5caa1ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,15 +11,8 @@ endif() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake") include(CMakeDependentOption) -set(DEPENDENCIES "dependencies") -# In case of 64-bit windows, use a different path for dependencies -# so that both dependencies can be installed next to each other -if ( WIN32 AND (CMAKE_SIZEOF_VOID_P EQUAL 8 ) ) - set(DEPENDENCIES "dependencies-64bit") -endif() - include(BuildTypeSTKRelease) -if (NOT CMAKE_BUILD_TYPE) +if(NOT CMAKE_BUILD_TYPE) message(STATUS "No build type selected, default to STKRelease") set(CMAKE_BUILD_TYPE "STKRelease") endif() @@ -28,12 +21,13 @@ option(SERVER_ONLY "Create a server only (i.e. no graphics or sound)" OFF) option(USE_FRIBIDI "Support for right-to-left languages" ON) option(CHECK_ASSETS "Check if assets are installed in ../stk-assets" ON) option(USE_SYSTEM_ANGELSCRIPT "Use system angelscript instead of built-in angelscript. If you enable this option, make sure to use a compatible version." OFF) +option(USE_SYSTEM_ENET "Use system ENET instead of the built-in version, when available." ON) option(USE_SYSTEM_GLEW "Use system GLEW instead of the built-in version, when available." ON) CMAKE_DEPENDENT_OPTION(BUILD_RECORDER "Build opengl recorder" ON "NOT SERVER_ONLY;NOT USE_GLES2;NOT APPLE" OFF) -if ((UNIX AND NOT APPLE) AND NOT SERVER_ONLY) +if((UNIX AND NOT APPLE) AND NOT SERVER_ONLY) option(ENABLE_WAYLAND_DEVICE "Enable Wayland device for linux build" ON) option(USE_GLES2 "Use OpenGL ES2 renderer" OFF) endif() @@ -73,6 +67,32 @@ set(STK_INSTALL_BINARY_DIR "bin" CACHE set(STK_INSTALL_DATA_DIR "share/supertuxkart" CACHE STRING "Install data folder to this directory, absolute or relative to CMAKE_INSTALL_PREFIX") +# Define dependencies path +if(MSVC) + set(DEPENDENCIES "dependencies-vs") +elseif(MINGW) + set(DEPENDENCIES "dependencies-mingw") +else() + set(DEPENDENCIES "dependencies") +endif() + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(DEPENDENCIES "${DEPENDENCIES}-64bit") +endif() + +if(WIN32) + if(NOT IS_DIRECTORY "${PROJECT_SOURCE_DIR}/${DEPENDENCIES}") + set(DEPENDENCIES "dependencies") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(DEPENDENCIES "${DEPENDENCIES}-64bit") + endif() + endif() + + if(NOT IS_DIRECTORY "${PROJECT_SOURCE_DIR}/${DEPENDENCIES}") + message(FATAL_ERROR "Dependencies directory not found.") + endif() +endif() + # These variables enable MSVC to find libraries located in "dependencies" if(WIN32) set(ENV{PATH} "$ENV{PATH};${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/include") @@ -107,14 +127,24 @@ endif() add_subdirectory("${PROJECT_SOURCE_DIR}/lib/bullet") include_directories("${PROJECT_SOURCE_DIR}/lib/bullet/src") -# Build the ENet UDP network library -add_subdirectory("${PROJECT_SOURCE_DIR}/lib/enet") -include_directories("${PROJECT_SOURCE_DIR}/lib/enet/include") +# Find system ENet library or build it if missing +if((UNIX AND NOT APPLE) AND USE_SYSTEM_ENET) + find_package(ENet) +endif() + +if(ENET_FOUND) + include_directories(${ENet_INCLUDE_DIRS}) +else() + # Fallback to built-in version + add_subdirectory("${PROJECT_SOURCE_DIR}/lib/enet") + include_directories("${PROJECT_SOURCE_DIR}/lib/enet/include") + set(ENet_LIBRARIES "enet") +endif() # Find system GLEW library or build it if missing if(NOT USE_GLES2 AND NOT SERVER_ONLY) add_definitions(-DGLEW_NO_GLU) - if(USE_SYSTEM_GLEW) + if((UNIX AND NOT APPLE) AND USE_SYSTEM_GLEW) find_package(PkgConfig) if(PKGCONFIG_FOUND) pkg_check_modules(GLEW glew>=2.1) @@ -434,7 +464,7 @@ target_link_libraries(supertuxkart bulletdynamics bulletcollision bulletmath - enet + ${ENet_LIBRARIES} stkirrlicht ${Angelscript_LIBRARIES} ${CURL_LIBRARIES} @@ -575,7 +605,7 @@ install(FILES ${STK_DATA_DIR}/supertuxkart.desktop DESTINATION share/application install(FILES data/supertuxkart_48.png DESTINATION share/icons/hicolor/48x48/apps RENAME supertuxkart.png) install(FILES data/supertuxkart_128.png DESTINATION share/icons/hicolor/128x128/apps RENAME supertuxkart.png) install(FILES data/supertuxkart_48.png DESTINATION share/pixmaps RENAME supertuxkart.png) -install(FILES data/supertuxkart.appdata.xml DESTINATION share/appdata) +install(FILES data/supertuxkart.appdata.xml DESTINATION share/metainfo) if(MINGW) install(DIRECTORY ${CMAKE_BINARY_DIR}/bin/ DESTINATION ${STK_INSTALL_BINARY_DIR} diff --git a/README.md b/README.md index 6e28c7bb4..972109cc0 100644 --- a/README.md +++ b/README.md @@ -108,10 +108,10 @@ To Build SuperTuxKart on Windows, follow these instructions: 1. Download and install Visual Studio from here: [Visual Studio - Download](https://www.visualstudio.com/downloads/). The free Visual Studio Community edition works fine. 2. Download the SuperTuxKart source package from either [SuperTuxKart download area - SourceForge.net](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart/0.9.2) or [SuperTuxKart.net - Source Control](https://supertuxkart.net/Source_control), and unpack it. *Note: If you downloaded the source package from here: [SuperTuxKart.net - Source Control](https://supertuxkart.net/Source_control), then both `stk-code` and `stk-assets` **must** be in the same directory, otherwise the build can result in failure* -3. Download the Windows dependencies package from either [SuperTuxKart download area: Dependecies - SourceForge.net](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/Windows/) +3. Download the Windows dependencies package from either [SuperTuxKart download area: Dependencies - SourceForge.net](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/Windows/) or [SuperTuxKart on GitHub - Dependencies](https://github.com/supertuxkart/dependencies), and unpack it; then, copy the `dependencies` directory from either the `windows` or the `windows_64bit` directories into the `stk-code` directory, rename it to `dependencies-64bit` if you want to compile a 64bit build. 4. Download CMake from here: [CMake - download page](https://cmake.org/download/), install it; once CMake is installed, double click on the CMake icon on your desktop, and point it towards your `stk-code` directory in the 'Where is the source code' field, and point it to a directory called `build` or `bld` inside the stk-code directory. -5. Press 'Configure'; CMake will ask you if it is OK to create the aformentioned directory, press `Yes`. CMake will then ask you about your version of Visual Studio. +5. Press 'Configure'; CMake will ask you if it is OK to create the aforementioned directory, press `Yes`. CMake will then ask you about your version of Visual Studio. Confirm your selection; *Please look at the table below to avoid confusion between version numbers and releases of Visual Studio*; CMake will begin creating the required files for the build in the directory. 6. Navigate to your build directory and open the `SuperTuxKart.sln` file; Visual Studio will now load the solution. diff --git a/android/Android.mk b/android/Android.mk index 08728da5f..947ca5490 100644 --- a/android/Android.mk +++ b/android/Android.mk @@ -162,6 +162,8 @@ LOCAL_CFLAGS := -I../lib/angelscript/include \ -DUSE_GLES2 \ -DHAVE_OGGVORBIS \ -DNDEBUG \ + -DANDROID_PACKAGE_NAME=\"$(PACKAGE_NAME)\" \ + -DANDROID_APP_DIR_NAME=\"$(APP_DIR_NAME)\" \ -std=gnu++0x LOCAL_STATIC_LIBRARIES := irrlicht bullet enet freetype ifaddrs angelscript \ diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 5b815379c..71e797ef7 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -8,6 +8,7 @@ @@ -24,12 +25,16 @@ + + + + diff --git a/android/banner.png b/android/banner.png new file mode 100644 index 000000000..9d05b0c0d Binary files /dev/null and b/android/banner.png differ diff --git a/android/build.gradle b/android/build.gradle index 4fae7a216..19fda57b1 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -15,7 +15,7 @@ apply plugin: 'com.android.application' android { - compileSdkVersion sdk_version.toInteger() + compileSdkVersion compile_sdk_version.toInteger() buildToolsVersion build_tools_ver sourceSets diff --git a/android/make.sh b/android/make.sh index 7fac9f3c6..3b2732aa9 100755 --- a/android/make.sh +++ b/android/make.sh @@ -22,25 +22,39 @@ export NDK_ABI_ARMV7=armeabi-v7a export ARCH_ARMV7=arm export HOST_ARMV7=arm-linux-androideabi export NDK_PLATFORM_ARMV7=android-19 -export SDK_VERSION_ARMV7=19 +export MIN_SDK_VERSION_ARMV7=19 +export TARGET_SDK_VERSION_ARMV7=21 +export COMPILE_SDK_VERSION_ARMV7=21 export NDK_ABI_X86=x86 export ARCH_X86=x86 export HOST_X86=i686-linux-android export NDK_PLATFORM_X86=android-19 -export SDK_VERSION_X86=19 +export MIN_SDK_VERSION_X86=19 +export TARGET_SDK_VERSION_X86=21 +export COMPILE_SDK_VERSION_X86=21 export NDK_ABI_AARCH64=arm64-v8a export ARCH_AARCH64=arm64 export HOST_AARCH64=aarch64-linux-android export NDK_PLATFORM_AARCH64=android-21 -export SDK_VERSION_AARCH64=21 +export MIN_SDK_VERSION_AARCH64=21 +export TARGET_SDK_VERSION_AARCH64=21 +export COMPILE_SDK_VERSION_AARCH64=21 export APP_NAME_RELEASE="SuperTuxKart" -export APP_NAME_DEBUG="SuperTuxKart Debug" export PACKAGE_NAME_RELEASE="org.supertuxkart.stk" -export PACKAGE_NAME_DEBUG="org.supertuxkart.stk_dev" +export APP_DIR_NAME_RELEASE="supertuxkart" export APP_ICON_RELEASE="$DIRNAME/icon.png" + +export APP_NAME_BETA="SuperTuxKart Beta" +export PACKAGE_NAME_BETA="org.supertuxkart.stk_beta" +export APP_DIR_NAME_BETA="supertuxkart-beta" +export APP_ICON_BETA="$DIRNAME/icon-dbg.png" + +export APP_NAME_DEBUG="SuperTuxKart Debug" +export PACKAGE_NAME_DEBUG="org.supertuxkart.stk_dbg" +export APP_DIR_NAME_DEBUG="supertuxkart-dbg" export APP_ICON_DEBUG="$DIRNAME/icon-dbg.png" @@ -88,19 +102,25 @@ if [ "$COMPILE_ARCH" = "armv7" ]; then export NDK_ABI=$NDK_ABI_ARMV7 export ARCH=$ARCH_ARMV7 export HOST=$HOST_ARMV7 - export SDK_VERSION=$SDK_VERSION_ARMV7 + export MIN_SDK_VERSION=$MIN_SDK_VERSION_ARMV7 + export TARGET_SDK_VERSION=$TARGET_SDK_VERSION_ARMV7 + export COMPILE_SDK_VERSION=$COMPILE_SDK_VERSION_ARMV7 elif [ "$COMPILE_ARCH" = "x86" ]; then export NDK_PLATFORM=$NDK_PLATFORM_X86 export NDK_ABI=$NDK_ABI_X86 export ARCH=$ARCH_X86 export HOST=$HOST_X86 - export SDK_VERSION=$SDK_VERSION_X86 + export MIN_SDK_VERSION=$MIN_SDK_VERSION_X86 + export TARGET_SDK_VERSION=$TARGET_SDK_VERSION_X86 + export COMPILE_SDK_VERSION=$COMPILE_SDK_VERSION_X86 elif [ "$COMPILE_ARCH" = "aarch64" ]; then export NDK_PLATFORM=$NDK_PLATFORM_AARCH64 export NDK_ABI=$NDK_ABI_AARCH64 export ARCH=$ARCH_AARCH64 export HOST=$HOST_AARCH64 - export SDK_VERSION=$SDK_VERSION_AARCH64 + export MIN_SDK_VERSION=$MIN_SDK_VERSION_AARCH64 + export TARGET_SDK_VERSION=$TARGET_SDK_VERSION_AARCH64 + export COMPILE_SDK_VERSION=$COMPILE_SDK_VERSION_AARCH64 else echo "Unknow COMPILE_ARCH: $COMPILE_ARCH. Possible values are: " \ "armv7, aarch64, x86" @@ -118,6 +138,7 @@ if [ "$BUILD_TYPE" = "debug" ] || [ "$BUILD_TYPE" = "Debug" ]; then export IS_DEBUG_BUILD=1 export APP_NAME="$APP_NAME_DEBUG" export PACKAGE_NAME="$PACKAGE_NAME_DEBUG" + export APP_DIR_NAME="$APP_DIR_NAME_DEBUG" export APP_ICON="$APP_ICON_DEBUG" elif [ "$BUILD_TYPE" = "release" ] || [ "$BUILD_TYPE" = "Release" ]; then export ANT_BUILD_TYPE="release" @@ -125,7 +146,16 @@ elif [ "$BUILD_TYPE" = "release" ] || [ "$BUILD_TYPE" = "Release" ]; then export IS_DEBUG_BUILD=0 export APP_NAME="$APP_NAME_RELEASE" export PACKAGE_NAME="$PACKAGE_NAME_RELEASE" + export APP_DIR_NAME="$APP_DIR_NAME_RELEASE" export APP_ICON="$APP_ICON_RELEASE" +elif [ "$BUILD_TYPE" = "beta" ] || [ "$BUILD_TYPE" = "Beta" ]; then + export ANT_BUILD_TYPE="release" + export GRADLE_BUILD_TYPE="assembleRelease" + export IS_DEBUG_BUILD=0 + export APP_NAME="$APP_NAME_BETA" + export PACKAGE_NAME="$PACKAGE_NAME_BETA" + export APP_DIR_NAME="$APP_DIR_NAME_BETA" + export APP_ICON="$APP_ICON_BETA" else echo "Unsupported BUILD_TYPE: $BUILD_TYPE. Possible values are: " \ "debug, release" @@ -370,12 +400,16 @@ echo "" >> "$STRINGS_FILE" echo " $APP_NAME" >> "$STRINGS_FILE" echo "" >> "$STRINGS_FILE" -sed -i "s/minSdkVersion=\".*\"/minSdkVersion=\"$SDK_VERSION\"/g" \ +sed -i "s/minSdkVersion=\".*\"/minSdkVersion=\"$MIN_SDK_VERSION\"/g" \ + "$DIRNAME/AndroidManifest.xml" + +sed -i "s/targetSdkVersion=\".*\"/targetSdkVersion=\"$TARGET_SDK_VERSION\"/g" \ "$DIRNAME/AndroidManifest.xml" sed -i "s/package=\".*\"/package=\"$PACKAGE_NAME\"/g" \ "$DIRNAME/AndroidManifest.xml" +cp "banner.png" "$DIRNAME/res/drawable/banner.png" cp "$APP_ICON" "$DIRNAME/res/drawable/icon.png" convert -scale 72x72 "$APP_ICON" "$DIRNAME/res/drawable-hdpi/icon.png" convert -scale 48x48 "$APP_ICON" "$DIRNAME/res/drawable-mdpi/icon.png" @@ -385,12 +419,12 @@ convert -scale 144x144 "$APP_ICON" "$DIRNAME/res/drawable-xxhdpi/icon.png" if [ "$BUILD_TOOL" = "gradle" ]; then export ANDROID_HOME="$SDK_PATH" - gradle -Psdk_version=$SDK_VERSION \ - -Pbuild_tools_ver="$BUILD_TOOLS_VER" \ + gradle -Pcompile_sdk_version=$COMPILE_SDK_VERSION \ + -Pbuild_tools_ver="$BUILD_TOOLS_VER" \ $GRADLE_BUILD_TYPE elif [ "$BUILD_TOOL" = "ant" ]; then ant -Dsdk.dir="$SDK_PATH" \ - -Dtarget=$NDK_PLATFORM \ + -Dtarget="android-$TARGET_SDK_VERSION" \ $ANT_BUILD_TYPE fi diff --git a/cmake/FindENet.cmake b/cmake/FindENet.cmake new file mode 100644 index 000000000..91c252713 --- /dev/null +++ b/cmake/FindENet.cmake @@ -0,0 +1,48 @@ +# - Try to find enet +# Once done this will define +# +# ENET_FOUND - system has enet +# ENet_INCLUDE_DIRS - the enet include directory +# ENet_LIBRARIES - the libraries needed to use enet +# +# $ENETDIR is an environment variable used for finding enet. +# +# Borrowed from The Mana World +# http://themanaworld.org/ +# +# Several changes and additions by Fabian 'x3n' Landau +# Lots of simplifications by Adrian Friedli +# > www.orxonox.net < + +FIND_PATH(ENet_INCLUDE_DIRS enet/enet.h + PATHS + $ENV{ENETDIR} + /usr/local + /usr + PATH_SUFFIXES include + ) + +FIND_LIBRARY(ENet_LIBRARY + NAMES enet + PATHS + $ENV{ENETDIR} + /usr/local + /usr + PATH_SUFFIXES lib + ) + +# handle the QUIETLY and REQUIRED arguments and set ENET_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(ENet DEFAULT_MSG ENet_LIBRARY ENet_INCLUDE_DIRS) + +IF (ENET_FOUND) + IF(WIN32) + SET(WINDOWS_ENET_DEPENDENCIES "ws2_32;winmm") + SET(ENet_LIBRARIES ${ENet_LIBRARY} ${WINDOWS_ENET_DEPENDENCIES}) + ELSE(WIN32) + SET(ENet_LIBRARIES ${ENet_LIBRARY}) + ENDIF(WIN32) +ENDIF (ENET_FOUND) + +MARK_AS_ADVANCED(ENet_LIBRARY ENet_LIBRARIES ENet_INCLUDE_DIRS) diff --git a/data/challenges/mansion.challenge b/data/challenges/mansion.challenge index 662a15879..f3ecabb20 100644 --- a/data/challenges/mansion.challenge +++ b/data/challenges/mansion.challenge @@ -3,10 +3,9 @@ - - + diff --git a/data/challenges/mines.challenge b/data/challenges/mines.challenge index 9d577f030..00e78ee08 100644 --- a/data/challenges/mines.challenge +++ b/data/challenges/mines.challenge @@ -6,7 +6,7 @@ - + diff --git a/data/challenges/snowmountain.challenge b/data/challenges/snowmountain.challenge index db4319738..0357581f4 100644 --- a/data/challenges/snowmountain.challenge +++ b/data/challenges/snowmountain.challenge @@ -3,10 +3,9 @@ - - + diff --git a/data/gui/options_ui.stkgui b/data/gui/options_ui.stkgui index 2c654be7b..737104b0d 100644 --- a/data/gui/options_ui.stkgui +++ b/data/gui/options_ui.stkgui @@ -72,8 +72,12 @@ - - + +
+ + +
diff --git a/data/shaders/combine_diffuse_color.frag b/data/shaders/combine_diffuse_color.frag index df7f34e86..68191277e 100644 --- a/data/shaders/combine_diffuse_color.frag +++ b/data/shaders/combine_diffuse_color.frag @@ -4,6 +4,9 @@ uniform sampler2D ssao_tex; uniform sampler2D gloss_map; uniform sampler2D diffuse_color; uniform sampler2D depth_stencil; +uniform sampler2D light_scatter; + +uniform vec4 bg_color; out vec4 o_final_color; @@ -31,13 +34,28 @@ void main() vec4 color_1 = vec4(tmp * ao + (emitMapValue * emitCol), diffuseMatColor.a); // Fog - float z = texture(depth_stencil, tc).x; - vec4 xpos = getPosFromUVDepth(vec3(tc, z), u_inverse_projection_matrix); + float depth = texture(depth_stencil, tc).x; + vec4 xpos = getPosFromUVDepth(vec3(tc, depth), u_inverse_projection_matrix); float dist = length(xpos.xyz); // fog density float factor = (1.0 - exp(u_fog_data.w * dist)); vec3 fog = u_fog_color.xyz * factor; // Additively blend the color by fog - o_final_color = color_1 + vec4(fog, factor); + color_1 = color_1 + vec4(fog, factor); + + // For skybox blending later + if (depth == 1.0) + { + color_1 = bg_color; + } + + // Light scatter (alpha blend function: (GL_ONE, GL_ONE_MINUS_SRC_ALPHA)) + vec4 ls = texture(light_scatter, tc); + vec4 color_2; + color_2.r = ls.r + color_1.r * (1.0 - ls.a); + color_2.g = ls.g + color_1.g * (1.0 - ls.a); + color_2.b = ls.b + color_1.b * (1.0 - ls.a); + color_2.a = ls.a + color_1.a * (1.0 - ls.a); + o_final_color = color_2; } diff --git a/data/shaders/simple_particle.frag b/data/shaders/simple_particle.frag index 144f42dac..ad12bfc3f 100644 --- a/data/shaders/simple_particle.frag +++ b/data/shaders/simple_particle.frag @@ -1,21 +1,25 @@ uniform sampler2D tex; uniform sampler2D dtex; +uniform float billboard; in vec2 tc; in vec4 pc; -flat in float billboard_mix; out vec4 FragColor; #stk_include "utils/getPosFromUVDepth.frag" void main(void) { + float billboard_alpha = mix(1.0, texture(tex, tc).a, billboard); +#if defined(Advanced_Lighting_Enabled) vec2 xy = gl_FragCoord.xy / u_screen; float FragZ = gl_FragCoord.z; vec4 FragmentPos = getPosFromUVDepth(vec3(xy, FragZ), u_inverse_projection_matrix); float EnvZ = texture(dtex, xy).x; vec4 EnvPos = getPosFromUVDepth(vec3(xy, EnvZ), u_inverse_projection_matrix); float alpha = clamp((EnvPos.z - FragmentPos.z) * 0.3, 0., 1.); - float billboard_alpha = mix(1.0, texture(tex, tc).a, billboard_mix); +#else + float alpha = 1.0; +#endif FragColor = texture(tex, tc) * billboard_alpha * pc * alpha; } diff --git a/data/shaders/simple_particle.vert b/data/shaders/simple_particle.vert index 3abc9bbda..d1ab36e09 100644 --- a/data/shaders/simple_particle.vert +++ b/data/shaders/simple_particle.vert @@ -23,7 +23,6 @@ in vec2 quadcorner; in float anglespeed; #endif -flat out float billboard_mix; out vec2 tc; out vec4 pc; @@ -34,13 +33,11 @@ void main(void) gl_Position = vec4(0.); pc = vec4(0.0); tc = vec2(0.0); - billboard_mix = 0.0; return; } float lifetime = color_lifetime.w; float alpha = mix(smoothstep(1.0, 0.8, lifetime), lifetime, billboard); - billboard_mix = billboard; vec4 particle_color = vec4(color_lifetime.zyx, 1.0) * alpha; tc = Texcoord; diff --git a/data/shaders/sp_alpha_test.frag b/data/shaders/sp_alpha_test.frag index 3f9e46f2a..f344c95c3 100644 --- a/data/shaders/sp_alpha_test.frag +++ b/data/shaders/sp_alpha_test.frag @@ -1,4 +1,4 @@ -flat in float hue_change; +in float hue_change; in vec4 color; in vec3 normal; @@ -28,9 +28,7 @@ void main(void) vec3 new_color = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z)); col = vec4(new_color.r, new_color.g, new_color.b, col.a); } - - vec3 final_color = col.xyz * color.xyz; - o_diffuse_color = vec4(final_color, 1.0); + o_diffuse_color = vec4(col.xyz, 1.0); #if defined(Advanced_Lighting_Enabled) vec4 layer_2 = sampleTextureLayer2(uv); diff --git a/data/shaders/sp_ghost.frag b/data/shaders/sp_ghost.frag index 0887e7a63..2211494b3 100644 --- a/data/shaders/sp_ghost.frag +++ b/data/shaders/sp_ghost.frag @@ -1,6 +1,6 @@ uniform float custom_alpha; -flat in float hue_change; +in float hue_change; in vec2 uv; in vec4 color; diff --git a/data/shaders/sp_grass.frag b/data/shaders/sp_grass.frag index 1c166c2f7..412e7a7a9 100644 --- a/data/shaders/sp_grass.frag +++ b/data/shaders/sp_grass.frag @@ -1,4 +1,4 @@ -flat in float hue_change; +in float hue_change; in vec3 normal; in vec2 uv; @@ -26,9 +26,7 @@ void main(void) vec3 new_color = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z)); col = vec4(new_color.r, new_color.g, new_color.b, col.a); } - - vec3 final_color = col.xyz; - o_diffuse_color = vec4(final_color, 1.0); + o_diffuse_color = vec4(col.xyz, 1.0); #if defined(Advanced_Lighting_Enabled) vec4 layer_2 = sampleTextureLayer2(uv); diff --git a/data/shaders/sp_grass_pass.vert b/data/shaders/sp_grass_pass.vert index 1164ae5f1..074754bea 100644 --- a/data/shaders/sp_grass_pass.vert +++ b/data/shaders/sp_grass_pass.vert @@ -25,7 +25,7 @@ layout(location = 12) in ivec2 i_misc_data; out vec3 normal; out vec2 uv; -flat out float hue_change; +out float hue_change; void main() { diff --git a/data/shaders/sp_normal_map.frag b/data/shaders/sp_normal_map.frag index 2fee160a5..c98497748 100644 --- a/data/shaders/sp_normal_map.frag +++ b/data/shaders/sp_normal_map.frag @@ -1,9 +1,6 @@ -flat in float hue_change; +in float hue_change; in vec4 color; -in vec3 tangent; -in vec3 bitangent; -in vec3 normal; in vec2 uv; layout(location = 0) out vec4 o_diffuse_color; @@ -13,6 +10,7 @@ layout(location = 2) out vec2 o_gloss_map; #stk_include "utils/encode_normal.frag" #stk_include "utils/rgb_conversion.frag" #stk_include "utils/sp_texture_sampling.frag" +#stk_include "utils/sp_normalMapOutput.frag" void main() { @@ -39,16 +37,7 @@ void main() #if defined(Advanced_Lighting_Enabled) vec4 layer_3 = sampleTextureLayer3(uv); - vec3 tangent_space_normal = 2.0 * layer_3.xyz - 1.0; - vec3 frag_tangent = normalize(tangent); - vec3 frag_bitangent = normalize(bitangent); - vec3 frag_normal = normalize(normal); - mat3 t_b_n = mat3(frag_tangent, frag_bitangent, frag_normal); - vec3 world_normal = t_b_n * tangent_space_normal; - vec4 layer_2 = sampleTextureLayer2(uv); - o_normal_depth.xy = 0.5 * EncodeNormal(normalize(world_normal)) + 0.5; - o_normal_depth.z = layer_2.x; - o_gloss_map = layer_2.yz; + outputNormalMapPbrData(layer_3.rgb, layer_2.rgb); #endif } diff --git a/data/shaders/sp_normal_visualizer.geom b/data/shaders/sp_normal_visualizer.geom index c5693d192..9d2d58322 100644 --- a/data/shaders/sp_normal_visualizer.geom +++ b/data/shaders/sp_normal_visualizer.geom @@ -1,3 +1,9 @@ +uniform int enable_normals; +uniform int enable_tangents; +uniform int enable_bitangents; +uniform int enable_wireframe; +uniform int enable_triangle_normals; + layout(triangles) in; layout(line_strip, max_vertices = 24) out; @@ -9,6 +15,13 @@ flat out vec4 o_color; void main() { + if (enable_normals == 0 && enable_tangents == 0 && + enable_bitangents == 0 && enable_wireframe == 0 && + enable_triangle_normals == 0) + { + return; + } + // colors for different type of new lines vec4 edge_color = vec4(0.2, 0.1, 0.1, 1.0); vec4 face_normal_color = vec4(0.5, 0.7, 0.2, 1.0); @@ -47,56 +60,71 @@ void main() // get position of the vertex vec3 P = gl_in[i].gl_Position.xyz; - // create normal for vertex - o_color = normal_color; - gl_Position = pos[i]; - EmitVertex(); - gl_Position = u_projection_view_matrix * vec4(P + o_normal[i].xyz - * normal_scale, 1.0); - EmitVertex(); - EndPrimitive(); + if (enable_normals > 0) + { + // create normal for vertex + o_color = normal_color; + gl_Position = pos[i]; + EmitVertex(); + gl_Position = u_projection_view_matrix * vec4(P + o_normal[i].xyz + * normal_scale, 1.0); + EmitVertex(); + EndPrimitive(); + } - // create tangent for vertex - o_color = tangent_color; - gl_Position = pos[i]; - EmitVertex(); - gl_Position = u_projection_view_matrix * - vec4(P + o_tangent[i].xyz * normal_scale, 1.0); - EmitVertex(); - EndPrimitive(); + if (enable_tangents > 0) + { + // create tangent for vertex + o_color = tangent_color; + gl_Position = pos[i]; + EmitVertex(); + gl_Position = u_projection_view_matrix * + vec4(P + o_tangent[i].xyz * normal_scale, 1.0); + EmitVertex(); + EndPrimitive(); + } - // create bitangent for vertex - o_color = bitangent_color; - gl_Position = pos[i]; + if (enable_bitangents > 0) + { + // create bitangent for vertex + o_color = bitangent_color; + gl_Position = pos[i]; + EmitVertex(); + gl_Position = u_projection_view_matrix * vec4(P + + o_bitangent[i].xyz * normal_scale, 1.0); + EmitVertex(); + EndPrimitive(); + } + } + + if (enable_wireframe > 0) + { + // create edges for triangle + o_color = edge_color; + gl_Position = pos[0]; EmitVertex(); - gl_Position = u_projection_view_matrix * vec4(P + - o_bitangent[i].xyz * normal_scale, 1.0); + gl_Position = pos[1]; EmitVertex(); + gl_Position = pos[2]; + EmitVertex(); + gl_Position = pos[0]; + EmitVertex(); + // end line strip after four added vertices, so we will get three lines EndPrimitive(); } - // create edges for triangle - o_color = edge_color; - gl_Position = pos[0]; - EmitVertex(); - gl_Position = pos[1]; - EmitVertex(); - gl_Position = pos[2]; - EmitVertex(); - gl_Position = pos[0]; - EmitVertex(); - // end line strip after four added vertices, so we will get three lines - EndPrimitive(); + if (enable_triangle_normals > 0) + { + // create normal for triangle + o_color = face_normal_color; - // create normal for triangle - o_color = face_normal_color; - - // position as arithmetic average - vec3 P = (gl_in[0].gl_Position.xyz + gl_in[1].gl_Position.xyz - + gl_in[2].gl_Position.xyz) / 3.0; - gl_Position = u_projection_view_matrix * vec4(P, 1.0); - EmitVertex(); - gl_Position = u_projection_view_matrix * vec4(P + N * normal_scale, 1.0); - EmitVertex(); - EndPrimitive(); + // position as arithmetic average + vec3 P = (gl_in[0].gl_Position.xyz + gl_in[1].gl_Position.xyz + + gl_in[2].gl_Position.xyz) / 3.0; + gl_Position = u_projection_view_matrix * vec4(P, 1.0); + EmitVertex(); + gl_Position = u_projection_view_matrix * vec4(P + N * normal_scale, 1.0); + EmitVertex(); + EndPrimitive(); + } } diff --git a/data/shaders/sp_normal_visualizer.vert b/data/shaders/sp_normal_visualizer.vert index a6c53a21e..83849ec86 100644 --- a/data/shaders/sp_normal_visualizer.vert +++ b/data/shaders/sp_normal_visualizer.vert @@ -50,21 +50,55 @@ void main() vec4 skinned_tangent = vec4(0.0); int skinning_offset = i_misc_data.x; - for (int i = 0; i < 4; i++) - { - mat4 joint_matrix = mat4( - texelFetch(skinning_tex, - clamp(i_joint[i] + skinning_offset, 0, MAX_BONES) * 4), - texelFetch(skinning_tex, - clamp(i_joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 1), - texelFetch(skinning_tex, - clamp(i_joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 2), - texelFetch(skinning_tex, - clamp(i_joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 3)); - skinned_position += i_weight[i] * joint_matrix * idle_position; - skinned_normal += i_weight[i] * joint_matrix * idle_normal; - skinned_tangent += i_weight[i] * joint_matrix * idle_tangent; - } +#ifdef GL_ES + mat4 joint_matrix = + i_weight[0] * mat4( + texelFetch(skinning_tex, ivec2(0, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(1, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(2, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(3, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES)), 0)) + + i_weight[1] * mat4( + texelFetch(skinning_tex, ivec2(0, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(1, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(2, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(3, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES)), 0)) + + i_weight[2] * mat4( + texelFetch(skinning_tex, ivec2(0, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(1, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(2, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(3, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES)), 0)) + + i_weight[3] * mat4( + texelFetch(skinning_tex, ivec2(0, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(1, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(2, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(3, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES)), 0)); +#else + mat4 joint_matrix = + i_weight[0] * mat4( + texelFetch(skinning_tex, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES) * 4), + texelFetch(skinning_tex, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES) * 4 + 1), + texelFetch(skinning_tex, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES) * 4 + 2), + texelFetch(skinning_tex, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES) * 4 + 3)) + + i_weight[1] * mat4( + texelFetch(skinning_tex, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES) * 4), + texelFetch(skinning_tex, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES) * 4 + 1), + texelFetch(skinning_tex, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES) * 4 + 2), + texelFetch(skinning_tex, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES) * 4 + 3)) + + i_weight[2] * mat4( + texelFetch(skinning_tex, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES) * 4), + texelFetch(skinning_tex, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES) * 4 + 1), + texelFetch(skinning_tex, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES) * 4 + 2), + texelFetch(skinning_tex, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES) * 4 + 3)) + + i_weight[3] * mat4( + texelFetch(skinning_tex, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES) * 4), + texelFetch(skinning_tex, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES) * 4 + 1), + texelFetch(skinning_tex, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES) * 4 + 2), + texelFetch(skinning_tex, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES) * 4 + 3)); +#endif + + skinned_position = joint_matrix * idle_position; + skinned_normal = joint_matrix * idle_normal; + skinned_tangent = joint_matrix * idle_tangent; float step_mix = step(float(skinning_offset), 0.0); skinned_position = mix(skinned_position, idle_position, step_mix); diff --git a/data/shaders/sp_pass.vert b/data/shaders/sp_pass.vert index c3a2f6e93..1ce18e733 100644 --- a/data/shaders/sp_pass.vert +++ b/data/shaders/sp_pass.vert @@ -36,8 +36,9 @@ out vec3 normal; out vec2 uv; out vec2 uv_two; out vec4 color; +out vec4 world_position; out float camdist; -flat out float hue_change; +out float hue_change; void main() { @@ -49,7 +50,7 @@ void main() #endif vec4 quaternion = normalize(vec4(i_rotation.xyz, i_scale.w)); - vec4 world_position = getWorldPosition(i_origin, quaternion, i_scale.xyz, + vec4 v_world_position = getWorldPosition(i_origin, quaternion, i_scale.xyz, i_position); vec3 world_normal = rotateVector(quaternion, i_normal.xyz); vec3 world_tangent = rotateVector(quaternion, i_tangent.xyz); @@ -66,7 +67,8 @@ void main() uv_two = i_uv_two; color = i_color.zyxw; - camdist = length(u_view_matrix * world_position); + camdist = length(u_view_matrix * v_world_position); hue_change = float(i_misc_data.y) * 0.01; - gl_Position = u_projection_view_matrix * world_position; + gl_Position = u_projection_view_matrix * v_world_position; + world_position = v_world_position; } diff --git a/data/shaders/sp_skinning.vert b/data/shaders/sp_skinning.vert index 28824111a..af8cf21a5 100644 --- a/data/shaders/sp_skinning.vert +++ b/data/shaders/sp_skinning.vert @@ -44,7 +44,7 @@ out vec2 uv; out vec2 uv_two; out vec4 color; out float camdist; -flat out float hue_change; +out float hue_change; void main() { @@ -63,33 +63,55 @@ void main() vec4 skinned_tangent = vec4(0.0); int skinning_offset = i_misc_data.x; - for (int i = 0; i < 4; i++) - { #ifdef GL_ES - mat4 joint_matrix = mat4( - texelFetch(skinning_tex, ivec2 - (0 , clamp(i_joint[i] + skinning_offset, 0, MAX_BONES)), 0), - texelFetch(skinning_tex, ivec2 - (1, clamp(i_joint[i] + skinning_offset, 0, MAX_BONES)), 0), - texelFetch(skinning_tex, ivec2 - (2, clamp(i_joint[i] + skinning_offset, 0, MAX_BONES)), 0), - texelFetch(skinning_tex, ivec2 - (3, clamp(i_joint[i] + skinning_offset, 0, MAX_BONES)), 0)); + mat4 joint_matrix = + i_weight[0] * mat4( + texelFetch(skinning_tex, ivec2(0, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(1, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(2, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(3, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES)), 0)) + + i_weight[1] * mat4( + texelFetch(skinning_tex, ivec2(0, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(1, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(2, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(3, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES)), 0)) + + i_weight[2] * mat4( + texelFetch(skinning_tex, ivec2(0, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(1, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(2, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(3, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES)), 0)) + + i_weight[3] * mat4( + texelFetch(skinning_tex, ivec2(0, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(1, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(2, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(3, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES)), 0)); #else - mat4 joint_matrix = mat4( - texelFetch(skinning_tex, - clamp(i_joint[i] + skinning_offset, 0, MAX_BONES) * 4), - texelFetch(skinning_tex, - clamp(i_joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 1), - texelFetch(skinning_tex, - clamp(i_joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 2), - texelFetch(skinning_tex, - clamp(i_joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 3)); + mat4 joint_matrix = + i_weight[0] * mat4( + texelFetch(skinning_tex, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES) * 4), + texelFetch(skinning_tex, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES) * 4 + 1), + texelFetch(skinning_tex, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES) * 4 + 2), + texelFetch(skinning_tex, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES) * 4 + 3)) + + i_weight[1] * mat4( + texelFetch(skinning_tex, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES) * 4), + texelFetch(skinning_tex, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES) * 4 + 1), + texelFetch(skinning_tex, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES) * 4 + 2), + texelFetch(skinning_tex, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES) * 4 + 3)) + + i_weight[2] * mat4( + texelFetch(skinning_tex, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES) * 4), + texelFetch(skinning_tex, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES) * 4 + 1), + texelFetch(skinning_tex, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES) * 4 + 2), + texelFetch(skinning_tex, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES) * 4 + 3)) + + i_weight[3] * mat4( + texelFetch(skinning_tex, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES) * 4), + texelFetch(skinning_tex, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES) * 4 + 1), + texelFetch(skinning_tex, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES) * 4 + 2), + texelFetch(skinning_tex, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES) * 4 + 3)); #endif - skinned_position += i_weight[i] * joint_matrix * idle_position; - skinned_normal += i_weight[i] * joint_matrix * idle_normal; - skinned_tangent += i_weight[i] * joint_matrix * idle_tangent; - } + + skinned_position = joint_matrix * idle_position; + skinned_normal = joint_matrix * idle_normal; + skinned_tangent = joint_matrix * idle_tangent; vec4 quaternion = normalize(vec4(i_rotation.xyz, i_scale.w)); vec4 world_position = getWorldPosition(i_origin, quaternion, i_scale.xyz, diff --git a/data/shaders/sp_skinning_shadow.vert b/data/shaders/sp_skinning_shadow.vert index 81e0b6c3f..96d337fb7 100644 --- a/data/shaders/sp_skinning_shadow.vert +++ b/data/shaders/sp_skinning_shadow.vert @@ -36,31 +36,53 @@ void main() vec4 skinned_position = vec4(0.0); int skinning_offset = i_misc_data.x; - for (int i = 0; i < 4; i++) - { #ifdef GL_ES - mat4 joint_matrix = mat4( - texelFetch(skinning_tex, ivec2 - (0, clamp(i_joint[i] + skinning_offset, 0, MAX_BONES)), 0), - texelFetch(skinning_tex, ivec2 - (1, clamp(i_joint[i] + skinning_offset, 0, MAX_BONES)), 0), - texelFetch(skinning_tex, ivec2 - (2, clamp(i_joint[i] + skinning_offset, 0, MAX_BONES)), 0), - texelFetch(skinning_tex, ivec2 - (3, clamp(i_joint[i] + skinning_offset, 0, MAX_BONES)), 0)); + mat4 joint_matrix = + i_weight[0] * mat4( + texelFetch(skinning_tex, ivec2(0, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(1, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(2, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(3, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES)), 0)) + + i_weight[1] * mat4( + texelFetch(skinning_tex, ivec2(0, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(1, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(2, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(3, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES)), 0)) + + i_weight[2] * mat4( + texelFetch(skinning_tex, ivec2(0, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(1, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(2, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(3, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES)), 0)) + + i_weight[3] * mat4( + texelFetch(skinning_tex, ivec2(0, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(1, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(2, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES)), 0), + texelFetch(skinning_tex, ivec2(3, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES)), 0)); #else - mat4 joint_matrix = mat4( - texelFetch(skinning_tex, - clamp(i_joint[i] + skinning_offset, 0, MAX_BONES) * 4), - texelFetch(skinning_tex, - clamp(i_joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 1), - texelFetch(skinning_tex, - clamp(i_joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 2), - texelFetch(skinning_tex, - clamp(i_joint[i] + skinning_offset, 0, MAX_BONES) * 4 + 3)); + mat4 joint_matrix = + i_weight[0] * mat4( + texelFetch(skinning_tex, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES) * 4), + texelFetch(skinning_tex, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES) * 4 + 1), + texelFetch(skinning_tex, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES) * 4 + 2), + texelFetch(skinning_tex, clamp(i_joint[0] + skinning_offset, 0, MAX_BONES) * 4 + 3)) + + i_weight[1] * mat4( + texelFetch(skinning_tex, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES) * 4), + texelFetch(skinning_tex, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES) * 4 + 1), + texelFetch(skinning_tex, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES) * 4 + 2), + texelFetch(skinning_tex, clamp(i_joint[1] + skinning_offset, 0, MAX_BONES) * 4 + 3)) + + i_weight[2] * mat4( + texelFetch(skinning_tex, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES) * 4), + texelFetch(skinning_tex, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES) * 4 + 1), + texelFetch(skinning_tex, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES) * 4 + 2), + texelFetch(skinning_tex, clamp(i_joint[2] + skinning_offset, 0, MAX_BONES) * 4 + 3)) + + i_weight[3] * mat4( + texelFetch(skinning_tex, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES) * 4), + texelFetch(skinning_tex, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES) * 4 + 1), + texelFetch(skinning_tex, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES) * 4 + 2), + texelFetch(skinning_tex, clamp(i_joint[3] + skinning_offset, 0, MAX_BONES) * 4 + 3)); #endif - skinned_position += i_weight[i] * joint_matrix * idle_position; - } + + skinned_position = joint_matrix * idle_position; vec4 quaternion = normalize(vec4(i_rotation.xyz, i_scale.w)); vec4 world_position = getWorldPosition(i_origin, quaternion, i_scale.xyz, diff --git a/data/shaders/sp_solid.frag b/data/shaders/sp_solid.frag index 911ed9e76..b9860f786 100644 --- a/data/shaders/sp_solid.frag +++ b/data/shaders/sp_solid.frag @@ -1,4 +1,4 @@ -flat in float hue_change; +in float hue_change; in vec4 color; in vec3 normal; diff --git a/data/shaders/sps_0_solid.xml b/data/shaders/sps_0_solid.xml index 41e07c969..477691b17 100644 --- a/data/shaders/sps_0_solid.xml +++ b/data/shaders/sps_0_solid.xml @@ -100,18 +100,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/data/skins/Ocean.stkskin b/data/skins/Ocean.stkskin index b251e5b37..72b93bfda 100644 --- a/data/skins/Ocean.stkskin +++ b/data/skins/Ocean.stkskin @@ -128,6 +128,9 @@ when the border that intersect at this corner are enabled. hborder_out_portion="0.2" /> + diff --git a/data/skins/Peach.stkskin b/data/skins/Peach.stkskin index 4b67f0f5b..2f2ab97d4 100644 --- a/data/skins/Peach.stkskin +++ b/data/skins/Peach.stkskin @@ -129,6 +129,9 @@ when the border that intersect at this corner are enabled. + diff --git a/data/skins/Ruby.stkskin b/data/skins/Ruby.stkskin index 76407f632..844fcc2d9 100644 --- a/data/skins/Ruby.stkskin +++ b/data/skins/Ruby.stkskin @@ -130,6 +130,9 @@ when the border that intersect at this corner are enabled. + diff --git a/data/skins/forest/glass_square_focused_bw.png b/data/skins/forest/glass_square_focused_bw.png new file mode 100644 index 000000000..300633757 Binary files /dev/null and b/data/skins/forest/glass_square_focused_bw.png differ diff --git a/data/skins/ocean/glass_square_focused_bw.png b/data/skins/ocean/glass_square_focused_bw.png new file mode 100644 index 000000000..8319920d5 Binary files /dev/null and b/data/skins/ocean/glass_square_focused_bw.png differ diff --git a/data/skins/peach/glass_square_focused_bw.png b/data/skins/peach/glass_square_focused_bw.png new file mode 100644 index 000000000..113c08a6f Binary files /dev/null and b/data/skins/peach/glass_square_focused_bw.png differ diff --git a/data/skins/ruby/glass_square_focused_bw.png b/data/skins/ruby/glass_square_focused_bw.png new file mode 100644 index 000000000..5ca9e5454 Binary files /dev/null and b/data/skins/ruby/glass_square_focused_bw.png differ diff --git a/lib/angelscript/include/angelscript.h b/lib/angelscript/include/angelscript.h index 98d33c516..72724a65c 100644 --- a/lib/angelscript/include/angelscript.h +++ b/lib/angelscript/include/angelscript.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -58,8 +58,8 @@ BEGIN_AS_NAMESPACE // AngelScript version -#define ANGELSCRIPT_VERSION 23002 -#define ANGELSCRIPT_VERSION_STRING "2.30.2" +#define ANGELSCRIPT_VERSION 23200 +#define ANGELSCRIPT_VERSION_STRING "2.32.0" // Data types @@ -68,12 +68,13 @@ class asIScriptModule; class asIScriptContext; class asIScriptGeneric; class asIScriptObject; -class asIObjectType; +class asITypeInfo; class asIScriptFunction; class asIBinaryStream; class asIJITCompiler; class asIThreadManager; class asILockableSharedBool; +class asIStringFactory; // Enumerations and constants @@ -138,6 +139,9 @@ enum asEEngineProp asEP_DISABLE_INTEGER_DIVISION = 22, asEP_DISALLOW_EMPTY_LIST_ELEMENTS = 23, asEP_PRIVATE_PROP_AS_PROTECTED = 24, + asEP_ALLOW_UNICODE_IDENTIFIERS = 25, + asEP_HEREDOC_TRIM_MODE = 26, + asEP_MAX_NESTED_CALLS = 27, asEP_LAST_PROPERTY }; @@ -200,7 +204,7 @@ enum asEObjTypeFlags asOBJ_SCRIPT_OBJECT = (1<<21), asOBJ_SHARED = (1<<22), asOBJ_NOINHERIT = (1<<23), - asOBJ_SCRIPT_FUNCTION = (1<<24), + asOBJ_FUNCDEF = (1<<24), asOBJ_LIST_PATTERN = (1<<25), asOBJ_ENUM = (1<<26), asOBJ_TEMPLATE_SUBTYPE = (1<<27), @@ -225,14 +229,6 @@ enum asEBehaviours asBEHAVE_GET_WEAKREF_FLAG, // Object operators -#ifdef AS_DEPRECATED - // Deprecated since 2.30.0, 2014-10-24 - asBEHAVE_VALUE_CAST, - asBEHAVE_IMPLICIT_VALUE_CAST, - // Deprecated since 2.30.0, 2014-12-30 - asBEHAVE_REF_CAST, - asBEHAVE_IMPLICIT_REF_CAST, -#endif asBEHAVE_TEMPLATE_CALLBACK, // Garbage collection behaviours @@ -356,29 +352,31 @@ enum asEFuncType // asQWORD = 64 bits // asPWORD = size of pointer // +typedef signed char asINT8; +typedef signed short asINT16; typedef unsigned char asBYTE; typedef unsigned short asWORD; typedef unsigned int asUINT; -#if (defined(_MSC_VER) && _MSC_VER <= 1200) || defined(__S3E__) +#if (defined(_MSC_VER) && _MSC_VER <= 1200) || defined(__S3E__) || (defined(_MSC_VER) && defined(__clang__)) // size_t is not really correct, since it only guaranteed to be large enough to hold the segment size. // For example, on 16bit systems the size_t may be 16bits only even if pointers are 32bit. But nobody // is likely to use MSVC6 to compile for 16bit systems anymore, so this should be ok. - typedef size_t asPWORD; + typedef size_t asPWORD; #else typedef uintptr_t asPWORD; #endif #ifdef __LP64__ - typedef unsigned int asDWORD; - typedef unsigned long asQWORD; - typedef long asINT64; + typedef unsigned int asDWORD; + typedef unsigned long asQWORD; + typedef long asINT64; #else - typedef unsigned long asDWORD; - #if defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_CC) || defined(__psp2__) - typedef uint64_t asQWORD; - typedef int64_t asINT64; + typedef unsigned long asDWORD; + #if !defined(_MSC_VER) && (defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_CC) || defined(__psp2__)) + typedef uint64_t asQWORD; + typedef int64_t asINT64; #else - typedef unsigned __int64 asQWORD; - typedef __int64 asINT64; + typedef unsigned __int64 asQWORD; + typedef __int64 asINT64; #endif #endif @@ -397,7 +395,7 @@ typedef void (*asCLEANENGINEFUNC_t)(asIScriptEngine *); typedef void (*asCLEANMODULEFUNC_t)(asIScriptModule *); typedef void (*asCLEANCONTEXTFUNC_t)(asIScriptContext *); typedef void (*asCLEANFUNCTIONFUNC_t)(asIScriptFunction *); -typedef void (*asCLEANOBJECTTYPEFUNC_t)(asIObjectType *); +typedef void (*asCLEANTYPEINFOFUNC_t)(asITypeInfo *); typedef void (*asCLEANSCRIPTOBJECTFUNC_t)(asIScriptObject *); typedef asIScriptContext *(*asREQUESTCONTEXTFUNC_t)(asIScriptEngine *, void *); typedef void (*asRETURNCONTEXTFUNC_t)(asIScriptEngine *, asIScriptContext *, void *); @@ -425,7 +423,7 @@ typedef void (*asRETURNCONTEXTFUNC_t)(asIScriptEngine *, asIScriptContext *, voi // BCC v5.8 (C++Builder 2006) and earlier have a similar bug which forces us to fall back to a C-style cast. #define asFUNCTIONPR(f,p,r) asFunctionPtr((void (*)())((r (*)p)(f))) #else -#define asFUNCTIONPR(f,p,r) asFunctionPtr((void (*)())(static_cast(f))) +#define asFUNCTIONPR(f,p,r) asFunctionPtr(reinterpret_cast(static_cast(f))) #endif #ifndef AS_NO_CLASS_METHODS @@ -584,7 +582,7 @@ BEGIN_AS_NAMESPACE template asUINT asGetTypeTraits() { -#if defined(_MSC_VER) || defined(_LIBCPP_TYPE_TRAITS) || (__GNUC__ >= 5) +#if defined(_MSC_VER) || defined(_LIBCPP_TYPE_TRAITS) || (__GNUC__ >= 5) || defined(__clang__) // MSVC, XCode/Clang, and gnuc 5+ // C++11 compliant code bool hasConstructor = std::is_default_constructible::value && !std::is_trivially_default_constructible::value; @@ -665,7 +663,7 @@ public: virtual asIJITCompiler *GetJITCompiler() const = 0; // Global functions - virtual int RegisterGlobalFunction(const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall = 0) = 0; + virtual int RegisterGlobalFunction(const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0) = 0; virtual asUINT GetGlobalFunctionCount() const = 0; virtual asIScriptFunction *GetGlobalFunctionByIndex(asUINT index) const = 0; virtual asIScriptFunction *GetGlobalFunctionByDecl(const char *declaration) const = 0; @@ -679,18 +677,16 @@ public: // Object types virtual int RegisterObjectType(const char *obj, int byteSize, asDWORD flags) = 0; - virtual int RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset) = 0; - virtual int RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall = 0) = 0; - virtual int RegisterObjectBehaviour(const char *obj, asEBehaviours behaviour, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall = 0) = 0; + virtual int RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset, int compositeOffset = 0, bool isCompositeIndirect = false) = 0; + virtual int RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0, int compositeOffset = 0, bool isCompositeIndirect = false) = 0; + virtual int RegisterObjectBehaviour(const char *obj, asEBehaviours behaviour, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0, int compositeOffset = 0, bool isCompositeIndirect = false) = 0; virtual int RegisterInterface(const char *name) = 0; virtual int RegisterInterfaceMethod(const char *intf, const char *declaration) = 0; virtual asUINT GetObjectTypeCount() const = 0; - virtual asIObjectType *GetObjectTypeByIndex(asUINT index) const = 0; - virtual asIObjectType *GetObjectTypeByName(const char *name) const = 0; - virtual asIObjectType *GetObjectTypeByDecl(const char *decl) const = 0; + virtual asITypeInfo *GetObjectTypeByIndex(asUINT index) const = 0; // String factory - virtual int RegisterStringFactory(const char *datatype, const asSFuncPtr &factoryFunc, asDWORD callConv, void *objForThiscall = 0) = 0; + virtual int RegisterStringFactory(const char *datatype, asIStringFactory *factory) = 0; virtual int GetStringFactoryReturnTypeId(asDWORD *flags = 0) const = 0; // Default array type @@ -698,22 +694,20 @@ public: virtual int GetDefaultArrayTypeId() const = 0; // Enums - virtual int RegisterEnum(const char *type) = 0; - virtual int RegisterEnumValue(const char *type, const char *name, int value) = 0; - virtual asUINT GetEnumCount() const = 0; - virtual const char *GetEnumByIndex(asUINT index, int *enumTypeId, const char **nameSpace = 0, const char **configGroup = 0, asDWORD *accessMask = 0) const = 0; - virtual int GetEnumValueCount(int enumTypeId) const = 0; - virtual const char *GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const = 0; + virtual int RegisterEnum(const char *type) = 0; + virtual int RegisterEnumValue(const char *type, const char *name, int value) = 0; + virtual asUINT GetEnumCount() const = 0; + virtual asITypeInfo *GetEnumByIndex(asUINT index) const = 0; // Funcdefs - virtual int RegisterFuncdef(const char *decl) = 0; - virtual asUINT GetFuncdefCount() const = 0; - virtual asIScriptFunction *GetFuncdefByIndex(asUINT index) const = 0; + virtual int RegisterFuncdef(const char *decl) = 0; + virtual asUINT GetFuncdefCount() const = 0; + virtual asITypeInfo *GetFuncdefByIndex(asUINT index) const = 0; // Typedefs - virtual int RegisterTypedef(const char *type, const char *decl) = 0; - virtual asUINT GetTypedefCount() const = 0; - virtual const char *GetTypedefByIndex(asUINT index, int *typeId, const char **nameSpace = 0, const char **configGroup = 0, asDWORD *accessMask = 0) const = 0; + virtual int RegisterTypedef(const char *type, const char *decl) = 0; + virtual asUINT GetTypedefCount() const = 0; + virtual asITypeInfo *GetTypedefByIndex(asUINT index) const = 0; // Configuration groups virtual int BeginConfigGroup(const char *groupName) = 0; @@ -731,29 +725,26 @@ public: // Script functions virtual asIScriptFunction *GetFunctionById(int funcId) const = 0; - virtual asIScriptFunction *GetFuncDefFromTypeId(int typeId) const = 0; // Type identification - virtual asIObjectType *GetObjectTypeById(int typeId) const = 0; virtual int GetTypeIdByDecl(const char *decl) const = 0; virtual const char *GetTypeDeclaration(int typeId, bool includeNamespace = false) const = 0; virtual int GetSizeOfPrimitiveType(int typeId) const = 0; + virtual asITypeInfo *GetTypeInfoById(int typeId) const = 0; + virtual asITypeInfo *GetTypeInfoByName(const char *name) const = 0; + virtual asITypeInfo *GetTypeInfoByDecl(const char *decl) const = 0; // Script execution virtual asIScriptContext *CreateContext() = 0; - virtual void *CreateScriptObject(const asIObjectType *type) = 0; - virtual void *CreateScriptObjectCopy(void *obj, const asIObjectType *type) = 0; - virtual void *CreateUninitializedScriptObject(const asIObjectType *type) = 0; + virtual void *CreateScriptObject(const asITypeInfo *type) = 0; + virtual void *CreateScriptObjectCopy(void *obj, const asITypeInfo *type) = 0; + virtual void *CreateUninitializedScriptObject(const asITypeInfo *type) = 0; virtual asIScriptFunction *CreateDelegate(asIScriptFunction *func, void *obj) = 0; - virtual int AssignScriptObject(void *dstObj, void *srcObj, const asIObjectType *type) = 0; - virtual void ReleaseScriptObject(void *obj, const asIObjectType *type) = 0; - virtual void AddRefScriptObject(void *obj, const asIObjectType *type) = 0; - virtual int RefCastObject(void *obj, asIObjectType *fromType, asIObjectType *toType, void **newPtr, bool useOnlyImplicitCast = false) = 0; -#ifdef AS_DEPRECATED - // Deprecated since 2.30.0, 2014-11-04 - virtual bool IsHandleCompatibleWithObject(void *obj, int objTypeId, int handleTypeId) const = 0; -#endif - virtual asILockableSharedBool *GetWeakRefFlagOfScriptObject(void *obj, const asIObjectType *type) const = 0; + virtual int AssignScriptObject(void *dstObj, void *srcObj, const asITypeInfo *type) = 0; + virtual void ReleaseScriptObject(void *obj, const asITypeInfo *type) = 0; + virtual void AddRefScriptObject(void *obj, const asITypeInfo *type) = 0; + virtual int RefCastObject(void *obj, asITypeInfo *fromType, asITypeInfo *toType, void **newPtr, bool useOnlyImplicitCast = false) = 0; + virtual asILockableSharedBool *GetWeakRefFlagOfScriptObject(void *obj, const asITypeInfo *type) const = 0; // Context pooling virtual asIScriptContext *RequestContext() = 0; @@ -766,8 +757,8 @@ public: // Garbage collection virtual int GarbageCollect(asDWORD flags = asGC_FULL_CYCLE, asUINT numIterations = 1) = 0; virtual void GetGCStatistics(asUINT *currentSize, asUINT *totalDestroyed = 0, asUINT *totalDetected = 0, asUINT *newObjects = 0, asUINT *totalNewDestroyed = 0) const = 0; - virtual int NotifyGarbageCollectorOfNewObject(void *obj, asIObjectType *type) = 0; - virtual int GetObjectInGC(asUINT idx, asUINT *seqNbr = 0, void **obj = 0, asIObjectType **type = 0) = 0; + virtual int NotifyGarbageCollectorOfNewObject(void *obj, asITypeInfo *type) = 0; + virtual int GetObjectInGC(asUINT idx, asUINT *seqNbr = 0, void **obj = 0, asITypeInfo **type = 0) = 0; virtual void GCEnumCallback(void *reference) = 0; // User data @@ -777,13 +768,24 @@ public: virtual void SetModuleUserDataCleanupCallback(asCLEANMODULEFUNC_t callback, asPWORD type = 0) = 0; virtual void SetContextUserDataCleanupCallback(asCLEANCONTEXTFUNC_t callback, asPWORD type = 0) = 0; virtual void SetFunctionUserDataCleanupCallback(asCLEANFUNCTIONFUNC_t callback, asPWORD type = 0) = 0; - virtual void SetObjectTypeUserDataCleanupCallback(asCLEANOBJECTTYPEFUNC_t callback, asPWORD type = 0) = 0; + virtual void SetTypeInfoUserDataCleanupCallback(asCLEANTYPEINFOFUNC_t callback, asPWORD type = 0) = 0; virtual void SetScriptObjectUserDataCleanupCallback(asCLEANSCRIPTOBJECTFUNC_t callback, asPWORD type = 0) = 0; protected: virtual ~asIScriptEngine() {} }; +class asIStringFactory +{ +public: + virtual const void *GetStringConstant(const char *data, asUINT length) = 0; + virtual int ReleaseStringConstant(const void *str) = 0; + virtual int GetRawStringData(const void *str, char *data, asUINT *length) const = 0; + +protected: + virtual ~asIStringFactory() {} +}; + class asIThreadManager { protected: @@ -826,20 +828,18 @@ public: // Type identification virtual asUINT GetObjectTypeCount() const = 0; - virtual asIObjectType *GetObjectTypeByIndex(asUINT index) const = 0; - virtual asIObjectType *GetObjectTypeByName(const char *name) const = 0; - virtual asIObjectType *GetObjectTypeByDecl(const char *decl) const = 0; + virtual asITypeInfo *GetObjectTypeByIndex(asUINT index) const = 0; virtual int GetTypeIdByDecl(const char *decl) const = 0; + virtual asITypeInfo *GetTypeInfoByName(const char *name) const = 0; + virtual asITypeInfo *GetTypeInfoByDecl(const char *decl) const = 0; // Enums - virtual asUINT GetEnumCount() const = 0; - virtual const char *GetEnumByIndex(asUINT index, int *enumTypeId, const char **nameSpace = 0) const = 0; - virtual int GetEnumValueCount(int enumTypeId) const = 0; - virtual const char *GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const = 0; + virtual asUINT GetEnumCount() const = 0; + virtual asITypeInfo *GetEnumByIndex(asUINT index) const = 0; // Typedefs - virtual asUINT GetTypedefCount() const = 0; - virtual const char *GetTypedefByIndex(asUINT index, int *typeId, const char **nameSpace = 0) const = 0; + virtual asUINT GetTypedefCount() const = 0; + virtual asITypeInfo *GetTypedefByIndex(asUINT index) const = 0; // Dynamic binding between modules virtual asUINT GetImportedFunctionCount() const = 0; @@ -948,6 +948,7 @@ public: // Miscellaneous virtual asIScriptEngine *GetEngine() const = 0; virtual asIScriptFunction *GetFunction() const = 0; + virtual void *GetAuxiliary() const = 0; // Object virtual void *GetObject() = 0; @@ -992,7 +993,7 @@ public: // Type info virtual int GetTypeId() const = 0; - virtual asIObjectType *GetObjectType() const = 0; + virtual asITypeInfo *GetObjectType() const = 0; // Class properties virtual asUINT GetPropertyCount() const = 0; @@ -1012,7 +1013,7 @@ protected: virtual ~asIScriptObject() {} }; -class asIObjectType +class asITypeInfo { public: // Miscellaneous @@ -1028,19 +1029,19 @@ public: // Type info virtual const char *GetName() const = 0; virtual const char *GetNamespace() const = 0; - virtual asIObjectType *GetBaseType() const = 0; - virtual bool DerivesFrom(const asIObjectType *objType) const = 0; + virtual asITypeInfo *GetBaseType() const = 0; + virtual bool DerivesFrom(const asITypeInfo *objType) const = 0; virtual asDWORD GetFlags() const = 0; virtual asUINT GetSize() const = 0; virtual int GetTypeId() const = 0; virtual int GetSubTypeId(asUINT subTypeIndex = 0) const = 0; - virtual asIObjectType *GetSubType(asUINT subTypeIndex = 0) const = 0; + virtual asITypeInfo *GetSubType(asUINT subTypeIndex = 0) const = 0; virtual asUINT GetSubTypeCount() const = 0; // Interfaces virtual asUINT GetInterfaceCount() const = 0; - virtual asIObjectType *GetInterface(asUINT index) const = 0; - virtual bool Implements(const asIObjectType *objType) const = 0; + virtual asITypeInfo *GetInterface(asUINT index) const = 0; + virtual bool Implements(const asITypeInfo *objType) const = 0; // Factories virtual asUINT GetFactoryCount() const = 0; @@ -1055,19 +1056,34 @@ public: // Properties virtual asUINT GetPropertyCount() const = 0; - virtual int GetProperty(asUINT index, const char **name, int *typeId = 0, bool *isPrivate = 0, bool *isProtected = 0, int *offset = 0, bool *isReference = 0, asDWORD *accessMask = 0) const = 0; + virtual int GetProperty(asUINT index, const char **name, int *typeId = 0, bool *isPrivate = 0, bool *isProtected = 0, int *offset = 0, bool *isReference = 0, asDWORD *accessMask = 0, int *compositeOffset = 0, bool *isCompositeIndirect = 0) const = 0; virtual const char *GetPropertyDeclaration(asUINT index, bool includeNamespace = false) const = 0; // Behaviours virtual asUINT GetBehaviourCount() const = 0; virtual asIScriptFunction *GetBehaviourByIndex(asUINT index, asEBehaviours *outBehaviour) const = 0; + // Child types + virtual asUINT GetChildFuncdefCount() const = 0; + virtual asITypeInfo *GetChildFuncdef(asUINT index) const = 0; + virtual asITypeInfo *GetParentType() const = 0; + + // Enums + virtual asUINT GetEnumValueCount() const = 0; + virtual const char *GetEnumValueByIndex(asUINT index, int *outValue) const = 0; + + // Typedef + virtual int GetTypedefTypeId() const = 0; + + // Funcdef + virtual asIScriptFunction *GetFuncdefSignature() const = 0; + // User data virtual void *SetUserData(void *data, asPWORD type = 0) = 0; virtual void *GetUserData(asPWORD type = 0) const = 0; protected: - virtual ~asIObjectType() {} + virtual ~asITypeInfo() {} }; class asIScriptFunction @@ -1087,9 +1103,10 @@ public: virtual const char *GetScriptSectionName() const = 0; virtual const char *GetConfigGroup() const = 0; virtual asDWORD GetAccessMask() const = 0; + virtual void *GetAuxiliary() const = 0; // Function signature - virtual asIObjectType *GetObjectType() const = 0; + virtual asITypeInfo *GetObjectType() const = 0; virtual const char *GetObjectName() const = 0; virtual const char *GetName() const = 0; virtual const char *GetNamespace() const = 0; @@ -1102,10 +1119,6 @@ public: virtual bool IsShared() const = 0; virtual asUINT GetParamCount() const = 0; virtual int GetParam(asUINT index, int *typeId, asDWORD *flags = 0, const char **name = 0, const char **defaultArg = 0) const = 0; -#ifdef AS_DEPRECATED - // Deprecated since 2.29.0, 2014-04-06 - virtual int GetParamTypeId(asUINT index, asDWORD *flags = 0) const = 0; -#endif virtual int GetReturnTypeId(asDWORD *flags = 0) const = 0; // Type id for function pointers @@ -1114,7 +1127,7 @@ public: // Delegates virtual void *GetDelegateObject() const = 0; - virtual asIObjectType *GetDelegateObjectType() const = 0; + virtual asITypeInfo *GetDelegateObjectType() const = 0; virtual asIScriptFunction *GetDelegateFunction() const = 0; // Debug information @@ -1137,8 +1150,8 @@ protected: class asIBinaryStream { public: - virtual void Read(void *ptr, asUINT size) = 0; - virtual void Write(const void *ptr, asUINT size) = 0; + virtual int Read(void *ptr, asUINT size) = 0; + virtual int Write(const void *ptr, asUINT size) = 0; public: virtual ~asIBinaryStream() {} @@ -1337,7 +1350,7 @@ struct asSVMRegisters asDWORD *stackPointer; // top of stack (grows downward) asQWORD valueRegister; // temp register for primitives void *objectRegister; // temp register for objects and handles - asIObjectType *objectType; // type of object held in object register + asITypeInfo *objectType; // type of object held in object register bool doProcessSuspend; // whether or not the JIT should break out when it encounters a suspend instruction asIScriptContext *ctx; // the active context }; diff --git a/lib/angelscript/projects/cmake/CMakeLists.txt b/lib/angelscript/projects/cmake/CMakeLists.txt index 755d8378c..2d0688720 100644 --- a/lib/angelscript/projects/cmake/CMakeLists.txt +++ b/lib/angelscript/projects/cmake/CMakeLists.txt @@ -137,8 +137,10 @@ else() set(ANGELSCRIPT_LIBRARY_NAME Angelscript) # OS X frameworks should have capitalized name set(BUILD_SHARED_LIBS TRUE) endif() +set(ANGELSCRIPT_LIBRARY_NAME ${ANGELSCRIPT_LIBRARY_NAME} CACHE STRING "" FORCE) add_library(${ANGELSCRIPT_LIBRARY_NAME} ${ANGELSCRIPT_SOURCE} ${ANGELSCRIPT_HEADERS}) +# Don't override the default library output path to avoid conflicts when building for multiple target platforms #set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../../lib) target_link_libraries(${ANGELSCRIPT_LIBRARY_NAME} ${CMAKE_THREAD_LIBS_INIT}) @@ -160,7 +162,7 @@ if(MSVC) set_target_properties(${ANGELSCRIPT_LIBRARY_NAME} PROPERTIES COMPILE_FLAGS "/MP") endif() +# Don't override the default runtime output path to avoid conflicts when building for multiple target platforms #set(RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../../bin) -#add_subdirectory(../../../samples/game/projects/cmake/ ./game) diff --git a/lib/angelscript/source/as_array.h b/lib/angelscript/source/as_array.h index e1487e48d..647495177 100644 --- a/lib/angelscript/source/as_array.h +++ b/lib/angelscript/source/as_array.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -468,10 +468,10 @@ bool asCArray::Concatenate(const asCArray &other) } template -void asCArray::Concatenate(T* array, unsigned int count) +void asCArray::Concatenate(T* other, unsigned int count) { for( unsigned int c = 0; c < count; c++ ) - PushLast(array[c]); + PushLast(other[c]); } template diff --git a/lib/angelscript/source/as_builder.cpp b/lib/angelscript/source/as_builder.cpp index 2ff191c3a..4a852b2f1 100644 --- a/lib/angelscript/source/as_builder.cpp +++ b/lib/angelscript/source/as_builder.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -248,10 +248,10 @@ void asCBuilder::EvaluateTemplateInstances(asUINT startIdx, bool keepSilent) if( callback && !engine->CallGlobalFunctionRetBool(tmpl, &dontGarbageCollect, callback->sysFuncIntf, callback) ) { asCString sub = tmpl->templateSubTypes[0].Format(engine->nameSpaces[0]); - for( asUINT n = 1; n < tmpl->templateSubTypes.GetLength(); n++ ) + for( asUINT m = 1; m < tmpl->templateSubTypes.GetLength(); m++ ) { sub += ","; - sub += tmpl->templateSubTypes[n].Format(engine->nameSpaces[0]); + sub += tmpl->templateSubTypes[m].Format(engine->nameSpaces[0]); } asCString str; str.Format(TXT_INSTANCING_INVLD_TMPL_TYPE_s_s, tmpl->name.AddressOf(), sub.AddressOf()); @@ -279,11 +279,11 @@ int asCBuilder::Build() Reset(); // The template callbacks must only be called after the subtypes have a known structure, - // otherwise the callback may think it is not possible to create the template instance, + // otherwise the callback may think it is not possible to create the template instance, // even though it is. - // TODO: This flag shouldn't be set globally in the engine, as it would mean that another - // thread requesting a template instance in parallel to the compilation wouldn't - // evaluate the template instance. + // TODO: This flag shouldn't be set globally in the engine, as it would mean that another + // thread requesting a template instance in parallel to the compilation wouldn't + // evaluate the template instance. engine->deferValidationOfTemplateTypes = true; asUINT numTempl = (asUINT)engine->templateInstanceTypes.GetLength(); @@ -293,7 +293,7 @@ int asCBuilder::Build() CompileInterfaces(); CompileClasses(numTempl); - // Evaluate the template instances one last time, this time with error messages, as we know + // Evaluate the template instances one last time, this time with error messages, as we know // all classes have been fully built and it is known which ones will need garbage collection. EvaluateTemplateInstances(numTempl, false); engine->deferValidationOfTemplateTypes = false; @@ -376,7 +376,7 @@ int asCBuilder::CompileGlobalVar(const char *sectionName, const char *code, int if( numWarnings > 0 && engine->ep.compilerWarnings == 2 ) WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0); - // None of the functions should be added to the module if any error occurred, + // None of the functions should be added to the module if any error occurred, // or it was requested that the functions wouldn't be added to the scope if( numErrors > 0 ) { @@ -520,12 +520,12 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l node = node->firstChild; // Create the function - bool isConstructor, isDestructor, isPrivate, isProtected, isFinal, isOverride, isShared; + asSFunctionTraits funcTraits; asCScriptFunction *func = asNEW(asCScriptFunction)(engine, compileFlags & asCOMP_ADD_TO_MODULE ? module : 0, asFUNC_SCRIPT); if( func == 0 ) return asOUT_OF_MEMORY; - GetParsedFunctionDetails(node, scripts[0], 0, func->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, func->defaultArgs, func->isReadOnly, isConstructor, isDestructor, isPrivate, isProtected, isFinal, isOverride, isShared, module->defaultNamespace); + GetParsedFunctionDetails(node, scripts[0], 0, func->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, func->defaultArgs, funcTraits, module->defaultNamespace); func->id = engine->GetNextScriptFunctionId(); func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : ""); int row, col; @@ -544,7 +544,7 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l // Tell the engine that the function exists already so the compiler can access it if( compileFlags & asCOMP_ADD_TO_MODULE ) { - int r = CheckNameConflict(func->name.AddressOf(), node, scripts[0], module->defaultNamespace); + r = CheckNameConflict(func->name.AddressOf(), node, scripts[0], module->defaultNamespace); if( r < 0 ) { func->ReleaseInternal(); @@ -552,7 +552,7 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l } module->globalFunctions.Put(func); - + module->AddScriptFunction(func); } else @@ -579,8 +579,8 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l for( asUINT n = 0; n < functions.GetLength(); n++ ) { asCCompiler compiler(engine); - asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId]; - int r = compiler.CompileFunction(this, functions[n]->script, func->parameterNames, functions[n]->node, func, 0); + asCScriptFunction *f = engine->scriptFunctions[functions[n]->funcId]; + r = compiler.CompileFunction(this, functions[n]->script, f->parameterNames, functions[n]->node, f, 0); if( r < 0 ) break; } @@ -588,18 +588,18 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l if( numWarnings > 0 && engine->ep.compilerWarnings == 2 ) WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0); - // None of the functions should be added to the module if any error occurred, + // None of the functions should be added to the module if any error occurred, // or it was requested that the functions wouldn't be added to the scope if( !(compileFlags & asCOMP_ADD_TO_MODULE) || numErrors > 0 ) { for( asUINT n = 0; n < functions.GetLength(); n++ ) { - asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId]; - if( module->globalFunctions.GetIndex(func) >= 0 ) + asCScriptFunction *f = engine->scriptFunctions[functions[n]->funcId]; + if( module->globalFunctions.GetIndex(f) >= 0 ) { - module->globalFunctions.Erase(module->globalFunctions.GetIndex(func)); - module->scriptFunctions.RemoveValue(func); - func->ReleaseInternal(); + module->globalFunctions.Erase(module->globalFunctions.GetIndex(f)); + module->scriptFunctions.RemoveValue(f); + f->ReleaseInternal(); } } } @@ -638,16 +638,20 @@ void asCBuilder::ParseScripts() } } - if( numErrors == 0 ) + if (numErrors == 0) { // Find all type declarations - for( n = 0; n < scripts.GetLength(); n++ ) + for (n = 0; n < scripts.GetLength(); n++) { asCScriptNode *node = parsers[n]->GetScriptNode(); RegisterTypesFromScript(node, scripts[n], engine->nameSpaces[0]); } - // Register the complete function definitions + // Before moving forward the builder must establish the relationship between types + // so that a derived type can see the child types of the parent type. + DetermineTypeRelations(); + + // Complete function definitions (defining returntype and parameters) for( n = 0; n < funcDefs.GetLength(); n++ ) CompleteFuncDef(funcDefs[n]); @@ -667,12 +671,12 @@ void asCBuilder::ParseScripts() if( node->nodeType == snFunction ) { node->DisconnectParent(); - RegisterScriptFunctionFromNode(node, decl->script, decl->objType, true, false, 0, decl->isExistingShared); + RegisterScriptFunctionFromNode(node, decl->script, CastToObjectType(decl->typeInfo), true, false, 0, decl->isExistingShared); } else if( node->nodeType == snVirtualProperty ) { node->DisconnectParent(); - RegisterVirtualProperty(node, decl->script, decl->objType, true, false, 0, decl->isExistingShared); + RegisterVirtualProperty(node, decl->script, CastToObjectType(decl->typeInfo), true, false, 0, decl->isExistingShared); } node = next; @@ -696,44 +700,45 @@ void asCBuilder::ParseScripts() if( node->nodeType == snFunction ) { node->DisconnectParent(); - RegisterScriptFunctionFromNode(node, decl->script, decl->objType, false, false, 0, decl->isExistingShared); + RegisterScriptFunctionFromNode(node, decl->script, CastToObjectType(decl->typeInfo), false, false, 0, decl->isExistingShared); } else if( node->nodeType == snVirtualProperty ) { node->DisconnectParent(); - RegisterVirtualProperty(node, decl->script, decl->objType, false, false, 0, decl->isExistingShared); + RegisterVirtualProperty(node, decl->script, CastToObjectType(decl->typeInfo), false, false, 0, decl->isExistingShared); } node = next; } // Make sure the default factory & constructor exists for classes - if( decl->objType->beh.construct == engine->scriptTypeBehaviours.beh.construct ) + asCObjectType *ot = CastToObjectType(decl->typeInfo); + if( ot->beh.construct == engine->scriptTypeBehaviours.beh.construct ) { - if( decl->objType->beh.constructors.GetLength() == 1 || engine->ep.alwaysImplDefaultConstruct ) + if( ot->beh.constructors.GetLength() == 1 || engine->ep.alwaysImplDefaultConstruct ) { - AddDefaultConstructor(decl->objType, decl->script); + AddDefaultConstructor(ot, decl->script); } else { // As the class has another constructor we shouldn't provide the default constructor - if( decl->objType->beh.construct ) + if( ot->beh.construct ) { - engine->scriptFunctions[decl->objType->beh.construct]->ReleaseInternal(); - decl->objType->beh.construct = 0; - decl->objType->beh.constructors.RemoveIndex(0); + engine->scriptFunctions[ot->beh.construct]->ReleaseInternal(); + ot->beh.construct = 0; + ot->beh.constructors.RemoveIndex(0); } - if( decl->objType->beh.factory ) + if( ot->beh.factory ) { - engine->scriptFunctions[decl->objType->beh.factory]->ReleaseInternal(); - decl->objType->beh.factory = 0; - decl->objType->beh.factories.RemoveIndex(0); + engine->scriptFunctions[ot->beh.factory]->ReleaseInternal(); + ot->beh.factory = 0; + ot->beh.factories.RemoveIndex(0); } // Only remove the opAssign method if the script hasn't provided one - if( decl->objType->beh.copy == engine->scriptTypeBehaviours.beh.copy ) + if( ot->beh.copy == engine->scriptTypeBehaviours.beh.copy ) { - engine->scriptFunctions[decl->objType->beh.copy]->ReleaseInternal(); - decl->objType->beh.copy = 0; + engine->scriptFunctions[ot->beh.copy]->ReleaseInternal(); + ot->beh.copy = 0; } } } @@ -799,7 +804,7 @@ void asCBuilder::RegisterTypesFromScript(asCScriptNode *node, asCScriptCode *scr else if( node->nodeType == snFuncDef ) { node->DisconnectParent(); - RegisterFuncDef(node, script, ns); + RegisterFuncDef(node, script, ns, 0); } else if( node->nodeType == snMixin ) { @@ -868,6 +873,10 @@ void asCBuilder::CompileFunctions() // Don't compile the function again if it was an existing shared function if( current->isExistingShared ) continue; + // Don't compile if there is no statement block + if (current->node && !(current->node->nodeType == snStatementBlock || current->node->lastChild->nodeType == snStatementBlock)) + continue; + asCCompiler compiler(engine); asCScriptFunction *func = engine->scriptFunctions[current->funcId]; @@ -875,11 +884,11 @@ void asCBuilder::CompileFunctions() sClassDeclaration *classDecl = 0; if( current->objType && current->name == current->objType->name ) { - for( asUINT n = 0; n < classDeclarations.GetLength(); n++ ) + for( asUINT c = 0; c < classDeclarations.GetLength(); c++ ) { - if( classDeclarations[n]->objType == current->objType ) + if( classDeclarations[c]->typeInfo == current->objType ) { - classDecl = classDeclarations[n]; + classDecl = classDeclarations[c]; break; } } @@ -994,7 +1003,7 @@ int asCBuilder::VerifyProperty(asCDataType *dt, const char *decl, asCString &nam if( dt ) { // Verify that the object type exist - if( dt->GetObjectType() == 0 ) + if( CastToObjectType(dt->GetTypeInfo()) == 0 ) return asINVALID_OBJECT; } @@ -1018,14 +1027,14 @@ int asCBuilder::VerifyProperty(asCDataType *dt, const char *decl, asCString &nam // If an object property is registered, then use the // object's namespace, otherwise use the specified namespace - type = CreateDataTypeFromNode(dataType, &source, dt ? dt->GetObjectType()->nameSpace : ns); + type = CreateDataTypeFromNode(dataType, &source, dt ? dt->GetTypeInfo()->nameSpace : ns); name.Assign(&decl[nameNode->tokenPos], nameNode->tokenLength); type.MakeReference(isReference); // Validate that the type really can be a registered property // We cannot use CanBeInstantiated, as it is allowed to register // properties of type that cannot otherwise be instantiated - if( type.GetFuncDef() && !type.IsObjectHandle() ) + if( type.IsFuncdef() && !type.IsObjectHandle() ) { // Function definitions must always be handles return asINVALID_DECLARATION; @@ -1034,7 +1043,7 @@ int asCBuilder::VerifyProperty(asCDataType *dt, const char *decl, asCString &nam // Verify property name if( dt ) { - if( CheckNameConflictMember(dt->GetObjectType(), name.AddressOf(), nameNode, &source, true) < 0 ) + if( CheckNameConflictMember(dt->GetTypeInfo(), name.AddressOf(), nameNode, &source, true) < 0 ) return asNAME_TAKEN; } else @@ -1052,10 +1061,10 @@ int asCBuilder::VerifyProperty(asCDataType *dt, const char *decl, asCString &nam #ifndef AS_NO_COMPILER asCObjectProperty *asCBuilder::GetObjectProperty(asCDataType &obj, const char *prop) { - asASSERT(obj.GetObjectType() != 0); + asASSERT(CastToObjectType(obj.GetTypeInfo()) != 0); // TODO: optimize: Improve linear search - asCArray &props = obj.GetObjectType()->properties; + asCArray &props = CastToObjectType(obj.GetTypeInfo())->properties; for( asUINT n = 0; n < props.GetLength(); n++ ) { if( props[n]->name == prop ) @@ -1131,7 +1140,7 @@ asCGlobalProperty *asCBuilder::GetGlobalProperty(const char *prop, asSNameSpace if( isPureConstant ) *isPureConstant = globDesc->isPureConstant; if( constantValue ) *constantValue = globDesc->constantValue; } - else + else #endif if( isAppProp ) { @@ -1145,10 +1154,15 @@ asCGlobalProperty *asCBuilder::GetGlobalProperty(const char *prop, asSNameSpace return 0; } -int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray *paramAutoHandles, bool *returnAutoHandle, asSNameSpace *ns, asCScriptNode **listPattern) +int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray *paramAutoHandles, bool *returnAutoHandle, asSNameSpace *ns, asCScriptNode **listPattern, asCObjectType **outParentClass) { asASSERT( objType || ns ); + if (listPattern) + *listPattern = 0; + if (outParentClass) + *outParentClass = 0; + // TODO: Can't we use GetParsedFunctionDetails to do most of what is done in this function? Reset(); @@ -1165,13 +1179,15 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec // Determine scope asCScriptNode *n = node->firstChild->next->next; - asCString scope = GetScopeFromNode(n, &source, &n); - if( scope == "::" ) - func->nameSpace = engine->nameSpaces[0]; - else - func->nameSpace = engine->FindNameSpace(scope.AddressOf()); - if( func->nameSpace == 0 ) + asCObjectType *parentClass = 0; + func->nameSpace = GetNameSpaceFromNode(n, &source, ns, &n, &parentClass); + if( func->nameSpace == 0 && parentClass == 0 ) return asINVALID_DECLARATION; + if (parentClass && func->funcType != asFUNC_FUNCDEF) + return asINVALID_DECLARATION; + + if (outParentClass) + *outParentClass = parentClass; // Find name func->name.Assign(&source.code[n->tokenPos], n->tokenLength); @@ -1180,7 +1196,7 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec bool autoHandle; // Scoped reference types are allowed to use handle when returned from application functions - func->returnType = CreateDataTypeFromNode(node->firstChild, &source, objType ? objType->nameSpace : ns, true, objType); + func->returnType = CreateDataTypeFromNode(node->firstChild, &source, objType ? objType->nameSpace : ns, true, parentClass ? parentClass : objType); func->returnType = ModifyDataTypeFromNode(func->returnType, node->firstChild->next, &source, 0, &autoHandle); if( autoHandle && (!func->returnType.IsObjectHandle() || func->returnType.IsReference()) ) return asINVALID_DECLARATION; @@ -1188,8 +1204,8 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec // Reference types cannot be returned by value from system functions if( isSystemFunction && - (func->returnType.GetObjectType() && - (func->returnType.GetObjectType()->flags & asOBJ_REF)) && + (func->returnType.GetTypeInfo() && + (func->returnType.GetTypeInfo()->flags & asOBJ_REF)) && !(func->returnType.IsReference() || func->returnType.IsObjectHandle()) ) return asINVALID_DECLARATION; @@ -1221,13 +1237,13 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec while( n ) { asETypeModifiers inOutFlags; - asCDataType type = CreateDataTypeFromNode(n, &source, objType ? objType->nameSpace : ns, false, objType); + asCDataType type = CreateDataTypeFromNode(n, &source, objType ? objType->nameSpace : ns, false, parentClass ? parentClass : objType); type = ModifyDataTypeFromNode(type, n->next, &source, &inOutFlags, &autoHandle); // Reference types cannot be passed by value to system functions if( isSystemFunction && - (type.GetObjectType() && - (type.GetObjectType()->flags & asOBJ_REF)) && + (type.GetTypeInfo() && + (type.GetTypeInfo()->flags & asOBJ_REF)) && !(type.IsReference() || type.IsObjectHandle()) ) return asINVALID_DECLARATION; @@ -1252,7 +1268,7 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec // Move to next parameter n = n->next->next; - if( n && n->nodeType == snIdentifier ) + if( n && n->nodeType == snIdentifier ) { func->parameterNames[index] = asCString(&source.code[n->tokenPos], n->tokenLength); n = n->next; @@ -1281,17 +1297,17 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec { if( objType == 0 ) return asINVALID_DECLARATION; - func->isReadOnly = true; + func->SetReadOnly(true); n = n->next; } else - func->isReadOnly = false; + func->SetReadOnly(false); // If the caller expects a list pattern, check for the existence, else report an error if not if( listPattern ) { - if( n == 0 || n->nodeType != snListPattern ) + if( n == 0 || n->nodeType != snListPattern ) return asINVALID_DECLARATION; else { @@ -1304,7 +1320,7 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec if( n ) return asINVALID_DECLARATION; } - + // Make sure the default args are declared correctly ValidateDefaultArgs(&source, node, func); @@ -1331,6 +1347,7 @@ int asCBuilder::ParseVariableDeclaration(const char *decl, asSNameSpace *implici // Determine the scope from declaration asCScriptNode *n = node->firstChild->next; + // TODO: child funcdef: The parentType will be set if the scope is actually a type rather than a namespace outNamespace = GetNameSpaceFromNode(n, &source, implicitNamespace, &n); if( outNamespace == 0 ) return asINVALID_DECLARATION; @@ -1347,12 +1364,16 @@ int asCBuilder::ParseVariableDeclaration(const char *decl, asSNameSpace *implici return 0; } -int asCBuilder::CheckNameConflictMember(asCObjectType *t, const char *name, asCScriptNode *node, asCScriptCode *code, bool isProperty) +int asCBuilder::CheckNameConflictMember(asCTypeInfo *t, const char *name, asCScriptNode *node, asCScriptCode *code, bool isProperty) { // It's not necessary to check against object types + asCObjectType *ot = CastToObjectType(t); + if (!ot) + return 0; + // TODO: optimize: Improve linear search - asCArray &props = t->properties; + asCArray &props = ot->properties; for( asUINT n = 0; n < props.GetLength(); n++ ) { if( props[n]->name == name ) @@ -1368,10 +1389,26 @@ int asCBuilder::CheckNameConflictMember(asCObjectType *t, const char *name, asCS } } + asCArray &funcdefs = ot->childFuncDefs; + for (asUINT n = 0; n < funcdefs.GetLength(); n++) + { + if (funcdefs[n]->name == name) + { + if (code) + { + asCString str; + str.Format(TXT_NAME_CONFLICT_s_IS_FUNCDEF, name); + WriteError(str, code, node); + } + + return -1; + } + } + // Property names must be checked against method names if( isProperty ) { - asCArray methods = t->methods; + asCArray methods = ot->methods; for( asUINT n = 0; n < methods.GetLength(); n++ ) { if( engine->scriptFunctions[methods[n]]->name == name ) @@ -1395,7 +1432,7 @@ int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScri { // Check against registered object types // TODO: Must check against registered funcdefs too - if( engine->GetRegisteredObjectType(name, ns) != 0 ) + if( engine->GetRegisteredType(name, ns) != 0 ) { if( code ) { @@ -1428,7 +1465,7 @@ int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScri for( n = 0; n < classDeclarations.GetLength(); n++ ) { if( classDeclarations[n]->name == name && - classDeclarations[n]->objType->nameSpace == ns ) + classDeclarations[n]->typeInfo->nameSpace == ns ) { if( code ) { @@ -1445,7 +1482,7 @@ int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScri for( n = 0; n < namedTypeDeclarations.GetLength(); n++ ) { if( namedTypeDeclarations[n]->name == name && - namedTypeDeclarations[n]->objType->nameSpace == ns ) + namedTypeDeclarations[n]->typeInfo->nameSpace == ns ) { if( code ) { @@ -1503,25 +1540,41 @@ sMixinClass *asCBuilder::GetMixinClass(const char *name, asSNameSpace *ns) return 0; } -int asCBuilder::RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns) +int asCBuilder::RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns, asCObjectType *parent) { - // TODO: redesign: Allow funcdefs to be explicitly declared as 'shared'. In this case - // an error should be given if any of the arguments/return type is not - // shared. + // namespace and parent are exclusively mutual + asASSERT((ns == 0 && parent) || (ns && parent == 0)); + + // Skip leading 'shared' and 'external' keywords + asCScriptNode *n = node->firstChild; + while (n->nodeType == snIdentifier) + n = n->next; // Find the name - asASSERT( node->firstChild->nodeType == snDataType ); - asCScriptNode *n = node->firstChild->next->next; + asASSERT( n->nodeType == snDataType ); + n = n->next->next; asCString name; name.Assign(&file->code[n->tokenPos], n->tokenLength); // Check for name conflict with other types - int r = CheckNameConflict(name.AddressOf(), node, file, ns); - if( asSUCCESS != r ) + if (ns) { - node->Destroy(engine); - return r; + int r = CheckNameConflict(name.AddressOf(), node, file, ns); + if (asSUCCESS != r) + { + node->Destroy(engine); + return r; + } + } + else + { + int r = CheckNameConflictMember(parent, name.AddressOf(), node, file, false); + if (asSUCCESS != r) + { + node->Destroy(engine); + return r; + } } // The function definition should be stored as a asCScriptFunction so that the application @@ -1541,7 +1594,7 @@ int asCBuilder::RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNam fd->name = name; fd->node = node; fd->script = file; - fd->idx = module->AddFuncDef(name, ns); + fd->idx = module->AddFuncDef(name, ns, parent); funcDefs.PushLast(fd); @@ -1551,20 +1604,14 @@ int asCBuilder::RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNam void asCBuilder::CompleteFuncDef(sFuncDef *funcDef) { asCArray defaultArgs; - bool isConstMethod; - bool isConstructor; - bool isDestructor; - bool isProtected; - bool isPrivate; - bool isOverride; - bool isFinal; - bool isShared; + asSFunctionTraits funcTraits; - asCScriptFunction *func = module->funcDefs[funcDef->idx]; - asASSERT( func ); + asCFuncdefType *fdt = module->funcDefs[funcDef->idx]; + asASSERT( fdt ); + asCScriptFunction *func = fdt->funcdef; - // TODO: It should be possible to declare funcdef as shared. In this case a compiler error will be given if any of the types it uses are not shared - GetParsedFunctionDetails(funcDef->node, funcDef->script, 0, funcDef->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared, func->nameSpace); + asSNameSpace *implicitNs = func->nameSpace ? func->nameSpace : fdt->parentClass->nameSpace; + GetParsedFunctionDetails(funcDef->node, funcDef->script, fdt->parentClass, funcDef->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, defaultArgs, funcTraits, implicitNs); // There should not be any defaultArgs, but if there are any we need to delete them to avoid leaks for( asUINT n = 0; n < defaultArgs.GetLength(); n++ ) @@ -1572,48 +1619,73 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef) asDELETE(defaultArgs[n], asCString); // All funcdefs are shared, unless one of the parameter types or return type is not shared - isShared = true; - if( func->returnType.GetObjectType() && !func->returnType.GetObjectType()->IsShared() ) - isShared = false; - if( func->returnType.GetFuncDef() && !func->returnType.GetFuncDef()->IsShared() ) - isShared = false; - for( asUINT n = 0; isShared && n < func->parameterTypes.GetLength(); n++ ) + bool declaredShared = funcTraits.GetTrait(asTRAIT_SHARED); + funcTraits.SetTrait(asTRAIT_SHARED, true); + if (func->returnType.GetTypeInfo() && !func->returnType.GetTypeInfo()->IsShared()) { - if( func->parameterTypes[n].GetObjectType() && !func->parameterTypes[n].GetObjectType()->IsShared() ) - isShared = false; - if( func->parameterTypes[n].GetFuncDef() && !func->parameterTypes[n].GetFuncDef()->IsShared() ) - isShared = false; + if (declaredShared) + { + asCString s; + s.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, func->returnType.GetTypeInfo()->name.AddressOf()); + WriteError(s.AddressOf(), funcDef->script, funcDef->node); + } + funcTraits.SetTrait(asTRAIT_SHARED, false); } - func->isShared = isShared; + for( asUINT n = 0; funcTraits.GetTrait(asTRAIT_SHARED) && n < func->parameterTypes.GetLength(); n++ ) + if (func->parameterTypes[n].GetTypeInfo() && !func->parameterTypes[n].GetTypeInfo()->IsShared()) + { + if (declaredShared) + { + asCString s; + s.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, func->parameterTypes[n].GetTypeInfo()->name.AddressOf()); + WriteError(s.AddressOf(), funcDef->script, funcDef->node); + } + funcTraits.SetTrait(asTRAIT_SHARED, false); + } + func->SetShared(funcTraits.GetTrait(asTRAIT_SHARED)); // Check if there is another identical funcdef from another module and if so reuse that instead - if( func->isShared ) + bool found = false; + if( func->IsShared() ) { for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ ) { - asCScriptFunction *f2 = engine->funcDefs[n]; - if( f2 == 0 || func == f2 ) + asCFuncdefType *fdt2 = engine->funcDefs[n]; + if( fdt2 == 0 || fdt == fdt2 ) continue; - if( !f2->isShared ) + if( !fdt2->funcdef->IsShared() ) continue; - if( f2->name == func->name && - f2->nameSpace == func->nameSpace && - f2->IsSignatureExceptNameEqual(func) ) + if( fdt2->name == fdt->name && + fdt2->nameSpace == fdt->nameSpace && + fdt2->funcdef->IsSignatureExceptNameEqual(func) ) { // Replace our funcdef for the existing one - funcDef->idx = f2->id; - module->funcDefs[module->funcDefs.IndexOf(func)] = f2; - f2->AddRefInternal(); + funcDef->idx = fdt2->funcdef->id; + module->funcDefs[module->funcDefs.IndexOf(fdt)] = fdt2; + fdt2->AddRefInternal(); - engine->funcDefs.RemoveValue(func); + engine->funcDefs.RemoveValue(fdt); - func->ReleaseInternal(); + fdt->ReleaseInternal(); + found = true; break; } } } + + // If the funcdef was declared as external then the existing shared declaration must have been found + if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && !found) + { + asCString str; + str.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, funcDef->name.AddressOf()); + WriteError(str, funcDef->script, funcDef->node); + } + + // Remember if the type was declared as external so the saved bytecode can be flagged accordingly + if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && found) + module->externalTypes.PushLast(engine->scriptFunctions[funcDef->idx]->funcdefType); } int asCBuilder::RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns) @@ -1741,6 +1813,19 @@ int asCBuilder::RegisterMixinClass(asCScriptNode *node, asCScriptCode *file, asS cl->DisconnectParent(); node->Destroy(engine); + // Check that the mixin class doesn't contain any child types + // TODO: Add support for child types in mixin classes + n = cl->firstChild; + while (n) + { + if (n->nodeType == snFuncDef) + { + WriteError(TXT_MIXIN_CANNOT_HAVE_CHILD_TYPES, file, n); + break; + } + n = n->next; + } + return 0; } @@ -1750,6 +1835,7 @@ int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameS bool isFinal = false; bool isShared = false; bool isAbstract = false; + bool isExternal = false; // Check the class modifiers while( n->tokenType == ttIdentifier ) @@ -1779,6 +1865,16 @@ int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameS } isShared = true; } + else if (file->TokenEquals(n->tokenPos, n->tokenLength, EXTERNAL_TOKEN)) + { + if (isExternal) + { + asCString msg; + msg.Format(TXT_ATTR_s_INFORMED_MULTIPLE_TIMES, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf()); + WriteWarning(msg, file, n); + } + isExternal = true; + } else if( file->TokenEquals(n->tokenPos, n->tokenLength, ABSTRACT_TOKEN) ) { if( isFinal ) @@ -1822,14 +1918,29 @@ int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameS decl->script = file; decl->node = node; + // External shared interfaces must not try to redefine the interface + if (isExternal && (n->next == 0 || n->next->tokenType != ttEndStatement)) + { + asCString str; + str.Format(TXT_EXTERNAL_SHARED_s_CANNOT_REDEF, name.AddressOf()); + WriteError(str, file, n); + } + else if (!isExternal && n->next && n->next->tokenType == ttEndStatement) + { + asCString str; + str.Format(TXT_MISSING_DEFINITION_OF_s, name.AddressOf()); + WriteError(str, file, n); + } + // If this type is shared and there already exist another shared // type of the same name, then that one should be used instead of // creating a new one. + asCObjectType *st = 0; if( isShared ) { - for( asUINT n = 0; n < engine->sharedScriptTypes.GetLength(); n++ ) + for( asUINT i = 0; i < engine->sharedScriptTypes.GetLength(); i++ ) { - asCObjectType *st = engine->sharedScriptTypes[n]; + st = CastToObjectType(engine->sharedScriptTypes[i]); if( st && st->IsShared() && st->name == name && @@ -1838,68 +1949,106 @@ int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameS { // We'll use the existing type decl->isExistingShared = true; - decl->objType = st; + decl->typeInfo = st; module->classTypes.PushLast(st); st->AddRefInternal(); - return 0; + break; } } } - // Create a new object type for this class - asCObjectType *st = asNEW(asCObjectType)(engine); - if( st == 0 ) - return asOUT_OF_MEMORY; - - // By default all script classes are marked as garbage collected. - // Only after the complete structure and relationship between classes - // is known, can the flag be cleared for those objects that truly cannot - // form circular references. This is important because a template - // callback may be called with a script class before the compilation - // completes, and until it is known, the callback must assume the class - // is garbage collected. - st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT | asOBJ_GC; - - if( isShared ) - st->flags |= asOBJ_SHARED; - - if( isFinal ) - st->flags |= asOBJ_NOINHERIT; - - if( isAbstract ) - st->flags |= asOBJ_ABSTRACT; - - if( node->tokenType == ttHandle ) - st->flags |= asOBJ_IMPLICIT_HANDLE; - - st->size = sizeof(asCScriptObject); - st->name = name; - st->nameSpace = ns; - st->module = module; - module->classTypes.PushLast(st); - if( isShared ) + // If the class was declared as external then it must have been compiled in a different module first + if (isExternal && decl->typeInfo == 0) { - engine->sharedScriptTypes.PushLast(st); - st->AddRefInternal(); + asCString str; + str.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, name.AddressOf()); + WriteError(str, file, n); } - decl->objType = st; - // Use the default script class behaviours - st->beh = engine->scriptTypeBehaviours.beh; + // Remember if the class was declared as external so the saved bytecode can be flagged accordingly + if (isExternal) + module->externalTypes.PushLast(st); - // TODO: Move this to asCObjectType so that the asCRestore can reuse it - engine->scriptFunctions[st->beh.addref]->AddRefInternal(); - engine->scriptFunctions[st->beh.release]->AddRefInternal(); - engine->scriptFunctions[st->beh.gcEnumReferences]->AddRefInternal(); - engine->scriptFunctions[st->beh.gcGetFlag]->AddRefInternal(); - engine->scriptFunctions[st->beh.gcGetRefCount]->AddRefInternal(); - engine->scriptFunctions[st->beh.gcReleaseAllReferences]->AddRefInternal(); - engine->scriptFunctions[st->beh.gcSetFlag]->AddRefInternal(); - engine->scriptFunctions[st->beh.copy]->AddRefInternal(); - engine->scriptFunctions[st->beh.factory]->AddRefInternal(); - engine->scriptFunctions[st->beh.construct]->AddRefInternal(); - // TODO: weak: Should not do this if the class has been declared with noweak - engine->scriptFunctions[st->beh.getWeakRefFlag]->AddRefInternal(); + if (!decl->isExistingShared) + { + // Create a new object type for this class + st = asNEW(asCObjectType)(engine); + if (st == 0) + return asOUT_OF_MEMORY; + + // By default all script classes are marked as garbage collected. + // Only after the complete structure and relationship between classes + // is known, can the flag be cleared for those objects that truly cannot + // form circular references. This is important because a template + // callback may be called with a script class before the compilation + // completes, and until it is known, the callback must assume the class + // is garbage collected. + st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT | asOBJ_GC; + + if (isShared) + st->flags |= asOBJ_SHARED; + + if (isFinal) + st->flags |= asOBJ_NOINHERIT; + + if (isAbstract) + st->flags |= asOBJ_ABSTRACT; + + if (node->tokenType == ttHandle) + st->flags |= asOBJ_IMPLICIT_HANDLE; + + st->size = sizeof(asCScriptObject); + st->name = name; + st->nameSpace = ns; + st->module = module; + module->classTypes.PushLast(st); + if (isShared) + { + engine->sharedScriptTypes.PushLast(st); + st->AddRefInternal(); + } + decl->typeInfo = st; + + // Use the default script class behaviours + st->beh = engine->scriptTypeBehaviours.beh; + + // TODO: Move this to asCObjectType so that the asCRestore can reuse it + engine->scriptFunctions[st->beh.addref]->AddRefInternal(); + engine->scriptFunctions[st->beh.release]->AddRefInternal(); + engine->scriptFunctions[st->beh.gcEnumReferences]->AddRefInternal(); + engine->scriptFunctions[st->beh.gcGetFlag]->AddRefInternal(); + engine->scriptFunctions[st->beh.gcGetRefCount]->AddRefInternal(); + engine->scriptFunctions[st->beh.gcReleaseAllReferences]->AddRefInternal(); + engine->scriptFunctions[st->beh.gcSetFlag]->AddRefInternal(); + engine->scriptFunctions[st->beh.copy]->AddRefInternal(); + engine->scriptFunctions[st->beh.factory]->AddRefInternal(); + engine->scriptFunctions[st->beh.construct]->AddRefInternal(); + // TODO: weak: Should not do this if the class has been declared with noweak + engine->scriptFunctions[st->beh.getWeakRefFlag]->AddRefInternal(); + + // Skip to the content of the class + while (n && n->nodeType == snIdentifier) + n = n->next; + } + + // Register possible child types + while (n) + { + node = n->next; + if (n->nodeType == snFuncDef) + { + n->DisconnectParent(); + if (!decl->isExistingShared) + RegisterFuncDef(n, file, 0, st); + else + { + // Destroy the node, since it won't be used + // TODO: Should verify that the funcdef is identical to the one in the existing shared class + n->Destroy(engine); + } + } + n = node; + } return 0; } @@ -1907,20 +2056,25 @@ int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameS int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns) { asCScriptNode *n = node->firstChild; - asCString name(&file->code[n->tokenPos], n->tokenLength); bool isShared = false; - if( name == SHARED_TOKEN ) + bool isExternal = false; + while( n->nodeType == snIdentifier ) { - isShared = true; - + if (file->TokenEquals(n->tokenPos, n->tokenLength, SHARED_TOKEN)) + isShared = true; + else if (file->TokenEquals(n->tokenPos, n->tokenLength, EXTERNAL_TOKEN)) + isExternal = true; + else + break; n = n->next; - name.Assign(&file->code[n->tokenPos], n->tokenLength); } int r, c; file->ConvertPosToRowCol(n->tokenPos, &r, &c); + asCString name; + name.Assign(&file->code[n->tokenPos], n->tokenLength); CheckNameConflict(name.AddressOf(), n, file, ns); sClassDeclaration *decl = asNEW(sClassDeclaration); @@ -1935,14 +2089,28 @@ int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSN decl->script = file; decl->node = node; + // External shared interfaces must not try to redefine the interface + if (isExternal && (n->next == 0 || n->next->tokenType != ttEndStatement) ) + { + asCString str; + str.Format(TXT_EXTERNAL_SHARED_s_CANNOT_REDEF, name.AddressOf()); + WriteError(str, file, n); + } + else if (!isExternal && n->next && n->next->tokenType == ttEndStatement) + { + asCString str; + str.Format(TXT_MISSING_DEFINITION_OF_s, name.AddressOf()); + WriteError(str, file, n); + } + // If this type is shared and there already exist another shared // type of the same name, then that one should be used instead of // creating a new one. if( isShared ) { - for( asUINT n = 0; n < engine->sharedScriptTypes.GetLength(); n++ ) + for( asUINT i = 0; i < engine->sharedScriptTypes.GetLength(); i++ ) { - asCObjectType *st = engine->sharedScriptTypes[n]; + asCObjectType *st = CastToObjectType(engine->sharedScriptTypes[i]); if( st && st->IsShared() && st->name == name && @@ -1951,14 +2119,27 @@ int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSN { // We'll use the existing type decl->isExistingShared = true; - decl->objType = st; + decl->typeInfo = st; module->classTypes.PushLast(st); st->AddRefInternal(); + + // Remember if the interface was declared as external so the saved bytecode can be flagged accordingly + if (isExternal) + module->externalTypes.PushLast(st); + return 0; } } } + // If the interface was declared as external then it must have been compiled in a different module first + if (isExternal) + { + asCString str; + str.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, name.AddressOf()); + WriteError(str, file, n); + } + // Register the object type for the interface asCObjectType *st = asNEW(asCObjectType)(engine); if( st == 0 ) @@ -1979,7 +2160,7 @@ int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSN engine->sharedScriptTypes.PushLast(st); st->AddRefInternal(); } - decl->objType = st; + decl->typeInfo = st; // Use the default script class behaviours st->beh.construct = 0; @@ -2067,7 +2248,7 @@ void asCBuilder::CompileGlobalVariables() asCScriptFunction func(engine, module, asFUNC_SCRIPT); // Set the namespace that should be used during the compilation - func.nameSpace = gvar->datatype.GetObjectType()->nameSpace; + func.nameSpace = gvar->datatype.GetTypeInfo()->nameSpace; // Temporarily switch the type of the variable to int so it can be compiled properly asCDataType saveType; @@ -2092,8 +2273,7 @@ void asCBuilder::CompileGlobalVariables() sGlobalVariableDescription *gvar2 = *prev_it; if(gvar2->datatype == gvar->datatype ) { - // The integer value is stored in the lower bytes - enumVal = (*(int*)&gvar2->constantValue) + 1; + enumVal = int(gvar2->constantValue) + 1; if( !gvar2->isCompiled ) { @@ -2112,8 +2292,7 @@ void asCBuilder::CompileGlobalVariables() } } - // The integer value is stored in the lower bytes - *(int*)&gvar->constantValue = enumVal; + gvar->constantValue = enumVal; } if( r >= 0 ) @@ -2200,8 +2379,8 @@ void asCBuilder::CompileGlobalVariables() // Convert enums to true enum values, so subsequent compilations can access it as an enum if( gvar->isEnumValue ) { - asCObjectType *objectType = gvar->datatype.GetObjectType(); - asASSERT(NULL != objectType); + asCEnumType *enumType = CastToEnumType(gvar->datatype.GetTypeInfo()); + asASSERT(NULL != enumType); asSEnumValue *e = asNEW(asSEnumValue); if( e == 0 ) @@ -2212,9 +2391,9 @@ void asCBuilder::CompileGlobalVariables() } e->name = gvar->name; - e->value = *(int*)&gvar->constantValue; + e->value = int(gvar->constantValue); - objectType->enumValues.PushLast(e); + enumType->enumValues.PushLast(e); } } else @@ -2303,9 +2482,11 @@ void asCBuilder::CompileGlobalVariables() int asCBuilder::GetNamespaceAndNameFromNode(asCScriptNode *n, asCScriptCode *script, asSNameSpace *implicitNs, asSNameSpace *&outNs, asCString &outName) { + // TODO: child funcdef: The node might be a snScope now asASSERT( n->nodeType == snIdentifier ); // Get the optional scope from the node + // TODO: child funcdef: The parentType will be set if the scope is actually a type rather than a namespace asSNameSpace *ns = GetNameSpaceFromNode(n->firstChild, script, implicitNs, 0); if( ns == 0 ) return -1; @@ -2345,7 +2526,7 @@ void asCBuilder::AddInterfaceFromMixinToClass(sClassDeclaration *decl, asCScript if( objType && objType->IsInterface() ) { // Only add the interface if the class doesn't already implement it - if( !decl->objType->Implements(objType) ) + if( !decl->typeInfo->Implements(objType) ) AddInterfaceToClass(decl, errNode, objType); } else @@ -2371,7 +2552,7 @@ void asCBuilder::AddInterfaceFromMixinToClass(sClassDeclaration *decl, asCScript void asCBuilder::AddInterfaceToClass(sClassDeclaration *decl, asCScriptNode *errNode, asCObjectType *intfType) { // A shared type may only implement from shared interfaces - if( decl->objType->IsShared() && !intfType->IsShared() ) + if( decl->typeInfo->IsShared() && !intfType->IsShared() ) { asCString msg; msg.Format(TXT_SHARED_CANNOT_IMPLEMENT_NON_SHARED_s, intfType->name.AddressOf()); @@ -2383,10 +2564,10 @@ void asCBuilder::AddInterfaceToClass(sClassDeclaration *decl, asCScriptNode *err { // If the class is an existing shared class, then just check if the // interface exists in the original declaration too - if( !decl->objType->Implements(intfType) ) + if( !decl->typeInfo->Implements(intfType) ) { asCString str; - str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->objType->GetName()); + str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->typeInfo->GetName()); WriteError(str, decl->script, errNode); return; } @@ -2394,15 +2575,15 @@ void asCBuilder::AddInterfaceToClass(sClassDeclaration *decl, asCScriptNode *err else { // If the interface is already in the class then don't add it again - if( decl->objType->Implements(intfType) ) + if( decl->typeInfo->Implements(intfType) ) return; // Add the interface to the class - decl->objType->interfaces.PushLast(intfType); + CastToObjectType(decl->typeInfo)->interfaces.PushLast(intfType); // Add the inherited interfaces too // For interfaces this will be done outside to handle out-of-order declarations - if( !decl->objType->IsInterface() ) + if( !CastToObjectType(decl->typeInfo)->IsInterface() ) { for( asUINT n = 0; n < intfType->interfaces.GetLength(); n++ ) AddInterfaceToClass(decl, errNode, intfType->interfaces[n]); @@ -2413,107 +2594,20 @@ void asCBuilder::AddInterfaceToClass(sClassDeclaration *decl, asCScriptNode *err void asCBuilder::CompileInterfaces() { asUINT n; - for( n = 0; n < interfaceDeclarations.GetLength(); n++ ) - { - sClassDeclaration *intfDecl = interfaceDeclarations[n]; - asCObjectType *intfType = intfDecl->objType; - - asCScriptNode *node = intfDecl->node; - asASSERT(node && node->nodeType == snInterface); - node = node->firstChild; - - // Skip the 'shared' keyword - if( intfType->IsShared() ) - node = node->next; - - // Skip the name - node = node->next; - - // Verify the inherited interfaces - while( node && node->nodeType == snIdentifier ) - { - asSNameSpace *ns; - asCString name; - if( GetNamespaceAndNameFromNode(node, intfDecl->script, intfType->nameSpace, ns, name) < 0 ) - { - node = node->next; - continue; - } - - // Find the object type for the interface - asCObjectType *objType = 0; - while( ns ) - { - objType = GetObjectType(name.AddressOf(), ns); - if( objType ) break; - - ns = engine->GetParentNameSpace(ns); - } - - // Check that the object type is an interface - bool ok = true; - if( objType && objType->IsInterface() ) - { - // Check that the implemented interface is shared if the base interface is shared - if( intfType->IsShared() && !objType->IsShared() ) - { - asCString str; - str.Format(TXT_SHARED_CANNOT_IMPLEMENT_NON_SHARED_s, objType->GetName()); - WriteError(str, intfDecl->script, node); - ok = false; - } - } - else - { - WriteError(TXT_INTERFACE_CAN_ONLY_IMPLEMENT_INTERFACE, intfDecl->script, node); - ok = false; - } - - if( ok ) - { - // Make sure none of the implemented interfaces implement from this one - asCObjectType *base = objType; - while( base != 0 ) - { - if( base == intfType ) - { - WriteError(TXT_CANNOT_IMPLEMENT_SELF, intfDecl->script, node); - ok = false; - break; - } - - // At this point there is at most one implemented interface - if( base->interfaces.GetLength() ) - base = base->interfaces[0]; - else - break; - } - } - - if( ok ) - AddInterfaceToClass(intfDecl, node, objType); - - // Remove the nodes so they aren't parsed again - asCScriptNode *delNode = node; - node = node->next; - delNode->DisconnectParent(); - delNode->Destroy(engine); - } - } // Order the interfaces with inheritances so that the inherited // of inherited interfaces can be added properly for( n = 0; n < interfaceDeclarations.GetLength(); n++ ) { sClassDeclaration *intfDecl = interfaceDeclarations[n]; - asCObjectType *intfType = intfDecl->objType; + asCObjectType *intfType = CastToObjectType(intfDecl->typeInfo); if( intfType->interfaces.GetLength() == 0 ) continue; // If any of the derived interfaces are found after this interface, then move this to the end of the list for( asUINT m = n+1; m < interfaceDeclarations.GetLength(); m++ ) { - if( intfType->Implements(interfaceDeclarations[m]->objType) ) + if( intfType->Implements(interfaceDeclarations[m]->typeInfo) ) { interfaceDeclarations.RemoveIndex(n); interfaceDeclarations.PushLast(intfDecl); @@ -2529,7 +2623,7 @@ void asCBuilder::CompileInterfaces() for( n = 0; n < interfaceDeclarations.GetLength(); n++ ) { sClassDeclaration *intfDecl = interfaceDeclarations[n]; - asCObjectType *intfType = intfDecl->objType; + asCObjectType *intfType = CastToObjectType(intfDecl->typeInfo); // TODO: Is this really at the correct place? Hasn't the vfTableIdx already been set here? // Co-opt the vfTableIdx value in our own methods to indicate the @@ -2553,10 +2647,10 @@ void asCBuilder::CompileInterfaces() AddInterfaceToClass(intfDecl, intfDecl->node, base->interfaces[l]); // Add the methods from the implemented interface - for( asUINT m = 0; m < base->methods.GetLength(); m++ ) + for( asUINT l = 0; l < base->methods.GetLength(); l++ ) { // If the derived interface implements the same method, then don't add the base interface' method - asCScriptFunction *baseFunc = GetFunctionDescription(base->methods[m]); + asCScriptFunction *baseFunc = GetFunctionDescription(base->methods[l]); asCScriptFunction *derivedFunc = 0; bool found = false; for( asUINT d = 0; d < intfType->methods.GetLength(); d++ ) @@ -2580,14 +2674,101 @@ void asCBuilder::CompileInterfaces() } } -// numTempl is the number of template instances that existed in the engine before the build begun -void asCBuilder::CompileClasses(asUINT numTempl) +void asCBuilder::DetermineTypeRelations() { - asUINT n; - asCArray toValidate((int)classDeclarations.GetLength()); + // Determine inheritance between interfaces + for (asUINT n = 0; n < interfaceDeclarations.GetLength(); n++) + { + sClassDeclaration *intfDecl = interfaceDeclarations[n]; + asCObjectType *intfType = CastToObjectType(intfDecl->typeInfo); + + asCScriptNode *node = intfDecl->node; + asASSERT(node && node->nodeType == snInterface); + node = node->firstChild; + + // Skip the 'shared' & 'external' keywords + while( node->nodeType == snIdentifier && + (intfDecl->script->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN) || + intfDecl->script->TokenEquals(node->tokenPos, node->tokenLength, EXTERNAL_TOKEN)) ) + node = node->next; + + // Skip the name + node = node->next; + + // Verify the inherited interfaces + while (node && node->nodeType == snIdentifier) + { + asSNameSpace *ns; + asCString name; + if (GetNamespaceAndNameFromNode(node, intfDecl->script, intfType->nameSpace, ns, name) < 0) + { + node = node->next; + continue; + } + + // Find the object type for the interface + asCObjectType *objType = 0; + while (ns) + { + objType = GetObjectType(name.AddressOf(), ns); + if (objType) break; + + ns = engine->GetParentNameSpace(ns); + } + + // Check that the object type is an interface + bool ok = true; + if (objType && objType->IsInterface()) + { + // Check that the implemented interface is shared if the base interface is shared + if (intfType->IsShared() && !objType->IsShared()) + { + asCString str; + str.Format(TXT_SHARED_CANNOT_IMPLEMENT_NON_SHARED_s, objType->GetName()); + WriteError(str, intfDecl->script, node); + ok = false; + } + } + else + { + WriteError(TXT_INTERFACE_CAN_ONLY_IMPLEMENT_INTERFACE, intfDecl->script, node); + ok = false; + } + + if (ok) + { + // Make sure none of the implemented interfaces implement from this one + asCObjectType *base = objType; + while (base != 0) + { + if (base == intfType) + { + WriteError(TXT_CANNOT_IMPLEMENT_SELF, intfDecl->script, node); + ok = false; + break; + } + + // At this point there is at most one implemented interface + if (base->interfaces.GetLength()) + base = base->interfaces[0]; + else + break; + } + } + + if (ok) + AddInterfaceToClass(intfDecl, node, objType); + + // Remove the nodes so they aren't parsed again + asCScriptNode *delNode = node; + node = node->next; + delNode->DisconnectParent(); + delNode->Destroy(engine); + } + } // Determine class inheritances and interfaces - for( n = 0; n < classDeclarations.GetLength(); n++ ) + for (asUINT n = 0; n < classDeclarations.GetLength(); n++) { sClassDeclaration *decl = classDeclarations[n]; asCScriptCode *file = decl->script; @@ -2596,9 +2777,10 @@ void asCBuilder::CompileClasses(asUINT numTempl) bool multipleInheritance = false; asCScriptNode *node = decl->node->firstChild; - while( file->TokenEquals(node->tokenPos, node->tokenLength, FINAL_TOKEN) || - file->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN) || - file->TokenEquals(node->tokenPos, node->tokenLength, ABSTRACT_TOKEN) ) + while (file->TokenEquals(node->tokenPos, node->tokenLength, FINAL_TOKEN) || + file->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN) || + file->TokenEquals(node->tokenPos, node->tokenLength, ABSTRACT_TOKEN) || + file->TokenEquals(node->tokenPos, node->tokenLength, EXTERNAL_TOKEN)) { node = node->next; } @@ -2607,11 +2789,11 @@ void asCBuilder::CompileClasses(asUINT numTempl) asASSERT(node->tokenType == ttIdentifier); node = node->next; - while( node && node->nodeType == snIdentifier ) + while (node && node->nodeType == snIdentifier) { asSNameSpace *ns; asCString name; - if( GetNamespaceAndNameFromNode(node, file, decl->objType->nameSpace, ns, name) < 0 ) + if (GetNamespaceAndNameFromNode(node, file, decl->typeInfo->nameSpace, ns, name) < 0) { node = node->next; continue; @@ -2621,33 +2803,33 @@ void asCBuilder::CompileClasses(asUINT numTempl) asCObjectType *objType = 0; sMixinClass *mixin = 0; asSNameSpace *origNs = ns; - while( ns ) + while (ns) { objType = GetObjectType(name.AddressOf(), ns); - if( objType == 0 ) + if (objType == 0) mixin = GetMixinClass(name.AddressOf(), ns); - if( objType || mixin ) + if (objType || mixin) break; ns = engine->GetParentNameSpace(ns); } - if( objType == 0 && mixin == 0 ) + if (objType == 0 && mixin == 0) { asCString str; - if( origNs->name == "" ) + if (origNs->name == "") str.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_GLOBAL_NS, name.AddressOf()); else str.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s, name.AddressOf(), origNs->name.AddressOf()); WriteError(str, file, node); } - else if( mixin ) + else if (mixin) { AddInterfaceFromMixinToClass(decl, node, mixin); } - else if( !(objType->flags & asOBJ_SCRIPT_OBJECT) || - (objType->flags & asOBJ_NOINHERIT) ) + else if (!(objType->flags & asOBJ_SCRIPT_OBJECT) || + (objType->flags & asOBJ_NOINHERIT)) { // Either the class is not a script class or interface // or the class has been declared as 'final' @@ -2655,12 +2837,12 @@ void asCBuilder::CompileClasses(asUINT numTempl) str.Format(TXT_CANNOT_INHERIT_FROM_s_FINAL, objType->name.AddressOf()); WriteError(str, file, node); } - else if( objType->size != 0 ) + else if (objType->size != 0) { // The class inherits from another script class - if( !decl->isExistingShared && decl->objType->derivedFrom != 0 ) + if (!decl->isExistingShared && CastToObjectType(decl->typeInfo)->derivedFrom != 0) { - if( !multipleInheritance ) + if (!multipleInheritance) { WriteError(TXT_CANNOT_INHERIT_FROM_MULTIPLE_CLASSES, file, node); multipleInheritance = true; @@ -2671,9 +2853,9 @@ void asCBuilder::CompileClasses(asUINT numTempl) // Make sure none of the base classes inherit from this one asCObjectType *base = objType; bool error = false; - while( base != 0 ) + while (base != 0) { - if( base == decl->objType ) + if (base == decl->typeInfo) { WriteError(TXT_CANNOT_INHERIT_FROM_SELF, file, node); error = true; @@ -2683,10 +2865,10 @@ void asCBuilder::CompileClasses(asUINT numTempl) base = base->derivedFrom; } - if( !error ) + if (!error) { // A shared type may only inherit from other shared types - if( (decl->objType->IsShared()) && !(objType->IsShared()) ) + if ((decl->typeInfo->IsShared()) && !(objType->IsShared())) { asCString msg; msg.Format(TXT_SHARED_CANNOT_INHERIT_FROM_NON_SHARED_s, objType->name.AddressOf()); @@ -2695,22 +2877,22 @@ void asCBuilder::CompileClasses(asUINT numTempl) } } - if( !error ) + if (!error) { - if( decl->isExistingShared ) + if (decl->isExistingShared) { // Verify that the base class is the same as the original shared type - if( decl->objType->derivedFrom != objType ) + if (CastToObjectType(decl->typeInfo)->derivedFrom != objType) { asCString str; - str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->objType->GetName()); + str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->typeInfo->GetName()); WriteError(str, file, node); } } else { // Set the base class - decl->objType->derivedFrom = objType; + CastToObjectType(decl->typeInfo)->derivedFrom = objType; objType->AddRefInternal(); } } @@ -2725,13 +2907,21 @@ void asCBuilder::CompileClasses(asUINT numTempl) node = node->next; } } +} + +// numTempl is the number of template instances that existed in the engine before the build begun +void asCBuilder::CompileClasses(asUINT numTempl) +{ + asUINT n; + asCArray toValidate((int)classDeclarations.GetLength()); + // Order class declarations so that base classes are compiled before derived classes. // This will allow the derived classes to copy properties and methods in the next step. for( n = 0; n < classDeclarations.GetLength(); n++ ) { sClassDeclaration *decl = classDeclarations[n]; - asCObjectType *derived = decl->objType; + asCObjectType *derived = CastToObjectType(decl->typeInfo); asCObjectType *base = derived->derivedFrom; if( base == 0 ) continue; @@ -2740,7 +2930,7 @@ void asCBuilder::CompileClasses(asUINT numTempl) for( asUINT m = n+1; m < classDeclarations.GetLength(); m++ ) { sClassDeclaration *declBase = classDeclarations[m]; - if( base == declBase->objType ) + if( base == declBase->typeInfo ) { classDeclarations.RemoveIndex(n); classDeclarations.PushLast(decl); @@ -2756,6 +2946,7 @@ void asCBuilder::CompileClasses(asUINT numTempl) for( n = 0; n < classDeclarations.GetLength(); n++ ) { sClassDeclaration *decl = classDeclarations[n]; + asCObjectType *ot = CastToObjectType(decl->typeInfo); if( decl->isExistingShared ) { // Set the declaration as validated already, so that other @@ -2767,22 +2958,22 @@ void asCBuilder::CompileClasses(asUINT numTempl) // compilation. We do not care if something that is there in the previous // declaration is not included in the new declaration though. - asASSERT( decl->objType->interfaces.GetLength() == decl->objType->interfaceVFTOffsets.GetLength() ); + asASSERT( ot->interfaces.GetLength() == ot->interfaceVFTOffsets.GetLength() ); } // Methods included from mixin classes should take precedence over inherited methods IncludeMethodsFromMixins(decl); // Add all properties and methods from the base class - if( !decl->isExistingShared && decl->objType->derivedFrom ) + if( !decl->isExistingShared && ot->derivedFrom ) { - asCObjectType *baseType = decl->objType->derivedFrom; + asCObjectType *baseType = ot->derivedFrom; // The derived class inherits all interfaces from the base class - for( unsigned int n = 0; n < baseType->interfaces.GetLength(); n++ ) + for( unsigned int m = 0; m < baseType->interfaces.GetLength(); m++ ) { - if( !decl->objType->Implements(baseType->interfaces[n]) ) - decl->objType->interfaces.PushLast(baseType->interfaces[n]); + if( !ot->Implements(baseType->interfaces[m]) ) + ot->interfaces.PushLast(baseType->interfaces[m]); } // TODO: Need to check for name conflict with new class methods @@ -2803,9 +2994,9 @@ void asCBuilder::CompileClasses(asUINT numTempl) asCScriptFunction *baseFunc = GetFunctionDescription(baseType->methods[m]); asCScriptFunction *derivedFunc = 0; bool found = false; - for( asUINT d = 0; d < decl->objType->methods.GetLength(); d++ ) + for( asUINT d = 0; d < ot->methods.GetLength(); d++ ) { - derivedFunc = GetFunctionDescription(decl->objType->methods[d]); + derivedFunc = GetFunctionDescription(ot->methods[d]); if( baseFunc->name == "opConv" || baseFunc->name == "opImplConv" || baseFunc->name == "opCast" || baseFunc->name == "opImplCast" ) { @@ -2821,8 +3012,8 @@ void asCBuilder::CompileClasses(asUINT numTempl) } // Move the function from the methods array to the virtualFunctionTable - decl->objType->methods.RemoveIndex(d); - decl->objType->virtualFunctionTable.PushLast(derivedFunc); + ot->methods.RemoveIndex(d); + ot->virtualFunctionTable.PushLast(derivedFunc); found = true; break; } @@ -2847,8 +3038,8 @@ void asCBuilder::CompileClasses(asUINT numTempl) } // Move the function from the methods array to the virtualFunctionTable - decl->objType->methods.RemoveIndex(d); - decl->objType->virtualFunctionTable.PushLast(derivedFunc); + ot->methods.RemoveIndex(d); + ot->virtualFunctionTable.PushLast(derivedFunc); found = true; break; } @@ -2858,13 +3049,13 @@ void asCBuilder::CompileClasses(asUINT numTempl) if( !found ) { // Push the base class function on the virtual function table - decl->objType->virtualFunctionTable.PushLast(baseType->virtualFunctionTable[m]); + ot->virtualFunctionTable.PushLast(baseType->virtualFunctionTable[m]); baseType->virtualFunctionTable[m]->AddRefInternal(); - CheckForConflictsDueToDefaultArgs(decl->script, decl->node, baseType->virtualFunctionTable[m], decl->objType); + CheckForConflictsDueToDefaultArgs(decl->script, decl->node, baseType->virtualFunctionTable[m], ot); } - decl->objType->methods.PushLast(baseType->methods[m]); + ot->methods.PushLast(baseType->methods[m]); engine->scriptFunctions[baseType->methods[m]]->AddRefInternal(); } } @@ -2872,30 +3063,30 @@ void asCBuilder::CompileClasses(asUINT numTempl) if( !decl->isExistingShared ) { // Move this class' methods into the virtual function table - for( asUINT m = 0; m < decl->objType->methods.GetLength(); m++ ) + for( asUINT m = 0; m < ot->methods.GetLength(); m++ ) { - asCScriptFunction *func = GetFunctionDescription(decl->objType->methods[m]); + asCScriptFunction *func = GetFunctionDescription(ot->methods[m]); if( func->funcType != asFUNC_VIRTUAL ) { // Move the reference from the method list to the virtual function list - decl->objType->methods.RemoveIndex(m); - decl->objType->virtualFunctionTable.PushLast(func); + ot->methods.RemoveIndex(m); + ot->virtualFunctionTable.PushLast(func); // Substitute the function description in the method list for a virtual method // Make sure the methods are in the same order as the virtual function table - decl->objType->methods.PushLast(CreateVirtualFunction(func, (int)decl->objType->virtualFunctionTable.GetLength() - 1)); + ot->methods.PushLast(CreateVirtualFunction(func, (int)ot->virtualFunctionTable.GetLength() - 1)); m--; } } // Make virtual function table chunks for each implemented interface - for( asUINT n = 0; n < decl->objType->interfaces.GetLength(); n++ ) + for( asUINT m = 0; m < ot->interfaces.GetLength(); m++ ) { - asCObjectType *intf = decl->objType->interfaces[n]; + asCObjectType *intf = ot->interfaces[m]; // Add all the interface's functions to the virtual function table - asUINT offset = asUINT(decl->objType->virtualFunctionTable.GetLength()); - decl->objType->interfaceVFTOffsets.PushLast(offset); + asUINT offset = asUINT(ot->virtualFunctionTable.GetLength()); + ot->interfaceVFTOffsets.PushLast(offset); for( asUINT j = 0; j < intf->methods.GetLength(); j++ ) { @@ -2910,15 +3101,15 @@ void asCBuilder::CompileClasses(asUINT numTempl) //Find the interface function in the list of methods asCScriptFunction *realFunc = 0; - for( asUINT p = 0; p < decl->objType->methods.GetLength(); p++ ) + for( asUINT p = 0; p < ot->methods.GetLength(); p++ ) { - asCScriptFunction *func = GetFunctionDescription(decl->objType->methods[p]); + asCScriptFunction *func = GetFunctionDescription(ot->methods[p]); if( func->signatureId == intfFunc->signatureId ) { if( func->funcType == asFUNC_VIRTUAL ) { - realFunc = decl->objType->virtualFunctionTable[func->vfTableIdx]; + realFunc = ot->virtualFunctionTable[func->vfTableIdx]; } else { @@ -2931,7 +3122,7 @@ void asCBuilder::CompileClasses(asUINT numTempl) // If realFunc is still null, the interface was not // implemented and we error out later in the checks. - decl->objType->virtualFunctionTable.PushLast(realFunc); + ot->virtualFunctionTable.PushLast(realFunc); if( realFunc ) realFunc->AddRefInternal(); } @@ -2945,82 +3136,77 @@ void asCBuilder::CompileClasses(asUINT numTempl) while( node && node->nodeType == snIdentifier ) node = node->next; - while( node ) + while( node && node->nodeType == snDeclaration ) { - if( node->nodeType == snDeclaration ) + asCScriptNode *nd = node->firstChild; + + // Is the property declared as private or protected? + bool isPrivate = false, isProtected = false; + if( nd && nd->tokenType == ttPrivate ) { - asCScriptNode *n = node->firstChild; - - // Is the property declared as private or protected? - bool isPrivate = false, isProtected = false; - if( n && n->tokenType == ttPrivate ) - { - isPrivate = true; - n = n->next; - } - else if( n && n->tokenType == ttProtected ) - { - isProtected = true; - n = n->next; - } - - // Determine the type of the property - asCScriptCode *file = decl->script; - asCDataType dt = CreateDataTypeFromNode(n, file, decl->objType->nameSpace); - if( decl->objType->IsShared() && dt.GetObjectType() && !dt.GetObjectType()->IsShared() ) - { - asCString msg; - msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetObjectType()->name.AddressOf()); - WriteError(msg, file, node); - } - - if( dt.IsReadOnly() ) - WriteError(TXT_PROPERTY_CANT_BE_CONST, file, node); - - // Multiple properties can be declared separated by , - n = n->next; - while( n ) - { - asCString name(&file->code[n->tokenPos], n->tokenLength); - - if( !decl->isExistingShared ) - { - CheckNameConflictMember(decl->objType, name.AddressOf(), n, file, true); - AddPropertyToClass(decl, name, dt, isPrivate, isProtected, false, file, n); - } - else - { - // Verify that the property exists in the original declaration - bool found = false; - for( asUINT p = 0; p < decl->objType->properties.GetLength(); p++ ) - { - asCObjectProperty *prop = decl->objType->properties[p]; - if( prop->isPrivate == isPrivate && - prop->isProtected == isProtected && - prop->name == name && - prop->type.IsEqualExceptRef(dt) ) - { - found = true; - break; - } - } - if( !found ) - { - asCString str; - str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->objType->GetName()); - WriteError(str, file, n); - } - } - - // Skip the initialization node - if( n->next && n->next->nodeType != snIdentifier ) - n = n->next; - - n = n->next; - } + isPrivate = true; + nd = nd->next; + } + else if( nd && nd->tokenType == ttProtected ) + { + isProtected = true; + nd = nd->next; + } + + // Determine the type of the property + asCScriptCode *file = decl->script; + asCDataType dt = CreateDataTypeFromNode(nd, file, ot->nameSpace, false, ot); + if( ot->IsShared() && dt.GetTypeInfo() && !dt.GetTypeInfo()->IsShared() ) + { + asCString msg; + msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetTypeInfo()->name.AddressOf()); + WriteError(msg, file, node); + } + + if( dt.IsReadOnly() ) + WriteError(TXT_PROPERTY_CANT_BE_CONST, file, node); + + // Multiple properties can be declared separated by , + nd = nd->next; + while( nd ) + { + asCString name(&file->code[nd->tokenPos], nd->tokenLength); + + if( !decl->isExistingShared ) + { + CheckNameConflictMember(ot, name.AddressOf(), nd, file, true); + AddPropertyToClass(decl, name, dt, isPrivate, isProtected, false, file, nd); + } + else + { + // Verify that the property exists in the original declaration + bool found = false; + for( asUINT p = 0; p < ot->properties.GetLength(); p++ ) + { + asCObjectProperty *prop = ot->properties[p]; + if( prop->isPrivate == isPrivate && + prop->isProtected == isProtected && + prop->name == name && + prop->type.IsEqualExceptRef(dt) ) + { + found = true; + break; + } + } + if( !found ) + { + asCString str; + str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName()); + WriteError(str, file, nd); + } + } + + // Skip the initialization node + if( nd->next && nd->next->nodeType != snIdentifier ) + nd = nd->next; + + nd = nd->next; } - else - asASSERT(false); node = node->next; } @@ -3031,7 +3217,7 @@ void asCBuilder::CompileClasses(asUINT numTempl) if( !decl->isExistingShared ) toValidate.PushLast(decl); - asASSERT( decl->objType->interfaces.GetLength() == decl->objType->interfaceVFTOffsets.GetLength() ); + asASSERT( ot->interfaces.GetLength() == ot->interfaceVFTOffsets.GetLength() ); } // TODO: Warn if a method overrides a base method without marking it as 'override'. @@ -3048,13 +3234,14 @@ void asCBuilder::CompileClasses(asUINT numTempl) sClassDeclaration *decl = classDeclarations[n]; if( decl->isExistingShared ) continue; - asCArray overrideValidations(decl->objType->GetMethodCount()); - for( asUINT k = 0; k < decl->objType->methods.GetLength(); k++ ) - overrideValidations.PushLast( !static_cast(decl->objType->GetMethodByIndex(k, false))->IsOverride() ); + asCObjectType *ot = CastToObjectType(decl->typeInfo); + asCArray overrideValidations(ot->GetMethodCount()); + for( asUINT k = 0; k < ot->methods.GetLength(); k++ ) + overrideValidations.PushLast( !static_cast(ot->GetMethodByIndex(k, false))->IsOverride() ); - for( asUINT m = 0; m < decl->objType->interfaces.GetLength(); m++ ) + for( asUINT m = 0; m < ot->interfaces.GetLength(); m++ ) { - asCObjectType *objType = decl->objType->interfaces[m]; + asCObjectType *objType = ot->interfaces[m]; for( asUINT i = 0; i < objType->methods.GetLength(); i++ ) { // Only check the interface methods that was explicitly declared in this interface @@ -3063,7 +3250,7 @@ void asCBuilder::CompileClasses(asUINT numTempl) continue; asUINT overrideIndex; - if( !DoesMethodExist(decl->objType, objType->methods[i], &overrideIndex) ) + if( !DoesMethodExist(ot, objType->methods[i], &overrideIndex) ) { asCString str; str.Format(TXT_MISSING_IMPLEMENTATION_OF_s, @@ -3075,14 +3262,14 @@ void asCBuilder::CompileClasses(asUINT numTempl) } } - bool hasBaseClass = decl->objType->derivedFrom != 0; + bool hasBaseClass = ot->derivedFrom != 0; for( asUINT j = 0; j < overrideValidations.GetLength(); j++ ) { - if( !overrideValidations[j] && (!hasBaseClass || !DoesMethodExist(decl->objType->derivedFrom, decl->objType->methods[j])) ) + if( !overrideValidations[j] && (!hasBaseClass || !DoesMethodExist(ot->derivedFrom, ot->methods[j])) ) { asCString msg; - msg.Format(TXT_METHOD_s_DOES_NOT_OVERRIDE, decl->objType->GetMethodByIndex(j, false)->GetDeclaration()); + msg.Format(TXT_METHOD_s_DOES_NOT_OVERRIDE, ot->GetMethodByIndex(j, false)->GetDeclaration()); WriteError(msg, decl->script, decl->node); } } @@ -3098,15 +3285,16 @@ void asCBuilder::CompileClasses(asUINT numTempl) while( toValidate.GetLength() > 0 ) { sClassDeclaration *decl = toValidate[toValidate.GetLength()-1]; + asCObjectType *ot = CastToObjectType(decl->typeInfo); int validState = 1; - for( asUINT n = 0; n < decl->objType->properties.GetLength(); n++ ) + for( n = 0; n < ot->properties.GetLength(); n++ ) { // A valid structure is one that uses only primitives or other valid objects - asCObjectProperty *prop = decl->objType->properties[n]; + asCObjectProperty *prop = ot->properties[n]; asCDataType dt = prop->type; // TODO: Add this check again, once solving the issues commented below - /* + /* if( dt.IsTemplate() ) { // TODO: This must verify all sub types, not just the first one @@ -3127,7 +3315,7 @@ void asCBuilder::CompileClasses(asUINT numTempl) sClassDeclaration *pdecl = 0; for( asUINT p = 0; p < classDeclarations.GetLength(); p++ ) { - if( classDeclarations[p]->objType == dt.GetObjectType() ) + if( classDeclarations[p]->typeInfo == dt.GetTypeInfo() ) { pdecl = classDeclarations[p]; break; @@ -3136,7 +3324,7 @@ void asCBuilder::CompileClasses(asUINT numTempl) if( pdecl ) { - if( pdecl->objType == decl->objType ) + if( pdecl->typeInfo == decl->typeInfo ) { WriteError(TXT_ILLEGAL_MEMBER_TYPE, decl->script, decl->node); validState = 2; @@ -3198,9 +3386,11 @@ void asCBuilder::CompileClasses(asUINT numTempl) // Existing shared classes won't need evaluating, nor interfaces sClassDeclaration *decl = classDeclarations[n]; if( decl->isExistingShared ) continue; - if( decl->objType->IsInterface() ) continue; - typesToValidate.PushLast(decl->objType); + asCObjectType *ot = CastToObjectType(decl->typeInfo); + if( ot->IsInterface() ) continue; + + typesToValidate.PushLast(ot); } asUINT numReevaluations = 0; @@ -3208,7 +3398,7 @@ void asCBuilder::CompileClasses(asUINT numTempl) { if( numReevaluations > typesToValidate.GetLength() ) { - // No types could be completely evaluated in the last iteration so + // No types could be completely evaluated in the last iteration so // we consider the remaining types in the array as garbage collected break; } @@ -3233,7 +3423,7 @@ void asCBuilder::CompileClasses(asUINT numTempl) // Evaluate template instances (silently) before verifying each of the classes, since it is possible that // a class will be marked as non-garbage collected, which in turn will mark the template instance that uses - // it as non-garbage collected, which in turn means the class that contains the array also do not have to be + // it as non-garbage collected, which in turn means the class that contains the array also do not have to be // garbage collected EvaluateTemplateInstances(numTempl, true); @@ -3244,10 +3434,28 @@ void asCBuilder::CompileClasses(asUINT numTempl) for( asUINT p = 0; p < type->properties.GetLength(); p++ ) { asCDataType dt = type->properties[p]->type; + + if (dt.IsFuncdef()) + { + // If a class holds a function pointer as member then the class must be garbage collected as the + // function pointer can form circular references with the class through use of a delegate. Example: + // + // class A { B @b; void f(); } + // class B { F @f; } + // funcdef void F(); + // + // A a; + // @a.b = B(); // instance of A refers to instance of B + // @a.b.f = F(a.f); // instance of B refers to delegate that refers to instance of A + // + gc = true; + break; + } + if( !dt.IsObject() ) continue; - if( typesToValidate.Exists(dt.GetObjectType()) ) + if( typesToValidate.Exists(CastToObjectType(dt.GetTypeInfo())) ) mustReevaluate = true; else { @@ -3255,9 +3463,9 @@ void asCBuilder::CompileClasses(asUINT numTempl) { // Check if any of the subtypes are yet to be evaluated bool skip = false; - for( asUINT s = 0; s < dt.GetObjectType()->GetSubTypeCount(); s++ ) + for( asUINT s = 0; s < dt.GetTypeInfo()->GetSubTypeCount(); s++ ) { - asCObjectType *t = reinterpret_cast(dt.GetObjectType()->GetSubType(s)); + asCObjectType *t = reinterpret_cast(dt.GetTypeInfo()->GetSubType(s)); if( typesToValidate.Exists(t) ) { mustReevaluate = true; @@ -3273,7 +3481,7 @@ void asCBuilder::CompileClasses(asUINT numTempl) { // If it is known that the handle can't be involved in a circular reference // then this object doesn't need to be marked as garbage collected. - asCObjectType *prop = dt.GetObjectType(); + asCObjectType *prop = CastToObjectType(dt.GetTypeInfo()); if( prop->flags & asOBJ_SCRIPT_OBJECT ) { @@ -3292,13 +3500,13 @@ void asCBuilder::CompileClasses(asUINT numTempl) if( sdt.IsObjectHandle() ) { // TODO: runtime optimize: If the handle is again to a final class, then we can recursively check if the circular reference can occur - if( sdt.GetObjectType()->flags & (asOBJ_SCRIPT_OBJECT | asOBJ_GC) ) + if( sdt.GetTypeInfo()->flags & (asOBJ_SCRIPT_OBJECT | asOBJ_GC) ) { gc = true; break; } } - else if( sdt.GetObjectType()->flags & asOBJ_GC ) + else if( sdt.GetTypeInfo()->flags & asOBJ_GC ) { // TODO: runtime optimize: Just because the member type is a potential circle doesn't mean that this one is. // Only if the object is of a type that can reference this type, either directly or indirectly @@ -3321,14 +3529,14 @@ void asCBuilder::CompileClasses(asUINT numTempl) else if( prop->flags & asOBJ_GC ) { // If a type is not a script object, adopt its GC flag - // TODO: runtime optimize: Just because an application registered class is garbage collected, doesn't mean it + // TODO: runtime optimize: Just because an application registered class is garbage collected, doesn't mean it // can form a circular reference with this script class. Perhaps need a flag to tell // if the script classes that contains the type should be garbage collected or not. gc = true; break; } } - else if( dt.GetObjectType()->flags & asOBJ_GC ) + else if( dt.GetTypeInfo()->flags & asOBJ_GC ) { // TODO: runtime optimize: Just because the member type is a potential circle doesn't mean that this one is. // Only if the object is of a type that can reference this type, either directly or indirectly @@ -3338,8 +3546,8 @@ void asCBuilder::CompileClasses(asUINT numTempl) } } - // If the class wasn't found to require garbage collection, but it - // contains another type that has yet to be evaluated then it must be + // If the class wasn't found to require garbage collection, but it + // contains another type that has yet to be evaluated then it must be // re-evaluated. if( !gc && mustReevaluate ) { @@ -3376,7 +3584,7 @@ void asCBuilder::IncludeMethodsFromMixins(sClassDeclaration *decl) { asSNameSpace *ns; asCString name; - if( GetNamespaceAndNameFromNode(node, decl->script, decl->objType->nameSpace, ns, name) < 0 ) + if( GetNamespaceAndNameFromNode(node, decl->script, decl->typeInfo->nameSpace, ns, name) < 0 ) { node = node->next; continue; @@ -3385,11 +3593,11 @@ void asCBuilder::IncludeMethodsFromMixins(sClassDeclaration *decl) sMixinClass *mixin = 0; while( ns ) { - // Need to make sure the name is not an object type + // Need to make sure the name is not an object type asCObjectType *objType = GetObjectType(name.AddressOf(), ns); if( objType == 0 ) mixin = GetMixinClass(name.AddressOf(), ns); - + if( objType || mixin ) break; @@ -3416,7 +3624,7 @@ void asCBuilder::IncludeMethodsFromMixins(sClassDeclaration *decl) asCScriptNode *copy = n->CreateCopy(engine); // Register the method, but only if it doesn't already exist in the class - RegisterScriptFunctionFromNode(copy, mixin->script, decl->objType, false, false, mixin->ns, false, true); + RegisterScriptFunctionFromNode(copy, mixin->script, CastToObjectType(decl->typeInfo), false, false, mixin->ns, false, true); } else if( n->nodeType == snVirtualProperty ) { @@ -3450,7 +3658,7 @@ void asCBuilder::IncludePropertiesFromMixins(sClassDeclaration *decl) { asSNameSpace *ns; asCString name; - if( GetNamespaceAndNameFromNode(node, decl->script, decl->objType->nameSpace, ns, name) < 0 ) + if( GetNamespaceAndNameFromNode(node, decl->script, decl->typeInfo->nameSpace, ns, name) < 0 ) { node = node->next; continue; @@ -3459,11 +3667,11 @@ void asCBuilder::IncludePropertiesFromMixins(sClassDeclaration *decl) sMixinClass *mixin = 0; while( ns ) { - // Need to make sure the name is not an object type + // Need to make sure the name is not an object type asCObjectType *objType = GetObjectType(name.AddressOf(), ns); if( objType == 0 ) mixin = GetMixinClass(name.AddressOf(), ns); - + if( objType || mixin ) break; @@ -3501,10 +3709,10 @@ void asCBuilder::IncludePropertiesFromMixins(sClassDeclaration *decl) asCScriptCode *file = mixin->script; asCDataType dt = CreateDataTypeFromNode(n2, file, mixin->ns); - if( decl->objType->IsShared() && dt.GetObjectType() && !dt.GetObjectType()->IsShared() ) + if( decl->typeInfo->IsShared() && dt.GetTypeInfo() && !dt.GetTypeInfo()->IsShared() ) { asCString msg; - msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetObjectType()->name.AddressOf()); + msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetTypeInfo()->name.AddressOf()); WriteError(msg, file, n); WriteInfo(TXT_WHILE_INCLUDING_MIXIN, decl->script, node); } @@ -3515,12 +3723,13 @@ void asCBuilder::IncludePropertiesFromMixins(sClassDeclaration *decl) n2 = n2->next; while( n2 ) { - asCString name(&file->code[n2->tokenPos], n2->tokenLength); + name.Assign(&file->code[n2->tokenPos], n2->tokenLength); // Add the property only if it doesn't already exist in the class bool exists = false; - for( asUINT p = 0; p < decl->objType->properties.GetLength(); p++ ) - if( decl->objType->properties[p]->name == name ) + asCObjectType *ot = CastToObjectType(decl->typeInfo); + for( asUINT p = 0; p < ot->properties.GetLength(); p++ ) + if( ot->properties[p]->name == name ) { exists = true; break; @@ -3531,7 +3740,7 @@ void asCBuilder::IncludePropertiesFromMixins(sClassDeclaration *decl) if( !decl->isExistingShared ) { // It must not conflict with the name of methods - int r = CheckNameConflictMember(decl->objType, name.AddressOf(), n2, file, true); + int r = CheckNameConflictMember(ot, name.AddressOf(), n2, file, true); if( r < 0 ) WriteInfo(TXT_WHILE_INCLUDING_MIXIN, decl->script, node); @@ -3541,9 +3750,9 @@ void asCBuilder::IncludePropertiesFromMixins(sClassDeclaration *decl) { // Verify that the property exists in the original declaration bool found = false; - for( asUINT p = 0; p < decl->objType->properties.GetLength(); p++ ) + for( asUINT p = 0; p < ot->properties.GetLength(); p++ ) { - asCObjectProperty *prop = decl->objType->properties[p]; + asCObjectProperty *prop = ot->properties[p]; if( prop->isPrivate == isPrivate && prop->isProtected == isProtected && prop->name == name && @@ -3556,7 +3765,7 @@ void asCBuilder::IncludePropertiesFromMixins(sClassDeclaration *decl) if( !found ) { asCString str; - str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->objType->GetName()); + str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName()); WriteError(str, decl->script, decl->node); WriteInfo(TXT_WHILE_INCLUDING_MIXIN, decl->script, node); } @@ -3590,15 +3799,14 @@ int asCBuilder::CreateVirtualFunction(asCScriptFunction *func, int idx) vf->parameterTypes = func->parameterTypes; vf->inOutFlags = func->inOutFlags; vf->id = engine->GetNextScriptFunctionId(); - vf->isReadOnly = func->isReadOnly; vf->objectType = func->objectType; vf->objectType->AddRefInternal(); vf->signatureId = func->signatureId; - vf->isPrivate = func->isPrivate; - vf->isProtected = func->isProtected; - vf->isFinal = func->isFinal; - vf->isOverride = func->isOverride; vf->vfTableIdx = idx; + vf->traits = func->traits; + + // Clear the shared trait since the virtual function should not have that + vf->SetShared(false); // It is not necessary to copy the default args, as they have no meaning in the virtual function @@ -3623,12 +3831,12 @@ asCObjectProperty *asCBuilder::AddPropertyToClass(sClassDeclaration *decl, const { asCString str; if( dt.IsAbstractClass() ) - str.Format(TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED, dt.Format(decl->objType->nameSpace).AddressOf()); + str.Format(TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED, dt.Format(decl->typeInfo->nameSpace).AddressOf()); else if( dt.IsInterface() ) - str.Format(TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED, dt.Format(decl->objType->nameSpace).AddressOf()); + str.Format(TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED, dt.Format(decl->typeInfo->nameSpace).AddressOf()); else // TODO: Improve error message to explain why - str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format(decl->objType->nameSpace).AddressOf()); + str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format(decl->typeInfo->nameSpace).AddressOf()); WriteError(str, file, node); } return 0; @@ -3654,7 +3862,7 @@ asCObjectProperty *asCBuilder::AddPropertyToClass(sClassDeclaration *decl, const } // Add the property to the object type - return decl->objType->AddPropertyToClass(name, dt, isPrivate, isProtected, isInherited); + return CastToObjectType(decl->typeInfo)->AddPropertyToClass(name, dt, isPrivate, isProtected, isInherited); } bool asCBuilder::DoesMethodExist(asCObjectType *objType, int methodId, asUINT *methodIndex) @@ -3667,7 +3875,7 @@ bool asCBuilder::DoesMethodExist(asCObjectType *objType, int methodId, asUINT *m if( m->name != method->name ) continue; if( m->returnType != method->returnType ) continue; - if( m->isReadOnly != method->isReadOnly ) continue; + if( m->IsReadOnly() != method->IsReadOnly() ) continue; if( m->parameterTypes != method->parameterTypes ) continue; if( m->inOutFlags != method->inOutFlags ) continue; @@ -3692,7 +3900,7 @@ void asCBuilder::AddDefaultConstructor(asCObjectType *objType, asCScriptCode *fi // Add the script function // TODO: declaredAt should be set to where the class has been declared - module->AddScriptFunction(file->idx, 0, funcId, objType->name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, false, objType); + module->AddScriptFunction(file->idx, 0, funcId, objType->name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, false, objType, false, asSFunctionTraits(), objType->nameSpace); // Set it as default constructor if( objType->beh.construct ) @@ -3735,18 +3943,24 @@ void asCBuilder::AddDefaultConstructor(asCObjectType *objType, asCScriptCode *fi // If the object is shared, then the factory must also be marked as shared if( objType->flags & asOBJ_SHARED ) - engine->scriptFunctions[funcId]->isShared = true; + engine->scriptFunctions[funcId]->SetShared(true); } int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns) { // Is it a shared enum? bool isShared = false; - asCObjectType *existingSharedType = 0; + bool isExternal = false; + asCEnumType *existingSharedType = 0; asCScriptNode *tmp = node->firstChild; - if( tmp->nodeType == snIdentifier && file->TokenEquals(tmp->tokenPos, tmp->tokenLength, SHARED_TOKEN) ) + while( tmp->nodeType == snIdentifier ) { - isShared = true; + if (file->TokenEquals(tmp->tokenPos, tmp->tokenLength, SHARED_TOKEN)) + isShared = true; + else if (file->TokenEquals(tmp->tokenPos, tmp->tokenLength, EXTERNAL_TOKEN)) + isExternal = true; + else + break; tmp = tmp->next; } @@ -3761,24 +3975,36 @@ int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSp // Look for a pre-existing shared enum with the same signature for( asUINT n = 0; n < engine->sharedScriptTypes.GetLength(); n++ ) { - asCObjectType *o = engine->sharedScriptTypes[n]; + asCTypeInfo *o = engine->sharedScriptTypes[n]; if( o && o->IsShared() && (o->flags & asOBJ_ENUM) && o->name == name && o->nameSpace == ns ) { - existingSharedType = o; + existingSharedType = CastToEnumType(o); break; } } } + // If the enum was declared as external then it must have been compiled in a different module first + if (isExternal && existingSharedType == 0) + { + asCString str; + str.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, name.AddressOf()); + WriteError(str, file, tmp); + } + + // Remember if the type was declared as external so the saved bytecode can be flagged accordingly + if (isExternal && existingSharedType) + module->externalTypes.PushLast(existingSharedType); + // Check the name and add the enum int r = CheckNameConflict(name.AddressOf(), tmp->firstChild, file, ns); if( asSUCCESS == r ) { - asCObjectType *st; + asCEnumType *st; if( existingSharedType ) { @@ -3787,7 +4013,7 @@ int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSp } else { - st = asNEW(asCObjectType)(engine); + st = asNEW(asCEnumType)(engine); if( st == 0 ) return asOUT_OF_MEMORY; @@ -3814,19 +4040,31 @@ int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSp decl->name = name; decl->script = file; - decl->objType = st; + decl->typeInfo = st; namedTypeDeclarations.PushLast(decl); asCDataType type = CreateDataTypeFromNode(tmp, file, ns); asASSERT(!type.IsReference()); + // External shared enums must not redeclare the enum values + if (isExternal && (tmp->next == 0 || tmp->next->tokenType != ttEndStatement) ) + { + asCString str; + str.Format(TXT_EXTERNAL_SHARED_s_CANNOT_REDEF, name.AddressOf()); + WriteError(str, file, tmp); + } + else if (!isExternal && tmp->next && tmp->next->tokenType == ttEndStatement) + { + asCString str; + str.Format(TXT_MISSING_DEFINITION_OF_s, name.AddressOf()); + WriteError(str, file, tmp); + } + // Register the enum values tmp = tmp->next; - while( tmp ) + while( tmp && tmp->nodeType == snIdentifier ) { - asASSERT(snIdentifier == tmp->nodeType); - - asCString name(&file->code[tmp->tokenPos], tmp->tokenLength); + name.Assign(&file->code[tmp->tokenPos], tmp->tokenLength); if( existingSharedType ) { @@ -3890,7 +4128,7 @@ int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSp gvar->ns = ns; // No need to allocate space on the global memory stack since the values are stored in the asCObjectType // Set the index to a negative to allow compiler to diferentiate from ordinary global var when compiling the initialization - gvar->index = -1; + gvar->index = -1; gvar->isCompiled = false; gvar->isPureConstant = true; gvar->isEnumValue = true; @@ -3935,11 +4173,11 @@ int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNam // If the name is not already in use add it int r = CheckNameConflict(name.AddressOf(), tmp, file, ns); - asCObjectType *st = 0; + asCTypedefType *st = 0; if( asSUCCESS == r ) { // Create the new type - st = asNEW(asCObjectType)(engine); + st = asNEW(asCTypedefType)(engine); if( st == 0 ) r = asOUT_OF_MEMORY; } @@ -3950,7 +4188,7 @@ int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNam st->size = dataType.GetSizeInMemoryBytes(); st->name = name; st->nameSpace = ns; - st->templateSubTypes.PushLast(dataType); + st->aliasForType = dataType; st->module = module; module->typeDefs.PushLast(st); @@ -3963,7 +4201,7 @@ int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNam { decl->name = name; decl->script = file; - decl->objType = st; + decl->typeInfo = st; namedTypeDeclarations.PushLast(decl); } } @@ -3973,34 +4211,41 @@ int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNam return r; } -void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray ¶meterNames, asCArray ¶meterTypes, asCArray &inOutFlags, asCArray &defaultArgs, bool &isConstMethod, bool &isConstructor, bool &isDestructor, bool &isPrivate, bool &isProtected, bool &isOverride, bool &isFinal, bool &isShared, asSNameSpace *implicitNamespace) +void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray ¶meterNames, asCArray ¶meterTypes, asCArray &inOutFlags, asCArray &defaultArgs, asSFunctionTraits &funcTraits, asSNameSpace *implicitNamespace) { node = node->firstChild; + // Is the function shared? + funcTraits.SetTrait(asTRAIT_SHARED, false); + funcTraits.SetTrait(asTRAIT_EXTERNAL, false); + while (node->tokenType == ttIdentifier) + { + if (file->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN)) + funcTraits.SetTrait(asTRAIT_SHARED, true); + else if (file->TokenEquals(node->tokenPos, node->tokenLength, EXTERNAL_TOKEN)) + funcTraits.SetTrait(asTRAIT_EXTERNAL, true); + else + break; + node = node->next; + } + // Is the function a private or protected class method? - isPrivate = false, isProtected = false; + funcTraits.SetTrait(asTRAIT_PRIVATE, false); + funcTraits.SetTrait(asTRAIT_PROTECTED, false); if( node->tokenType == ttPrivate ) { - isPrivate = true; + funcTraits.SetTrait(asTRAIT_PRIVATE, true); node = node->next; } else if( node->tokenType == ttProtected ) { - isProtected = true; - node = node->next; - } - - // Is the function shared? - isShared = false; - if( node->tokenType == ttIdentifier && file->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN) ) - { - isShared = true; + funcTraits.SetTrait(asTRAIT_PROTECTED, true); node = node->next; } // Find the name - isConstructor = false; - isDestructor = false; + funcTraits.SetTrait(asTRAIT_CONSTRUCTOR, false); + funcTraits.SetTrait(asTRAIT_DESTRUCTOR, false); asCScriptNode *n = 0; if( node->nodeType == snDataType ) n = node->next->next; @@ -4010,27 +4255,26 @@ void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *fi if( node->tokenType == ttBitNot ) { n = node->next; - isDestructor = true; + funcTraits.SetTrait(asTRAIT_DESTRUCTOR, true); } else { n = node; - isConstructor = true; + funcTraits.SetTrait(asTRAIT_CONSTRUCTOR, true); } } name.Assign(&file->code[n->tokenPos], n->tokenLength); - // Initialize a script function object for registration - if( !isConstructor && !isDestructor ) + if( !funcTraits.GetTrait(asTRAIT_CONSTRUCTOR) && !funcTraits.GetTrait(asTRAIT_DESTRUCTOR) ) { - returnType = CreateDataTypeFromNode(node, file, implicitNamespace); + returnType = CreateDataTypeFromNode(node, file, implicitNamespace, false, objType); returnType = ModifyDataTypeFromNode(returnType, node->next, file, 0, 0); if( engine->ep.disallowValueAssignForRefType && - returnType.GetObjectType() && - (returnType.GetObjectType()->flags & asOBJ_REF) && - !(returnType.GetObjectType()->flags & asOBJ_SCOPED) && - !returnType.IsReference() && + returnType.GetTypeInfo() && + (returnType.GetTypeInfo()->flags & asOBJ_REF) && + !(returnType.GetTypeInfo()->flags & asOBJ_SCOPED) && + !returnType.IsReference() && !returnType.IsObjectHandle() ) { WriteError(TXT_REF_TYPE_CANT_BE_RETURNED_BY_VAL, file, node); @@ -4039,9 +4283,9 @@ void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *fi else returnType = asCDataType::CreatePrimitive(ttVoid, false); - isConstMethod = false; - isFinal = false; - isOverride = false; + funcTraits.SetTrait(asTRAIT_CONST, false); + funcTraits.SetTrait(asTRAIT_FINAL, false); + funcTraits.SetTrait(asTRAIT_OVERRIDE, false); if( objType && n->next->next ) { @@ -4050,16 +4294,16 @@ void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *fi // Is this a const method? if( decorator->tokenType == ttConst ) { - isConstMethod = true; + funcTraits.SetTrait(asTRAIT_CONST, true); decorator = decorator->next; } while( decorator ) { if( decorator->tokenType == ttIdentifier && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, FINAL_TOKEN) ) - isFinal = true; + funcTraits.SetTrait(asTRAIT_FINAL, true); else if( decorator->tokenType == ttIdentifier && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, OVERRIDE_TOKEN) ) - isOverride = true; + funcTraits.SetTrait(asTRAIT_OVERRIDE, true); decorator = decorator->next; } @@ -4087,14 +4331,14 @@ void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *fi while( n ) { asETypeModifiers inOutFlag; - asCDataType type = CreateDataTypeFromNode(n, file, implicitNamespace); + asCDataType type = CreateDataTypeFromNode(n, file, implicitNamespace, false, objType); type = ModifyDataTypeFromNode(type, n->next, file, &inOutFlag, 0); if( engine->ep.disallowValueAssignForRefType && - type.GetObjectType() && - (type.GetObjectType()->flags & asOBJ_REF) && - !(type.GetObjectType()->flags & asOBJ_SCOPED) && - !type.IsReference() && + type.GetTypeInfo() && + (type.GetTypeInfo()->flags & asOBJ_REF) && + !(type.GetTypeInfo()->flags & asOBJ_SCOPED) && + !type.IsReference() && !type.IsObjectHandle() ) { WriteError(TXT_REF_TYPE_CANT_BE_PASSED_BY_VAL, file, node); @@ -4108,9 +4352,8 @@ void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *fi n = n->next->next; if( n && n->nodeType == snIdentifier ) { - asCString name; - name.Assign(&file->code[n->tokenPos], n->tokenLength); - parameterNames.PushLast(name); + asCString paramName(&file->code[n->tokenPos], n->tokenLength); + parameterNames.PushLast(paramName); n = n->next; } else @@ -4167,14 +4410,7 @@ int asCBuilder::RegisterScriptFunctionFromNode(asCScriptNode *node, asCScriptCod asCArray parameterTypes; asCArray inOutFlags; asCArray defaultArgs; - bool isConstMethod; - bool isOverride; - bool isFinal; - bool isConstructor; - bool isDestructor; - bool isPrivate; - bool isProtected; - bool isShared; + asSFunctionTraits funcTraits; asASSERT( (objType && ns == 0) || isGlobalFunction || isMixin ); @@ -4187,9 +4423,9 @@ int asCBuilder::RegisterScriptFunctionFromNode(asCScriptNode *node, asCScriptCod ns = engine->nameSpaces[0]; } - GetParsedFunctionDetails(node, file, objType, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared, ns); + GetParsedFunctionDetails(node, file, objType, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, funcTraits, ns); - return RegisterScriptFunction(node, file, objType, isInterface, isGlobalFunction, ns, isExistingShared, isMixin, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared); + return RegisterScriptFunction(node, file, objType, isInterface, isGlobalFunction, ns, isExistingShared, isMixin, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, funcTraits); } asCScriptFunction *asCBuilder::RegisterLambda(asCScriptNode *node, asCScriptCode *file, asCScriptFunction *funcDef, const asCString &name, asSNameSpace *ns) @@ -4212,7 +4448,7 @@ asCScriptFunction *asCBuilder::RegisterLambda(asCScriptNode *node, asCScriptCode // Get the return and parameter types from the funcDef asCString funcName = name; - int r = RegisterScriptFunction(args, file, 0, 0, true, ns, false, false, funcName, funcDef->returnType, parameterNames, funcDef->parameterTypes, funcDef->inOutFlags, defaultArgs, false, false, false, false, false, false, false, false); + int r = RegisterScriptFunction(args, file, 0, 0, true, ns, false, false, funcName, funcDef->returnType, parameterNames, funcDef->parameterTypes, funcDef->inOutFlags, defaultArgs, asSFunctionTraits()); if( r < 0 ) return 0; @@ -4220,7 +4456,7 @@ asCScriptFunction *asCBuilder::RegisterLambda(asCScriptNode *node, asCScriptCode return engine->scriptFunctions[functions[functions.GetLength()-1]->funcId]; } -int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray ¶meterNames, asCArray ¶meterTypes, asCArray &inOutFlags, asCArray &defaultArgs, bool isConstMethod, bool isConstructor, bool isDestructor, bool isPrivate, bool isProtected, bool isOverride, bool isFinal, bool isShared) +int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray ¶meterNames, asCArray ¶meterTypes, asCArray &inOutFlags, asCArray &defaultArgs, asSFunctionTraits funcTraits) { // Determine default namespace if not specified if( ns == 0 ) @@ -4237,7 +4473,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, // Should validate that the function really exists in the class/interface bool found = false; - if( isConstructor || isDestructor ) + if(funcTraits.GetTrait(asTRAIT_CONSTRUCTOR) || funcTraits.GetTrait(asTRAIT_DESTRUCTOR) ) { // TODO: shared: Should check the existance of these too found = true; @@ -4248,7 +4484,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, { asCScriptFunction *func = engine->scriptFunctions[objType->methods[n]]; if( func->name == name && - func->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, objType, isConstMethod) ) + func->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, objType, funcTraits.GetTrait(asTRAIT_CONST)) ) { // Add the shared function in this module too module->AddScriptFunction(func); @@ -4276,7 +4512,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, } // Check for name conflicts - if( !isConstructor && !isDestructor ) + if( !funcTraits.GetTrait(asTRAIT_CONSTRUCTOR) && !funcTraits.GetTrait(asTRAIT_DESTRUCTOR) ) { if( objType ) { @@ -4308,14 +4544,14 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, if( name != objType->name ) { asCString str; - if( isDestructor ) + if(funcTraits.GetTrait(asTRAIT_DESTRUCTOR) ) str.Format(TXT_DESTRUCTOR_s_s_NAME_ERROR, objType->name.AddressOf(), name.AddressOf()); else str.Format(TXT_METHOD_s_s_HAS_NO_RETURN_TYPE, objType->name.AddressOf(), name.AddressOf()); WriteError(str, file, node); } - if( isDestructor ) + if(funcTraits.GetTrait(asTRAIT_DESTRUCTOR)) name = "~" + name; } @@ -4344,14 +4580,14 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, func->isExistingShared = false; func->paramNames = parameterNames; - if( isShared ) + if(funcTraits.GetTrait(asTRAIT_SHARED)) { // Look for a pre-existing shared function with the same signature for( asUINT n = 0; n < engine->scriptFunctions.GetLength(); n++ ) { asCScriptFunction *f = engine->scriptFunctions[n]; if( f && - f->isShared && + f->IsShared() && f->name == name && f->nameSpace == ns && f->objectType == objType && @@ -4363,30 +4599,58 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, } } } + + // Remember if the function was declared as external so the saved bytecode can be flagged accordingly + if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && func->isExistingShared) + module->externalFunctions.PushLast(engine->scriptFunctions[func->funcId]); + + if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && !func->isExistingShared) + { + // Mark it as existing shared to avoid compiling it + func->isExistingShared = true; + + asCString str; + str.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, name.AddressOf()); + WriteError(str, file, node); + } + + // External shared function must not try to redefine the interface + if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && !(node->tokenType == ttEndStatement || node->lastChild->tokenType == ttEndStatement)) + { + asCString str; + str.Format(TXT_EXTERNAL_SHARED_s_CANNOT_REDEF, name.AddressOf()); + WriteError(str, file, node); + } + else if (!funcTraits.GetTrait(asTRAIT_EXTERNAL) && !(node->nodeType == snStatementBlock || node->lastChild->nodeType == snStatementBlock) ) + { + asCString str; + str.Format(TXT_MISSING_DEFINITION_OF_s, name.AddressOf()); + WriteError(str, file, node); + } } // Destructors may not have any parameters - if( isDestructor && parameterTypes.GetLength() > 0 ) + if (funcTraits.GetTrait(asTRAIT_DESTRUCTOR) && parameterTypes.GetLength() > 0) WriteError(TXT_DESTRUCTOR_MAY_NOT_HAVE_PARM, file, node); // If a function, class, or interface is shared then only shared types may be used in the signature - if( (objType && objType->IsShared()) || isShared ) + if( (objType && objType->IsShared()) || funcTraits.GetTrait(asTRAIT_SHARED)) { - asCObjectType *ot = returnType.GetObjectType(); - if( ot && !ot->IsShared() ) + asCTypeInfo *ti = returnType.GetTypeInfo(); + if( ti && !ti->IsShared() ) { asCString msg; - msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ot->name.AddressOf()); + msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ti->name.AddressOf()); WriteError(msg, file, node); } for( asUINT p = 0; p < parameterTypes.GetLength(); ++p ) { - asCObjectType *ot = parameterTypes[p].GetObjectType(); - if( ot && !ot->IsShared() ) + ti = parameterTypes[p].GetTypeInfo(); + if( ti && !ti->IsShared() ) { asCString msg; - msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ot->name.AddressOf()); + msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ti->name.AddressOf()); WriteError(msg, file, node); } } @@ -4404,7 +4668,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, for( asUINT n = 0; n < funcs.GetLength(); ++n ) { asCScriptFunction *func = GetFunctionDescription(funcs[n]); - if( func->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, objType, isConstMethod) ) + if( func->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, objType, funcTraits.GetTrait(asTRAIT_CONST)) ) { // TODO: clean up: Reuse the same error handling for both opConv and normal methods if( isMixin ) @@ -4412,11 +4676,11 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, // Clean up the memory, as the function will not be registered if( node ) node->Destroy(engine); - sFunctionDescription *func = functions.PopLast(); - asDELETE(func, sFunctionDescription); + sFunctionDescription *funcDesc = functions.PopLast(); + asDELETE(funcDesc, sFunctionDescription); // Free the default args - for( asUINT n = 0; n < defaultArgs.GetLength(); n++ ) + for( n = 0; n < defaultArgs.GetLength(); n++ ) if( defaultArgs[n] ) asDELETE(defaultArgs[n], asCString); @@ -4433,18 +4697,18 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, for( asUINT n = 0; n < funcs.GetLength(); ++n ) { asCScriptFunction *func = GetFunctionDescription(funcs[n]); - if( func->IsSignatureExceptNameAndReturnTypeEqual(parameterTypes, inOutFlags, objType, isConstMethod) ) + if( func->IsSignatureExceptNameAndReturnTypeEqual(parameterTypes, inOutFlags, objType, funcTraits.GetTrait(asTRAIT_CONST)) ) { if( isMixin ) { // Clean up the memory, as the function will not be registered if( node ) node->Destroy(engine); - sFunctionDescription *func = functions.PopLast(); - asDELETE(func, sFunctionDescription); + sFunctionDescription *funcDesc = functions.PopLast(); + asDELETE(funcDesc, sFunctionDescription); // Free the default args - for( asUINT n = 0; n < defaultArgs.GetLength(); n++ ) + for( n = 0; n < defaultArgs.GetLength(); n++ ) if( defaultArgs[n] ) asDELETE(defaultArgs[n], asCString); @@ -4476,7 +4740,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, int row = 0, col = 0; if( node ) file->ConvertPosToRowCol(node->tokenPos, &row, &col); - module->AddScriptFunction(file->idx, (row&0xFFFFF)|((col&0xFFF)<<20), funcId, name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, isInterface, objType, isConstMethod, isGlobalFunction, isPrivate, isProtected, isFinal, isOverride, isShared, ns); + module->AddScriptFunction(file->idx, (row&0xFFFFF)|((col&0xFFF)<<20), funcId, name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, isInterface, objType, isGlobalFunction, funcTraits, ns); } // Make sure the default args are declared correctly @@ -4488,7 +4752,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asASSERT( !isExistingShared ); engine->scriptFunctions[funcId]->AddRefInternal(); - if( isConstructor ) + if(funcTraits.GetTrait(asTRAIT_CONSTRUCTOR)) { int factoryId = engine->GetNextScriptFunctionId(); if( parameterTypes.GetLength() == 0 ) @@ -4521,7 +4785,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, // If the object is shared, then the factory must also be marked as shared if( objType->flags & asOBJ_SHARED ) - engine->scriptFunctions[factoryId]->isShared = true; + engine->scriptFunctions[factoryId]->SetShared(true); // Add a dummy function to the builder so that it doesn't mix up the fund Ids functions.PushLast(0); @@ -4531,14 +4795,14 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, compiler.CompileFactory(this, file, engine->scriptFunctions[factoryId]); engine->scriptFunctions[factoryId]->AddRefInternal(); } - else if( isDestructor ) + else if(funcTraits.GetTrait(asTRAIT_DESTRUCTOR)) objType->beh.destruct = funcId; else { // If the method is the assignment operator we need to replace the default implementation asCScriptFunction *f = engine->scriptFunctions[funcId]; if( f->name == "opAssign" && f->parameterTypes.GetLength() == 1 && - f->parameterTypes[0].GetObjectType() == f->objectType && + f->parameterTypes[0].GetTypeInfo() == f->objectType && (f->inOutFlags[0] & asTM_INREF) ) { engine->scriptFunctions[objType->beh.copy]->ReleaseInternal(); @@ -4603,14 +4867,12 @@ int asCBuilder::RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file WriteError(TXT_PROPERTY_WITHOUT_ACCESSOR, file, node); node = node->next; - while( node ) + while (node) { - asCScriptNode *next = node->next; - asCScriptNode *funcNode = 0; - bool success = false; - bool isConst = false; - bool isFinal = false; - bool isOverride = false; + asCScriptNode *next = node->next; + asCScriptNode *funcNode = 0; + bool success = false; + asSFunctionTraits funcTraits; asCDataType returnType; asCArray paramNames; asCArray paramTypes; @@ -4618,33 +4880,44 @@ int asCBuilder::RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file asCArray defaultArgs; asCString name; + funcTraits.SetTrait(asTRAIT_PRIVATE, isPrivate); + funcTraits.SetTrait(asTRAIT_PROTECTED, isProtected); + // TODO: getset: Allow private for individual property accessors // TODO: getset: If the accessor uses its own name, then the property should be automatically declared - if( node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, GET_TOKEN) ) + if (node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, GET_TOKEN)) + name = "get_"; + else if (node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, SET_TOKEN)) + name = "set_"; + else + WriteError(TXT_UNRECOGNIZED_VIRTUAL_PROPERTY_NODE, file, node); + + if (name != "") { - funcNode = node->firstChild->next; + success = true; + funcNode = node->firstChild->next; - if( funcNode && funcNode->tokenType == ttConst ) + if (funcNode && funcNode->tokenType == ttConst) { - isConst = true; + funcTraits.SetTrait(asTRAIT_CONST, true); funcNode = funcNode->next; } - while( funcNode && funcNode->nodeType != snStatementBlock ) + while (funcNode && funcNode->nodeType != snStatementBlock) { - if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN) ) - isFinal = true; - else if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN) ) - isOverride = true; + if (funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN)) + funcTraits.SetTrait(asTRAIT_FINAL, true); + else if (funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN)) + funcTraits.SetTrait(asTRAIT_OVERRIDE, true); funcNode = funcNode->next; } - if( funcNode ) + if (funcNode) funcNode->DisconnectParent(); - if( funcNode == 0 && (objType == 0 || !objType->IsInterface()) ) + if (funcNode == 0 && (objType == 0 || !objType->IsInterface())) { // TODO: getset: If no implementation is supplied the builder should provide an automatically generated implementation // The compiler needs to be able to handle the different types, primitive, value type, and handle @@ -4652,53 +4925,28 @@ int asCBuilder::RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file WriteError(TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED, file, node); } - // Setup the signature for the get accessor method - returnType = emulatedType; - name = "get_" + emulatedName; - success = true; - } - else if( node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, SET_TOKEN) ) - { - funcNode = node->firstChild->next; - - if( funcNode && funcNode->tokenType == ttConst ) + if (name == "get_") { - isConst = true; - funcNode = funcNode->next; + // Setup the signature for the get accessor method + returnType = emulatedType; + name = "get_" + emulatedName; } - - while( funcNode && funcNode->nodeType != snStatementBlock ) + else if (name == "set_") { - if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN) ) - isFinal = true; - else if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN) ) - isOverride = true; - - funcNode = funcNode->next; + // Setup the signature for the set accessor method + returnType = asCDataType::CreatePrimitive(ttVoid, false); + paramModifiers.PushLast(asTM_NONE); + paramNames.PushLast("value"); + paramTypes.PushLast(emulatedType); + defaultArgs.PushLast(0); + name = "set_" + emulatedName; } - - if( funcNode ) - funcNode->DisconnectParent(); - - if( funcNode == 0 && (objType == 0 || !objType->IsInterface()) ) - WriteError(TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED, file, node); - - // Setup the signature for the set accessor method - returnType = asCDataType::CreatePrimitive(ttVoid, false); - paramModifiers.PushLast(asTM_NONE); - paramNames.PushLast("value"); - paramTypes.PushLast(emulatedType); - defaultArgs.PushLast(0); - name = "set_" + emulatedName; - success = true; } - else - WriteError(TXT_UNRECOGNIZED_VIRTUAL_PROPERTY_NODE, file, node); if( success ) { if( !isExistingShared ) - RegisterScriptFunction(funcNode, file, objType, isInterface, isGlobalFunction, ns, false, false, name, returnType, paramNames, paramTypes, paramModifiers, defaultArgs, isConst, false, false, isPrivate, isProtected, isOverride, isFinal, false); + RegisterScriptFunction(funcNode, file, objType, isInterface, isGlobalFunction, ns, false, false, name, returnType, paramNames, paramTypes, paramModifiers, defaultArgs, funcTraits); else { // Free the funcNode as it won't be used @@ -4710,7 +4958,7 @@ int asCBuilder::RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file { asCScriptFunction *func = engine->scriptFunctions[objType->methods[n]]; if( func->name == name && - func->IsSignatureExceptNameEqual(returnType, paramTypes, paramModifiers, objType, isConst) ) + func->IsSignatureExceptNameEqual(returnType, paramTypes, paramModifiers, objType, funcTraits.GetTrait(asTRAIT_CONST)) ) { found = true; break; @@ -4742,12 +4990,12 @@ int asCBuilder::RegisterImportedFunction(int importID, asCScriptNode *node, asCS asCArray parameterTypes; asCArray inOutFlags; asCArray defaultArgs; - bool isConstMethod, isOverride, isFinal, isConstructor, isDestructor, isPrivate, isProtected, isShared; + asSFunctionTraits funcTraits; if( ns == 0 ) ns = engine->nameSpaces[0]; - GetParsedFunctionDetails(node->firstChild, file, 0, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared, ns); + GetParsedFunctionDetails(node->firstChild, file, 0, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, funcTraits, ns); CheckNameConflict(name.AddressOf(), node, file, ns); // Check that the same function hasn't been registered already in the namespace @@ -4823,73 +5071,70 @@ void asCBuilder::GetFunctionDescriptions(const char *name, asCArray &funcs, } } +// scope is only informed when looking for a base class' method void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *objectType, asCArray &methods, bool objIsConst, const asCString &scope, asCScriptNode *errNode, asCScriptCode *script) { + asASSERT(objectType); + if( scope != "" ) { // If searching with a scope informed, then the node and script must also be informed for potential error reporting asASSERT( errNode && script ); // If the scope contains ::identifier, then use the last identifier as the class name and the rest of it as the namespace + // TODO: child funcdef: A scope can include a template type, e.g. array int n = scope.FindLast("::"); asCString className = n >= 0 ? scope.SubString(n+2) : scope; asCString nsName = n >= 0 ? scope.SubString(0, n) : ""; - // Check if the namespace actually exist, if not return silently as this cannot be the referring to a base class - asSNameSpace *ns = GetNameSpaceByString(nsName, objectType->nameSpace, errNode, script, false); - if( ns == 0 ) - return; + // If a namespace was specifically defined, then this must be used + asSNameSpace *ns = 0; + if (n >= 0) + { + if (nsName == "") + ns = engine->nameSpaces[0]; + else + ns = GetNameSpaceByString(nsName, objectType->nameSpace, errNode, script, 0, false); + + // If the namespace isn't found return silently and let the calling + // function report the error if it cannot resolve the symbol + if (ns == 0) + return; + } // Find the base class with the specified scope - while( objectType && (objectType->name != className || objectType->nameSpace != ns) ) + while (objectType) + { + // If the name and namespace matches it is the correct class. If no + // specific namespace was given, then don't compare the namespace + if (objectType->name == className && (ns == 0 || objectType->nameSpace == ns)) + break; + objectType = objectType->derivedFrom; + } // If the scope is not any of the base classes, then return no methods if( objectType == 0 ) return; } + // Find the methods in the object that match the name // TODO: optimize: Improve linear search - if( objIsConst ) + for( asUINT n = 0; n < objectType->methods.GetLength(); n++ ) { - // Only add const methods to the list - for( asUINT n = 0; n < objectType->methods.GetLength(); n++ ) + asCScriptFunction *func = engine->scriptFunctions[objectType->methods[n]]; + if( func->name == name && + (!objIsConst || func->IsReadOnly()) && + (func->accessMask & module->accessMask) ) { - asCScriptFunction *func = engine->scriptFunctions[objectType->methods[n]]; - if( func->name == name && - func->isReadOnly && - (func->accessMask & module->accessMask) ) + // When the scope is defined the returned methods should be the true methods, not the virtual method stubs + if( scope == "" ) + methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id); + else { - // When the scope is defined the returned methods should be the true methods, not the virtual method stubs - if( scope == "" ) - methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id); - else - { - asCScriptFunction *virtFunc = engine->scriptFunctions[objectType->methods[n]]; - asCScriptFunction *realFunc = objectType->virtualFunctionTable[virtFunc->vfTableIdx]; - methods.PushLast(realFunc->id); - } - } - } - } - else - { - // TODO: Prefer non-const over const - for( asUINT n = 0; n < objectType->methods.GetLength(); n++ ) - { - asCScriptFunction *func = engine->scriptFunctions[objectType->methods[n]]; - if( func->name == name && - (func->accessMask & module->accessMask) ) - { - // When the scope is defined the returned methods should be the true methods, not the virtual method stubs - if( scope == "" ) - methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id); - else - { - asCScriptFunction *virtFunc = engine->scriptFunctions[objectType->methods[n]]; - asCScriptFunction *realFunc = objectType->virtualFunctionTable[virtFunc->vfTableIdx]; - methods.PushLast(realFunc->id); - } + asCScriptFunction *virtFunc = engine->scriptFunctions[objectType->methods[n]]; + asCScriptFunction *realFunc = objectType->virtualFunctionTable[virtFunc->vfTableIdx]; + methods.PushLast(realFunc->id); } } } @@ -4962,16 +5207,25 @@ void asCBuilder::WriteWarning(const asCString &message, asCScriptCode *file, asC WriteWarning(file ? file->name : asCString(""), message, r, c); } +// TODO: child funcdef: Should try to eliminate this function. GetNameSpaceFromNode is more complete asCString asCBuilder::GetScopeFromNode(asCScriptNode *node, asCScriptCode *script, asCScriptNode **next) { + if (node->nodeType != snScope) + { + if (next) + *next = node; + return ""; + } + asCString scope; - asCScriptNode *sn = node; + asCScriptNode *sn = node->firstChild; if( sn->tokenType == ttScope ) { scope = "::"; sn = sn->next; } + // TODO: child funcdef: A scope can have a template type as the innermost while( sn && sn->next && sn->next->tokenType == ttScope ) { asCString tmp; @@ -4983,26 +5237,128 @@ asCString asCBuilder::GetScopeFromNode(asCScriptNode *node, asCScriptCode *scrip } if( next ) - *next = sn; + *next = node->next; return scope; } -asSNameSpace *asCBuilder::GetNameSpaceFromNode(asCScriptNode *node, asCScriptCode *script, asSNameSpace *implicitNs, asCScriptNode **next) +asSNameSpace *asCBuilder::GetNameSpaceFromNode(asCScriptNode *node, asCScriptCode *script, asSNameSpace *implicitNs, asCScriptNode **next, asCObjectType **objType) { - asCString scope = GetScopeFromNode(node, script, next); - return GetNameSpaceByString(scope, implicitNs, node, script); + if (objType) + *objType = 0; + + // If no scope has been informed, then return the implicit namespace + if (node->nodeType != snScope) + { + if (next) + *next = node; + return implicitNs ? implicitNs : engine->nameSpaces[0]; + } + + if (next) + *next = node->next; + + asCString scope; + asCScriptNode *sn = node->firstChild; + if (sn && sn->tokenType == ttScope) + { + scope = "::"; + sn = sn->next; + } + + while (sn) + { + if (sn->next->tokenType == ttScope) + { + asCString tmp; + tmp.Assign(&script->code[sn->tokenPos], sn->tokenLength); + if (scope != "" && scope != "::") + scope += "::"; + scope += tmp; + sn = sn->next->next; + } + else + { + // This is a template type + asASSERT(sn->next->nodeType == snDataType); + + asSNameSpace *ns = implicitNs; + if (scope != "") + ns = engine->FindNameSpace(scope.AddressOf()); + + asCString templateName(&script->code[sn->tokenPos], sn->tokenLength); + asCObjectType *templateType = GetObjectType(templateName.AddressOf(), ns); + if (templateType == 0 || (templateType->flags & asOBJ_TEMPLATE) == 0) + { + // TODO: child funcdef: Report error + return ns; + } + + if (objType) + *objType = GetTemplateInstanceFromNode(sn, script, templateType, implicitNs, 0); + + // Return no namespace, since this is an object type + return 0; + } + } + + asCTypeInfo *ti = 0; + asSNameSpace *ns = GetNameSpaceByString(scope, implicitNs ? implicitNs : engine->nameSpaces[0], node, script, &ti); + if (ti && objType) + *objType = CastToObjectType(ti); + return ns; } -asSNameSpace *asCBuilder::GetNameSpaceByString(const asCString &nsName, asSNameSpace *implicitNs, asCScriptNode *errNode, asCScriptCode *script, bool isRequired) +asSNameSpace *asCBuilder::GetNameSpaceByString(const asCString &nsName, asSNameSpace *implicitNs, asCScriptNode *errNode, asCScriptCode *script, asCTypeInfo **scopeType, bool isRequired) { + if( scopeType ) + *scopeType = 0; + asSNameSpace *ns = implicitNs; if( nsName == "::" ) ns = engine->nameSpaces[0]; else if( nsName != "" ) { ns = engine->FindNameSpace(nsName.AddressOf()); - if( ns == 0 && isRequired ) + if (ns == 0 && scopeType) + { + asCString typeName; + asCString searchNs; + + // Split the scope with at the inner most :: + int pos = nsName.FindLast("::"); + bool recursive = false; + if (pos >= 0) + { + // Fully qualified namespace + typeName = nsName.SubString(pos + 2); + searchNs = nsName.SubString(0, pos); + } + else + { + // Partially qualified, use the implicit namespace and then search recursively for the type + typeName = nsName; + searchNs = implicitNs->name; + recursive = true; + } + + asSNameSpace *nsTmp = searchNs == "::" ? engine->nameSpaces[0] : engine->FindNameSpace(searchNs.AddressOf()); + asCTypeInfo *ti = 0; + while( !ti && nsTmp ) + { + // Check if the typeName is an existing type in the namespace + ti = GetType(typeName.AddressOf(), nsTmp, 0); + if (ti) + { + // The informed scope is not a namespace, but it does match a type + *scopeType = ti; + return 0; + } + nsTmp = recursive ? engine->GetParentNameSpace(nsTmp) : 0; + } + } + + if (ns == 0 && isRequired) { asCString msg; msg.Format(TXT_NAMESPACE_s_DOESNT_EXIST, nsName.AddressOf()); @@ -5013,14 +5369,22 @@ asSNameSpace *asCBuilder::GetNameSpaceByString(const asCString &nsName, asSNameS return ns; } -asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCode *file, asSNameSpace *implicitNamespace, bool acceptHandleForScope, asCObjectType *currentType) +asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCode *file, asSNameSpace *implicitNamespace, bool acceptHandleForScope, asCObjectType *currentType, bool reportError, bool *isValid) { - asASSERT(node->nodeType == snDataType); + asASSERT(node->nodeType == snDataType || node->nodeType == snIdentifier || node->nodeType == snScope ); asCDataType dt; asCScriptNode *n = node->firstChild; + if (isValid) + *isValid = true; + + // If the informed node is an identifier or scope, then the + // datatype should be identified directly from that + if (node->nodeType != snDataType) + n = node; + bool isConst = false; bool isImplicitHandle = false; if( n->tokenType == ttConst ) @@ -5029,12 +5393,15 @@ asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCod n = n->next; } - // Determine namespace - asSNameSpace *ns = GetNameSpaceFromNode(n, file, implicitNamespace, &n); - if( ns == 0 ) + // Determine namespace (or parent type) to search for the data type in + asCObjectType *parentType = 0; + asSNameSpace *ns = GetNameSpaceFromNode(n, file, implicitNamespace, &n, &parentType); + if( ns == 0 && parentType == 0 ) { - // The namespace doesn't exist. Return a dummy type instead. + // The namespace and parent type doesn't exist. Return a dummy type instead. dt = asCDataType::CreatePrimitive(ttInt, false); + if (isValid) + *isValid = false; return dt; } @@ -5042,189 +5409,146 @@ asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCod { bool found = false; - asCScriptNode *nameToken = n; asCString str; str.Assign(&file->code[n->tokenPos], n->tokenLength); // Recursively search parent namespaces for matching type asSNameSpace *origNs = ns; - while( ns && !found ) + asCObjectType *origParentType = parentType; + while( (ns || parentType) && !found ) { - asCObjectType *ot = 0; + asCTypeInfo *ti = 0; - // If this is for a template type, then we must first determine if the - // identifier matches any of the template subtypes - if( currentType && (currentType->flags & asOBJ_TEMPLATE) ) + if (currentType) { - for( asUINT subtypeIndex = 0; subtypeIndex < currentType->templateSubTypes.GetLength(); subtypeIndex++) + // If this is for a template type, then we must first determine if the + // identifier matches any of the template subtypes + if (currentType->flags & asOBJ_TEMPLATE) { - asCObjectType *type = currentType->templateSubTypes[subtypeIndex].GetObjectType(); - if( type && str == type->name ) + for (asUINT subtypeIndex = 0; subtypeIndex < currentType->templateSubTypes.GetLength(); subtypeIndex++) { - ot = type; - break; + asCTypeInfo *type = currentType->templateSubTypes[subtypeIndex].GetTypeInfo(); + if (type && str == type->name) + { + ti = type; + break; + } + } + } + + if (ti == 0) + { + // Check if the type is a child type of the current type + ti = GetFuncDef(str.AddressOf(), 0, currentType); + if (ti) + { + dt = asCDataType::CreateType(ti, false); + found = true; } } } - if( ot == 0 ) - ot = GetObjectType(str.AddressOf(), ns); - if( ot == 0 && !module && currentType ) - ot = GetObjectTypeFromTypesKnownByObject(str.AddressOf(), currentType); + if( ti == 0 ) + ti = GetType(str.AddressOf(), ns, parentType); + if( ti == 0 && !module && currentType ) + ti = GetTypeFromTypesKnownByObject(str.AddressOf(), currentType); - if( ot ) + if( ti && !found ) { found = true; - if( ot->flags & asOBJ_IMPLICIT_HANDLE ) + if( ti->flags & asOBJ_IMPLICIT_HANDLE ) isImplicitHandle = true; // Make sure the module has access to the object type - if( !module || (module->accessMask & ot->accessMask) ) + if( !module || (module->accessMask & ti->accessMask) ) { - if( asOBJ_TYPEDEF == (ot->flags & asOBJ_TYPEDEF) ) + if( asOBJ_TYPEDEF == (ti->flags & asOBJ_TYPEDEF) ) { // TODO: typedef: A typedef should be considered different from the original type (though with implicit conversions between the two) // Create primitive data type based on object flags - dt = ot->templateSubTypes[0]; + dt = CastToTypedefType(ti)->aliasForType; dt.MakeReadOnly(isConst); } else { - if( ot->flags & asOBJ_TEMPLATE ) + if( ti->flags & asOBJ_TEMPLATE ) { - // Check if the subtype is a type or the template's subtype - // if it is the template's subtype then this is the actual template type, - // orderwise it is a template instance. - // Only do this for application registered interface, as the - // scripts cannot implement templates. - asCArray subTypes; - asUINT subtypeIndex; - while( n && n->next && n->next->nodeType == snDataType ) + ti = GetTemplateInstanceFromNode(n, file, CastToObjectType(ti), implicitNamespace, currentType, &n); + if (ti == 0) { - n = n->next; - - // When parsing function definitions for template registrations (currentType != 0) it is necessary - // to pass in the current template type to the recursive call since it is this ones sub-template types - // that should be allowed. - asCDataType subType = CreateDataTypeFromNode(n, file, implicitNamespace, false, module ? 0 : (currentType ? currentType : ot)); - subTypes.PushLast(subType); - - if( subType.IsReadOnly() ) - { - asCString msg; - msg.Format(TXT_TMPL_SUBTYPE_MUST_NOT_BE_READ_ONLY); - WriteError(msg, file, n); - - // Return a dummy - return asCDataType::CreatePrimitive(ttInt, false); - } - } - - if( subTypes.GetLength() != ot->templateSubTypes.GetLength() ) - { - asCString msg; - msg.Format(TXT_TMPL_s_EXPECTS_d_SUBTYPES, ot->name.AddressOf(), int(ot->templateSubTypes.GetLength())); - WriteError(msg, file, nameToken); + if (isValid) + *isValid = false; // Return a dummy return asCDataType::CreatePrimitive(ttInt, false); } - - // Check if any of the given subtypes are different from the template's declared subtypes - bool isDifferent = false; - for( subtypeIndex = 0; subtypeIndex < subTypes.GetLength(); subtypeIndex++ ) - { - if( subTypes[subtypeIndex].GetObjectType() != ot->templateSubTypes[subtypeIndex].GetObjectType() ) - { - isDifferent = true; - break; - } - } - - if( isDifferent ) - { - // This is a template instance - // Need to find the correct object type - asCObjectType *otInstance = engine->GetTemplateInstanceType(ot, subTypes, module); - - if( otInstance && otInstance->scriptSectionIdx < 0 ) - { - // If this is the first time the template instance is used, store where it was declared from - otInstance->scriptSectionIdx = engine->GetScriptSectionNameIndex(file->name.AddressOf()); - int row, column; - file->ConvertPosToRowCol(n->tokenPos, &row, &column); - otInstance->declaredAt = (row&0xFFFFF)|(column<<20); - } - - if( !otInstance ) - { - asCString sub = subTypes[0].Format(ot->nameSpace); - for( asUINT s = 1; s < subTypes.GetLength(); s++ ) - { - sub += ","; - sub += subTypes[s].Format(ot->nameSpace); - } - asCString str; - str.Format(TXT_INSTANCING_INVLD_TMPL_TYPE_s_s, ot->name.AddressOf(), sub.AddressOf()); - WriteError(str, file, n); - } - - ot = otInstance; - } } else if( n && n->next && n->next->nodeType == snDataType ) { - asCString str; - str.Format(TXT_TYPE_s_NOT_TEMPLATE, ot->name.AddressOf()); - WriteError(str, file, n); + if (reportError) + { + asCString msg; + msg.Format(TXT_TYPE_s_NOT_TEMPLATE, ti->name.AddressOf()); + WriteError(msg, file, n); + } + if (isValid) + *isValid = false; } // Create object data type - if( ot ) - dt = asCDataType::CreateObject(ot, isConst); + if( ti ) + dt = asCDataType::CreateType(ti, isConst); else dt = asCDataType::CreatePrimitive(ttInt, isConst); } } else { - asCString msg; - msg.Format(TXT_TYPE_s_NOT_AVAILABLE_FOR_MODULE, (const char *)str.AddressOf()); - WriteError(msg, file, n); + if (reportError) + { + asCString msg; + msg.Format(TXT_TYPE_s_NOT_AVAILABLE_FOR_MODULE, (const char *)str.AddressOf()); + WriteError(msg, file, n); + } dt.SetTokenType(ttInt); - } - } - else if( ot == 0 ) - { - // It can still be a function definition - asCScriptFunction *funcdef = GetFuncDef(str.AddressOf()); - - if( funcdef ) - { - dt = asCDataType::CreateFuncDef(funcdef); - found = true; + if (isValid) + *isValid = false; } } if( !found ) { // Try to find it in the parent namespace - ns = engine->GetParentNameSpace(ns); + if( ns ) + ns = engine->GetParentNameSpace(ns); + if (parentType) + parentType = 0; } } if( !found ) { - asCString msg; - if( origNs->name == "" ) - msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_GLOBAL_NS, str.AddressOf()); - else - msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s, str.AddressOf(), origNs->name.AddressOf()); - WriteError(msg, file, n); + if (reportError) + { + asCString msg; + if (origNs && origNs->name == "") + msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_GLOBAL_NS, str.AddressOf()); + else if (origNs) + msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s, str.AddressOf(), origNs->name.AddressOf()); + else + { + // TODO: child funcdef: Message should explain that the identifier is not a type of the parent type + asCDataType pt = asCDataType::CreateType(origParentType, false); + msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s, str.AddressOf(), pt.Format(origParentType->nameSpace, false).AddressOf()); + } + WriteError(msg, file, n); + } dt = asCDataType::CreatePrimitive(ttInt, isConst); + if (isValid) + *isValid = false; return dt; } } @@ -5247,22 +5571,30 @@ asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCod // Make sure the sub type can be instantiated if( !dt.CanBeInstantiated() ) { - asCString str; - if( dt.IsAbstractClass() ) - str.Format(TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED, dt.Format(ns).AddressOf()); - else if( dt.IsInterface() ) - str.Format(TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED, dt.Format(ns).AddressOf()); - else - // TODO: Improve error message to explain why - str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format(ns).AddressOf()); + if (reportError) + { + asCString str; + if (dt.IsAbstractClass()) + str.Format(TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED, dt.Format(ns).AddressOf()); + else if (dt.IsInterface()) + str.Format(TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED, dt.Format(ns).AddressOf()); + else + // TODO: Improve error message to explain why + str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format(ns).AddressOf()); - WriteError(str, file, n); + WriteError(str, file, n); + } + if (isValid) + *isValid = false; } // Make the type an array (or multidimensional array) if( dt.MakeArray(engine, module) < 0 ) { - WriteError(TXT_NO_DEFAULT_ARRAY_TYPE, file, n); + if( reportError ) + WriteError(TXT_NO_DEFAULT_ARRAY_TYPE, file, n); + if (isValid) + *isValid = false; break; } } @@ -5271,12 +5603,18 @@ asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCod // Make the type a handle if( dt.IsObjectHandle() ) { - WriteError(TXT_HANDLE_OF_HANDLE_IS_NOT_ALLOWED, file, n); + if( reportError ) + WriteError(TXT_HANDLE_OF_HANDLE_IS_NOT_ALLOWED, file, n); + if (isValid) + *isValid = false; break; } else if( dt.MakeHandle(true, acceptHandleForScope) < 0 ) { - WriteError(TXT_OBJECT_HANDLE_NOT_SUPPORTED, file, n); + if( reportError ) + WriteError(TXT_OBJECT_HANDLE_NOT_SUPPORTED, file, n); + if (isValid) + *isValid = false; break; } } @@ -5286,13 +5624,107 @@ asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCod if( isImplicitHandle ) { // Make the type a handle - if( dt.MakeHandle(true, acceptHandleForScope) < 0 ) - WriteError(TXT_OBJECT_HANDLE_NOT_SUPPORTED, file, n); + if (dt.MakeHandle(true, acceptHandleForScope) < 0) + { + if( reportError ) + WriteError(TXT_OBJECT_HANDLE_NOT_SUPPORTED, file, n); + if (isValid) + *isValid = false; + } } return dt; } +asCObjectType *asCBuilder::GetTemplateInstanceFromNode(asCScriptNode *node, asCScriptCode *file, asCObjectType *templateType, asSNameSpace *implicitNamespace, asCObjectType *currentType, asCScriptNode **next) +{ + // Check if the subtype is a type or the template's subtype + // if it is the template's subtype then this is the actual template type, + // orderwise it is a template instance. + // Only do this for application registered interface, as the + // scripts cannot implement templates. + asCArray subTypes; + asUINT subtypeIndex; + asCScriptNode *n = node; + while (n && n->next && n->next->nodeType == snDataType) + { + n = n->next; + + // When parsing function definitions for template registrations (currentType != 0) it is necessary + // to pass in the current template type to the recursive call since it is this ones sub-template types + // that should be allowed. + asCDataType subType = CreateDataTypeFromNode(n, file, implicitNamespace, false, module ? 0 : (currentType ? currentType : templateType)); + subTypes.PushLast(subType); + + if (subType.IsReadOnly()) + { + asCString msg; + msg.Format(TXT_TMPL_SUBTYPE_MUST_NOT_BE_READ_ONLY); + WriteError(msg, file, n); + + // Return a dummy + return 0; + } + } + + if (next) + *next = n; + + if (subTypes.GetLength() != templateType->templateSubTypes.GetLength()) + { + asCString msg; + msg.Format(TXT_TMPL_s_EXPECTS_d_SUBTYPES, templateType->name.AddressOf(), int(templateType->templateSubTypes.GetLength())); + WriteError(msg, file, node); + + // Return a dummy + return 0; + } + + // Check if any of the given subtypes are different from the template's declared subtypes + bool isDifferent = false; + for (subtypeIndex = 0; subtypeIndex < subTypes.GetLength(); subtypeIndex++) + { + if (subTypes[subtypeIndex].GetTypeInfo() != templateType->templateSubTypes[subtypeIndex].GetTypeInfo()) + { + isDifferent = true; + break; + } + } + + if (isDifferent) + { + // This is a template instance + // Need to find the correct object type + asCObjectType *otInstance = engine->GetTemplateInstanceType(templateType, subTypes, module); + + if (otInstance && otInstance->scriptSectionIdx < 0) + { + // If this is the first time the template instance is used, store where it was declared from + otInstance->scriptSectionIdx = engine->GetScriptSectionNameIndex(file->name.AddressOf()); + int row, column; + file->ConvertPosToRowCol(n->tokenPos, &row, &column); + otInstance->declaredAt = (row & 0xFFFFF) | (column << 20); + } + + if (!otInstance) + { + asCString sub = subTypes[0].Format(templateType->nameSpace); + for (asUINT s = 1; s < subTypes.GetLength(); s++) + { + sub += ","; + sub += subTypes[s].Format(templateType->nameSpace); + } + asCString msg; + msg.Format(TXT_INSTANCING_INVLD_TMPL_TYPE_s_s, templateType->name.AddressOf(), sub.AddressOf()); + WriteError(msg, file, n); + } + + return otInstance; + } + + return templateType; +} + asCDataType asCBuilder::ModifyDataTypeFromNode(const asCDataType &type, asCScriptNode *node, asCScriptCode *file, asETypeModifiers *inOutFlags, bool *autoHandle) { asCDataType dt = type; @@ -5303,6 +5735,14 @@ asCDataType asCBuilder::ModifyDataTypeFromNode(const asCDataType &type, asCScrip asCScriptNode *n = node->firstChild; if( n && n->tokenType == ttAmp ) { + if (dt.GetTokenType() == ttVoid) + { + asCString msg; + msg.Format(TXT_TYPE_s_CANNOT_BE_REFERENCE, type.Format(0).AddressOf()); + WriteError(msg, file, node->firstChild); + return dt; + } + dt.MakeReference(true); n = n->next; @@ -5332,7 +5772,7 @@ asCDataType asCBuilder::ModifyDataTypeFromNode(const asCDataType &type, asCScrip inOutFlags && *inOutFlags == asTM_INOUTREF ) { // Verify that the base type support &inout parameter types - if( !dt.IsObject() || dt.IsObjectHandle() || !((dt.GetObjectType()->flags & asOBJ_NOCOUNT) || (dt.GetObjectType()->beh.addref && dt.GetObjectType()->beh.release)) ) + if( !dt.IsObject() || dt.IsObjectHandle() || !((dt.GetTypeInfo()->flags & asOBJ_NOCOUNT) || (CastToObjectType(dt.GetTypeInfo())->beh.addref && CastToObjectType(dt.GetTypeInfo())->beh.release)) ) WriteError(TXT_ONLY_OBJECTS_MAY_USE_REF_INOUT, file, node->firstChild); } } @@ -5342,24 +5782,65 @@ asCDataType asCBuilder::ModifyDataTypeFromNode(const asCDataType &type, asCScrip if( n && n->tokenType == ttPlus ) { // Autohandles are not supported for types with NOCOUNT - // If the type is not a handle then there was an error with building the type, but + // If the type is not a handle then there was an error with building the type, but // this error would already have been reported so no need to report another error here - if( dt.IsObjectHandle() && (dt.GetObjectType()->flags & asOBJ_NOCOUNT) ) + if( dt.IsObjectHandle() && (dt.GetTypeInfo()->flags & asOBJ_NOCOUNT) ) WriteError(TXT_AUTOHANDLE_CANNOT_BE_USED_FOR_NOCOUNT, file, node->firstChild); if( autoHandle ) *autoHandle = true; } + if (n && n->tokenType == ttIdentifier) + { + asCString str; + str.Assign(&file->code[n->tokenPos], n->tokenLength); + if (str == IF_HANDLE_TOKEN) + dt.SetIfHandleThenConst(true); + else + { + // TODO: Should give error if not currently parsing template registration + asCString msg; + msg.Format(TXT_UNEXPECTED_TOKEN_s, str.AddressOf()); + WriteError(msg, file, node->firstChild); + } + } + return dt; } +asCTypeInfo *asCBuilder::GetType(const char *type, asSNameSpace *ns, asCObjectType *parentType) +{ + asASSERT((ns == 0 && parentType) || (ns && parentType == 0)); + + if (ns) + { + asCTypeInfo *ti = engine->GetRegisteredType(type, ns); + if (!ti && module) + ti = module->GetType(type, ns); + return ti; + } + else + { + // Recursively check base classes + asCObjectType *currType = parentType; + while (currType) + { + for (asUINT n = 0; n < currType->childFuncDefs.GetLength(); n++) + { + asCFuncdefType *funcDef = currType->childFuncDefs[n]; + if (funcDef && funcDef->name == type) + return funcDef; + } + currType = currType->derivedFrom; + } + } + + return 0; +} + asCObjectType *asCBuilder::GetObjectType(const char *type, asSNameSpace *ns) { - asCObjectType *ot = engine->GetRegisteredObjectType(type, ns); - if( !ot && module ) - ot = module->GetObjectType(type, ns); - - return ot; + return CastToObjectType(GetType(type, ns, 0)); } #ifndef AS_NO_COMPILER @@ -5378,8 +5859,8 @@ bool asCBuilder::DoesTypeExist(const asCString &type) // Only do this once hasCachedKnownTypes = true; - // Add registered object types - asSMapNode *cursor; + // Add registered types + asSMapNode *cursor; engine->allRegisteredTypes.MoveFirst(&cursor); while( cursor ) { @@ -5389,31 +5870,26 @@ bool asCBuilder::DoesTypeExist(const asCString &type) engine->allRegisteredTypes.MoveNext(&cursor, cursor); } - // Add registered funcdefs - for( n = 0; n < engine->registeredFuncDefs.GetLength(); n++ ) - if( !knownTypes.MoveTo(0, engine->registeredFuncDefs[n]->name) ) - knownTypes.Insert(engine->registeredFuncDefs[n]->name, true); - - if( module ) + if (module) { // Add script classes and interfaces - for( n = 0; n < module->classTypes.GetLength(); n++ ) - if( !knownTypes.MoveTo(0, module->classTypes[n]->name) ) + for (n = 0; n < module->classTypes.GetLength(); n++) + if (!knownTypes.MoveTo(0, module->classTypes[n]->name)) knownTypes.Insert(module->classTypes[n]->name, true); // Add script enums - for( n = 0; n < module->enumTypes.GetLength(); n++ ) - if( !knownTypes.MoveTo(0, module->enumTypes[n]->name) ) + for (n = 0; n < module->enumTypes.GetLength(); n++) + if (!knownTypes.MoveTo(0, module->enumTypes[n]->name)) knownTypes.Insert(module->enumTypes[n]->name, true); // Add script typedefs - for( n = 0; n < module->typeDefs.GetLength(); n++ ) - if( !knownTypes.MoveTo(0, module->typeDefs[n]->name) ) + for (n = 0; n < module->typeDefs.GetLength(); n++) + if (!knownTypes.MoveTo(0, module->typeDefs[n]->name)) knownTypes.Insert(module->typeDefs[n]->name, true); // Add script funcdefs - for( n = 0; n < module->funcDefs.GetLength(); n++ ) - if( !knownTypes.MoveTo(0, module->funcDefs[n]->name) ) + for (n = 0; n < module->funcDefs.GetLength(); n++) + if (!knownTypes.MoveTo(0, module->funcDefs[n]->name)) knownTypes.Insert(module->funcDefs[n]->name, true); } } @@ -5423,56 +5899,82 @@ bool asCBuilder::DoesTypeExist(const asCString &type) } #endif -asCObjectType *asCBuilder::GetObjectTypeFromTypesKnownByObject(const char *type, asCObjectType *currentType) +asCTypeInfo *asCBuilder::GetTypeFromTypesKnownByObject(const char *type, asCObjectType *currentType) { - if( currentType->name == type ) + if (currentType->name == type) return currentType; asUINT n; - asCObjectType *found = 0; + asCTypeInfo *found = 0; - for( n = 0; found == 0 && n < currentType->properties.GetLength(); n++ ) - if( currentType->properties[n]->type.GetObjectType() && - currentType->properties[n]->type.GetObjectType()->name == type ) - found = currentType->properties[n]->type.GetObjectType(); + for (n = 0; found == 0 && n < currentType->properties.GetLength(); n++) + if (currentType->properties[n]->type.GetTypeInfo() && + currentType->properties[n]->type.GetTypeInfo()->name == type) + found = currentType->properties[n]->type.GetTypeInfo(); - for( n = 0; found == 0 && n < currentType->methods.GetLength(); n++ ) + for (n = 0; found == 0 && n < currentType->methods.GetLength(); n++) { asCScriptFunction *func = engine->scriptFunctions[currentType->methods[n]]; - if( func->returnType.GetObjectType() && - func->returnType.GetObjectType()->name == type ) - found = func->returnType.GetObjectType(); - - for( asUINT f = 0; found == 0 && f < func->parameterTypes.GetLength(); f++ ) - if( func->parameterTypes[f].GetObjectType() && - func->parameterTypes[f].GetObjectType()->name == type ) - found = func->parameterTypes[f].GetObjectType(); + if (func->returnType.GetTypeInfo() && + func->returnType.GetTypeInfo()->name == type) + found = func->returnType.GetTypeInfo(); + + for (asUINT f = 0; found == 0 && f < func->parameterTypes.GetLength(); f++) + if (func->parameterTypes[f].GetTypeInfo() && + func->parameterTypes[f].GetTypeInfo()->name == type) + found = func->parameterTypes[f].GetTypeInfo(); } - if( found ) + if (found) { // In case we find a template instance it mustn't be returned // because it is not known if the subtype is really matching - if( found->flags & asOBJ_TEMPLATE ) + if (found->flags & asOBJ_TEMPLATE) return 0; } return found; } -asCScriptFunction *asCBuilder::GetFuncDef(const char *type) +asCFuncdefType *asCBuilder::GetFuncDef(const char *type, asSNameSpace *ns, asCObjectType *parentType) { - for( asUINT n = 0; n < engine->registeredFuncDefs.GetLength(); n++ ) - // TODO: access: Only return the definitions that the module has access to - if( engine->registeredFuncDefs[n]->name == type ) - return engine->registeredFuncDefs[n]; + asASSERT((ns == 0 && parentType) || (ns && parentType == 0)); - if( module ) + if (ns) { - for( asUINT n = 0; n < module->funcDefs.GetLength(); n++ ) - if( module->funcDefs[n]->name == type ) - return module->funcDefs[n]; + for (asUINT n = 0; n < engine->registeredFuncDefs.GetLength(); n++) + { + asCFuncdefType *funcDef = engine->registeredFuncDefs[n]; + // TODO: access: Only return the definitions that the module has access to + if (funcDef && funcDef->nameSpace == ns && funcDef->name == type) + return funcDef; + } + + if (module) + { + for (asUINT n = 0; n < module->funcDefs.GetLength(); n++) + { + asCFuncdefType *funcDef = module->funcDefs[n]; + if (funcDef && funcDef->nameSpace == ns && funcDef->name == type) + return funcDef; + } + } + } + else + { + // Recursively check base classes + asCObjectType *currType = parentType; + while (currType) + { + for (asUINT n = 0; n < currType->childFuncDefs.GetLength(); n++) + { + asCFuncdefType *funcDef = currType->childFuncDefs[n]; + if (funcDef && funcDef->name == type) + return funcDef; + } + currType = currType->derivedFrom; + } } return 0; @@ -5480,17 +5982,17 @@ asCScriptFunction *asCBuilder::GetFuncDef(const char *type) #ifndef AS_NO_COMPILER -int asCBuilder::GetEnumValueFromObjectType(asCObjectType *objType, const char *name, asCDataType &outDt, asDWORD &outValue) +int asCBuilder::GetEnumValueFromType(asCEnumType *type, const char *name, asCDataType &outDt, asDWORD &outValue) { - if( !objType || !(objType->flags & asOBJ_ENUM) ) + if( !type || !(type->flags & asOBJ_ENUM) ) return 0; - for( asUINT n = 0; n < objType->enumValues.GetLength(); ++n ) + for( asUINT n = 0; n < type->enumValues.GetLength(); ++n ) { - if( objType->enumValues[n]->name == name ) + if( type->enumValues[n]->name == name ) { - outDt = asCDataType::CreateObject(objType, true); - outValue = objType->enumValues[n]->value; + outDt = asCDataType::CreateType(type, true); + outValue = type->enumValues[n]->value; return 1; } } @@ -5506,14 +6008,14 @@ int asCBuilder::GetEnumValue(const char *name, asCDataType &outDt, asDWORD &outV asUINT t; for( t = 0; t < engine->registeredEnums.GetLength(); t++ ) { - asCObjectType *ot = engine->registeredEnums[t]; - if( ns != ot->nameSpace ) continue; + asCEnumType *et = engine->registeredEnums[t]; + if( ns != et->nameSpace ) continue; // Don't bother with types the module doesn't have access to - if( (ot->accessMask & module->accessMask) == 0 ) + if( (et->accessMask & module->accessMask) == 0 ) continue; - if( GetEnumValueFromObjectType(ot, name, outDt, outValue) ) + if( GetEnumValueFromType(et, name, outDt, outValue) ) { if( !found ) found = true; @@ -5527,10 +6029,10 @@ int asCBuilder::GetEnumValue(const char *name, asCDataType &outDt, asDWORD &outV for( t = 0; t < module->enumTypes.GetLength(); t++ ) { - asCObjectType *ot = module->enumTypes[t]; - if( ns != ot->nameSpace ) continue; + asCEnumType *et = module->enumTypes[t]; + if( ns != et->nameSpace ) continue; - if( GetEnumValueFromObjectType(ot, name, outDt, outValue) ) + if( GetEnumValueFromType(et, name, outDt, outValue) ) { if( !found ) found = true; diff --git a/lib/angelscript/source/as_builder.h b/lib/angelscript/source/as_builder.h index 11c9ed917..988273123 100644 --- a/lib/angelscript/source/as_builder.h +++ b/lib/angelscript/source/as_builder.h @@ -1,24 +1,24 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; you + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product + this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source + 3. This notice may not be removed or altered from any source distribution. The original version of this library can be located at: @@ -99,13 +99,13 @@ struct sPropertyInitializer struct sClassDeclaration { - sClassDeclaration() {script = 0; node = 0; validState = 0; objType = 0; isExistingShared = false; isFinal = false;} + sClassDeclaration() {script = 0; node = 0; validState = 0; typeInfo = 0; isExistingShared = false; isFinal = false;} asCScriptCode *script; asCScriptNode *node; asCString name; int validState; - asCObjectType *objType; + asCTypeInfo *typeInfo; bool isExistingShared; bool isFinal; @@ -140,10 +140,10 @@ public: int VerifyProperty(asCDataType *dt, const char *decl, asCString &outName, asCDataType &outType, asSNameSpace *ns); int ParseDataType(const char *datatype, asCDataType *result, asSNameSpace *implicitNamespace, bool isReturnType = false); int ParseTemplateDecl(const char *decl, asCString *name, asCArray &subtypeNames); - int ParseFunctionDeclaration(asCObjectType *type, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray *paramAutoHandles = 0, bool *returnAutoHandle = 0, asSNameSpace *ns = 0, asCScriptNode **listPattern = 0); + int ParseFunctionDeclaration(asCObjectType *type, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray *paramAutoHandles = 0, bool *returnAutoHandle = 0, asSNameSpace *ns = 0, asCScriptNode **outListPattern = 0, asCObjectType **outParentClass = 0); int ParseVariableDeclaration(const char *decl, asSNameSpace *implicitNamespace, asCString &outName, asSNameSpace *&outNamespace, asCDataType &outDt); int CheckNameConflict(const char *name, asCScriptNode *node, asCScriptCode *code, asSNameSpace *ns); - int CheckNameConflictMember(asCObjectType *type, const char *name, asCScriptNode *node, asCScriptCode *code, bool isProperty); + int CheckNameConflictMember(asCTypeInfo *type, const char *name, asCScriptNode *node, asCScriptCode *code, bool isProperty); #ifndef AS_NO_COMPILER int AddCode(const char *name, const char *code, int codeLength, int lineOffset, int sectionIdx, bool makeCopy); @@ -173,14 +173,16 @@ protected: int ValidateDefaultArgs(asCScriptCode *script, asCScriptNode *node, asCScriptFunction *func); asCString GetCleanExpressionString(asCScriptNode *n, asCScriptCode *file); - asSNameSpace *GetNameSpaceFromNode(asCScriptNode *node, asCScriptCode *script, asSNameSpace *implicitNs, asCScriptNode **next); - asSNameSpace *GetNameSpaceByString(const asCString &nsName, asSNameSpace *implicitNs, asCScriptNode *errNode, asCScriptCode *script, bool isRequired = true); + asSNameSpace *GetNameSpaceFromNode(asCScriptNode *node, asCScriptCode *script, asSNameSpace *implicitNs, asCScriptNode **next, asCObjectType **objType = 0); + asSNameSpace *GetNameSpaceByString(const asCString &nsName, asSNameSpace *implicitNs, asCScriptNode *errNode, asCScriptCode *script, asCTypeInfo **scopeType = 0, bool isRequired = true); asCString GetScopeFromNode(asCScriptNode *n, asCScriptCode *script, asCScriptNode **next = 0); + asCTypeInfo *GetType(const char *type, asSNameSpace *ns, asCObjectType *parentType); asCObjectType *GetObjectType(const char *type, asSNameSpace *ns); - asCScriptFunction *GetFuncDef(const char *type); - asCObjectType *GetObjectTypeFromTypesKnownByObject(const char *type, asCObjectType *currentType); - asCDataType CreateDataTypeFromNode(asCScriptNode *node, asCScriptCode *file, asSNameSpace *implicitNamespace, bool acceptHandleForScope = false, asCObjectType *currentType = 0); + asCFuncdefType *GetFuncDef(const char *type, asSNameSpace *ns, asCObjectType *parentType); + asCTypeInfo *GetTypeFromTypesKnownByObject(const char *type, asCObjectType *currentType); + asCDataType CreateDataTypeFromNode(asCScriptNode *node, asCScriptCode *file, asSNameSpace *implicitNamespace, bool acceptHandleForScope = false, asCObjectType *currentType = 0, bool reportError = true, bool *isValid = 0); + asCObjectType *GetTemplateInstanceFromNode(asCScriptNode *node, asCScriptCode *file, asCObjectType *templateType, asSNameSpace *implicitNamespace, asCObjectType *currentType, asCScriptNode **next = 0); asCDataType ModifyDataTypeFromNode(const asCDataType &type, asCScriptNode *node, asCScriptCode *file, asETypeModifiers *inOutFlag, bool *autoHandle); int numErrors; @@ -204,7 +206,7 @@ protected: void AddInterfaceFromMixinToClass(sClassDeclaration *decl, asCScriptNode *errNode, sMixinClass *mixin); int RegisterScriptFunctionFromNode(asCScriptNode *node, asCScriptCode *file, asCObjectType *object = 0, bool isInterface = false, bool isGlobalFunction = false, asSNameSpace *ns = 0, bool isExistingShared = false, bool isMixin = false); - int RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray ¶meterNames, asCArray ¶meterTypes, asCArray &inOutFlags, asCArray &defaultArgs, bool isConstMethod, bool isConstructor, bool isDestructor, bool isPrivate, bool isProtected, bool isOverride, bool isFinal, bool isShared); + int RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray ¶meterNames, asCArray ¶meterTypes, asCArray &inOutFlags, asCArray &defaultArgs, asSFunctionTraits funcTraits); int RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file, asCObjectType *object = 0, bool isInterface = false, bool isGlobalFunction = false, asSNameSpace *ns = 0, bool isExistingShared = false); int RegisterImportedFunction(int funcID, asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns); int RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns); @@ -212,12 +214,13 @@ protected: int RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns); int RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns); int RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns); - int RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns); + int RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns, asCObjectType *parent); asCScriptFunction *RegisterLambda(asCScriptNode *node, asCScriptCode *file, asCScriptFunction *funcDef, const asCString &name, asSNameSpace *ns); void CompleteFuncDef(sFuncDef *funcDef); void CompileInterfaces(); void CompileClasses(asUINT originalNumTempl); - void GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray ¶meterNames, asCArray ¶meterTypes, asCArray &inOutFlags, asCArray &defaultArgs, bool &isConstMethod, bool &isConstructor, bool &isDestructor, bool &isPrivate, bool &isProtected, bool &isOverride, bool &isFinal, bool &isShared, asSNameSpace *implicitNamespace); + void DetermineTypeRelations(); + void GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray ¶meterNames, asCArray ¶meterTypes, asCArray &inOutFlags, asCArray &defaultArgs, asSFunctionTraits &traits, asSNameSpace *implicitNamespace); bool DoesMethodExist(asCObjectType *objType, int methodId, asUINT *methodIndex = 0); void AddDefaultConstructor(asCObjectType *objType, asCScriptCode *file); asCObjectProperty *AddPropertyToClass(sClassDeclaration *c, const asCString &name, const asCDataType &type, bool isPrivate, bool isProtected, bool isInherited, asCScriptCode *file = 0, asCScriptNode *node = 0); @@ -227,7 +230,7 @@ protected: void RegisterNonTypesFromScript(asCScriptNode *node, asCScriptCode *script, asSNameSpace *ns); void CompileFunctions(); void CompileGlobalVariables(); - int GetEnumValueFromObjectType(asCObjectType *objType, const char *name, asCDataType &outDt, asDWORD &outValue); + int GetEnumValueFromType(asCEnumType *type, const char *name, asCDataType &outDt, asDWORD &outValue); int GetEnumValue(const char *name, asCDataType &outDt, asDWORD &outValue, asSNameSpace *ns); bool DoesTypeExist(const asCString &type); asCObjectProperty *GetObjectProperty(asCDataType &obj, const char *prop); diff --git a/lib/angelscript/source/as_bytecode.cpp b/lib/angelscript/source/as_bytecode.cpp index b0777d4f8..d16dbc201 100644 --- a/lib/angelscript/source/as_bytecode.cpp +++ b/lib/angelscript/source/as_bytecode.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -1045,7 +1045,7 @@ void asCByteCode::OptimizeLocally(const asCArray &tempVariableOffsets) short tempVar = last->wArg[0]; asCArray freedVars; - asCByteInstruction *instr = last->prev; + instr = last->prev; asASSERT( instr && instr->op == asBC_Block ); instr = instr->prev; while( instr && instr->op == asBC_FREE ) @@ -1164,6 +1164,12 @@ void asCByteCode::Optimize() DeleteInstruction(instr); instr = GoBack(DeleteInstruction(curr)); } + // LINE, VarDecl, LINE -> VarDecl, LINE + else if (instrOp == asBC_VarDecl && instr->next && instr->next->op == asBC_LINE ) + { + // Delete the first instruction + instr = GoBack(DeleteInstruction(curr)); + } // LINE, LINE -> LINE else if( instrOp == asBC_LINE ) { @@ -1390,6 +1396,7 @@ bool asCByteCode::IsTempRegUsed(asCByteInstruction *curr) curr->op == asBC_PopRPtr || curr->op == asBC_CALLSYS || curr->op == asBC_CALLBND || + curr->op == asBC_Thiscall1 || curr->op == asBC_SUSPEND || curr->op == asBC_ALLOC || curr->op == asBC_CpyVtoR4 || @@ -1444,7 +1451,8 @@ bool asCByteCode::IsSimpleExpression() instr->op == asBC_FREE || instr->op == asBC_CallPtr || instr->op == asBC_CALLINTF || - instr->op == asBC_CALLBND ) + instr->op == asBC_CALLBND || + instr->op == asBC_Thiscall1 ) return false; instr = instr->next; @@ -1536,7 +1544,7 @@ void asCByteCode::ExtractObjectVariableInfo(asCScriptFunction *outFunc) asSObjectVariableInfo info; info.programPos = pos; info.variableOffset = (short)instr->wArg[0]; - info.option = *(int*)ARG_DW(instr->arg); + info.option = (asEObjVarInfoOption)*(int*)ARG_DW(instr->arg); outFunc->scriptData->objVariableInfo.PushLast(info); } else if( instr->op == asBC_VarDecl ) @@ -2064,18 +2072,23 @@ void asCByteCode::PostProcess() } #ifdef AS_DEBUG -void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScriptFunction *func) +void asCByteCode::DebugOutput(const char *name, asCScriptFunction *func) { _mkdir("AS_DEBUG"); - asCString str = "AS_DEBUG/"; - str += name; + asCString path = "AS_DEBUG/"; + path += name; + + // Anonymous functions created from within class methods will contain :: as part of the name + // Replace :: with __ to avoid error when creating the file for debug output + for (asUINT n = 0; n < path.GetLength(); n++) + if (path[n] == ':') path[n] = '_'; #if _MSC_VER >= 1500 && !defined(AS_MARMALADE) FILE *file; - fopen_s(&file, str.AddressOf(), "w"); + fopen_s(&file, path.AddressOf(), "w"); #else - FILE *file = fopen(str.AddressOf(), "w"); + FILE *file = fopen(path.AddressOf(), "w"); #endif #if !defined(AS_XENON) // XBox 360: When running in DVD Emu, no write is allowed @@ -2186,14 +2199,7 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri switch( asBCInfo[instr->op].type ) { case asBCTYPE_W_ARG: - if( instr->op == asBC_STR ) - { - int id = asWORD(instr->wArg[0]); - const asCString &str = engine->GetConstantString(id); - fprintf(file, " %-8s %d (l:%ld s:\"%.10s\")\n", asBCInfo[instr->op].name, asWORD(instr->wArg[0]), (long int)str.GetLength(), str.AddressOf()); - } - else - fprintf(file, " %-8s %d\n", asBCInfo[instr->op].name, instr->wArg[0]); + fprintf(file, " %-8s %d\n", asBCInfo[instr->op].name, instr->wArg[0]); break; case asBCTYPE_wW_ARG: @@ -2237,8 +2243,8 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri case asBC_FuncPtr: { - asCScriptFunction *func = *(asCScriptFunction**)ARG_DW(instr->arg); - fprintf(file, " %-8s 0x%x (func:%s)\n", asBCInfo[instr->op].name, (asUINT)*ARG_DW(instr->arg), func->GetDeclaration()); + asCScriptFunction *f = *(asCScriptFunction**)ARG_DW(instr->arg); + fprintf(file, " %-8s 0x%x (func:%s)\n", asBCInfo[instr->op].name, (asUINT)*ARG_DW(instr->arg), f->GetDeclaration()); } break; @@ -2298,8 +2304,8 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri case asBC_FuncPtr: { - asCScriptFunction *func = *(asCScriptFunction**)ARG_QW(instr->arg); - fprintf(file, " %-8s 0x%x (func:%s)\n", asBCInfo[instr->op].name, (asUINT)*ARG_QW(instr->arg), func->GetDeclaration()); + asCScriptFunction *f = *(asCScriptFunction**)ARG_QW(instr->arg); + fprintf(file, " %-8s 0x%x (func:%s)\n", asBCInfo[instr->op].name, (asUINT)*ARG_QW(instr->arg), f->GetDeclaration()); } break; @@ -2345,8 +2351,8 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri if( instr->op == asBC_ALLOC ) { asCObjectType *ot = *(asCObjectType**)ARG_DW(instr->arg); - asCScriptFunction *func = engine->scriptFunctions[instr->wArg[0]]; - fprintf(file, " %-8s 0x%x, %d (type:%s, %s)\n", asBCInfo[instr->op].name, *(int*)ARG_DW(instr->arg), *(int*)(ARG_DW(instr->arg)+1), ot->GetName(), func ? func->GetDeclaration() : "{no func}"); + asCScriptFunction *f = engine->scriptFunctions[instr->wArg[0]]; + fprintf(file, " %-8s 0x%x, %d (type:%s, %s)\n", asBCInfo[instr->op].name, *(int*)ARG_DW(instr->arg), *(int*)(ARG_DW(instr->arg)+1), ot->GetName(), f ? f->GetDeclaration() : "{no func}"); } else fprintf(file, " %-8s %u, %d\n", asBCInfo[instr->op].name, *(int*)ARG_DW(instr->arg), *(int*)(ARG_DW(instr->arg)+1)); @@ -2360,19 +2366,19 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri if( instr->op == asBC_ALLOC ) { asCObjectType *ot = *(asCObjectType**)ARG_QW(instr->arg); - asCScriptFunction *func = engine->scriptFunctions[instr->wArg[0]]; -#ifdef __GNUC__ + asCScriptFunction *f = engine->scriptFunctions[instr->wArg[0]]; +#if defined(__GNUC__) && !defined(_MSC_VER) #ifdef AS_64BIT_PTR - fprintf(file, " %-8s 0x%lx, %d (type:%s, %s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName(), func ? func->GetDeclaration() : "{no func}"); + fprintf(file, " %-8s 0x%lx, %d (type:%s, %s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName(), f ? f->GetDeclaration() : "{no func}"); #else - fprintf(file, " %-8s 0x%llx, %d (type:%s, %s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName(), func ? func->GetDeclaration() : "{no func}"); + fprintf(file, " %-8s 0x%llx, %d (type:%s, %s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName(), f ? f->GetDeclaration() : "{no func}"); #endif #else - fprintf(file, " %-8s 0x%I64x, %d (type:%s, %s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName(), func ? func->GetDeclaration() : "{no func}"); + fprintf(file, " %-8s 0x%I64x, %d (type:%s, %s)\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2), ot->GetName(), f ? f->GetDeclaration() : "{no func}"); #endif } else -#ifdef __GNUC__ +#if defined(__GNUC__) && !defined(_MSC_VER) #ifdef AS_64BIT_PTR fprintf(file, " %-8s %lu, %d\n", asBCInfo[instr->op].name, *(asINT64*)ARG_QW(instr->arg), *(int*)(ARG_DW(instr->arg)+2)); #else diff --git a/lib/angelscript/source/as_bytecode.h b/lib/angelscript/source/as_bytecode.h index b1bb1127b..1c1067d7d 100644 --- a/lib/angelscript/source/as_bytecode.h +++ b/lib/angelscript/source/as_bytecode.h @@ -83,7 +83,7 @@ public: void PostProcess(); #ifdef AS_DEBUG - void DebugOutput(const char *name, asCScriptEngine *engine, asCScriptFunction *func); + void DebugOutput(const char *name, asCScriptFunction *func); #endif int GetLastInstr(); diff --git a/lib/angelscript/source/as_callfunc.cpp b/lib/angelscript/source/as_callfunc.cpp index 81095ab8b..00d04a9c1 100644 --- a/lib/angelscript/source/as_callfunc.cpp +++ b/lib/angelscript/source/as_callfunc.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -53,12 +53,12 @@ BEGIN_AS_NAMESPACE // describes the structure for class method pointers on Itanium and arm64 ABI // http://clang.llvm.org/doxygen/CodeGen_2ItaniumCXXABI_8cpp_source.html#l00937 -int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, void *objForThiscall, asSSystemFunctionInterface *internal) +int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, void *auxiliary, asSSystemFunctionInterface *internal) { memset(internal, 0, sizeof(asSSystemFunctionInterface)); - internal->func = ptr.ptr.f.func; - internal->objForThiscall = 0; + internal->func = ptr.ptr.f.func; + internal->auxiliary = 0; // Was a compatible calling convention specified? if( internal->func ) @@ -80,21 +80,26 @@ int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, internal->callConv = ICC_STDCALL; else if( base == asCALL_THISCALL_ASGLOBAL ) { - if( objForThiscall == 0 ) + if(auxiliary == 0) return asINVALID_ARG; - internal->objForThiscall = objForThiscall; - internal->callConv = ICC_THISCALL; + internal->auxiliary = auxiliary; + internal->callConv = ICC_THISCALL; // This is really a thiscall, so it is necessary to check for virtual method pointers base = asCALL_THISCALL; isMethod = true; } - else if( base == asCALL_GENERIC ) + else if (base == asCALL_GENERIC) + { internal->callConv = ICC_GENERIC_FUNC; + + // The auxiliary object is optional for generic calling convention + internal->auxiliary = auxiliary; + } else return asNOT_SUPPORTED; } - + if( isMethod ) { #ifndef AS_NO_CLASS_METHODS @@ -103,7 +108,7 @@ int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, internalCallConv thisCallConv; if( base == asCALL_THISCALL ) { - if( callConv != asCALL_THISCALL_ASGLOBAL && objForThiscall ) + if(callConv != asCALL_THISCALL_ASGLOBAL && auxiliary) return asINVALID_ARG; thisCallConv = ICC_THISCALL; @@ -113,10 +118,10 @@ int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, #ifdef AS_NO_THISCALL_FUNCTOR_METHOD return asNOT_SUPPORTED; #else - if( objForThiscall == 0 ) + if(auxiliary == 0) return asINVALID_ARG; - internal->objForThiscall = objForThiscall; + internal->auxiliary = auxiliary; if( base == asCALL_THISCALL_OBJFIRST ) thisCallConv = ICC_THISCALL_OBJFIRST; else //if( base == asCALL_THISCALL_OBJLAST ) @@ -151,8 +156,11 @@ int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, internal->callConv = ICC_CDECL_OBJLAST; else if( base == asCALL_CDECL_OBJFIRST ) internal->callConv = ICC_CDECL_OBJFIRST; - else if( base == asCALL_GENERIC ) + else if (base == asCALL_GENERIC) + { internal->callConv = ICC_GENERIC_METHOD; + internal->auxiliary = auxiliary; + } else return asNOT_SUPPORTED; } @@ -161,7 +169,7 @@ int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, } // This function should prepare system functions so that it will be faster to call them -int PrepareSystemFunctionGeneric(asCScriptFunction *func, asSSystemFunctionInterface *internal, asCScriptEngine * /*engine*/) +int PrepareSystemFunctionGeneric(asCScriptFunction *func, asSSystemFunctionInterface *internal, asCScriptEngine *engine) { asASSERT(internal->callConv == ICC_GENERIC_METHOD || internal->callConv == ICC_GENERIC_FUNC); @@ -175,17 +183,25 @@ int PrepareSystemFunctionGeneric(asCScriptFunction *func, asSSystemFunctionInter { asCDataType &dt = func->parameterTypes[n]; - if( dt.IsObject() && !dt.IsReference() ) + if( (dt.IsObject() || dt.IsFuncdef()) && !dt.IsReference() ) { - asSTypeBehaviour *beh = &dt.GetObjectType()->beh; - if( dt.GetObjectType()->flags & asOBJ_REF ) + if (dt.IsFuncdef()) { - asASSERT( (dt.GetObjectType()->flags & asOBJ_NOCOUNT) || beh->release ); + asSSystemFunctionInterface::SClean clean; + clean.op = 0; // call release + clean.ot = &engine->functionBehaviours; + clean.off = short(offset); + internal->cleanArgs.PushLast(clean); + } + else if( dt.GetTypeInfo()->flags & asOBJ_REF ) + { + asSTypeBehaviour *beh = &CastToObjectType(dt.GetTypeInfo())->beh; + asASSERT( (dt.GetTypeInfo()->flags & asOBJ_NOCOUNT) || beh->release ); if( beh->release ) { asSSystemFunctionInterface::SClean clean; clean.op = 0; // call release - clean.ot = dt.GetObjectType(); + clean.ot = CastToObjectType(dt.GetTypeInfo()); clean.off = short(offset); internal->cleanArgs.PushLast(clean); } @@ -194,10 +210,11 @@ int PrepareSystemFunctionGeneric(asCScriptFunction *func, asSSystemFunctionInter { asSSystemFunctionInterface::SClean clean; clean.op = 1; // call free - clean.ot = dt.GetObjectType(); + clean.ot = CastToObjectType(dt.GetTypeInfo()); clean.off = short(offset); // Call the destructor then free the memory + asSTypeBehaviour *beh = &CastToObjectType(dt.GetTypeInfo())->beh; if( beh->destruct ) clean.op = 2; // call destruct, then free @@ -222,7 +239,7 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i UNUSED_VAR(internal); UNUSED_VAR(engine); - // This should never happen, as when AS_MAX_PORTABILITY is on, all functions + // This should never happen, as when AS_MAX_PORTABILITY is on, all functions // are asCALL_GENERIC, which are prepared by PrepareSystemFunctionGeneric asASSERT(false); #else @@ -236,8 +253,8 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i // Registered types have special flags that determine how they are returned else if( func->returnType.IsObject() ) { - asDWORD objType = func->returnType.GetObjectType()->flags; - + asDWORD objType = func->returnType.GetTypeInfo()->flags; + // Only value types can be returned by value asASSERT( objType & asOBJ_VALUE ); @@ -247,7 +264,7 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, func->GetDeclarationStr().AddressOf()); asCString str; - str.Format(TXT_CANNOT_RET_TYPE_s_BY_VAL, func->returnType.GetObjectType()->name.AddressOf()); + str.Format(TXT_CANNOT_RET_TYPE_s_BY_VAL, func->returnType.GetTypeInfo()->name.AddressOf()); engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); engine->ConfigError(asINVALID_CONFIGURATION, 0, 0, 0); } @@ -282,7 +299,7 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i internal->hostReturnInMemory = false; internal->hostReturnSize = func->returnType.GetSizeInMemoryDWords(); #ifdef SPLIT_OBJS_BY_MEMBER_TYPES - if( func->returnType.GetObjectType()->flags & asOBJ_APP_CLASS_ALLFLOATS ) + if( func->returnType.GetTypeInfo()->flags & asOBJ_APP_CLASS_ALLFLOATS ) internal->hostReturnFloat = true; #endif } @@ -329,7 +346,7 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i // Ref: http://www.agner.org/optimize/calling_conventions.pdf // If the application informs that the class should be treated as all integers, then we allow it if( !internal->hostReturnInMemory && - !(func->returnType.GetObjectType()->flags & (asOBJ_APP_CLASS_ALLINTS | asOBJ_APP_CLASS_ALLFLOATS)) ) + !(func->returnType.GetTypeInfo()->flags & (asOBJ_APP_CLASS_ALLINTS | asOBJ_APP_CLASS_ALLFLOATS)) ) { engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, func->GetDeclarationStr().AddressOf()); @@ -405,12 +422,12 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i internal->takesObjByVal = true; // Can't pass objects by value unless the application type is informed - if( !(func->parameterTypes[n].GetObjectType()->flags & (asOBJ_APP_CLASS | asOBJ_APP_PRIMITIVE | asOBJ_APP_FLOAT | asOBJ_APP_ARRAY)) ) + if( !(func->parameterTypes[n].GetTypeInfo()->flags & (asOBJ_APP_CLASS | asOBJ_APP_PRIMITIVE | asOBJ_APP_FLOAT | asOBJ_APP_ARRAY)) ) { engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, func->GetDeclarationStr().AddressOf()); - + asCString str; - str.Format(TXT_CANNOT_PASS_TYPE_s_BY_VAL, func->parameterTypes[n].GetObjectType()->name.AddressOf()); + str.Format(TXT_CANNOT_PASS_TYPE_s_BY_VAL, func->parameterTypes[n].GetTypeInfo()->name.AddressOf()); engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); engine->ConfigError(asINVALID_CONFIGURATION, 0, 0, 0); } @@ -421,19 +438,19 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i // will be used depending on the memory layout of the object // Ref: http://www.x86-64.org/documentation/abi.pdf // Ref: http://www.agner.org/optimize/calling_conventions.pdf - if( + if( #ifdef COMPLEX_OBJS_PASSED_BY_REF - !(func->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK) && + !(func->parameterTypes[n].GetTypeInfo()->flags & COMPLEX_MASK) && #endif #ifdef LARGE_OBJS_PASS_BY_REF func->parameterTypes[n].GetSizeInMemoryDWords() < AS_LARGE_OBJ_MIN_SIZE && #endif - !(func->parameterTypes[n].GetObjectType()->flags & (asOBJ_APP_PRIMITIVE | asOBJ_APP_FLOAT | asOBJ_APP_CLASS_ALLINTS | asOBJ_APP_CLASS_ALLFLOATS)) ) + !(func->parameterTypes[n].GetTypeInfo()->flags & (asOBJ_APP_PRIMITIVE | asOBJ_APP_FLOAT | asOBJ_APP_CLASS_ALLINTS | asOBJ_APP_CLASS_ALLFLOATS)) ) { engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, func->GetDeclarationStr().AddressOf()); asCString str; - str.Format(TXT_DONT_SUPPORT_TYPE_s_BY_VAL, func->parameterTypes[n].GetObjectType()->name.AddressOf()); + str.Format(TXT_DONT_SUPPORT_TYPE_s_BY_VAL, func->parameterTypes[n].GetTypeInfo()->name.AddressOf()); engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); engine->ConfigError(asINVALID_CONFIGURATION, 0, 0, 0); } @@ -452,24 +469,24 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i #if defined(COMPLEX_OBJS_PASSED_BY_REF) || defined(AS_LARGE_OBJS_PASSED_BY_REF) bool needFree = false; #ifdef COMPLEX_OBJS_PASSED_BY_REF - if( dt.GetObjectType() && dt.GetObjectType()->flags & COMPLEX_MASK ) needFree = true; + if( dt.GetTypeInfo() && dt.GetTypeInfo()->flags & COMPLEX_MASK ) needFree = true; #endif #ifdef AS_LARGE_OBJS_PASSED_BY_REF if( dt.GetSizeInMemoryDWords() >= AS_LARGE_OBJ_MIN_SIZE ) needFree = true; #endif if( needFree && dt.IsObject() && - !dt.IsObjectHandle() && + !dt.IsObjectHandle() && !dt.IsReference() ) { asSSystemFunctionInterface::SClean clean; clean.op = 1; // call free - clean.ot = dt.GetObjectType(); + clean.ot = CastToObjectType(dt.GetTypeInfo()); clean.off = short(offset); #ifndef AS_CALLEE_DESTROY_OBJ_BY_VAL // If the called function doesn't destroy objects passed by value we must do so here - asSTypeBehaviour *beh = &dt.GetObjectType()->beh; + asSTypeBehaviour *beh = &CastToObjectType(dt.GetTypeInfo())->beh; if( beh->destruct ) clean.op = 2; // call destruct, then free #endif @@ -482,7 +499,10 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i { asSSystemFunctionInterface::SClean clean; clean.op = 0; // call release - clean.ot = dt.GetObjectType(); + if (dt.IsFuncdef()) + clean.ot = &engine->functionBehaviours; + else + clean.ot = CastToObjectType(dt.GetTypeInfo()); clean.off = short(offset); internal->cleanArgs.PushLast(clean); } @@ -533,7 +553,7 @@ int CallSystemFunction(int id, asCContext *context) // // Return value: // -// The function should return the value that is returned in registers. +// The function should return the value that is returned in registers. asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &retQW2, void *secondObj); @@ -553,16 +573,22 @@ int CallSystemFunction(int id, asCContext *context) void *retPointer = 0; int popSize = sysFunc->paramSize; + // TODO: clean-up: CallSystemFunctionNative should have two arguments for object pointers + // objForThiscall is the object pointer that should be used for the thiscall + // objForArg is the object pointer that should be passed as argument when using OBJFIRST or OBJLAST + + // Used to save two object pointers with THISCALL_OBJLAST or THISCALL_OBJFIRST + void *obj = 0; + void *secondObj = 0; + #ifdef AS_NO_THISCALL_FUNCTOR_METHOD - void *obj = 0; - void *secondObj = 0; if( callConv >= ICC_THISCALL ) { - if( sysFunc->objForThiscall ) + if(sysFunc->auxiliary) { // This class method is being called as if it is a global function - obj = sysFunc->objForThiscall; + obj = sysFunc->auxiliary; } else { @@ -593,13 +619,6 @@ int CallSystemFunction(int id, asCContext *context) } } #else - // TODO: clean-up: CallSystemFunctionNative should have two arguments for object pointers - // objForThiscall is the object pointer that should be used for the thiscall - // objForArg is the object pointer that should be passed as argument when using OBJFIRST or OBJLAST - - // Used to save two object pointers with THISCALL_OBJLAST or THISCALL_OBJFIRST - void *obj = 0; - void *secondObj = 0; if( callConv >= ICC_THISCALL ) { @@ -608,15 +627,15 @@ int CallSystemFunction(int id, asCContext *context) if( callConv >= ICC_THISCALL_OBJLAST ) { - asASSERT( sysFunc->objForThiscall != 0 ); - // This class method is being called as object method (sysFunc->objForThiscall must be set). - obj = sysFunc->objForThiscall; + asASSERT( sysFunc->auxiliary != 0 ); + // This class method is being called as object method (sysFunc->auxiliary must be set). + obj = sysFunc->auxiliary; continueCheckIndex = 1; } - else if( sysFunc->objForThiscall ) + else if(sysFunc->auxiliary) { // This class method is being called as if it is a global function - obj = sysFunc->objForThiscall; + obj = sysFunc->auxiliary; continueCheck = false; } @@ -667,14 +686,21 @@ int CallSystemFunction(int id, asCContext *context) popSize += AS_PTR_SIZE; args += AS_PTR_SIZE; - // When returning the value on the location allocated by the called + // When returning the value on the location allocated by the called // we shouldn't set the object type in the register context->m_regs.objectType = 0; } else { // Set the object type of the reference held in the register - context->m_regs.objectType = descr->returnType.GetObjectType(); + context->m_regs.objectType = descr->returnType.GetTypeInfo(); + } + + // For composition we need to add the offset and/or dereference the pointer + if(obj) + { + obj = (void*) ((char*) obj + sysFunc->compositeOffset); + if(sysFunc->isCompositeIndirect) obj = *((void**)obj); } context->m_callingSystemFunction = descr; @@ -682,10 +708,10 @@ int CallSystemFunction(int id, asCContext *context) #ifdef AS_NO_EXCEPTIONS retQW = CallSystemFunctionNative(context, descr, obj, args, sysFunc->hostReturnInMemory ? retPointer : 0, retQW2, secondObj); #else - // This try/catch block is to catch potential exception that may + // This try/catch block is to catch potential exception that may // be thrown by the registered function. The implementation of the // CallSystemFunctionNative() must make sure not to have any manual - // clean-up after the call to the real function, or that won't be + // clean-up after the call to the real function, or that won't be // executed in case of an exception. try { @@ -695,7 +721,7 @@ int CallSystemFunction(int id, asCContext *context) { cppException = true; - // Convert the exception to a script exception so the VM can + // Convert the exception to a script exception so the VM can // properly report the error to the application and then clean up context->SetException(TXT_EXCEPTION_CAUGHT); } @@ -703,7 +729,7 @@ int CallSystemFunction(int id, asCContext *context) context->m_callingSystemFunction = 0; // Store the returned value in our stack - if( descr->returnType.IsObject() && !descr->returnType.IsReference() ) + if( (descr->returnType.IsObject() || descr->returnType.IsFuncdef()) && !descr->returnType.IsReference() ) { if( descr->returnType.IsObjectHandle() ) { @@ -717,8 +743,8 @@ int CallSystemFunction(int id, asCContext *context) if( sysFunc->returnAutoHandle && context->m_regs.objectRegister ) { - asASSERT( !(descr->returnType.GetObjectType()->flags & asOBJ_NOCOUNT) ); - engine->CallObjectMethod(context->m_regs.objectRegister, descr->returnType.GetObjectType()->beh.addref); + asASSERT( !(descr->returnType.GetTypeInfo()->flags & asOBJ_NOCOUNT) ); + engine->CallObjectMethod(context->m_regs.objectRegister, CastToObjectType(descr->returnType.GetTypeInfo())->beh.addref); } } else @@ -754,12 +780,12 @@ int CallSystemFunction(int id, asCContext *context) if( context->m_status == asEXECUTION_EXCEPTION && !cppException ) { - // If the function raised a script exception it really shouldn't have - // initialized the object. However, as it is a soft exception there is + // If the function raised a script exception it really shouldn't have + // initialized the object. However, as it is a soft exception there is // no way for the application to not return a value, so instead we simply // destroy it here, to pretend it was never created. - if( descr->returnType.GetObjectType()->beh.destruct ) - engine->CallObjectMethod(retPointer, descr->returnType.GetObjectType()->beh.destruct); + if(CastToObjectType(descr->returnType.GetTypeInfo())->beh.destruct ) + engine->CallObjectMethod(retPointer, CastToObjectType(descr->returnType.GetTypeInfo())->beh.destruct); } } } @@ -833,7 +859,7 @@ int CallSystemFunction(int id, asCContext *context) // Skip the object pointer on the stack // TODO: runtime optimize: This check and increment should have been done in PrepareSystemFunction - if( callConv >= ICC_THISCALL && sysFunc->objForThiscall == 0 ) + if( callConv >= ICC_THISCALL && sysFunc->auxiliary == 0 ) args += AS_PTR_SIZE; asSSystemFunctionInterface::SClean *clean = sysFunc->cleanArgs.AddressOf(); @@ -848,14 +874,14 @@ int CallSystemFunction(int id, asCContext *context) *addr = 0; } } - else + else { asASSERT( clean->op == 1 || clean->op == 2 ); asASSERT( *addr ); if( clean->op == 2 ) engine->CallObjectMethod(*addr, clean->ot->beh.destruct); - + engine->CallFree(*addr); } } diff --git a/lib/angelscript/source/as_callfunc.h b/lib/angelscript/source/as_callfunc.h index dde7f72d7..c77a4d708 100644 --- a/lib/angelscript/source/as_callfunc.h +++ b/lib/angelscript/source/as_callfunc.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -49,7 +49,7 @@ class asCScriptFunction; class asCObjectType; struct asSSystemFunctionInterface; -int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, void *objForThiscall, asSSystemFunctionInterface *internal); +int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, void *auxiliary, asSSystemFunctionInterface *internal); int PrepareSystemFunctionGeneric(asCScriptFunction *func, asSSystemFunctionInterface *internal, asCScriptEngine *engine); @@ -59,7 +59,7 @@ int CallSystemFunction(int id, asCContext *context); inline asPWORD FuncPtrToUInt(asFUNCTION_t func) { - // A little trickery as the C++ standard doesn't allow direct + // A little trickery as the C++ standard doesn't allow direct // conversion between function pointer and data pointer union { asFUNCTION_t func; asPWORD idx; } u; u.func = func; @@ -108,7 +108,9 @@ struct asSSystemFunctionInterface bool takesObjByVal; asCArray paramAutoHandles; // TODO: Should be able to remove this array. Perhaps the flags can be stored together with the inOutFlags in asCScriptFunction? bool returnAutoHandle; - void *objForThiscall; + int compositeOffset; + bool isCompositeIndirect; + void *auxiliary; // can be used for functors, e.g. by asCALL_THISCALL_ASGLOBAL or asCALL_THISCALL_OBJFIRST struct SClean { @@ -118,7 +120,7 @@ struct asSSystemFunctionInterface }; asCArray cleanArgs; - asSSystemFunctionInterface() {} + asSSystemFunctionInterface() : func(0), baseOffset(0), callConv(ICC_GENERIC_FUNC), scriptReturnSize(0), hostReturnInMemory(false), hostReturnFloat(false), hostReturnSize(0), paramSize(0), takesObjByVal(false), returnAutoHandle(false), compositeOffset(0), isCompositeIndirect(false), auxiliary(0) {} asSSystemFunctionInterface(const asSSystemFunctionInterface &in) { @@ -127,19 +129,21 @@ struct asSSystemFunctionInterface asSSystemFunctionInterface &operator=(const asSSystemFunctionInterface &in) { - func = in.func; - baseOffset = in.baseOffset; - callConv = in.callConv; - scriptReturnSize = in.scriptReturnSize; - hostReturnInMemory = in.hostReturnInMemory; - hostReturnFloat = in.hostReturnFloat; - hostReturnSize = in.hostReturnSize; - paramSize = in.paramSize; - takesObjByVal = in.takesObjByVal; - paramAutoHandles = in.paramAutoHandles; - returnAutoHandle = in.returnAutoHandle; - objForThiscall = in.objForThiscall; - cleanArgs = in.cleanArgs; + func = in.func; + baseOffset = in.baseOffset; + callConv = in.callConv; + scriptReturnSize = in.scriptReturnSize; + hostReturnInMemory = in.hostReturnInMemory; + hostReturnFloat = in.hostReturnFloat; + hostReturnSize = in.hostReturnSize; + paramSize = in.paramSize; + takesObjByVal = in.takesObjByVal; + paramAutoHandles = in.paramAutoHandles; + returnAutoHandle = in.returnAutoHandle; + compositeOffset = in.compositeOffset; + isCompositeIndirect = in.isCompositeIndirect; + auxiliary = in.auxiliary; + cleanArgs = in.cleanArgs; return *this; } }; diff --git a/lib/angelscript/source/as_callfunc_arm.cpp b/lib/angelscript/source/as_callfunc_arm.cpp index a5d20355e..6d820702f 100644 --- a/lib/angelscript/source/as_callfunc_arm.cpp +++ b/lib/angelscript/source/as_callfunc_arm.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -150,7 +150,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() ) { #ifdef COMPLEX_OBJS_PASSED_BY_REF - if( descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK ) + if( descr->parameterTypes[n].GetTypeInfo()->flags & COMPLEX_MASK ) { paramBuffer[dpos++] = args[spos++]; paramSize++; @@ -159,7 +159,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, #endif { #if defined(AS_ANDROID) || defined(AS_LINUX) - if( (descr->parameterTypes[n].GetObjectType()->flags & asOBJ_APP_CLASS_ALIGN8) && + if( (descr->parameterTypes[n].GetTypeInfo()->flags & asOBJ_APP_CLASS_ALIGN8) && ((dpos & 1) == mask) ) { // 64 bit value align @@ -337,8 +337,8 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, if( sysFunc->hostReturnInMemory ) { // TODO: runtime optimize: This check should be done in PrepareSystemFunction - if ( !( descr->returnType.GetObjectType()->flags & COMPLEX_RETURN_MASK ) && - ( descr->returnType.GetObjectType()->flags & asOBJ_APP_CLASS_ALLFLOATS ) && + if ( !( descr->returnType.GetTypeInfo()->flags & COMPLEX_RETURN_MASK ) && + ( descr->returnType.GetTypeInfo()->flags & asOBJ_APP_CLASS_ALLFLOATS ) && descr->returnType.GetSizeInMemoryBytes() <= 8 ) callConv--; @@ -396,10 +396,10 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, { // TODO: runtime optimize: Declare a reference to descr->parameterTypes[n] so the array doesn't have to be access all the time if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() && - !(descr->parameterTypes[n].GetObjectType()->flags & asOBJ_APP_ARRAY) ) + !(descr->parameterTypes[n].GetTypeInfo()->flags & asOBJ_APP_ARRAY) ) { #ifdef COMPLEX_OBJS_PASSED_BY_REF - if( descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK ) + if( descr->parameterTypes[n].GetTypeInfo()->flags & COMPLEX_MASK ) { paramBuffer[dpos++] = args[spos++]; paramSize++; @@ -407,7 +407,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, else #endif { - if( (descr->parameterTypes[n].GetObjectType()->flags & asOBJ_APP_CLASS_ALIGN8) ) + if( (descr->parameterTypes[n].GetTypeInfo()->flags & asOBJ_APP_CLASS_ALIGN8) ) { if ( (dpos & 1) == mask ) { @@ -425,7 +425,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, } // Copy the object's memory to the buffer - if (descr->parameterTypes[n].GetObjectType()->flags & asOBJ_APP_CLASS_ALLFLOATS) + if (descr->parameterTypes[n].GetTypeInfo()->flags & asOBJ_APP_CLASS_ALLFLOATS) { int target = (freeFloatSlot > freeDoubleSlot) ? freeFloatSlot : freeDoubleSlot; @@ -645,8 +645,8 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, // TODO: runtime optimize: This should be identified with a flag determined in PrepareSystemFunction if ( !descr->returnType.IsObjectHandle() && !descr->returnType.IsReference() && - !(descr->returnType.GetObjectType()->flags & COMPLEX_RETURN_MASK) && - (descr->returnType.GetObjectType()->flags & asOBJ_APP_CLASS_ALLFLOATS) ) + !(descr->returnType.GetTypeInfo()->flags & COMPLEX_RETURN_MASK) && + (descr->returnType.GetTypeInfo()->flags & asOBJ_APP_CLASS_ALLFLOATS) ) memcpy( retPointer, ¶mBuffer[VFP_OFFSET], descr->returnType.GetSizeInMemoryBytes() ); } diff --git a/lib/angelscript/source/as_callfunc_arm_gcc.S b/lib/angelscript/source/as_callfunc_arm_gcc.S index 3ce5566a4..a311ee773 100644 --- a/lib/angelscript/source/as_callfunc_arm_gcc.S +++ b/lib/angelscript/source/as_callfunc_arm_gcc.S @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2016 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -717,13 +717,14 @@ nomoreargsarmFuncR0R1: #endif /* hard float abi */ +#endif /* arm */ + #if defined(__linux__) && defined(__ELF__) -/* ref: http://hardened.gentoo.org/gnu-stack.xml */ +/* ref: http://hardened.gentoo.org/gnu-stack.xml + ref: https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart */ .section .note.GNU-stack,"",%progbits #endif -#endif /* arm */ - #endif /* !AS_MAX_PORTABILITY */ diff --git a/lib/angelscript/source/as_callfunc_mips.cpp b/lib/angelscript/source/as_callfunc_mips.cpp index 0b2e3b4fc..be7d18952 100644 --- a/lib/angelscript/source/as_callfunc_mips.cpp +++ b/lib/angelscript/source/as_callfunc_mips.cpp @@ -135,7 +135,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, asCDataType ¶mType = descr->parameterTypes[n]; if( paramType.IsObject() && !paramType.IsObjectHandle() && !paramType.IsReference() ) { - if( paramType.GetObjectType()->flags & COMPLEX_MASK ) + if( paramType.GetTypeInfo()->flags & COMPLEX_MASK ) { // The object is passed by reference argBuffer[argOffset++] = args[spos++]; @@ -143,7 +143,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, else { // Ensure 8byte alignment for classes that need it - if( (paramType.GetObjectType()->flags & asOBJ_APP_CLASS_ALIGN8) && (argOffset & 1) ) + if( (paramType.GetTypeInfo()->flags & asOBJ_APP_CLASS_ALIGN8) && (argOffset & 1) ) argOffset++; // Copy the object's memory to the buffer @@ -557,7 +557,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() ) { #ifdef COMPLEX_OBJS_PASSED_BY_REF - if( descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK ) + if( descr->parameterTypes[n].GetTypeInfo()->flags & COMPLEX_MASK ) { paramBuffer[dpos++] = args[spos++]; paramSize++; diff --git a/lib/angelscript/source/as_callfunc_ppc.cpp b/lib/angelscript/source/as_callfunc_ppc.cpp index 32a73f8f8..053221fe9 100644 --- a/lib/angelscript/source/as_callfunc_ppc.cpp +++ b/lib/angelscript/source/as_callfunc_ppc.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -576,7 +576,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() ) { #ifdef COMPLEX_OBJS_PASSED_BY_REF - if( descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK ) + if( descr->parameterTypes[n].GetTypeInfo()->flags & COMPLEX_MASK ) { argsType[a++] = ppcINTARG; paramBuffer[dpos++] = args[spos++]; diff --git a/lib/angelscript/source/as_callfunc_ppc_64.cpp b/lib/angelscript/source/as_callfunc_ppc_64.cpp index a2c62f2b9..275f6152b 100644 --- a/lib/angelscript/source/as_callfunc_ppc_64.cpp +++ b/lib/angelscript/source/as_callfunc_ppc_64.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2016 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -41,6 +41,10 @@ #ifndef AS_MAX_PORTABILITY #ifdef AS_PPC_64 +#if AS_PTR_SIZE == 2 +// TODO: Add support for PPC 64bit platforms with 64bit pointers, for example Linux PPC64 (big endian) and PPC64 (little endian) +#error This code has not been prepared for PPC with 64bit pointers. Most likely the ABI is different +#else #include "as_callfunc.h" #include "as_scriptengine.h" @@ -666,10 +670,10 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ ) { if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() && - !(descr->parameterTypes[n].GetObjectType()->flags & asOBJ_APP_ARRAY) ) + !(descr->parameterTypes[n].GetTypeInfo()->flags & asOBJ_APP_ARRAY) ) { #ifdef COMPLEX_OBJS_PASSED_BY_REF - if( descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK ) + if( descr->parameterTypes[n].GetTypeInfo()->flags & COMPLEX_MASK ) { paramBuffer[dpos++] = args[spos++]; ++paramSize; @@ -763,6 +767,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, END_AS_NAMESPACE +#endif // AS_PTR_SIZE == 2 #endif // AS_PPC_64 #endif // AS_MAX_PORTABILITY diff --git a/lib/angelscript/source/as_callfunc_sh4.cpp b/lib/angelscript/source/as_callfunc_sh4.cpp index 2fb4ff68f..b24be9a54 100644 --- a/lib/angelscript/source/as_callfunc_sh4.cpp +++ b/lib/angelscript/source/as_callfunc_sh4.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -313,7 +313,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() ) { #ifdef COMPLEX_OBJS_PASSED_BY_REF - if( descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK ) + if( descr->parameterTypes[n].GetTypeInfo()->flags & COMPLEX_MASK ) { paramBuffer[dpos++] = args[spos++]; paramSize++; diff --git a/lib/angelscript/source/as_callfunc_x64_gcc.cpp b/lib/angelscript/source/as_callfunc_x64_gcc.cpp index e05ae986f..ad6c27fb6 100644 --- a/lib/angelscript/source/as_callfunc_x64_gcc.cpp +++ b/lib/angelscript/source/as_callfunc_x64_gcc.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -157,7 +157,7 @@ static asQWORD __attribute__((noinline)) X64_CallFunction(const asQWORD *args, i " movq %%rdx, %4 \n" "endcall: \n" - : : "r" ((asQWORD)cnt), "r" (args), "r" (func), "m" (retQW1), "m" (retQW2), "m" (returnFloat) + : : "g" ((asQWORD)cnt), "g" (args), "g" (func), "m" (retQW1), "m" (retQW2), "m" (returnFloat) : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%rdi", "%rsi", "%rax", "%rdx", "%rcx", "%r8", "%r9", "%r10", "%r11", "%r15"); @@ -345,7 +345,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, else { // An object is being passed by value - if( (parmType.GetObjectType()->flags & COMPLEX_MASK) || + if( (parmType.GetTypeInfo()->flags & COMPLEX_MASK) || parmType.GetSizeInMemoryDWords() > 4 ) { // Copy the address of the object @@ -353,8 +353,8 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, memcpy(paramBuffer + argIndex, stack_pointer, sizeof(asQWORD)); argIndex++; } - else if( (parmType.GetObjectType()->flags & asOBJ_APP_CLASS_ALLINTS) || - (parmType.GetObjectType()->flags & asOBJ_APP_PRIMITIVE) ) + else if( (parmType.GetTypeInfo()->flags & asOBJ_APP_CLASS_ALLINTS) || + (parmType.GetTypeInfo()->flags & asOBJ_APP_PRIMITIVE) ) { // Copy the value of the object if( parmType.GetSizeInMemoryDWords() > 2 ) @@ -373,8 +373,8 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, // Delete the original memory engine->CallFree(*(void**)stack_pointer); } - else if( (parmType.GetObjectType()->flags & asOBJ_APP_CLASS_ALLFLOATS) || - (parmType.GetObjectType()->flags & asOBJ_APP_FLOAT) ) + else if( (parmType.GetTypeInfo()->flags & asOBJ_APP_CLASS_ALLFLOATS) || + (parmType.GetTypeInfo()->flags & asOBJ_APP_FLOAT) ) { // Copy the value of the object if( parmType.GetSizeInMemoryDWords() > 2 ) diff --git a/lib/angelscript/source/as_callfunc_x64_mingw.cpp b/lib/angelscript/source/as_callfunc_x64_mingw.cpp index 35e775fe9..1c5bdb552 100644 --- a/lib/angelscript/source/as_callfunc_x64_mingw.cpp +++ b/lib/angelscript/source/as_callfunc_x64_mingw.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -248,7 +248,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() ) { if( descr->parameterTypes[n].GetSizeInMemoryDWords() >= AS_LARGE_OBJ_MIN_SIZE || - (descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK) ) + (descr->parameterTypes[n].GetTypeInfo()->flags & COMPLEX_MASK) ) { allArgBuffer[dpos++] = *(asQWORD*)&args[spos]; spos += AS_PTR_SIZE; diff --git a/lib/angelscript/source/as_callfunc_x64_msvc.cpp b/lib/angelscript/source/as_callfunc_x64_msvc.cpp index 84b96c2dd..8af5adc01 100644 --- a/lib/angelscript/source/as_callfunc_x64_msvc.cpp +++ b/lib/angelscript/source/as_callfunc_x64_msvc.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -119,7 +119,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, if( dt.IsObject() && !dt.IsObjectHandle() && !dt.IsReference() ) { if( dt.GetSizeInMemoryDWords() >= AS_LARGE_OBJ_MIN_SIZE || - (dt.GetObjectType()->flags & COMPLEX_MASK) ) + (dt.GetTypeInfo()->flags & COMPLEX_MASK) ) { allArgBuffer[dpos++] = *(asQWORD*)&args[spos]; spos += AS_PTR_SIZE; diff --git a/lib/angelscript/source/as_callfunc_x86.cpp b/lib/angelscript/source/as_callfunc_x86.cpp index d6f50db81..0ac690ed7 100644 --- a/lib/angelscript/source/as_callfunc_x86.cpp +++ b/lib/angelscript/source/as_callfunc_x86.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2016 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -126,7 +126,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() ) { #ifdef COMPLEX_OBJS_PASSED_BY_REF - if( descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK ) + if( descr->parameterTypes[n].GetTypeInfo()->flags & COMPLEX_MASK ) { paramBuffer[dpos++] = args[spos++]; paramSize++; @@ -340,6 +340,17 @@ endcopy: volatile asPWORD a[] = {asPWORD(args), asPWORD(paramSize), asPWORD(func)}; asm __volatile__( +#ifdef __OPTIMIZE__ + // When compiled with optimizations the stack unwind doesn't work properly, + // causing exceptions to crash the application. By adding this prologue + // and the epilogue below, the stack unwind works as it should. + // TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below + "pushl %%ebp \n" + ".cfi_adjust_cfa_offset 4 \n" + ".cfi_rel_offset ebp, 0 \n" + "movl %%esp, %%ebp \n" + ".cfi_def_cfa_register ebp \n" +#endif _S(CLEAR_FPU_STACK) "\n" "pushl %%ebx \n" "movl %%edx, %%ebx \n" @@ -374,7 +385,14 @@ endcopy: // Pop the alignment bytes "popl %%esp \n" "popl %%ebx \n" - +#ifdef __OPTIMIZE__ + // Epilogue + "movl %%ebp, %%esp \n" + ".cfi_def_cfa_register esp \n" + "popl %%ebp \n" + ".cfi_adjust_cfa_offset -4 \n" + ".cfi_restore ebp \n" +#endif // Copy EAX:EDX to retQW. As the stack pointer has been // restored it is now safe to access the local variable "leal %1, %%ecx \n" @@ -444,6 +462,17 @@ endcopy: volatile asPWORD a[] = {asPWORD(obj), asPWORD(args), asPWORD(paramSize), asPWORD(func)}; asm __volatile__ ( +#ifdef __OPTIMIZE__ + // When compiled with optimizations the stack unwind doesn't work properly, + // causing exceptions to crash the application. By adding this prologue + // and the epilogue below, the stack unwind works as it should. + // TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below + "pushl %%ebp \n" + ".cfi_adjust_cfa_offset 4 \n" + ".cfi_rel_offset ebp, 0 \n" + "movl %%esp, %%ebp \n" + ".cfi_def_cfa_register ebp \n" +#endif _S(CLEAR_FPU_STACK) "\n" "pushl %%ebx \n" "movl %%edx, %%ebx \n" @@ -479,7 +508,14 @@ endcopy: // Pop the alignment bytes "popl %%esp \n" "popl %%ebx \n" - +#ifdef __OPTIMIZE__ + // Epilogue + "movl %%ebp, %%esp \n" + ".cfi_def_cfa_register esp \n" + "popl %%ebp \n" + ".cfi_adjust_cfa_offset -4 \n" + ".cfi_restore ebp \n" +#endif // Copy EAX:EDX to retQW. As the stack pointer has been // restored it is now safe to access the local variable "leal %1, %%ecx \n" @@ -549,6 +585,17 @@ endcopy: volatile asPWORD a[] = {asPWORD(obj), asPWORD(args), asPWORD(paramSize), asPWORD(func)}; asm __volatile__ ( +#ifdef __OPTIMIZE__ + // When compiled with optimizations the stack unwind doesn't work properly, + // causing exceptions to crash the application. By adding this prologue + // and the epilogue below, the stack unwind works as it should. + // TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below + "pushl %%ebp \n" + ".cfi_adjust_cfa_offset 4 \n" + ".cfi_rel_offset ebp, 0 \n" + "movl %%esp, %%ebp \n" + ".cfi_def_cfa_register ebp \n" +#endif _S(CLEAR_FPU_STACK) "\n" "pushl %%ebx \n" "movl %%edx, %%ebx \n" @@ -584,7 +631,14 @@ endcopy: // Pop the alignment bytes "popl %%esp \n" "popl %%ebx \n" - +#ifdef __OPTIMIZE__ + // Epilogue + "movl %%ebp, %%esp \n" + ".cfi_def_cfa_register esp \n" + "popl %%ebp \n" + ".cfi_adjust_cfa_offset -4 \n" + ".cfi_restore ebp \n" +#endif // Copy EAX:EDX to retQW. As the stack pointer has been // restored it is now safe to access the local variable "leal %1, %%ecx \n" @@ -663,6 +717,17 @@ endcopy: volatile asPWORD a[] = {asPWORD(obj), asPWORD(args), asPWORD(paramSize), asPWORD(func), asPWORD(retPtr)}; asm __volatile__ ( +#ifdef __OPTIMIZE__ + // When compiled with optimizations the stack unwind doesn't work properly, + // causing exceptions to crash the application. By adding this prologue + // and the epilogue below, the stack unwind works as it should. + // TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below + "pushl %%ebp \n" + ".cfi_adjust_cfa_offset 4 \n" + ".cfi_rel_offset ebp, 0 \n" + "movl %%esp, %%ebp \n" + ".cfi_def_cfa_register ebp \n" +#endif _S(CLEAR_FPU_STACK) "\n" "pushl %%ebx \n" "movl %%edx, %%ebx \n" @@ -702,7 +767,14 @@ endcopy: // Pop the alignment bytes "popl %%esp \n" "popl %%ebx \n" - +#ifdef __OPTIMIZE__ + // Epilogue + "movl %%ebp, %%esp \n" + ".cfi_def_cfa_register esp \n" + "popl %%ebp \n" + ".cfi_adjust_cfa_offset -4 \n" + ".cfi_restore ebp \n" +#endif // Copy EAX:EDX to retQW. As the stack pointer has been // restored it is now safe to access the local variable "leal %1, %%ecx \n" @@ -777,6 +849,17 @@ endcopy: volatile asPWORD a[] = {asPWORD(args), asPWORD(paramSize), asPWORD(func), asPWORD(retPtr)}; asm __volatile__ ( +#ifdef __OPTIMIZE__ + // When compiled with optimizations the stack unwind doesn't work properly, + // causing exceptions to crash the application. By adding this prologue + // and the epilogue below, the stack unwind works as it should. + // TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below + "pushl %%ebp \n" + ".cfi_adjust_cfa_offset 4 \n" + ".cfi_rel_offset ebp, 0 \n" + "movl %%esp, %%ebp \n" + ".cfi_def_cfa_register ebp \n" +#endif _S(CLEAR_FPU_STACK) "\n" "pushl %%ebx \n" "movl %%edx, %%ebx \n" @@ -813,7 +896,14 @@ endcopy: // Pop the alignment bytes "popl %%esp \n" "popl %%ebx \n" - +#ifdef __OPTIMIZE__ + // Epilogue + "movl %%ebp, %%esp \n" + ".cfi_def_cfa_register esp \n" + "popl %%ebp \n" + ".cfi_adjust_cfa_offset -4 \n" + ".cfi_restore ebp \n" +#endif // Copy EAX:EDX to retQW. As the stack pointer has been // restored it is now safe to access the local variable "leal %1, %%ecx \n" @@ -890,6 +980,17 @@ endcopy: volatile asPWORD a[] = {asPWORD(obj), asPWORD(args), asPWORD(paramSize), asPWORD(func), asPWORD(retPtr)}; asm __volatile__ ( +#ifdef __OPTIMIZE__ + // When compiled with optimizations the stack unwind doesn't work properly, + // causing exceptions to crash the application. By adding this prologue + // and the epilogue below, the stack unwind works as it should. + // TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below + "pushl %%ebp \n" + ".cfi_adjust_cfa_offset 4 \n" + ".cfi_rel_offset ebp, 0 \n" + "movl %%esp, %%ebp \n" + ".cfi_def_cfa_register ebp \n" +#endif _S(CLEAR_FPU_STACK) "\n" "pushl %%ebx \n" "movl %%edx, %%ebx \n" @@ -929,7 +1030,14 @@ endcopy: // Pop the alignment bytes "popl %%esp \n" "popl %%ebx \n" - +#ifdef __OPTIMIZE__ + // Epilogue + "movl %%ebp, %%esp \n" + ".cfi_def_cfa_register esp \n" + "popl %%ebp \n" + ".cfi_adjust_cfa_offset -4 \n" + ".cfi_restore ebp \n" +#endif // Copy EAX:EDX to retQW. As the stack pointer has been // restored it is now safe to access the local variable "leal %1, %%ecx \n" @@ -994,6 +1102,17 @@ endcopy: volatile asPWORD a[] = {asPWORD(args), asPWORD(paramSize), asPWORD(func)}; asm __volatile__ ( +#ifdef __OPTIMIZE__ + // When compiled with optimizations the stack unwind doesn't work properly, + // causing exceptions to crash the application. By adding this prologue + // and the epilogue below, the stack unwind works as it should. + // TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below + "pushl %%ebp \n" + ".cfi_adjust_cfa_offset 4 \n" + ".cfi_rel_offset ebp, 0 \n" + "movl %%esp, %%ebp \n" + ".cfi_def_cfa_register ebp \n" +#endif _S(CLEAR_FPU_STACK) "\n" "pushl %%ebx \n" "movl %%edx, %%ebx \n" @@ -1026,7 +1145,14 @@ endcopy: // Pop the alignment bytes "popl %%esp \n" "popl %%ebx \n" - +#ifdef __OPTIMIZE__ + // Epilogue + "movl %%ebp, %%esp \n" + ".cfi_def_cfa_register esp \n" + "popl %%ebp \n" + ".cfi_adjust_cfa_offset -4 \n" + ".cfi_restore ebp \n" +#endif // Copy EAX:EDX to retQW. As the stack pointer has been // restored it is now safe to access the local variable "leal %1, %%ecx \n" @@ -1107,6 +1233,17 @@ endcopy: volatile asPWORD a[] = {asPWORD(obj), asPWORD(args), asPWORD(paramSize), asPWORD(func)}; asm __volatile__ ( +#ifdef __OPTIMIZE__ + // When compiled with optimizations the stack unwind doesn't work properly, + // causing exceptions to crash the application. By adding this prologue + // and the epilogue below, the stack unwind works as it should. + // TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below + "pushl %%ebp \n" + ".cfi_adjust_cfa_offset 4 \n" + ".cfi_rel_offset ebp, 0 \n" + "movl %%esp, %%ebp \n" + ".cfi_def_cfa_register ebp \n" +#endif _S(CLEAR_FPU_STACK) "\n" "pushl %%ebx \n" "movl %%edx, %%ebx \n" @@ -1148,7 +1285,14 @@ endcopy: // Pop the alignment bytes "popl %%esp \n" "popl %%ebx \n" - +#ifdef __OPTIMIZE__ + // Epilogue + "movl %%ebp, %%esp \n" + ".cfi_def_cfa_register esp \n" + "popl %%ebp \n" + ".cfi_adjust_cfa_offset -4 \n" + ".cfi_restore ebp \n" +#endif // Copy EAX:EDX to retQW. As the stack pointer has been // restored it is now safe to access the local variable "leal %1, %%ecx \n" @@ -1236,6 +1380,17 @@ endcopy: volatile asPWORD a[] = {asPWORD(obj), asPWORD(args), asPWORD(paramSize), asPWORD(func), asPWORD(retPtr)}; asm __volatile__ ( +#ifdef __OPTIMIZE__ + // When compiled with optimizations the stack unwind doesn't work properly, + // causing exceptions to crash the application. By adding this prologue + // and the epilogue below, the stack unwind works as it should. + // TODO: runtime optimize: The prologue/epilogue shouldn't be needed if the correct cfi directives are used below + "pushl %%ebp \n" + ".cfi_adjust_cfa_offset 4 \n" + ".cfi_rel_offset ebp, 0 \n" + "movl %%esp, %%ebp \n" + ".cfi_def_cfa_register ebp \n" +#endif _S(CLEAR_FPU_STACK) "\n" "pushl %%ebx \n" "movl %%edx, %%ebx \n" @@ -1290,7 +1445,14 @@ endcopy: // Pop the alignment bytes "popl %%esp \n" "popl %%ebx \n" - +#ifdef __OPTIMIZE__ + // Epilogue + "movl %%ebp, %%esp \n" + ".cfi_def_cfa_register esp \n" + "popl %%ebp \n" + ".cfi_adjust_cfa_offset -4 \n" + ".cfi_restore ebp \n" +#endif // Copy EAX:EDX to retQW. As the stack pointer has been // restored it is now safe to access the local variable "leal %1, %%ecx \n" diff --git a/lib/angelscript/source/as_callfunc_xenon.cpp b/lib/angelscript/source/as_callfunc_xenon.cpp index aaa4d8586..c52055e99 100644 --- a/lib/angelscript/source/as_callfunc_xenon.cpp +++ b/lib/angelscript/source/as_callfunc_xenon.cpp @@ -552,7 +552,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, !descr->parameterTypes[n].IsReference() ) { #ifdef COMPLEX_OBJS_PASSED_BY_REF - if( descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK ) + if( descr->parameterTypes[n].GetTypeInfo()->flags & COMPLEX_MASK ) { paramBuffer[dpos++] = args[spos++]; paramSize++; diff --git a/lib/angelscript/source/as_compiler.cpp b/lib/angelscript/source/as_compiler.cpp index 337e209df..e0f487c73 100644 --- a/lib/angelscript/source/as_compiler.cpp +++ b/lib/angelscript/source/as_compiler.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -64,7 +64,7 @@ BEGIN_AS_NAMESPACE -// TODO: I must correct the interpretation of a references to objects in the compiler. +// TODO: I must correct the interpretation of a reference to objects in the compiler. // A reference should mean that a pointer to the object is on the stack. // No expression should end up as non-references to objects, as the actual object is // never put on the stack. @@ -96,14 +96,20 @@ asCCompiler::~asCCompiler() asDELETE(var,asCVariableScope); } + + // Clean up all the string constants that were allocated. By now the script + // functions that were compiled successfully already holds their own references + for (asUINT n = 0; n < usedStringConstants.GetLength(); n++) + engine->stringFactory->ReleaseStringConstant(usedStringConstants[n]); + usedStringConstants.SetLength(0); } -void asCCompiler::Reset(asCBuilder *builder, asCScriptCode *script, asCScriptFunction *outFunc) +void asCCompiler::Reset(asCBuilder *in_builder, asCScriptCode *in_script, asCScriptFunction *in_outFunc) { - this->builder = builder; - this->engine = builder->engine; - this->script = script; - this->outFunc = outFunc; + this->builder = in_builder; + this->engine = in_builder->engine; + this->script = in_script; + this->outFunc = in_outFunc; hasCompileErrors = false; @@ -121,11 +127,11 @@ void asCCompiler::Reset(asCBuilder *builder, asCScriptCode *script, asCScriptFun byteCode.ClearAll(); } -int asCCompiler::CompileDefaultConstructor(asCBuilder *builder, asCScriptCode *script, asCScriptNode *node, asCScriptFunction *outFunc, sClassDeclaration *classDecl) +int asCCompiler::CompileDefaultConstructor(asCBuilder *in_builder, asCScriptCode *in_script, asCScriptNode *in_node, asCScriptFunction *in_outFunc, sClassDeclaration *in_classDecl) { - Reset(builder, script, outFunc); + Reset(in_builder, in_script, in_outFunc); - m_classDecl = classDecl; + m_classDecl = in_classDecl; // Insert a JitEntry at the start of the function for JIT compilers byteCode.InstrPTR(asBC_JitEntry, 0); @@ -144,7 +150,7 @@ int asCCompiler::CompileDefaultConstructor(asCBuilder *builder, asCScriptCode *s { // Make sure the base class really has a default constructor if( outFunc->objectType->derivedFrom->beh.construct == 0 ) - Error(TEXT_BASE_DOESNT_HAVE_DEF_CONSTR, node); + Error(TEXT_BASE_DOESNT_HAVE_DEF_CONSTR, in_node); // Call the base class' default constructor byteCode.InstrSHORT(asBC_PSF, 0); @@ -172,21 +178,21 @@ int asCCompiler::CompileDefaultConstructor(asCBuilder *builder, asCScriptCode *s #ifdef AS_DEBUG // DEBUG: output byte code - byteCode.DebugOutput(("__" + outFunc->objectType->name + "_" + outFunc->name + "__defconstr.txt").AddressOf(), engine, outFunc); + byteCode.DebugOutput(("__" + outFunc->objectType->name + "_" + outFunc->name + "__defconstr.txt").AddressOf(), in_outFunc); #endif return 0; } -int asCCompiler::CompileFactory(asCBuilder *builder, asCScriptCode *script, asCScriptFunction *outFunc) +int asCCompiler::CompileFactory(asCBuilder *in_builder, asCScriptCode *in_script, asCScriptFunction *in_outFunc) { - Reset(builder, script, outFunc); + Reset(in_builder, in_script, in_outFunc); // Insert a JitEntry at the start of the function for JIT compilers byteCode.InstrPTR(asBC_JitEntry, 0); // Find the corresponding constructor - asCDataType dt = asCDataType::CreateObject(outFunc->returnType.GetObjectType(), false); + asCDataType dt = asCDataType::CreateType(outFunc->returnType.GetTypeInfo(), false); int constructor = 0; for( unsigned int n = 0; n < dt.GetBehaviour()->factories.GetLength(); n++ ) { @@ -230,7 +236,7 @@ int asCCompiler::CompileFactory(asCBuilder *builder, asCScriptCode *script, asCS } int argDwords = (int)outFunc->GetSpaceNeededForArguments(); - byteCode.Alloc(asBC_ALLOC, dt.GetObjectType(), constructor, argDwords + AS_PTR_SIZE); + byteCode.Alloc(asBC_ALLOC, dt.GetTypeInfo(), constructor, argDwords + AS_PTR_SIZE); // Return a handle to the newly created object byteCode.InstrSHORT(asBC_LOADOBJ, (short)varOffset); @@ -269,12 +275,11 @@ void asCCompiler::FinalizeFunction() // Start with the variables allocated on the heap, and then the ones allocated on the stack for( n = 0; n < variableAllocations.GetLength(); n++ ) { - if( variableAllocations[n].IsObject() && !variableAllocations[n].IsReference() ) + if( (variableAllocations[n].IsObject() || variableAllocations[n].IsFuncdef()) && !variableAllocations[n].IsReference() ) { if( variableIsOnHeap[n] ) { - outFunc->scriptData->objVariableTypes.PushLast(variableAllocations[n].GetObjectType()); - outFunc->scriptData->funcVariableTypes.PushLast(variableAllocations[n].GetFuncDef()); + outFunc->scriptData->objVariableTypes.PushLast(variableAllocations[n].GetTypeInfo()); outFunc->scriptData->objVariablePos.PushLast(GetVariableOffset(n)); } } @@ -282,12 +287,11 @@ void asCCompiler::FinalizeFunction() outFunc->scriptData->objVariablesOnHeap = asUINT(outFunc->scriptData->objVariablePos.GetLength()); for( n = 0; n < variableAllocations.GetLength(); n++ ) { - if( variableAllocations[n].IsObject() && !variableAllocations[n].IsReference() ) + if( (variableAllocations[n].IsObject() || variableAllocations[n].IsFuncdef()) && !variableAllocations[n].IsReference() ) { if( !variableIsOnHeap[n] ) { - outFunc->scriptData->objVariableTypes.PushLast(variableAllocations[n].GetObjectType()); - outFunc->scriptData->funcVariableTypes.PushLast(variableAllocations[n].GetFuncDef()); + outFunc->scriptData->objVariableTypes.PushLast(variableAllocations[n].GetTypeInfo()); outFunc->scriptData->objVariablePos.PushLast(GetVariableOffset(n)); } } @@ -413,7 +417,7 @@ int asCCompiler::SetupParametersAndReturnVariable(asCArray ¶meter return stackPos; } -void asCCompiler::CompileMemberInitialization(asCByteCode *byteCode, bool onlyDefaults) +void asCCompiler::CompileMemberInitialization(asCByteCode *bc, bool onlyDefaults) { asASSERT( m_classDecl ); @@ -477,11 +481,11 @@ void asCCompiler::CompileMemberInitialization(asCByteCode *byteCode, bool onlyDe // here we should just validate that the member has a default constructor if( prop->type.IsObject() && !prop->type.IsObjectHandle() && - (((prop->type.GetObjectType()->flags & asOBJ_REF) && + (((prop->type.GetTypeInfo()->flags & asOBJ_REF) && prop->type.GetBehaviour()->factory == 0) || - ((prop->type.GetObjectType()->flags & asOBJ_VALUE) && + ((prop->type.GetTypeInfo()->flags & asOBJ_VALUE) && prop->type.GetBehaviour()->construct == 0 && - !(prop->type.GetObjectType()->flags & asOBJ_POD))) ) + !(prop->type.GetTypeInfo()->flags & asOBJ_POD))) ) { // Class has no default factory/constructor. asCString str; @@ -489,7 +493,7 @@ void asCCompiler::CompileMemberInitialization(asCByteCode *byteCode, bool onlyDe if( prop->type.GetFuncDef() ) str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, prop->type.GetFuncDef()->GetName()); else - str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, prop->type.GetObjectType()->GetName()); + str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, prop->type.GetTypeInfo()->GetName()); Error(str, declNode); } #else @@ -499,14 +503,14 @@ void asCCompiler::CompileMemberInitialization(asCByteCode *byteCode, bool onlyDe script = initScript; // Add a line instruction with the position of the declaration - LineInstr(byteCode, declNode->tokenPos); + LineInstr(bc, declNode->tokenPos); // Compile the initialization asQWORD constantValue; - asCByteCode bc(engine); - CompileInitialization(initNode, &bc, prop->type, declNode, prop->byteOffset, &constantValue, 2); - bc.OptimizeLocally(tempVariableOffsets); - byteCode->AddCode(&bc); + asCByteCode bcInit(engine); + CompileInitialization(initNode, &bcInit, prop->type, declNode, prop->byteOffset, &constantValue, 2); + bcInit.OptimizeLocally(tempVariableOffsets); + bc->AddCode(&bcInit); script = origScript; #endif @@ -515,30 +519,30 @@ void asCCompiler::CompileMemberInitialization(asCByteCode *byteCode, bool onlyDe } // Entry -int asCCompiler::CompileFunction(asCBuilder *builder, asCScriptCode *script, asCArray ¶meterNames, asCScriptNode *func, asCScriptFunction *outFunc, sClassDeclaration *classDecl) +int asCCompiler::CompileFunction(asCBuilder *in_builder, asCScriptCode *in_script, asCArray &in_parameterNames, asCScriptNode *in_func, asCScriptFunction *in_outFunc, sClassDeclaration *in_classDecl) { TimeIt("asCCompiler::CompileFunction"); - Reset(builder, script, outFunc); + Reset(in_builder, in_script, in_outFunc); int buildErrors = builder->numErrors; - int stackPos = SetupParametersAndReturnVariable(parameterNames, func); + int stackPos = SetupParametersAndReturnVariable(in_parameterNames, in_func); //-------------------------------------------- // Compile the statement block if( m_isConstructor ) - m_classDecl = classDecl; + m_classDecl = in_classDecl; // We need to parse the statement block now asCScriptNode *blockBegin; // If the function signature was implicit, e.g. virtual property accessor or // lambda function, then the received node already is the statement block - if( func->nodeType != snStatementBlock ) - blockBegin = func->lastChild; + if( in_func->nodeType != snStatementBlock ) + blockBegin = in_func->lastChild; else - blockBegin = func; + blockBegin = in_func; // TODO: memory: We can parse the statement block one statement at a time, thus save even more memory // TODO: optimize: For large functions, the parsing of the statement block can take a long time. Presumably because a lot of memory needs to be allocated @@ -656,7 +660,7 @@ int asCCompiler::CompileFunction(asCBuilder *builder, asCScriptCode *script, asC // Check if the number of labels in the functions isn't too many to be handled if( nextLabel >= (1<<15) ) - Error(TXT_TOO_MANY_JUMP_LABELS, func); + Error(TXT_TOO_MANY_JUMP_LABELS, in_func); // If there are compile errors, there is no reason to build the final code if( hasCompileErrors || builder->numErrors != buildErrors ) @@ -675,15 +679,15 @@ int asCCompiler::CompileFunction(asCBuilder *builder, asCScriptCode *script, asC #ifdef AS_DEBUG // DEBUG: output byte code if( outFunc->objectType ) - byteCode.DebugOutput(("__" + outFunc->objectType->name + "_" + outFunc->name + ".txt").AddressOf(), engine, outFunc); + byteCode.DebugOutput(("__" + outFunc->objectType->name + "_" + outFunc->name + ".txt").AddressOf(), in_outFunc); else - byteCode.DebugOutput(("__" + outFunc->name + ".txt").AddressOf(), engine, outFunc); + byteCode.DebugOutput(("__" + outFunc->name + ".txt").AddressOf(), in_outFunc); #endif return 0; } -int asCCompiler::CallCopyConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asSExprContext *arg, asCScriptNode *node, bool isGlobalVar, bool derefDest) +int asCCompiler::CallCopyConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asCExprContext *arg, asCScriptNode *node, bool isGlobalVar, bool derefDest) { if( !type.IsObject() ) return 0; @@ -691,20 +695,20 @@ int asCCompiler::CallCopyConstructor(asCDataType &type, int offset, bool isObjec // CallCopyConstructor should not be called for object handles. asASSERT( !type.IsObjectHandle() ); - asCArray args; + asCArray args; args.PushLast(arg); // The reference parameter must be pushed on the stack - asASSERT( arg->type.dataType.GetObjectType() == type.GetObjectType() ); + asASSERT( arg->type.dataType.GetTypeInfo() == type.GetTypeInfo() ); // Since we're calling the copy constructor, we have to trust the function to not do // anything stupid otherwise we will just enter a loop, as we try to make temporary // copies of the argument in order to guarantee safety. - if( type.GetObjectType()->flags & asOBJ_REF ) + if( type.GetTypeInfo()->flags & asOBJ_REF ) { - asSExprContext ctx(engine); + asCExprContext ctx(engine); int func = 0; asSTypeBehaviour *beh = type.GetBehaviour(); @@ -715,7 +719,7 @@ int asCCompiler::CallCopyConstructor(asCDataType &type, int offset, bool isObjec if( !isGlobalVar ) { // Call factory and store the handle in the given variable - PerformFunctionCall(func, &ctx, false, &args, type.GetObjectType(), true, offset); + PerformFunctionCall(func, &ctx, false, &args, CastToObjectType(type.GetTypeInfo()), true, offset); // Pop the reference left by the function call ctx.bc.Instr(asBC_PopPtr); @@ -723,12 +727,12 @@ int asCCompiler::CallCopyConstructor(asCDataType &type, int offset, bool isObjec else { // Call factory - PerformFunctionCall(func, &ctx, false, &args, type.GetObjectType()); + PerformFunctionCall(func, &ctx, false, &args, CastToObjectType(type.GetTypeInfo())); // Store the returned handle in the global variable ctx.bc.Instr(asBC_RDSPtr); ctx.bc.InstrPTR(asBC_PGA, engine->globalProperties[offset]->GetAddressOfValue()); - ctx.bc.InstrPTR(asBC_REFCPY, type.GetObjectType()); + ctx.bc.InstrPTR(asBC_REFCPY, type.GetTypeInfo()); ctx.bc.Instr(asBC_PopPtr); ReleaseTemporaryVariable(ctx.type.stackOffset, &ctx.bc); } @@ -769,8 +773,8 @@ int asCCompiler::CallCopyConstructor(asCDataType &type, int offset, bool isObjec } } - asSExprContext ctx(engine); - PerformFunctionCall(func, &ctx, isObjectOnHeap, &args, type.GetObjectType()); + asCExprContext ctx(engine); + PerformFunctionCall(func, &ctx, isObjectOnHeap, &args, CastToObjectType(type.GetTypeInfo())); bc->AddCode(&ctx.bc); @@ -786,7 +790,7 @@ int asCCompiler::CallCopyConstructor(asCDataType &type, int offset, bool isObjec // Class has no copy constructor/factory. asCString str; - str.Format(TXT_NO_COPY_CONSTRUCTOR_FOR_s, type.GetObjectType()->GetName()); + str.Format(TXT_NO_COPY_CONSTRUCTOR_FOR_s, type.GetTypeInfo()->GetName()); Error(str, node); return -1; @@ -797,9 +801,9 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo if( !type.IsObject() || type.IsObjectHandle() ) return 0; - if( type.GetObjectType()->flags & asOBJ_REF ) + if( type.GetTypeInfo()->flags & asOBJ_REF ) { - asSExprContext ctx(engine); + asCExprContext ctx(engine); ctx.exprNode = node; int func = 0; @@ -826,12 +830,12 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo if( func > 0 ) { - asCArray args; + asCArray args; asCScriptFunction *f = engine->scriptFunctions[func]; if( f->parameterTypes.GetLength() ) { // Add the default values for arguments not explicitly supplied - CompileDefaultAndNamedArgs(node, args, func, type.GetObjectType()); + CompileDefaultAndNamedArgs(node, args, func, CastToObjectType(type.GetTypeInfo())); PrepareFunctionCall(func, &ctx.bc, args); @@ -841,7 +845,7 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo if( isVarGlobOrMem == 0 ) { // Call factory and store the handle in the given variable - PerformFunctionCall(func, &ctx, false, &args, type.GetObjectType(), true, offset); + PerformFunctionCall(func, &ctx, false, &args, CastToObjectType(type.GetTypeInfo()), true, offset); // Pop the reference left by the function call ctx.bc.Instr(asBC_PopPtr); @@ -849,13 +853,13 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo else { // Call factory - PerformFunctionCall(func, &ctx, false, &args, type.GetObjectType()); + PerformFunctionCall(func, &ctx, false, &args, CastToObjectType(type.GetTypeInfo())); // TODO: runtime optimize: Should have a way of storing the object pointer directly to the destination // instead of first storing it in a local variable and then copying it to the // destination. - if( !(type.GetObjectType()->flags & asOBJ_SCOPED) ) + if( !(type.GetTypeInfo()->flags & asOBJ_SCOPED) ) { // Only dereference the variable if not a scoped type ctx.bc.Instr(asBC_RDSPtr); @@ -871,10 +875,10 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo // Store the returned handle in the class member ctx.bc.InstrSHORT(asBC_PSF, 0); ctx.bc.Instr(asBC_RDSPtr); - ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); } - if( type.GetObjectType()->flags & asOBJ_SCOPED ) + if( type.GetTypeInfo()->flags & asOBJ_SCOPED ) { // For scoped typed we must move the reference from the local // variable rather than copy it as there is no AddRef behaviour @@ -885,7 +889,10 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo } else { - ctx.bc.InstrPTR(asBC_REFCPY, type.GetObjectType()); + if( type.IsFuncdef() ) + ctx.bc.InstrPTR(asBC_REFCPY, &engine->functionBehaviours); + else + ctx.bc.InstrPTR(asBC_REFCPY, type.GetTypeInfo()); } ctx.bc.Instr(asBC_PopPtr); ReleaseTemporaryVariable(ctx.type.stackOffset, &ctx.bc); @@ -897,7 +904,7 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo for( asUINT n = 0; n < args.GetLength(); n++ ) if( args[n] ) { - asDELETE(args[n],asSExprContext); + asDELETE(args[n], asCExprContext); } return 0; @@ -905,7 +912,7 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo } else { - asSExprContext ctx(engine); + asCExprContext ctx(engine); ctx.exprNode = node; asSTypeBehaviour *beh = type.GetBehaviour(); @@ -932,14 +939,14 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo } // Allocate and initialize with the default constructor - if( func != 0 || (type.GetObjectType()->flags & asOBJ_POD) ) + if( func != 0 || (type.GetTypeInfo()->flags & asOBJ_POD) ) { - asCArray args; + asCArray args; asCScriptFunction *f = engine->scriptFunctions[func]; if( f && f->parameterTypes.GetLength() ) { // Add the default values for arguments not explicitly supplied - CompileDefaultAndNamedArgs(node, args, func, type.GetObjectType()); + CompileDefaultAndNamedArgs(node, args, func, CastToObjectType(type.GetTypeInfo())); PrepareFunctionCall(func, &ctx.bc, args); @@ -959,9 +966,9 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo if( derefDest ) bc->Instr(asBC_RDSPtr); - asSExprContext ctx(engine); - PerformFunctionCall(func, &ctx, false, 0, type.GetObjectType()); - bc->AddCode(&ctx.bc); + asCExprContext ctxCall(engine); + PerformFunctionCall(func, &ctxCall, false, 0, CastToObjectType(type.GetTypeInfo())); + bc->AddCode(&ctxCall.bc); // TODO: value on stack: This probably needs to be done in PerformFunctionCall // Mark the object as initialized @@ -971,18 +978,18 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo else if( isVarGlobOrMem == 2 ) { // Only POD types can be allocated inline in script classes - asASSERT( type.GetObjectType()->flags & asOBJ_POD ); + asASSERT( type.GetTypeInfo()->flags & asOBJ_POD ); if( func ) { // Call the constructor as a normal function bc->InstrSHORT(asBC_PSF, 0); bc->Instr(asBC_RDSPtr); - bc->InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + bc->InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); - asSExprContext ctx(engine); - PerformFunctionCall(func, &ctx, false, 0, type.GetObjectType()); - bc->AddCode(&ctx.bc); + asCExprContext ctxCall(engine); + PerformFunctionCall(func, &ctxCall, false, 0, CastToObjectType(type.GetTypeInfo())); + bc->AddCode(&ctxCall.bc); } } else @@ -1000,10 +1007,10 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo { bc->InstrSHORT(asBC_PSF, 0); bc->Instr(asBC_RDSPtr); - bc->InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + bc->InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); } - if( (type.GetObjectType()->flags & asOBJ_TEMPLATE) ) + if( (type.GetTypeInfo()->flags & asOBJ_TEMPLATE) ) { asCScriptFunction *descr = engine->scriptFunctions[func]; asASSERT( descr->funcType == asFUNC_SCRIPT ); @@ -1023,18 +1030,18 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo asASSERT( id ); - bc->InstrPTR(asBC_OBJTYPE, type.GetObjectType()); - bc->Alloc(asBC_ALLOC, type.GetObjectType(), id, AS_PTR_SIZE + AS_PTR_SIZE); + bc->InstrPTR(asBC_OBJTYPE, type.GetTypeInfo()); + bc->Alloc(asBC_ALLOC, type.GetTypeInfo(), id, AS_PTR_SIZE + AS_PTR_SIZE); } else - bc->Alloc(asBC_ALLOC, type.GetObjectType(), func, AS_PTR_SIZE); + bc->Alloc(asBC_ALLOC, type.GetTypeInfo(), func, AS_PTR_SIZE); } // Cleanup for( asUINT n = 0; n < args.GetLength(); n++ ) if( args[n] ) { - asDELETE(args[n],asSExprContext); + asDELETE(args[n], asCExprContext); } return 0; @@ -1043,11 +1050,7 @@ int asCCompiler::CallDefaultConstructor(const asCDataType &type, int offset, boo // Class has no default factory/constructor. asCString str; - // TODO: funcdef: asCDataType should have a GetTypeName() - if( type.GetFuncDef() ) - str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, type.GetFuncDef()->GetName()); - else - str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, type.GetObjectType()->GetName()); + str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, type.GetTypeInfo()->GetName()); Error(str, node); return -1; @@ -1058,29 +1061,32 @@ void asCCompiler::CallDestructor(asCDataType &type, int offset, bool isObjectOnH if( !type.IsReference() ) { // Call destructor for the data type - if( type.IsObject() ) + if( type.IsObject() || type.IsFuncdef() ) { // The null pointer doesn't need to be destroyed if( type.IsNullHandle() ) return; // Nothing is done for list pattern types, as this is taken care of by the CompileInitList method - if( type.GetObjectType()->flags & asOBJ_LIST_PATTERN ) + if( type.GetTypeInfo()->flags & asOBJ_LIST_PATTERN ) return; if( isObjectOnHeap || type.IsObjectHandle() ) { // Free the memory - bc->InstrW_PTR(asBC_FREE, (short)offset, type.GetObjectType()); + if (type.IsFuncdef()) + bc->InstrW_PTR(asBC_FREE, (short)offset, &engine->functionBehaviours); + else + bc->InstrW_PTR(asBC_FREE, (short)offset, type.GetTypeInfo()); } else { - asASSERT( type.GetObjectType()->GetFlags() & asOBJ_VALUE ); + asASSERT( type.GetTypeInfo()->GetFlags() & asOBJ_VALUE ); if( type.GetBehaviour()->destruct ) { // Call the destructor as a regular function - asSExprContext ctx(engine); + asCExprContext ctx(engine); ctx.bc.InstrSHORT(asBC_PSF, (short)offset); PerformFunctionCall(type.GetBehaviour()->destruct, &ctx); ctx.bc.OptimizeLocally(tempVariableOffsets); @@ -1187,47 +1193,56 @@ void asCCompiler::CompileStatementBlock(asCScriptNode *block, bool ownVariableSc } // Entry -int asCCompiler::CompileGlobalVariable(asCBuilder *builder, asCScriptCode *script, asCScriptNode *node, sGlobalVariableDescription *gvar, asCScriptFunction *outFunc) +int asCCompiler::CompileGlobalVariable(asCBuilder *in_builder, asCScriptCode *in_script, asCScriptNode *in_node, sGlobalVariableDescription *in_gvar, asCScriptFunction *in_outFunc) { - Reset(builder, script, outFunc); - m_globalVar = gvar; + Reset(in_builder, in_script, in_outFunc); + m_globalVar = in_gvar; // Add a variable scope (even though variables can't be declared) AddVariableScope(); - gvar->isPureConstant = false; + in_gvar->isPureConstant = false; // Parse the initialization nodes asCParser parser(builder); - if( node ) + if (in_node) { - int r = parser.ParseVarInit(script, node); - if( r < 0 ) + int r = parser.ParseVarInit(in_script, in_node); + if (r < 0) return r; - node = parser.GetScriptNode(); + in_node = parser.GetScriptNode(); } - asSExprContext compiledCtx(engine); + asCExprContext compiledCtx(engine); bool preCompiled = false; - if( gvar->datatype.IsAuto() ) - preCompiled = CompileAutoType(gvar->datatype, compiledCtx, node, gvar->declaredAtNode); - if( gvar->property == 0 ) + if (in_gvar->datatype.IsAuto()) { - gvar->property = builder->module->AllocateGlobalProperty(gvar->name.AddressOf(), gvar->datatype, gvar->ns); - gvar->index = gvar->property->id; + preCompiled = CompileAutoType(in_gvar->datatype, compiledCtx, in_node, in_gvar->declaredAtNode); + if (!preCompiled) + { + // If it wasn't possible to determine the type from the expression then there + // is no need to continue with the initialization. The error was already reported + // in CompileAutoType. + return -1; + } + } + if( in_gvar->property == 0 ) + { + in_gvar->property = builder->module->AllocateGlobalProperty(in_gvar->name.AddressOf(), in_gvar->datatype, in_gvar->ns); + in_gvar->index = in_gvar->property->id; } // Compile the expression - asSExprContext ctx(engine); + asCExprContext ctx(engine); asQWORD constantValue = 0; - if( CompileInitialization(node, &ctx.bc, gvar->datatype, gvar->declaredAtNode, gvar->index, &constantValue, 1, preCompiled ? &compiledCtx : 0) ) + if( CompileInitialization(in_node, &ctx.bc, in_gvar->datatype, in_gvar->declaredAtNode, in_gvar->index, &constantValue, 1, preCompiled ? &compiledCtx : 0) ) { // Should the variable be marked as pure constant? - if( gvar->datatype.IsPrimitive() && gvar->datatype.IsReadOnly() ) + if( in_gvar->datatype.IsPrimitive() && in_gvar->datatype.IsReadOnly() ) { - gvar->isPureConstant = true; - gvar->constantValue = constantValue; + in_gvar->isPureConstant = true; + in_gvar->constantValue = constantValue; } } @@ -1236,10 +1251,10 @@ int asCCompiler::CompileGlobalVariable(asCBuilder *builder, asCScriptCode *scrip // Add information on the line number for the global variable size_t pos = 0; - if( gvar->declaredAtNode ) - pos = gvar->declaredAtNode->tokenPos; - else if( gvar->initializationNode ) - pos = gvar->initializationNode->tokenPos; + if( in_gvar->declaredAtNode ) + pos = in_gvar->declaredAtNode->tokenPos; + else if( in_gvar->initializationNode ) + pos = in_gvar->initializationNode->tokenPos; LineInstr(&byteCode, pos); // Reserve space for all local variables @@ -1274,13 +1289,13 @@ int asCCompiler::CompileGlobalVariable(asCBuilder *builder, asCScriptCode *scrip #ifdef AS_DEBUG // DEBUG: output byte code - byteCode.DebugOutput(("___init_" + gvar->name + ".txt").AddressOf(), engine, outFunc); + byteCode.DebugOutput(("___init_" + in_gvar->name + ".txt").AddressOf(), outFunc); #endif return 0; } -void asCCompiler::DetermineSingleFunc(asSExprContext *ctx, asCScriptNode *node) +void asCCompiler::DetermineSingleFunc(asCExprContext *ctx, asCScriptNode *node) { // Don't do anything if this is not a deferred global function if( !ctx->IsGlobalFunc() ) @@ -1336,20 +1351,18 @@ void asCCompiler::DetermineSingleFunc(asSExprContext *ctx, asCScriptNode *node) // Push the function pointer on the stack ctx->bc.InstrPTR(asBC_FuncPtr, builder->GetFunctionDescription(funcs[0])); - ctx->type.Set(asCDataType::CreateFuncDef(builder->GetFunctionDescription(funcs[0]))); + ctx->type.Set(asCDataType::CreateType(engine->FindMatchingFuncdef(builder->GetFunctionDescription(funcs[0]), builder->module), false)); ctx->type.dataType.MakeHandle(true); ctx->type.isExplicitHandle = true; ctx->methodName = ""; } -void asCCompiler::CompileInitAsCopy(asCDataType &dt, int offset, asCByteCode *bc, asSExprContext *arg, asCScriptNode *node, bool derefDestination) +void asCCompiler::CompileInitAsCopy(asCDataType &dt, int offset, asCByteCode *bc, asCExprContext *arg, asCScriptNode *node, bool derefDestination) { - asASSERT( dt.GetObjectType() ); - bool isObjectOnHeap = derefDestination ? false : IsVariableOnHeap(offset); // Use copy constructor if available. - if( dt.GetObjectType()->beh.copyconstruct ) + if(CastToObjectType(dt.GetTypeInfo()) && CastToObjectType(dt.GetTypeInfo())->beh.copyconstruct ) { PrepareForAssignment(&dt, arg, node, true); int r = CallCopyConstructor(dt, offset, isObjectOnHeap, bc, arg, node, 0, derefDestination); @@ -1380,7 +1393,7 @@ void asCCompiler::CompileInitAsCopy(asCDataType &dt, int offset, asCByteCode *bc // Call the opAssign method to assign the value to the temporary object dt.MakeReference(isObjectOnHeap); - asCTypeInfo type; + asCExprValue type; type.Set(dt); type.isTemporary = true; type.stackOffset = (short)offset; @@ -1401,7 +1414,7 @@ void asCCompiler::CompileInitAsCopy(asCDataType &dt, int offset, asCByteCode *bc } // Pop the reference that was pushed on the stack if the result is an object - if( type.dataType.IsObject() ) + if( type.dataType.IsObject() || type.dataType.IsFuncdef() ) bc->Instr(asBC_PopPtr); // If the assignment operator returned an object by value it will @@ -1414,7 +1427,7 @@ void asCCompiler::CompileInitAsCopy(asCDataType &dt, int offset, asCByteCode *bc } } -int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, asCScriptNode *node, bool isFunction, int refType, bool isMakingCopy) +int asCCompiler::PrepareArgument(asCDataType *paramType, asCExprContext *ctx, asCScriptNode *node, bool isFunction, int refType, bool isMakingCopy) { asCDataType param = *paramType; if( paramType->GetTokenType() == ttQuestion ) @@ -1433,7 +1446,7 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as // If value assign is disabled for reference types, then make // sure to always pass the handle to ? parameters if( builder->engine->ep.disallowValueAssignForRefType && - ctx->type.dataType.GetObjectType() && (ctx->type.dataType.GetObjectType()->flags & asOBJ_REF) && !(ctx->type.dataType.GetObjectType()->flags & asOBJ_SCOPED) ) + ctx->type.dataType.GetTypeInfo() && (ctx->type.dataType.GetTypeInfo()->flags & asOBJ_REF) && !(ctx->type.dataType.GetTypeInfo()->flags & asOBJ_SCOPED) ) { param.MakeHandle(true); } @@ -1454,7 +1467,7 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as dt.MakeReadOnly(false); int offset; - if( refType == 1 ) // &in + if( refType == asTM_INREF ) { ProcessPropertyGetAccessor(ctx, node); @@ -1511,6 +1524,7 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as ctx->bc.InstrWORD(asBC_PSF, (short)offset); ctx->type.SetVariable(dt, offset, true); + ctx->type.isExplicitHandle = true; } else { @@ -1540,12 +1554,14 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as // the function as it is, since the local variable will stay alive, and since it // is temporary there is no side effect if the function modifies it. - // If the parameter is read-only and therefor guaranteed not to be modified by the + // If the parameter is read-only and therefore guaranteed not to be modified by the // function, then it is enough that the variable is local to guarantee the lifetime. if( !ctx->type.isTemporary && !(param.IsReadOnly() && ctx->type.isVariable) ) { - if( (ctx->type.dataType.GetObjectType()->flags & asOBJ_REF) && param.IsReadOnly() && !(ctx->type.dataType.GetObjectType()->flags & asOBJ_SCOPED) ) + if( ctx->type.dataType.IsFuncdef() || ((ctx->type.dataType.GetTypeInfo()->flags & asOBJ_REF) && param.IsReadOnly() && !(ctx->type.dataType.GetTypeInfo()->flags & asOBJ_SCOPED)) ) { + // Funcdefs only need an extra handle to guarantee the lifetime. + // If the object is a reference type (except scoped reference types), and the // parameter is a const reference, then it is not necessary to make a copy of the // object. The compiler just needs to hold a handle to guarantee the lifetime. @@ -1557,17 +1573,26 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as // Copy the handle Dereference(ctx, true); ctx->bc.InstrWORD(asBC_PSF, (asWORD)offset); - ctx->bc.InstrPTR(asBC_REFCPY, ctx->type.dataType.GetObjectType()); + if (ctx->type.dataType.IsFuncdef()) + ctx->bc.InstrPTR(asBC_REFCPY, &engine->functionBehaviours); + else + ctx->bc.InstrPTR(asBC_REFCPY, ctx->type.dataType.GetTypeInfo()); ctx->bc.Instr(asBC_PopPtr); ctx->bc.InstrWORD(asBC_PSF, (asWORD)offset); // The type should be set to the param type instead of dt to guarantee // that the expression keeps the correct type for variable ? args. Otherwise // MoveArgsToStack will use the wrong bytecode to move the arg to the stack + bool isExplicitHandle = ctx->type.isExplicitHandle; ctx->type.SetVariable(param, offset, true); + ctx->type.dataType.MakeHandle(true); + ctx->type.isExplicitHandle = isExplicitHandle; } else { + // Make a copy of the object to guarantee that the original isn't modified + asASSERT(!dt.IsFuncdef()); + // Allocate and initialize a temporary local object offset = AllocateVariableNotIn(dt, true, false, ctx); CompileInitAsCopy(dt, offset, &ctx->bc, ctx, node, false); @@ -1588,18 +1613,49 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as ctx->type.dataType.MakeReadOnly(true); } } + + // When calling a function expecting a var arg with a parameter received as reference to handle + // then it is necessary to copy the handle to a local variable, otherwise MoveArgsToStack will + // not be able to do the correct double dereference to put the reference to the object on the stack. + if (paramType->GetTokenType() == ttQuestion && !param.IsObjectHandle() && ctx->type.isVariable) + { + sVariable *var = variables->GetVariableByOffset(ctx->type.stackOffset); + if (var && var->type.IsReference() && var->type.IsObjectHandle()) + { + // Copy the handle to local variable + + // Allocate a handle variable + dt.MakeHandle(true); + offset = AllocateVariableNotIn(dt, true, false, ctx); + + // Copy the handle + Dereference(ctx, true); + ctx->bc.InstrWORD(asBC_PSF, (asWORD)offset); + if (ctx->type.dataType.IsFuncdef()) + ctx->bc.InstrPTR(asBC_REFCPY, &engine->functionBehaviours); + else + ctx->bc.InstrPTR(asBC_REFCPY, ctx->type.dataType.GetTypeInfo()); + ctx->bc.Instr(asBC_PopPtr); + ctx->bc.InstrWORD(asBC_PSF, (asWORD)offset); + + // The type should be set to the param type instead of dt to guarantee + // that the expression keeps the correct type for variable ? args. Otherwise + // MoveArgsToStack will use the wrong bytecode to move the arg to the stack + ctx->type.SetVariable(param, offset, true); + } + } } else { // We must guarantee that the address to the value is on the stack - if( ctx->type.dataType.IsObject() && + if( (ctx->type.dataType.IsObject() || ctx->type.dataType.IsFuncdef()) && !ctx->type.dataType.IsObjectHandle() && ctx->type.dataType.IsReference() ) Dereference(ctx, true); } } } - else if( refType == 2 ) // &out + else if( refType == asTM_OUTREF ) { // Add the type id as hidden arg if the parameter is a ? type if( paramType->GetTokenType() == ttQuestion ) @@ -1624,6 +1680,11 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as } else { + // Null handles and void expressions must be marked as explicit + // handles for correct treatement in MoveArgsToStack + if (dt.IsNullHandle()) + ctx->type.isExplicitHandle = true; + // Make sure the variable is not used in the expression offset = AllocateVariableNotIn(dt, true, false, ctx); @@ -1634,9 +1695,6 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as } else { - // TODO: Need to reserve variables, as the default constructor may need - // to allocate temporary variables to compute default args - // Allocate and construct the temporary object asCByteCode tmpBC(engine); CallDefaultConstructor(dt, offset, IsVariableOnHeap(offset), &tmpBC, node); @@ -1645,16 +1703,17 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as tmpBC.AddCode(&ctx->bc); ctx->bc.AddCode(&tmpBC); - dt.MakeReference(!dt.IsObject() || dt.IsObjectHandle()); - asCTypeInfo type; + dt.MakeReference(!(dt.IsObject() || dt.IsFuncdef()) || dt.IsObjectHandle()); + asCExprValue type; type.Set(dt); type.isTemporary = true; type.stackOffset = (short)offset; + type.isExplicitHandle = ctx->type.isExplicitHandle; ctx->type = type; ctx->bc.InstrSHORT(asBC_PSF, (short)offset); - if( dt.IsObject() && !dt.IsObjectHandle() ) + if( (dt.IsObject() || dt.IsFuncdef()) && !dt.IsObjectHandle() ) ctx->bc.Instr(asBC_RDSPtr); } @@ -1680,7 +1739,9 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as } // Literal constants cannot be passed to inout ref arguments - if( !ctx->type.isVariable && ctx->type.isConstant ) + if( !ctx->type.isVariable && + ctx->type.isConstant && + !ctx->type.dataType.IsEqualExceptRefAndConst(engine->stringType) ) { // Unless unsafe references are turned on and the reference is const if( param.IsReadOnly() && engine->ep.allowUnsafeReferences ) @@ -1697,7 +1758,7 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as } // Perform implicit ref cast if necessary, but don't allow the implicit conversion to create new objects - if( ctx->type.dataType.IsObject() && ctx->type.dataType.GetObjectType() != dt.GetObjectType() ) + if( (ctx->type.dataType.IsObject() || ctx->type.dataType.IsFuncdef()) && ctx->type.dataType.GetTypeInfo() != dt.GetTypeInfo() ) ImplicitConversion(ctx, dt, node, asIC_IMPLICIT_CONV, true, false); // Only objects that support object handles @@ -1706,15 +1767,16 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as // references if( !engine->ep.allowUnsafeReferences && !ctx->type.isVariable && - ctx->type.dataType.IsObject() && + (ctx->type.dataType.IsObject() || ctx->type.dataType.IsFuncdef()) && !ctx->type.dataType.IsObjectHandle() && ((ctx->type.dataType.GetBehaviour()->addref && ctx->type.dataType.GetBehaviour()->release) || - (ctx->type.dataType.GetObjectType()->flags & asOBJ_NOCOUNT)) ) + (ctx->type.dataType.GetTypeInfo()->flags & asOBJ_NOCOUNT) || + ctx->type.dataType.IsFuncdef()) ) { // Store a handle to the object as local variable - asSExprContext tmp(engine); - asCDataType dt = ctx->type.dataType; + asCExprContext tmp(engine); + dt = ctx->type.dataType; dt.MakeHandle(true); dt.MakeReference(false); @@ -1724,7 +1786,10 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as if( !ctx->type.dataType.IsObjectHandle() && ctx->type.dataType.IsReference() ) ctx->bc.Instr(asBC_RDSPtr); ctx->bc.InstrWORD(asBC_PSF, (asWORD)offset); - ctx->bc.InstrPTR(asBC_REFCPY, ctx->type.dataType.GetObjectType()); + if( ctx->type.dataType.IsFuncdef() ) + ctx->bc.InstrPTR(asBC_REFCPY, &engine->functionBehaviours); + else + ctx->bc.InstrPTR(asBC_REFCPY, ctx->type.dataType.GetTypeInfo()); ctx->bc.Instr(asBC_PopPtr); ctx->bc.InstrWORD(asBC_PSF, (asWORD)offset); @@ -1741,9 +1806,9 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as // Make sure the reference to the value is on the stack // For objects, the reference needs to be dereferenced so the pointer on the stack is to the actual object // For handles, the reference shouldn't be changed because the pointer on the stack should be to the handle - if( ctx->type.dataType.IsObject() && ctx->type.dataType.IsReference() && !param.IsObjectHandle() ) + if( (ctx->type.dataType.IsObject() || ctx->type.dataType.IsFuncdef()) && ctx->type.dataType.IsReference() && !param.IsObjectHandle() ) Dereference(ctx, true); - else if( ctx->type.isVariable && !ctx->type.dataType.IsObject() ) + else if( ctx->type.isVariable && !(ctx->type.dataType.IsObject() || ctx->type.dataType.IsFuncdef()) ) ctx->bc.InstrSHORT(asBC_PSF, ctx->type.stackOffset); else if( ctx->type.dataType.IsPrimitive() ) ctx->bc.Instr(asBC_PshRPtr); @@ -1795,41 +1860,31 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as if( dt.IsObjectHandle() ) ctx->type.isExplicitHandle = true; - if( dt.IsObject() && !dt.IsNullHandle() ) + if( (dt.IsObject() || dt.IsFuncdef()) && !dt.IsNullHandle() && !dt.IsReference() ) { - if( !dt.IsReference() ) - { - // Objects passed by value must be placed in temporary variables - // so that they are guaranteed to not be referenced anywhere else. - // The object must also be allocated on the heap, as the memory will - // be deleted by in as_callfunc_xxx. - // TODO: value on stack: How can we avoid this unnecessary allocation? + // Objects passed by value must be placed in temporary variables + // so that they are guaranteed to not be referenced anywhere else. + // The object must also be allocated on the heap, as the memory will + // be deleted by the called function. - // Local variables doesn't need to be copied into - // a temp if we're already compiling an assignment - if( !isMakingCopy || !ctx->type.dataType.IsObjectHandle() || !ctx->type.isVariable ) - PrepareTemporaryObject(node, ctx, true); + // Handles passed by value must also be placed in a temporary variable + // to guarantee that the object referred to isn't freed too early. - // The implicit conversion shouldn't convert the object to - // non-reference yet. It will be dereferenced just before the call. - // Otherwise the object might be missed by the exception handler. - dt.MakeReference(true); - } - else - { - // An object passed by reference should place the pointer to - // the object on the stack. - dt.MakeReference(false); - } + // TODO: value on stack: How can we avoid this unnecessary allocation? + + // Don't make temporary copies of handles if it is going to be used + // for handle assignment anyway, i.e. REFCPY. + if( !(!isFunction && isMakingCopy && ctx->type.dataType.IsObjectHandle() && ctx->type.isVariable) ) + PrepareTemporaryVariable(node, ctx, true); } } } // Don't put any pointer on the stack yet - if( param.IsReference() || (param.IsObject() && !param.IsNullHandle()) ) + if( param.IsReference() || ((param.IsObject() || param.IsFuncdef()) && !param.IsNullHandle()) ) { // &inout parameter may leave the reference on the stack already - if( refType != 3 ) + if( refType != asTM_INOUTREF ) { asASSERT( ctx->type.isVariable || ctx->type.isTemporary || isMakingCopy ); @@ -1846,7 +1901,7 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, as return 0; } -void asCCompiler::PrepareFunctionCall(int funcId, asCByteCode *bc, asCArray &args) +void asCCompiler::PrepareFunctionCall(int funcId, asCByteCode *bc, asCArray &args) { // When a match has been found, compile the final byte code using correct parameter types asCScriptFunction *descr = builder->GetFunctionDescription(funcId); @@ -1858,18 +1913,18 @@ void asCCompiler::PrepareFunctionCall(int funcId, asCByteCode *bc, asCArrayparameterTypes.GetLength() == 1 && descr->parameterTypes[0].IsEqualExceptRefAndConst(args[0]->type.dataType) && - (((descr->name == "opAssign" || descr->name == "$beh0") && descr->objectType && descr->objectType == args[0]->type.dataType.GetObjectType()) || - (descr->objectType == 0 && args[0]->type.dataType.GetObjectType() && descr->name == args[0]->type.dataType.GetObjectType()->name)) ) + (((descr->name == "opAssign" || descr->name == "$beh0") && descr->objectType && descr->objectType == args[0]->type.dataType.GetTypeInfo()) || + (descr->objectType == 0 && args[0]->type.dataType.GetTypeInfo() && descr->name == args[0]->type.dataType.GetTypeInfo()->name)) ) makingCopy = true; // Add code for arguments - asSExprContext e(engine); + asCExprContext e(engine); for( int n = (int)args.GetLength()-1; n >= 0; n-- ) { // Make sure PrepareArgument doesn't use any variable that is already - // being used by any of the following argument expressions + // being used by the argument or any of the following argument expressions int l = int(reservedVariables.GetLength()); - for( int m = n-1; m >= 0; m-- ) + for( int m = n; m >= 0; m-- ) args[m]->bc.GetVarsUsed(reservedVariables); PrepareArgument2(&e, args[n], &descr->parameterTypes[n], true, descr->inOutFlags[n], makingCopy); @@ -1879,7 +1934,7 @@ void asCCompiler::PrepareFunctionCall(int funcId, asCByteCode *bc, asCArrayAddCode(&e.bc); } -void asCCompiler::MoveArgsToStack(int funcId, asCByteCode *bc, asCArray &args, bool addOneToOffset) +void asCCompiler::MoveArgsToStack(int funcId, asCByteCode *bc, asCArray &args, bool addOneToOffset) { asCScriptFunction *descr = builder->GetFunctionDescription(funcId); @@ -1897,8 +1952,8 @@ void asCCompiler::MoveArgsToStack(int funcId, asCByteCode *bc, asCArrayparameterTypes.GetLength() == 1 && descr->parameterTypes[0].IsEqualExceptRefAndConst(args[0]->type.dataType) && - (((descr->name == "opAssign" || descr->name == "$beh0") && descr->objectType && descr->objectType == args[0]->type.dataType.GetObjectType()) || - (descr->objectType == 0 && args[0]->type.dataType.GetObjectType() && descr->name == args[0]->type.dataType.GetObjectType()->name)) ) + (((descr->name == "opAssign" || descr->name == "$beh0") && descr->objectType && descr->objectType == args[0]->type.dataType.GetTypeInfo()) || + (descr->objectType == 0 && args[0]->type.dataType.GetTypeInfo() && descr->name == args[0]->type.dataType.GetTypeInfo()->name)) ) makingCopy = true; #endif @@ -1907,11 +1962,12 @@ void asCCompiler::MoveArgsToStack(int funcId, asCByteCode *bc, asCArrayparameterTypes[n].IsReference() ) { - if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() ) + if( (descr->parameterTypes[n].IsObject() || descr->parameterTypes[n].IsFuncdef()) && !descr->parameterTypes[n].IsObjectHandle() ) { if( descr->inOutFlags[n] != asTM_INOUTREF ) { #ifdef AS_DEBUG + // This assert is inside AS_DEBUG because of the variable makingCopy which is only defined in debug mode asASSERT( args[n]->type.isVariable || args[n]->type.isTemporary || makingCopy ); #endif @@ -1931,7 +1987,8 @@ void asCCompiler::MoveArgsToStack(int funcId, asCByteCode *bc, asCArrayinOutFlags[n] != asTM_INOUTREF ) { if( descr->parameterTypes[n].GetTokenType() == ttQuestion && - args[n]->type.dataType.IsObject() && !args[n]->type.dataType.IsObjectHandle() ) + (args[n]->type.dataType.IsObject() || args[n]->type.dataType.IsFuncdef()) && + !args[n]->type.dataType.IsObjectHandle() ) { // Send the object as a reference to the object, // and not to the variable holding the object @@ -1942,21 +1999,42 @@ void asCCompiler::MoveArgsToStack(int funcId, asCByteCode *bc, asCArrayInstrWORD(asBC_GETOBJREF, (asWORD)offset); } + else if (descr->parameterTypes[n].GetTokenType() == ttQuestion && + args[n]->type.dataType.IsObjectHandle() && !args[n]->type.isExplicitHandle) + { + // The object handle is being passed as an object, so dereference it before + // the call so the reference will be to the object rather than to the handle + if (engine->ep.disallowValueAssignForRefType ) + { + // With disallow value assign all ref type objects are always passed by handle + bc->InstrWORD(asBC_GETREF, (asWORD)offset); + } + else + bc->InstrWORD(asBC_GETOBJREF, (asWORD)offset); + } else { - bc->InstrWORD(asBC_GETREF, (asWORD)offset); + // If the variable is really an argument of @& type, then it is necessary + // to use asBC_GETOBJREF so the pointer is correctly dereferenced. + sVariable *var = variables->GetVariableByOffset(args[n]->type.stackOffset); + if (var == 0 || !var->type.IsReference() || !var->type.IsObjectHandle()) + bc->InstrWORD(asBC_GETREF, (asWORD)offset); + else + bc->InstrWORD(asBC_GETOBJREF, (asWORD)offset); } } } - else if( descr->parameterTypes[n].IsObject() ) + else if( descr->parameterTypes[n].IsObject() || descr->parameterTypes[n].IsFuncdef() ) { // TODO: value on stack: What can we do to avoid this unnecessary allocation? // The object must be allocated on the heap, because this memory will be deleted in as_callfunc_xxx asASSERT(IsVariableOnHeap(args[n]->type.stackOffset)); + // The pointer in the variable will be moved to the stack bc->InstrWORD(asBC_GETOBJ, (asWORD)offset); - // The temporary variable must not be freed as it will no longer hold an object + // Deallocate the variable slot so it can be reused, but do not attempt to + // free the content of the variable since it was moved to the stack for the call DeallocateVariable(args[n]->type.stackOffset); args[n]->type.isTemporary = false; } @@ -1965,7 +2043,7 @@ void asCCompiler::MoveArgsToStack(int funcId, asCByteCode *bc, asCArray &args, asCArray &namedArgs) +int asCCompiler::CompileArgumentList(asCScriptNode *node, asCArray &args, asCArray &namedArgs) { asASSERT(node->nodeType == snArgList); @@ -2009,11 +2087,11 @@ int asCCompiler::CompileArgumentList(asCScriptNode *node, asCArray &args, int funcId, asCObjectType *objectType, asCArray *namedArgs) +int asCCompiler::CompileDefaultAndNamedArgs(asCScriptNode *node, asCArray &args, int funcId, asCObjectType *objectType, asCArray *namedArgs) { asCScriptFunction *func = builder->GetFunctionDescription(funcId); if( func == 0 || args.GetLength() >= (asUINT)func->GetParamCount() ) @@ -2068,7 +2146,7 @@ int asCCompiler::CompileDefaultAndNamedArgs(asCScriptNode *node, asCArraynameSpace; outFunc->nameSpace = func->nameSpace; - asSExprContext expr(engine); + asCExprContext expr(engine); r = CompileExpression(arg, &expr); // Restore the namespace outFunc->nameSpace = origNameSpace; // Don't allow address of class method - if( expr.methodName != "" ) + if( expr.IsClassMethod() ) { // TODO: Improve error message Error(TXT_DEF_ARG_TYPE_DOESNT_MATCH, arg); @@ -2178,7 +2256,7 @@ int asCCompiler::CompileDefaultAndNamedArgs(asCScriptNode *node, asCArray &funcs, asCArray &args, asCScriptNode *node, const char *name, asCArray *namedArgs, asCObjectType *objectType, bool isConstMethod, bool silent, bool allowObjectConstruct, const asCString &scope) +asUINT asCCompiler::MatchFunctions(asCArray &funcs, asCArray &args, asCScriptNode *node, const char *name, asCArray *namedArgs, asCObjectType *objectType, bool isConstMethod, bool silent, bool allowObjectConstruct, const asCString &scope) { asCArray origFuncs = funcs; // Keep the original list for error message asUINT cost = 0; @@ -2348,7 +2426,7 @@ asUINT asCCompiler::MatchFunctions(asCArray &funcs, asCArray &funcs, asCArrayIsClassMethod() ) { attemptsPassingClassMethod = true; - str += args[n]->type.dataType.GetObjectType()->GetName(); + str += args[n]->type.dataType.GetTypeInfo()->GetName(); str += "::"; } str += args[n]->methodName; } + else if (args[n]->IsAnonymousInitList()) + { + str += "{...}"; + } else str += args[n]->type.dataType.Format(outFunc->nameSpace); } @@ -2428,7 +2510,7 @@ asUINT asCCompiler::MatchFunctions(asCArray &funcs, asCArraymethodName != "" ) str += named.ctx->methodName; else @@ -2480,43 +2562,63 @@ asUINT asCCompiler::MatchFunctions(asCArray &funcs, asCArraynodeType == snAssignment ) { int r = CompileAssignment(node, &compiledCtx); if( r >= 0 ) { + // Must not have unused ambiguous names + if (compiledCtx.IsClassMethod() || compiledCtx.IsGlobalFunc()) + { + // TODO: Should mention that the problem is the ambiguous name + Error(TXT_CANNOT_RESOLVE_AUTO, errNode); + return false; + } + + // Must not have unused anonymous functions + if (compiledCtx.IsLambda()) + { + // TODO: Should mention that the problem is the anonymous function + Error(TXT_CANNOT_RESOLVE_AUTO, errNode); + return false; + } + + // Must not be a null handle + if (compiledCtx.type.dataType.IsNullHandle()) + { + // TODO: Should mention that the problem is the null pointer + Error(TXT_CANNOT_RESOLVE_AUTO, errNode); + return false; + } + asCDataType newType = compiledCtx.type.dataType; - bool success = true; // Handle const qualifier on auto - if( type.IsReadOnly() ) + if (type.IsReadOnly()) newType.MakeReadOnly(true); - else if( newType.IsPrimitive() ) + else if (newType.IsPrimitive()) newType.MakeReadOnly(false); // Handle reference/value stuff newType.MakeReference(false); - if( !newType.IsObjectHandle() ) + if (!newType.IsObjectHandle()) { // We got a value object or an object reference. // Turn the variable into a handle if specified // as auto@, otherwise make it a 'value'. - if( type.IsHandleToAuto() ) + if (type.IsHandleToAuto()) { - if( newType.MakeHandle(true) < 0 ) + if (newType.MakeHandle(true) < 0) { Error(TXT_OBJECT_HANDLE_NOT_SUPPORTED, errNode); - success = false; + return false; } } } - if(success) - type = newType; - else - type = asCDataType::CreatePrimitive(ttInt, false); + type = newType; return true; } @@ -2533,17 +2635,26 @@ bool asCCompiler::CompileAutoType(asCDataType &type, asSExprContext &compiledCtx void asCCompiler::CompileDeclaration(asCScriptNode *decl, asCByteCode *bc) { // Get the data type - asCDataType type = builder->CreateDataTypeFromNode(decl->firstChild, script, outFunc->nameSpace); + asCDataType type = builder->CreateDataTypeFromNode(decl->firstChild, script, outFunc->nameSpace, false, outFunc->objectType); // Declare all variables in this declaration asCScriptNode *node = decl->firstChild->next; while( node ) { // If this is an auto type, we have to compile the assignment now to figure out the type - asSExprContext compiledCtx(engine); + asCExprContext compiledCtx(engine); bool preCompiled = false; - if( type.IsAuto() ) + if (type.IsAuto()) + { preCompiled = CompileAutoType(type, compiledCtx, node->next, node); + if (!preCompiled) + { + // If it wasn't possible to determine the type from the expression then there + // is no need to continue with the initialization. The error was already reported + // in CompileAutoType. + return; + } + } // Is the type allowed? if( !type.CanBeInstantiated() ) @@ -2558,14 +2669,15 @@ void asCCompiler::CompileDeclaration(asCScriptNode *decl, asCByteCode *bc) str.Format(TXT_DATA_TYPE_CANT_BE_s, type.Format(outFunc->nameSpace).AddressOf()); Error(str, node); - // Use int instead to avoid further problems - type = asCDataType::CreatePrimitive(ttInt, false); + // Don't continue, as it will most likely lead to further + // errors that may just mislead the script writer + return; } // A shared object may not declare variables of non-shared types if( outFunc->IsShared() ) { - asCObjectType *ot = type.GetObjectType(); + asCTypeInfo *ot = type.GetTypeInfo(); if( ot && !ot->IsShared() ) { asCString msg; @@ -2579,7 +2691,7 @@ void asCCompiler::CompileDeclaration(asCScriptNode *decl, asCByteCode *bc) // Verify that the name isn't used by a dynamic data type // TODO: Must check against registered funcdefs too - if( engine->GetRegisteredObjectType(name.AddressOf(), outFunc->nameSpace) != 0 ) + if( engine->GetRegisteredType(name.AddressOf(), outFunc->nameSpace) != 0 ) { asCString str; str.Format(TXT_ILLEGAL_VARIABLE_NAME_s, name.AddressOf()); @@ -2646,20 +2758,20 @@ void asCCompiler::CompileDeclaration(asCScriptNode *decl, asCByteCode *bc) } // Returns true if the initialization expression is a constant expression -bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, asCDataType &type, asCScriptNode *errNode, int offset, asQWORD *constantValue, int isVarGlobOrMem, asSExprContext *preCompiled) +bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, const asCDataType &type, asCScriptNode *errNode, int offset, asQWORD *constantValue, int isVarGlobOrMem, asCExprContext *preCompiled) { bool isConstantExpression = false; if( node && node->nodeType == snArgList ) { // Make sure it is an object and not a handle - if( type.GetObjectType() == 0 || type.IsObjectHandle() ) + if( type.GetTypeInfo() == 0 || type.IsObjectHandle() ) { Error(TXT_MUST_BE_OBJECT, node); } else { // Compile the arguments - asCArray args; + asCArray args; asCArray namedArgs; if( CompileArgumentList(node, args, namedArgs) >= 0 ) { @@ -2668,7 +2780,7 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as asSTypeBehaviour *beh = type.GetBehaviour(); if( beh ) { - if( type.GetObjectType()->flags & asOBJ_REF ) + if( type.GetTypeInfo()->flags & asOBJ_REF ) funcs = beh->factories; else funcs = beh->constructors; @@ -2680,12 +2792,12 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as if( funcs.GetLength() == 1 ) { // Add the default values for arguments not explicitly supplied - int r = CompileDefaultAndNamedArgs(node, args, funcs[0], type.GetObjectType(), &namedArgs); + int r = CompileDefaultAndNamedArgs(node, args, funcs[0], CastToObjectType(type.GetTypeInfo()), &namedArgs); if( r == asSUCCESS ) { - asSExprContext ctx(engine); - if( type.GetObjectType() && (type.GetObjectType()->flags & asOBJ_REF) ) + asCExprContext ctx(engine); + if( type.GetTypeInfo() && (type.GetTypeInfo()->flags & asOBJ_REF) ) { if( isVarGlobOrMem == 0 ) MakeFunctionCall(&ctx, funcs[0], 0, args, node, true, offset); @@ -2703,9 +2815,12 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as // Store the returned handle in the member ctx.bc.InstrSHORT(asBC_PSF, 0); ctx.bc.Instr(asBC_RDSPtr); - ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); } - ctx.bc.InstrPTR(asBC_REFCPY, type.GetObjectType()); + if( type.IsFuncdef()) + ctx.bc.InstrPTR(asBC_REFCPY, &engine->functionBehaviours); + else + ctx.bc.InstrPTR(asBC_REFCPY, type.GetTypeInfo()); ReleaseTemporaryVariable(ctx.type.stackOffset, &ctx.bc); } @@ -2736,12 +2851,12 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as else { // Value types may be allocated inline if they are POD types - onHeap = !type.IsObject() || type.IsReference() || (type.GetObjectType()->flags & asOBJ_REF); + onHeap = !(type.IsObject() || type.IsFuncdef()) || type.IsReference() || (type.GetTypeInfo()->flags & asOBJ_REF); if( onHeap ) { ctx.bc.InstrSHORT(asBC_PSF, 0); ctx.bc.Instr(asBC_RDSPtr); - ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); } } @@ -2756,7 +2871,7 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as { ctx.bc.InstrSHORT(asBC_PSF, 0); ctx.bc.Instr(asBC_RDSPtr); - ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); } else { @@ -2764,7 +2879,7 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as } } - PerformFunctionCall(funcs[0], &ctx, onHeap, &args, type.GetObjectType()); + PerformFunctionCall(funcs[0], &ctx, onHeap, &args, CastToObjectType(type.GetTypeInfo())); if( isVarGlobOrMem == 0 ) { @@ -2781,18 +2896,18 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as for( asUINT n = 0; n < args.GetLength(); n++ ) if( args[n] ) { - asDELETE(args[n],asSExprContext); + asDELETE(args[n], asCExprContext); } for( asUINT n = 0; n < namedArgs.GetLength(); n++ ) if( namedArgs[n].ctx ) { - asDELETE(namedArgs[n].ctx,asSExprContext); + asDELETE(namedArgs[n].ctx, asCExprContext); } } } else if( node && node->nodeType == snInitList ) { - asCTypeInfo ti; + asCExprValue ti; ti.Set(type); ti.isVariable = (isVarGlobOrMem == 0); ti.isTemporary = false; @@ -2803,11 +2918,9 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as } else if( node && node->nodeType == snAssignment ) { - asSExprContext ctx(engine); - // Compile the expression - asSExprContext newExpr(engine); - asSExprContext* expr; + asCExprContext newExpr(engine); + asCExprContext* expr; int r = 0; if( preCompiled ) @@ -2820,24 +2933,29 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as r = CompileAssignment(node, expr); } + // handles initialized with null doesn't need any bytecode + // since handles will be initialized to null by default anyway + if (type.IsObjectHandle() && expr->type.IsNullConstant() && expr->bc.IsSimpleExpression() ) + return false; + // Look for appropriate constructor asCArray funcs; - asCArray args; + asCArray args; // Handles must use the handle assignment operation. // Types that are ASHANDLE must not allow the use of the constructor in this case, // because it is ambiguous whether a value assignment or handle assignment will be done. - // Only do this if the expression is of the same type, as the expression is an assignment + // Only do this if the expression is of the same type, as the expression is an assignment // and an initialization constructor may not have the same meaning. // TODO: Should allow initialization constructor if it is declared as allowed for implicit conversions. if( !type.IsObjectHandle() && !expr->type.isExplicitHandle && - !(type.GetObjectType() && (type.GetObjectType()->GetFlags() & asOBJ_ASHANDLE)) && + !(type.GetTypeInfo() && (type.GetTypeInfo()->GetFlags() & asOBJ_ASHANDLE)) && type.IsEqualExceptRefAndConst(expr->type.dataType) ) { asSTypeBehaviour *beh = type.GetBehaviour(); if( beh ) { - if( type.GetObjectType()->flags & asOBJ_REF ) + if( type.GetTypeInfo()->flags & asOBJ_REF ) funcs = beh->factories; else funcs = beh->constructors; @@ -2846,6 +2964,14 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as asCString str = type.Format(outFunc->nameSpace); args.PushLast(expr); MatchFunctions(funcs, args, node, str.AddressOf(), 0, 0, 0, true); + + // Make sure the argument is of the right type (and not just compatible with the expression) + if (funcs.GetLength() == 1) + { + asCScriptFunction *f = engine->scriptFunctions[funcs[0]]; + if (!f->parameterTypes[0].IsEqualExceptRefAndConst(expr->type.dataType)) + funcs.PopLast(); + } } if( funcs.GetLength() == 1 ) @@ -2855,12 +2981,12 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as // TODO: clean-up: A large part of this is identical to the initalization with argList above // Add the default values for arguments not explicitly supplied - int r = CompileDefaultAndNamedArgs(node, args, funcs[0], type.GetObjectType()); + r = CompileDefaultAndNamedArgs(node, args, funcs[0], CastToObjectType(type.GetTypeInfo())); if( r == asSUCCESS ) { - asSExprContext ctx(engine); - if( type.GetObjectType() && (type.GetObjectType()->flags & asOBJ_REF) ) + asCExprContext ctx(engine); + if( type.GetTypeInfo() && (type.GetTypeInfo()->flags & asOBJ_REF) ) { if( isVarGlobOrMem == 0 ) MakeFunctionCall(&ctx, funcs[0], 0, args, node, true, offset); @@ -2878,9 +3004,12 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as // Store the returned handle in the member ctx.bc.InstrSHORT(asBC_PSF, 0); ctx.bc.Instr(asBC_RDSPtr); - ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); } - ctx.bc.InstrPTR(asBC_REFCPY, type.GetObjectType()); + if( type.IsFuncdef() ) + ctx.bc.InstrPTR(asBC_REFCPY, &engine->functionBehaviours); + else + ctx.bc.InstrPTR(asBC_REFCPY, type.GetTypeInfo()); ReleaseTemporaryVariable(ctx.type.stackOffset, &ctx.bc); } @@ -2911,12 +3040,12 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as else { // Value types may be allocated inline if they are POD types - onHeap = !type.IsObject() || type.IsReference() || (type.GetObjectType()->flags & asOBJ_REF); + onHeap = !(type.IsObject() || type.IsFuncdef()) || type.IsReference() || (type.GetTypeInfo()->flags & asOBJ_REF); if( onHeap ) { ctx.bc.InstrSHORT(asBC_PSF, 0); ctx.bc.Instr(asBC_RDSPtr); - ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); } } @@ -2931,7 +3060,7 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as { ctx.bc.InstrSHORT(asBC_PSF, 0); ctx.bc.Instr(asBC_RDSPtr); - ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); } else { @@ -2939,7 +3068,7 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as } } - PerformFunctionCall(funcs[0], &ctx, onHeap, &args, type.GetObjectType()); + PerformFunctionCall(funcs[0], &ctx, onHeap, &args, CastToObjectType(type.GetTypeInfo())); if( isVarGlobOrMem == 0 ) { @@ -2953,6 +3082,7 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as else { // Call the default constructur, then call the assignment operator + asCExprContext ctx(engine); // Call the default constructor here if( isVarGlobOrMem == 0 ) @@ -2972,10 +3102,10 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as // Tell caller that the expression is a constant so it can mark the variable as pure constant isConstantExpression = true; - *constantValue = expr->type.qwordValue; + *constantValue = expr->type.GetConstantData(); } - asSExprContext lctx(engine); + asCExprContext lctx(engine); if( isVarGlobOrMem == 0 ) lctx.type.SetVariable(type, offset, false); else if( isVarGlobOrMem == 1 ) @@ -2997,7 +3127,7 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as // Load the reference of the primitive member into the register lctx.bc.InstrSHORT(asBC_PSF, 0); lctx.bc.Instr(asBC_RDSPtr); - lctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + lctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); lctx.bc.Instr(asBC_PopRPtr); } lctx.type.dataType.MakeReadOnly(false); @@ -3012,7 +3142,7 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as // just the copy constructor. Only if no appropriate constructor is // available should the assignment operator be used. - asSExprContext lexpr(engine); + asCExprContext lexpr(engine); lexpr.type.Set(type); if( isVarGlobOrMem == 0 ) lexpr.type.dataType.MakeReference(IsVariableOnHeap(offset)); @@ -3020,7 +3150,7 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as lexpr.type.dataType.MakeReference(true); else if( isVarGlobOrMem == 2 ) { - if( !lexpr.type.dataType.IsObject() || (lexpr.type.dataType.GetObjectType()->flags & asOBJ_REF) ) + if( !lexpr.type.dataType.IsObject() || lexpr.type.dataType.IsFuncdef() || (lexpr.type.dataType.GetTypeInfo()->flags & asOBJ_REF) ) lexpr.type.dataType.MakeReference(true); } @@ -3044,7 +3174,7 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as { lexpr.bc.InstrSHORT(asBC_PSF, 0); lexpr.bc.Instr(asBC_RDSPtr); - lexpr.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + lexpr.bc.InstrSHORT_DW(asBC_ADDSi, (short)offset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); lexpr.type.stackOffset = -1; } lexpr.type.isLValue = true; @@ -3057,10 +3187,10 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as // and a simple assignment. bool assigned = false; // Even though an ASHANDLE can be an explicit handle the overloaded operator needs to be called - if( lexpr.type.dataType.IsObject() && (!lexpr.type.isExplicitHandle || (lexpr.type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE)) ) + if( (lexpr.type.dataType.IsObject() || lexpr.type.dataType.IsFuncdef()) && (!lexpr.type.isExplicitHandle || (lexpr.type.dataType.GetTypeInfo() && (lexpr.type.dataType.GetTypeInfo()->flags & asOBJ_ASHANDLE))) ) { bool useHndlAssign = lexpr.type.dataType.IsHandleToAsHandleType(); - assigned = CompileOverloadedDualOperator(node, &lexpr, expr, &ctx, useHndlAssign); + assigned = CompileOverloadedDualOperator(node, &lexpr, expr, false, &ctx, useHndlAssign); if( assigned ) { // Pop the resulting value @@ -3085,7 +3215,7 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as if( type.IsReadOnly() && expr->type.isConstant ) { isConstantExpression = true; - *constantValue = expr->type.qwordValue; + *constantValue = expr->type.GetConstantQW(); } // Add expression code to bytecode @@ -3120,7 +3250,7 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as CallDefaultConstructor(type, offset, true, bc, errNode, isVarGlobOrMem); else if( isVarGlobOrMem == 2 ) { - if( !type.IsObject() || type.IsReference() || (type.GetObjectType()->flags & asOBJ_REF) ) + if( !(type.IsObject() || type.IsFuncdef()) || type.IsReference() || (type.GetTypeInfo()->flags & asOBJ_REF) ) CallDefaultConstructor(type, offset, true, bc, errNode, isVarGlobOrMem); else CallDefaultConstructor(type, offset, false, bc, errNode, isVarGlobOrMem); @@ -3130,10 +3260,10 @@ bool asCCompiler::CompileInitialization(asCScriptNode *node, asCByteCode *bc, as return isConstantExpression; } -void asCCompiler::CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByteCode *bc, int isVarGlobOrMem) +void asCCompiler::CompileInitList(asCExprValue *var, asCScriptNode *node, asCByteCode *bc, int isVarGlobOrMem) { // Check if the type supports initialization lists - if( var->dataType.GetObjectType() == 0 || + if( var->dataType.GetTypeInfo() == 0 || var->dataType.GetBehaviour()->listFactory == 0 ) { asCString str; @@ -3156,20 +3286,25 @@ void asCCompiler::CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByte asCObjectType *listPatternType = engine->GetListPatternType(funcId); // Allocate a temporary variable to hold the pointer to the buffer - int bufferVar = AllocateVariable(asCDataType::CreateObject(listPatternType, false), true); + int bufferVar = AllocateVariable(asCDataType::CreateType(listPatternType, false), true); asUINT bufferSize = 0; // Evaluate all elements of the list - asSExprContext valueExpr(engine); + asCExprContext valueExpr(engine); asCScriptNode *el = node; asSListPatternNode *patternNode = engine->scriptFunctions[listPatternType->templateSubTypes[0].GetBehaviour()->listFactory]->listPattern; int elementsInSubList = -1; - int r = CompileInitListElement(patternNode, el, engine->GetTypeIdFromDataType(asCDataType::CreateObject(listPatternType, false)), short(bufferVar), bufferSize, valueExpr.bc, elementsInSubList); + int r = CompileInitListElement(patternNode, el, engine->GetTypeIdFromDataType(asCDataType::CreateType(listPatternType, false)), short(bufferVar), bufferSize, valueExpr.bc, elementsInSubList); asASSERT( r || patternNode == 0 ); - UNUSED_VAR(r); + if (r < 0) + { + asCString msg; + msg.Format(TXT_PREV_ERROR_WHILE_COMP_LIST_FOR_TYPE_s, var->dataType.Format(outFunc->nameSpace).AddressOf()); + Error(msg, node); + } // After all values have been evaluated we know the final size of the buffer - asSExprContext allocExpr(engine); + asCExprContext allocExpr(engine); allocExpr.bc.InstrSHORT_DW(asBC_AllocMem, short(bufferVar), bufferSize); // Merge the bytecode into the final sequence @@ -3177,20 +3312,20 @@ void asCCompiler::CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByte bc->AddCode(&valueExpr.bc); // The object itself is the last to be created and will receive the pointer to the buffer - asCArray args; - asSExprContext arg1(engine); + asCArray args; + asCExprContext arg1(engine); arg1.type.Set(asCDataType::CreatePrimitive(ttUInt, false)); arg1.type.dataType.MakeReference(true); arg1.bc.InstrSHORT(asBC_PshVPtr, short(bufferVar)); args.PushLast(&arg1); - asSExprContext ctx(engine); + asCExprContext ctx(engine); if( var->isVariable ) { asASSERT( isVarGlobOrMem == 0 ); - if( var->dataType.GetObjectType()->GetFlags() & asOBJ_REF ) + if( var->dataType.GetTypeInfo()->GetFlags() & asOBJ_REF ) { ctx.bc.AddCode(&arg1.bc); @@ -3217,7 +3352,7 @@ void asCCompiler::CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByte if( !onHeap ) ctx.bc.InstrSHORT(asBC_PSF, var->stackOffset); - PerformFunctionCall(funcId, &ctx, onHeap, &args, var->dataType.GetObjectType()); + PerformFunctionCall(funcId, &ctx, onHeap, &args, CastToObjectType(var->dataType.GetTypeInfo())); // Mark the object in the local variable as initialized ctx.bc.ObjInfo(var->stackOffset, asOBJ_INIT); @@ -3225,7 +3360,7 @@ void asCCompiler::CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByte } else { - if( var->dataType.GetObjectType()->GetFlags() & asOBJ_REF ) + if( var->dataType.GetTypeInfo()->GetFlags() & asOBJ_REF ) { ctx.bc.AddCode(&arg1.bc); @@ -3242,9 +3377,12 @@ void asCCompiler::CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByte // Store the returned handle in the member ctx.bc.InstrSHORT(asBC_PSF, 0); ctx.bc.Instr(asBC_RDSPtr); - ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)var->stackOffset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)var->stackOffset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); } - ctx.bc.InstrPTR(asBC_REFCPY, var->dataType.GetObjectType()); + if (var->dataType.IsFuncdef()) + ctx.bc.InstrPTR(asBC_REFCPY, &engine->functionBehaviours); + else + ctx.bc.InstrPTR(asBC_REFCPY, var->dataType.GetTypeInfo()); ctx.bc.Instr(asBC_PopPtr); ReleaseTemporaryVariable(ctx.type.stackOffset, &ctx.bc); } @@ -3257,12 +3395,12 @@ void asCCompiler::CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByte ctx.bc.InstrPTR(asBC_PGA, engine->globalProperties[var->stackOffset]->GetAddressOfValue()); else { - onHeap = !var->dataType.IsObject() || var->dataType.IsReference() || (var->dataType.GetObjectType()->flags & asOBJ_REF); + onHeap = !(var->dataType.IsObject() || var->dataType.IsFuncdef()) || var->dataType.IsReference() || (var->dataType.GetTypeInfo()->flags & asOBJ_REF); if( onHeap ) { ctx.bc.InstrSHORT(asBC_PSF, 0); ctx.bc.Instr(asBC_RDSPtr); - ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)var->stackOffset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)var->stackOffset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); } } @@ -3273,11 +3411,11 @@ void asCCompiler::CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByte { ctx.bc.InstrSHORT(asBC_PSF, 0); ctx.bc.Instr(asBC_RDSPtr); - ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)var->stackOffset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false))); + ctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)var->stackOffset, engine->GetTypeIdFromDataType(asCDataType::CreateType(outFunc->objectType, false))); } // Call the ALLOC instruction to allocate memory and invoke constructor - PerformFunctionCall(funcId, &ctx, onHeap, &args, var->dataType.GetObjectType()); + PerformFunctionCall(funcId, &ctx, onHeap, &args, CastToObjectType(var->dataType.GetTypeInfo())); } } @@ -3289,7 +3427,7 @@ void asCCompiler::CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByte ReleaseTemporaryVariable(bufferVar, bc); } -int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScriptNode *&valueNode, int bufferTypeId, short bufferVar, asUINT &bufferSize, asCByteCode &byteCode, int &elementsInSubList) +int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScriptNode *&valueNode, int bufferTypeId, short bufferVar, asUINT &bufferSize, asCByteCode &bcInit, int &elementsInSubList) { if( patternNode->type == asLPT_START ) { @@ -3312,7 +3450,7 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr } asCScriptNode *errNode = node; - int r = CompileInitListElement(patternNode, node, bufferTypeId, bufferVar, bufferSize, byteCode, elementsInSubList); + int r = CompileInitListElement(patternNode, node, bufferTypeId, bufferVar, bufferSize, bcInit, elementsInSubList); if( r < 0 ) return r; if( r == 1 ) @@ -3360,7 +3498,7 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr int elementsInSubSubList = -1; - asSExprContext ctx(engine); + asCExprContext ctx(engine); while( valueNode ) { patternNode = nextNode; @@ -3370,7 +3508,7 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr if( r == 0 ) countElements++; - else + else { asASSERT( r == 1 && engine->ep.disallowEmptyListElements ); if( valueNode ) @@ -3419,10 +3557,10 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr } // The first dword in the buffer will hold the number of elements - byteCode.InstrSHORT_DW_DW(asBC_SetListSize, bufferVar, currSize, countElements); + bcInit.InstrSHORT_DW_DW(asBC_SetListSize, bufferVar, currSize, countElements); // Add the values - byteCode.AddCode(&ctx.bc); + bcInit.AddCode(&ctx.bc); } else if( patternNode->type == asLPT_TYPE ) { @@ -3435,8 +3573,8 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr if( valueNode->nodeType == snAssignment || valueNode->nodeType == snInitList ) { - asSExprContext lctx(engine); - asSExprContext rctx(engine); + asCExprContext lctx(engine); + asCExprContext rctx(engine); if( valueNode->nodeType == snAssignment ) { @@ -3445,6 +3583,9 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr if( dt.GetTokenType() == ttQuestion ) { + // Make sure the type is not ambiguous + DetermineSingleFunc(&rctx, valueNode); + // We now know the type dt = rctx.type.dataType; dt.MakeReadOnly(false); @@ -3455,7 +3596,7 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr bufferSize += 4 - (bufferSize & 0x3); // Place the type id in the buffer - byteCode.InstrSHORT_DW_DW(asBC_SetListType, bufferVar, bufferSize, engine->GetTypeIdFromDataType(dt)); + bcInit.InstrSHORT_DW_DW(asBC_SetListType, bufferVar, bufferSize, engine->GetTypeIdFromDataType(dt)); bufferSize += 4; } } @@ -3491,7 +3632,7 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr } // Determine size of the element - if( dt.IsPrimitive() || (!dt.IsNullHandle() && (dt.GetObjectType()->flags & asOBJ_VALUE)) ) + if( dt.IsPrimitive() || (!dt.IsNullHandle() && (dt.GetTypeInfo()->flags & asOBJ_VALUE)) ) size = dt.GetSizeInMemoryBytes(); else size = AS_PTR_SIZE*4; @@ -3510,51 +3651,47 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr lctx.type.dataType.MakeReference(true); } else if( dt.IsObjectHandle() || - dt.GetObjectType()->flags & asOBJ_REF ) + dt.GetTypeInfo()->flags & asOBJ_REF ) { lctx.type.isExplicitHandle = true; lctx.type.dataType.MakeReference(true); } else { - asASSERT( dt.GetObjectType()->flags & asOBJ_VALUE ); + asASSERT( dt.GetTypeInfo()->flags & asOBJ_VALUE ); // Make sure the object has been constructed before the assignment // TODO: runtime optimize: Use copy constructor instead of assignment to initialize the objects asSTypeBehaviour *beh = dt.GetBehaviour(); int func = 0; if( beh ) func = beh->construct; - if( func == 0 && (dt.GetObjectType()->flags & asOBJ_POD) == 0 ) + if( func == 0 && (dt.GetTypeInfo()->flags & asOBJ_POD) == 0 ) { asCString str; - // TODO: funcdef: asCDataType should have a GetTypeName() - if( dt.GetFuncDef() ) - str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, dt.GetFuncDef()->GetName()); - else - str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, dt.GetObjectType()->GetName()); + str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, dt.GetTypeInfo()->GetName()); Error(str, valueNode); } else if( func ) { // Call the constructor as a normal function - byteCode.InstrSHORT_DW(asBC_PshListElmnt, bufferVar, bufferSize); + bcInit.InstrSHORT_DW(asBC_PshListElmnt, bufferVar, bufferSize); - asSExprContext ctx(engine); - PerformFunctionCall(func, &ctx, false, 0, dt.GetObjectType()); - byteCode.AddCode(&ctx.bc); + asCExprContext ctx(engine); + PerformFunctionCall(func, &ctx, false, 0, CastToObjectType(dt.GetTypeInfo())); + bcInit.AddCode(&ctx.bc); } } if( lctx.type.dataType.IsNullHandle() ) { - // Don't add any code to assign a null handle. RefCpy doesn't work without a known type. + // Don't add any code to assign a null handle. RefCpy doesn't work without a known type. // The buffer is already initialized to zero in asBC_AllocMem anyway. asASSERT( rctx.bc.GetLastInstr() == asBC_PshNull ); asASSERT( reinterpret_cast(patternNode)->dataType.GetTokenType() == ttQuestion ); } else { - asSExprContext ctx(engine); + asCExprContext ctx(engine); DoAssignment(&ctx, &lctx, &rctx, valueNode, valueNode, ttAssignment, valueNode); if( !lctx.type.dataType.IsPrimitive() ) @@ -3565,7 +3702,7 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr ProcessDeferredParams(&ctx); - byteCode.AddCode(&ctx.bc); + bcInit.AddCode(&ctx.bc); } } else @@ -3585,27 +3722,23 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr bufferSize += 4 - (bufferSize & 0x3); // Place the type id for a null handle in the buffer - byteCode.InstrSHORT_DW_DW(asBC_SetListType, bufferVar, bufferSize, 0); + bcInit.InstrSHORT_DW_DW(asBC_SetListType, bufferVar, bufferSize, 0); bufferSize += 4; dt = asCDataType::CreateNullHandle(); // No need to initialize the handle as the buffer is already initialized with zeroes } - else if( dt.GetObjectType() && dt.GetObjectType()->flags & asOBJ_VALUE ) + else if( dt.GetTypeInfo() && dt.GetTypeInfo()->flags & asOBJ_VALUE ) { // For value types with default constructor we need to call the constructor asSTypeBehaviour *beh = dt.GetBehaviour(); int func = 0; if( beh ) func = beh->construct; - if( func == 0 && (dt.GetObjectType()->flags & asOBJ_POD) == 0 ) + if( func == 0 && (dt.GetTypeInfo()->flags & asOBJ_POD) == 0 ) { asCString str; - // TODO: funcdef: asCDataType should have a GetTypeName() - if( dt.GetFuncDef() ) - str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, dt.GetFuncDef()->GetName()); - else - str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, dt.GetObjectType()->GetName()); + str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, dt.GetTypeInfo()->GetName()); Error(str, valueNode); } else if( func ) @@ -3615,14 +3748,14 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr bufferSize += 4 - (bufferSize & 0x3); // Call the constructor as a normal function - byteCode.InstrSHORT_DW(asBC_PshListElmnt, bufferVar, bufferSize); + bcInit.InstrSHORT_DW(asBC_PshListElmnt, bufferVar, bufferSize); - asSExprContext ctx(engine); - PerformFunctionCall(func, &ctx, false, 0, dt.GetObjectType()); - byteCode.AddCode(&ctx.bc); + asCExprContext ctx(engine); + PerformFunctionCall(func, &ctx, false, 0, CastToObjectType(dt.GetTypeInfo())); + bcInit.AddCode(&ctx.bc); } } - else if( !dt.IsObjectHandle() && dt.GetObjectType() && dt.GetObjectType()->flags & asOBJ_REF ) + else if( !dt.IsObjectHandle() && dt.GetTypeInfo() && dt.GetTypeInfo()->flags & asOBJ_REF ) { // For ref types (not handles) we need to call the default factory asSTypeBehaviour *beh = dt.GetBehaviour(); @@ -3631,30 +3764,26 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr if( func == 0 ) { asCString str; - // TODO: funcdef: asCDataType should have a GetTypeName() - if( dt.GetFuncDef() ) - str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, dt.GetFuncDef()->GetName()); - else - str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, dt.GetObjectType()->GetName()); + str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, dt.GetTypeInfo()->GetName()); Error(str, valueNode); } else if( func ) { - asSExprContext rctx(engine); - PerformFunctionCall(func, &rctx, false, 0, dt.GetObjectType()); + asCExprContext rctx(engine); + PerformFunctionCall(func, &rctx, false, 0, CastToObjectType(dt.GetTypeInfo())); // Values on the list must be aligned to 32bit boundaries, except if the type is smaller than 32bit. if( bufferSize & 0x3 ) bufferSize += 4 - (bufferSize & 0x3); - asSExprContext lctx(engine); + asCExprContext lctx(engine); lctx.bc.InstrSHORT_DW(asBC_PshListElmnt, bufferVar, bufferSize); lctx.type.Set(dt); lctx.type.isLValue = true; lctx.type.isExplicitHandle = true; lctx.type.dataType.MakeReference(true); - asSExprContext ctx(engine); + asCExprContext ctx(engine); DoAssignment(&ctx, &lctx, &rctx, valueNode, valueNode, ttAssignment, valueNode); if( !lctx.type.dataType.IsPrimitive() ) @@ -3665,7 +3794,7 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr ProcessDeferredParams(&ctx); - byteCode.AddCode(&ctx.bc); + bcInit.AddCode(&ctx.bc); } } } @@ -3674,7 +3803,7 @@ int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScr if( !isEmpty ) { // Determine size of the element - if( dt.IsPrimitive() || (!dt.IsNullHandle() && (dt.GetObjectType()->flags & asOBJ_VALUE)) ) + if( dt.IsPrimitive() || (!dt.IsNullHandle() && (dt.GetTypeInfo()->flags & asOBJ_VALUE)) ) size = dt.GetSizeInMemoryBytes(); else size = AS_PTR_SIZE*4; @@ -3748,7 +3877,7 @@ void asCCompiler::CompileSwitchStatement(asCScriptNode *snode, bool *, asCByteCo //------------------------------- // Compile the switch expression - asSExprContext expr(engine); + asCExprContext expr(engine); CompileAssignment(snode->firstChild, &expr); // Verify that the expression is a primitive type @@ -3799,7 +3928,7 @@ void asCCompiler::CompileSwitchStatement(asCScriptNode *snode, bool *, asCByteCo if( cnode->firstChild && cnode->firstChild->nodeType == snExpression ) { // Compile expression - asSExprContext c(engine); + asCExprContext c(engine); CompileExpression(cnode->firstChild, &c); // Verify that the result is a constant @@ -3807,24 +3936,24 @@ void asCCompiler::CompileSwitchStatement(asCScriptNode *snode, bool *, asCByteCo Error(TXT_SWITCH_CASE_MUST_BE_CONSTANT, cnode->firstChild); // Verify that the result is an integral number - if( !c.type.dataType.IsIntegerType() && !c.type.dataType.IsUnsignedType() ) + if (!c.type.dataType.IsIntegerType() && !c.type.dataType.IsUnsignedType()) Error(TXT_SWITCH_MUST_BE_INTEGRAL, cnode->firstChild); - - ImplicitConversion(&c, to, cnode->firstChild, asIC_IMPLICIT_CONV, true); - - // Has this case been declared already? - if( caseValues.IndexOf(c.type.intValue) >= 0 ) + else { - Error(TXT_DUPLICATE_SWITCH_CASE, cnode->firstChild); + ImplicitConversion(&c, to, cnode->firstChild, asIC_IMPLICIT_CONV, true); + + // Has this case been declared already? + if (caseValues.IndexOf(c.type.GetConstantDW()) >= 0) + Error(TXT_DUPLICATE_SWITCH_CASE, cnode->firstChild); + + // TODO: Optimize: We can insert the numbers sorted already + + // Store constant for later use + caseValues.PushLast(c.type.GetConstantDW()); + + // Reserve label for this case + caseLabels.PushLast(nextLabel++); } - - // TODO: Optimize: We can insert the numbers sorted already - - // Store constant for later use - caseValues.PushLast(c.type.intValue); - - // Reserve label for this case - caseLabels.PushLast(nextLabel++); } else { @@ -3843,7 +3972,7 @@ void asCCompiler::CompileSwitchStatement(asCScriptNode *snode, bool *, asCByteCo cnode = cnode->next; } - // check for empty switch + // check for empty switch if (caseValues.GetLength() == 0) { Error(TXT_EMPTY_SWITCH, snode); @@ -3854,7 +3983,7 @@ void asCCompiler::CompileSwitchStatement(asCScriptNode *snode, bool *, asCByteCo defaultLabel = breakLabel; //--------------------------------- - // Output the optimized case comparisons + // Output the optimized case comparisons // with jumps to the case code //------------------------------------ @@ -3944,9 +4073,9 @@ void asCCompiler::CompileSwitchStatement(asCScriptNode *snode, bool *, asCByteCo // Add the list of jumps to the correct labels (any holes, jump to default) index = ranges[range]; - for( int n = caseValues[index]; n <= maxRange; n++ ) + for( int i = caseValues[index]; i <= maxRange; i++ ) { - if( caseValues[index] == n ) + if( caseValues[index] == i ) expr.bc.InstrINT(asBC_JMP, caseLabels[index++]); else expr.bc.InstrINT(asBC_JMP, defaultLabel); @@ -3957,13 +4086,12 @@ void asCCompiler::CompileSwitchStatement(asCScriptNode *snode, bool *, asCByteCo else { // Simply make a comparison with each value - int n; - for( n = ranges[range]; n < index; ++n ) + for( int i = ranges[range]; i < index; ++i ) { tmpOffset = AllocateVariable(asCDataType::CreatePrimitive(ttInt, false), true); - expr.bc.InstrSHORT_DW(asBC_SetV4, (short)tmpOffset, caseValues[n]); + expr.bc.InstrSHORT_DW(asBC_SetV4, (short)tmpOffset, caseValues[i]); expr.bc.InstrW_W(asBC_CMPi, offset, tmpOffset); - expr.bc.InstrDWORD(asBC_JZ, caseLabels[n]); + expr.bc.InstrDWORD(asBC_JZ, caseLabels[i]); ReleaseTemporaryVariable(tmpOffset, &expr.bc); } } @@ -4066,12 +4194,12 @@ void asCCompiler::CompileIfStatement(asCScriptNode *inode, bool *hasReturn, asCB int afterLabel = nextLabel++; // Compile the expression - asSExprContext expr(engine); + asCExprContext expr(engine); int r = CompileAssignment(inode->firstChild, &expr); if( r == 0 ) { // Allow value types to be converted to bool using 'bool opImplConv()' - if( expr.type.dataType.GetObjectType() && (expr.type.dataType.GetObjectType()->GetFlags() & asOBJ_VALUE) ) + if( expr.type.dataType.GetTypeInfo() && (expr.type.dataType.GetTypeInfo()->GetFlags() & asOBJ_VALUE) ) ImplicitConversion(&expr, asCDataType::CreatePrimitive(ttBool, false), inode, asIC_IMPLICIT_CONV); if( !expr.type.dataType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, true)) ) @@ -4096,7 +4224,11 @@ void asCCompiler::CompileIfStatement(asCScriptNode *inode, bool *hasReturn, asCB expr.bc.OptimizeLocally(tempVariableOffsets); bc->AddCode(&expr.bc); } - else if( expr.type.dwordValue == 0 ) +#if AS_SIZEOF_BOOL == 1 + else if( expr.type.GetConstantB() == 0 ) +#else + else if (expr.type.GetConstantDW() == 0) +#endif { // Jump to the else case bc->InstrINT(asBC_JMP, afterLabel); @@ -4216,7 +4348,7 @@ void asCCompiler::CompileForStatement(asCScriptNode *fnode, asCByteCode *bc) //----------------------------------- // Compile the condition statement - asSExprContext expr(engine); + asCExprContext expr(engine); asCScriptNode *second = fnode->firstChild->next; if( second->firstChild ) { @@ -4224,7 +4356,7 @@ void asCCompiler::CompileForStatement(asCScriptNode *fnode, asCByteCode *bc) if( r >= 0 ) { // Allow value types to be converted to bool using 'bool opImplConv()' - if( expr.type.dataType.GetObjectType() && (expr.type.dataType.GetObjectType()->GetFlags() & asOBJ_VALUE) ) + if( expr.type.dataType.GetTypeInfo() && (expr.type.dataType.GetTypeInfo()->GetFlags() & asOBJ_VALUE) ) ImplicitConversion(&expr, asCDataType::CreatePrimitive(ttBool, false), second->firstChild, asIC_IMPLICIT_CONV); if( !expr.type.dataType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, true)) ) @@ -4333,12 +4465,12 @@ void asCCompiler::CompileWhileStatement(asCScriptNode *wnode, asCByteCode *bc) bc->Label((short)beforeLabel); // Compile expression - asSExprContext expr(engine); + asCExprContext expr(engine); int r = CompileAssignment(wnode->firstChild, &expr); if( r == 0 ) { // Allow value types to be converted to bool using 'bool opImplConv()' - if( expr.type.dataType.GetObjectType() && (expr.type.dataType.GetObjectType()->GetFlags() & asOBJ_VALUE) ) + if( expr.type.dataType.GetTypeInfo() && (expr.type.dataType.GetTypeInfo()->GetFlags() & asOBJ_VALUE) ) ImplicitConversion(&expr, asCDataType::CreatePrimitive(ttBool, false), wnode->firstChild, asIC_IMPLICIT_CONV); if( !expr.type.dataType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, true)) ) @@ -4427,11 +4559,11 @@ void asCCompiler::CompileDoWhileStatement(asCScriptNode *wnode, asCByteCode *bc) LineInstr(bc, wnode->lastChild->tokenPos); // Compile expression - asSExprContext expr(engine); + asCExprContext expr(engine); CompileAssignment(wnode->lastChild, &expr); // Allow value types to be converted to bool using 'bool opImplConv()' - if( expr.type.dataType.GetObjectType() && (expr.type.dataType.GetObjectType()->GetFlags() & asOBJ_VALUE) ) + if( expr.type.dataType.GetTypeInfo() && (expr.type.dataType.GetTypeInfo()->GetFlags() & asOBJ_VALUE) ) ImplicitConversion(&expr, asCDataType::CreatePrimitive(ttBool, false), wnode->lastChild, asIC_IMPLICIT_CONV); if( !expr.type.dataType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, true)) ) @@ -4518,7 +4650,7 @@ void asCCompiler::CompileExpressionStatement(asCScriptNode *enode, asCByteCode * if( enode->firstChild ) { // Compile the expression - asSExprContext expr(engine); + asCExprContext expr(engine); CompileAssignment(enode->firstChild, &expr); // Must not have unused ambiguous names @@ -4549,8 +4681,11 @@ void asCCompiler::CompileExpressionStatement(asCScriptNode *enode, asCByteCode * } } -void asCCompiler::PrepareTemporaryObject(asCScriptNode *node, asSExprContext *ctx, bool forceOnHeap) +void asCCompiler::PrepareTemporaryVariable(asCScriptNode *node, asCExprContext *ctx, bool forceOnHeap) { + // The input can be either an object or funcdef, either as handle or reference + asASSERT(ctx->type.dataType.IsObject() || ctx->type.dataType.IsFuncdef()); + // If the object already is stored in temporary variable then nothing needs to be done // Note, a type can be temporary without being a variable, in which case it is holding off // on releasing a previously used object. @@ -4579,13 +4714,20 @@ void asCCompiler::PrepareTemporaryObject(asCScriptNode *node, asSExprContext *ct // Objects stored on the stack are not considered references dt.MakeReference(IsVariableOnHeap(offset)); - asCTypeInfo lvalue; + asCExprValue lvalue; lvalue.Set(dt); lvalue.isExplicitHandle = ctx->type.isExplicitHandle; bool isExplicitHandle = ctx->type.isExplicitHandle; + bool prevIsTemp = ctx->type.isTemporary; + int prevStackOffset = ctx->type.stackOffset; + CompileInitAsCopy(dt, offset, &ctx->bc, ctx, node, false); + // Release the previous temporary variable if it hasn't already been released + if( prevIsTemp && tempVariables.Exists(prevStackOffset) ) + ReleaseTemporaryVariable(prevStackOffset, &ctx->bc); + // Push the reference to the temporary variable on the stack ctx->bc.InstrSHORT(asBC_PSF, (short)offset); @@ -4618,7 +4760,7 @@ void asCCompiler::CompileReturnStatement(asCScriptNode *rnode, asCByteCode *bc) if( rnode->firstChild ) { // Compile the expression - asSExprContext expr(engine); + asCExprContext expr(engine); int r = CompileAssignment(rnode->firstChild, &expr); if( r < 0 ) return; @@ -4660,7 +4802,7 @@ void asCCompiler::CompileReturnStatement(asCScriptNode *rnode, asCByteCode *bc) // The type must match exactly as we cannot convert // the reference without loosing the original value if( !(v->type.IsEqualExceptConst(expr.type.dataType) || - (expr.type.dataType.IsObject() && + ((expr.type.dataType.IsObject() || expr.type.dataType.IsFuncdef()) && !expr.type.dataType.IsObjectHandle() && v->type.IsEqualExceptRefAndConst(expr.type.dataType))) || (!v->type.IsReadOnly() && expr.type.dataType.IsReadOnly()) ) @@ -4773,7 +4915,7 @@ void asCCompiler::CompileReturnStatement(asCScriptNode *rnode, asCByteCode *bc) expr.bc.InstrSHORT(asBC_CpyVtoR8, expr.type.stackOffset); } } - else if( v->type.IsObject() ) + else if( v->type.IsObject() || v->type.IsFuncdef() ) { // Value types are returned on the stack, in a location // that has been reserved by the calling function. @@ -4803,7 +4945,7 @@ void asCCompiler::CompileReturnStatement(asCScriptNode *rnode, asCByteCode *bc) } else { - asASSERT( v->type.GetObjectType()->flags & asOBJ_REF ); + asASSERT( (v->type.GetTypeInfo()->flags & asOBJ_REF) || v->type.IsFuncdef() ); // Prepare the expression to be loaded into the object // register. This will place the reference in local variable @@ -4932,7 +5074,7 @@ void asCCompiler::PrintMatchingFuncs(asCArray &funcs, asCScriptNode *node, } } -int asCCompiler::AllocateVariableNotIn(const asCDataType &type, bool isTemporary, bool forceOnHeap, asSExprContext *ctx) +int asCCompiler::AllocateVariableNotIn(const asCDataType &type, bool isTemporary, bool forceOnHeap, asCExprContext *ctx) { int l = int(reservedVariables.GetLength()); ctx->bc.GetVarsUsed(reservedVariables); @@ -4957,7 +5099,7 @@ int asCCompiler::AllocateVariable(const asCDataType &type, bool isTemporary, boo bool isOnHeap = true; if( t.IsPrimitive() || - (t.GetObjectType() && (t.GetObjectType()->GetFlags() & asOBJ_VALUE) && !forceOnHeap) ) + (t.GetTypeInfo() && (t.GetTypeInfo()->GetFlags() & asOBJ_VALUE) && !forceOnHeap) ) { // Primitives and value types (unless overridden) are allocated on the stack isOnHeap = false; @@ -5092,6 +5234,7 @@ void asCCompiler::DeallocateVariable(int offset) } } + // Mark the variable slot available for new allocations n = GetVariableSlot(offset); if( n != -1 ) { @@ -5100,13 +5243,13 @@ void asCCompiler::DeallocateVariable(int offset) } // We might get here if the variable was implicitly declared - // because it was use before a formal declaration, in this case + // because it was used before a formal declaration, in this case // the offset is 0x7FFF asASSERT(offset == 0x7FFF); } -void asCCompiler::ReleaseTemporaryVariable(asCTypeInfo &t, asCByteCode *bc) +void asCCompiler::ReleaseTemporaryVariable(asCExprValue &t, asCByteCode *bc) { if( t.isTemporary ) { @@ -5137,11 +5280,11 @@ void asCCompiler::ReleaseTemporaryVariable(int offset, asCByteCode *bc) DeallocateVariable(offset); } -void asCCompiler::Dereference(asSExprContext *ctx, bool generateCode) +void asCCompiler::Dereference(asCExprContext *ctx, bool generateCode) { if( ctx->type.dataType.IsReference() ) { - if( ctx->type.dataType.IsObject() ) + if( ctx->type.dataType.IsObject() || ctx->type.dataType.IsFuncdef() ) { ctx->type.dataType.MakeReference(false); if( generateCode ) @@ -5155,7 +5298,7 @@ void asCCompiler::Dereference(asSExprContext *ctx, bool generateCode) } } -bool asCCompiler::IsVariableInitialized(asCTypeInfo *type, asCScriptNode *node) +bool asCCompiler::IsVariableInitialized(asCExprValue *type, asCScriptNode *node) { // No need to check if there is no variable scope if( variables == 0 ) return true; @@ -5175,7 +5318,7 @@ bool asCCompiler::IsVariableInitialized(asCTypeInfo *type, asCScriptNode *node) if( v->isInitialized ) return true; // Complex types don't need this test - if( v->type.IsObject() ) return true; + if( v->type.IsObject() || v->type.IsFuncdef() ) return true; // Mark as initialized so that the user will not be bothered again v->isInitialized = true; @@ -5188,7 +5331,7 @@ bool asCCompiler::IsVariableInitialized(asCTypeInfo *type, asCScriptNode *node) return false; } -void asCCompiler::PrepareOperand(asSExprContext *ctx, asCScriptNode *node) +void asCCompiler::PrepareOperand(asCExprContext *ctx, asCScriptNode *node) { // Check if the variable is initialized (if it indeed is a variable) IsVariableInitialized(&ctx->type, node); @@ -5201,7 +5344,7 @@ void asCCompiler::PrepareOperand(asSExprContext *ctx, asCScriptNode *node) ProcessDeferredParams(ctx); } -void asCCompiler::PrepareForAssignment(asCDataType *lvalue, asSExprContext *rctx, asCScriptNode *node, bool toTemporary, asSExprContext *lvalueExpr) +void asCCompiler::PrepareForAssignment(asCDataType *lvalue, asCExprContext *rctx, asCScriptNode *node, bool toTemporary, asCExprContext *lvalueExpr) { // Reserve the temporary variables used in the lvalue expression so they won't end up being used by the rvalue too int l = int(reservedVariables.GetLength()); @@ -5249,14 +5392,14 @@ void asCCompiler::PrepareForAssignment(asCDataType *lvalue, asSExprContext *rctx // TODO: ImplicitConversion should know to do this by itself // First convert to a handle which will do a reference cast if( !lvalue->IsObjectHandle() && - (lvalue->GetObjectType()->flags & asOBJ_SCRIPT_OBJECT) ) + (lvalue->GetTypeInfo()->flags & asOBJ_SCRIPT_OBJECT) ) to.MakeHandle(true); // Don't allow the implicit conversion to create an object ImplicitConversion(rctx, to, node, asIC_IMPLICIT_CONV, true, !toTemporary); if( !lvalue->IsObjectHandle() && - (lvalue->GetObjectType()->flags & asOBJ_SCRIPT_OBJECT) ) + (lvalue->GetTypeInfo()->flags & asOBJ_SCRIPT_OBJECT) ) { // Then convert to a reference, which will validate the handle to.MakeHandle(false); @@ -5273,8 +5416,7 @@ void asCCompiler::PrepareForAssignment(asCDataType *lvalue, asSExprContext *rctx else { // If the assignment will be made with the copy behaviour then the rvalue must not be a reference - if( lvalue->IsObject() ) - asASSERT(!rctx->type.dataType.IsReference()); + asASSERT(!lvalue->IsObject() || !rctx->type.dataType.IsReference()); } } @@ -5282,7 +5424,7 @@ void asCCompiler::PrepareForAssignment(asCDataType *lvalue, asSExprContext *rctx reservedVariables.SetLength(l); } -bool asCCompiler::IsLValue(asCTypeInfo &type) +bool asCCompiler::IsLValue(asCExprValue &type) { if( !type.isLValue ) return false; if( type.dataType.IsReadOnly() ) return false; @@ -5290,7 +5432,7 @@ bool asCCompiler::IsLValue(asCTypeInfo &type) return true; } -int asCCompiler::PerformAssignment(asCTypeInfo *lvalue, asCTypeInfo *rvalue, asCByteCode *bc, asCScriptNode *node) +int asCCompiler::PerformAssignment(asCExprValue *lvalue, asCExprValue *rvalue, asCByteCode *bc, asCScriptNode *node) { if( lvalue->dataType.IsReadOnly() ) { @@ -5333,22 +5475,22 @@ int asCCompiler::PerformAssignment(asCTypeInfo *lvalue, asCTypeInfo *rvalue, asC } else if( !lvalue->isExplicitHandle ) { - asSExprContext ctx(engine); + asCExprContext ctx(engine); ctx.type = *lvalue; Dereference(&ctx, true); *lvalue = ctx.type; bc->AddCode(&ctx.bc); asSTypeBehaviour *beh = lvalue->dataType.GetBehaviour(); - if( beh->copy && beh->copy != engine->scriptTypeBehaviours.beh.copy ) + if( beh && beh->copy && beh->copy != engine->scriptTypeBehaviours.beh.copy ) { - asSExprContext res(engine); - PerformFunctionCall(beh->copy, &res, false, 0, lvalue->dataType.GetObjectType()); + asCExprContext res(engine); + PerformFunctionCall(beh->copy, &res, false, 0, CastToObjectType(lvalue->dataType.GetTypeInfo())); bc->AddCode(&res.bc); *lvalue = res.type; } - else if( beh->copy == engine->scriptTypeBehaviours.beh.copy ) + else if( beh && beh->copy == engine->scriptTypeBehaviours.beh.copy ) { // Call the default copy operator for script classes // This is done differently because the default copy operator @@ -5363,10 +5505,10 @@ int asCCompiler::PerformAssignment(asCTypeInfo *lvalue, asCTypeInfo *rvalue, asC { // Default copy operator if( lvalue->dataType.GetSizeInMemoryDWords() == 0 || - !(lvalue->dataType.GetObjectType()->flags & asOBJ_POD) ) + !(lvalue->dataType.GetTypeInfo()->flags & asOBJ_POD) ) { asCString msg; - msg.Format(TXT_NO_DEFAULT_COPY_OP_FOR_s, lvalue->dataType.GetObjectType()->name.AddressOf()); + msg.Format(TXT_NO_DEFAULT_COPY_OP_FOR_s, lvalue->dataType.GetTypeInfo()->name.AddressOf()); Error(msg, node); return -1; } @@ -5385,7 +5527,10 @@ int asCCompiler::PerformAssignment(asCTypeInfo *lvalue, asCTypeInfo *rvalue, asC return -1; } - bc->InstrPTR(asBC_REFCPY, lvalue->dataType.GetObjectType()); + if( lvalue->dataType.IsFuncdef() ) + bc->InstrPTR(asBC_REFCPY, &engine->functionBehaviours); + else + bc->InstrPTR(asBC_REFCPY, lvalue->dataType.GetTypeInfo()); // Mark variable as initialized if( variables ) @@ -5398,7 +5543,7 @@ int asCCompiler::PerformAssignment(asCTypeInfo *lvalue, asCTypeInfo *rvalue, asC return 0; } -bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, bool isExplicit, asCScriptNode *node, bool generateCode) +bool asCCompiler::CompileRefCast(asCExprContext *ctx, const asCDataType &to, bool isExplicit, asCScriptNode *node, bool generateCode) { bool conversionDone = false; @@ -5409,15 +5554,15 @@ bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, boo bool isConst = ctx->type.dataType.IsObjectConst(); // Find a suitable opCast or opImplCast method - asCObjectType *ot = ctx->type.dataType.GetObjectType(); - for( n = 0; n < ot->methods.GetLength(); n++ ) + asCObjectType *ot = CastToObjectType(ctx->type.dataType.GetTypeInfo()); + for( n = 0; ot && n < ot->methods.GetLength(); n++ ) { asCScriptFunction *func = engine->scriptFunctions[ot->methods[n]]; if( (isExplicit && func->name == "opCast") || func->name == "opImplCast" ) { // Is the operator for the output type? - if( func->returnType.GetObjectType() != to.GetObjectType() ) + if( func->returnType.GetTypeInfo() != to.GetTypeInfo() ) continue; // Can't call a non-const function on a const object @@ -5431,9 +5576,22 @@ bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, boo // Filter the list by constness to remove const methods if there are matching non-const methods FilterConst(ops, !isConst); - // It shouldn't be possible to have more than one - // TODO: Should be allowed to have different behaviours for const and non-const references - asASSERT( ops.GetLength() <= 1 ); + // Give an error more than one opCast methods were found + if (ops.GetLength() > 1) + { + if (isExplicit && generateCode) + { + asCString str; + str.Format(TXT_MULTIPLE_MATCHING_SIGNATURES_TO_s, "opCast"); + Error(str, node); + + PrintMatchingFuncs(ops, node, ot); + } + // Return that the conversion was done to avoid further complaints + conversionDone = true; + ctx->type.Set(to); + return conversionDone; + } // Should only have one behaviour for each output type if( ops.GetLength() == 1 ) @@ -5450,13 +5608,13 @@ bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, boo // functions with 1 parameter, even though they should still be // registered with RegisterObjectBehaviour() - if( ctx->type.dataType.GetObjectType()->flags & asOBJ_REF ) + if( (ctx->type.dataType.GetTypeInfo()->flags & asOBJ_REF) && !(ctx->type.dataType.GetTypeInfo()->flags & asOBJ_NOHANDLE)) { // Add code to avoid calling the cast behaviour if the handle is already null, // because that will raise a null pointer exception due to the cast behaviour // being a class method, and the this pointer cannot be null. - if( !ctx->type.isVariable ) + if (!ctx->type.isVariable) { Dereference(ctx, true); ConvertToVariable(ctx); @@ -5480,8 +5638,8 @@ bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, boo ctx->bc.Instr(asBC_RDSPtr); ctx->type.dataType.MakeReference(false); - asCArray args; - MakeFunctionCall(ctx, ops[0], ctx->type.dataType.GetObjectType(), args, node); + asCArray args; + MakeFunctionCall(ctx, ops[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node); ctx->bc.Instr(asBC_PopPtr); int endLabel = nextLabel++; @@ -5498,11 +5656,15 @@ bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, boo } else { - // Value types cannot be null, so there is no need to check for this + // Value types cannot be null, so there is no need to check for this. + + // Likewise for reference types that are registered with asOBJ_NOHANDLE + // as those are only expected as registered global properties that cannot + // be modified anyway. // Call the cast operator - asCArray args; - MakeFunctionCall(ctx, ops[0], ctx->type.dataType.GetObjectType(), args, node); + asCArray args; + MakeFunctionCall(ctx, ops[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node); } } else @@ -5511,10 +5673,10 @@ bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, boo ctx->type.Set(func->returnType); } } - else if( ops.GetLength() == 0 && !(ctx->type.dataType.GetObjectType()->flags & asOBJ_SCRIPT_OBJECT) ) + else if( ops.GetLength() == 0 && !(ctx->type.dataType.GetTypeInfo()->flags & asOBJ_SCRIPT_OBJECT) ) { // Check for the generic ref cast method: void opCast(?&out) - for( n = 0; n < ot->methods.GetLength(); n++ ) + for( n = 0; ot && n < ot->methods.GetLength(); n++ ) { asCScriptFunction *func = engine->scriptFunctions[ot->methods[n]]; if( (isExplicit && func->name == "opCast") || @@ -5542,14 +5704,49 @@ bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, boo { asASSERT(to.IsObjectHandle()); + int afterLabel = 0; + bool doNullCheck = false; + asCExprContext tmp(engine); + if ((ctx->type.dataType.GetTypeInfo()->flags & asOBJ_REF) && !(ctx->type.dataType.GetTypeInfo()->flags & asOBJ_NOHANDLE)) + { + tmp.bc.AddCode(&ctx->bc); + tmp.Merge(ctx); + + // Add code to avoid calling the cast behaviour if the handle is already null, + // because that will raise a null pointer exception due to the cast behaviour + // being a class method, and the this pointer cannot be null. + doNullCheck = true; + if (!ctx->type.isVariable) + { + Dereference(&tmp, true); + ConvertToVariable(&tmp); + } + + // The reference on the stack will not be used + tmp.bc.Instr(asBC_PopPtr); + + // TODO: runtime optimize: should have immediate comparison for null pointer + int offset = AllocateVariable(asCDataType::CreateNullHandle(), true); + // TODO: runtime optimize: ClrVPtr is not necessary, because the VM should initialize the variable to null anyway (it is currently not done for null pointers though) + tmp.bc.InstrSHORT(asBC_ClrVPtr, (asWORD)offset); + tmp.bc.InstrW_W(asBC_CmpPtr, tmp.type.stackOffset, offset); + DeallocateVariable(offset); + + afterLabel = nextLabel++; + tmp.bc.InstrDWORD(asBC_JZ, afterLabel); + + // Place the object pointer on the stack + ctx->bc.InstrSHORT(asBC_PSF, (short)tmp.type.stackOffset); + } + // Allocate a temporary variable of the requested handle type int stackOffset = AllocateVariableNotIn(to, true, false, ctx); // Pass the reference of that variable to the function as output parameter asCDataType toRef(to); toRef.MakeReference(true); - asCArray args; - asSExprContext arg(engine); + asCArray args; + asCExprContext arg(engine); arg.bc.InstrSHORT(asBC_PSF, (short)stackOffset); // Don't mark the variable as temporary, so it won't be freed too early arg.type.SetVariable(toRef, stackOffset, false); @@ -5558,7 +5755,23 @@ bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, boo args.PushLast(&arg); // Call the behaviour method - MakeFunctionCall(ctx, ops[0], ctx->type.dataType.GetObjectType(), args, node); + MakeFunctionCall(ctx, ops[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node); + + if (doNullCheck) + { + // Add the call after the null check + tmp.bc.AddCode(&ctx->bc); + ctx->bc.AddCode(&tmp.bc); + + int endLabel = nextLabel++; + + ctx->bc.InstrINT(asBC_JMP, endLabel); + ctx->bc.Label((short)afterLabel); + + // Make a NULL pointer + ctx->bc.InstrSHORT(asBC_ClrVPtr, (short)stackOffset); + ctx->bc.Label((short)endLabel); + } // Use the reference to the variable as the result of the expression // Now we can mark the variable as temporary @@ -5573,16 +5786,16 @@ bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, boo } } - // If the script object didn't implement a matching opCast or opImplCast + // If the script object didn't implement a matching opCast or opImplCast // then check if the desired type is part of the hierarchy - if( !conversionDone && (ctx->type.dataType.GetObjectType()->flags & asOBJ_SCRIPT_OBJECT) ) + if( !conversionDone && (ctx->type.dataType.GetTypeInfo()->flags & asOBJ_SCRIPT_OBJECT) ) { // We need it to be a reference if( !ctx->type.dataType.IsReference() ) { - asCDataType to = ctx->type.dataType; - to.MakeReference(true); - ImplicitConversion(ctx, to, 0, isExplicit ? asIC_EXPLICIT_REF_CAST : asIC_IMPLICIT_CONV, generateCode); + asCDataType toRef = ctx->type.dataType; + toRef.MakeReference(true); + ImplicitConversion(ctx, toRef, 0, isExplicit ? asIC_EXPLICIT_REF_CAST : asIC_IMPLICIT_CONV, generateCode); } if( isExplicit ) @@ -5616,10 +5829,10 @@ bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, boo } else { - if( ctx->type.dataType.GetObjectType()->DerivesFrom(to.GetObjectType()) ) + if( CastToObjectType(ctx->type.dataType.GetTypeInfo())->DerivesFrom(to.GetTypeInfo()) ) { conversionDone = true; - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); } } @@ -5631,7 +5844,7 @@ bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, boo return conversionDone; } -asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const asCDataType &toOrig, asCScriptNode *node, EImplicitConv convType, bool generateCode) +asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asCExprContext *ctx, const asCDataType &toOrig, asCScriptNode *node, EImplicitConv convType, bool generateCode) { asCDataType to = toOrig; to.MakeReference(false); @@ -5653,7 +5866,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const // Attempt to resolve an ambiguous enum value asCDataType out; asDWORD value; - if( builder->GetEnumValueFromObjectType(to.GetObjectType(), ctx->enumValue.AddressOf(), out, value) ) + if( builder->GetEnumValueFromType(CastToEnumType(to.GetTypeInfo()), ctx->enumValue.AddressOf(), out, value) ) { ctx->type.SetConstantDW(out, value); ctx->type.dataType.MakeReadOnly(to.IsReadOnly()); @@ -5678,13 +5891,17 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const asUINT cost = asCC_NO_CONV; if( (to.IsIntegerType() || to.IsUnsignedType()) && (ctx->type.dataType.IsFloatType() || ctx->type.dataType.IsDoubleType()) ) cost = asCC_INT_FLOAT_CONV; - else if( (to.IsFloatType() || to.IsDoubleType()) && (ctx->type.dataType.IsIntegerType() || ctx->type.dataType.IsUnsignedType()) ) + else if ((to.IsFloatType() || to.IsDoubleType()) && (ctx->type.dataType.IsIntegerType() || ctx->type.dataType.IsUnsignedType())) cost = asCC_INT_FLOAT_CONV; + else if (ctx->type.dataType.IsEnumType() && to.IsIntegerType() && to.GetSizeInMemoryBytes() == ctx->type.dataType.GetSizeInMemoryBytes() ) + cost = asCC_ENUM_SAME_SIZE_CONV; + else if (ctx->type.dataType.IsEnumType() && to.IsIntegerType() && to.GetSizeInMemoryBytes() != ctx->type.dataType.GetSizeInMemoryBytes()) + cost = asCC_ENUM_DIFF_SIZE_CONV; else if( to.IsUnsignedType() && ctx->type.dataType.IsIntegerType() ) cost = asCC_SIGNED_CONV; else if( to.IsIntegerType() && ctx->type.dataType.IsUnsignedType() ) cost = asCC_SIGNED_CONV; - else if( to.GetSizeInMemoryBytes() || ctx->type.dataType.GetSizeInMemoryBytes() ) + else if( to.GetSizeInMemoryBytes() != ctx->type.dataType.GetSizeInMemoryBytes() ) cost = asCC_PRIMITIVE_SIZE_CONV; // Start by implicitly converting constant values @@ -5732,7 +5949,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const if( ctx->type.dataType.GetSizeInMemoryDWords() == 1 ) { ctx->type.dataType.SetTokenType(to.GetTokenType()); - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); } else { @@ -5748,7 +5965,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const ConvertToTempVariable(ctx); ctx->bc.InstrSHORT(asBC_fTOi, ctx->type.stackOffset); ctx->type.dataType.SetTokenType(to.GetTokenType()); - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); if( convType != asIC_EXPLICIT_VAL_CAST ) Warning(TXT_FLOAT_CONV_TO_INT_CAUSE_TRUNC, node); @@ -5766,7 +5983,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const } // Convert to smaller integer if necessary - int s = to.GetSizeInMemoryBytes(); + s = to.GetSizeInMemoryBytes(); if( s < 4 ) { ConvertToTempVariable(ctx); @@ -5784,7 +6001,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const if( ctx->type.dataType.GetSizeInMemoryDWords() == 2 ) { ctx->type.dataType.SetTokenType(to.GetTokenType()); - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); } else { @@ -5814,7 +6031,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const ConvertToTempVariable(ctx); ctx->bc.InstrSHORT(asBC_dTOi64, ctx->type.stackOffset); ctx->type.dataType.SetTokenType(to.GetTokenType()); - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); if( convType != asIC_EXPLICIT_VAL_CAST ) Warning(TXT_FLOAT_CONV_TO_INT_CAUSE_TRUNC, node); @@ -5828,7 +6045,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const if( ctx->type.dataType.GetSizeInMemoryDWords() == 1 ) { ctx->type.dataType.SetTokenType(to.GetTokenType()); - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); } else { @@ -5844,7 +6061,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const ConvertToTempVariable(ctx); ctx->bc.InstrSHORT(asBC_fTOu, ctx->type.stackOffset); ctx->type.dataType.SetTokenType(to.GetTokenType()); - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); if( convType != asIC_EXPLICIT_VAL_CAST ) Warning(TXT_FLOAT_CONV_TO_INT_CAUSE_TRUNC, node); @@ -5862,7 +6079,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const } // Convert to smaller integer if necessary - int s = to.GetSizeInMemoryBytes(); + s = to.GetSizeInMemoryBytes(); if( s < 4 ) { ConvertToTempVariable(ctx); @@ -5880,7 +6097,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const if( ctx->type.dataType.GetSizeInMemoryDWords() == 2 ) { ctx->type.dataType.SetTokenType(to.GetTokenType()); - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); } else { @@ -5910,7 +6127,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const ConvertToTempVariable(ctx); ctx->bc.InstrSHORT(asBC_dTOu64, ctx->type.stackOffset); ctx->type.dataType.SetTokenType(to.GetTokenType()); - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); if( convType != asIC_EXPLICIT_VAL_CAST ) Warning(TXT_FLOAT_CONV_TO_INT_CAUSE_TRUNC, node); @@ -5923,7 +6140,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const ConvertToTempVariable(ctx); ctx->bc.InstrSHORT(asBC_iTOf, ctx->type.stackOffset); ctx->type.dataType.SetTokenType(to.GetTokenType()); - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); } else if( ctx->type.dataType.IsIntegerType() && ctx->type.dataType.GetSizeInMemoryDWords() == 2 ) { @@ -5938,7 +6155,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const ConvertToTempVariable(ctx); ctx->bc.InstrSHORT(asBC_uTOf, ctx->type.stackOffset); ctx->type.dataType.SetTokenType(to.GetTokenType()); - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); } else if( ctx->type.dataType.IsUnsignedType() && ctx->type.dataType.GetSizeInMemoryDWords() == 2 ) { @@ -5972,7 +6189,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const ConvertToTempVariable(ctx); ctx->bc.InstrSHORT(asBC_i64TOd, ctx->type.stackOffset); ctx->type.dataType.SetTokenType(to.GetTokenType()); - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); } else if( ctx->type.dataType.IsUnsignedType() && ctx->type.dataType.GetSizeInMemoryDWords() == 1 ) { @@ -5987,7 +6204,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const ConvertToTempVariable(ctx); ctx->bc.InstrSHORT(asBC_u64TOd, ctx->type.stackOffset); ctx->type.dataType.SetTokenType(to.GetTokenType()); - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); } else if( ctx->type.dataType.IsFloatType() ) { @@ -6008,7 +6225,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const ctx->type.dataType.IsFloatType() || ctx->type.dataType.IsDoubleType()) ) { ctx->type.dataType.SetTokenType(to.GetTokenType()); - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); } } @@ -6017,9 +6234,9 @@ asUINT asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const return cost; } -asUINT asCCompiler::ImplicitConvLambdaToFunc(asSExprContext *ctx, const asCDataType &to, asCScriptNode * /*node*/, EImplicitConv /*convType*/, bool generateCode) +asUINT asCCompiler::ImplicitConvLambdaToFunc(asCExprContext *ctx, const asCDataType &to, asCScriptNode * /*node*/, EImplicitConv /*convType*/, bool generateCode) { - asASSERT( to.GetFuncDef() && ctx->IsLambda() ); + asASSERT( to.IsFuncdef() && ctx->IsLambda() ); // Check that the lambda has the correct amount of arguments asUINT count = 0; @@ -6031,7 +6248,7 @@ asUINT asCCompiler::ImplicitConvLambdaToFunc(asSExprContext *ctx, const asCDataT } asASSERT( argNode->nodeType == snStatementBlock ); - asCScriptFunction *funcDef = to.GetFuncDef(); + asCScriptFunction *funcDef = CastToFuncdefType(to.GetTypeInfo())->funcdef; if( funcDef->parameterTypes.GetLength() != count ) return asCC_NO_CONV; @@ -6059,14 +6276,25 @@ asUINT asCCompiler::ImplicitConvLambdaToFunc(asSExprContext *ctx, const asCDataT return asCC_CONST_CONV; } -asUINT asCCompiler::ImplicitConversion(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode, bool allowObjectConstruct) +asUINT asCCompiler::ImplicitConversion(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode, bool allowObjectConstruct) { asASSERT( ctx->type.dataType.GetTokenType() != ttUnrecognizedToken || - ctx->type.dataType.IsNullHandle() ); + ctx->type.dataType.IsNullHandle() || + ctx->IsAnonymousInitList() ); - if( to.GetFuncDef() && ctx->IsLambda() ) - { + if( to.IsFuncdef() && ctx->IsLambda() ) return ImplicitConvLambdaToFunc(ctx, to, node, convType, generateCode); + + if (ctx->IsAnonymousInitList()) + { + if (to.GetBehaviour() && to.GetBehaviour()->listFactory) + { + if (generateCode) + CompilerAnonymousInitList(ctx->exprNode, ctx, to); + else + ctx->type.dataType = to; + } + return asCC_NO_CONV; } // No conversion from void to any other type @@ -6099,14 +6327,14 @@ asUINT asCCompiler::ImplicitConversion(asSExprContext *ctx, const asCDataType &t { if( ctx->type.dataType.IsPrimitive() ) return ImplicitConvPrimitiveToObject(ctx, to, node, convType, generateCode, allowObjectConstruct); - else if( ctx->type.IsNullConstant() || ctx->type.dataType.GetObjectType() ) + else if( ctx->type.IsNullConstant() || ctx->type.dataType.GetTypeInfo() ) return ImplicitConvObjectToObject(ctx, to, node, convType, generateCode, allowObjectConstruct); } return asCC_NO_CONV; } -asUINT asCCompiler::ImplicitConvObjectToPrimitive(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode) +asUINT asCCompiler::ImplicitConvObjectToPrimitive(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode) { if( ctx->type.isExplicitHandle ) { @@ -6125,7 +6353,7 @@ asUINT asCCompiler::ImplicitConvObjectToPrimitive(asSExprContext *ctx, const asC // Find matching value cast behaviours // Here we're only interested in those that convert the type to a primitive type asCArray funcs; - asCObjectType *ot = ctx->type.dataType.GetObjectType(); + asCObjectType *ot = CastToObjectType(ctx->type.dataType.GetTypeInfo()); if( ot == 0 ) { if( convType != asIC_IMPLICIT_CONV && node ) @@ -6281,8 +6509,8 @@ asUINT asCCompiler::ImplicitConvObjectToPrimitive(asSExprContext *ctx, const asC asCDataType toRef(to); toRef.MakeReference(true); toRef.MakeReadOnly(false); - asCArray args; - asSExprContext arg(engine); + asCArray args; + asCExprContext arg(engine); // Don't mark the variable as temporary, so it won't be freed too early arg.type.SetVariable(toRef, stackOffset, false); arg.type.isLValue = true; @@ -6290,7 +6518,7 @@ asUINT asCCompiler::ImplicitConvObjectToPrimitive(asSExprContext *ctx, const asC args.PushLast(&arg); // Call the behaviour method - MakeFunctionCall(ctx, funcs[0], ctx->type.dataType.GetObjectType(), args, node); + MakeFunctionCall(ctx, funcs[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node); // Use the reference to the variable as the result of the expression // Now we can mark the variable as temporary @@ -6314,7 +6542,7 @@ asUINT asCCompiler::ImplicitConvObjectToPrimitive(asSExprContext *ctx, const asC } -asUINT asCCompiler::ImplicitConvObjectRef(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode) +asUINT asCCompiler::ImplicitConvObjectRef(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode) { // Convert null to any object type handle, but not to a non-handle type if( ctx->type.IsNullConstant() && ctx->methodName == "" ) @@ -6327,47 +6555,47 @@ asUINT asCCompiler::ImplicitConvObjectRef(asSExprContext *ctx, const asCDataType return asCC_NO_CONV; } - asASSERT(ctx->type.dataType.GetObjectType() || ctx->methodName != ""); + asASSERT(ctx->type.dataType.GetTypeInfo() || ctx->methodName != ""); // First attempt to convert the base type without instantiating another instance - if( to.GetObjectType() != ctx->type.dataType.GetObjectType() && ctx->methodName == "" ) + if( to.GetTypeInfo() != ctx->type.dataType.GetTypeInfo() && ctx->methodName == "" ) { // If the to type is an interface and the from type implements it, then we can convert it immediately - if( ctx->type.dataType.GetObjectType()->Implements(to.GetObjectType()) ) + if( ctx->type.dataType.GetTypeInfo()->Implements(to.GetTypeInfo()) ) { - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); return asCC_REF_CONV; } // If the to type is a class and the from type derives from it, then we can convert it immediately - else if( ctx->type.dataType.GetObjectType()->DerivesFrom(to.GetObjectType()) ) + else if( ctx->type.dataType.GetTypeInfo()->DerivesFrom(to.GetTypeInfo()) ) { - ctx->type.dataType.SetObjectType(to.GetObjectType()); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); return asCC_REF_CONV; } // If the types are not equal yet, then we may still be able to find a reference cast - else if( ctx->type.dataType.GetObjectType() != to.GetObjectType() ) + else if( ctx->type.dataType.GetTypeInfo() != to.GetTypeInfo() ) { // We may still be able to find an implicit ref cast behaviour CompileRefCast(ctx, to, convType == asIC_EXPLICIT_REF_CAST, node, generateCode); // Was the conversion done? - if( ctx->type.dataType.GetObjectType() == to.GetObjectType() ) + if( ctx->type.dataType.GetTypeInfo() == to.GetTypeInfo() ) return asCC_REF_CONV; } } // Convert matching function types - if( to.GetFuncDef() ) + if( to.IsFuncdef() ) { // If the input expression is already a funcdef, check if it can be converted - if( ctx->type.dataType.GetFuncDef() && - to.GetFuncDef() != ctx->type.dataType.GetFuncDef() ) + if( ctx->type.dataType.IsFuncdef() && + to.GetTypeInfo() != ctx->type.dataType.GetTypeInfo() ) { - asCScriptFunction *toFunc = to.GetFuncDef(); - asCScriptFunction *fromFunc = ctx->type.dataType.GetFuncDef(); + asCScriptFunction *toFunc = CastToFuncdefType(to.GetTypeInfo())->funcdef; + asCScriptFunction *fromFunc = CastToFuncdefType(ctx->type.dataType.GetTypeInfo())->funcdef; if( toFunc->IsSignatureExceptNameEqual(fromFunc) ) { - ctx->type.dataType.SetFuncDef(toFunc); + ctx->type.dataType.SetTypeInfo(to.GetTypeInfo()); return asCC_REF_CONV; } } @@ -6399,10 +6627,11 @@ asUINT asCCompiler::ImplicitConvObjectRef(asSExprContext *ctx, const asCDataType builder->GetFunctionDescriptions(name.AddressOf(), funcs, ns); // Check if any of the functions have perfect match + asCScriptFunction *toFunc = CastToFuncdefType(to.GetTypeInfo())->funcdef; for( asUINT n = 0; n < funcs.GetLength(); n++ ) { asCScriptFunction *func = builder->GetFunctionDescription(funcs[n]); - if( to.GetFuncDef()->IsSignatureExceptNameEqual(func) ) + if( toFunc->IsSignatureExceptNameEqual(func) ) { if( generateCode ) { @@ -6417,7 +6646,7 @@ asUINT asCCompiler::ImplicitConvObjectRef(asSExprContext *ctx, const asCDataType } } - ctx->type.dataType = asCDataType::CreateFuncDef(to.GetFuncDef()); + ctx->type.dataType = asCDataType::CreateType(to.GetTypeInfo(), false); return asCC_REF_CONV; } } @@ -6427,16 +6656,16 @@ asUINT asCCompiler::ImplicitConvObjectRef(asSExprContext *ctx, const asCDataType return asCC_NO_CONV; } -asUINT asCCompiler::ImplicitConvObjectValue(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode) +asUINT asCCompiler::ImplicitConvObjectValue(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode) { asUINT cost = asCC_NO_CONV; // If the base type is still different, and we are allowed to instance // another object then we can try an implicit value cast - if( to.GetObjectType() != ctx->type.dataType.GetObjectType() ) + if( to.GetTypeInfo() != ctx->type.dataType.GetTypeInfo() ) { // TODO: Implement support for implicit constructor/factory - asCObjectType *ot = ctx->type.dataType.GetObjectType(); + asCObjectType *ot = CastToObjectType(ctx->type.dataType.GetTypeInfo()); if( ot == 0 ) return cost; @@ -6450,7 +6679,7 @@ asUINT asCCompiler::ImplicitConvObjectValue(asSExprContext *ctx, const asCDataTy // accept both implicit and explicit cast if( (func->name == "opConv" || func->name == "opImplConv") && - func->returnType.GetObjectType() == to.GetObjectType() && + func->returnType.GetTypeInfo() == to.GetTypeInfo() && func->parameterTypes.GetLength() == 0 ) funcs.PushLast(ot->methods[n]); } @@ -6463,7 +6692,7 @@ asUINT asCCompiler::ImplicitConvObjectValue(asSExprContext *ctx, const asCDataTy // accept only implicit cast if( func->name == "opImplConv" && - func->returnType.GetObjectType() == to.GetObjectType() && + func->returnType.GetTypeInfo() == to.GetTypeInfo() && func->parameterTypes.GetLength() == 0 ) funcs.PushLast(ot->methods[n]); } @@ -6538,7 +6767,7 @@ asUINT asCCompiler::ImplicitConvObjectValue(asSExprContext *ctx, const asCDataTy // Pass the reference of that variable to the function as output parameter asCDataType toRef(to); toRef.MakeReference(false); - asSExprContext arg(engine); + asCExprContext arg(engine); arg.bc.InstrSHORT(asBC_PSF, (short)stackOffset); // If this an object on the heap, the pointer must be dereferenced @@ -6550,14 +6779,14 @@ asUINT asCCompiler::ImplicitConvObjectValue(asSExprContext *ctx, const asCDataTy arg.type.isLValue = true; arg.exprNode = node; - // Mark the argument as clean, so that MakeFunctionCall knows it + // Mark the argument as clean, so that MakeFunctionCall knows it // doesn't have to make a copy of it in order to protect the value arg.isCleanArg = true; // Call the behaviour method - asCArray args; + asCArray args; args.PushLast(&arg); - MakeFunctionCall(ctx, funcs[0], ctx->type.dataType.GetObjectType(), args, node); + MakeFunctionCall(ctx, funcs[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node); // Use the reference to the variable as the result of the expression // Now we can mark the variable as temporary @@ -6576,19 +6805,19 @@ asUINT asCCompiler::ImplicitConvObjectValue(asSExprContext *ctx, const asCDataTy return cost; } -asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode, bool allowObjectConstruct) +asUINT asCCompiler::ImplicitConvObjectToObject(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode, bool allowObjectConstruct) { // First try a ref cast asUINT cost = ImplicitConvObjectRef(ctx, to, node, convType, generateCode); // If the desired type is an asOBJ_ASHANDLE then we'll assume it is allowed to implicitly // construct the object through any of the available constructors - if( to.GetObjectType() && (to.GetObjectType()->flags & asOBJ_ASHANDLE) && to.GetObjectType() != ctx->type.dataType.GetObjectType() && allowObjectConstruct ) + if( to.GetTypeInfo() && (to.GetTypeInfo()->flags & asOBJ_ASHANDLE) && to.GetTypeInfo() != ctx->type.dataType.GetTypeInfo() && allowObjectConstruct ) { asCArray funcs; - funcs = to.GetObjectType()->beh.constructors; + funcs = CastToObjectType(to.GetTypeInfo())->beh.constructors; - asCArray args; + asCArray args; args.PushLast(ctx); cost = asCC_TO_OBJECT_CONV + MatchFunctions(funcs, args, node, 0, 0, 0, false, true, false); @@ -6619,7 +6848,7 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat // TODO: This should really reuse the code from CompileConstructCall // Allocate the new object - asCTypeInfo tempObj; + asCExprValue tempObj; tempObj.dataType = to; tempObj.dataType.MakeReference(false); tempObj.stackOffset = (short)AllocateVariable(tempObj.dataType, true); @@ -6630,7 +6859,7 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat bool onHeap = IsVariableOnHeap(tempObj.stackOffset); // Push the address of the object on the stack - asSExprContext e(engine); + asCExprContext e(engine); if( onHeap ) e.bc.InstrSHORT(asBC_VAR, tempObj.stackOffset); @@ -6649,7 +6878,7 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat else e.bc.InstrSHORT(asBC_PSF, tempObj.stackOffset); - PerformFunctionCall(funcs[0], &e, onHeap, &args, tempObj.dataType.GetObjectType()); + PerformFunctionCall(funcs[0], &e, onHeap, &args, CastToObjectType(tempObj.dataType.GetTypeInfo())); // Add tag that the object has been initialized e.bc.ObjInfo(tempObj.stackOffset, asOBJ_INIT); @@ -6668,14 +6897,14 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat } else { - ctx->type.Set(asCDataType::CreateObject(to.GetObjectType(), false)); + ctx->type.Set(asCDataType::CreateType(to.GetTypeInfo(), false)); } } } // If the base type is still different, and we are allowed to instance // another object then we can try an implicit value cast - if( to.GetObjectType() != ctx->type.dataType.GetObjectType() && allowObjectConstruct ) + if( to.GetTypeInfo() != ctx->type.dataType.GetTypeInfo() && allowObjectConstruct ) { // Attempt implicit value cast cost = ImplicitConvObjectValue(ctx, to, node, convType, generateCode); @@ -6683,7 +6912,7 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat // If we still haven't converted the base type to the correct type, then there is // no need to continue as it is not possible to do the conversion - if( to.GetObjectType() != ctx->type.dataType.GetObjectType() ) + if( to.GetTypeInfo() != ctx->type.dataType.GetTypeInfo() ) return asCC_NO_CONV; @@ -6698,13 +6927,25 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat // reference -> reference to handle // object -> reference to handle - // TODO: If the type is handle, then we can't use IsReadOnly to determine the constness of the basetype - - // If the rvalue is a handle to a const object, then - // the lvalue must also be a handle to a const object - if( ctx->type.dataType.IsReadOnly() && !to.IsReadOnly() ) + if( (!ctx->type.dataType.IsObjectHandle() && ctx->type.dataType.IsReadOnly() && !to.IsHandleToConst()) || + (ctx->type.dataType.IsObjectHandle() && ctx->type.dataType.IsHandleToConst() && !to.IsHandleToConst()) ) { - if( convType != asIC_IMPLICIT_CONV ) + // String literals can be implicitly converted to temporary local variables in order to pass them to functions expecting non-const + // TODO: NEWSTRING: Should have an engine property to warn or error on this + if (ctx->type.isConstant && ctx->type.dataType.IsEqualExceptRefAndConst(engine->stringType)) + { + if (generateCode) + PrepareTemporaryVariable(node, ctx); + else + { + ctx->type.dataType.MakeReadOnly(false); + ctx->type.isConstant = false; + } + + // Add the cost for the copy + cost += asCC_TO_OBJECT_CONV; + } + else if( convType != asIC_IMPLICIT_CONV ) { asASSERT(node); asCString str; @@ -6755,7 +6996,10 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat if( ctx->type.dataType.IsReference() ) ctx->bc.Instr(asBC_RDSPtr); ctx->bc.InstrSHORT(asBC_PSF, (short)offset); - ctx->bc.InstrPTR(asBC_REFCPY, dt.GetObjectType()); + if (dt.IsFuncdef()) + ctx->bc.InstrPTR(asBC_REFCPY, &engine->functionBehaviours); + else + ctx->bc.InstrPTR(asBC_REFCPY, dt.GetTypeInfo()); ctx->bc.Instr(asBC_PopPtr); ctx->bc.InstrSHORT(asBC_PSF, (short)offset); @@ -6806,7 +7050,7 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat // If the object already is a temporary variable, then the copy // doesn't have to be made as it is already a unique object - PrepareTemporaryObject(node, ctx); + PrepareTemporaryVariable(node, ctx); ctx->type.dataType.MakeReadOnly(typeIsReadOnly); ctx->type.isExplicitHandle = isExplicitHandle; @@ -6862,7 +7106,7 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat if( generateCode ) { // Make a temporary object with the copy - PrepareTemporaryObject(node, ctx); + PrepareTemporaryVariable(node, ctx); } // In case the object was already in a temporary variable, then the function @@ -6900,7 +7144,7 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat if( ctx->type.dataType.IsReference() ) { - if( ctx->type.isExplicitHandle && ctx->type.dataType.GetObjectType() && (ctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE) ) + if( ctx->type.isExplicitHandle && ctx->type.dataType.GetTypeInfo() && (ctx->type.dataType.GetTypeInfo()->flags & asOBJ_ASHANDLE) ) { // ASHANDLE objects are really value types, so explicit handle can be removed ctx->type.isExplicitHandle = false; @@ -6919,7 +7163,7 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat // A reference to a non-const can be converted to a reference to a const if( to.IsReadOnly() ) ctx->type.dataType.MakeReadOnly(true); - else if( ctx->type.dataType.IsReadOnly() ) + else if( ctx->type.dataType.IsReadOnly() && allowObjectConstruct ) { // A reference to a const can be converted to a reference to a // non-const by copying the object to a temporary variable @@ -6929,7 +7173,7 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat { // If the object already is a temporary variable, then the copy // doesn't have to be made as it is already a unique object - PrepareTemporaryObject(node, ctx); + PrepareTemporaryVariable(node, ctx); } // Add the cost for the copy @@ -6964,7 +7208,7 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat // A value type allocated on the stack is differentiated // by it not being a reference. But it can be handled as // reference by pushing the pointer on the stack - if( (ctx->type.dataType.GetObjectType()->GetFlags() & asOBJ_VALUE) && + if( (ctx->type.dataType.GetTypeInfo()->GetFlags() & asOBJ_VALUE) && (ctx->type.isVariable || ctx->type.isTemporary) && !IsVariableOnHeap(ctx->type.stackOffset) ) { @@ -6983,7 +7227,7 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat // If the object already is a temporary variable, then the copy // doesn't have to be made as it is already a unique object - PrepareTemporaryObject(node, ctx); + PrepareTemporaryVariable(node, ctx); ctx->type.dataType.MakeReadOnly(typeIsReadOnly); @@ -6997,9 +7241,45 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat ctx->type.dataType.MakeReference(IsVariableOnHeap(ctx->type.stackOffset)); } - // TODO: If the variable is an object allocated on the stack the following is not true as the copy may not have been made - // Since it is a new temporary variable it doesn't have to be const - ctx->type.dataType.MakeReadOnly(to.IsReadOnly()); + if (to.IsReadOnly()) + { + // This doesn't cost anything + ctx->type.dataType.MakeReadOnly(true); + } + + if (!to.IsReadOnly() && ctx->type.dataType.IsReadOnly()) + { + // A const object can be converted to a non-const object through a copy + if (allowObjectConstruct || convType == asIC_EXPLICIT_VAL_CAST) + { + ctx->type.dataType.MakeReadOnly(false); + + if (generateCode) + { + // Make a temporary copy of the object in order to make it non-const + PrepareTemporaryVariable(node, ctx); + } + + // Add the cost for the copy + cost += asCC_TO_OBJECT_CONV; + } + + // String literals can be implicitly converted to temporary local variables in order to pass them to functions expecting non-const + // TODO: NEWSTRING: Should have an engine property to warn or error on this + if (ctx->type.isConstant && ctx->type.dataType.IsEqualExceptRefAndConst(engine->stringType)) + { + if (generateCode) + PrepareTemporaryVariable(node, ctx); + else + { + ctx->type.dataType.MakeReadOnly(false); + ctx->type.isConstant = false; + } + + // Add the cost for the copy + cost += asCC_TO_OBJECT_CONV; + } + } } } } @@ -7007,12 +7287,12 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat return cost; } -asUINT asCCompiler::ImplicitConvPrimitiveToObject(asSExprContext *ctx, const asCDataType &to, asCScriptNode * /*node*/, EImplicitConv /*isExplicit*/, bool generateCode, bool /*allowObjectConstruct*/) +asUINT asCCompiler::ImplicitConvPrimitiveToObject(asCExprContext *ctx, const asCDataType &to, asCScriptNode * /*node*/, EImplicitConv /*isExplicit*/, bool generateCode, bool /*allowObjectConstruct*/) { // Reference types currently don't allow implicit conversion from primitive to object // TODO: Allow implicit conversion to scoped reference types as they are supposed to appear like ordinary value types - asCObjectType *objType = to.GetObjectType(); - asASSERT( objType ); + asCObjectType *objType = CastToObjectType(to.GetTypeInfo()); + asASSERT( objType || CastToFuncdefType(to.GetTypeInfo()) ); if( !objType || (objType->flags & asOBJ_REF) ) return asCC_NO_CONV; @@ -7033,10 +7313,10 @@ asUINT asCCompiler::ImplicitConvPrimitiveToObject(asSExprContext *ctx, const asC return asCC_NO_CONV; // Check if it is possible to choose a best match - asSExprContext arg(engine); + asCExprContext arg(engine); arg.type = ctx->type; arg.exprNode = ctx->exprNode; // Use the same node for compiler messages - asCArray args; + asCArray args; args.PushLast(&arg); asUINT cost = asCC_TO_OBJECT_CONV + MatchFunctions(funcs, args, 0, 0, 0, objType, false, true, false); if( funcs.GetLength() != 1 ) @@ -7054,7 +7334,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToObject(asSExprContext *ctx, const asC ctx->type.SetDummy(); // Value types and script types are allocated through the constructor - asCTypeInfo tempObj; + asCExprValue tempObj; tempObj.dataType = to; tempObj.stackOffset = (short)AllocateVariable(to, true); tempObj.dataType.MakeReference(true); @@ -7085,7 +7365,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToObject(asSExprContext *ctx, const asC else ctx->bc.InstrSHORT(asBC_PSF, tempObj.stackOffset); - PerformFunctionCall(funcs[0], ctx, onHeap, &args, tempObj.dataType.GetObjectType()); + PerformFunctionCall(funcs[0], ctx, onHeap, &args, CastToObjectType(tempObj.dataType.GetTypeInfo())); // Add tag that the object has been initialized ctx->bc.ObjInfo(tempObj.stackOffset, asOBJ_INIT); @@ -7111,7 +7391,7 @@ asUINT asCCompiler::ImplicitConvPrimitiveToObject(asSExprContext *ctx, const asC return cost; } -void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCDataType &to, asCScriptNode *node, EImplicitConv convType) +void asCCompiler::ImplicitConversionConstant(asCExprContext *from, const asCDataType &to, asCScriptNode *node, EImplicitConv convType) { asASSERT(from->type.isConstant); @@ -7133,11 +7413,17 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData from->type.dataType.IsUnsignedType() || from->type.dataType.IsIntegerType() ) { + asCDataType targetDt; + if (to.IsEnumType()) + targetDt = to; + else + targetDt = asCDataType::CreatePrimitive(ttInt, true); + // Transform the value // Float constants can be implicitly converted to int if( from->type.dataType.IsFloatType() ) { - float fc = from->type.floatValue; + float fc = from->type.GetConstantF(); int ic = int(fc); if( float(ic) != fc ) @@ -7145,12 +7431,12 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.intValue = ic; + from->type.SetConstantDW(targetDt, ic); } // Double constants can be implicitly converted to int else if( from->type.dataType.IsDoubleType() ) { - double fc = from->type.doubleValue; + double fc = from->type.GetConstantD(); int ic = int(fc); if( double(ic) != fc ) @@ -7158,42 +7444,60 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.intValue = ic; + from->type.SetConstantDW(targetDt, ic); } else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 1 ) { // Verify that it is possible to convert to signed without getting negative - if( from->type.intValue < 0 ) - { - if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_CHANGE_SIGN, node); - } + if( from->type.dataType.GetSizeInMemoryBytes() == 4 && + int(from->type.GetConstantDW()) < 0 && + convType != asIC_EXPLICIT_VAL_CAST && + node != 0 ) + Warning(TXT_CHANGE_SIGN, node); // Convert to 32bit if( from->type.dataType.GetSizeInMemoryBytes() == 1 ) - from->type.intValue = from->type.byteValue; - else if( from->type.dataType.GetSizeInMemoryBytes() == 2 ) - from->type.intValue = from->type.wordValue; + from->type.SetConstantDW(targetDt, from->type.GetConstantB()); + else if (from->type.dataType.GetSizeInMemoryBytes() == 2) + from->type.SetConstantDW(targetDt, from->type.GetConstantW()); + else + from->type.dataType = targetDt; } else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 2 ) { + if (asQWORD(from->type.GetConstantQW()) >> 31) + if (convType != asIC_EXPLICIT_VAL_CAST && node) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node); + // Convert to 32bit - from->type.intValue = int(from->type.qwordValue); + from->type.SetConstantDW(targetDt, int(from->type.GetConstantQW())); } - else if( from->type.dataType.IsIntegerType() && - from->type.dataType.GetSizeInMemoryBytes() < 4 ) + else if (from->type.dataType.IsIntegerType() && from->type.dataType.GetSizeInMemoryDWords() == 2) + { + if (int(from->type.GetConstantQW()) != asINT64(from->type.GetConstantQW())) + if (convType != asIC_EXPLICIT_VAL_CAST && node) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node); + + // Convert to 32bit + from->type.SetConstantDW(targetDt, int(from->type.GetConstantQW())); + } + else if (from->type.dataType.IsIntegerType() && + from->type.dataType.GetSizeInMemoryBytes() < 4) { // Convert to 32bit - if( from->type.dataType.GetSizeInMemoryBytes() == 1 ) - from->type.intValue = (signed char)from->type.byteValue; - else if( from->type.dataType.GetSizeInMemoryBytes() == 2 ) - from->type.intValue = (short)from->type.wordValue; + if (from->type.dataType.GetSizeInMemoryBytes() == 1) + from->type.SetConstantDW(targetDt, (asINT8)from->type.GetConstantB()); + else if (from->type.dataType.GetSizeInMemoryBytes() == 2) + from->type.SetConstantDW(targetDt, (asINT16)from->type.GetConstantW()); } - - // Set the resulting type - if( to.IsEnumType() ) - from->type.dataType = to; else - from->type.dataType = asCDataType::CreatePrimitive(ttInt, true); + { + // Only int32 and enums should come here and as these are 32bit + // already nothing needs to be done except set the target type + asASSERT((from->type.dataType.GetTokenType() == ttInt || + from->type.dataType.IsEnumType()) && + from->type.dataType.GetSizeInMemoryBytes() == 4); + + from->type.dataType = targetDt; + } } // Check if a downsize is necessary @@ -7204,20 +7508,18 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData // Verify if it is possible if( to.GetSizeInMemoryBytes() == 1 ) { - if( char(from->type.intValue) != from->type.intValue ) + if( asINT8(from->type.GetConstantDW()) != int(from->type.GetConstantDW()) ) if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node); - from->type.byteValue = char(from->type.intValue); + from->type.SetConstantB(asCDataType::CreatePrimitive(to.GetTokenType(), true), asINT8(from->type.GetConstantDW())); } else if( to.GetSizeInMemoryBytes() == 2 ) { - if( short(from->type.intValue) != from->type.intValue ) + if( asINT16(from->type.GetConstantDW()) != int(from->type.GetConstantDW()) ) if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node); - from->type.wordValue = short(from->type.intValue); + from->type.SetConstantW(asCDataType::CreatePrimitive(to.GetTokenType(), true), asINT16(from->type.GetConstantDW())); } - - from->type.dataType = asCDataType::CreatePrimitive(to.GetTokenType(), true); } } else if( to.IsIntegerType() && to.GetSizeInMemoryDWords() == 2 ) @@ -7225,7 +7527,7 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData // Float constants can be implicitly converted to int if( from->type.dataType.IsFloatType() ) { - float fc = from->type.floatValue; + float fc = from->type.GetConstantF(); asINT64 ic = asINT64(fc); if( float(ic) != fc ) @@ -7233,13 +7535,12 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.dataType = asCDataType::CreatePrimitive(ttInt64, true); - from->type.qwordValue = ic; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttInt64, true), ic); } // Double constants can be implicitly converted to int else if( from->type.dataType.IsDoubleType() ) { - double fc = from->type.doubleValue; + double fc = from->type.GetConstantD(); asINT64 ic = asINT64(fc); if( double(ic) != fc ) @@ -7247,46 +7548,42 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.dataType = asCDataType::CreatePrimitive(ttInt64, true); - from->type.qwordValue = ic; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttInt64, true), ic); } else if( from->type.dataType.IsUnsignedType() ) { // Convert to 64bit if( from->type.dataType.GetSizeInMemoryBytes() == 1 ) - from->type.qwordValue = from->type.byteValue; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttInt64, true), from->type.GetConstantB()); else if( from->type.dataType.GetSizeInMemoryBytes() == 2 ) - from->type.qwordValue = from->type.wordValue; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttInt64, true), from->type.GetConstantW()); else if( from->type.dataType.GetSizeInMemoryBytes() == 4 ) - from->type.qwordValue = from->type.dwordValue; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttInt64, true), from->type.GetConstantDW()); else if( from->type.dataType.GetSizeInMemoryBytes() == 8 ) { - if( asINT64(from->type.qwordValue) < 0 ) + if( asINT64(from->type.GetConstantQW()) < 0 ) { if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_CHANGE_SIGN, node); } + from->type.dataType = asCDataType::CreatePrimitive(ttInt64, true); } - - from->type.dataType = asCDataType::CreatePrimitive(ttInt64, true); } else if( from->type.dataType.IsIntegerType() ) { // Convert to 64bit if( from->type.dataType.GetSizeInMemoryBytes() == 1 ) - from->type.qwordValue = (signed char)from->type.byteValue; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttInt64, true), (asINT8)from->type.GetConstantB()); else if( from->type.dataType.GetSizeInMemoryBytes() == 2 ) - from->type.qwordValue = (short)from->type.wordValue; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttInt64, true), (asINT16)from->type.GetConstantW()); else if( from->type.dataType.GetSizeInMemoryBytes() == 4 ) - from->type.qwordValue = from->type.intValue; - - from->type.dataType = asCDataType::CreatePrimitive(ttInt64, true); + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttInt64, true), (int)from->type.GetConstantDW()); } } else if( to.IsUnsignedType() && to.GetSizeInMemoryDWords() == 1 ) { if( from->type.dataType.IsFloatType() ) { - float fc = from->type.floatValue; + float fc = from->type.GetConstantF(); // Some compilers set the value to 0 when converting a negative float to unsigned int. // To maintain a consistent behaviour across compilers we convert to int first. asUINT uic = asUINT(int(fc)); @@ -7296,15 +7593,14 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.dataType = asCDataType::CreatePrimitive(ttUInt, true); - from->type.intValue = uic; + from->type.SetConstantDW(asCDataType::CreatePrimitive(ttUInt, true), uic); // Try once more, in case of a smaller type ImplicitConversionConstant(from, to, node, convType); } else if( from->type.dataType.IsDoubleType() ) { - double fc = from->type.doubleValue; + double fc = from->type.GetConstantD(); // Some compilers set the value to 0 when converting a negative double to unsigned int. // To maintain a consistent behaviour across compilers we convert to int first. asUINT uic = asUINT(int(fc)); @@ -7314,8 +7610,7 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.dataType = asCDataType::CreatePrimitive(ttUInt, true); - from->type.intValue = uic; + from->type.SetConstantDW(asCDataType::CreatePrimitive(ttUInt, true), uic); // Try once more, in case of a smaller type ImplicitConversionConstant(from, to, node, convType); @@ -7323,25 +7618,29 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData else if( from->type.dataType.IsIntegerType() ) { // Verify that it is possible to convert to unsigned without loosing negative - if( (from->type.dataType.GetSizeInMemoryBytes() > 4 && asINT64(from->type.qwordValue) < 0) || - (from->type.dataType.GetSizeInMemoryBytes() <= 4 && from->type.intValue < 0) ) + if( (from->type.dataType.GetSizeInMemoryBytes() > 4 && asINT64(from->type.GetConstantQW()) < 0) || + (from->type.dataType.GetSizeInMemoryBytes() == 4 && int(from->type.GetConstantDW()) < 0) || + (from->type.dataType.GetSizeInMemoryBytes() == 2 && asINT16(from->type.GetConstantW()) < 0) || + (from->type.dataType.GetSizeInMemoryBytes() == 1 && asINT8(from->type.GetConstantB()) < 0)) { if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_CHANGE_SIGN, node); } // Check if any data is lost - if( from->type.dataType.GetSizeInMemoryBytes() > 4 && (from->type.qwordValue >> 32) != 0 && (from->type.qwordValue >> 32) != 0xFFFFFFFF ) + if( from->type.dataType.GetSizeInMemoryBytes() > 4 && (from->type.GetConstantQW() >> 32) != 0 && (from->type.GetConstantQW() >> 32) != 0xFFFFFFFF ) { if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node); } // Convert to 32bit if( from->type.dataType.GetSizeInMemoryBytes() == 1 ) - from->type.intValue = (signed char)from->type.byteValue; + from->type.SetConstantDW(asCDataType::CreatePrimitive(ttUInt, true), (asINT8)from->type.GetConstantB()); else if( from->type.dataType.GetSizeInMemoryBytes() == 2 ) - from->type.intValue = (short)from->type.wordValue; - - from->type.dataType = asCDataType::CreatePrimitive(ttUInt, true); + from->type.SetConstantDW(asCDataType::CreatePrimitive(ttUInt, true), (asINT16)from->type.GetConstantW()); + else if (from->type.dataType.GetSizeInMemoryBytes() == 4 ) + from->type.SetConstantDW(asCDataType::CreatePrimitive(ttUInt, true), (int)from->type.GetConstantDW()); + else + from->type.SetConstantDW(asCDataType::CreatePrimitive(ttUInt, true), (int)(asINT64)from->type.GetConstantQW()); // Try once more, in case of a smaller type ImplicitConversionConstant(from, to, node, convType); @@ -7351,11 +7650,9 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData { // Convert to 32bit if( from->type.dataType.GetSizeInMemoryBytes() == 1 ) - from->type.dwordValue = from->type.byteValue; + from->type.SetConstantDW(asCDataType::CreatePrimitive(ttUInt, true), from->type.GetConstantB()); else if( from->type.dataType.GetSizeInMemoryBytes() == 2 ) - from->type.dwordValue = from->type.wordValue; - - from->type.dataType = asCDataType::CreatePrimitive(ttUInt, true); + from->type.SetConstantDW(asCDataType::CreatePrimitive(ttUInt, true), from->type.GetConstantW()); // Try once more, in case of a smaller type ImplicitConversionConstant(from, to, node, convType); @@ -7366,27 +7663,32 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData // Verify if it is possible if( to.GetSizeInMemoryBytes() == 1 ) { - if( asBYTE(from->type.dwordValue) != from->type.dwordValue ) + if( asBYTE(from->type.GetConstantDW()) != from->type.GetConstantDW() ) if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node); - from->type.byteValue = asBYTE(from->type.dwordValue); + from->type.SetConstantB(asCDataType::CreatePrimitive(to.GetTokenType(), true), asBYTE(from->type.GetConstantDW())); } else if( to.GetSizeInMemoryBytes() == 2 ) { - if( asWORD(from->type.dwordValue) != from->type.dwordValue ) + if( asWORD(from->type.GetConstantDW()) != from->type.GetConstantDW()) if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node); - from->type.wordValue = asWORD(from->type.dwordValue); + from->type.SetConstantW(asCDataType::CreatePrimitive(to.GetTokenType(), true), asWORD(from->type.GetConstantDW())); } + else if (to.GetSizeInMemoryBytes() == 4) + { + if( asDWORD(from->type.GetConstantQW()) != from->type.GetConstantQW()) + if (convType != asIC_EXPLICIT_VAL_CAST && node) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node); - from->type.dataType = asCDataType::CreatePrimitive(to.GetTokenType(), true); + from->type.SetConstantDW(asCDataType::CreatePrimitive(to.GetTokenType(), true), asDWORD(from->type.GetConstantQW())); + } } } else if( to.IsUnsignedType() && to.GetSizeInMemoryDWords() == 2 ) { if( from->type.dataType.IsFloatType() ) { - float fc = from->type.floatValue; + float fc = from->type.GetConstantF(); // Convert first to int64 then to uint64 to avoid negative float becoming 0 on gnuc base compilers asQWORD uic = asQWORD(asINT64(fc)); @@ -7398,12 +7700,11 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData } #endif - from->type.dataType = asCDataType::CreatePrimitive(ttUInt64, true); - from->type.qwordValue = uic; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttUInt64, true), uic); } else if( from->type.dataType.IsDoubleType() ) { - double fc = from->type.doubleValue; + double fc = from->type.GetConstantD(); // Convert first to int64 then to uint64 to avoid negative float becoming 0 on gnuc base compilers asQWORD uic = asQWORD(asINT64(fc)); @@ -7415,21 +7716,20 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData } #endif - from->type.dataType = asCDataType::CreatePrimitive(ttUInt64, true); - from->type.qwordValue = uic; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttUInt64, true), uic); } else if( from->type.dataType.IsIntegerType() && from->type.dataType.GetSizeInMemoryDWords() == 1 ) { // Convert to 64bit if( from->type.dataType.GetSizeInMemoryBytes() == 1 ) - from->type.qwordValue = (asINT64)(signed char)from->type.byteValue; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttUInt64, true), (asINT64)(asINT8)from->type.GetConstantB()); else if( from->type.dataType.GetSizeInMemoryBytes() == 2 ) - from->type.qwordValue = (asINT64)(short)from->type.wordValue; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttUInt64, true), (asINT64)(asINT16)from->type.GetConstantW()); else if( from->type.dataType.GetSizeInMemoryBytes() == 4 ) - from->type.qwordValue = (asINT64)from->type.intValue; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttUInt64, true), (asINT64)(int)from->type.GetConstantDW()); // Verify that it is possible to convert to unsigned without loosing negative - if( asINT64(from->type.qwordValue) < 0 ) + if( asINT64(from->type.GetConstantQW()) < 0 ) { if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_CHANGE_SIGN, node); } @@ -7439,7 +7739,7 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData else if( from->type.dataType.IsIntegerType() && from->type.dataType.GetSizeInMemoryDWords() == 2 ) { // Verify that it is possible to convert to unsigned without loosing negative - if( asINT64(from->type.qwordValue) < 0 ) + if( asINT64(from->type.GetConstantQW()) < 0 ) { if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_CHANGE_SIGN, node); } @@ -7450,35 +7750,32 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData { // Convert to 64bit if( from->type.dataType.GetSizeInMemoryBytes() == 1 ) - from->type.qwordValue = from->type.byteValue; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttUInt64, true), from->type.GetConstantB()); else if( from->type.dataType.GetSizeInMemoryBytes() == 2 ) - from->type.qwordValue = from->type.wordValue; + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttUInt64, true), from->type.GetConstantW()); else if( from->type.dataType.GetSizeInMemoryBytes() == 4 ) - from->type.qwordValue = from->type.dwordValue; - - from->type.dataType = asCDataType::CreatePrimitive(ttUInt64, true); + from->type.SetConstantQW(asCDataType::CreatePrimitive(ttUInt64, true), from->type.GetConstantDW()); } } else if( to.IsFloatType() ) { if( from->type.dataType.IsDoubleType() ) { - double ic = from->type.doubleValue; + double ic = from->type.GetConstantD(); float fc = float(ic); - from->type.dataType = asCDataType::CreatePrimitive(to.GetTokenType(), true); - from->type.floatValue = fc; + from->type.SetConstantF(asCDataType::CreatePrimitive(to.GetTokenType(), true), fc); } else if( from->type.dataType.IsIntegerType() && from->type.dataType.GetSizeInMemoryDWords() == 1 ) { // Must properly convert value in case the from value is smaller int ic; if( from->type.dataType.GetSizeInMemoryBytes() == 1 ) - ic = (signed char)from->type.byteValue; + ic = (asINT8)from->type.GetConstantB(); else if( from->type.dataType.GetSizeInMemoryBytes() == 2 ) - ic = (short)from->type.wordValue; + ic = (asINT16)from->type.GetConstantW(); else - ic = from->type.intValue; + ic = (int)from->type.GetConstantDW(); float fc = float(ic); if( int(fc) != ic ) @@ -7486,30 +7783,28 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.dataType = asCDataType::CreatePrimitive(to.GetTokenType(), true); - from->type.floatValue = fc; + from->type.SetConstantF(asCDataType::CreatePrimitive(to.GetTokenType(), true), fc); } else if( from->type.dataType.IsIntegerType() && from->type.dataType.GetSizeInMemoryDWords() == 2 ) { - float fc = float(asINT64(from->type.qwordValue)); - if( asINT64(fc) != asINT64(from->type.qwordValue) ) + float fc = float(asINT64(from->type.GetConstantQW())); + if( asINT64(fc) != asINT64(from->type.GetConstantQW()) ) { if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.dataType = asCDataType::CreatePrimitive(to.GetTokenType(), true); - from->type.floatValue = fc; + from->type.SetConstantF(asCDataType::CreatePrimitive(to.GetTokenType(), true), fc); } else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 1 ) { // Must properly convert value in case the from value is smaller unsigned int uic; if( from->type.dataType.GetSizeInMemoryBytes() == 1 ) - uic = from->type.byteValue; + uic = from->type.GetConstantB(); else if( from->type.dataType.GetSizeInMemoryBytes() == 2 ) - uic = from->type.wordValue; + uic = from->type.GetConstantW(); else - uic = from->type.dwordValue; + uic = from->type.GetConstantDW(); float fc = float(uic); if( (unsigned int)(fc) != uic ) @@ -7517,42 +7812,39 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.dataType = asCDataType::CreatePrimitive(to.GetTokenType(), true); - from->type.floatValue = fc; + from->type.SetConstantF(asCDataType::CreatePrimitive(to.GetTokenType(), true), fc); } else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 2 ) { - float fc = float((asINT64)from->type.qwordValue); + float fc = float((asINT64)from->type.GetConstantQW()); - if( asQWORD(fc) != from->type.qwordValue ) + if( asQWORD(fc) != from->type.GetConstantQW()) { if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.dataType = asCDataType::CreatePrimitive(to.GetTokenType(), true); - from->type.floatValue = fc; + from->type.SetConstantF(asCDataType::CreatePrimitive(to.GetTokenType(), true), fc); } } else if( to.IsDoubleType() ) { if( from->type.dataType.IsFloatType() ) { - float ic = from->type.floatValue; + float ic = from->type.GetConstantF(); double fc = double(ic); - from->type.dataType = asCDataType::CreatePrimitive(to.GetTokenType(), true); - from->type.doubleValue = fc; + from->type.SetConstantD(asCDataType::CreatePrimitive(to.GetTokenType(), true), fc); } else if( from->type.dataType.IsIntegerType() && from->type.dataType.GetSizeInMemoryDWords() == 1 ) { // Must properly convert value in case the from value is smaller int ic; if( from->type.dataType.GetSizeInMemoryBytes() == 1 ) - ic = (signed char)from->type.byteValue; + ic = (asINT8)from->type.GetConstantB(); else if( from->type.dataType.GetSizeInMemoryBytes() == 2 ) - ic = (short)from->type.wordValue; + ic = (asINT16)from->type.GetConstantW(); else - ic = from->type.intValue; + ic = (int)from->type.GetConstantDW(); double fc = double(ic); if( int(fc) != ic ) @@ -7560,31 +7852,29 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.dataType = asCDataType::CreatePrimitive(to.GetTokenType(), true); - from->type.doubleValue = fc; + from->type.SetConstantD(asCDataType::CreatePrimitive(to.GetTokenType(), true), fc); } else if( from->type.dataType.IsIntegerType() && from->type.dataType.GetSizeInMemoryDWords() == 2 ) { - double fc = double(asINT64(from->type.qwordValue)); + double fc = double(asINT64(from->type.GetConstantQW())); - if( asINT64(fc) != asINT64(from->type.qwordValue) ) + if( asINT64(fc) != asINT64(from->type.GetConstantQW()) ) { if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.dataType = asCDataType::CreatePrimitive(to.GetTokenType(), true); - from->type.doubleValue = fc; + from->type.SetConstantD(asCDataType::CreatePrimitive(to.GetTokenType(), true), fc); } else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 1 ) { // Must properly convert value in case the from value is smaller unsigned int uic; if( from->type.dataType.GetSizeInMemoryBytes() == 1 ) - uic = from->type.byteValue; + uic = from->type.GetConstantB(); else if( from->type.dataType.GetSizeInMemoryBytes() == 2 ) - uic = from->type.wordValue; + uic = from->type.GetConstantW(); else - uic = from->type.dwordValue; + uic = from->type.GetConstantDW(); double fc = double(uic); if( (unsigned int)(fc) != uic ) @@ -7592,25 +7882,23 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.dataType = asCDataType::CreatePrimitive(to.GetTokenType(), true); - from->type.doubleValue = fc; + from->type.SetConstantD(asCDataType::CreatePrimitive(to.GetTokenType(), true), fc); } else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 2 ) { - double fc = double((asINT64)from->type.qwordValue); + double fc = double((asINT64)from->type.GetConstantQW()); - if( asQWORD(fc) != from->type.qwordValue ) + if( asQWORD(fc) != from->type.GetConstantQW()) { if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node); } - from->type.dataType = asCDataType::CreatePrimitive(to.GetTokenType(), true); - from->type.doubleValue = fc; + from->type.SetConstantD(asCDataType::CreatePrimitive(to.GetTokenType(), true), fc); } } } -int asCCompiler::DoAssignment(asSExprContext *ctx, asSExprContext *lctx, asSExprContext *rctx, asCScriptNode *lexpr, asCScriptNode *rexpr, eTokenType op, asCScriptNode *opNode) +int asCCompiler::DoAssignment(asCExprContext *ctx, asCExprContext *lctx, asCExprContext *rctx, asCScriptNode *lexpr, asCScriptNode *rexpr, eTokenType op, asCScriptNode *opNode) { // Don't allow any operators on expressions that take address of class method // If methodName is set but the type is not an object, then it is a global function @@ -7621,7 +7909,7 @@ int asCCompiler::DoAssignment(asSExprContext *ctx, asSExprContext *lctx, asSExpr } // Implicit handle types should always be treated as handles in assignments - if (lctx->type.dataType.GetObjectType() && (lctx->type.dataType.GetObjectType()->flags & asOBJ_IMPLICIT_HANDLE) ) + if (lctx->type.dataType.GetTypeInfo() && (lctx->type.dataType.GetTypeInfo()->flags & asOBJ_IMPLICIT_HANDLE) ) { lctx->type.dataType.MakeHandle(true); lctx->type.isExplicitHandle = true; @@ -7678,7 +7966,7 @@ int asCCompiler::DoAssignment(asSExprContext *ctx, asSExprContext *lctx, asSExpr if( op != ttAssignment ) { // Compute the operator before the assignment - asCTypeInfo lvalue = lctx->type; + asCExprValue lvalue = lctx->type; if( lctx->type.isTemporary && !lctx->type.isVariable ) { @@ -7688,7 +7976,7 @@ int asCCompiler::DoAssignment(asSExprContext *ctx, asSExprContext *lctx, asSExpr lctx->type.isTemporary = false; } - asSExprContext o(engine); + asCExprContext o(engine); CompileOperator(opNode, lctx, rctx, &o); MergeExprBytecode(rctx, &o); rctx->type = o.type; @@ -7733,13 +8021,13 @@ int asCCompiler::DoAssignment(asSExprContext *ctx, asSExprContext *lctx, asSExpr return -1; } - if( lctx->type.dataType.GetObjectType() && (lctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE) ) + if( lctx->type.dataType.GetTypeInfo() && (lctx->type.dataType.GetTypeInfo()->flags & asOBJ_ASHANDLE) ) { // The object is a value type but that should be treated as a handle // Make sure the right hand value is a handle if( !rctx->type.isExplicitHandle && - !(rctx->type.dataType.GetObjectType() && (rctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE)) ) + !(rctx->type.dataType.GetTypeInfo() && (rctx->type.dataType.GetTypeInfo()->flags & asOBJ_ASHANDLE)) ) { // Function names can be considered handles already if( rctx->methodName == "" ) @@ -7757,9 +8045,14 @@ int asCCompiler::DoAssignment(asSExprContext *ctx, asSExprContext *lctx, asSExpr return -1; } } + + // Mark the right hand expression as explicit handle even if the user didn't do it, otherwise + // the code for moving the argument to the stack may not know to correctly handle the argument type + // in case of variable parameter type. + rctx->type.isExplicitHandle = true; } - if( CompileOverloadedDualOperator(opNode, lctx, rctx, ctx, true) ) + if( CompileOverloadedDualOperator(opNode, lctx, rctx, false, ctx, true) ) { // An overloaded assignment operator was found (or a compilation error occured) return 0; @@ -7776,7 +8069,7 @@ int asCCompiler::DoAssignment(asSExprContext *ctx, asSExprContext *lctx, asSExpr asCDataType dt = lctx->type.dataType; dt.MakeReference(false); - PrepareArgument(&dt, rctx, rexpr, true, asTM_INREF , true); + PrepareArgument(&dt, rctx, rexpr, false, asTM_INREF , true); if( !dt.IsEqualExceptRefAndConst(rctx->type.dataType) ) { asCString str; @@ -7816,7 +8109,7 @@ int asCCompiler::DoAssignment(asSExprContext *ctx, asSExprContext *lctx, asSExpr } // Check for overloaded assignment operator - if( CompileOverloadedDualOperator(opNode, lctx, rctx, ctx) ) + if( CompileOverloadedDualOperator(opNode, lctx, rctx, false, ctx) ) { // An overloaded assignment operator was found (or a compilation error occured) return 0; @@ -7844,7 +8137,7 @@ int asCCompiler::DoAssignment(asSExprContext *ctx, asSExprContext *lctx, asSExpr // the application developer is responsible for making the // implementation safe against unwanted destruction of the input // reference before the time. - bool simpleExpr = (lctx->type.dataType.GetObjectType()->GetFlags() & asOBJ_VALUE) && lctx->bc.IsSimpleExpression(); + bool simpleExpr = (lctx->type.dataType.GetTypeInfo()->GetFlags() & asOBJ_VALUE) && lctx->bc.IsSimpleExpression(); // Implicitly convert the rvalue to the type of the lvalue bool needConversion = false; @@ -7903,13 +8196,15 @@ int asCCompiler::DoAssignment(asSExprContext *ctx, asSExprContext *lctx, asSExpr return 0; } -int asCCompiler::CompileAssignment(asCScriptNode *expr, asSExprContext *ctx) +int asCCompiler::CompileAssignment(asCScriptNode *expr, asCExprContext *ctx) { + asASSERT(expr->nodeType == snAssignment); + asCScriptNode *lexpr = expr->firstChild; if( lexpr->next ) { // Compile the two expression terms - asSExprContext lctx(engine), rctx(engine); + asCExprContext lctx(engine), rctx(engine); int rr = CompileAssignment(lexpr->next->next, &rctx); int lr = CompileCondition(lexpr, &lctx); @@ -7924,9 +8219,9 @@ int asCCompiler::CompileAssignment(asCScriptNode *expr, asSExprContext *ctx) return CompileCondition(lexpr, ctx); } -int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx) +int asCCompiler::CompileCondition(asCScriptNode *expr, asCExprContext *ctx) { - asCTypeInfo ctype; + asCExprValue ctype; // Compile the conditional expression asCScriptNode *cexpr = expr->firstChild; @@ -7934,13 +8229,13 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx) { //------------------------------- // Compile the condition - asSExprContext e(engine); + asCExprContext e(engine); int r = CompileExpression(cexpr, &e); if( r < 0 ) e.type.SetConstantB(asCDataType::CreatePrimitive(ttBool, true), true); // Allow value types to be converted to bool using 'bool opImplConv()' - if( e.type.dataType.GetObjectType() && (e.type.dataType.GetObjectType()->GetFlags() & asOBJ_VALUE) ) + if( e.type.dataType.GetTypeInfo() && (e.type.dataType.GetTypeInfo()->GetFlags() & asOBJ_VALUE) ) ImplicitConversion(&e, asCDataType::CreatePrimitive(ttBool, false), cexpr, asIC_IMPLICIT_CONV); if( r >= 0 && !e.type.dataType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, true)) ) @@ -7957,13 +8252,17 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx) //------------------------------- // Compile the left expression - asSExprContext le(engine); + asCExprContext le(engine); int lr = CompileAssignment(cexpr->next, &le); + // Resolve any function names already + DetermineSingleFunc(&le, cexpr->next); + //------------------------------- // Compile the right expression - asSExprContext re(engine); + asCExprContext re(engine); int rr = CompileAssignment(cexpr->next->next, &re); + DetermineSingleFunc(&re, cexpr->next->next); if( lr >= 0 && rr >= 0 ) { @@ -7980,7 +8279,7 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx) bool isExplicitHandle = le.type.isExplicitHandle || re.type.isExplicitHandle; // Allow a 0 or null in the first case to be implicitly converted to the second type - if( le.type.isConstant && le.type.intValue == 0 && le.type.dataType.IsIntegerType() ) + if( le.type.isConstant && le.type.GetConstantData() == 0 && le.type.dataType.IsIntegerType() ) { asCDataType to = re.type.dataType; to.MakeReference(false); @@ -8036,6 +8335,24 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx) // Set the type of the result ctx->type = le.type; } + else if (le.type.IsNullConstant() && re.type.IsNullConstant()) + { + // Special case for when both results are 'null' + // TODO: Other expressions where both results are identical literal constants can probably also be handled this way + + // Put the code for the condition expression on the output + MergeExprBytecode(ctx, &e); + + // Load the result into the register, but ignore the value since both paths give the same response + ctx->type = e.type; + ConvertToVariable(ctx); + ctx->bc.InstrSHORT(asBC_CpyVtoR4, ctx->type.stackOffset); + ReleaseTemporaryVariable(ctx->type, &ctx->bc); + + // Return a null constant + ctx->bc.Instr(asBC_PshNull); + ctx->type.SetNullConstant(); + } else { // Allow "(a ? b : c) = d;" and "return (a ? b : c);" (where the latter returns the reference) @@ -8046,12 +8363,12 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx) // that would have to be cleaned up after the reference // 3. neither expression can be temporary // - // If either expression is local, the resulting lvalue is not valid - // for return since it is not allowed to return references to local + // If either expression is local, the resulting lvalue is not valid + // for return since it is not allowed to return references to local // variables. // // The reference to the local variable must be loaded into the register, - // the resulting expression must not be considered as a local variable + // the resulting expression must not be considered as a local variable // with a stack offset (i.e. it will not be allowed to use asBC_VAR) if( le.type.isLValue && re.type.isLValue && @@ -8092,7 +8409,7 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx) ctx->bc.Label((short)afterLabel); - // In case the options were to objects, it is necessary to dereference the pointer on + // In case the options were to objects, it is necessary to dereference the pointer on // the stack so it will point to the actual object, instead of the variable if( le.type.dataType.IsReference() && le.type.dataType.IsObject() && !le.type.dataType.IsObjectHandle() ) { @@ -8114,12 +8431,12 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx) ctx->type.isTemporary = false; // Must remember if the reference was to a local variable, since it must not be allowed to be returned - ctx->type.isRefToLocal = le.type.isVariable || le.type.isRefToLocal || re.type.isVariable || re.type.isRefToLocal; + ctx->type.isRefToLocal = le.type.isVariable || le.type.isRefToLocal || re.type.isVariable || re.type.isRefToLocal; } else { // Allocate temporary variable and copy the result to that one - asCTypeInfo temp; + asCExprValue temp; temp = le.type; temp.dataType.MakeReference(false); temp.dataType.MakeReadOnly(false); @@ -8135,7 +8452,7 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx) temp.SetVariable(temp.dataType, offset, true); - // TODO: copy: Use copy constructor if available. See PrepareTemporaryObject() + // TODO: copy: Use copy constructor if available. See PrepareTemporaryVariable() CallDefaultConstructor(temp.dataType, offset, IsVariableOnHeap(offset), &ctx->bc, expr); @@ -8151,7 +8468,7 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx) ReleaseTemporaryVariable(ctx->type, &ctx->bc); // Assign the result of the left expression to the temporary variable - asCTypeInfo rtemp; + asCExprValue rtemp; rtemp = temp; if( rtemp.dataType.IsObjectHandle() ) rtemp.isExplicitHandle = true; @@ -8164,7 +8481,7 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx) ctx->bc.InstrSHORT(asBC_PSF, (short)offset); rtemp.dataType.MakeReference(IsVariableOnHeap(offset)); } - asCTypeInfo result; + asCExprValue result; result = rtemp; PerformAssignment(&result, &le.type, &ctx->bc, cexpr->next); if( !result.dataType.IsPrimitive() ) @@ -8228,50 +8545,10 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx) return 0; } -int asCCompiler::CompileExpression(asCScriptNode *expr, asSExprContext *ctx) +int asCCompiler::CompileExpression(asCScriptNode *expr, asCExprContext *ctx) { asASSERT(expr->nodeType == snExpression); - // Check if this is an initialization of a temp object with an initialization list - if( expr->firstChild && expr->firstChild->nodeType == snDataType ) - { - // TODO: It should be possible to infer the type of the object from where the - // expression will be used. The compilation of the initialization list - // should be deferred until it is known for what it will be used. It will - // then for example be possible to write expressions like: - // - // @dict = {{'key', 'value'}}; - // funcTakingArrayOfInt({1,2,3,4}); - - // Determine the type of the temporary object - asCDataType dt = builder->CreateDataTypeFromNode(expr->firstChild, script, outFunc->nameSpace); - - // Do not allow constructing non-shared types in shared functions - if( outFunc->IsShared() && - dt.GetObjectType() && !dt.GetObjectType()->IsShared() ) - { - asCString msg; - msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetObjectType()->name.AddressOf()); - Error(msg, expr); - } - - // Allocate and initialize the temporary object - int offset = AllocateVariable(dt, true); - CompileInitialization(expr->lastChild, &ctx->bc, dt, expr, offset, 0, 0); - - // Push the reference to the object on the stack - ctx->bc.InstrSHORT(asBC_PSF, (short)offset); - ctx->type.SetVariable(dt, offset, true); - ctx->type.isLValue = false; - - // If the variable is allocated on the heap we have a reference, - // otherwise the actual object pointer is pushed on the stack. - if( IsVariableOnHeap(offset) ) - ctx->type.dataType.MakeReference(true); - - return 0; - } - // Convert to polish post fix, i.e: a+b => ab+ asCArray postfix; ConvertToPostFix(expr, postfix); @@ -8317,7 +8594,7 @@ void asCCompiler::ConvertToPostFix(asCScriptNode *expr, asCArray *postfix, asSExprContext *ctx) +int asCCompiler::CompilePostFixExpression(asCArray *postfix, asCExprContext *ctx) { // Shouldn't send any byte code asASSERT(ctx->bc.GetLastInstr() == -1); @@ -8327,26 +8604,26 @@ int asCCompiler::CompilePostFixExpression(asCArray *postfix, as ctx->type.SetDummy(); // Evaluate the operands and operators - asCArray free; - asCArray expr; + asCArray free; + asCArray expr; int ret = 0; for( asUINT n = 0; ret == 0 && n < postfix->GetLength(); n++ ) { asCScriptNode *node = (*postfix)[n]; if( node->nodeType == snExprTerm ) { - asSExprContext *e = free.GetLength() ? free.PopLast() : asNEW(asSExprContext)(engine); + asCExprContext *e = free.GetLength() ? free.PopLast() : asNEW(asCExprContext)(engine); expr.PushLast(e); e->exprNode = node; ret = CompileExpressionTerm(node, e); } else { - asSExprContext *r = expr.PopLast(); - asSExprContext *l = expr.PopLast(); + asCExprContext *r = expr.PopLast(); + asCExprContext *l = expr.PopLast(); // Now compile the operator - asSExprContext *e = free.GetLength() ? free.PopLast() : asNEW(asSExprContext)(engine); + asCExprContext *e = free.GetLength() ? free.PopLast() : asNEW(asCExprContext)(engine); ret = CompileOperator(node, l, r, e); expr.PushLast(e); @@ -8369,18 +8646,67 @@ int asCCompiler::CompilePostFixExpression(asCArray *postfix, as // Clean up for( asUINT e = 0; e < expr.GetLength(); e++ ) - asDELETE(expr[e], asSExprContext); + asDELETE(expr[e], asCExprContext); for( asUINT f = 0; f < free.GetLength(); f++ ) - asDELETE(free[f], asSExprContext); + asDELETE(free[f], asCExprContext); return ret; } -int asCCompiler::CompileExpressionTerm(asCScriptNode *node, asSExprContext *ctx) +int asCCompiler::CompilerAnonymousInitList(asCScriptNode *node, asCExprContext *ctx, const asCDataType &dt) +{ + asASSERT(node->nodeType == snInitList); + + // Do not allow constructing non-shared types in shared functions + if (outFunc->IsShared() && + dt.GetTypeInfo() && !dt.GetTypeInfo()->IsShared()) + { + asCString msg; + msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetTypeInfo()->name.AddressOf()); + Error(msg, node); + } + + // Allocate and initialize the temporary object + int offset = AllocateVariable(dt, true); + CompileInitialization(node, &ctx->bc, dt, node, offset, 0, 0); + + // Push the reference to the object on the stack + ctx->bc.InstrSHORT(asBC_PSF, (short)offset); + ctx->type.SetVariable(dt, offset, true); + ctx->type.isLValue = false; + + // If the variable is allocated on the heap we have a reference, + // otherwise the actual object pointer is pushed on the stack. + if (IsVariableOnHeap(offset)) + ctx->type.dataType.MakeReference(true); + + return 0; +} + +int asCCompiler::CompileExpressionTerm(asCScriptNode *node, asCExprContext *ctx) { // Shouldn't send any byte code asASSERT(ctx->bc.GetLastInstr() == -1); + // Check if this is an initialization of a temp object with an initialization list + if (node->firstChild ) + { + if (node->firstChild->nodeType == snDataType) + { + // Determine the type of the temporary object + asCDataType dt = builder->CreateDataTypeFromNode(node->firstChild, script, outFunc->nameSpace); + + return CompilerAnonymousInitList(node->lastChild, ctx, dt); + } + else if (node->firstChild->nodeType == snInitList) + { + // As the type is not yet known, the init list will be compiled at a + // later time when the type can be determined from the destination + ctx->SetAnonymousInitList(node->firstChild); + return 0; + } + } + // Set the type as a dummy by default, in case of any compiler errors ctx->type.SetDummy(); @@ -8389,7 +8715,7 @@ int asCCompiler::CompileExpressionTerm(asCScriptNode *node, asSExprContext *ctx) while( vnode->nodeType != snExprValue ) vnode = vnode->next; - asSExprContext v(engine); + asCExprContext v(engine); int r = CompileExpressionValue(vnode, &v); if( r < 0 ) return r; // Compile post fix operators @@ -8414,7 +8740,7 @@ int asCCompiler::CompileExpressionTerm(asCScriptNode *node, asSExprContext *ctx) return 0; } -int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &scope, asSExprContext *ctx, asCScriptNode *errNode, bool isOptional, bool noFunction, bool noGlobal, asCObjectType *objType) +int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &scope, asCExprContext *ctx, asCScriptNode *errNode, bool isOptional, bool noFunction, bool noGlobal, asCObjectType *objType) { bool found = false; @@ -8428,7 +8754,7 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s found = true; if( v->isPureConstant ) - ctx->type.SetConstantQW(v->type, v->constantValue); + ctx->type.SetConstantData(v->type, v->constantValue); else if( v->type.IsPrimitive() ) { if( v->type.IsReference() ) @@ -8441,7 +8767,9 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s else ctx->type.SetVariable(v->type, v->stackOffset, false); - ctx->type.isLValue = true; + // Set as lvalue unless it is a const variable + if( !v->type.IsReadOnly() ) + ctx->type.isLValue = true; } else { @@ -8456,7 +8784,14 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s if( v->type.IsReference() && (!v->type.IsObject() || v->type.IsObjectHandle()) ) ctx->bc.Instr(asBC_RDSPtr); - ctx->type.isLValue = true; + // Mark the object as safe for access unless it is a handle, as the + // life time of the object is guaranteed throughout the scope. + if( !v->type.IsObjectHandle() ) + ctx->type.isHandleSafe = true; + + // Set as lvalue unless it is a const variable + if (!v->type.IsReadOnly()) + ctx->type.isLValue = true; } } @@ -8466,7 +8801,7 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s { if( name == THIS_TOKEN && !objType ) { - asCDataType dt = asCDataType::CreateObject(outFunc->objectType, outFunc->isReadOnly); + asCDataType dt = asCDataType::CreateType(outFunc->objectType, outFunc->IsReadOnly()); // The object pointer is located at stack position 0 ctx->bc.InstrSHORT(asBC_PSF, 0); @@ -8474,23 +8809,26 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s ctx->type.dataType.MakeReference(true); ctx->type.isLValue = true; + // The 'this' handle is always considered safe (i.e. life time guaranteed) + ctx->type.isHandleSafe = true; + found = true; } if( !found ) { // See if there are any matching property accessors - asSExprContext access(engine); + asCExprContext access(engine); if( objType ) - access.type.Set(asCDataType::CreateObject(objType, false)); + access.type.Set(asCDataType::CreateType(objType, false)); else - access.type.Set(asCDataType::CreateObject(outFunc->objectType, outFunc->isReadOnly)); + access.type.Set(asCDataType::CreateType(outFunc->objectType, outFunc->IsReadOnly())); access.type.dataType.MakeReference(true); int r = 0; if( errNode->next && errNode->next->tokenType == ttOpenBracket ) { // This is an index access, check if there is a property accessor that takes an index arg - asSExprContext dummyArg(engine); + asCExprContext dummyArg(engine); r = FindPropertyAccessor(name, &access, &dummyArg, errNode, 0, true); } if( r == 0 ) @@ -8517,9 +8855,9 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s { asCDataType dt; if( objType ) - dt = asCDataType::CreateObject(objType, false); + dt = asCDataType::CreateType(objType, false); else - dt = asCDataType::CreateObject(outFunc->objectType, false); + dt = asCDataType::CreateType(outFunc->objectType, false); asCObjectProperty *prop = builder->GetObjectProperty(dt, name.AddressOf()); if( prop ) { @@ -8577,10 +8915,20 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s { // Objects that are members are not references ctx->type.dataType.MakeReference(false); + + // Objects that are members but not handles are safe as long as the parent object is safe + if (!objType || ctx->type.isHandleSafe) + ctx->type.isHandleSafe = true; + } + else if (ctx->type.dataType.IsObjectHandle()) + { + // Objects accessed through handles cannot be considered safe + // as the handle can be cleared at any time + ctx->type.isHandleSafe = false; } // If the object reference is const, the property will also be const - ctx->type.dataType.MakeReadOnly(outFunc->isReadOnly); + ctx->type.dataType.MakeReadOnly(outFunc->IsReadOnly()); found = true; } @@ -8613,7 +8961,7 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s // The object pointer is located at stack position 0 // This is only done when accessing through the implicit this pointer ctx->bc.InstrSHORT(asBC_PSF, 0); - ctx->type.SetVariable(asCDataType::CreateObject(outFunc->objectType, false), 0, false); + ctx->type.SetVariable(asCDataType::CreateType(outFunc->objectType, false), 0, false); ctx->type.dataType.MakeReference(true); Dereference(ctx, true); } @@ -8638,12 +8986,12 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s if( !found && ns ) { // See if there are any matching global property accessors - asSExprContext access(engine); + asCExprContext access(engine); int r = 0; if( errNode->next && errNode->next->tokenType == ttOpenBracket ) { // This is an index access, check if there is a property accessor that takes an index arg - asSExprContext dummyArg(engine); + asCExprContext dummyArg(engine); r = FindPropertyAccessor(name, &access, &dummyArg, errNode, ns); } if( r == 0 ) @@ -8675,7 +9023,7 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s // Verify that the global property has been compiled already if( isCompiled ) { - if( ctx->type.dataType.GetObjectType() && (ctx->type.dataType.GetObjectType()->flags & asOBJ_IMPLICIT_HANDLE) ) + if( ctx->type.dataType.GetTypeInfo() && (ctx->type.dataType.GetTypeInfo()->flags & asOBJ_IMPLICIT_HANDLE) ) { ctx->type.dataType.MakeHandle(true); ctx->type.isExplicitHandle = true; @@ -8685,8 +9033,8 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s // we can allow the compiler to optimize it. Pure // constants are global constant variables that were // initialized by literal constants. - if( isPureConstant ) - ctx->type.SetConstantQW(prop->type, constantValue); + if (isPureConstant) + ctx->type.SetConstantData(prop->type, constantValue); else { // A shared type must not access global vars, unless they @@ -8724,7 +9072,7 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s // This check is not needed for application registered properties, since they // are guaranteed to be valid by the application itself. if( !isAppProp && - ((ctx->type.dataType.GetObjectType()->flags & asOBJ_VALUE) || + ((ctx->type.dataType.GetTypeInfo()->flags & asOBJ_VALUE) || !ctx->type.dataType.IsObjectHandle()) ) { ctx->bc.Instr(asBC_ChkRefS); @@ -8733,14 +9081,14 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s // If the address pushed on the stack is to a value type or an object // handle, then mark the expression as a reference. Addresses to a reference // type aren't marked as references to get correct behaviour - if( (ctx->type.dataType.GetObjectType()->flags & asOBJ_VALUE) || + if( (ctx->type.dataType.GetTypeInfo()->flags & asOBJ_VALUE) || ctx->type.dataType.IsObjectHandle() ) { ctx->type.dataType.MakeReference(true); } else { - asASSERT( (ctx->type.dataType.GetObjectType()->flags & asOBJ_REF) && !ctx->type.dataType.IsObjectHandle() ); + asASSERT( (ctx->type.dataType.GetTypeInfo()->flags & asOBJ_REF) && !ctx->type.dataType.IsObjectHandle() ); // It's necessary to dereference the pointer so the pointer on the stack will point to the actual object ctx->bc.Instr(asBC_RDSPtr); @@ -8781,27 +9129,17 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s if( !found ) { // The enum type may be declared in a namespace too - asCObjectType *scopeType = 0; + asCTypeInfo *scopeType = 0; if( currScope != "" && currScope != "::" ) { - // Use the last scope name as the enum type - asCString enumType = currScope; - asCString nsScope; - int p = currScope.FindLast("::"); - if( p != -1 ) - { - enumType = currScope.SubString(p+2); - nsScope = currScope.SubString(0, p); - } - - asSNameSpace *ns = engine->FindNameSpace(nsScope.AddressOf()); - if( ns ) - scopeType = builder->GetObjectType(enumType.AddressOf(), ns); + builder->GetNameSpaceByString(currScope, outFunc->objectType ? outFunc->objectType->nameSpace : outFunc->nameSpace, errNode, script, &scopeType, false); + if (CastToEnumType(scopeType) == 0) + scopeType = 0; } asDWORD value = 0; asCDataType dt; - if( scopeType && builder->GetEnumValueFromObjectType(scopeType, name.AddressOf(), dt, value) ) + if( scopeType && builder->GetEnumValueFromType(CastToEnumType(scopeType), name.AddressOf(), dt, value) ) { // scoped enum value found found = true; @@ -8809,10 +9147,10 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s else if( !engine->ep.requireEnumScope ) { // Look for the enum value without explicitly informing the enum type - asSNameSpace *ns = DetermineNameSpace(currScope); + asSNameSpace *nsEnum = DetermineNameSpace(currScope); int e = 0; - if( ns ) - e = builder->GetEnumValue(name.AddressOf(), dt, value, ns); + if(nsEnum) + e = builder->GetEnumValue(name.AddressOf(), dt, value, nsEnum); if( e ) { found = true; @@ -8895,7 +9233,7 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s variables->DeclareVariable(name.AddressOf(), asCDataType::CreatePrimitive(ttInt, false), 0x7FFF, true); // Mark the variable as initialized so that the user will not be bother by it again - sVariable *v = variables->GetVariable(name.AddressOf()); + v = variables->GetVariable(name.AddressOf()); asASSERT(v); if( v ) v->isInitialized = true; } @@ -8907,7 +9245,7 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s return 0; } -int asCCompiler::CompileExpressionValue(asCScriptNode *node, asSExprContext *ctx) +int asCCompiler::CompileExpressionValue(asCScriptNode *node, asCExprContext *ctx) { // Shouldn't receive any byte code asASSERT(ctx->bc.GetLastInstr() == -1); @@ -8931,7 +9269,17 @@ int asCCompiler::CompileExpressionValue(asCScriptNode *node, asSExprContext *ctx { asCString value(&script->code[vnode->tokenPos], vnode->tokenLength); - asQWORD val = asStringScanUInt64(value.AddressOf(), 10, 0); + bool overflow = false; + asQWORD val = asStringScanUInt64(value.AddressOf(), 10, 0, &overflow); + + // Is the number bigger than a 64bit word? + if (overflow) + { + Error(TXT_VALUE_TOO_LARGE_FOR_TYPE, vnode); + + // Set the value to zero to avoid further warnings + val = 0; + } // Do we need 64 bits? // If the 31st bit is set we'll treat the value as a signed 64bit number to avoid @@ -8952,8 +9300,17 @@ int asCCompiler::CompileExpressionValue(asCScriptNode *node, asSExprContext *ctx asCString value(&script->code[vnode->tokenPos], vnode->tokenLength); // Let the function determine the radix from the prefix 0x = 16, 0d = 10, 0o = 8, or 0b = 2 - // TODO: Check for overflow - asQWORD val = asStringScanUInt64(value.AddressOf(), 0, 0); + bool overflow = false; + asQWORD val = asStringScanUInt64(value.AddressOf(), 0, 0, &overflow); + + // Is the number bigger than a 64bit word? + if (overflow) + { + Error(TXT_VALUE_TOO_LARGE_FOR_TYPE, vnode); + + // Set the value to zero to avoid further warnings + val = 0; + } // Do we need 64 bits? if( val>>32 ) @@ -9007,7 +9364,7 @@ int asCCompiler::CompileExpressionValue(asCScriptNode *node, asSExprContext *ctx str.Assign(&script->code[snode->tokenPos+1], snode->tokenLength-2); asDWORD val = 0; - if( str.GetLength() && (unsigned char)str[0] > 127 && engine->ep.scanner == 1 ) + if( str.GetLength() && (asBYTE)str[0] > 127 && engine->ep.scanner == 1 ) { // This is the start of a UTF8 encoded character. We need to decode it val = asStringDecodeUTF8(str.AddressOf(), 0); @@ -9054,8 +9411,7 @@ int asCCompiler::CompileExpressionValue(asCScriptNode *node, asSExprContext *ctx } // Call the string factory function to create a string object - asCScriptFunction *descr = engine->stringFactory; - if( descr == 0 ) + if(engine->stringFactory == 0 ) { // Error Error(TXT_STRINGS_NOT_RECOGNIZED, vnode); @@ -9066,21 +9422,27 @@ int asCCompiler::CompileExpressionValue(asCScriptNode *node, asSExprContext *ctx } else { - // Register the constant string with the engine - int id = engine->AddConstantString(str.AddressOf(), str.GetLength()); - ctx->bc.InstrWORD(asBC_STR, (asWORD)id); - - bool useVariable = false; - int stackOffset = 0; - - if( descr->DoesReturnOnStack() ) + void *strPtr = const_cast(engine->stringFactory->GetStringConstant(str.AddressOf(), (asUINT)str.GetLength())); + if (strPtr == 0) { - useVariable = true; - stackOffset = AllocateVariable(descr->returnType, true); - ctx->bc.InstrSHORT(asBC_PSF, short(stackOffset)); + // TODO: A better message is needed + Error(TXT_NULL_POINTER_ACCESS, vnode); + ctx->type.SetDummy(); + return -1; } - PerformFunctionCall(descr->id, ctx, false, 0, 0, useVariable, stackOffset); + // Keep the pointer in the list for clean up at exit + usedStringConstants.PushLast(strPtr); + + // Push the pointer on the stack. The string factory already guarantees that the + // string object is valid throughout the lifetime of the script so no need to add + // reference count or make local copy. + ctx->bc.InstrPTR(asBC_PGA, strPtr); + ctx->type.Set(engine->stringType); + + // Mark the string as literal constant so the compiler knows it is allowed + // to treat it differently than an ordinary constant string variable + ctx->type.isConstant = true; } } } @@ -9105,7 +9467,7 @@ int asCCompiler::CompileExpressionValue(asCScriptNode *node, asSExprContext *ctx } else if( vnode->nodeType == snAssignment ) { - asSExprContext e(engine); + asCExprContext e(engine); int r = CompileAssignment(vnode, &e); if( r < 0 ) { @@ -9127,7 +9489,7 @@ int asCCompiler::CompileExpressionValue(asCScriptNode *node, asSExprContext *ctx else if( vnode->nodeType == snFunction ) { // This is an anonymous function - // Defer the evaluation of the function until it known where it + // Defer the evaluation of the function until it known where it // will be used, which is where the signature will be defined ctx->SetLambda(vnode); } @@ -9333,11 +9695,14 @@ asUINT asCCompiler::ProcessStringConstant(asCString &cstr, asCScriptNode *node, void asCCompiler::ProcessHeredocStringConstant(asCString &str, asCScriptNode *node) { // Remove first line if it only contains whitespace + bool isMultiline = false; int start; for( start = 0; start < (int)str.GetLength(); start++ ) { if( str[start] == '\n' ) { + isMultiline = true; + // Remove the linebreak as well start++; break; @@ -9377,21 +9742,29 @@ void asCCompiler::ProcessHeredocStringConstant(asCString &str, asCScriptNode *no if( end < 0 ) end = 0; asCString tmp; - if( end > start ) - tmp.Assign(&str[start], end-start); + if (end > start || engine->ep.heredocTrimMode != 2 ) + { + // if heredocTrimMode == 0 the string shouldn't be trimmed + // if heredocTrimMode == 1 the string should only be trimmed if it is multiline + // if heredocTrimMode == 2 the string should always be trimmed + if (engine->ep.heredocTrimMode == 2 || (isMultiline && engine->ep.heredocTrimMode == 1)) + tmp.Assign(&str[start], end - start); + else + tmp = str; + } ProcessStringConstant(tmp, node, false); str = tmp; } -int asCCompiler::CompileConversion(asCScriptNode *node, asSExprContext *ctx) +int asCCompiler::CompileConversion(asCScriptNode *node, asCExprContext *ctx) { - asSExprContext expr(engine); + asCExprContext expr(engine); asCDataType to; bool anyErrors = false; EImplicitConv convType; - if( node->nodeType == snConstructCall ) + if( node->nodeType == snConstructCall || node->nodeType == snFunctionCall ) { convType = asIC_EXPLICIT_VAL_CAST; @@ -9403,6 +9776,13 @@ int asCCompiler::CompileConversion(asCScriptNode *node, asSExprContext *ctx) expr.type.SetDummy(); anyErrors = true; } + else if (node->lastChild->firstChild && + node->lastChild->firstChild->nodeType == snNamedArgument) + { + Error(TXT_INVALID_USE_OF_NAMED_ARGS, node->lastChild); + expr.type.SetDummy(); + anyErrors = true; + } else { // Compile the expression @@ -9445,10 +9825,10 @@ int asCCompiler::CompileConversion(asCScriptNode *node, asSExprContext *ctx) // Do not allow casting to non shared type if we're compiling a shared method if( outFunc->IsShared() && - to.GetObjectType() && !to.GetObjectType()->IsShared() ) + to.GetTypeInfo() && !to.GetTypeInfo()->IsShared() ) { asCString msg; - msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, to.GetObjectType()->name.AddressOf()); + msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, to.GetTypeInfo()->name.AddressOf()); Error(msg, node); anyErrors = true; } @@ -9456,7 +9836,7 @@ int asCCompiler::CompileConversion(asCScriptNode *node, asSExprContext *ctx) if( anyErrors ) { // Assume that the error can be fixed and allow the compilation to continue - ctx->type.SetConstantDW(to, 0); + ctx->type.Set(to); return -1; } @@ -9537,9 +9917,9 @@ int asCCompiler::CompileConversion(asCScriptNode *node, asSExprContext *ctx) return -1; } -void asCCompiler::AfterFunctionCall(int funcID, asCArray &args, asSExprContext *ctx, bool deferAll) +void asCCompiler::AfterFunctionCall(int funcID, asCArray &args, asCExprContext *ctx, bool deferAll) { - // deferAll is set to true if for example the function returns a reference, since in + // deferAll is set to true if for example the function returns a reference, since in // this case the function might be returning a reference to one of the arguments. asCScriptFunction *descr = builder->GetFunctionDescription(funcID); @@ -9588,7 +9968,7 @@ void asCCompiler::AfterFunctionCall(int funcID, asCArray &args, } } -void asCCompiler::ProcessDeferredParams(asSExprContext *ctx) +void asCCompiler::ProcessDeferredParams(asCExprContext *ctx) { if( isProcessingDeferredParams ) return; @@ -9604,7 +9984,7 @@ void asCCompiler::ProcessDeferredParams(asSExprContext *ctx) } else if( outParam.argInOutFlags == asTM_OUTREF ) { - asSExprContext *expr = outParam.origExpr; + asCExprContext *expr = outParam.origExpr; outParam.origExpr = 0; if( outParam.argType.dataType.IsObjectHandle() ) @@ -9617,7 +9997,7 @@ void asCCompiler::ProcessDeferredParams(asSExprContext *ctx) // Verify that the expression result in a lvalue, or a property accessor if( IsLValue(expr->type) || expr->property_get || expr->property_set ) { - asSExprContext rctx(engine); + asCExprContext rctx(engine); rctx.type = outParam.argType; if( rctx.type.dataType.IsPrimitive() ) rctx.type.dataType.MakeReference(false); @@ -9629,7 +10009,7 @@ void asCCompiler::ProcessDeferredParams(asSExprContext *ctx) rctx.type.isExplicitHandle = true; } - asSExprContext o(engine); + asCExprContext o(engine); DoAssignment(&o, expr, &rctx, outParam.argNode, outParam.argNode, ttAssignment, outParam.argNode); if( !o.type.dataType.IsPrimitive() ) o.bc.Instr(asBC_PopPtr); @@ -9649,7 +10029,7 @@ void asCCompiler::ProcessDeferredParams(asSExprContext *ctx) ctx->bc.Instr(asBC_PopPtr); // Give an error, except if the argument is void, null or 0 which indicate the argument is explicitly to be ignored - if( !expr->IsVoidExpression() && !expr->type.IsNullConstant() && !(expr->type.isConstant && expr->type.qwordValue == 0) ) + if( !expr->IsVoidExpression() && !expr->type.IsNullConstant() && !(expr->type.isConstant && expr->type.GetConstantData() == 0) ) Error(TXT_ARG_NOT_LVALUE, outParam.argNode); ReleaseTemporaryVariable(outParam.argType, &ctx->bc); @@ -9658,7 +10038,7 @@ void asCCompiler::ProcessDeferredParams(asSExprContext *ctx) ReleaseTemporaryVariable(expr->type, &ctx->bc); // Delete the original expression context - asDELETE(expr,asSExprContext); + asDELETE(expr, asCExprContext); } else // &inout { @@ -9669,7 +10049,7 @@ void asCCompiler::ProcessDeferredParams(asSExprContext *ctx) if( outParam.argType.dataType.IsObject() && ((outParam.argType.dataType.GetBehaviour()->addref && outParam.argType.dataType.GetBehaviour()->release) || - (outParam.argType.dataType.GetObjectType()->flags & asOBJ_NOCOUNT)) ) + (outParam.argType.dataType.GetTypeInfo()->flags & asOBJ_NOCOUNT)) ) { // Release the object handle that was taken to guarantee the reference ReleaseTemporaryVariable(outParam.argType, &ctx->bc); @@ -9683,11 +10063,11 @@ void asCCompiler::ProcessDeferredParams(asSExprContext *ctx) } -int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) +int asCCompiler::CompileConstructCall(asCScriptNode *node, asCExprContext *ctx) { // The first node is a datatype node asCString name; - asCTypeInfo tempObj; + asCExprValue tempObj; bool onHeap = true; asCArray funcs; bool error = false; @@ -9701,7 +10081,7 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) return CompileConversion(node, ctx); } - if( dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_IMPLICIT_HANDLE) ) + if( dt.GetTypeInfo() && (dt.GetTypeInfo()->flags & asOBJ_IMPLICIT_HANDLE) ) { // Types declared as implicit handle must not attempt to construct a handle dt.MakeHandle(false); @@ -9717,7 +10097,10 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) return -1; } - if( !dt.CanBeInstantiated() ) + // Make sure the desired type can actually be instantiated + // Delegates are allowed to be created through construct calls, + // even though they cannot be instantiated as variables + if( !dt.CanBeInstantiated() && !dt.IsFuncdef() ) { asCString str; if( dt.IsAbstractClass() ) @@ -9734,37 +10117,43 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) // Do not allow constructing non-shared types in shared functions if( outFunc->IsShared() && - dt.GetObjectType() && !dt.GetObjectType()->IsShared() ) + dt.GetTypeInfo() && !dt.GetTypeInfo()->IsShared() ) { asCString msg; - msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetObjectType()->name.AddressOf()); + msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetTypeInfo()->name.AddressOf()); Error(msg, node); return -1; } // Compile the arguments - asCArray args; + asCArray args; asCArray namedArgs; - asCArray temporaryVariables; + asCArray temporaryVariables; if( CompileArgumentList(node->lastChild, args, namedArgs) >= 0 ) { // Check for a value cast behaviour - if( args.GetLength() == 1 && args[0]->type.dataType.GetObjectType() ) + if( args.GetLength() == 1 && args[0]->type.dataType.GetTypeInfo() ) { - asSExprContext conv(engine); + asCExprContext conv(engine); conv.type = args[0]->type; asUINT cost = ImplicitConversion(&conv, dt, node->lastChild, asIC_EXPLICIT_VAL_CAST, false); // Don't use this if the cost is 0 because it would mean that nothing - // is done and the scipt wants a new value to be constructed + // is done and the script wants a new value to be constructed if( conv.type.dataType.IsEqualExceptRef(dt) && cost > 0 ) { + // Make sure the result is a reference, just as if to a local variable + dt.MakeReference(true); + + // Make sure any property accessor is already evaluated + ProcessPropertyGetAccessor(args[0], args[0]->exprNode); + ImplicitConversion(args[0], dt, node->lastChild, asIC_EXPLICIT_VAL_CAST); ctx->bc.AddCode(&args[0]->bc); ctx->type = args[0]->type; - asDELETE(args[0],asSExprContext); + asDELETE(args[0], asCExprContext); return 0; } @@ -9775,7 +10164,7 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) asSTypeBehaviour *beh = dt.GetBehaviour(); - if( !(dt.GetObjectType()->flags & asOBJ_REF) ) + if( !(dt.GetTypeInfo()->flags & asOBJ_REF) && !dt.IsFuncdef() ) { funcs = beh->constructors; @@ -9792,7 +10181,7 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) if( onHeap ) ctx->bc.InstrSHORT(asBC_VAR, tempObj.stackOffset); } - else + else if( beh ) funcs = beh->factories; // Special case: Allow calling func(void) with a void expression. @@ -9800,7 +10189,7 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) { // Evaluate the expression before the function call MergeExprBytecode(ctx, args[0]); - asDELETE(args[0],asSExprContext); + asDELETE(args[0], asCExprContext); args.SetLength(0); } @@ -9808,8 +10197,8 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) // If none has been registered, just allocate the variable and push it on the stack. if( args.GetLength() == 0 ) { - asSTypeBehaviour *beh = tempObj.dataType.GetBehaviour(); - if( beh && beh->construct == 0 && !(dt.GetObjectType()->flags & asOBJ_REF) ) + beh = tempObj.dataType.GetBehaviour(); + if( beh && beh->construct == 0 && !(dt.GetTypeInfo()->flags & asOBJ_REF) ) { // Call the default constructor ctx->type = tempObj; @@ -9829,7 +10218,7 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) } // Special case: If this is a construction of a delegate and the expression names an object method - if( dt.GetFuncDef() && args.GetLength() == 1 && args[0]->methodName != "" ) + if( dt.IsFuncdef() && args.GetLength() == 1 && args[0]->methodName != "" ) { // TODO: delegate: It is possible that the argument returns a function pointer already, in which // case no object delegate will be created, but instead a delegate for a function pointer @@ -9848,7 +10237,7 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) else { // Filter the available object methods to find the one that matches the func def - asCObjectType *type = args[0]->type.dataType.GetObjectType(); + asCObjectType *type = CastToObjectType(args[0]->type.dataType.GetTypeInfo()); asCScriptFunction *bestMethod = 0; for( asUINT n = 0; n < type->methods.GetLength(); n++ ) { @@ -9861,7 +10250,7 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) if( args[0]->type.dataType.IsReadOnly() && !func->IsReadOnly() ) continue; - if( func->IsSignatureExceptNameAndObjectTypeEqual(dt.GetFuncDef()) ) + if( func->IsSignatureExceptNameAndObjectTypeEqual(CastToFuncdefType(dt.GetTypeInfo())->funcdef) ) { bestMethod = func; @@ -9880,10 +10269,10 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) ctx->bc.InstrPTR(asBC_FuncPtr, bestMethod); // Call the factory function for the delegate - asCArray funcs; - builder->GetFunctionDescriptions(DELEGATE_FACTORY, funcs, engine->nameSpaces[0]); - asASSERT( funcs.GetLength() == 1 ); - ctx->bc.Call(asBC_CALLSYS , funcs[0], 2*AS_PTR_SIZE); + asCArray delegateFuncs; + builder->GetFunctionDescriptions(DELEGATE_FACTORY, delegateFuncs, engine->nameSpaces[0]); + asASSERT(delegateFuncs.GetLength() == 1 ); + ctx->bc.Call(asBC_CALLSYS , delegateFuncs[0], 2*AS_PTR_SIZE); // Store the returned delegate in a temporary variable int returnOffset = AllocateVariable(dt, true, false); @@ -9900,14 +10289,14 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) else { asCString msg; - msg.Format(TXT_NO_MATCHING_SIGNATURES_TO_s, dt.GetFuncDef()->GetDeclaration()); + msg.Format(TXT_NO_MATCHING_SIGNATURES_TO_s, CastToFuncdefType(dt.GetTypeInfo())->funcdef->GetDeclaration()); Error(msg.AddressOf(), node); error = true; } } // Clean-up arg - asDELETE(args[0],asSExprContext); + asDELETE(args[0], asCExprContext); return error ? -1 : 0; } @@ -9926,7 +10315,7 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) // TODO: Clean up: Merge this with MakeFunctionCall // Add the default values for arguments not explicitly supplied - int r = CompileDefaultAndNamedArgs(node, args, funcs[0], dt.GetObjectType(), &namedArgs); + int r = CompileDefaultAndNamedArgs(node, args, funcs[0], CastToObjectType(dt.GetTypeInfo()), &namedArgs); if( r == asSUCCESS ) { @@ -9936,7 +10325,7 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) MoveArgsToStack(funcs[0], &ctx->bc, args, false); - if( !(dt.GetObjectType()->flags & asOBJ_REF) ) + if( !(dt.GetTypeInfo()->flags & asOBJ_REF) ) { // If the object is allocated on the stack, then call the constructor as a normal function if( onHeap ) @@ -9951,7 +10340,7 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) else ctx->bc.InstrSHORT(asBC_PSF, tempObj.stackOffset); - PerformFunctionCall(funcs[0], ctx, onHeap, &args, tempObj.dataType.GetObjectType()); + PerformFunctionCall(funcs[0], ctx, onHeap, &args, CastToObjectType(tempObj.dataType.GetTypeInfo())); // Add tag that the object has been initialized ctx->bc.ObjInfo(tempObj.stackOffset, asOBJ_INIT); @@ -9987,25 +10376,25 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx) for( asUINT n = 0; n < args.GetLength(); n++ ) if( args[n] ) { - asDELETE(args[n],asSExprContext); + asDELETE(args[n], asCExprContext); } for( asUINT n = 0; n < namedArgs.GetLength(); n++ ) if( namedArgs[n].ctx ) { - asDELETE(namedArgs[n].ctx,asSExprContext); + asDELETE(namedArgs[n].ctx, asCExprContext); } return error ? -1 : 0; } -int asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx, asCObjectType *objectType, bool objIsConst, const asCString &scope) +int asCCompiler::CompileFunctionCall(asCScriptNode *node, asCExprContext *ctx, asCObjectType *objectType, bool objIsConst, const asCString &scope) { - asCTypeInfo tempObj; + asCExprValue tempObj; asCArray funcs; int localVar = -1; bool initializeMembers = false; - asSExprContext funcExpr(engine); + asCExprContext funcExpr(engine); asCScriptNode *nm = node->lastChild->prev; asCString name(&script->code[nm->tokenPos], nm->tokenLength); @@ -10017,12 +10406,12 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx, a { localVar = CompileVariableAccess(name, scope, &funcExpr, node, true, true, true); if( localVar >= 0 && - !(funcExpr.type.dataType.GetFuncDef() || funcExpr.type.dataType.IsObject()) && + !(funcExpr.type.dataType.IsFuncdef() || funcExpr.type.dataType.IsObject()) && funcExpr.methodName == "" ) { // The variable is not a function or object with opCall asCString msg; - msg.Format(TXT_NOT_A_FUNC_s_IS_VAR, name.AddressOf()); + msg.Format(TXT_NOT_A_FUNC_s_IS_TYPE_s, name.AddressOf(), funcExpr.type.dataType.Format(outFunc->nameSpace).AddressOf()); Error(msg, node); return -1; } @@ -10079,12 +10468,12 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx, a { int r = CompileVariableAccess(name, scope, &funcExpr, node, true, true, true, objectType); if( r >= 0 && - !(funcExpr.type.dataType.GetFuncDef() || funcExpr.type.dataType.IsObject()) && + !(funcExpr.type.dataType.IsFuncdef() || funcExpr.type.dataType.IsObject()) && funcExpr.methodName == "" ) { // The variable is not a function asCString msg; - msg.Format(TXT_NOT_A_FUNC_s_IS_VAR, name.AddressOf()); + msg.Format(TXT_NOT_A_FUNC_s_IS_TYPE_s, name.AddressOf(), funcExpr.type.dataType.Format(outFunc->nameSpace).AddressOf()); Error(msg, node); return -1; } @@ -10100,7 +10489,7 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx, a { objectType = outFunc->objectType; - asCDataType dt = asCDataType::CreateObject(objectType, false); + asCDataType dt = asCDataType::CreateType(objectType, false); // The object pointer is located at stack position 0 ctx->bc.InstrSHORT(asBC_PSF, 0); @@ -10115,26 +10504,26 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx, a // then look for global functions or global function pointers, // unless this is an expression post op, incase only member // functions are expected - if( objectType == 0 && funcs.GetLength() == 0 && (funcExpr.type.dataType.GetFuncDef() == 0 || funcExpr.type.dataType.IsObject()) ) + if( objectType == 0 && funcs.GetLength() == 0 && (!funcExpr.type.dataType.IsFuncdef() || funcExpr.type.dataType.IsObject()) ) { // The scope is used to define the namespace asSNameSpace *ns = DetermineNameSpace(scope); if( ns ) { // Search recursively in parent namespaces - while( ns && funcs.GetLength() == 0 && funcExpr.type.dataType.GetFuncDef() == 0 ) + while( ns && funcs.GetLength() == 0 && !funcExpr.type.dataType.IsFuncdef() ) { builder->GetFunctionDescriptions(name.AddressOf(), funcs, ns); if( funcs.GetLength() == 0 ) { int r = CompileVariableAccess(name, scope, &funcExpr, node, true, true); if( r >= 0 && - !(funcExpr.type.dataType.GetFuncDef() || funcExpr.type.dataType.IsObject()) && + !(funcExpr.type.dataType.IsFuncdef() || funcExpr.type.dataType.IsObject()) && funcExpr.methodName == "" ) { // The variable is not a function asCString msg; - msg.Format(TXT_NOT_A_FUNC_s_IS_VAR, name.AddressOf()); + msg.Format(TXT_NOT_A_FUNC_s_IS_TYPE_s, name.AddressOf(), funcExpr.type.dataType.Format(outFunc->nameSpace).AddressOf()); Error(msg, node); return -1; } @@ -10155,9 +10544,9 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx, a if( funcs.GetLength() == 0 ) { - if( funcExpr.type.dataType.GetFuncDef() ) + if( funcExpr.type.dataType.IsFuncdef() ) { - funcs.PushLast(funcExpr.type.dataType.GetFuncDef()->id); + funcs.PushLast(CastToFuncdefType(funcExpr.type.dataType.GetTypeInfo())->funcdef->id); } else if( funcExpr.type.dataType.IsObject() ) { @@ -10182,7 +10571,7 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx, a ProcessPropertyGetAccessor(ctx, node); Dereference(ctx, true); - objectType = funcExpr.type.dataType.GetObjectType(); + objectType = CastToObjectType(funcExpr.type.dataType.GetTypeInfo()); // Get the opCall methods from the object type if( funcExpr.type.dataType.IsObjectHandle() ) @@ -10190,12 +10579,21 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx, a else objIsConst = funcExpr.type.dataType.IsReadOnly(); - builder->GetObjectMethodDescriptions("opCall", funcExpr.type.dataType.GetObjectType(), funcs, objIsConst); + builder->GetObjectMethodDescriptions("opCall", CastToObjectType(funcExpr.type.dataType.GetTypeInfo()), funcs, objIsConst); } } + // If at this point no functions have been identified, then this may be a construct call + if (funcs.GetLength() == 0) + { + bool isValid = false; + asCDataType dt = builder->CreateDataTypeFromNode(node->firstChild, script, outFunc->nameSpace, false, 0, false, &isValid); + if (isValid) + return CompileConstructCall(node, ctx); + } + // Compile the arguments - asCArray args; + asCArray args; asCArray namedArgs; bool isOK = true; @@ -10206,7 +10604,7 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx, a { // Evaluate the expression before the function call MergeExprBytecode(ctx, args[0]); - asDELETE(args[0],asSExprContext); + asDELETE(args[0], asCExprContext); args.SetLength(0); } @@ -10238,7 +10636,7 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx, a if( objectType && funcExpr.property_get <= 0 ) { // Dereference the object pointer to access the member - Dereference(ctx, true); + Dereference(ctx, true); } if( funcExpr.property_get > 0 ) @@ -10258,7 +10656,7 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx, a // The function call will be made directly from the local variable so the function pointer shouldn't be on the stack funcExpr.bc.Instr(asBC_PopPtr); - asCTypeInfo tmp = ctx->type; + asCExprValue tmp = ctx->type; MergeExprBytecodeAndType(ctx, &funcExpr); ReleaseTemporaryVariable(tmp, &ctx->bc); } @@ -10280,12 +10678,12 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx, a for( asUINT n = 0; n < args.GetLength(); n++ ) if( args[n] ) { - asDELETE(args[n],asSExprContext); + asDELETE(args[n], asCExprContext); } for( asUINT n = 0; n < namedArgs.GetLength(); n++ ) if( namedArgs[n].ctx ) { - asDELETE(namedArgs[n].ctx,asSExprContext); + asDELETE(namedArgs[n].ctx, asCExprContext); } if( initializeMembers ) @@ -10329,7 +10727,7 @@ asSNameSpace *asCCompiler::DetermineNameSpace(const asCString &scope) return ns; } -int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx) +int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asCExprContext *ctx) { int op = node->tokenType; @@ -10373,9 +10771,7 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx if( !ctx->type.IsNullConstant() ) { // Verify that the type allow its handle to be taken - if( !ctx->type.dataType.IsObject() || - !(((ctx->type.dataType.GetObjectType()->beh.addref && ctx->type.dataType.GetObjectType()->beh.release) || (ctx->type.dataType.GetObjectType()->flags & asOBJ_NOCOUNT)) || - (ctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE)) ) + if( !ctx->type.dataType.SupportHandles() && !ctx->type.dataType.IsObjectHandle() ) { Error(TXT_OBJECT_HANDLE_NOT_SUPPORTED, node); return -1; @@ -10384,7 +10780,7 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx // Objects that are not local variables are not references // Objects allocated on the stack are also not marked as references if( !ctx->type.dataType.IsReference() && - !(ctx->type.dataType.IsObject() && !ctx->type.isVariable) && + !((ctx->type.dataType.IsObject() || ctx->type.dataType.IsFuncdef()) && !ctx->type.isVariable) && !(ctx->type.isVariable && !IsVariableOnHeap(ctx->type.stackOffset)) ) { Error(TXT_NOT_VALID_REFERENCE, node); @@ -10392,7 +10788,7 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx } // Convert the expression to a handle - if( !ctx->type.dataType.IsObjectHandle() && !(ctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE) ) + if( !ctx->type.dataType.IsObjectHandle() && !(ctx->type.dataType.GetTypeInfo()->flags & asOBJ_ASHANDLE) ) { asCDataType to = ctx->type.dataType; to.MakeHandle(true); @@ -10402,7 +10798,7 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx asASSERT( ctx->type.dataType.IsObjectHandle() ); } - else if( ctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE ) + else if( ctx->type.dataType.GetTypeInfo()->flags & asOBJ_ASHANDLE ) { // For the ASHANDLE type we'll simply set the expression as a handle ctx->type.dataType.MakeHandle(true); @@ -10436,13 +10832,13 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx // Find the correct method bool isConst = ctx->type.dataType.IsObjectConst(); asCArray funcs; - asCObjectType *ot = ctx->type.dataType.GetObjectType(); + asCObjectType *ot = CastToObjectType(ctx->type.dataType.GetTypeInfo()); for( asUINT n = 0; n < ot->methods.GetLength(); n++ ) { asCScriptFunction *func = engine->scriptFunctions[ot->methods[n]]; if( func->name == opName && func->parameterTypes.GetLength() == 0 && - (!isConst || func->isReadOnly) ) + (!isConst || func->IsReadOnly()) ) { funcs.PushLast(func->id); } @@ -10451,8 +10847,8 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx // Did we find the method? if( funcs.GetLength() == 1 ) { - asCArray args; - MakeFunctionCall(ctx, funcs[0], ctx->type.dataType.GetObjectType(), args, node); + asCArray args; + MakeFunctionCall(ctx, funcs[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node); return 0; } else if( funcs.GetLength() == 0 ) @@ -10551,14 +10947,21 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx { if( op == ttMinus ) { - if( ctx->type.dataType.IsIntegerType() && ctx->type.dataType.GetSizeInMemoryDWords() == 1 ) - ctx->type.intValue = -ctx->type.intValue; - else if( ctx->type.dataType.IsIntegerType() && ctx->type.dataType.GetSizeInMemoryDWords() == 2 ) - ctx->type.qwordValue = -(asINT64)ctx->type.qwordValue; + if (ctx->type.dataType.IsIntegerType()) + { + if (ctx->type.dataType.GetSizeInMemoryBytes() == 4) + ctx->type.SetConstantDW(-(int)ctx->type.GetConstantDW()); + else if (ctx->type.dataType.GetSizeInMemoryBytes() == 2) + ctx->type.SetConstantW(-(asINT16)ctx->type.GetConstantW()); + else if (ctx->type.dataType.GetSizeInMemoryBytes() == 1) + ctx->type.SetConstantB(-(asINT8)ctx->type.GetConstantB()); + else if (ctx->type.dataType.GetSizeInMemoryBytes() == 8) + ctx->type.SetConstantQW(-(asINT64)ctx->type.GetConstantQW()); + } else if( ctx->type.dataType.IsFloatType() ) - ctx->type.floatValue = -ctx->type.floatValue; + ctx->type.SetConstantF(-ctx->type.GetConstantF()); else if( ctx->type.dataType.IsDoubleType() ) - ctx->type.doubleValue = -ctx->type.doubleValue; + ctx->type.SetConstantD(-ctx->type.GetConstantD()); else { Error(TXT_ILLEGAL_OPERATION, node); @@ -10572,14 +10975,18 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx else if( op == ttNot ) { // Allow value types to be converted to bool using 'bool opImplConv()' - if( ctx->type.dataType.GetObjectType() && (ctx->type.dataType.GetObjectType()->GetFlags() & asOBJ_VALUE) ) + if( ctx->type.dataType.GetTypeInfo() && (ctx->type.dataType.GetTypeInfo()->GetFlags() & asOBJ_VALUE) ) ImplicitConversion(ctx, asCDataType::CreatePrimitive(ttBool, false), node, asIC_IMPLICIT_CONV); if( ctx->type.dataType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, true)) ) { if( ctx->type.isConstant ) { - ctx->type.dwordValue = (ctx->type.dwordValue == 0 ? VALUE_OF_BOOLEAN_TRUE : 0); + #if AS_SIZEOF_BOOL == 1 + ctx->type.SetConstantB(ctx->type.GetConstantB() == 0 ? VALUE_OF_BOOLEAN_TRUE : 0); + #else + ctx->type.SetConstantDW(ctx->type.GetConstantDW() == 0 ? VALUE_OF_BOOLEAN_TRUE : 0); + #endif return 0; } @@ -10626,7 +11033,14 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx { if( ctx->type.isConstant ) { - ctx->type.qwordValue = ~ctx->type.qwordValue; + if( ctx->type.dataType.GetSizeInMemoryBytes() == 1 ) + ctx->type.SetConstantB(~ctx->type.GetConstantB()); + else if (ctx->type.dataType.GetSizeInMemoryBytes() == 2) + ctx->type.SetConstantW(~ctx->type.GetConstantW()); + else if (ctx->type.dataType.GetSizeInMemoryBytes() == 4) + ctx->type.SetConstantDW(~ctx->type.GetConstantDW()); + else + ctx->type.SetConstantQW(~ctx->type.GetConstantQW()); return 0; } @@ -10741,7 +11155,7 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx return 0; } -void asCCompiler::ConvertToReference(asSExprContext *ctx) +void asCCompiler::ConvertToReference(asCExprContext *ctx) { if( ctx->type.isVariable && !ctx->type.dataType.IsReference() ) { @@ -10751,12 +11165,12 @@ void asCCompiler::ConvertToReference(asSExprContext *ctx) } } -int asCCompiler::FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asCScriptNode *node, asSNameSpace *ns, bool isThisAccess) +int asCCompiler::FindPropertyAccessor(const asCString &name, asCExprContext *ctx, asCScriptNode *node, asSNameSpace *ns, bool isThisAccess) { return FindPropertyAccessor(name, ctx, 0, node, ns, isThisAccess); } -int asCCompiler::FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node, asSNameSpace *ns, bool isThisAccess) +int asCCompiler::FindPropertyAccessor(const asCString &name, asCExprContext *ctx, asCExprContext *arg, asCScriptNode *node, asSNameSpace *ns, bool isThisAccess) { if( engine->ep.propertyAccessorMode == 0 ) { @@ -10775,11 +11189,11 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asSExprContext *ctx // Don't look for property accessors in script classes if the script // property accessors have been disabled by the application - if( !(ctx->type.dataType.GetObjectType()->flags & asOBJ_SCRIPT_OBJECT) || + if( !(ctx->type.dataType.GetTypeInfo()->flags & asOBJ_SCRIPT_OBJECT) || engine->ep.propertyAccessorMode == 2 ) { // Check if the object has any methods with the corresponding accessor name(s) - asCObjectType *ot = ctx->type.dataType.GetObjectType(); + asCObjectType *ot = CastToObjectType(ctx->type.dataType.GetTypeInfo()); for( asUINT n = 0; n < ot->methods.GetLength(); n++ ) { asCScriptFunction *f = engine->scriptFunctions[ot->methods[n]]; @@ -10916,7 +11330,7 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asSExprContext *ctx int idx = (arg?1:0); if( !getFunc->returnType.IsEqualExceptRefAndConst(setFunc->parameterTypes[idx]) && !((getFunc->returnType.IsObjectHandle() && !setFunc->parameterTypes[idx].IsObjectHandle()) && - (getFunc->returnType.GetObjectType() == setFunc->parameterTypes[idx].GetObjectType())) ) + (getFunc->returnType.GetTypeInfo() == setFunc->parameterTypes[idx].GetTypeInfo())) ) { asCString str; str.Format(TXT_GET_SET_ACCESSOR_TYPE_MISMATCH_FOR_s, name.AddressOf()); @@ -10977,6 +11391,8 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asSExprContext *ctx ctx->property_get = getId; ctx->property_set = setId; + bool isHandleSafe = ctx->type.isHandleSafe; + if( ctx->type.dataType.IsObject() ) { // If the object is read-only then we need to remember that @@ -11008,10 +11424,14 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asSExprContext *ctx ctx->type.isTemporary = isTemp; ctx->exprNode = node; + // Remember if the object is safe, so the invocation of the property + // accessor doesn't needlessly make a safe copy of the handle + ctx->type.isHandleSafe = isHandleSafe; + // Store the argument for later use if( arg ) { - ctx->property_arg = asNEW(asSExprContext)(engine); + ctx->property_arg = asNEW(asCExprContext)(engine); if( ctx->property_arg == 0 ) { // Out of memory @@ -11028,7 +11448,7 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asSExprContext *ctx return 0; } -int asCCompiler::ProcessPropertySetAccessor(asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node) +int asCCompiler::ProcessPropertySetAccessor(asCExprContext *ctx, asCExprContext *arg, asCScriptNode *node) { // TODO: A lot of this code is similar to ProcessPropertyGetAccessor. Can we unify them? @@ -11043,7 +11463,7 @@ int asCCompiler::ProcessPropertySetAccessor(asSExprContext *ctx, asSExprContext // Make sure the arg match the property asCArray funcs; funcs.PushLast(ctx->property_set); - asCArray args; + asCArray args; if( ctx->property_arg ) args.PushLast(ctx->property_arg); args.PushLast(arg); @@ -11053,7 +11473,7 @@ int asCCompiler::ProcessPropertySetAccessor(asSExprContext *ctx, asSExprContext // MatchFunctions already reported the error if( ctx->property_arg ) { - asDELETE(ctx->property_arg, asSExprContext); + asDELETE(ctx->property_arg, asCExprContext); ctx->property_arg = 0; } return -1; @@ -11062,17 +11482,17 @@ int asCCompiler::ProcessPropertySetAccessor(asSExprContext *ctx, asSExprContext if( func->objectType ) { // Setup the context with the original type so the method call gets built correctly - ctx->type.dataType = asCDataType::CreateObject(func->objectType, ctx->property_const); + ctx->type.dataType = asCDataType::CreateType(func->objectType, ctx->property_const); if( ctx->property_handle ) ctx->type.dataType.MakeHandle(true); if( ctx->property_ref ) ctx->type.dataType.MakeReference(true); // Don't allow the call if the object is read-only and the property accessor is not const - if( ctx->property_const && !func->isReadOnly ) + if( ctx->property_const && !func->IsReadOnly() ) { Error(TXT_NON_CONST_METHOD_ON_CONST_OBJ, node); - asCArray funcs; - funcs.PushLast(ctx->property_set); - PrintMatchingFuncs(funcs, node); + asCArray funcCandidates; + funcCandidates.PushLast(ctx->property_set); + PrintMatchingFuncs(funcCandidates, node); } } @@ -11083,17 +11503,17 @@ int asCCompiler::ProcessPropertySetAccessor(asSExprContext *ctx, asSExprContext ctx->property_set = 0; if( ctx->property_arg ) { - asDELETE(ctx->property_arg, asSExprContext); + asDELETE(ctx->property_arg, asCExprContext); ctx->property_arg = 0; } return 0; } -int asCCompiler::ProcessPropertyGetSetAccessor(asSExprContext *ctx, asSExprContext *lctx, asSExprContext *rctx, eTokenType op, asCScriptNode *errNode) +int asCCompiler::ProcessPropertyGetSetAccessor(asCExprContext *ctx, asCExprContext *lctx, asCExprContext *rctx, eTokenType op, asCScriptNode *errNode) { - // TODO: Perhaps it might be interesting to allow the definition of compound setters for better - // performance, e.g. set_add_prop, set_mul_prop, etc. With these it would also be possible + // TODO: Perhaps it might be interesting to allow the definition of compound setters for better + // performance, e.g. set_add_prop, set_mul_prop, etc. With these it would also be possible // to support value types, since it would be a single call // Compound assignment for indexed property accessors is not supported yet @@ -11114,7 +11534,7 @@ int asCCompiler::ProcessPropertyGetSetAccessor(asSExprContext *ctx, asSExprConte return -1; } - // Property accessors on value types (or scoped references types) are not supported since + // Property accessors on value types (or scoped references types) are not supported since // it is not possible to guarantee that the object will stay alive between the two calls asCScriptFunction *func = engine->scriptFunctions[lctx->property_set]; if( func->objectType && (func->objectType->flags & (asOBJ_VALUE | asOBJ_SCOPED)) ) @@ -11134,9 +11554,9 @@ int asCCompiler::ProcessPropertyGetSetAccessor(asSExprContext *ctx, asSExprConte case ttDivAssign: op = ttSlash; break; case ttModAssign: op = ttPercent; break; case ttPowAssign: op = ttStarStar; break; - + case ttAndAssign: op = ttAmp; break; - case ttOrAssign: op = ttBitOr; break; + case ttOrAssign: op = ttBitOr; break; case ttXorAssign: op = ttBitXor; break; case ttShiftLeftAssign: op = ttBitShiftLeft; break; @@ -11149,14 +11569,14 @@ int asCCompiler::ProcessPropertyGetSetAccessor(asSExprContext *ctx, asSExprConte if( op == ttUnrecognizedToken ) { // Shouldn't happen - asASSERT(false); + asASSERT(false); // Process the property to free the memory ProcessPropertySetAccessor(lctx, rctx, errNode); return -1; } - asSExprContext before(engine); + asCExprContext before(engine); if( func->objectType && (func->objectType->flags & (asOBJ_REF|asOBJ_SCOPED)) == asOBJ_REF ) { // Keep a reference to the object in a local variable @@ -11202,7 +11622,7 @@ int asCCompiler::ProcessPropertyGetSetAccessor(asSExprContext *ctx, asSExprConte } // Keep the original information on the property - asSExprContext llctx(engine); + asCExprContext llctx(engine); llctx.type = lctx->type; llctx.property_arg = lctx->property_arg; llctx.property_const = lctx->property_const; @@ -11212,7 +11632,7 @@ int asCCompiler::ProcessPropertyGetSetAccessor(asSExprContext *ctx, asSExprConte llctx.property_set = lctx->property_set; // Compile the dual operator using the get accessor - CompileOperator(errNode, lctx, rctx, ctx, op); + CompileOperator(errNode, lctx, rctx, ctx, op, false); // If we made a local variable to hold the reference it must be reused if( before.type.stackOffset ) @@ -11233,7 +11653,7 @@ int asCCompiler::ProcessPropertyGetSetAccessor(asSExprContext *ctx, asSExprConte return 0; } -void asCCompiler::ProcessPropertyGetAccessor(asSExprContext *ctx, asCScriptNode *node) +void asCCompiler::ProcessPropertyGetAccessor(asCExprContext *ctx, asCScriptNode *node) { // If no property accessor has been prepared then don't do anything if( !ctx->property_get && !ctx->property_set ) @@ -11247,13 +11667,13 @@ void asCCompiler::ProcessPropertyGetAccessor(asSExprContext *ctx, asCScriptNode return; } - asCTypeInfo objType = ctx->type; + asCExprValue objType = ctx->type; asCScriptFunction *func = builder->GetFunctionDescription(ctx->property_get); // Make sure the arg match the property asCArray funcs; funcs.PushLast(ctx->property_get); - asCArray args; + asCArray args; if( ctx->property_arg ) args.PushLast(ctx->property_arg); MatchFunctions(funcs, args, node, func->GetName(), 0, func->objectType, ctx->property_const); @@ -11262,7 +11682,7 @@ void asCCompiler::ProcessPropertyGetAccessor(asSExprContext *ctx, asCScriptNode // MatchFunctions already reported the error if( ctx->property_arg ) { - asDELETE(ctx->property_arg, asSExprContext); + asDELETE(ctx->property_arg, asCExprContext); ctx->property_arg = 0; } ctx->type.SetDummy(); @@ -11272,17 +11692,17 @@ void asCCompiler::ProcessPropertyGetAccessor(asSExprContext *ctx, asCScriptNode if( func->objectType ) { // Setup the context with the original type so the method call gets built correctly - ctx->type.dataType = asCDataType::CreateObject(func->objectType, ctx->property_const); + ctx->type.dataType = asCDataType::CreateType(func->objectType, ctx->property_const); if( ctx->property_handle ) ctx->type.dataType.MakeHandle(true); if( ctx->property_ref ) ctx->type.dataType.MakeReference(true); // Don't allow the call if the object is read-only and the property accessor is not const - if( ctx->property_const && !func->isReadOnly ) + if( ctx->property_const && !func->IsReadOnly() ) { Error(TXT_NON_CONST_METHOD_ON_CONST_OBJ, node); - asCArray funcs; - funcs.PushLast(ctx->property_get); - PrintMatchingFuncs(funcs, node); + asCArray funcCandidates; + funcCandidates.PushLast(ctx->property_get); + PrintMatchingFuncs(funcCandidates, node); } } @@ -11294,17 +11714,17 @@ void asCCompiler::ProcessPropertyGetAccessor(asSExprContext *ctx, asCScriptNode if( isExplicitHandle ) ctx->type.isExplicitHandle = true; - // Clear the property get/set ids + // Clear the property get/set ids ctx->property_get = 0; ctx->property_set = 0; if( ctx->property_arg ) { - asDELETE(ctx->property_arg, asSExprContext); + asDELETE(ctx->property_arg, asCExprContext); ctx->property_arg = 0; } } -int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ctx) +int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asCExprContext *ctx) { // Don't allow any postfix operators on expressions that take address of class method if( ctx->IsClassMethod() ) @@ -11343,13 +11763,13 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct // Find the correct method bool isConst = ctx->type.dataType.IsObjectConst(); asCArray funcs; - asCObjectType *ot = ctx->type.dataType.GetObjectType(); + asCObjectType *ot = CastToObjectType(ctx->type.dataType.GetTypeInfo()); for( asUINT n = 0; n < ot->methods.GetLength(); n++ ) { asCScriptFunction *func = engine->scriptFunctions[ot->methods[n]]; if( func->name == opName && func->parameterTypes.GetLength() == 0 && - (!isConst || func->isReadOnly) ) + (!isConst || func->IsReadOnly()) ) { funcs.PushLast(func->id); } @@ -11358,8 +11778,8 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct // Did we find the method? if( funcs.GetLength() == 1 ) { - asCArray args; - MakeFunctionCall(ctx, funcs[0], ctx->type.dataType.GetObjectType(), args, node); + asCArray args; + MakeFunctionCall(ctx, funcs[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node); return 0; } else if( funcs.GetLength() == 0 ) @@ -11478,7 +11898,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct if( node->next && node->next->tokenType == ttOpenBracket ) { // The property accessor should take an index arg - asSExprContext dummyArg(engine); + asCExprContext dummyArg(engine); r = FindPropertyAccessor(name, ctx, &dummyArg, node, 0); } if( r == 0 ) @@ -11507,7 +11927,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct if( prop ) { // Is the property access allowed? - if( (prop->isPrivate || prop->isProtected) && (!outFunc || outFunc->objectType != ctx->type.dataType.GetObjectType()) ) + if( (prop->isPrivate || prop->isProtected) && (!outFunc || outFunc->objectType != ctx->type.dataType.GetTypeInfo()) ) { asCString msg; if( prop->isPrivate ) @@ -11517,8 +11937,16 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct Error(msg, node); } + // Adjust the pointer for composite member + // This must always be done even if the offset is 0 because the asCWriter needs the meta data in ADDSi to identify the composite property + if( prop->compositeOffset || prop->isCompositeIndirect ) + ctx->bc.InstrSHORT_DW(asBC_ADDSi, (short)prop->compositeOffset, engine->GetTypeIdFromDataType(asCDataType::CreateType(ctx->type.dataType.GetTypeInfo(), false))); + if (prop->isCompositeIndirect) + ctx->bc.Instr(asBC_RDSPtr); + // Put the offset on the stack - ctx->bc.InstrSHORT_DW(asBC_ADDSi, (short)prop->byteOffset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(ctx->type.dataType.GetObjectType(), false))); + // This must always be done even if the offset is 0 so the type info is stored + ctx->bc.InstrSHORT_DW(asBC_ADDSi, (short)prop->byteOffset, engine->GetTypeIdFromDataType(asCDataType::CreateType(ctx->type.dataType.GetTypeInfo(), false))); if( prop->type.IsReference() ) ctx->bc.Instr(asBC_RDSPtr); @@ -11548,10 +11976,18 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct ctx->type.isVariable = false; ctx->type.isTemporary = false; - if( ctx->type.dataType.IsObject() && !ctx->type.dataType.IsObjectHandle() ) + if( (ctx->type.dataType.IsObject() || ctx->type.dataType.IsFuncdef()) && !ctx->type.dataType.IsObjectHandle() ) { // Objects that are members are not references ctx->type.dataType.MakeReference(false); + + // The object is safe (life time guaranteed) if the parent object is also safe + } + else if (ctx->type.dataType.IsObjectHandle()) + { + // A object accessed through a handle cannot be considered safe, + // as it can be cleared at any time + ctx->type.isHandleSafe = false; } ctx->type.dataType.MakeReadOnly(isConst ? true : prop->type.IsReadOnly()); @@ -11561,7 +11997,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct // If the name is not a property, the compiler must check if the name matches // a method, which can be used for constructing delegates asIScriptFunction *func = 0; - asCObjectType *ot = ctx->type.dataType.GetObjectType(); + asCObjectType *ot = CastToObjectType(ctx->type.dataType.GetTypeInfo()); for( asUINT n = 0; n < ot->methods.GetLength(); n++ ) { if( engine->scriptFunctions[ot->methods[n]]->name == name ) @@ -11610,7 +12046,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct ProcessPropertyGetAccessor(ctx, node); // Compile function call - int r = CompileFunctionCall(node->firstChild, ctx, ctx->type.dataType.GetObjectType(), ctx->type.dataType.IsObjectConst()); + int r = CompileFunctionCall(node->firstChild, ctx, CastToObjectType(ctx->type.dataType.GetTypeInfo()), ctx->type.dataType.IsObjectConst()); if( r < 0 ) return r; } } @@ -11638,7 +12074,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct // Set the original type of the expression so we can re-evaluate the property accessor if( func->objectType ) { - ctx->type.dataType = asCDataType::CreateObject(func->objectType, ctx->property_const); + ctx->type.dataType = asCDataType::CreateType(func->objectType, ctx->property_const); if( ctx->property_handle ) ctx->type.dataType.MakeHandle(true); if( ctx->property_ref ) ctx->type.dataType.MakeReference(true); } @@ -11653,7 +12089,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct ctx->property_get = ctx->property_set = 0; if( ctx->property_arg ) { - asDELETE(ctx->property_arg, asSExprContext); + asDELETE(ctx->property_arg, asCExprContext); ctx->property_arg = 0; } } @@ -11672,7 +12108,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct // Compile the expression bool isOK = true; - asCArray args; + asCArray args; asCArray namedArgs; asASSERT( node->firstChild->nodeType == snArgList ); if( CompileArgumentList(node->firstChild, args, namedArgs) >= 0 ) @@ -11682,7 +12118,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct if( propertyName == "" ) { bool isConst = ctx->type.dataType.IsObjectConst(); - asCObjectType *objectType = ctx->type.dataType.GetObjectType(); + asCObjectType *objectType = CastToObjectType(ctx->type.dataType.GetTypeInfo()); asCArray funcs; builder->GetObjectMethodDescriptions("opIndex", objectType, funcs, isConst); @@ -11714,29 +12150,31 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct { if( args.GetLength() != 1 ) { - // TODO: opIndex: Implement this - Error("Property accessor with index only support 1 index argument for now", node); + // TODO: opIndex: Implement support for multiple index arguments in set_opIndex too + Error(TXT_PROP_ACCESS_WITH_INDEX_ONE_ARG, node); isOK = false; } - - Dereference(ctx, true); - asSExprContext lctx(engine); - MergeExprBytecodeAndType(&lctx, ctx); - - // Check for accessors methods for the opIndex, either as get/set_opIndex or as get/set with the property name - int r = FindPropertyAccessor(propertyName == "" ? "opIndex" : propertyName.AddressOf(), &lctx, args[0], node, ns); - if( r == 0 ) + else { - asCString str; - str.Format(TXT_OBJECT_DOESNT_SUPPORT_INDEX_OP, ctx->type.dataType.Format(outFunc->nameSpace).AddressOf()); - Error(str, node); - isOK = false; - } - else if( r < 0 ) - isOK = false; + Dereference(ctx, true); + asCExprContext lctx(engine); + MergeExprBytecodeAndType(&lctx, ctx); - if( isOK ) - MergeExprBytecodeAndType(ctx, &lctx); + // Check for accessors methods for the opIndex, either as get/set_opIndex or as get/set with the property name + int r = FindPropertyAccessor(propertyName == "" ? "opIndex" : propertyName.AddressOf(), &lctx, args[0], node, ns); + if (r == 0) + { + asCString str; + str.Format(TXT_OBJECT_DOESNT_SUPPORT_INDEX_OP, ctx->type.dataType.Format(outFunc->nameSpace).AddressOf()); + Error(str, node); + isOK = false; + } + else if (r < 0) + isOK = false; + + if (isOK) + MergeExprBytecodeAndType(ctx, &lctx); + } } } else @@ -11746,7 +12184,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct for( asUINT n = 0; n < args.GetLength(); n++ ) if( args[n] ) { - asDELETE(args[n],asSExprContext); + asDELETE(args[n], asCExprContext); } if( !isOK ) @@ -11757,30 +12195,30 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct // TODO: Most of this is already done by CompileFunctionCall(). Can we share the code? // Make sure the expression is a funcdef or an object that may have opCall methods - if( !ctx->type.dataType.GetFuncDef() && !ctx->type.dataType.IsObject() ) + if( !ctx->type.dataType.GetTypeInfo() || (!ctx->type.dataType.IsFuncdef() && !ctx->type.dataType.IsObject()) ) { Error(TXT_EXPR_DOESNT_EVAL_TO_FUNC, node); return -1; } // Compile arguments - asCArray args; + asCArray args; asCArray namedArgs; if( CompileArgumentList(node->lastChild, args, namedArgs) >= 0 ) { // Match arguments with the funcdef asCArray funcs; - if( ctx->type.dataType.GetFuncDef() ) + if( ctx->type.dataType.IsFuncdef() ) { - funcs.PushLast(ctx->type.dataType.GetFuncDef()->id); - MatchFunctions(funcs, args, node, ctx->type.dataType.GetFuncDef()->name.AddressOf(), &namedArgs); + funcs.PushLast(CastToFuncdefType(ctx->type.dataType.GetTypeInfo())->funcdef->id); + MatchFunctions(funcs, args, node, ctx->type.dataType.GetTypeInfo()->name.AddressOf(), &namedArgs); } else { bool isConst = ctx->type.dataType.IsObjectConst(); - builder->GetObjectMethodDescriptions("opCall", ctx->type.dataType.GetObjectType(), funcs, isConst); - MatchFunctions(funcs, args, node, "opCall", &namedArgs, ctx->type.dataType.GetObjectType(), isConst); + builder->GetObjectMethodDescriptions("opCall", CastToObjectType(ctx->type.dataType.GetTypeInfo()), funcs, isConst); + MatchFunctions(funcs, args, node, "opCall", &namedArgs, CastToObjectType(ctx->type.dataType.GetTypeInfo()), isConst); } if( funcs.GetLength() != 1 ) @@ -11793,7 +12231,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct else { // Add the default values for arguments not explicitly supplied - int r = CompileDefaultAndNamedArgs(node, args, funcs[0], ctx->type.dataType.GetObjectType(), &namedArgs); + int r = CompileDefaultAndNamedArgs(node, args, funcs[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), &namedArgs); // TODO: funcdef: Do we have to make sure the handle is stored in a temporary variable, or // is it enough to make sure it is in a local variable? @@ -11803,7 +12241,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct if( r == asSUCCESS ) { Dereference(ctx, true); - if( ctx->type.dataType.GetFuncDef() ) + if( ctx->type.dataType.IsFuncdef() ) { if( !ctx->type.isVariable ) ConvertToVariable(ctx); @@ -11812,7 +12250,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct ctx->bc.Instr(asBC_PopPtr); } - MakeFunctionCall(ctx, funcs[0], ctx->type.dataType.GetFuncDef() ? 0 : ctx->type.dataType.GetObjectType(), args, node, false, 0, ctx->type.stackOffset); + MakeFunctionCall(ctx, funcs[0], ctx->type.dataType.IsFuncdef() ? 0 : CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node, false, 0, ctx->type.stackOffset); } } } @@ -11823,12 +12261,12 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct for( asUINT n = 0; n < args.GetLength(); n++ ) if( args[n] ) { - asDELETE(args[n],asSExprContext); + asDELETE(args[n], asCExprContext); } for( asUINT n = 0; n < namedArgs.GetLength(); n++ ) if( namedArgs[n].ctx ) { - asDELETE(namedArgs[n].ctx,asSExprContext); + asDELETE(namedArgs[n].ctx, asCExprContext); } } @@ -11900,7 +12338,7 @@ int asCCompiler::GetPrecedence(asCScriptNode *op) return 0; } -asUINT asCCompiler::MatchArgument(asCArray &funcs, asCArray &matches, const asSExprContext *argExpr, int paramNum, bool allowObjectConstruct) +asUINT asCCompiler::MatchArgument(asCArray &funcs, asCArray &matches, const asCExprContext *argExpr, int paramNum, bool allowObjectConstruct) { matches.SetLength(0); @@ -11920,7 +12358,7 @@ asUINT asCCompiler::MatchArgument(asCArray &funcs, asCArrayIsVoidExpression() ) @@ -11930,14 +12368,31 @@ int asCCompiler::MatchArgument(asCScriptFunction *desc, const asSExprContext *ar return -1; } + // Anonymous init lists can only match parameters that can be initialized with a list + if (argExpr->IsAnonymousInitList()) + { + if ((desc->parameterTypes[paramNum].IsReference() && desc->inOutFlags[paramNum] != asTM_INREF) || + desc->parameterTypes[paramNum].GetTypeInfo() == 0 || + desc->parameterTypes[paramNum].GetBehaviour()->listFactory == 0) + { + return -1; + } + return 0; + } + // Can we make the match by implicit conversion? - asSExprContext ti(engine); + asCExprContext ti(engine); ti.type = argExpr->type; ti.methodName = argExpr->methodName; ti.enumValue = argExpr->enumValue; ti.exprNode = argExpr->exprNode; if( argExpr->type.dataType.IsPrimitive() ) ti.type.dataType.MakeReference(false); + + // Don't allow the implicit conversion to make a copy in case the argument is expecting a reference to the true value + if (desc->parameterTypes[paramNum].IsReference() && desc->inOutFlags[paramNum] == asTM_INOUTREF) + allowObjectConstruct = false; + int cost = ImplicitConversion(&ti, desc->parameterTypes[paramNum], 0, asIC_IMPLICIT_CONV, false, allowObjectConstruct); // If the function parameter is an inout-reference then it must not be possible to call the @@ -11960,7 +12415,7 @@ int asCCompiler::MatchArgument(asCScriptFunction *desc, const asSExprContext *ar // Don't allow an enum to be converted to a reference of another enum type if( desc->parameterTypes[paramNum].IsEnumType() && - desc->parameterTypes[paramNum].GetObjectType() != argExpr->type.dataType.GetObjectType() ) + desc->parameterTypes[paramNum].GetTypeInfo() != argExpr->type.dataType.GetTypeInfo() ) { asASSERT( engine->ep.allowUnsafeReferences ); return -1; @@ -11975,8 +12430,8 @@ int asCCompiler::MatchArgument(asCScriptFunction *desc, const asSExprContext *ar } // Don't allow a value type to be converted - if( (desc->parameterTypes[paramNum].GetObjectType() && (desc->parameterTypes[paramNum].GetObjectType()->GetFlags() & asOBJ_VALUE)) && - (desc->parameterTypes[paramNum].GetObjectType() != argExpr->type.dataType.GetObjectType()) ) + if( (desc->parameterTypes[paramNum].GetTypeInfo() && (desc->parameterTypes[paramNum].GetTypeInfo()->GetFlags() & asOBJ_VALUE)) && + (desc->parameterTypes[paramNum].GetTypeInfo() != argExpr->type.dataType.GetTypeInfo()) ) { asASSERT( engine->ep.allowUnsafeReferences ); return -1; @@ -11991,14 +12446,14 @@ int asCCompiler::MatchArgument(asCScriptFunction *desc, const asSExprContext *ar return -1; } -void asCCompiler::PrepareArgument2(asSExprContext *ctx, asSExprContext *arg, asCDataType *paramType, bool isFunction, int refType, bool isMakingCopy) +void asCCompiler::PrepareArgument2(asCExprContext *ctx, asCExprContext *arg, asCDataType *paramType, bool isFunction, int refType, bool isMakingCopy) { // Reference parameters whose value won't be used don't evaluate the expression // Clean arguments (i.e. default value) will be passed in directly as there is nothing to protect if( paramType->IsReference() && !(refType & asTM_INREF) && !arg->isCleanArg ) { // Store the original bytecode so that it can be reused when processing the deferred output parameter - asSExprContext *orig = asNEW(asSExprContext)(engine); + asCExprContext *orig = asNEW(asCExprContext)(engine); if( orig == 0 ) { // Out of memory @@ -12014,7 +12469,7 @@ void asCCompiler::PrepareArgument2(asSExprContext *ctx, asSExprContext *arg, asC ctx->bc.AddCode(&arg->bc); } -bool asCCompiler::CompileOverloadedDualOperator(asCScriptNode *node, asSExprContext *lctx, asSExprContext *rctx, asSExprContext *ctx, bool isHandle, eTokenType token) +bool asCCompiler::CompileOverloadedDualOperator(asCScriptNode *node, asCExprContext *lctx, asCExprContext *rctx, bool leftToRight, asCExprContext *ctx, bool isHandle, eTokenType token) { DetermineSingleFunc(lctx, node); DetermineSingleFunc(rctx, node); @@ -12044,11 +12499,11 @@ bool asCCompiler::CompileOverloadedDualOperator(asCScriptNode *node, asSExprCont { // TODO: Should evaluate which of the two have the best match. If both have equal match, the first version should be used // Find the matching opEquals method - int r = CompileOverloadedDualOperator2(node, "opEquals", lctx, rctx, ctx, true, asCDataType::CreatePrimitive(ttBool, false)); + int r = CompileOverloadedDualOperator2(node, "opEquals", lctx, rctx, leftToRight, ctx, true, asCDataType::CreatePrimitive(ttBool, false)); if( r == 0 ) { // Try again by switching the order of the operands - r = CompileOverloadedDualOperator2(node, "opEquals", rctx, lctx, ctx, true, asCDataType::CreatePrimitive(ttBool, false)); + r = CompileOverloadedDualOperator2(node, "opEquals", rctx, lctx, !leftToRight, ctx, true, asCDataType::CreatePrimitive(ttBool, false)); } if( r == 1 ) @@ -12078,12 +12533,12 @@ bool asCCompiler::CompileOverloadedDualOperator(asCScriptNode *node, asSExprCont // TODO: Should evaluate which of the two have the best match. If both have equal match, the first version should be used // Find the matching opCmp method - int r = CompileOverloadedDualOperator2(node, "opCmp", lctx, rctx, ctx, true, asCDataType::CreatePrimitive(ttInt, false)); + int r = CompileOverloadedDualOperator2(node, "opCmp", lctx, rctx, leftToRight, ctx, true, asCDataType::CreatePrimitive(ttInt, false)); if( r == 0 ) { // Try again by switching the order of the operands swappedOrder = true; - r = CompileOverloadedDualOperator2(node, "opCmp", rctx, lctx, ctx, true, asCDataType::CreatePrimitive(ttInt, false)); + r = CompileOverloadedDualOperator2(node, "opCmp", rctx, lctx, !leftToRight, ctx, true, asCDataType::CreatePrimitive(ttInt, false)); } if( r == 1 ) @@ -12121,7 +12576,11 @@ bool asCCompiler::CompileOverloadedDualOperator(asCScriptNode *node, asSExprCont else if( r < 0 ) { // Compiler error, don't continue - ctx->type.SetConstantDW(asCDataType::CreatePrimitive(ttBool, true), true); + #if AS_SIZEOF_BOOL == 1 + ctx->type.SetConstantB(asCDataType::CreatePrimitive(ttBool, true), true); + #else + ctx->type.SetConstantDW(asCDataType::CreatePrimitive(ttBool, true), true); + #endif return true; } } @@ -12150,11 +12609,11 @@ bool asCCompiler::CompileOverloadedDualOperator(asCScriptNode *node, asSExprCont { // TODO: Should evaluate which of the two have the best match. If both have equal match, the first version should be used // Find the matching operator method - int r = CompileOverloadedDualOperator2(node, op, lctx, rctx, ctx); + int r = CompileOverloadedDualOperator2(node, op, lctx, rctx, leftToRight, ctx); if( r == 0 ) { // Try again by switching the order of the operands, and using the reversed operator - r = CompileOverloadedDualOperator2(node, op_r, rctx, lctx, ctx); + r = CompileOverloadedDualOperator2(node, op_r, rctx, lctx, !leftToRight, ctx); } if( r == 1 ) @@ -12175,7 +12634,7 @@ bool asCCompiler::CompileOverloadedDualOperator(asCScriptNode *node, asSExprCont if( isHandle ) { // Only asOBJ_ASHANDLE types can get here - asASSERT( lctx->type.dataType.GetObjectType() && (lctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE) ); + asASSERT( lctx->type.dataType.GetTypeInfo() && (lctx->type.dataType.GetTypeInfo()->flags & asOBJ_ASHANDLE) ); asASSERT( token == ttAssignment ); if( token == ttAssignment ) @@ -12204,7 +12663,7 @@ bool asCCompiler::CompileOverloadedDualOperator(asCScriptNode *node, asSExprCont if( op ) { if( builder->engine->ep.disallowValueAssignForRefType && - lctx->type.dataType.GetObjectType() && (lctx->type.dataType.GetObjectType()->flags & asOBJ_REF) && !(lctx->type.dataType.GetObjectType()->flags & asOBJ_SCOPED) ) + lctx->type.dataType.GetTypeInfo() && (lctx->type.dataType.GetTypeInfo()->flags & asOBJ_REF) && !(lctx->type.dataType.GetTypeInfo()->flags & asOBJ_SCOPED) ) { if( token == ttAssignment ) Error(TXT_DISALLOW_ASSIGN_ON_REF_TYPE, node); @@ -12219,7 +12678,7 @@ bool asCCompiler::CompileOverloadedDualOperator(asCScriptNode *node, asSExprCont // TODO: Shouldn't accept const lvalue with the assignment operators // Find the matching operator method - int r = CompileOverloadedDualOperator2(node, op, lctx, rctx, ctx); + int r = CompileOverloadedDualOperator2(node, op, lctx, rctx, false, ctx); if( r == 1 ) { // Success, don't continue @@ -12240,12 +12699,12 @@ bool asCCompiler::CompileOverloadedDualOperator(asCScriptNode *node, asSExprCont // Returns negative on compile error // zero on no matching operator // one on matching operator -int asCCompiler::CompileOverloadedDualOperator2(asCScriptNode *node, const char *methodName, asSExprContext *lctx, asSExprContext *rctx, asSExprContext *ctx, bool specificReturn, const asCDataType &returnType) +int asCCompiler::CompileOverloadedDualOperator2(asCScriptNode *node, const char *methodName, asCExprContext *lctx, asCExprContext *rctx, bool leftToRight, asCExprContext *ctx, bool specificReturn, const asCDataType &returnType) { // Find the matching method if( lctx->type.dataType.IsObject() && (!lctx->type.isExplicitHandle || - lctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE) ) + lctx->type.dataType.GetTypeInfo()->flags & asOBJ_ASHANDLE) ) { asUINT n; @@ -12253,7 +12712,7 @@ int asCCompiler::CompileOverloadedDualOperator2(asCScriptNode *node, const char bool isConst = lctx->type.dataType.IsObjectConst(); asCArray funcs; - asCObjectType *ot = lctx->type.dataType.GetObjectType(); + asCObjectType *ot = CastToObjectType(lctx->type.dataType.GetTypeInfo()); for( n = 0; n < ot->methods.GetLength(); n++ ) { asCScriptFunction *func = engine->scriptFunctions[ot->methods[n]]; @@ -12261,7 +12720,7 @@ int asCCompiler::CompileOverloadedDualOperator2(asCScriptNode *node, const char if( func && func->name == methodName && (!specificReturn || func->returnType == returnType) && func->parameterTypes.GetLength() == 1 && - (!isConst || func->isReadOnly) ) + (!isConst || func->IsReadOnly()) ) { // Make sure the method is accessible by the module if( builder->module->accessMask & func->accessMask ) @@ -12297,38 +12756,88 @@ int asCCompiler::CompileOverloadedDualOperator2(asCScriptNode *node, const char // Did we find an operator? if( ops.GetLength() == 1 ) { + // Reserve the variables used in the right expression so the new temporary + // variable allocated for the left operand isn't accidentally overwritten. + int l = int(reservedVariables.GetLength()); + rctx->bc.GetVarsUsed(reservedVariables); + // Process the lctx expression as get accessor ProcessPropertyGetAccessor(lctx, node); - // Make sure the rvalue doesn't have deferred temporary variables that are also used in the lvalue, - // since that would cause the VM to overwrite the variable while executing the bytecode for the lvalue. - asCArray usedVars; - lctx->bc.GetVarsUsed(usedVars); - asUINT oldReservedVars = reservedVariables.GetLength(); - for( asUINT n = 0; n < rctx->deferredParams.GetLength(); n++ ) - { - if( rctx->deferredParams[n].argType.isTemporary && - usedVars.Exists(rctx->deferredParams[n].argType.stackOffset) ) - { - if( reservedVariables.GetLength() == oldReservedVars ) - reservedVariables.Concatenate(usedVars); + reservedVariables.SetLength(l); - // Allocate a new variable for the deferred argument - int offset = AllocateVariableNotIn(rctx->deferredParams[n].argType.dataType, true, false, rctx); - int oldVar = rctx->deferredParams[n].argType.stackOffset; - rctx->deferredParams[n].argType.stackOffset = short(offset); - rctx->bc.ExchangeVar(oldVar, offset); - ReleaseTemporaryVariable(oldVar, 0); + asCExprContext tmpCtx(engine); + if (leftToRight) + { + // Make sure lctx is in fact a variable. If it is a reference there is no + // guarantee that the reference will stay alive throughout the evaluation of rctx + if (!lctx->type.isVariable) + { + // Reserve the variables used in the right expression so the new temporary + // variable allocated for the left operand isn't accidentally overwritten. + l = int(reservedVariables.GetLength()); + rctx->bc.GetVarsUsed(reservedVariables); + + if (lctx->type.dataType.SupportHandles()) + lctx->type.dataType.MakeHandle(true); + PrepareTemporaryVariable(node, lctx); + + reservedVariables.SetLength(l); } + + // Move the bytecode for the left operand to a temporary context + // so we can later make sure this is computed first + tmpCtx.bc.AddCode(&lctx->bc); + tmpCtx.bc.Instr(asBC_PopPtr); + + // Add bytecode to push the object pointer computed in the left operand on the stack as the this pointer + // This will be placed after rctx by MakeFunctionCall below + lctx->bc.InstrWORD(asBC_PSF, lctx->type.stackOffset); + + // Implicitly dereference handle parameters sent by reference + sVariable *v = variables->GetVariableByOffset(lctx->type.stackOffset); + if (v && v->type.IsReference() && (!v->type.IsObject() || v->type.IsObjectHandle())) + lctx->bc.Instr(asBC_RDSPtr); + } + else + { + // Make sure the rvalue doesn't have deferred temporary variables that are also used in the lvalue, + // since that would cause the VM to overwrite the variable while executing the bytecode for the lvalue. + asCArray usedVars; + lctx->bc.GetVarsUsed(usedVars); + asUINT oldReservedVars = reservedVariables.GetLength(); + for (n = 0; n < rctx->deferredParams.GetLength(); n++) + { + if (rctx->deferredParams[n].argType.isTemporary && + usedVars.Exists(rctx->deferredParams[n].argType.stackOffset)) + { + if (reservedVariables.GetLength() == oldReservedVars) + reservedVariables.Concatenate(usedVars); + + // Allocate a new variable for the deferred argument + int offset = AllocateVariableNotIn(rctx->deferredParams[n].argType.dataType, true, false, rctx); + int oldVar = rctx->deferredParams[n].argType.stackOffset; + rctx->deferredParams[n].argType.stackOffset = short(offset); + rctx->bc.ExchangeVar(oldVar, offset); + ReleaseTemporaryVariable(oldVar, 0); + } + } + reservedVariables.SetLength(oldReservedVars); } - reservedVariables.SetLength(oldReservedVars); // Merge the bytecode so that it forms lvalue.methodName(rvalue) - asCArray args; + asCArray args; args.PushLast(rctx); MergeExprBytecode(ctx, lctx); ctx->type = lctx->type; - MakeFunctionCall(ctx, ops[0], ctx->type.dataType.GetObjectType(), args, node); + MakeFunctionCall(ctx, ops[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node); + + // Rearrange the bytecode so the left argument is computed first + if (leftToRight) + { + tmpCtx.bc.AddCode(&ctx->bc); + ctx->bc.AddCode(&tmpCtx.bc); + } // Found matching operator return 1; @@ -12349,7 +12858,7 @@ int asCCompiler::CompileOverloadedDualOperator2(asCScriptNode *node, const char return 0; } -void asCCompiler::MakeFunctionCall(asSExprContext *ctx, int funcId, asCObjectType *objectType, asCArray &args, asCScriptNode *node, bool useVariable, int stackOffset, int funcPtrVar) +void asCCompiler::MakeFunctionCall(asCExprContext *ctx, int funcId, asCObjectType *objectType, asCArray &args, asCScriptNode *node, bool useVariable, int stackOffset, int funcPtrVar) { if( objectType ) Dereference(ctx, true); @@ -12410,7 +12919,7 @@ void asCCompiler::MakeFunctionCall(asSExprContext *ctx, int funcId, asCObjectTyp PerformFunctionCall(funcId, ctx, false, &args, 0, useVariable, stackOffset, funcPtrVar); } -int asCCompiler::CompileOperator(asCScriptNode *node, asSExprContext *lctx, asSExprContext *rctx, asSExprContext *ctx, eTokenType op) +int asCCompiler::CompileOperator(asCScriptNode *node, asCExprContext *lctx, asCExprContext *rctx, asCExprContext *ctx, eTokenType op, bool leftToRight) { // Don't allow any operators on expressions that take address of class method, but allow it on global functions if( (lctx->IsClassMethod()) || (rctx->IsClassMethod()) ) @@ -12442,7 +12951,7 @@ int asCCompiler::CompileOperator(asCScriptNode *node, asSExprContext *lctx, asSE else { // Compile an overloaded operator for the two operands - if( CompileOverloadedDualOperator(node, lctx, rctx, ctx, false, op) ) + if( CompileOverloadedDualOperator(node, lctx, rctx, leftToRight, ctx, false, op) ) return 0; // If both operands are objects, then we shouldn't continue @@ -12520,7 +13029,7 @@ int asCCompiler::CompileOperator(asCScriptNode *node, asSExprContext *lctx, asSE return -1; } -void asCCompiler::ConvertToTempVariableNotIn(asSExprContext *ctx, asSExprContext *exclude) +void asCCompiler::ConvertToTempVariableNotIn(asCExprContext *ctx, asCExprContext *exclude) { int l = int(reservedVariables.GetLength()); if( exclude ) exclude->bc.GetVarsUsed(reservedVariables); @@ -12528,7 +13037,7 @@ void asCCompiler::ConvertToTempVariableNotIn(asSExprContext *ctx, asSExprContext reservedVariables.SetLength(l); } -void asCCompiler::ConvertToTempVariable(asSExprContext *ctx) +void asCCompiler::ConvertToTempVariable(asCExprContext *ctx) { // This is only used for primitive types and null handles asASSERT( ctx->type.dataType.IsPrimitive() || ctx->type.dataType.IsNullHandle() ); @@ -12554,7 +13063,7 @@ void asCCompiler::ConvertToTempVariable(asSExprContext *ctx) } } -void asCCompiler::ConvertToVariable(asSExprContext *ctx) +void asCCompiler::ConvertToVariable(asCExprContext *ctx) { // We should never get here while the context is still an unprocessed property accessor asASSERT(ctx->property_get == 0 && ctx->property_set == 0); @@ -12577,7 +13086,10 @@ void asCCompiler::ConvertToVariable(asSExprContext *ctx) // Copy the object handle to a variable ctx->bc.InstrSHORT(asBC_PSF, (short)offset); - ctx->bc.InstrPTR(asBC_REFCPY, ctx->type.dataType.GetObjectType()); + if( ctx->type.dataType.IsFuncdef() ) + ctx->bc.InstrPTR(asBC_REFCPY, &engine->functionBehaviours); + else + ctx->bc.InstrPTR(asBC_REFCPY, ctx->type.dataType.GetTypeInfo()); ctx->bc.Instr(asBC_PopPtr); } @@ -12596,13 +13108,13 @@ void asCCompiler::ConvertToVariable(asSExprContext *ctx) { offset = AllocateVariable(ctx->type.dataType, true); if( ctx->type.dataType.GetSizeInMemoryBytes() == 1 ) - ctx->bc.InstrSHORT_B(asBC_SetV1, (short)offset, ctx->type.byteValue); + ctx->bc.InstrSHORT_B(asBC_SetV1, (short)offset, ctx->type.GetConstantB()); else if( ctx->type.dataType.GetSizeInMemoryBytes() == 2 ) - ctx->bc.InstrSHORT_W(asBC_SetV2, (short)offset, ctx->type.wordValue); + ctx->bc.InstrSHORT_W(asBC_SetV2, (short)offset, ctx->type.GetConstantW()); else if( ctx->type.dataType.GetSizeInMemoryBytes() == 4 ) - ctx->bc.InstrSHORT_DW(asBC_SetV4, (short)offset, ctx->type.dwordValue); + ctx->bc.InstrSHORT_DW(asBC_SetV4, (short)offset, ctx->type.GetConstantDW()); else - ctx->bc.InstrSHORT_QW(asBC_SetV8, (short)offset, ctx->type.qwordValue); + ctx->bc.InstrSHORT_QW(asBC_SetV8, (short)offset, ctx->type.GetConstantQW()); ctx->type.SetVariable(ctx->type.dataType, offset, true); return; @@ -12631,7 +13143,7 @@ void asCCompiler::ConvertToVariable(asSExprContext *ctx) } } -void asCCompiler::ConvertToVariableNotIn(asSExprContext *ctx, asSExprContext *exclude) +void asCCompiler::ConvertToVariableNotIn(asCExprContext *ctx, asCExprContext *exclude) { int l = int(reservedVariables.GetLength()); if( exclude ) exclude->bc.GetVarsUsed(reservedVariables); @@ -12639,10 +13151,10 @@ void asCCompiler::ConvertToVariableNotIn(asSExprContext *ctx, asSExprContext *ex reservedVariables.SetLength(l); } -void asCCompiler::ImplicitConvObjectToBestMathType(asSExprContext *ctx, asCScriptNode *node) +void asCCompiler::ImplicitConvObjectToBestMathType(asCExprContext *ctx, asCScriptNode *node) { asCArray funcs; - asCObjectType *ot = ctx->type.dataType.GetObjectType(); + asCObjectType *ot = CastToObjectType(ctx->type.dataType.GetTypeInfo()); if( ot ) { for( unsigned int n = 0; n < ot->methods.GetLength(); n++ ) @@ -12702,7 +13214,7 @@ void asCCompiler::ImplicitConvObjectToBestMathType(asSExprContext *ctx, asCScrip } } -void asCCompiler::CompileMathOperator(asCScriptNode *node, asSExprContext *lctx, asSExprContext *rctx, asSExprContext *ctx, eTokenType op) +void asCCompiler::CompileMathOperator(asCScriptNode *node, asCExprContext *lctx, asCExprContext *rctx, asCExprContext *ctx, eTokenType op) { // TODO: If a constant is only using 32bits, then a 32bit operation is preferred @@ -12833,9 +13345,13 @@ void asCCompiler::CompileMathOperator(asCScriptNode *node, asSExprContext *lctx, bool isConstant = lctx->type.isConstant && rctx->type.isConstant; // Verify if we are dividing with a constant zero - if( rctx->type.isConstant && rctx->type.qwordValue == 0 && + if( rctx->type.isConstant && (op == ttSlash || op == ttDivAssign || - op == ttPercent || op == ttModAssign) ) + op == ttPercent || op == ttModAssign) && + ((rctx->type.dataType.GetSizeInMemoryBytes() == 4 && rctx->type.GetConstantDW() == 0) || + (rctx->type.dataType.GetSizeInMemoryBytes() == 8 && rctx->type.GetConstantQW() == 0) || + (rctx->type.dataType.GetSizeInMemoryBytes() == 1 && rctx->type.GetConstantB() == 0) || + (rctx->type.dataType.GetSizeInMemoryBytes() == 2 && rctx->type.GetConstantW() == 0)) ) { Error(TXT_DIVIDE_BY_ZERO, node); } @@ -12998,40 +13514,40 @@ void asCCompiler::CompileMathOperator(asCScriptNode *node, asSExprContext *lctx, { int v = 0; if( op == ttPlus ) - v = lctx->type.intValue + rctx->type.intValue; + v = int(lctx->type.GetConstantDW()) + int(rctx->type.GetConstantDW()); else if( op == ttMinus ) - v = lctx->type.intValue - rctx->type.intValue; + v = int(lctx->type.GetConstantDW()) - int(rctx->type.GetConstantDW()); else if( op == ttStar ) - v = lctx->type.intValue * rctx->type.intValue; + v = int(lctx->type.GetConstantDW()) * int(rctx->type.GetConstantDW()); else if( op == ttSlash ) { // TODO: Should probably report an error, rather than silently convert the value to 0 - if( rctx->type.intValue == 0 || (rctx->type.intValue == -1 && lctx->type.dwordValue == 0x80000000) ) + if( rctx->type.GetConstantDW() == 0 || (int(rctx->type.GetConstantDW()) == -1 && lctx->type.GetConstantDW() == 0x80000000) ) v = 0; else if( lctx->type.dataType.IsIntegerType() ) - v = lctx->type.intValue / rctx->type.intValue; + v = int(lctx->type.GetConstantDW()) / int(rctx->type.GetConstantDW()); else - v = lctx->type.dwordValue / rctx->type.dwordValue; + v = lctx->type.GetConstantDW() / rctx->type.GetConstantDW(); } else if( op == ttPercent ) { // TODO: Should probably report an error, rather than silently convert the value to 0 - if( rctx->type.intValue == 0 || (rctx->type.intValue == -1 && lctx->type.dwordValue == 0x80000000) ) + if( rctx->type.GetConstantDW() == 0 || (int(rctx->type.GetConstantDW()) == -1 && lctx->type.GetConstantDW() == 0x80000000) ) v = 0; else if( lctx->type.dataType.IsIntegerType() ) - v = lctx->type.intValue % rctx->type.intValue; + v = int(lctx->type.GetConstantDW()) % int(rctx->type.GetConstantDW()); else - v = lctx->type.dwordValue % rctx->type.dwordValue; + v = lctx->type.GetConstantDW() % rctx->type.GetConstantDW(); } else if( op == ttStarStar ) { bool isOverflow; if( lctx->type.dataType.IsIntegerType() ) - v = as_powi(lctx->type.intValue, rctx->type.intValue, isOverflow); + v = as_powi(int(lctx->type.GetConstantDW()), int(rctx->type.GetConstantDW()), isOverflow); else - v = as_powu(lctx->type.dwordValue, rctx->type.dwordValue, isOverflow); + v = as_powu(lctx->type.GetConstantDW(), rctx->type.GetConstantDW(), isOverflow); if( isOverflow ) Error(TXT_POW_OVERFLOW, node); @@ -13040,47 +13556,47 @@ void asCCompiler::CompileMathOperator(asCScriptNode *node, asSExprContext *lctx, ctx->type.SetConstantDW(lctx->type.dataType, v); // If the right value is greater than the left value in a minus operation, then we need to convert the type to int - if( lctx->type.dataType.GetTokenType() == ttUInt && op == ttMinus && lctx->type.intValue < rctx->type.intValue ) + if( lctx->type.dataType.GetTokenType() == ttUInt && op == ttMinus && lctx->type.GetConstantDW() < rctx->type.GetConstantDW()) ctx->type.dataType.SetTokenType(ttInt); } else { asQWORD v = 0; if( op == ttPlus ) - v = lctx->type.qwordValue + rctx->type.qwordValue; + v = asINT64(lctx->type.GetConstantQW()) + asINT64(rctx->type.GetConstantQW()); else if( op == ttMinus ) - v = lctx->type.qwordValue - rctx->type.qwordValue; + v = asINT64(lctx->type.GetConstantQW()) - asINT64(rctx->type.GetConstantQW()); else if( op == ttStar ) - v = lctx->type.qwordValue * rctx->type.qwordValue; + v = asINT64(lctx->type.GetConstantQW()) * asINT64(rctx->type.GetConstantQW()); else if( op == ttSlash ) { // TODO: Should probably report an error, rather than silently convert the value to 0 - if( rctx->type.qwordValue == 0 || (rctx->type.qwordValue == asQWORD(-1) && lctx->type.qwordValue == (asQWORD(1)<<63)) ) + if( rctx->type.GetConstantQW() == 0 || (rctx->type.GetConstantQW() == asQWORD(-1) && lctx->type.GetConstantQW() == (asQWORD(1)<<63)) ) v = 0; else if( lctx->type.dataType.IsIntegerType() ) - v = asINT64(lctx->type.qwordValue) / asINT64(rctx->type.qwordValue); + v = asINT64(lctx->type.GetConstantQW()) / asINT64(rctx->type.GetConstantQW()); else - v = lctx->type.qwordValue / rctx->type.qwordValue; + v = lctx->type.GetConstantQW() / rctx->type.GetConstantQW(); } else if( op == ttPercent ) { // TODO: Should probably report an error, rather than silently convert the value to 0 - if( rctx->type.qwordValue == 0 || (rctx->type.qwordValue == asQWORD(-1) && lctx->type.qwordValue == (asQWORD(1)<<63)) ) + if( rctx->type.GetConstantQW() == 0 || (rctx->type.GetConstantQW() == asQWORD(-1) && lctx->type.GetConstantQW() == (asQWORD(1)<<63)) ) v = 0; else if( lctx->type.dataType.IsIntegerType() ) - v = asINT64(lctx->type.qwordValue) % asINT64(rctx->type.qwordValue); + v = asINT64(lctx->type.GetConstantQW()) % asINT64(rctx->type.GetConstantQW()); else - v = lctx->type.qwordValue % rctx->type.qwordValue; + v = lctx->type.GetConstantQW() % rctx->type.GetConstantQW(); } else if( op == ttStarStar ) { bool isOverflow; if( lctx->type.dataType.IsIntegerType() ) - v = as_powi64(asINT64(lctx->type.qwordValue), asINT64(rctx->type.qwordValue), isOverflow); + v = as_powi64(asINT64(lctx->type.GetConstantQW()), asINT64(rctx->type.GetConstantQW()), isOverflow); else - v = as_powu64(lctx->type.qwordValue, rctx->type.qwordValue, isOverflow); + v = as_powu64(lctx->type.GetConstantQW(), rctx->type.GetConstantQW(), isOverflow); if( isOverflow ) Error(TXT_POW_OVERFLOW, node); @@ -13089,7 +13605,7 @@ void asCCompiler::CompileMathOperator(asCScriptNode *node, asSExprContext *lctx, ctx->type.SetConstantQW(lctx->type.dataType, v); // If the right value is greater than the left value in a minus operation, then we need to convert the type to int - if( lctx->type.dataType.GetTokenType() == ttUInt64 && op == ttMinus && lctx->type.qwordValue < rctx->type.qwordValue ) + if( lctx->type.dataType.GetTokenType() == ttUInt64 && op == ttMinus && lctx->type.GetConstantQW() < rctx->type.GetConstantQW()) ctx->type.dataType.SetTokenType(ttInt64); } } @@ -13097,28 +13613,28 @@ void asCCompiler::CompileMathOperator(asCScriptNode *node, asSExprContext *lctx, { float v = 0.0f; if( op == ttPlus ) - v = lctx->type.floatValue + rctx->type.floatValue; + v = lctx->type.GetConstantF() + rctx->type.GetConstantF(); else if( op == ttMinus ) - v = lctx->type.floatValue - rctx->type.floatValue; + v = lctx->type.GetConstantF() - rctx->type.GetConstantF(); else if( op == ttStar ) - v = lctx->type.floatValue * rctx->type.floatValue; + v = lctx->type.GetConstantF() * rctx->type.GetConstantF(); else if( op == ttSlash ) { - if( rctx->type.floatValue == 0 ) + if( rctx->type.GetConstantF() == 0 ) v = 0; else - v = lctx->type.floatValue / rctx->type.floatValue; + v = lctx->type.GetConstantF() / rctx->type.GetConstantF(); } else if( op == ttPercent ) { - if( rctx->type.floatValue == 0 ) + if( rctx->type.GetConstantF() == 0 ) v = 0; else - v = fmodf(lctx->type.floatValue, rctx->type.floatValue); + v = fmodf(lctx->type.GetConstantF(), rctx->type.GetConstantF()); } else if( op == ttStarStar ) { - v = pow(lctx->type.floatValue, rctx->type.floatValue); + v = powf(lctx->type.GetConstantF(), rctx->type.GetConstantF()); if( v == HUGE_VAL ) Error(TXT_POW_OVERFLOW, node); @@ -13135,7 +13651,7 @@ void asCCompiler::CompileMathOperator(asCScriptNode *node, asSExprContext *lctx, if( op == ttStarStar || op == ttPowAssign ) { - v = pow(lctx->type.doubleValue, rctx->type.intValue); + v = pow(lctx->type.GetConstantD(), int(rctx->type.GetConstantDW())); if( v == HUGE_VAL ) Error(TXT_POW_OVERFLOW, node); } @@ -13145,28 +13661,28 @@ void asCCompiler::CompileMathOperator(asCScriptNode *node, asSExprContext *lctx, else { if( op == ttPlus ) - v = lctx->type.doubleValue + rctx->type.doubleValue; + v = lctx->type.GetConstantD() + rctx->type.GetConstantD(); else if( op == ttMinus ) - v = lctx->type.doubleValue - rctx->type.doubleValue; + v = lctx->type.GetConstantD() - rctx->type.GetConstantD(); else if( op == ttStar ) - v = lctx->type.doubleValue * rctx->type.doubleValue; + v = lctx->type.GetConstantD() * rctx->type.GetConstantD(); else if( op == ttSlash ) { - if( rctx->type.doubleValue == 0 ) + if( rctx->type.GetConstantD() == 0 ) v = 0; else - v = lctx->type.doubleValue / rctx->type.doubleValue; + v = lctx->type.GetConstantD() / rctx->type.GetConstantD(); } else if( op == ttPercent ) { - if( rctx->type.doubleValue == 0 ) + if( rctx->type.GetConstantD() == 0 ) v = 0; else - v = fmod(lctx->type.doubleValue, rctx->type.doubleValue); + v = fmod(lctx->type.GetConstantD(), rctx->type.GetConstantD()); } else if( op == ttStarStar ) { - v = pow(lctx->type.doubleValue, rctx->type.doubleValue); + v = pow(lctx->type.GetConstantD(), rctx->type.GetConstantD()); if( v == HUGE_VAL ) Error(TXT_POW_OVERFLOW, node); } @@ -13182,7 +13698,7 @@ void asCCompiler::CompileMathOperator(asCScriptNode *node, asSExprContext *lctx, } } -void asCCompiler::CompileBitwiseOperator(asCScriptNode *node, asSExprContext *lctx, asSExprContext *rctx, asSExprContext *ctx, eTokenType op) +void asCCompiler::CompileBitwiseOperator(asCScriptNode *node, asCExprContext *lctx, asCExprContext *rctx, asCExprContext *ctx, eTokenType op) { // TODO: If a constant is only using 32bits, then a 32bit operation is preferred @@ -13291,11 +13807,11 @@ void asCCompiler::CompileBitwiseOperator(asCScriptNode *node, asSExprContext *lc { asQWORD v = 0; if( op == ttAmp ) - v = lctx->type.qwordValue & rctx->type.qwordValue; + v = lctx->type.GetConstantQW() & rctx->type.GetConstantQW(); else if( op == ttBitOr ) - v = lctx->type.qwordValue | rctx->type.qwordValue; + v = lctx->type.GetConstantQW() | rctx->type.GetConstantQW(); else if( op == ttBitXor ) - v = lctx->type.qwordValue ^ rctx->type.qwordValue; + v = lctx->type.GetConstantQW() ^ rctx->type.GetConstantQW(); // Remember the result ctx->type.SetConstantQW(lctx->type.dataType, v); @@ -13304,11 +13820,11 @@ void asCCompiler::CompileBitwiseOperator(asCScriptNode *node, asSExprContext *lc { asDWORD v = 0; if( op == ttAmp ) - v = lctx->type.dwordValue & rctx->type.dwordValue; + v = lctx->type.GetConstantDW() & rctx->type.GetConstantDW(); else if( op == ttBitOr ) - v = lctx->type.dwordValue | rctx->type.dwordValue; + v = lctx->type.GetConstantDW() | rctx->type.GetConstantDW(); else if( op == ttBitXor ) - v = lctx->type.dwordValue ^ rctx->type.dwordValue; + v = lctx->type.GetConstantDW() ^ rctx->type.GetConstantDW(); // Remember the result ctx->type.SetConstantDW(lctx->type.dataType, v); @@ -13336,15 +13852,15 @@ void asCCompiler::CompileBitwiseOperator(asCScriptNode *node, asSExprContext *lc if( lctx->type.dataType.IsUnsignedType() && lctx->type.dataType.GetSizeInMemoryBytes() < 4 ) { + // Upgrade to 32bit to = asCDataType::CreatePrimitive(ttUInt, false); } else if( !lctx->type.dataType.IsUnsignedType() ) { - asCDataType to; - if( lctx->type.dataType.GetSizeInMemoryDWords() == 2 ) - to.SetTokenType(ttInt64); + if (lctx->type.dataType.GetSizeInMemoryDWords() == 2) + to = asCDataType::CreatePrimitive(ttInt64, false); else - to.SetTokenType(ttInt); + to = asCDataType::CreatePrimitive(ttInt, false); } // Do the actual conversion @@ -13430,11 +13946,11 @@ void asCCompiler::CompileBitwiseOperator(asCScriptNode *node, asSExprContext *lc { asDWORD v = 0; if( op == ttBitShiftLeft ) - v = lctx->type.dwordValue << rctx->type.dwordValue; + v = lctx->type.GetConstantDW() << rctx->type.GetConstantDW(); else if( op == ttBitShiftRight ) - v = lctx->type.dwordValue >> rctx->type.dwordValue; + v = lctx->type.GetConstantDW() >> rctx->type.GetConstantDW(); else if( op == ttBitShiftRightArith ) - v = lctx->type.intValue >> rctx->type.dwordValue; + v = int(lctx->type.GetConstantDW()) >> rctx->type.GetConstantDW(); ctx->type.SetConstantDW(lctx->type.dataType, v); } @@ -13442,11 +13958,11 @@ void asCCompiler::CompileBitwiseOperator(asCScriptNode *node, asSExprContext *lc { asQWORD v = 0; if( op == ttBitShiftLeft ) - v = lctx->type.qwordValue << rctx->type.dwordValue; + v = lctx->type.GetConstantQW() << rctx->type.GetConstantDW(); else if( op == ttBitShiftRight ) - v = lctx->type.qwordValue >> rctx->type.dwordValue; + v = lctx->type.GetConstantQW() >> rctx->type.GetConstantDW(); else if( op == ttBitShiftRightArith ) - v = asINT64(lctx->type.qwordValue) >> rctx->type.dwordValue; + v = asINT64(lctx->type.GetConstantQW()) >> rctx->type.GetConstantDW(); ctx->type.SetConstantQW(lctx->type.dataType, v); } @@ -13454,7 +13970,7 @@ void asCCompiler::CompileBitwiseOperator(asCScriptNode *node, asSExprContext *lc } } -void asCCompiler::CompileComparisonOperator(asCScriptNode *node, asSExprContext *lctx, asSExprContext *rctx, asSExprContext *ctx, eTokenType op) +void asCCompiler::CompileComparisonOperator(asCScriptNode *node, asCExprContext *lctx, asCExprContext *rctx, asCExprContext *ctx, eTokenType op) { // Both operands must be of the same type @@ -13516,22 +14032,32 @@ void asCCompiler::CompileComparisonOperator(asCScriptNode *node, asSExprContext bool signMismatch = false; for( int n = 0; !signMismatch && n < 2; n++ ) { - asSExprContext *op = n ? rctx : lctx; + asCExprContext *opCtx = n ? rctx : lctx; - if( op->type.dataType.IsUnsignedType() != to.IsUnsignedType() ) + if( opCtx->type.dataType.IsUnsignedType() != to.IsUnsignedType() ) { // We have a mismatch, unless the value is a literal constant and the conversion won't affect its value signMismatch = true; - if( op->type.isConstant ) + if( opCtx->type.isConstant ) { - if( op->type.dataType.GetTokenType() == ttUInt64 || op->type.dataType.GetTokenType() == ttInt64 ) + if( opCtx->type.dataType.GetTokenType() == ttUInt64 || opCtx->type.dataType.GetTokenType() == ttInt64 ) { - if( !(op->type.qwordValue & (asQWORD(1)<<63)) ) + if( !(opCtx->type.GetConstantQW() & (asQWORD(1)<<63)) ) signMismatch = false; } - else + else if(opCtx->type.dataType.GetTokenType() == ttUInt || opCtx->type.dataType.GetTokenType() == ttInt || opCtx->type.dataType.IsEnumType() ) { - if( !(op->type.dwordValue & (1<<31)) ) + if( !(opCtx->type.GetConstantDW() & (1<<31)) ) + signMismatch = false; + } + else if (opCtx->type.dataType.GetTokenType() == ttUInt16 || opCtx->type.dataType.GetTokenType() == ttInt16) + { + if (!(opCtx->type.GetConstantW() & (1 << 15))) + signMismatch = false; + } + else if (opCtx->type.dataType.GetTokenType() == ttUInt8 || opCtx->type.dataType.GetTokenType() == ttInt8) + { + if (!(opCtx->type.GetConstantB() & (1 << 7))) signMismatch = false; } @@ -13586,12 +14112,16 @@ void asCCompiler::CompileComparisonOperator(asCScriptNode *node, asSExprContext { // It wasn't possible to get two valid operands, so we just return // a boolean result and let the compiler continue. +#if AS_SIZEOF_BOOL == 1 + ctx->type.SetConstantB(asCDataType::CreatePrimitive(ttBool, true), true); +#else ctx->type.SetConstantDW(asCDataType::CreatePrimitive(ttBool, true), true); +#endif return; } bool isConstant = lctx->type.isConstant && rctx->type.isConstant; - + if( op == ttUnrecognizedToken ) op = node->tokenType; @@ -13638,7 +14168,11 @@ void asCCompiler::CompileComparisonOperator(asCScriptNode *node, asSExprContext { // TODO: Use TXT_ILLEGAL_OPERATION_ON Error(TXT_ILLEGAL_OPERATION, node); +#if AS_SIZEOF_BOOL == 1 + ctx->type.SetConstantB(asCDataType::CreatePrimitive(ttBool, true), 0); +#else ctx->type.SetConstantDW(asCDataType::CreatePrimitive(ttBool, true), 0); +#endif } } else @@ -13699,23 +14233,30 @@ void asCCompiler::CompileComparisonOperator(asCScriptNode *node, asSExprContext { if( op == ttEqual || op == ttNotEqual ) { + asDWORD lv, rv; + #if AS_SIZEOF_BOOL == 1 + lv = lctx->type.GetConstantB(); + rv = rctx->type.GetConstantB(); + #else + lv = lctx->type.GetConstantDW(); + rv = rctx->type.GetConstantDW(); + #endif + // Make sure they are equal if not false - if( lctx->type.dwordValue != 0 ) lctx->type.dwordValue = VALUE_OF_BOOLEAN_TRUE; - if( rctx->type.dwordValue != 0 ) rctx->type.dwordValue = VALUE_OF_BOOLEAN_TRUE; + if (lv != 0) lv = VALUE_OF_BOOLEAN_TRUE; + if (rv != 0) rv = VALUE_OF_BOOLEAN_TRUE; asDWORD v = 0; - if( op == ttEqual ) - { - v = lctx->type.intValue - rctx->type.intValue; - if( v == 0 ) v = VALUE_OF_BOOLEAN_TRUE; else v = 0; - } - else if( op == ttNotEqual ) - { - v = lctx->type.intValue - rctx->type.intValue; - if( v != 0 ) v = VALUE_OF_BOOLEAN_TRUE; else v = 0; - } + if (op == ttEqual) + v = (lv == rv) ? VALUE_OF_BOOLEAN_TRUE : 0; + else if (op == ttNotEqual) + v = (lv != rv) ? VALUE_OF_BOOLEAN_TRUE : 0; - ctx->type.SetConstantDW(asCDataType::CreatePrimitive(ttBool, true), v); + #if AS_SIZEOF_BOOL == 1 + ctx->type.SetConstantB(asCDataType::CreatePrimitive(ttBool, true), (asBYTE)v); + #else + ctx->type.SetConstantDW(asCDataType::CreatePrimitive(ttBool, true), v); + #endif } else { @@ -13728,39 +14269,39 @@ void asCCompiler::CompileComparisonOperator(asCScriptNode *node, asSExprContext int i = 0; if( lctx->type.dataType.IsIntegerType() && lctx->type.dataType.GetSizeInMemoryDWords() == 1 ) { - int v = lctx->type.intValue - rctx->type.intValue; + int v = int(lctx->type.GetConstantDW()) - int(rctx->type.GetConstantDW()); if( v < 0 ) i = -1; if( v > 0 ) i = 1; } else if( lctx->type.dataType.IsUnsignedType() && lctx->type.dataType.GetSizeInMemoryDWords() == 1 ) { - asDWORD v1 = lctx->type.dwordValue; - asDWORD v2 = rctx->type.dwordValue; + asDWORD v1 = lctx->type.GetConstantDW(); + asDWORD v2 = rctx->type.GetConstantDW(); if( v1 < v2 ) i = -1; if( v1 > v2 ) i = 1; } else if( lctx->type.dataType.IsIntegerType() && lctx->type.dataType.GetSizeInMemoryDWords() == 2 ) { - asINT64 v = asINT64(lctx->type.qwordValue) - asINT64(rctx->type.qwordValue); + asINT64 v = asINT64(lctx->type.GetConstantQW()) - asINT64(rctx->type.GetConstantQW()); if( v < 0 ) i = -1; if( v > 0 ) i = 1; } else if( lctx->type.dataType.IsUnsignedType() && lctx->type.dataType.GetSizeInMemoryDWords() == 2 ) { - asQWORD v1 = lctx->type.qwordValue; - asQWORD v2 = rctx->type.qwordValue; + asQWORD v1 = lctx->type.GetConstantQW(); + asQWORD v2 = rctx->type.GetConstantQW(); if( v1 < v2 ) i = -1; if( v1 > v2 ) i = 1; } else if( lctx->type.dataType.IsFloatType() ) { - float v = lctx->type.floatValue - rctx->type.floatValue; + float v = lctx->type.GetConstantF() - rctx->type.GetConstantF(); if( v < 0 ) i = -1; if( v > 0 ) i = 1; } else if( lctx->type.dataType.IsDoubleType() ) { - double v = lctx->type.doubleValue - rctx->type.doubleValue; + double v = lctx->type.GetConstantD() - rctx->type.GetConstantD(); if( v < 0 ) i = -1; if( v > 0 ) i = 1; } @@ -13779,12 +14320,16 @@ void asCCompiler::CompileComparisonOperator(asCScriptNode *node, asSExprContext else if( op == ttGreaterThanOrEqual ) i = (i >= 0 ? VALUE_OF_BOOLEAN_TRUE : 0); - ctx->type.SetConstantDW(asCDataType::CreatePrimitive(ttBool, true), i); + #if AS_SIZEOF_BOOL == 1 + ctx->type.SetConstantB(asCDataType::CreatePrimitive(ttBool, true), (asBYTE)i); + #else + ctx->type.SetConstantDW(asCDataType::CreatePrimitive(ttBool, true), i); + #endif } } } -void asCCompiler::PushVariableOnStack(asSExprContext *ctx, bool asReference) +void asCCompiler::PushVariableOnStack(asCExprContext *ctx, bool asReference) { // Put the result on the stack if( asReference ) @@ -13801,7 +14346,7 @@ void asCCompiler::PushVariableOnStack(asSExprContext *ctx, bool asReference) } } -void asCCompiler::CompileBooleanOperator(asCScriptNode *node, asSExprContext *lctx, asSExprContext *rctx, asSExprContext *ctx, eTokenType op) +void asCCompiler::CompileBooleanOperator(asCScriptNode *node, asCExprContext *lctx, asCExprContext *rctx, asCExprContext *ctx, eTokenType op) { // Both operands must be booleans asCDataType to; @@ -13813,9 +14358,9 @@ void asCCompiler::CompileBooleanOperator(asCScriptNode *node, asSExprContext *lc lctx->bc.GetVarsUsed(reservedVariables); // Allow value types to be converted to bool using 'bool opImplConv()' - if( lctx->type.dataType.GetObjectType() && (lctx->type.dataType.GetObjectType()->GetFlags() & asOBJ_VALUE) ) + if( lctx->type.dataType.GetTypeInfo() && (lctx->type.dataType.GetTypeInfo()->GetFlags() & asOBJ_VALUE) ) ImplicitConversion(lctx, to, node, asIC_IMPLICIT_CONV); - if( rctx->type.dataType.GetObjectType() && (rctx->type.dataType.GetObjectType()->GetFlags() & asOBJ_VALUE) ) + if( rctx->type.dataType.GetTypeInfo() && (rctx->type.dataType.GetTypeInfo()->GetFlags() & asOBJ_VALUE) ) ImplicitConversion(rctx, to, node, asIC_IMPLICIT_CONV); reservedVariables.SetLength(l); @@ -13875,25 +14420,25 @@ void asCCompiler::CompileBooleanOperator(asCScriptNode *node, asSExprContext *lc { // Make sure they are equal if not false #if AS_SIZEOF_BOOL == 1 - if( lctx->type.byteValue != 0 ) lctx->type.byteValue = VALUE_OF_BOOLEAN_TRUE; - if( rctx->type.byteValue != 0 ) rctx->type.byteValue = VALUE_OF_BOOLEAN_TRUE; + if( lctx->type.GetConstantB() != 0 ) lctx->type.SetConstantB(VALUE_OF_BOOLEAN_TRUE); + if( rctx->type.GetConstantB() != 0 ) rctx->type.SetConstantB(VALUE_OF_BOOLEAN_TRUE); asBYTE v = 0; - v = lctx->type.byteValue - rctx->type.byteValue; + v = lctx->type.GetConstantB() - rctx->type.GetConstantB(); if( v != 0 ) v = VALUE_OF_BOOLEAN_TRUE; else v = 0; ctx->type.isConstant = true; - ctx->type.byteValue = v; + ctx->type.SetConstantB(v); #else - if( lctx->type.dwordValue != 0 ) lctx->type.dwordValue = VALUE_OF_BOOLEAN_TRUE; - if( rctx->type.dwordValue != 0 ) rctx->type.dwordValue = VALUE_OF_BOOLEAN_TRUE; + if( lctx->type.GetConstantDW() != 0 ) lctx->type.SetConstantDW(VALUE_OF_BOOLEAN_TRUE); + if( rctx->type.GetConstantDW() != 0 ) rctx->type.SetConstantDW(VALUE_OF_BOOLEAN_TRUE); asDWORD v = 0; - v = lctx->type.intValue - rctx->type.intValue; + v = lctx->type.GetConstantDW() - rctx->type.GetConstantDW(); if( v != 0 ) v = VALUE_OF_BOOLEAN_TRUE; else v = 0; ctx->type.isConstant = true; - ctx->type.dwordValue = v; + ctx->type.SetConstantDW(v); #endif } } @@ -13946,29 +14491,29 @@ void asCCompiler::CompileBooleanOperator(asCScriptNode *node, asSExprContext *lc #if AS_SIZEOF_BOOL == 1 asBYTE v = 0; if( op == ttAnd ) - v = lctx->type.byteValue && rctx->type.byteValue; + v = lctx->type.GetConstantB() && rctx->type.GetConstantB(); else if( op == ttOr ) - v = lctx->type.byteValue || rctx->type.byteValue; + v = lctx->type.GetConstantB() || rctx->type.GetConstantB(); // Remember the result ctx->type.isConstant = true; - ctx->type.byteValue = v; + ctx->type.SetConstantB(v); #else asDWORD v = 0; if( op == ttAnd ) - v = lctx->type.dwordValue && rctx->type.dwordValue; + v = lctx->type.GetConstantDW() && rctx->type.GetConstantDW(); else if( op == ttOr ) - v = lctx->type.dwordValue || rctx->type.dwordValue; + v = lctx->type.GetConstantDW() || rctx->type.GetConstantDW(); // Remember the result ctx->type.isConstant = true; - ctx->type.dwordValue = v; + ctx->type.SetConstantDW(v); #endif } } } -void asCCompiler::CompileOperatorOnHandles(asCScriptNode *node, asSExprContext *lctx, asSExprContext *rctx, asSExprContext *ctx, eTokenType opToken) +void asCCompiler::CompileOperatorOnHandles(asCScriptNode *node, asCExprContext *lctx, asCExprContext *rctx, asCExprContext *ctx, eTokenType opToken) { // Process the property accessor as get ProcessPropertyGetAccessor(lctx, node); @@ -13992,25 +14537,25 @@ void asCCompiler::CompileOperatorOnHandles(asCScriptNode *node, asSExprContext * // Warn if not both operands are explicit handles or null handles if( (opToken == ttEqual || opToken == ttNotEqual) && - ((!(lctx->type.isExplicitHandle || lctx->type.IsNullConstant()) && !(lctx->type.dataType.GetObjectType() && (lctx->type.dataType.GetObjectType()->flags & asOBJ_IMPLICIT_HANDLE))) || - (!(rctx->type.isExplicitHandle || rctx->type.IsNullConstant()) && !(rctx->type.dataType.GetObjectType() && (rctx->type.dataType.GetObjectType()->flags & asOBJ_IMPLICIT_HANDLE)))) ) + ((!(lctx->type.isExplicitHandle || lctx->type.IsNullConstant()) && !(lctx->type.dataType.GetTypeInfo() && (lctx->type.dataType.GetTypeInfo()->flags & asOBJ_IMPLICIT_HANDLE))) || + (!(rctx->type.isExplicitHandle || rctx->type.IsNullConstant()) && !(rctx->type.dataType.GetTypeInfo() && (rctx->type.dataType.GetTypeInfo()->flags & asOBJ_IMPLICIT_HANDLE)))) ) { Warning(TXT_HANDLE_COMPARISON, node); } // If one of the operands is a value type used as handle, we should look for the opEquals method - if( ((lctx->type.dataType.GetObjectType() && (lctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE)) || - (rctx->type.dataType.GetObjectType() && (rctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE))) && + if( ((lctx->type.dataType.GetTypeInfo() && (lctx->type.dataType.GetTypeInfo()->flags & asOBJ_ASHANDLE)) || + (rctx->type.dataType.GetTypeInfo() && (rctx->type.dataType.GetTypeInfo()->flags & asOBJ_ASHANDLE))) && (opToken == ttEqual || opToken == ttIs || opToken == ttNotEqual || opToken == ttNotIs) ) { // TODO: Should evaluate which of the two have the best match. If both have equal match, the first version should be used // Find the matching opEquals method - int r = CompileOverloadedDualOperator2(node, "opEquals", lctx, rctx, ctx, true, asCDataType::CreatePrimitive(ttBool, false)); + int r = CompileOverloadedDualOperator2(node, "opEquals", lctx, rctx, true, ctx, true, asCDataType::CreatePrimitive(ttBool, false)); if( r == 0 ) { // Try again by switching the order of the operands - r = CompileOverloadedDualOperator2(node, "opEquals", rctx, lctx, ctx, true, asCDataType::CreatePrimitive(ttBool, false)); + r = CompileOverloadedDualOperator2(node, "opEquals", rctx, lctx, false, ctx, true, asCDataType::CreatePrimitive(ttBool, false)); } if( r == 1 ) @@ -14042,10 +14587,10 @@ void asCCompiler::CompileOperatorOnHandles(asCScriptNode *node, asSExprContext * else { // Find a common base type - asSExprContext tmp(engine); + asCExprContext tmp(engine); tmp.type = rctx->type; ImplicitConversion(&tmp, lctx->type.dataType, 0, asIC_IMPLICIT_CONV, false); - if( tmp.type.dataType.GetObjectType() == lctx->type.dataType.GetObjectType() ) + if( tmp.type.dataType.GetTypeInfo() == lctx->type.dataType.GetTypeInfo() ) to = lctx->type.dataType; else to = rctx->type.dataType; @@ -14068,7 +14613,11 @@ void asCCompiler::CompileOperatorOnHandles(asCScriptNode *node, asSExprContext * { // Compiler error, don't continue Error(TXT_OPERANDS_MUST_BE_HANDLES, node); +#if AS_SIZEOF_BOOL == 1 + ctx->type.SetConstantB(asCDataType::CreatePrimitive(ttBool, true), true); +#else ctx->type.SetConstantDW(asCDataType::CreatePrimitive(ttBool, true), true); +#endif return; } @@ -14103,7 +14652,7 @@ void asCCompiler::CompileOperatorOnHandles(asCScriptNode *node, asSExprContext * if( opToken == ttEqual || opToken == ttNotEqual || opToken == ttIs || opToken == ttNotIs ) { - // Make sure handles received as parameters by reference are copied to a local variable before the + // Make sure handles received as parameters by reference are copied to a local variable before the // asBC_CmpPtr, so we don't end up comparing the reference to the handle instead of the handle itself if( lctx->type.isVariable && !lctx->type.isTemporary && lctx->type.stackOffset <= 0 ) lctx->type.isVariable = false; @@ -14148,7 +14697,7 @@ void asCCompiler::CompileOperatorOnHandles(asCScriptNode *node, asSExprContext * } -void asCCompiler::PerformFunctionCall(int funcId, asSExprContext *ctx, bool isConstructor, asCArray *args, asCObjectType *objType, bool useVariable, int varOffset, int funcPtrVar) +void asCCompiler::PerformFunctionCall(int funcId, asCExprContext *ctx, bool isConstructor, asCArray *args, asCObjectType *objType, bool useVariable, int varOffset, int funcPtrVar) { asCScriptFunction *descr = builder->GetFunctionDescription(funcId); @@ -14161,14 +14710,14 @@ void asCCompiler::PerformFunctionCall(int funcId, asSExprContext *ctx, bool isCo } // Check if the function is private or protected - if( descr->isPrivate && descr->GetObjectType() != outFunc->GetObjectType() ) + if( descr->IsPrivate() && descr->GetObjectType() != outFunc->GetObjectType() ) { asCString msg; msg.Format(TXT_PRIVATE_METHOD_CALL_s, descr->GetDeclarationStr().AddressOf()); Error(msg, ctx->exprNode); } - else if( descr->isProtected && - !(descr->GetObjectType() == outFunc->GetObjectType() || + else if( descr->IsProtected() && + !(descr->GetObjectType() == outFunc->GetObjectType() || (outFunc->GetObjectType() && outFunc->GetObjectType()->DerivesFrom(descr->GetObjectType()))) ) { asCString msg; @@ -14182,25 +14731,24 @@ void asCCompiler::PerformFunctionCall(int funcId, asSExprContext *ctx, bool isCo // alive throughout the call by holding on to a reference in a local variable. This must // be done for any methods that return references, and any calls on script objects. // Application registered objects are assumed to know to keep themselves alive even - // if the method doesn't return a refernce. - if( descr->objectType && + // if the method doesn't return a reference. + if( !ctx->type.isHandleSafe && + descr->objectType && (ctx->type.dataType.IsObjectHandle() || ctx->type.dataType.SupportHandles()) && - (descr->returnType.IsReference() || (ctx->type.dataType.GetObjectType()->GetFlags() & asOBJ_SCRIPT_OBJECT)) && + (descr->returnType.IsReference() || (ctx->type.dataType.GetTypeInfo()->GetFlags() & asOBJ_SCRIPT_OBJECT)) && !(ctx->type.isVariable || ctx->type.isTemporary) && - !(ctx->type.dataType.GetObjectType()->GetFlags() & asOBJ_SCOPED) && - !(ctx->type.dataType.GetObjectType()->GetFlags() & asOBJ_ASHANDLE) ) + !(ctx->type.dataType.GetTypeInfo()->GetFlags() & asOBJ_SCOPED) && + !(ctx->type.dataType.GetTypeInfo()->GetFlags() & asOBJ_ASHANDLE) ) { - // TODO: runtime optimize: Avoid this for global variables, by storing a reference to the global variable once in a + // TODO: runtime optimize: Avoid this for global variables, by storing a reference to the global variable once in a // local variable and then refer to the same for each call. An alias for the global variable - // should be stored in the variable scope so that the compiler can find it. For loops and - // scopes that will always be executed, i.e. non-if scopes the alias should be stored in the + // should be stored in the variable scope so that the compiler can find it. For loops and + // scopes that will always be executed, i.e. non-if scopes the alias should be stored in the // higher scope to increase the probability of re-use. - // TODO: runtime optimize: This can be avoided for local variables (non-handles) as they have a well defined life time - int tempRef = AllocateVariable(ctx->type.dataType, true); ctx->bc.InstrSHORT(asBC_PSF, (short)tempRef); - ctx->bc.InstrPTR(asBC_REFCPY, ctx->type.dataType.GetObjectType()); + ctx->bc.InstrPTR(asBC_REFCPY, ctx->type.dataType.GetTypeInfo()); // Add the release of this reference as a deferred expression asSDeferredParam deferred; @@ -14302,11 +14850,11 @@ void asCCompiler::PerformFunctionCall(int funcId, asSExprContext *ctx, bool isCo else if( descr->funcType == asFUNC_SYSTEM ) { // Check if we can use the faster asBC_Thiscall1 instruction, i.e. one of - // type &obj::func(int) + // type &obj::func(int) // type &obj::func(uint) - if( descr->GetObjectType() && descr->returnType.IsReference() && - descr->parameterTypes.GetLength() == 1 && - (descr->parameterTypes[0].IsIntegerType() || descr->parameterTypes[0].IsUnsignedType()) && + if( descr->GetObjectType() && descr->returnType.IsReference() && + descr->parameterTypes.GetLength() == 1 && + (descr->parameterTypes[0].IsIntegerType() || descr->parameterTypes[0].IsUnsignedType()) && descr->parameterTypes[0].GetSizeInMemoryBytes() == 4 && !descr->parameterTypes[0].IsReference() ) ctx->bc.Call(asBC_Thiscall1, descr->id, argSize); @@ -14317,11 +14865,11 @@ void asCCompiler::PerformFunctionCall(int funcId, asSExprContext *ctx, bool isCo ctx->bc.CallPtr(asBC_CallPtr, funcPtrVar, argSize); } - if( descr->returnType.IsObject() && !descr->returnType.IsReference() ) + if( (descr->returnType.IsObject() || descr->returnType.IsFuncdef()) && !descr->returnType.IsReference() ) { int returnOffset = 0; - asCTypeInfo tmpExpr = ctx->type; + asCExprValue tmpExpr = ctx->type; if( descr->DoesReturnOnStack() ) { @@ -14413,7 +14961,7 @@ void asCCompiler::PerformFunctionCall(int funcId, asSExprContext *ctx, bool isCo { asASSERT(useVariable == false); - asCTypeInfo tmpExpr = ctx->type; + asCExprValue tmpExpr = ctx->type; if( descr->returnType.GetSizeInMemoryBytes() ) { @@ -14422,7 +14970,7 @@ void asCCompiler::PerformFunctionCall(int funcId, asSExprContext *ctx, bool isCo int l = int(reservedVariables.GetLength()); for( asUINT n = 0; args && n < args->GetLength(); n++ ) { - asSExprContext *expr = (*args)[n]->origExpr; + asCExprContext *expr = (*args)[n]->origExpr; if( expr ) expr->bc.GetVarsUsed(reservedVariables); } @@ -14453,7 +15001,7 @@ void asCCompiler::PerformFunctionCall(int funcId, asSExprContext *ctx, bool isCo } // This only merges the bytecode, but doesn't modify the type of the final context -void asCCompiler::MergeExprBytecode(asSExprContext *before, asSExprContext *after) +void asCCompiler::MergeExprBytecode(asCExprContext *before, asCExprContext *after) { before->bc.AddCode(&after->bc); @@ -14467,7 +15015,7 @@ void asCCompiler::MergeExprBytecode(asSExprContext *before, asSExprContext *afte } // This merges both bytecode and the type of the final context -void asCCompiler::MergeExprBytecodeAndType(asSExprContext *before, asSExprContext *after) +void asCCompiler::MergeExprBytecodeAndType(asCExprContext *before, asCExprContext *after) { MergeExprBytecode(before, after); @@ -14488,7 +15036,7 @@ void asCCompiler::FilterConst(asCArray &funcs, bool removeConst) for( n = 0; n < funcs.GetLength(); n++ ) { desc = builder->GetFunctionDescription(funcs[n]); - if( desc->isReadOnly != removeConst ) + if( desc->IsReadOnly() != removeConst ) { foundNonConst = true; break; @@ -14501,7 +15049,7 @@ void asCCompiler::FilterConst(asCArray &funcs, bool removeConst) for( n = 0; n < funcs.GetLength(); n++ ) { desc = builder->GetFunctionDescription(funcs[n]); - if( desc->isReadOnly == removeConst ) + if( desc->IsReadOnly() == removeConst ) { if( n == funcs.GetLength() - 1 ) funcs.PopLast(); @@ -14514,6 +15062,389 @@ void asCCompiler::FilterConst(asCArray &funcs, bool removeConst) } } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +asCExprValue::asCExprValue() +{ + isTemporary = false; + stackOffset = 0; + isConstant = false; + isVariable = false; + isExplicitHandle = false; + qwordValue = 0; + isLValue = false; + isRefToLocal = false; + isHandleSafe = false; +} + +void asCExprValue::Set(const asCDataType &dt) +{ + dataType = dt; + + isTemporary = false; + stackOffset = 0; + isConstant = false; + isVariable = false; + isExplicitHandle = false; + qwordValue = 0; + isLValue = false; + isRefToLocal = false; + isHandleSafe = false; +} + +void asCExprValue::SetVariable(const asCDataType &in_dt, int in_stackOffset, bool in_isTemporary) +{ + Set(in_dt); + + this->isVariable = true; + this->isTemporary = in_isTemporary; + this->stackOffset = (short)in_stackOffset; +} + +void asCExprValue::SetConstantQW(const asCDataType &dt, asQWORD value) +{ + Set(dt); + + isConstant = true; + SetConstantQW(value); +} + +void asCExprValue::SetConstantDW(const asCDataType &dt, asDWORD value) +{ + Set(dt); + + isConstant = true; + SetConstantDW(value); +} + +void asCExprValue::SetConstantB(const asCDataType &dt, asBYTE value) +{ + Set(dt); + + isConstant = true; + SetConstantB(value); +} + +void asCExprValue::SetConstantW(const asCDataType &dt, asWORD value) +{ + Set(dt); + + isConstant = true; + SetConstantW(value); +} + +void asCExprValue::SetConstantF(const asCDataType &dt, float value) +{ + Set(dt); + + isConstant = true; + SetConstantF(value); +} + +void asCExprValue::SetConstantD(const asCDataType &dt, double value) +{ + Set(dt); + + isConstant = true; + SetConstantD(value); +} + +void asCExprValue::SetConstantQW(asQWORD value) +{ + asASSERT(dataType.GetSizeInMemoryBytes() == 8); + qwordValue = value; +} + +void asCExprValue::SetConstantDW(asDWORD value) +{ + asASSERT(dataType.GetSizeInMemoryBytes() == 4); + dwordValue = value; +} + +void asCExprValue::SetConstantW(asWORD value) +{ + asASSERT(dataType.GetSizeInMemoryBytes() == 2); + wordValue = value; +} + +void asCExprValue::SetConstantB(asBYTE value) +{ + asASSERT(dataType.GetSizeInMemoryBytes() == 1); + byteValue = value; +} + +void asCExprValue::SetConstantF(float value) +{ + asASSERT(dataType.GetSizeInMemoryBytes() == 4); + floatValue = value; +} + +void asCExprValue::SetConstantD(double value) +{ + asASSERT(dataType.GetSizeInMemoryBytes() == 8); + doubleValue = value; +} + +asQWORD asCExprValue::GetConstantQW() +{ + asASSERT(dataType.GetSizeInMemoryBytes() == 8); + return qwordValue; +} + +asDWORD asCExprValue::GetConstantDW() +{ + asASSERT(dataType.GetSizeInMemoryBytes() == 4); + return dwordValue; +} + +asWORD asCExprValue::GetConstantW() +{ + asASSERT(dataType.GetSizeInMemoryBytes() == 2); + return wordValue; +} + +asBYTE asCExprValue::GetConstantB() +{ + asASSERT(dataType.GetSizeInMemoryBytes() == 1); + return byteValue; +} + +float asCExprValue::GetConstantF() +{ + asASSERT(dataType.GetSizeInMemoryBytes() == 4); + return floatValue; +} + +double asCExprValue::GetConstantD() +{ + asASSERT(dataType.GetSizeInMemoryBytes() == 8); + return doubleValue; +} + +void asCExprValue::SetConstantData(const asCDataType &dt, asQWORD qw) +{ + Set(dt); + + isConstant = true; + + // This code is necessary to guarantee that the code + // works on both big endian and little endian CPUs. + if (dataType.GetSizeInMemoryBytes() == 1) + byteValue = (asBYTE)qw; + if (dataType.GetSizeInMemoryBytes() == 2) + wordValue = (asWORD)qw; + if (dataType.GetSizeInMemoryBytes() == 4) + dwordValue = (asDWORD)qw; + else + qwordValue = qw; +} + +asQWORD asCExprValue::GetConstantData() +{ + asQWORD qw = 0; + // This code is necessary to guarantee that the code + // works on both big endian and little endian CPUs. + if (dataType.GetSizeInMemoryBytes() == 1) + qw = byteValue; + if (dataType.GetSizeInMemoryBytes() == 2) + qw = wordValue; + if (dataType.GetSizeInMemoryBytes() == 4) + qw = dwordValue; + else + qw = qwordValue; + return qw; +} + +void asCExprValue::SetUndefinedFuncHandle(asCScriptEngine *engine) +{ + // This is used for when the expression evaluates to a + // function, but it is not yet known exactly which. The + // owner expression will hold the name of the function + // to determine the exact function when the signature is + // known. + Set(asCDataType::CreateObjectHandle(&engine->functionBehaviours, true)); + isConstant = true; + isExplicitHandle = false; + qwordValue = 1; // Set to a different value than 0 to differentiate from null constant + isLValue = false; +} + +bool asCExprValue::IsUndefinedFuncHandle() const +{ + if (isConstant == false) return false; + if (qwordValue == 0) return false; + if (isLValue) return false; + if (dataType.GetTypeInfo() == 0) return false; + if (dataType.GetTypeInfo()->name != "$func") return false; + if (dataType.IsFuncdef()) return false; + + return true; +} + +void asCExprValue::SetNullConstant() +{ + Set(asCDataType::CreateNullHandle()); + isConstant = true; + isExplicitHandle = false; + qwordValue = 0; + isLValue = false; +} + +bool asCExprValue::IsNullConstant() const +{ + // We can't check the actual object type, because the null constant may have been cast to another type + if (isConstant && dataType.IsObjectHandle() && qwordValue == 0) + return true; + + return false; +} + +void asCExprValue::SetVoid() +{ + Set(asCDataType::CreatePrimitive(ttVoid, false)); + isLValue = false; + isConstant = true; +} + +bool asCExprValue::IsVoid() const +{ + if (dataType.GetTokenType() == ttVoid) + return true; + + return false; +} + +void asCExprValue::SetDummy() +{ + SetConstantDW(asCDataType::CreatePrimitive(ttInt, true), 0); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +asCExprContext::asCExprContext(asCScriptEngine *engine) : bc(engine) +{ + property_arg = 0; + + Clear(); +} + +asCExprContext::~asCExprContext() +{ + if (property_arg) + asDELETE(property_arg, asCExprContext); +} + +void asCExprContext::Clear() +{ + bc.ClearAll(); + type.Set(asCDataType()); + deferredParams.SetLength(0); + if (property_arg) + asDELETE(property_arg, asCExprContext); + property_arg = 0; + exprNode = 0; + origExpr = 0; + property_get = 0; + property_set = 0; + property_const = false; + property_handle = false; + property_ref = false; + methodName = ""; + enumValue = ""; + isVoidExpression = false; + isCleanArg = false; + isAnonymousInitList = false; +} + +bool asCExprContext::IsClassMethod() const +{ + if (type.dataType.GetTypeInfo() == 0) return false; + if (methodName == "") return false; + if (type.dataType.GetTypeInfo() == &type.dataType.GetTypeInfo()->engine->functionBehaviours) return false; + if (isAnonymousInitList) return false; + return true; +} + +bool asCExprContext::IsGlobalFunc() const +{ + if (type.dataType.GetTypeInfo() == 0) return false; + if (methodName == "") return false; + if (type.dataType.GetTypeInfo() != &type.dataType.GetTypeInfo()->engine->functionBehaviours) return false; + if (isAnonymousInitList) return false; + return true; +} + +void asCExprContext::SetLambda(asCScriptNode *funcDecl) +{ + asASSERT(funcDecl && funcDecl->nodeType == snFunction); + asASSERT(bc.GetLastInstr() == -1); + + Clear(); + type.SetUndefinedFuncHandle(bc.GetEngine()); + exprNode = funcDecl; +} + +bool asCExprContext::IsLambda() const +{ + if (type.IsUndefinedFuncHandle() && exprNode && exprNode->nodeType == snFunction) + return true; + + return false; +} + +void asCExprContext::SetVoidExpression() +{ + Clear(); + type.SetVoid(); + isVoidExpression = true; +} + +bool asCExprContext::IsVoidExpression() const +{ + if (isVoidExpression && type.IsVoid() && exprNode == 0) + return true; + + return false; +} + +void asCExprContext::SetAnonymousInitList(asCScriptNode *initList) +{ + Clear(); + exprNode = initList; + isAnonymousInitList = true; +} + +bool asCExprContext::IsAnonymousInitList() const +{ + if (isAnonymousInitList && exprNode && exprNode->nodeType == snInitList) + return true; + + return false; +} + +void asCExprContext::Merge(asCExprContext *after) +{ + type = after->type; + property_get = after->property_get; + property_set = after->property_set; + property_const = after->property_const; + property_handle = after->property_handle; + property_ref = after->property_ref; + property_arg = after->property_arg; + exprNode = after->exprNode; + methodName = after->methodName; + enumValue = after->enumValue; + isVoidExpression = after->isVoidExpression; + isCleanArg = after->isCleanArg; + isAnonymousInitList = after->isAnonymousInitList; + + after->property_arg = 0; + + // Do not copy the origExpr member +} + + + END_AS_NAMESPACE #endif // AS_NO_COMPILER diff --git a/lib/angelscript/source/as_compiler.h b/lib/angelscript/source/as_compiler.h index f9de7e475..61e9f3490 100644 --- a/lib/angelscript/source/as_compiler.h +++ b/lib/angelscript/source/as_compiler.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -50,123 +50,110 @@ #include "as_bytecode.h" #include "as_array.h" #include "as_datatype.h" -#include "as_typeinfo.h" BEGIN_AS_NAMESPACE -struct asSExprContext; +// This class represents the value of an expression as evaluated by the compiler. +// It holds information such as the type of the value, stack offset for a local +// variable, value of constants, whether the value can be modified (i.e. lvalue), etc. +struct asCExprValue +{ + asCExprValue(); + void Set(const asCDataType &dataType); + void SetVariable(const asCDataType &dataType, int stackOffset, bool isTemporary); + void SetConstantB(const asCDataType &dataType, asBYTE value); + void SetConstantQW(const asCDataType &dataType, asQWORD value); + void SetConstantDW(const asCDataType &dataType, asDWORD value); + void SetConstantW(const asCDataType &dataType, asWORD value); + void SetConstantF(const asCDataType &dataType, float value); + void SetConstantD(const asCDataType &dataType, double value); + void SetConstantB(asBYTE value); + void SetConstantW(asWORD value); + void SetConstantQW(asQWORD value); + void SetConstantDW(asDWORD value); + void SetConstantF(float value); + void SetConstantD(double value); + asBYTE GetConstantB(); + asWORD GetConstantW(); + asQWORD GetConstantQW(); + asDWORD GetConstantDW(); + float GetConstantF(); + double GetConstantD(); + + void SetConstantData(const asCDataType &dataType, asQWORD value); + asQWORD GetConstantData(); + + void SetNullConstant(); + void SetUndefinedFuncHandle(asCScriptEngine *engine); + void SetVoid(); + void SetDummy(); + + bool IsUndefinedFuncHandle() const; + bool IsNullConstant() const; + bool IsVoid() const; + + asCDataType dataType; + bool isLValue : 1; // Can this value be updated in assignment, or increment operators, etc + bool isTemporary : 1; + bool isConstant : 1; + bool isVariable : 1; + bool isExplicitHandle : 1; + bool isRefToLocal : 1; // The reference may be to a local variable + bool isHandleSafe : 1; // the life-time of the handle is guaranteed for the duration of the access + short dummy : 9; + short stackOffset; + +private: + // These values must not be accessed directly in order to avoid problems with endianess. + // Use the appropriate accessor methods instead + union + { + asQWORD qwordValue; + double doubleValue; + asDWORD dwordValue; + float floatValue; + asWORD wordValue; + asBYTE byteValue; + }; +}; + +struct asCExprContext; + +// This class holds information for arguments that needs to be +// cleaned up after the result of a function has been evaluated. struct asSDeferredParam { asSDeferredParam() {argNode = 0; origExpr = 0;} asCScriptNode *argNode; - asCTypeInfo argType; + asCExprValue argType; int argInOutFlags; - asSExprContext *origExpr; + asCExprContext *origExpr; }; -// TODO: refactor: asSExprContext should have indicators to inform where the value is, +// TODO: refactor: asCExprContext should have indicators to inform where the value is, // i.e. if the reference to an object is pushed on the stack or not, etc -struct asSExprContext +// This class holds information about an expression that is being evaluated, e.g. +// the current bytecode, ambiguous symbol names, property accessors, etc. +struct asCExprContext { - asSExprContext(asCScriptEngine *engine) : bc(engine) - { - property_arg = 0; - - Clear(); - } - ~asSExprContext() - { - if( property_arg ) - asDELETE(property_arg, asSExprContext); - } - void Clear() - { - bc.ClearAll(); - type.Set(asCDataType()); - deferredParams.SetLength(0); - if( property_arg ) - asDELETE(property_arg, asSExprContext); - property_arg = 0; - exprNode = 0; - origExpr = 0; - property_get = 0; - property_set = 0; - property_const = false; - property_handle = false; - property_ref = false; - methodName = ""; - enumValue = ""; - isVoidExpression = false; - isCleanArg = false; - } - bool IsClassMethod() const - { - if( type.dataType.GetObjectType() == 0 ) return false; - if( methodName == "" ) return false; - if( type.dataType.GetObjectType() == &type.dataType.GetObjectType()->engine->functionBehaviours ) return false; - return true; - } - bool IsGlobalFunc() const - { - if( type.dataType.GetObjectType() == 0 ) return false; - if( methodName == "" ) return false; - if( type.dataType.GetObjectType() != &type.dataType.GetObjectType()->engine->functionBehaviours ) return false; - return true; - } - void SetLambda(asCScriptNode *funcDecl) - { - asASSERT( funcDecl && funcDecl->nodeType == snFunction ); - asASSERT( bc.GetLastInstr() == -1 ); - - Clear(); - type.SetUndefinedFuncHandle(bc.GetEngine()); - exprNode = funcDecl; - } - bool IsLambda() const - { - if( type.IsUndefinedFuncHandle() && exprNode && exprNode->nodeType == snFunction ) - return true; - - return false; - } - void SetVoidExpression() - { - Clear(); - type.SetVoid(); - isVoidExpression = true; - } - bool IsVoidExpression() const - { - if( isVoidExpression && type.IsVoid() && exprNode == 0 ) - return true; - - return false; - } - void Merge(asSExprContext *after) - { - type = after->type; - property_get = after->property_get; - property_set = after->property_set; - property_const = after->property_const; - property_handle = after->property_handle; - property_ref = after->property_ref; - property_arg = after->property_arg; - exprNode = after->exprNode; - methodName = after->methodName; - enumValue = after->enumValue; - isVoidExpression = after->isVoidExpression; - isCleanArg = after->isCleanArg; - - after->property_arg = 0; - - // Do not copy the origExpr member - } + asCExprContext(asCScriptEngine *engine); + ~asCExprContext(); + void Clear(); + bool IsClassMethod() const; + bool IsGlobalFunc() const; + void SetLambda(asCScriptNode *funcDecl); + bool IsLambda() const; + void SetVoidExpression(); + bool IsVoidExpression() const; + void Merge(asCExprContext *after); + void SetAnonymousInitList(asCScriptNode *initList); + bool IsAnonymousInitList() const; asCByteCode bc; - asCTypeInfo type; + asCExprValue type; int property_get; int property_set; bool property_const; // If the object that is being accessed through property accessor is read-only @@ -174,19 +161,20 @@ struct asSExprContext bool property_ref; // If the property accessor is called on a reference bool isVoidExpression; // Set to true if the expression is an explicit 'void', e.g. used to ignore out parameters in func calls bool isCleanArg; // Set to true if the expression has only been initialized with default constructor - asSExprContext *property_arg; + asCExprContext *property_arg; asCArray deferredParams; asCScriptNode *exprNode; - asSExprContext *origExpr; + asCExprContext *origExpr; // TODO: cleanup: use ambiguousName and an enum to say if it is a method, global func, or enum value asCString methodName; asCString enumValue; + bool isAnonymousInitList; // Set to true if the expression is an init list for which the type has not yet been determined }; struct asSOverloadCandidate { asSOverloadCandidate() : funcId(0), cost(0) {} - asSOverloadCandidate(int _id, asUINT _cost ) : funcId(_id), cost(_cost) {} + asSOverloadCandidate(int _id, asUINT _cost) : funcId(_id), cost(_cost) {} int funcId; asUINT cost; }; @@ -194,7 +182,7 @@ struct asSOverloadCandidate struct asSNamedArgument { asCString name; - asSExprContext *ctx; + asCExprContext *ctx; asUINT match; }; @@ -209,13 +197,15 @@ enum EConvCost { asCC_NO_CONV = 0, asCC_CONST_CONV = 1, - asCC_PRIMITIVE_SIZE_CONV = 2, - asCC_SIGNED_CONV = 3, - asCC_INT_FLOAT_CONV = 4, - asCC_REF_CONV = 5, - asCC_OBJ_TO_PRIMITIVE_CONV = 6, - asCC_TO_OBJECT_CONV = 7, - asCC_VARIABLE_CONV = 8 + asCC_ENUM_SAME_SIZE_CONV = 2, + asCC_ENUM_DIFF_SIZE_CONV = 3, + asCC_PRIMITIVE_SIZE_CONV = 4, + asCC_SIGNED_CONV = 5, + asCC_INT_FLOAT_CONV = 6, + asCC_REF_CONV = 7, + asCC_OBJ_TO_PRIMITIVE_CONV = 8, + asCC_TO_OBJECT_CONV = 9, + asCC_VARIABLE_CONV = 10 }; class asCCompiler @@ -250,93 +240,94 @@ protected: void CompileExpressionStatement(asCScriptNode *node, asCByteCode *bc); // Expressions - int CompileAssignment(asCScriptNode *expr, asSExprContext *out); - int CompileCondition(asCScriptNode *expr, asSExprContext *out); - int CompileExpression(asCScriptNode *expr, asSExprContext *out); - int CompilePostFixExpression(asCArray *postfix, asSExprContext *out); - int CompileExpressionTerm(asCScriptNode *node, asSExprContext *out); - int CompileExpressionPreOp(asCScriptNode *node, asSExprContext *out); - int CompileExpressionPostOp(asCScriptNode *node, asSExprContext *out); - int CompileExpressionValue(asCScriptNode *node, asSExprContext *out); - int CompileFunctionCall(asCScriptNode *node, asSExprContext *out, asCObjectType *objectType, bool objIsConst, const asCString &scope = ""); - int CompileConstructCall(asCScriptNode *node, asSExprContext *out); - int CompileConversion(asCScriptNode *node, asSExprContext *out); - int CompileOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken); - void CompileOperatorOnHandles(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken); - void CompileMathOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken); - void CompileBitwiseOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken); - void CompileComparisonOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken); - void CompileBooleanOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken); - bool CompileOverloadedDualOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, bool isHandle = false, eTokenType opToken = ttUnrecognizedToken); - int CompileOverloadedDualOperator2(asCScriptNode *node, const char *methodName, asSExprContext *l, asSExprContext *r, asSExprContext *out, bool specificReturn = false, const asCDataType &returnType = asCDataType::CreatePrimitive(ttVoid, false)); + int CompileAssignment(asCScriptNode *expr, asCExprContext *out); + int CompileCondition(asCScriptNode *expr, asCExprContext *out); + int CompileExpression(asCScriptNode *expr, asCExprContext *out); + int CompilePostFixExpression(asCArray *postfix, asCExprContext *out); + int CompileExpressionTerm(asCScriptNode *node, asCExprContext *out); + int CompileExpressionPreOp(asCScriptNode *node, asCExprContext *out); + int CompileExpressionPostOp(asCScriptNode *node, asCExprContext *out); + int CompileExpressionValue(asCScriptNode *node, asCExprContext *out); + int CompileFunctionCall(asCScriptNode *node, asCExprContext *out, asCObjectType *objectType, bool objIsConst, const asCString &scope = ""); + int CompileConstructCall(asCScriptNode *node, asCExprContext *out); + int CompileConversion(asCScriptNode *node, asCExprContext *out); + int CompileOperator(asCScriptNode *node, asCExprContext *l, asCExprContext *r, asCExprContext *out, eTokenType opToken = ttUnrecognizedToken, bool leftToRight = true); + void CompileOperatorOnHandles(asCScriptNode *node, asCExprContext *l, asCExprContext *r, asCExprContext *out, eTokenType opToken = ttUnrecognizedToken); + void CompileMathOperator(asCScriptNode *node, asCExprContext *l, asCExprContext *r, asCExprContext *out, eTokenType opToken = ttUnrecognizedToken); + void CompileBitwiseOperator(asCScriptNode *node, asCExprContext *l, asCExprContext *r, asCExprContext *out, eTokenType opToken = ttUnrecognizedToken); + void CompileComparisonOperator(asCScriptNode *node, asCExprContext *l, asCExprContext *r, asCExprContext *out, eTokenType opToken = ttUnrecognizedToken); + void CompileBooleanOperator(asCScriptNode *node, asCExprContext *l, asCExprContext *r, asCExprContext *out, eTokenType opToken = ttUnrecognizedToken); + bool CompileOverloadedDualOperator(asCScriptNode *node, asCExprContext *l, asCExprContext *r, bool leftToRight, asCExprContext *out, bool isHandle = false, eTokenType opToken = ttUnrecognizedToken); + int CompileOverloadedDualOperator2(asCScriptNode *node, const char *methodName, asCExprContext *l, asCExprContext *r, bool leftToRight, asCExprContext *out, bool specificReturn = false, const asCDataType &returnType = asCDataType::CreatePrimitive(ttVoid, false)); - void CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByteCode *bc, int isVarGlobOrMem); + void CompileInitList(asCExprValue *var, asCScriptNode *node, asCByteCode *bc, int isVarGlobOrMem); int CompileInitListElement(asSListPatternNode *&patternNode, asCScriptNode *&valueNode, int bufferTypeId, short bufferVar, asUINT &bufferSize, asCByteCode &byteCode, int &elementsInSubList); + int CompilerAnonymousInitList(asCScriptNode *listNode, asCExprContext *ctx, const asCDataType &dt); int CallDefaultConstructor(const asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asCScriptNode *node, int isVarGlobOrMem = 0, bool derefDest = false); - int CallCopyConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asSExprContext *arg, asCScriptNode *node, bool isGlobalVar = false, bool derefDestination = false); + int CallCopyConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asCExprContext *arg, asCScriptNode *node, bool isGlobalVar = false, bool derefDestination = false); void CallDestructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc); - int CompileArgumentList(asCScriptNode *node, asCArray &args, asCArray &namedArgs); - int CompileDefaultAndNamedArgs(asCScriptNode *node, asCArray &args, int funcId, asCObjectType *type, asCArray *namedArgs = 0); - asUINT MatchFunctions(asCArray &funcs, asCArray &args, asCScriptNode *node, const char *name, asCArray *namedArgs = NULL, asCObjectType *objectType = NULL, bool isConstMethod = false, bool silent = false, bool allowObjectConstruct = true, const asCString &scope = ""); - int CompileVariableAccess(const asCString &name, const asCString &scope, asSExprContext *ctx, asCScriptNode *errNode, bool isOptional = false, bool noFunction = false, bool noGlobal = false, asCObjectType *objType = 0); + int CompileArgumentList(asCScriptNode *node, asCArray &args, asCArray &namedArgs); + int CompileDefaultAndNamedArgs(asCScriptNode *node, asCArray &args, int funcId, asCObjectType *type, asCArray *namedArgs = 0); + asUINT MatchFunctions(asCArray &funcs, asCArray &args, asCScriptNode *node, const char *name, asCArray *namedArgs = NULL, asCObjectType *objectType = NULL, bool isConstMethod = false, bool silent = false, bool allowObjectConstruct = true, const asCString &scope = ""); + int CompileVariableAccess(const asCString &name, const asCString &scope, asCExprContext *ctx, asCScriptNode *errNode, bool isOptional = false, bool noFunction = false, bool noGlobal = false, asCObjectType *objType = 0); void CompileMemberInitialization(asCByteCode *bc, bool onlyDefaults); - bool CompileAutoType(asCDataType &autoType, asSExprContext &compiledCtx, asCScriptNode *exprNode, asCScriptNode *errNode); - bool CompileInitialization(asCScriptNode *node, asCByteCode *bc, asCDataType &type, asCScriptNode *errNode, int offset, asQWORD *constantValue, int isVarGlobOrMem, asSExprContext *preCompiled = 0); - void CompileInitAsCopy(asCDataType &type, int offset, asCByteCode *bc, asSExprContext *arg, asCScriptNode *node, bool derefDestination); + bool CompileAutoType(asCDataType &autoType, asCExprContext &compiledCtx, asCScriptNode *exprNode, asCScriptNode *errNode); + bool CompileInitialization(asCScriptNode *node, asCByteCode *bc, const asCDataType &type, asCScriptNode *errNode, int offset, asQWORD *constantValue, int isVarGlobOrMem, asCExprContext *preCompiled = 0); + void CompileInitAsCopy(asCDataType &type, int offset, asCByteCode *bc, asCExprContext *arg, asCScriptNode *node, bool derefDestination); // Helper functions void ConvertToPostFix(asCScriptNode *expr, asCArray &postfix); - void ProcessPropertyGetAccessor(asSExprContext *ctx, asCScriptNode *node); - int ProcessPropertySetAccessor(asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node); - int ProcessPropertyGetSetAccessor(asSExprContext *ctx, asSExprContext *lctx, asSExprContext *rctx, eTokenType op, asCScriptNode *errNode); - int FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asCScriptNode *node, asSNameSpace *ns, bool isThisAccess = false); - int FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node, asSNameSpace *ns, bool isThisAccess = false); - void PrepareTemporaryObject(asCScriptNode *node, asSExprContext *ctx, bool forceOnHeap = false); - void PrepareOperand(asSExprContext *ctx, asCScriptNode *node); - void PrepareForAssignment(asCDataType *lvalue, asSExprContext *rvalue, asCScriptNode *node, bool toTemporary, asSExprContext *lvalueExpr = 0); - int PerformAssignment(asCTypeInfo *lvalue, asCTypeInfo *rvalue, asCByteCode *bc, asCScriptNode *node); - bool IsVariableInitialized(asCTypeInfo *type, asCScriptNode *node); - void Dereference(asSExprContext *ctx, bool generateCode); - bool CompileRefCast(asSExprContext *ctx, const asCDataType &to, bool isExplicit, asCScriptNode *node, bool generateCode = true); - asUINT MatchArgument(asCArray &funcs, asCArray &matches, const asSExprContext *argExpr, int paramNum, bool allowObjectConstruct = true); - int MatchArgument(asCScriptFunction *desc, const asSExprContext *argExpr, int paramNum, bool allowObjectConstruct = true); - void PerformFunctionCall(int funcId, asSExprContext *out, bool isConstructor = false, asCArray *args = 0, asCObjectType *objTypeForConstruct = 0, bool useVariable = false, int varOffset = 0, int funcPtrVar = 0); - void MoveArgsToStack(int funcId, asCByteCode *bc, asCArray &args, bool addOneToOffset); - void MakeFunctionCall(asSExprContext *ctx, int funcId, asCObjectType *objectType, asCArray &args, asCScriptNode *node, bool useVariable = false, int stackOffset = 0, int funcPtrVar = 0); - void PrepareFunctionCall(int funcId, asCByteCode *bc, asCArray &args); - void AfterFunctionCall(int funcId, asCArray &args, asSExprContext *ctx, bool deferAll); - void ProcessDeferredParams(asSExprContext *ctx); - int PrepareArgument(asCDataType *paramType, asSExprContext *ctx, asCScriptNode *node, bool isFunction = false, int refType = 0, bool isMakingCopy = false); - void PrepareArgument2(asSExprContext *ctx, asSExprContext *arg, asCDataType *paramType, bool isFunction = false, int refType = 0, bool isMakingCopy = false); - bool IsLValue(asCTypeInfo &type); - int DoAssignment(asSExprContext *out, asSExprContext *lctx, asSExprContext *rctx, asCScriptNode *lexpr, asCScriptNode *rexpr, eTokenType op, asCScriptNode *opNode); - void MergeExprBytecode(asSExprContext *before, asSExprContext *after); - void MergeExprBytecodeAndType(asSExprContext *before, asSExprContext *after); + void ProcessPropertyGetAccessor(asCExprContext *ctx, asCScriptNode *node); + int ProcessPropertySetAccessor(asCExprContext *ctx, asCExprContext *arg, asCScriptNode *node); + int ProcessPropertyGetSetAccessor(asCExprContext *ctx, asCExprContext *lctx, asCExprContext *rctx, eTokenType op, asCScriptNode *errNode); + int FindPropertyAccessor(const asCString &name, asCExprContext *ctx, asCScriptNode *node, asSNameSpace *ns, bool isThisAccess = false); + int FindPropertyAccessor(const asCString &name, asCExprContext *ctx, asCExprContext *arg, asCScriptNode *node, asSNameSpace *ns, bool isThisAccess = false); + void PrepareTemporaryVariable(asCScriptNode *node, asCExprContext *ctx, bool forceOnHeap = false); + void PrepareOperand(asCExprContext *ctx, asCScriptNode *node); + void PrepareForAssignment(asCDataType *lvalue, asCExprContext *rvalue, asCScriptNode *node, bool toTemporary, asCExprContext *lvalueExpr = 0); + int PerformAssignment(asCExprValue *lvalue, asCExprValue *rvalue, asCByteCode *bc, asCScriptNode *node); + bool IsVariableInitialized(asCExprValue *type, asCScriptNode *node); + void Dereference(asCExprContext *ctx, bool generateCode); + bool CompileRefCast(asCExprContext *ctx, const asCDataType &to, bool isExplicit, asCScriptNode *node, bool generateCode = true); + asUINT MatchArgument(asCArray &funcs, asCArray &matches, const asCExprContext *argExpr, int paramNum, bool allowObjectConstruct = true); + int MatchArgument(asCScriptFunction *desc, const asCExprContext *argExpr, int paramNum, bool allowObjectConstruct = true); + void PerformFunctionCall(int funcId, asCExprContext *out, bool isConstructor = false, asCArray *args = 0, asCObjectType *objTypeForConstruct = 0, bool useVariable = false, int varOffset = 0, int funcPtrVar = 0); + void MoveArgsToStack(int funcId, asCByteCode *bc, asCArray &args, bool addOneToOffset); + void MakeFunctionCall(asCExprContext *ctx, int funcId, asCObjectType *objectType, asCArray &args, asCScriptNode *node, bool useVariable = false, int stackOffset = 0, int funcPtrVar = 0); + void PrepareFunctionCall(int funcId, asCByteCode *bc, asCArray &args); + void AfterFunctionCall(int funcId, asCArray &args, asCExprContext *ctx, bool deferAll); + void ProcessDeferredParams(asCExprContext *ctx); + int PrepareArgument(asCDataType *paramType, asCExprContext *ctx, asCScriptNode *node, bool isFunction = false, int refType = 0, bool isMakingCopy = false); + void PrepareArgument2(asCExprContext *ctx, asCExprContext *arg, asCDataType *paramType, bool isFunction = false, int refType = 0, bool isMakingCopy = false); + bool IsLValue(asCExprValue &type); + int DoAssignment(asCExprContext *out, asCExprContext *lctx, asCExprContext *rctx, asCScriptNode *lexpr, asCScriptNode *rexpr, eTokenType op, asCScriptNode *opNode); + void MergeExprBytecode(asCExprContext *before, asCExprContext *after); + void MergeExprBytecodeAndType(asCExprContext *before, asCExprContext *after); void FilterConst(asCArray &funcs, bool removeConst = true); - void ConvertToVariable(asSExprContext *ctx); - void ConvertToVariableNotIn(asSExprContext *ctx, asSExprContext *exclude); - void ConvertToTempVariable(asSExprContext *ctx); - void ConvertToTempVariableNotIn(asSExprContext *ctx, asSExprContext *exclude); - void ConvertToReference(asSExprContext *ctx); - void PushVariableOnStack(asSExprContext *ctx, bool asReference); + void ConvertToVariable(asCExprContext *ctx); + void ConvertToVariableNotIn(asCExprContext *ctx, asCExprContext *exclude); + void ConvertToTempVariable(asCExprContext *ctx); + void ConvertToTempVariableNotIn(asCExprContext *ctx, asCExprContext *exclude); + void ConvertToReference(asCExprContext *ctx); + void PushVariableOnStack(asCExprContext *ctx, bool asReference); void DestroyVariables(asCByteCode *bc); asSNameSpace *DetermineNameSpace(const asCString &scope); int SetupParametersAndReturnVariable(asCArray ¶meterNames, asCScriptNode *func); - void DetermineSingleFunc(asSExprContext *ctx, asCScriptNode *node); + void DetermineSingleFunc(asCExprContext *ctx, asCScriptNode *node); // Returns the cost of the conversion (the sum of the EConvCost performed) - asUINT ImplicitConversion(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, bool allowObjectConstruct = true); - asUINT ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true); - asUINT ImplicitConvObjectToPrimitive(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true); - asUINT ImplicitConvPrimitiveToObject(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, bool allowObjectConstruct = true); - asUINT ImplicitConvObjectToObject(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, bool allowObjectConstruct = true); - asUINT ImplicitConvObjectRef(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode); - asUINT ImplicitConvObjectValue(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode); - void ImplicitConversionConstant(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType); - void ImplicitConvObjectToBestMathType(asSExprContext *ctx, asCScriptNode *node); - asUINT ImplicitConvLambdaToFunc(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true); + asUINT ImplicitConversion(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, bool allowObjectConstruct = true); + asUINT ImplicitConvPrimitiveToPrimitive(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true); + asUINT ImplicitConvObjectToPrimitive(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true); + asUINT ImplicitConvPrimitiveToObject(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, bool allowObjectConstruct = true); + asUINT ImplicitConvObjectToObject(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, bool allowObjectConstruct = true); + asUINT ImplicitConvObjectRef(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode); + asUINT ImplicitConvObjectValue(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode); + void ImplicitConversionConstant(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType); + void ImplicitConvObjectToBestMathType(asCExprContext *ctx, asCScriptNode *node); + asUINT ImplicitConvLambdaToFunc(asCExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true); void LineInstr(asCByteCode *bc, size_t pos); @@ -373,11 +364,11 @@ protected: asCArray continueLabels; int AllocateVariable(const asCDataType &type, bool isTemporary, bool forceOnHeap = false); - int AllocateVariableNotIn(const asCDataType &type, bool isTemporary, bool forceOnHeap, asSExprContext *ctx); + int AllocateVariableNotIn(const asCDataType &type, bool isTemporary, bool forceOnHeap, asCExprContext *ctx); int GetVariableOffset(int varIndex); int GetVariableSlot(int varOffset); void DeallocateVariable(int pos); - void ReleaseTemporaryVariable(asCTypeInfo &t, asCByteCode *bc); + void ReleaseTemporaryVariable(asCExprValue &t, asCByteCode *bc); void ReleaseTemporaryVariable(int offset, asCByteCode *bc); bool IsVariableOnHeap(int offset); @@ -402,6 +393,10 @@ protected: // This array holds the indices of variables that must not be used in an allocation asCArray reservedVariables; + // This array holds the string constants that were allocated during the compilation, + // so they can be released upon completion, whether the compilation was successful or not. + asCArray usedStringConstants; + bool isCompilingDefaultArg; bool isProcessingDeferredParams; int noCodeOutput; diff --git a/lib/angelscript/source/as_config.h b/lib/angelscript/source/as_config.h index 525ebed25..8542c186a 100644 --- a/lib/angelscript/source/as_config.h +++ b/lib/angelscript/source/as_config.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2016 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -155,6 +155,7 @@ // // How to identify different compilers //----------------------------------------- +// Ref: http://nadeausoftware.com/articles/2012/10/c_c_tip_how_detect_compiler_name_and_version_using_compiler_predefined_macros // MS Visual C++ // _MSC_VER is defined @@ -167,10 +168,13 @@ // GNU C based compilers // __GNUC__ is defined +// CLang/LLVM +// __clang__ is defined + // Embarcadero C++Builder // __BORLANDC__ is defined -// Sun CC compiler +// Oracle Solaris Studio (previously known as Sun CC compiler) // __SUNPRO_CC is defined @@ -602,7 +606,8 @@ // GNU C (and MinGW or Cygwin on Windows) // Use the following command to determine predefined macros: echo . | g++ -dM -E - -#if (defined(__GNUC__) && !defined(__SNC__)) || defined(EPPC) || defined(__CYGWIN__) // JWC -- use this instead for Wii +// MSVC2015 can now use CLang too, but it shouldn't go in here +#if (defined(__GNUC__) && !defined(__SNC__) && !defined(_MSC_VER)) || defined(EPPC) || defined(__CYGWIN__) // JWC -- use this instead for Wii #define GNU_STYLE_VIRTUAL_METHOD #define MULTI_BASE_OFFSET(x) (*((asPWORD*)(&x)+1)) #define asVSNPRINTF(a, b, c, d) vsnprintf(a, b, c, d) @@ -836,6 +841,7 @@ #define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY) #if (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__) + // x86 32bit #define THISCALL_RETURN_SIMPLE_IN_MEMORY #define CDECL_RETURN_SIMPLE_IN_MEMORY #define STDCALL_RETURN_SIMPLE_IN_MEMORY @@ -845,6 +851,7 @@ #define AS_X86 #undef AS_NO_THISCALL_FUNCTOR_METHOD #elif defined(__x86_64__) + // x86 64bit #define AS_X64_GCC #undef AS_NO_THISCALL_FUNCTOR_METHOD #define HAS_128_BIT_PRIMITIVES @@ -854,49 +861,56 @@ // STDCALL is not available on 64bit Linux #undef STDCALL #define STDCALL - #elif (defined(__ARMEL__) || defined(__arm__)) && !(defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)) - #define AS_ARM + #elif defined(__ARMEL__) || defined(__arm__) || defined(__aarch64__) || defined(__AARCH64EL__) + // arm - // TODO: The stack unwind on exceptions currently fails due to the assembler code in as_callfunc_arm_gcc.S - #define AS_NO_EXCEPTIONS + // The assembler code currently doesn't support arm v4, nor 64bit (v8) + #if !defined(__ARM_ARCH_4__) && !defined(__ARM_ARCH_4T__) && !defined(__LP64__) + #define AS_ARM - #undef STDCALL - #define STDCALL + // TODO: The stack unwind on exceptions currently fails due to the assembler code in as_callfunc_arm_gcc.S + #define AS_NO_EXCEPTIONS - #define CDECL_RETURN_SIMPLE_IN_MEMORY - #define STDCALL_RETURN_SIMPLE_IN_MEMORY - #define THISCALL_RETURN_SIMPLE_IN_MEMORY + #undef STDCALL + #define STDCALL - #undef THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE - #undef CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE - #undef STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE + #define CDECL_RETURN_SIMPLE_IN_MEMORY + #define STDCALL_RETURN_SIMPLE_IN_MEMORY + #define THISCALL_RETURN_SIMPLE_IN_MEMORY - #define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2 - #define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2 - #define STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2 + #undef THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE + #undef CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE + #undef STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE - #ifndef AS_MAX_PORTABILITY - // Make a few checks against incompatible ABI combinations - #if defined(__FAST_MATH__) && __FAST_MATH__ == 1 - #error -ffast-math is not supported with native calling conventions + #define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2 + #define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2 + #define STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 2 + + #ifndef AS_MAX_PORTABILITY + // Make a few checks against incompatible ABI combinations + #if defined(__FAST_MATH__) && __FAST_MATH__ == 1 + #error -ffast-math is not supported with native calling conventions + #endif + #endif + + // Verify if soft-float or hard-float ABI is used + #if defined(__SOFTFP__) && __SOFTFP__ == 1 + // -ffloat-abi=softfp or -ffloat-abi=soft + #define AS_SOFTFP + #endif + + // Tested with both hard float and soft float abi + #undef AS_NO_THISCALL_FUNCTOR_METHOD #endif - #endif - - // Verify if soft-float or hard-float ABI is used - #if defined(__SOFTFP__) && __SOFTFP__ == 1 - // -ffloat-abi=softfp or -ffloat-abi=soft - #define AS_SOFTFP - #endif - - // Tested with both hard float and soft float abi - #undef AS_NO_THISCALL_FUNCTOR_METHOD #elif defined(__mips__) + // mips #define AS_MIPS #undef STDCALL #define STDCALL #ifdef _ABIO32 + // 32bit O32 ABI #define AS_MIPS // All structures are returned in memory regardless of size or complexity @@ -911,6 +925,13 @@ // For other ABIs the native calling convention is not available (yet) #define AS_MAX_PORTABILITY #endif + #elif defined(__PPC64__) + // PPC 64bit + + // The code in as_callfunc_ppc_64.cpp was built for PS3 and XBox 360, that + // although use 64bit PPC only uses 32bit pointers. + // TODO: Add support for native calling conventions on Linux with PPC 64bit + #define AS_MAX_PORTABILITY #else #define AS_MAX_PORTABILITY #endif @@ -923,7 +944,7 @@ #endif // Free BSD - #elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) || defined(__NetBSD__) + #elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) #define AS_BSD #if (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__) #undef COMPLEX_MASK @@ -1153,23 +1174,20 @@ // Detect target hardware //------------------------------------------------ -// X86, Intel, AMD, etc, i.e. most PCs -#if defined(__i386__) || defined(_M_IX86) - // Nothing special here +// Big endian CPU target? +// see: http://sourceforge.net/p/predef/wiki/Endianness/ +#if !defined(AS_BIG_ENDIAN) && \ + defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \ + defined(__BIG_ENDIAN__) || \ + defined(__ARMEB__) || \ + defined(__THUMBEB__) || \ + defined(__AARCH64EB__) || \ + defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__) + #define AS_BIG_ENDIAN #endif -// PowerPC, e.g. Mac, GameCube, PS3, XBox 360, Wii -#if defined(__PPC__) || defined(__ppc__) || defined(_PPC_) || defined(EPPC) - #define AS_BIG_ENDIAN - - // Gamecube - #if defined(_GC) - #define AS_USE_DOUBLE_AS_FLOAT - #endif -#endif - -// Dreamcast console -#ifdef __SH4_SINGLE_ONLY__ +// Dreamcast and Gamecube use only 32bit floats, so treat doubles as floats +#if defined(__SH4_SINGLE_ONLY__) || defined(_GC) #define AS_USE_DOUBLE_AS_FLOAT // use 32bit floats instead of doubles #endif diff --git a/lib/angelscript/source/as_configgroup.cpp b/lib/angelscript/source/as_configgroup.cpp index 882fc4645..36a6b11d7 100644 --- a/lib/angelscript/source/as_configgroup.cpp +++ b/lib/angelscript/source/as_configgroup.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -66,11 +66,11 @@ int asCConfigGroup::Release() return refCount; } -asCObjectType *asCConfigGroup::FindType(const char *obj) +asCTypeInfo *asCConfigGroup::FindType(const char *obj) { - for( asUINT n = 0; n < objTypes.GetLength(); n++ ) - if( objTypes[n]->name == obj ) - return objTypes[n]; + for( asUINT n = 0; n < types.GetLength(); n++ ) + if( types[n]->name == obj ) + return types[n]; return 0; } @@ -90,27 +90,27 @@ void asCConfigGroup::RefConfigGroup(asCConfigGroup *group) void asCConfigGroup::AddReferencesForFunc(asCScriptEngine *engine, asCScriptFunction *func) { - AddReferencesForType(engine, func->returnType.GetObjectType()); + AddReferencesForType(engine, func->returnType.GetTypeInfo()); for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ ) - AddReferencesForType(engine, func->parameterTypes[n].GetObjectType()); + AddReferencesForType(engine, func->parameterTypes[n].GetTypeInfo()); } -void asCConfigGroup::AddReferencesForType(asCScriptEngine *engine, asCObjectType *type) +void asCConfigGroup::AddReferencesForType(asCScriptEngine *engine, asCTypeInfo *type) { if( type == 0 ) return; // Keep reference to other groups - RefConfigGroup(engine->FindConfigGroupForObjectType(type)); + RefConfigGroup(engine->FindConfigGroupForTypeInfo(type)); // Keep track of which generated template instances the config group uses - if( type->flags & asOBJ_TEMPLATE && engine->generatedTemplateTypes.Exists(type) && !generatedTemplateInstances.Exists(type) ) - generatedTemplateInstances.PushLast(type); + if( type->flags & asOBJ_TEMPLATE && engine->generatedTemplateTypes.Exists(CastToObjectType(type)) && !generatedTemplateInstances.Exists(CastToObjectType(type)) ) + generatedTemplateInstances.PushLast(CastToObjectType(type)); } bool asCConfigGroup::HasLiveObjects() { - for( asUINT n = 0; n < objTypes.GetLength(); n++ ) - if( objTypes[n]->externalRefCount.get() != 0 ) + for( asUINT n = 0; n < types.GetLength(); n++ ) + if( types[n]->externalRefCount.get() != 0 ) return true; return false; @@ -143,36 +143,24 @@ void asCConfigGroup::RemoveConfiguration(asCScriptEngine *engine, bool notUsed) if( index >= 0 ) engine->registeredGlobalFuncs.Erase(index); scriptFunctions[n]->ReleaseInternal(); - if( engine->stringFactory == scriptFunctions[n] ) - engine->stringFactory = 0; } scriptFunctions.SetLength(0); // Remove behaviours and members of object types - for( n = 0; n < objTypes.GetLength(); n++ ) + for( n = 0; n < types.GetLength(); n++ ) { - asCObjectType *obj = objTypes[n]; - - obj->ReleaseAllFunctions(); + asCObjectType *obj = CastToObjectType(types[n]); + if( obj ) + obj->ReleaseAllFunctions(); } - // Remove function definitions - for( n = 0; n < funcDefs.GetLength(); n++ ) - { - engine->registeredFuncDefs.RemoveValue(funcDefs[n]); - funcDefs[n]->ReleaseInternal(); - engine->RemoveFuncdef(funcDefs[n]); - funcDefs[n]->ReleaseInternal(); - } - funcDefs.SetLength(0); - // Remove object types (skip this if it is possible other groups are still using the types) if( !notUsed ) { - for( n = asUINT(objTypes.GetLength()); n-- > 0; ) + for( n = asUINT(types.GetLength()); n-- > 0; ) { - asCObjectType *t = objTypes[n]; - asSMapNode *cursor; + asCTypeInfo *t = types[n]; + asSMapNode *cursor; if( engine->allRegisteredTypes.MoveTo(&cursor, asSNameSpaceNamePair(t->nameSpace, t->name)) && cursor->value == t ) { @@ -182,29 +170,35 @@ void asCConfigGroup::RemoveConfiguration(asCScriptEngine *engine, bool notUsed) engine->defaultArrayObjectType = 0; if( t->flags & asOBJ_TYPEDEF ) - engine->registeredTypeDefs.RemoveValue(t); + engine->registeredTypeDefs.RemoveValue(CastToTypedefType(t)); else if( t->flags & asOBJ_ENUM ) - engine->registeredEnums.RemoveValue(t); - else if( t->flags & asOBJ_TEMPLATE ) - engine->registeredTemplateTypes.RemoveValue(t); + engine->registeredEnums.RemoveValue(CastToEnumType(t)); + else if (t->flags & asOBJ_TEMPLATE) + engine->registeredTemplateTypes.RemoveValue(CastToObjectType(t)); + else if (t->flags & asOBJ_FUNCDEF) + { + engine->registeredFuncDefs.RemoveValue(CastToFuncdefType(t)); + engine->RemoveFuncdef(CastToFuncdefType(t)); + } else - engine->registeredObjTypes.RemoveValue(t); + engine->registeredObjTypes.RemoveValue(CastToObjectType(t)); t->DestroyInternal(); t->ReleaseInternal(); } else { - int idx = engine->templateInstanceTypes.IndexOf(t); + int idx = engine->templateInstanceTypes.IndexOf(CastToObjectType(t)); if( idx >= 0 ) { engine->templateInstanceTypes.RemoveIndexUnordered(idx); - t->DestroyInternal(); - t->ReleaseInternal(); + asCObjectType *ot = CastToObjectType(t); + ot->DestroyInternal(); + ot->ReleaseInternal(); } } } - objTypes.SetLength(0); + types.SetLength(0); } // Release other config groups diff --git a/lib/angelscript/source/as_configgroup.h b/lib/angelscript/source/as_configgroup.h index ccf785e6c..48720301e 100644 --- a/lib/angelscript/source/as_configgroup.h +++ b/lib/angelscript/source/as_configgroup.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -57,23 +57,22 @@ public: int AddRef(); int Release(); - asCObjectType *FindType(const char *obj); + asCTypeInfo *FindType(const char *name); void RefConfigGroup(asCConfigGroup *group); bool HasLiveObjects(); void RemoveConfiguration(asCScriptEngine *engine, bool notUsed = false); void AddReferencesForFunc(asCScriptEngine *engine, asCScriptFunction *func); - void AddReferencesForType(asCScriptEngine *engine, asCObjectType *type); + void AddReferencesForType(asCScriptEngine *engine, asCTypeInfo *type); asCString groupName; int refCount; - asCArray objTypes; + asCArray types; asCArray scriptFunctions; asCArray globalProps; asCArray referencedConfigGroups; - asCArray funcDefs; // This array holds the generated template instances that are used // by the config group as part of function signature or property diff --git a/lib/angelscript/source/as_context.cpp b/lib/angelscript/source/as_context.cpp index 9096a1045..e10f85766 100644 --- a/lib/angelscript/source/as_context.cpp +++ b/lib/angelscript/source/as_context.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -153,7 +153,6 @@ AS_API asIScriptContext *asGetActiveContext() } // internal -// Note: There is no asPopActiveContext(), just call tld->activeContexts.PopLast() instead asCThreadLocalData *asPushActiveContext(asIScriptContext *ctx) { asCThreadLocalData *tld = asCThreadManager::GetLocalData(); @@ -164,6 +163,15 @@ asCThreadLocalData *asPushActiveContext(asIScriptContext *ctx) return tld; } +// internal +void asPopActiveContext(asCThreadLocalData *tld, asIScriptContext *ctx) +{ + UNUSED_VAR(ctx); + asASSERT(tld && tld->activeContexts[tld->activeContexts.GetLength() - 1] == ctx); + if (tld) + tld->activeContexts.PopLast(); +} + asCContext::asCContext(asCScriptEngine *engine, bool holdRef) { m_refCount.set(1); @@ -501,6 +509,11 @@ int asCContext::Unprepare() if( m_status == asEXECUTION_ACTIVE || m_status == asEXECUTION_SUSPENDED ) return asCONTEXT_ACTIVE; + // Set the context as active so that any clean up code can use access it if desired + asCThreadLocalData *tld = asPushActiveContext((asIScriptContext *)this); + asDWORD count = m_refCount.get(); + UNUSED_VAR(count); + // Only clean the stack if the context was prepared but not executed until the end if( m_status != asEXECUTION_UNINITIALIZED && m_status != asEXECUTION_FINISHED ) @@ -511,6 +524,11 @@ int asCContext::Unprepare() // Release the returned object (if any) CleanReturnObject(); + // TODO: Unprepare is called during destruction, so nobody + // must be allowed to keep an extra reference + asASSERT(m_refCount.get() == count); + asPopActiveContext(tld, this); + // Release the object if it is a script object if( m_initialFunction && m_initialFunction->objectType && (m_initialFunction->objectType->flags & asOBJ_SCRIPT_OBJECT) ) { @@ -552,7 +570,7 @@ asBYTE asCContext::GetReturnByte() asCDataType *dt = &m_initialFunction->returnType; - if( dt->IsObject() || dt->IsReference() ) return 0; + if( dt->IsObject() || dt->IsFuncdef() || dt->IsReference() ) return 0; return *(asBYTE*)&m_regs.valueRegister; } @@ -563,7 +581,7 @@ asWORD asCContext::GetReturnWord() asCDataType *dt = &m_initialFunction->returnType; - if( dt->IsObject() || dt->IsReference() ) return 0; + if( dt->IsObject() || dt->IsFuncdef() || dt->IsReference() ) return 0; return *(asWORD*)&m_regs.valueRegister; } @@ -574,7 +592,7 @@ asDWORD asCContext::GetReturnDWord() asCDataType *dt = &m_initialFunction->returnType; - if( dt->IsObject() || dt->IsReference() ) return 0; + if( dt->IsObject() || dt->IsFuncdef() || dt->IsReference() ) return 0; return *(asDWORD*)&m_regs.valueRegister; } @@ -585,7 +603,7 @@ asQWORD asCContext::GetReturnQWord() asCDataType *dt = &m_initialFunction->returnType; - if( dt->IsObject() || dt->IsReference() ) return 0; + if( dt->IsObject() || dt->IsFuncdef() || dt->IsReference() ) return 0; return m_regs.valueRegister; } @@ -596,7 +614,7 @@ float asCContext::GetReturnFloat() asCDataType *dt = &m_initialFunction->returnType; - if( dt->IsObject() || dt->IsReference() ) return 0; + if( dt->IsObject() || dt->IsFuncdef() || dt->IsReference() ) return 0; return *(float*)&m_regs.valueRegister; } @@ -607,7 +625,7 @@ double asCContext::GetReturnDouble() asCDataType *dt = &m_initialFunction->returnType; - if( dt->IsObject() || dt->IsReference() ) return 0; + if( dt->IsObject() || dt->IsFuncdef() || dt->IsReference() ) return 0; return *(double*)&m_regs.valueRegister; } @@ -620,7 +638,7 @@ void *asCContext::GetReturnAddress() if( dt->IsReference() ) return *(void**)&m_regs.valueRegister; - else if( dt->IsObject() ) + else if( dt->IsObject() || dt->IsFuncdef() ) { if( m_initialFunction->DoesReturnOnStack() ) { @@ -644,7 +662,7 @@ void *asCContext::GetReturnObject() asCDataType *dt = &m_initialFunction->returnType; - if( !dt->IsObject() ) return 0; + if( !dt->IsObject() && !dt->IsFuncdef() ) return 0; if( dt->IsReference() ) return *(void**)(asPWORD)m_regs.valueRegister; @@ -671,7 +689,7 @@ void *asCContext::GetAddressOfReturnValue() asCDataType *dt = &m_initialFunction->returnType; // An object is stored in the objectRegister - if( !dt->IsReference() && dt->IsObject() ) + if( !dt->IsReference() && (dt->IsObject() || dt->IsFuncdef()) ) { // Need to dereference objects if( !dt->IsObjectHandle() ) @@ -731,7 +749,7 @@ int asCContext::SetArgByte(asUINT arg, asBYTE value) // Verify the type of the argument asCDataType *dt = &m_initialFunction->parameterTypes[arg]; - if( dt->IsObject() || dt->IsReference() ) + if( dt->IsObject() || dt->IsFuncdef() || dt->IsReference() ) { m_status = asEXECUTION_ERROR; return asINVALID_TYPE; @@ -774,7 +792,7 @@ int asCContext::SetArgWord(asUINT arg, asWORD value) // Verify the type of the argument asCDataType *dt = &m_initialFunction->parameterTypes[arg]; - if( dt->IsObject() || dt->IsReference() ) + if( dt->IsObject() || dt->IsFuncdef() || dt->IsReference() ) { m_status = asEXECUTION_ERROR; return asINVALID_TYPE; @@ -817,7 +835,7 @@ int asCContext::SetArgDWord(asUINT arg, asDWORD value) // Verify the type of the argument asCDataType *dt = &m_initialFunction->parameterTypes[arg]; - if( dt->IsObject() || dt->IsReference() ) + if( dt->IsObject() || dt->IsFuncdef() || dt->IsReference() ) { m_status = asEXECUTION_ERROR; return asINVALID_TYPE; @@ -860,7 +878,7 @@ int asCContext::SetArgQWord(asUINT arg, asQWORD value) // Verify the type of the argument asCDataType *dt = &m_initialFunction->parameterTypes[arg]; - if( dt->IsObject() || dt->IsReference() ) + if( dt->IsObject() || dt->IsFuncdef() || dt->IsReference() ) { m_status = asEXECUTION_ERROR; return asINVALID_TYPE; @@ -903,7 +921,7 @@ int asCContext::SetArgFloat(asUINT arg, float value) // Verify the type of the argument asCDataType *dt = &m_initialFunction->parameterTypes[arg]; - if( dt->IsObject() || dt->IsReference() ) + if( dt->IsObject() || dt->IsFuncdef() || dt->IsReference() ) { m_status = asEXECUTION_ERROR; return asINVALID_TYPE; @@ -946,7 +964,7 @@ int asCContext::SetArgDouble(asUINT arg, double value) // Verify the type of the argument asCDataType *dt = &m_initialFunction->parameterTypes[arg]; - if( dt->IsObject() || dt->IsReference() ) + if( dt->IsObject() || dt->IsFuncdef() || dt->IsReference() ) { m_status = asEXECUTION_ERROR; return asINVALID_TYPE; @@ -1026,7 +1044,7 @@ int asCContext::SetArgObject(asUINT arg, void *obj) // Verify the type of the argument asCDataType *dt = &m_initialFunction->parameterTypes[arg]; - if( !dt->IsObject() ) + if( !dt->IsObject() && !dt->IsFuncdef() ) { m_status = asEXECUTION_ERROR; return asINVALID_TYPE; @@ -1038,13 +1056,18 @@ int asCContext::SetArgObject(asUINT arg, void *obj) if( dt->IsObjectHandle() ) { // Increase the reference counter - asSTypeBehaviour *beh = &dt->GetObjectType()->beh; - if( obj && beh->addref ) - m_engine->CallObjectMethod(obj, beh->addref); + if (obj && dt->IsFuncdef()) + ((asIScriptFunction*)obj)->AddRef(); + else + { + asSTypeBehaviour *beh = &CastToObjectType(dt->GetTypeInfo())->beh; + if (obj && beh->addref) + m_engine->CallObjectMethod(obj, beh->addref); + } } else { - obj = m_engine->CreateScriptObjectCopy(obj, dt->GetObjectType()); + obj = m_engine->CreateScriptObjectCopy(obj, dt->GetTypeInfo()); } } @@ -1186,7 +1209,11 @@ int asCContext::Execute() asCThreadLocalData *tld = asPushActiveContext((asIScriptContext *)this); - if( m_regs.programPointer == 0 ) + // Make sure there are not too many nested calls, as it could crash the application + // by filling up the thread call stack + if (tld->activeContexts.GetLength() > m_engine->ep.maxNestedCalls) + SetInternalException(TXT_TOO_MANY_NESTED_CALLS); + else if( m_regs.programPointer == 0 ) { if( m_currentFunction->funcType == asFUNC_DELEGATE ) { @@ -1319,13 +1346,11 @@ int asCContext::Execute() } // Pop the active context - asASSERT(tld && tld->activeContexts[tld->activeContexts.GetLength()-1] == this); - if( tld ) - tld->activeContexts.PopLast(); + asPopActiveContext(tld, this); if( m_status == asEXECUTION_FINISHED ) { - m_regs.objectType = m_initialFunction->returnType.GetObjectType(); + m_regs.objectType = m_initialFunction->returnType.GetTypeInfo(); return asEXECUTION_FINISHED; } @@ -1426,7 +1451,7 @@ int asCContext::PopState() m_regs.valueRegister = asQWORD(asDWORD(tmp[5])); m_regs.valueRegister |= asQWORD(tmp[6])<<32; m_regs.objectRegister = (void*)tmp[7]; - m_regs.objectType = (asIObjectType*)tmp[8]; + m_regs.objectType = (asITypeInfo*)tmp[8]; // Calculate the returnValueSize if( m_initialFunction->DoesReturnOnStack() ) @@ -2481,18 +2506,9 @@ void asCContext::ExecuteNext() break; case asBC_STR: - { - // Get the string id from the argument - asWORD w = asBC_WORDARG0(l_bc); - // Push the string pointer on the stack - const asCString &b = m_engine->GetConstantString(w); - l_sp -= AS_PTR_SIZE; - *(asPWORD*)l_sp = (asPWORD)b.AddressOf(); - // Push the string length on the stack - --l_sp; - *l_sp = (asDWORD)b.GetLength(); - l_bc++; - } + // TODO: NEWSTRING: Deprecate this instruction + asASSERT(false); + l_bc++; break; case asBC_CALLSYS: @@ -2803,7 +2819,7 @@ void asCContext::ExecuteNext() { // Read variable index from location on stack asPWORD *a = (asPWORD*)(l_sp + asBC_WORDARG0(l_bc)); - asDWORD offset = *(asDWORD*)a; + asPWORD offset = *a; // Move pointer from variable to the same location on the stack asPWORD *v = (asPWORD*)(l_fp - offset); *a = *v; @@ -4339,17 +4355,24 @@ void asCContext::ExecuteNext() // Pop the thispointer from the stack void *obj = *(void**)l_sp; - l_sp += AS_PTR_SIZE; + if (obj == 0) + SetInternalException(TXT_NULL_POINTER_ACCESS); + else + { + // Only update the stack pointer if all is OK so the + // exception handler can properly clean up the stack + l_sp += AS_PTR_SIZE; - // Pop the int arg from the stack - int arg = *(int*)l_sp; - l_sp++; + // Pop the int arg from the stack + int arg = *(int*)l_sp; + l_sp++; - // Call the method - m_callingSystemFunction = m_engine->scriptFunctions[i]; - void *ptr = m_engine->CallObjectMethodRetPtr(obj, arg, m_callingSystemFunction); - m_callingSystemFunction = 0; - *(asPWORD*)&m_regs.valueRegister = (asPWORD)ptr; + // Call the method + m_callingSystemFunction = m_engine->scriptFunctions[i]; + void *ptr = m_engine->CallObjectMethodRetPtr(obj, arg, m_callingSystemFunction); + m_callingSystemFunction = 0; + *(asPWORD*)&m_regs.valueRegister = (asPWORD)ptr; + } // Update the program position after the call so that line number is correct l_bc += 2; @@ -4510,8 +4533,8 @@ void asCContext::CleanReturnObject() if( m_initialFunction && m_initialFunction->DoesReturnOnStack() && m_status == asEXECUTION_FINISHED ) { // If function returns on stack we need to call the destructor on the returned object - if( m_initialFunction->returnType.GetObjectType()->beh.destruct ) - m_engine->CallObjectMethod(GetReturnObject(), m_initialFunction->returnType.GetObjectType()->beh.destruct); + if(CastToObjectType(m_initialFunction->returnType.GetTypeInfo())->beh.destruct ) + m_engine->CallObjectMethod(GetReturnObject(), CastToObjectType(m_initialFunction->returnType.GetTypeInfo())->beh.destruct); return; } @@ -4522,25 +4545,34 @@ void asCContext::CleanReturnObject() if( m_regs.objectType ) { - // Call the destructor on the object - asSTypeBehaviour *beh = &((asCObjectType*)m_regs.objectType)->beh; - if( m_regs.objectType->GetFlags() & asOBJ_REF ) + if (m_regs.objectType->GetFlags() & asOBJ_FUNCDEF) { - asASSERT( beh->release || (m_regs.objectType->GetFlags() & asOBJ_NOCOUNT) ); - - if( beh->release ) - m_engine->CallObjectMethod(m_regs.objectRegister, beh->release); - + // Release the function pointer + reinterpret_cast(m_regs.objectRegister)->Release(); m_regs.objectRegister = 0; } else { - if( beh->destruct ) - m_engine->CallObjectMethod(m_regs.objectRegister, beh->destruct); + // Call the destructor on the object + asSTypeBehaviour *beh = &(CastToObjectType(reinterpret_cast(m_regs.objectType))->beh); + if (m_regs.objectType->GetFlags() & asOBJ_REF) + { + asASSERT(beh->release || (m_regs.objectType->GetFlags() & asOBJ_NOCOUNT)); - // Free the memory - m_engine->CallFree(m_regs.objectRegister); - m_regs.objectRegister = 0; + if (beh->release) + m_engine->CallObjectMethod(m_regs.objectRegister, beh->release); + + m_regs.objectRegister = 0; + } + else + { + if (beh->destruct) + m_engine->CallObjectMethod(m_regs.objectRegister, beh->destruct); + + // Free the memory + m_engine->CallFree(m_regs.objectRegister); + m_regs.objectRegister = 0; + } } } } @@ -4779,7 +4811,7 @@ void asCContext::CleanArgsOnStack() for( v = 0; v < m_currentFunction->scriptData->objVariablePos.GetLength(); v++ ) if( m_currentFunction->scriptData->objVariablePos[v] == var ) { - func = m_currentFunction->scriptData->funcVariableTypes[v]; + func = CastToFuncdefType(m_currentFunction->scriptData->objVariableTypes[v])->funcdef; break; } @@ -4795,7 +4827,8 @@ void asCContext::CleanArgsOnStack() { if( var == paramPos ) { - func = m_currentFunction->parameterTypes[v].GetFuncDef(); + if (m_currentFunction->parameterTypes[v].IsFuncdef()) + func = CastToFuncdefType(m_currentFunction->parameterTypes[v].GetTypeInfo())->funcdef; break; } paramPos -= m_currentFunction->parameterTypes[v].GetSizeOnStackDWords(); @@ -4815,19 +4848,23 @@ void asCContext::CleanArgsOnStack() offset += AS_PTR_SIZE; for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ ) { - if( func->parameterTypes[n].IsObject() && !func->parameterTypes[n].IsReference() ) + if( (func->parameterTypes[n].IsObject() || func->parameterTypes[n].IsFuncdef()) && !func->parameterTypes[n].IsReference() ) { + // TODO: cleanup: This logic is repeated twice in CleanStackFrame too. Should create a common function to share the code if( *(asPWORD*)&m_regs.stackPointer[offset] ) { // Call the object's destructor asSTypeBehaviour *beh = func->parameterTypes[n].GetBehaviour(); - if( func->parameterTypes[n].GetObjectType()->flags & asOBJ_REF ) + if (func->parameterTypes[n].GetTypeInfo()->flags & asOBJ_FUNCDEF) { - asASSERT( (func->parameterTypes[n].GetObjectType()->flags & asOBJ_NOCOUNT) || beh->release ); + (*(asCScriptFunction**)&m_regs.stackPointer[offset])->Release(); + } + else if( func->parameterTypes[n].GetTypeInfo()->flags & asOBJ_REF ) + { + asASSERT( (func->parameterTypes[n].GetTypeInfo()->flags & asOBJ_NOCOUNT) || beh->release ); if( beh->release ) m_engine->CallObjectMethod((void*)*(asPWORD*)&m_regs.stackPointer[offset], beh->release); - *(asPWORD*)&m_regs.stackPointer[offset] = 0; } else { @@ -4836,8 +4873,8 @@ void asCContext::CleanArgsOnStack() // Free the memory m_engine->CallFree((void*)*(asPWORD*)&m_regs.stackPointer[offset]); - *(asPWORD*)&m_regs.stackPointer[offset] = 0; } + *(asPWORD*)&m_regs.stackPointer[offset] = 0; } } @@ -4875,25 +4912,29 @@ void asCContext::CleanStackFrame() if( *(asPWORD*)&m_regs.stackFramePointer[-pos] ) { // Call the object's destructor - asSTypeBehaviour *beh = &m_currentFunction->scriptData->objVariableTypes[n]->beh; - if( m_currentFunction->scriptData->objVariableTypes[n]->flags & asOBJ_REF ) + if (m_currentFunction->scriptData->objVariableTypes[n]->flags & asOBJ_FUNCDEF) { + (*(asCScriptFunction**)&m_regs.stackFramePointer[-pos])->Release(); + } + else if( m_currentFunction->scriptData->objVariableTypes[n]->flags & asOBJ_REF ) + { + asSTypeBehaviour *beh = &CastToObjectType(m_currentFunction->scriptData->objVariableTypes[n])->beh; asASSERT( (m_currentFunction->scriptData->objVariableTypes[n]->flags & asOBJ_NOCOUNT) || beh->release ); if( beh->release ) m_engine->CallObjectMethod((void*)*(asPWORD*)&m_regs.stackFramePointer[-pos], beh->release); - *(asPWORD*)&m_regs.stackFramePointer[-pos] = 0; } else { + asSTypeBehaviour *beh = &CastToObjectType(m_currentFunction->scriptData->objVariableTypes[n])->beh; if( beh->destruct ) m_engine->CallObjectMethod((void*)*(asPWORD*)&m_regs.stackFramePointer[-pos], beh->destruct); else if( m_currentFunction->scriptData->objVariableTypes[n]->flags & asOBJ_LIST_PATTERN ) - m_engine->DestroyList((asBYTE*)*(asPWORD*)&m_regs.stackFramePointer[-pos], m_currentFunction->scriptData->objVariableTypes[n]); + m_engine->DestroyList((asBYTE*)*(asPWORD*)&m_regs.stackFramePointer[-pos], CastToObjectType(m_currentFunction->scriptData->objVariableTypes[n])); // Free the memory m_engine->CallFree((void*)*(asPWORD*)&m_regs.stackFramePointer[-pos]); - *(asPWORD*)&m_regs.stackFramePointer[-pos] = 0; } + *(asPWORD*)&m_regs.stackFramePointer[-pos] = 0; } } else @@ -4903,7 +4944,7 @@ void asCContext::CleanStackFrame() // Only destroy the object if it is truly alive if( liveObjects[n] > 0 ) { - asSTypeBehaviour *beh = &m_currentFunction->scriptData->objVariableTypes[n]->beh; + asSTypeBehaviour *beh = &CastToObjectType(m_currentFunction->scriptData->objVariableTypes[n])->beh; if( beh->destruct ) m_engine->CallObjectMethod((void*)(asPWORD*)&m_regs.stackFramePointer[-pos], beh->destruct); } @@ -4925,19 +4966,22 @@ void asCContext::CleanStackFrame() offset += AS_PTR_SIZE; for( asUINT n = 0; n < m_currentFunction->parameterTypes.GetLength(); n++ ) { - if( m_currentFunction->parameterTypes[n].IsObject() && !m_currentFunction->parameterTypes[n].IsReference() ) + if( (m_currentFunction->parameterTypes[n].IsObject() ||m_currentFunction->parameterTypes[n].IsFuncdef()) && !m_currentFunction->parameterTypes[n].IsReference() ) { if( *(asPWORD*)&m_regs.stackFramePointer[offset] ) { // Call the object's destructor asSTypeBehaviour *beh = m_currentFunction->parameterTypes[n].GetBehaviour(); - if( m_currentFunction->parameterTypes[n].GetObjectType()->flags & asOBJ_REF ) + if (m_currentFunction->parameterTypes[n].GetTypeInfo()->flags & asOBJ_FUNCDEF) { - asASSERT( (m_currentFunction->parameterTypes[n].GetObjectType()->flags & asOBJ_NOCOUNT) || beh->release ); + (*(asCScriptFunction**)&m_regs.stackFramePointer[offset])->Release(); + } + else if( m_currentFunction->parameterTypes[n].GetTypeInfo()->flags & asOBJ_REF ) + { + asASSERT( (m_currentFunction->parameterTypes[n].GetTypeInfo()->flags & asOBJ_NOCOUNT) || beh->release ); if( beh->release ) m_engine->CallObjectMethod((void*)*(asPWORD*)&m_regs.stackFramePointer[offset], beh->release); - *(asPWORD*)&m_regs.stackFramePointer[offset] = 0; } else { @@ -4946,8 +4990,8 @@ void asCContext::CleanStackFrame() // Free the memory m_engine->CallFree((void*)*(asPWORD*)&m_regs.stackFramePointer[offset]); - *(asPWORD*)&m_regs.stackFramePointer[offset] = 0; } + *(asPWORD*)&m_regs.stackFramePointer[offset] = 0; } } @@ -5122,12 +5166,27 @@ int asCContext::CallGeneric(asCScriptFunction *descr) asCGeneric gen(m_engine, descr, currentObject, args); m_callingSystemFunction = descr; +#ifdef AS_NO_EXCEPTIONS func(&gen); +#else + // This try/catch block is to catch potential exception that may + // be thrown by the registered function. + try + { + func(&gen); + } + catch (...) + { + // Convert the exception to a script exception so the VM can + // properly report the error to the application and then clean up + SetException(TXT_EXCEPTION_CAUGHT); + } +#endif m_callingSystemFunction = 0; m_regs.valueRegister = gen.returnVal; m_regs.objectRegister = gen.objectRegister; - m_regs.objectType = descr->returnType.GetObjectType(); + m_regs.objectType = descr->returnType.GetTypeInfo(); // Clean up arguments const asUINT cleanCount = sysFunc->cleanArgs.GetLength(); @@ -5244,7 +5303,7 @@ void *asCContext::GetAddressOfVar(asUINT varIndex, asUINT stackLevel) !func->scriptData->variables[varIndex]->type.IsObjectHandle() ) { onHeap = true; - if( func->scriptData->variables[varIndex]->type.GetObjectType()->GetFlags() & asOBJ_VALUE ) + if( func->scriptData->variables[varIndex]->type.GetTypeInfo()->GetFlags() & asOBJ_VALUE ) { for( asUINT n = 0; n < func->scriptData->objVariablePos.GetLength(); n++ ) { @@ -5312,7 +5371,7 @@ int asCContext::GetThisTypeId(asUINT stackLevel) return 0; // not in a method // create a datatype - asCDataType dt = asCDataType::CreateObject((asCObjectType*)func->GetObjectType(), false); + asCDataType dt = asCDataType::CreateType((asCObjectType*)func->GetObjectType(), false); // return a typeId from the data type return m_engine->GetTypeIdFromDataType(dt); diff --git a/lib/angelscript/source/as_criticalsection.h b/lib/angelscript/source/as_criticalsection.h index 0a5084a1f..2e15288a5 100644 --- a/lib/angelscript/source/as_criticalsection.h +++ b/lib/angelscript/source/as_criticalsection.h @@ -1,24 +1,24 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; you + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product + this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source + 3. This notice may not be removed or altered from any source distribution. The original version of this library can be located at: @@ -45,18 +45,18 @@ BEGIN_AS_NAMESPACE #ifdef AS_NO_THREADS -#define DECLARECRITICALSECTION(x) -#define ENTERCRITICALSECTION(x) -#define LEAVECRITICALSECTION(x) +#define DECLARECRITICALSECTION(x) +#define ENTERCRITICALSECTION(x) +#define LEAVECRITICALSECTION(x) inline bool tryEnter() { return true; } #define TRYENTERCRITICALSECTION(x) tryEnter() -#define DECLAREREADWRITELOCK(x) -#define ACQUIREEXCLUSIVE(x) -#define RELEASEEXCLUSIVE(x) -#define ACQUIRESHARED(x) -#define RELEASESHARED(x) +#define DECLAREREADWRITELOCK(x) +#define ACQUIREEXCLUSIVE(x) +#define RELEASEEXCLUSIVE(x) +#define ACQUIRESHARED(x) +#define RELEASESHARED(x) #else @@ -115,7 +115,9 @@ END_AS_NAMESPACE #ifdef AS_XBOX360 #include #else -#define WIN32_LEAN_AND_MEAN +#ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN +#endif #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0600 // We need this to get the declaration for Windows Phone compatible Ex functions #endif @@ -154,11 +156,11 @@ public: void ReleaseShared(); protected: - // The Slim Read Write Lock object, SRWLOCK, is more efficient + // The Slim Read Write Lock object, SRWLOCK, is more efficient // but it is only available from Windows Vista so we cannot use it and // maintain compatibility with olders versions of Windows. - // Critical sections and semaphores are available on Windows XP and onwards. + // Critical sections and semaphores are available on Windows XP and onwards. // Windows XP is oldest version we support with multithreading. // The implementation is based on the following article, that shows diff --git a/lib/angelscript/source/as_datatype.cpp b/lib/angelscript/source/as_datatype.cpp index 88d0067eb..0fcd75ca6 100644 --- a/lib/angelscript/source/as_datatype.cpp +++ b/lib/angelscript/source/as_datatype.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -38,6 +38,7 @@ #include "as_config.h" #include "as_datatype.h" #include "as_tokendef.h" +#include "as_typeinfo.h" #include "as_objecttype.h" #include "as_scriptengine.h" #include "as_tokenizer.h" @@ -47,27 +48,27 @@ BEGIN_AS_NAMESPACE asCDataType::asCDataType() { tokenType = ttUnrecognizedToken; - objectType = 0; + typeInfo = 0; isReference = false; isReadOnly = false; isAuto = false; isObjectHandle = false; isConstHandle = false; - funcDef = 0; isHandleToAsHandleType = false; + ifHandleThenConst = false; } asCDataType::asCDataType(const asCDataType &dt) { tokenType = dt.tokenType; - objectType = dt.objectType; + typeInfo = dt.typeInfo; isReference = dt.isReference; isReadOnly = dt.isReadOnly; isAuto = dt.isAuto; isObjectHandle = dt.isObjectHandle; isConstHandle = dt.isConstHandle; - funcDef = dt.funcDef; isHandleToAsHandleType = dt.isHandleToAsHandleType; + ifHandleThenConst = dt.ifHandleThenConst; } asCDataType::~asCDataType() @@ -83,12 +84,12 @@ bool asCDataType::IsValid() const return true; } -asCDataType asCDataType::CreateObject(asCObjectType *ot, bool isConst) +asCDataType asCDataType::CreateType(asCTypeInfo *ti, bool isConst) { asCDataType dt; dt.tokenType = ttIdentifier; - dt.objectType = ot; + dt.typeInfo = ti; dt.isReadOnly = isConst; return dt; @@ -105,28 +106,20 @@ asCDataType asCDataType::CreateAuto(bool isConst) return dt; } -asCDataType asCDataType::CreateObjectHandle(asCObjectType *ot, bool isConst) +asCDataType asCDataType::CreateObjectHandle(asCTypeInfo *ot, bool isConst) { asCDataType dt; + asASSERT(CastToObjectType(ot)); + dt.tokenType = ttIdentifier; - dt.objectType = ot; + dt.typeInfo = ot; dt.isObjectHandle = true; dt.isConstHandle = isConst; return dt; } -asCDataType asCDataType::CreateFuncDef(asCScriptFunction *func) -{ - asCDataType dt; - dt.tokenType = ttIdentifier; - dt.funcDef = func; - dt.objectType = &func->engine->functionBehaviours; - - return dt; -} - asCDataType asCDataType::CreatePrimitive(eTokenType tt, bool isConst) { asCDataType dt; @@ -152,7 +145,7 @@ asCDataType asCDataType::CreateNullHandle() bool asCDataType::IsNullHandle() const { if( tokenType == ttUnrecognizedToken && - objectType == 0 && + typeInfo == 0 && isObjectHandle ) return true; @@ -171,38 +164,40 @@ asCString asCDataType::Format(asSNameSpace *currNs, bool includeNamespace) const // If the type is not declared in the current namespace, then the namespace // must always be informed to guarantee that the correct type is informed - if( includeNamespace || (objectType && objectType->nameSpace != currNs) || (funcDef && funcDef->nameSpace != currNs) ) + if (includeNamespace || (typeInfo && typeInfo->nameSpace != currNs)) { - if( objectType && objectType->nameSpace->name != "" ) - str += objectType->nameSpace->name + "::"; - else if( funcDef && funcDef->nameSpace->name != "" ) - str += funcDef->nameSpace->name + "::"; + if (typeInfo && typeInfo->nameSpace && typeInfo->nameSpace->name != "") + str += typeInfo->nameSpace->name + "::"; + } + if (typeInfo && typeInfo->nameSpace == 0) + { + // If funcDef->nameSpace is null it means the funcDef was declared as member of + // another type, in which case the scope should be built with the name of that type + str += CastToFuncdefType(typeInfo)->parentClass->name + "::"; } if( tokenType != ttIdentifier ) { str += asCTokenizer::GetDefinition(tokenType); } - else if( IsArrayType() && objectType && !objectType->engine->ep.expandDefaultArrayToTemplate ) + else if( IsArrayType() && typeInfo && !typeInfo->engine->ep.expandDefaultArrayToTemplate ) { - asASSERT( objectType->templateSubTypes.GetLength() == 1 ); - str += objectType->templateSubTypes[0].Format(currNs, includeNamespace); + asCObjectType *ot = CastToObjectType(typeInfo); + asASSERT( ot && ot->templateSubTypes.GetLength() == 1 ); + str += ot->templateSubTypes[0].Format(currNs, includeNamespace); str += "[]"; } - else if( funcDef ) + else if(typeInfo) { - str += funcDef->name; - } - else if( objectType ) - { - str += objectType->name; - if( objectType->templateSubTypes.GetLength() > 0 ) + str += typeInfo->name; + asCObjectType *ot = CastToObjectType(typeInfo); + if( ot && ot->templateSubTypes.GetLength() > 0 ) { str += "<"; - for( asUINT subtypeIndex = 0; subtypeIndex < objectType->templateSubTypes.GetLength(); subtypeIndex++ ) + for( asUINT subtypeIndex = 0; subtypeIndex < ot->templateSubTypes.GetLength(); subtypeIndex++ ) { - str += objectType->templateSubTypes[subtypeIndex].Format(currNs, includeNamespace); - if( subtypeIndex != objectType->templateSubTypes.GetLength()-1 ) + str += ot->templateSubTypes[subtypeIndex].Format(currNs, includeNamespace); + if( subtypeIndex != ot->templateSubTypes.GetLength()-1 ) str += ","; } str += ">"; @@ -210,10 +205,7 @@ asCString asCDataType::Format(asSNameSpace *currNs, bool includeNamespace) const } else if( isAuto ) { - if( isObjectHandle ) - str += ""; - else - str += ""; + str += ""; } else { @@ -237,13 +229,13 @@ asCDataType &asCDataType::operator =(const asCDataType &dt) { tokenType = dt.tokenType; isReference = dt.isReference; - objectType = dt.objectType; + typeInfo = dt.typeInfo; isReadOnly = dt.isReadOnly; isObjectHandle = dt.isObjectHandle; isConstHandle = dt.isConstHandle; isAuto = dt.isAuto; - funcDef = dt.funcDef; isHandleToAsHandleType = dt.isHandleToAsHandleType; + ifHandleThenConst = dt.ifHandleThenConst; return (asCDataType &)*this; } @@ -269,18 +261,17 @@ int asCDataType::MakeHandle(bool b, bool acceptHandleForScope) // (except when returned from registered function) // funcdefs are special reference types and support handles // value types with asOBJ_ASHANDLE are treated as a handle - if( !funcDef && - (!objectType || - !((objectType->flags & asOBJ_REF) || (objectType->flags & asOBJ_TEMPLATE_SUBTYPE) || (objectType->flags & asOBJ_ASHANDLE)) || - (objectType->flags & asOBJ_NOHANDLE) || - ((objectType->flags & asOBJ_SCOPED) && !acceptHandleForScope)) ) + if( (!typeInfo || + !((typeInfo->flags & asOBJ_REF) || (typeInfo->flags & asOBJ_TEMPLATE_SUBTYPE) || (typeInfo->flags & asOBJ_ASHANDLE) || (typeInfo->flags & asOBJ_FUNCDEF)) || + (typeInfo->flags & asOBJ_NOHANDLE) || + ((typeInfo->flags & asOBJ_SCOPED) && !acceptHandleForScope)) ) return -1; isObjectHandle = b; isConstHandle = false; // ASHANDLE supports being handle, but as it really is a value type it will not be marked as a handle - if( (objectType->flags & asOBJ_ASHANDLE) ) + if( (typeInfo->flags & asOBJ_ASHANDLE) ) { isObjectHandle = false; isHandleToAsHandleType = true; @@ -306,7 +297,7 @@ int asCDataType::MakeArray(asCScriptEngine *engine, asCModule *module) isObjectHandle = false; isConstHandle = false; - objectType = at; + typeInfo = at; tokenType = ttIdentifier; return 0; @@ -341,9 +332,9 @@ int asCDataType::MakeHandleToConst(bool b) bool asCDataType::SupportHandles() const { - if( objectType && - (objectType->flags & (asOBJ_REF | asOBJ_ASHANDLE)) && - !(objectType->flags & asOBJ_NOHANDLE) && + if( typeInfo && + (typeInfo->flags & (asOBJ_REF | asOBJ_ASHANDLE | asOBJ_FUNCDEF)) && + !(typeInfo->flags & asOBJ_NOHANDLE) && !isObjectHandle ) return true; @@ -355,19 +346,25 @@ bool asCDataType::CanBeInstantiated() const if( GetSizeOnStackDWords() == 0 ) // Void return false; - if( !IsObject() ) // Primitives + if( !IsObject() && !IsFuncdef() ) // Primitives return true; - if( IsObjectHandle() && !(objectType->flags & asOBJ_NOHANDLE) ) // Handles - return true; - - if( funcDef ) // Funcdefs can be instantiated as delegates - return true; - - if( (objectType->flags & asOBJ_REF) && objectType->beh.factories.GetLength() == 0 ) // ref types without factories + if (IsNullHandle()) // null return false; - if( (objectType->flags & asOBJ_ABSTRACT) && !IsObjectHandle() ) // Can't instantiate abstract classes + if( IsObjectHandle() && !(typeInfo->flags & asOBJ_NOHANDLE) ) // Handles + return true; + + // Funcdefs cannot be instantiated without being handles + // The exception being delegates, but these can only be created as temporary objects + if (IsFuncdef()) + return false; + + asCObjectType *ot = CastToObjectType(typeInfo); + if( ot && (ot->flags & asOBJ_REF) && ot->beh.factories.GetLength() == 0 ) // ref types without factories + return false; + + if( ot && (ot->flags & asOBJ_ABSTRACT) && !IsObjectHandle() ) // Can't instantiate abstract classes return false; return true; @@ -375,12 +372,16 @@ bool asCDataType::CanBeInstantiated() const bool asCDataType::IsAbstractClass() const { - return objectType && (objectType->flags & asOBJ_ABSTRACT) ? true : false; + return typeInfo && (typeInfo->flags & asOBJ_ABSTRACT) ? true : false; } bool asCDataType::IsInterface() const { - return objectType && objectType->IsInterface(); + if (typeInfo == 0) + return false; + + asCObjectType *ot = CastToObjectType(typeInfo); + return ot && ot->IsInterface(); } bool asCDataType::CanBeCopied() const @@ -389,19 +390,19 @@ bool asCDataType::CanBeCopied() const if( IsPrimitive() ) return true; // Plain-old-data structures can always be copied - if( objectType->flags & asOBJ_POD ) return true; + if( typeInfo->flags & asOBJ_POD ) return true; // It must be possible to instantiate the type if( !CanBeInstantiated() ) return false; - // It must have a default constructor or factory - if( objectType->beh.construct == 0 && - objectType->beh.factory == 0 ) return false; + // It must have a default constructor or factory and the opAssign + // Alternatively it must have the copy constructor + asCObjectType *ot = CastToObjectType(typeInfo); + if (ot && (((ot->beh.construct != 0 || ot->beh.factory != 0) && ot->beh.copy != 0) || + (ot->beh.copyconstruct != 0 || ot->beh.copyfactory != 0)) ) + return true; - // It must be possible to copy the type - if( objectType->beh.copy == 0 ) return false; - - return true; + return false; } bool asCDataType::IsReadOnly() const @@ -430,15 +431,15 @@ bool asCDataType::IsObjectConst() const bool asCDataType::IsArrayType() const { // This is only true if the type used is the default array type, i.e. the one used for the [] syntax form - if( objectType && objectType->engine->defaultArrayObjectType ) - return objectType->name == objectType->engine->defaultArrayObjectType->name; + if( typeInfo && typeInfo->engine->defaultArrayObjectType ) + return typeInfo->name == typeInfo->engine->defaultArrayObjectType->name; return false; } bool asCDataType::IsTemplate() const { - if( objectType && (objectType->flags & asOBJ_TEMPLATE) ) + if( typeInfo && (typeInfo->flags & asOBJ_TEMPLATE) ) return true; return false; @@ -446,7 +447,7 @@ bool asCDataType::IsTemplate() const bool asCDataType::IsScriptObject() const { - if( objectType && (objectType->flags & asOBJ_SCRIPT_OBJECT) ) + if( typeInfo && (typeInfo->flags & asOBJ_SCRIPT_OBJECT) ) return true; return false; @@ -454,8 +455,9 @@ bool asCDataType::IsScriptObject() const asCDataType asCDataType::GetSubType(asUINT subtypeIndex) const { - asASSERT(objectType); - return objectType->templateSubTypes[subtypeIndex]; + asASSERT(typeInfo); + asCObjectType *ot = CastToObjectType(typeInfo); + return ot->templateSubTypes[subtypeIndex]; } @@ -487,11 +489,10 @@ bool asCDataType::IsEqualExceptRefAndConst(const asCDataType &dt) const { // Check base type if( tokenType != dt.tokenType ) return false; - if( objectType != dt.objectType ) return false; + if( typeInfo != dt.typeInfo ) return false; if( isObjectHandle != dt.isObjectHandle ) return false; if( isObjectHandle ) if( isReadOnly != dt.isReadOnly ) return false; - if( funcDef != dt.funcDef ) return false; return true; } @@ -510,11 +511,11 @@ bool asCDataType::IsPrimitive() const if( IsEnumType() ) return true; - // A registered object is never a primitive neither is a pointer, nor an array - if( objectType || funcDef ) + // A registered object is never a primitive neither is a pointer nor an array + if( typeInfo ) return false; - // Null handle doesn't have an objectType, but it is not a primitive + // Null handle doesn't have a typeInfo, but it is not a primitive if( tokenType == ttUnrecognizedToken ) return false; @@ -584,16 +585,25 @@ bool asCDataType::IsObject() const return false; // Null handle doesn't have an object type but should still be considered an object - if( objectType == 0 ) + if( typeInfo == 0 ) return IsNullHandle(); - return true; + // Template subtypes shouldn't be considered objects + return CastToObjectType(typeInfo) ? true : false; +} + +bool asCDataType::IsFuncdef() const +{ + if (typeInfo && (typeInfo->flags & asOBJ_FUNCDEF)) + return true; + + return false; } int asCDataType::GetSizeInMemoryBytes() const { - if( objectType != 0 ) - return objectType->size; + if( typeInfo != 0 ) + return typeInfo->size; if( tokenType == ttVoid ) return 0; @@ -640,7 +650,7 @@ int asCDataType::GetSizeOnStackDWords() const int size = tokenType == ttQuestion ? 1 : 0; if( isReference ) return AS_PTR_SIZE + size; - if( objectType && !IsEnumType() ) return AS_PTR_SIZE + size; + if( typeInfo && !IsEnumType() ) return AS_PTR_SIZE + size; return GetSizeInMemoryDWords() + size; } @@ -648,27 +658,29 @@ int asCDataType::GetSizeOnStackDWords() const #ifdef WIP_16BYTE_ALIGN int asCDataType::GetAlignment() const { - if( objectType == NULL ) + if( typeInfo == NULL ) { // TODO: Small primitives should not be aligned to 4 byte boundaries return 4; //Default alignment } - return objectType->alignment; + return typeInfo->alignment; } #endif asSTypeBehaviour *asCDataType::GetBehaviour() const -{ - return objectType ? &objectType->beh : 0; +{ + if (!typeInfo) return 0; + asCObjectType *ot = CastToObjectType(typeInfo); + return ot ? &ot->beh : 0; } bool asCDataType::IsEnumType() const { // Do a sanity check on the objectType, to verify that we aren't trying to access memory after it has been released - asASSERT( objectType == 0 || objectType->name.GetLength() < 100 ); + asASSERT(typeInfo == 0 || typeInfo->name.GetLength() < 100); - if( objectType && (objectType->flags & asOBJ_ENUM) ) + if (typeInfo && (typeInfo->flags & asOBJ_ENUM)) return true; return false; diff --git a/lib/angelscript/source/as_datatype.h b/lib/angelscript/source/as_datatype.h index b079e447c..665f83a42 100644 --- a/lib/angelscript/source/as_datatype.h +++ b/lib/angelscript/source/as_datatype.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2016 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -47,12 +47,14 @@ BEGIN_AS_NAMESPACE struct asSTypeBehaviour; class asCScriptEngine; -class asCObjectType; +class asCTypeInfo; class asCScriptFunction; class asCModule; +class asCObjectType; +class asCEnumType; struct asSNameSpace; -// TODO: refactor: Reference should not be part of the datatype. This should be stored separately, e.g. in asCTypeInfo +// TODO: refactor: Reference should not be part of the datatype. This should be stored separately, e.g. in asCExprValue // MakeReference, MakeReadOnly, IsReference, IsReadOnly should be removed class asCDataType @@ -67,10 +69,9 @@ public: asCString Format(asSNameSpace *currNs, bool includeNamespace = false) const; static asCDataType CreatePrimitive(eTokenType tt, bool isConst); - static asCDataType CreateObject(asCObjectType *ot, bool isConst); + static asCDataType CreateType(asCTypeInfo *ti, bool isConst); static asCDataType CreateAuto(bool isConst); - static asCDataType CreateObjectHandle(asCObjectType *ot, bool isConst); - static asCDataType CreateFuncDef(asCScriptFunction *ot); + static asCDataType CreateObjectHandle(asCTypeInfo *ot, bool isConst); static asCDataType CreateNullHandle(); int MakeHandle(bool b, bool acceptHandleForScope = false); @@ -78,6 +79,8 @@ public: int MakeReference(bool b); int MakeReadOnly(bool b); int MakeHandleToConst(bool b); + void SetIfHandleThenConst(bool b) { ifHandleThenConst = b; } + bool HasIfHandleThenConst() const { return ifHandleThenConst; } bool IsTemplate() const; bool IsScriptObject() const; @@ -101,6 +104,7 @@ public: bool IsHandleToAsHandleType() const {return isHandleToAsHandleType;} bool IsAbstractClass() const; bool IsInterface() const; + bool IsFuncdef() const; bool IsObjectConst() const; @@ -118,8 +122,7 @@ public: asCDataType GetSubType(asUINT subtypeIndex = 0) const; eTokenType GetTokenType() const {return tokenType;} - asCObjectType *GetObjectType() const {return objectType;} - asCScriptFunction *GetFuncDef() const {return funcDef;} + asCTypeInfo *GetTypeInfo() const { return typeInfo; } int GetSizeOnStackDWords() const; int GetSizeInMemoryBytes() const; @@ -129,8 +132,7 @@ public: #endif void SetTokenType(eTokenType tt) {tokenType = tt;} - void SetObjectType(asCObjectType *obj) {objectType = obj;} - void SetFuncDef(asCScriptFunction *func) {asASSERT(funcDef); funcDef = func; } + void SetTypeInfo(asCTypeInfo *ti) {typeInfo = ti;} asCDataType &operator =(const asCDataType &); @@ -141,8 +143,7 @@ protected: eTokenType tokenType; // Behaviour type - asCObjectType *objectType; - asCScriptFunction *funcDef; + asCTypeInfo *typeInfo; // Top level bool isReference:1; @@ -151,7 +152,8 @@ protected: bool isConstHandle:1; bool isAuto:1; bool isHandleToAsHandleType:1; // Used by the compiler to know how to initialize the object - char dummy:2; + bool ifHandleThenConst:1; // Used when creating template instances to determine if a handle should be const or not + char dummy:1; }; END_AS_NAMESPACE diff --git a/lib/angelscript/source/as_debug.h b/lib/angelscript/source/as_debug.h index 197887401..e67d8b3ae 100644 --- a/lib/angelscript/source/as_debug.h +++ b/lib/angelscript/source/as_debug.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2016 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -49,7 +49,7 @@ #ifndef AS_PSVITA // Possible on PSVita, but requires SDK access -#if defined(__GNUC__) || defined( AS_MARMALADE ) +#if !defined(_MSC_VER) && (defined(__GNUC__) || defined(AS_MARMALADE)) #ifdef __ghs__ // WIIU defines __GNUC__ but types are not defined here in 'conventional' way diff --git a/lib/angelscript/source/as_gc.cpp b/lib/angelscript/source/as_gc.cpp index f488a5053..38a527f00 100644 --- a/lib/angelscript/source/as_gc.cpp +++ b/lib/angelscript/source/as_gc.cpp @@ -130,7 +130,7 @@ int asCGarbageCollector::AddScriptObjectToGC(void *obj, asCObjectType *objType) return ot.seqNbr; } -int asCGarbageCollector::GetObjectInGC(asUINT idx, asUINT *seqNbr, void **obj, asIObjectType **type) +int asCGarbageCollector::GetObjectInGC(asUINT idx, asUINT *seqNbr, void **obj, asITypeInfo **type) { if( seqNbr ) *seqNbr = 0; if( obj ) *obj = 0; diff --git a/lib/angelscript/source/as_gc.h b/lib/angelscript/source/as_gc.h index 3609ec42b..db8da0e40 100644 --- a/lib/angelscript/source/as_gc.h +++ b/lib/angelscript/source/as_gc.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -60,7 +60,7 @@ public: void GetStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected, asUINT *newObjects, asUINT *totalNewDestroyed) const; void GCEnumCallback(void *reference); int AddScriptObjectToGC(void *obj, asCObjectType *objType); - int GetObjectInGC(asUINT idx, asUINT *seqNbr, void **obj, asIObjectType **type); + int GetObjectInGC(asUINT idx, asUINT *seqNbr, void **obj, asITypeInfo **type); int ReportAndReleaseUndestroyedObjects(); diff --git a/lib/angelscript/source/as_generic.cpp b/lib/angelscript/source/as_generic.cpp index 7510a6d05..14dd9cb6f 100644 --- a/lib/angelscript/source/as_generic.cpp +++ b/lib/angelscript/source/as_generic.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2013 Andreas Jonsson + Copyright (c) 2003-2016 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -62,6 +62,12 @@ asCGeneric::~asCGeneric() { } +// interface +void *asCGeneric::GetAuxiliary() const +{ + return sysFunction->GetAuxiliary(); +} + // interface asIScriptEngine *asCGeneric::GetEngine() const { @@ -83,7 +89,7 @@ void *asCGeneric::GetObject() // interface int asCGeneric::GetObjectTypeId() const { - asCDataType dt = asCDataType::CreateObject(sysFunction->objectType, false); + asCDataType dt = asCDataType::CreateType(sysFunction->objectType, false); return engine->GetTypeIdFromDataType(dt); } @@ -101,7 +107,7 @@ asBYTE asCGeneric::GetArgByte(asUINT arg) // Verify that the type is correct asCDataType *dt = &sysFunction->parameterTypes[arg]; - if( dt->IsObject() || dt->IsReference() ) + if( (dt->IsObject() || dt->IsFuncdef()) || dt->IsReference() ) return 0; if( dt->GetSizeInMemoryBytes() != 1 ) @@ -124,7 +130,7 @@ asWORD asCGeneric::GetArgWord(asUINT arg) // Verify that the type is correct asCDataType *dt = &sysFunction->parameterTypes[arg]; - if( dt->IsObject() || dt->IsReference() ) + if( (dt->IsObject() || dt->IsFuncdef()) || dt->IsReference() ) return 0; if( dt->GetSizeInMemoryBytes() != 2 ) @@ -147,7 +153,7 @@ asDWORD asCGeneric::GetArgDWord(asUINT arg) // Verify that the type is correct asCDataType *dt = &sysFunction->parameterTypes[arg]; - if( dt->IsObject() || dt->IsReference() ) + if( (dt->IsObject() || dt->IsFuncdef()) || dt->IsReference() ) return 0; if( dt->GetSizeInMemoryBytes() != 4 ) @@ -170,7 +176,7 @@ asQWORD asCGeneric::GetArgQWord(asUINT arg) // Verify that the type is correct asCDataType *dt = &sysFunction->parameterTypes[arg]; - if( dt->IsObject() || dt->IsReference() ) + if( (dt->IsObject() || dt->IsFuncdef()) || dt->IsReference() ) return 0; if( dt->GetSizeInMemoryBytes() != 8 ) @@ -193,7 +199,7 @@ float asCGeneric::GetArgFloat(asUINT arg) // Verify that the type is correct asCDataType *dt = &sysFunction->parameterTypes[arg]; - if( dt->IsObject() || dt->IsReference() ) + if( (dt->IsObject() || dt->IsFuncdef()) || dt->IsReference() ) return 0; if( dt->GetSizeInMemoryBytes() != 4 ) @@ -216,7 +222,7 @@ double asCGeneric::GetArgDouble(asUINT arg) // Verify that the type is correct asCDataType *dt = &sysFunction->parameterTypes[arg]; - if( dt->IsObject() || dt->IsReference() ) + if( (dt->IsObject() || dt->IsFuncdef()) || dt->IsReference() ) return 0; if( dt->GetSizeInMemoryBytes() != 8 ) @@ -259,7 +265,7 @@ void *asCGeneric::GetArgObject(asUINT arg) // Verify that the type is correct asCDataType *dt = &sysFunction->parameterTypes[arg]; - if( !dt->IsObject() ) + if( !dt->IsObject() && !dt->IsFuncdef() ) return 0; // Determine the position of the argument @@ -325,14 +331,14 @@ int asCGeneric::GetArgTypeId(asUINT arg, asDWORD *flags) const int asCGeneric::SetReturnByte(asBYTE val) { // Verify the type of the return value - if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() ) + if( (sysFunction->returnType.IsObject() || sysFunction->returnType.IsFuncdef()) || sysFunction->returnType.IsReference() ) return asINVALID_TYPE; if( sysFunction->returnType.GetSizeInMemoryBytes() != 1 ) return asINVALID_TYPE; - // Store the value - *(asBYTE*)&returnVal = val; + // Store the value + *(asBYTE*)&returnVal = val; return 0; } @@ -341,14 +347,14 @@ int asCGeneric::SetReturnByte(asBYTE val) int asCGeneric::SetReturnWord(asWORD val) { // Verify the type of the return value - if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() ) + if( (sysFunction->returnType.IsObject() || sysFunction->returnType.IsFuncdef()) || sysFunction->returnType.IsReference() ) return asINVALID_TYPE; if( sysFunction->returnType.GetSizeInMemoryBytes() != 2 ) return asINVALID_TYPE; - // Store the value - *(asWORD*)&returnVal = val; + // Store the value + *(asWORD*)&returnVal = val; return 0; } @@ -357,14 +363,14 @@ int asCGeneric::SetReturnWord(asWORD val) int asCGeneric::SetReturnDWord(asDWORD val) { // Verify the type of the return value - if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() ) + if( (sysFunction->returnType.IsObject() || sysFunction->returnType.IsFuncdef()) || sysFunction->returnType.IsReference() ) return asINVALID_TYPE; if( sysFunction->returnType.GetSizeInMemoryBytes() != 4 ) return asINVALID_TYPE; - // Store the value - *(asDWORD*)&returnVal = val; + // Store the value + *(asDWORD*)&returnVal = val; return 0; } @@ -373,7 +379,7 @@ int asCGeneric::SetReturnDWord(asDWORD val) int asCGeneric::SetReturnQWord(asQWORD val) { // Verify the type of the return value - if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() ) + if( (sysFunction->returnType.IsObject() || sysFunction->returnType.IsFuncdef()) || sysFunction->returnType.IsReference() ) return asINVALID_TYPE; if( sysFunction->returnType.GetSizeOnStackDWords() != 2 ) @@ -389,7 +395,7 @@ int asCGeneric::SetReturnQWord(asQWORD val) int asCGeneric::SetReturnFloat(float val) { // Verify the type of the return value - if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() ) + if( (sysFunction->returnType.IsObject() || sysFunction->returnType.IsFuncdef()) || sysFunction->returnType.IsReference() ) return asINVALID_TYPE; if( sysFunction->returnType.GetSizeOnStackDWords() != 1 ) @@ -405,7 +411,7 @@ int asCGeneric::SetReturnFloat(float val) int asCGeneric::SetReturnDouble(double val) { // Verify the type of the return value - if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() ) + if( (sysFunction->returnType.IsObject() || sysFunction->returnType.IsFuncdef()) || sysFunction->returnType.IsReference() ) return asINVALID_TYPE; if( sysFunction->returnType.GetSizeOnStackDWords() != 2 ) @@ -441,7 +447,7 @@ int asCGeneric::SetReturnAddress(void *val) int asCGeneric::SetReturnObject(void *obj) { asCDataType *dt = &sysFunction->returnType; - if( !dt->IsObject() ) + if( !dt->IsObject() && !dt->IsFuncdef() ) return asINVALID_TYPE; if( dt->IsReference() ) @@ -453,9 +459,17 @@ int asCGeneric::SetReturnObject(void *obj) if( dt->IsObjectHandle() ) { // Increase the reference counter - asSTypeBehaviour *beh = &dt->GetObjectType()->beh; - if( obj && beh->addref ) - engine->CallObjectMethod(obj, beh->addref); + if (dt->IsFuncdef()) + { + if (obj) + reinterpret_cast(obj)->AddRef(); + } + else + { + asSTypeBehaviour *beh = &CastToObjectType(dt->GetTypeInfo())->beh; + if (obj && beh && beh->addref) + engine->CallObjectMethod(obj, beh->addref); + } } else { @@ -463,7 +477,7 @@ int asCGeneric::SetReturnObject(void *obj) // Here we should just initialize that memory by calling the copy constructor // or the default constructor followed by the assignment operator void *mem = (void*)*(asPWORD*)&stackPointer[-AS_PTR_SIZE]; - engine->ConstructScriptObjectCopy(mem, obj, dt->GetObjectType()); + engine->ConstructScriptObjectCopy(mem, obj, CastToObjectType(dt->GetTypeInfo())); return 0; } @@ -477,7 +491,7 @@ void *asCGeneric::GetReturnPointer() { asCDataType &dt = sysFunction->returnType; - if( dt.IsObject() && !dt.IsReference() ) + if( (dt.IsObject() ||dt.IsFuncdef()) && !dt.IsReference() ) { // This function doesn't support returning on the stack but the use of // the function doesn't require it so we don't need to implement it here. @@ -494,7 +508,7 @@ void *asCGeneric::GetAddressOfReturnLocation() { asCDataType &dt = sysFunction->returnType; - if( dt.IsObject() && !dt.IsReference() ) + if( (dt.IsObject() || dt.IsFuncdef()) && !dt.IsReference() ) { if( sysFunction->DoesReturnOnStack() ) { diff --git a/lib/angelscript/source/as_generic.h b/lib/angelscript/source/as_generic.h index dd122be13..158d8f9c7 100644 --- a/lib/angelscript/source/as_generic.h +++ b/lib/angelscript/source/as_generic.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2013 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -55,6 +55,7 @@ public: // Miscellaneous asIScriptEngine *GetEngine() const; asIScriptFunction *GetFunction() const; + void *GetAuxiliary() const; // Object void *GetObject(); diff --git a/lib/angelscript/source/as_globalproperty.cpp b/lib/angelscript/source/as_globalproperty.cpp index df2e51557..3fe4627fb 100644 --- a/lib/angelscript/source/as_globalproperty.cpp +++ b/lib/angelscript/source/as_globalproperty.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -120,13 +120,13 @@ void *asCGlobalProperty::GetRegisteredAddress() const return realAddress; } -void asCGlobalProperty::SetInitFunc(asCScriptFunction *initFunc) +void asCGlobalProperty::SetInitFunc(asCScriptFunction *in_initFunc) { // This should only be done once - asASSERT( this->initFunc == 0 ); + asASSERT( initFunc == 0 ); - this->initFunc = initFunc; - this->initFunc->AddRefInternal(); + initFunc = in_initFunc; + initFunc->AddRefInternal(); } asCScriptFunction *asCGlobalProperty::GetInitFunc() diff --git a/lib/angelscript/source/as_memory.cpp b/lib/angelscript/source/as_memory.cpp index a2a357b4d..db3b06f94 100644 --- a/lib/angelscript/source/as_memory.cpp +++ b/lib/angelscript/source/as_memory.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2016 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -38,8 +38,7 @@ #include -#if !defined(__APPLE__) && !defined( __SNC__ ) && !defined( __ghs__ ) \ - && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) +#if !defined(__APPLE__) && !defined(__SNC__) && !defined(__ghs__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) #include #endif diff --git a/lib/angelscript/source/as_module.cpp b/lib/angelscript/source/as_module.cpp index 2c81e0762..870a66932 100644 --- a/lib/angelscript/source/as_module.cpp +++ b/lib/angelscript/source/as_module.cpp @@ -1,24 +1,24 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; you + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product + this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source + 3. This notice may not be removed or altered from any source distribution. The original version of this library can be located at: @@ -67,7 +67,7 @@ asCModule::~asCModule() { InternalReset(); - // The builder is not removed by InternalReset because it holds the script + // The builder is not removed by InternalReset because it holds the script // sections that will be built, so we need to explictly remove it now if it exists if( builder ) { @@ -111,7 +111,7 @@ void asCModule::Discard() asCScriptEngine *lEngine = engine; // Instead of deleting the module immediately, move it to the discarded pile - // This will turn it invisible to the application, yet keep it alive until all + // This will turn it invisible to the application, yet keep it alive until all // external references to its entities have been released. ACQUIREEXCLUSIVE(engine->engineRWLock); if( lEngine->lastModule == this ) @@ -195,9 +195,9 @@ asIScriptEngine *asCModule::GetEngine() const } // interface -void asCModule::SetName(const char *name) +void asCModule::SetName(const char *in_name) { - this->name = name; + name = in_name; } // interface @@ -248,13 +248,13 @@ int asCModule::SetDefaultNamespace(const char *nameSpace) } // interface -int asCModule::AddScriptSection(const char *name, const char *code, size_t codeLength, int lineOffset) +int asCModule::AddScriptSection(const char *in_name, const char *in_code, size_t in_codeLength, int in_lineOffset) { #ifdef AS_NO_COMPILER - UNUSED_VAR(name); - UNUSED_VAR(code); - UNUSED_VAR(codeLength); - UNUSED_VAR(lineOffset); + UNUSED_VAR(in_name); + UNUSED_VAR(in_code); + UNUSED_VAR(in_codeLength); + UNUSED_VAR(in_lineOffset); return asNOT_SUPPORTED; #else if( !builder ) @@ -264,7 +264,7 @@ int asCModule::AddScriptSection(const char *name, const char *code, size_t codeL return asOUT_OF_MEMORY; } - return builder->AddCode(name, code, (int)codeLength, lineOffset, (int)engine->GetScriptSectionNameIndex(name ? name : ""), engine->ep.copyScriptSections); + return builder->AddCode(in_name, in_code, (int)in_codeLength, in_lineOffset, (int)engine->GetScriptSectionNameIndex(in_name ? in_name : ""), engine->ep.copyScriptSections); #endif } @@ -287,7 +287,7 @@ int asCModule::Build() #else TimeIt("asCModule::Build"); - // Don't allow the module to be rebuilt if there are still + // Don't allow the module to be rebuilt if there are still // external references that will need the previous code // TODO: interface: The asIScriptModule must have a method for querying if the module is used if( HasExternalReferences(false) ) @@ -322,7 +322,7 @@ int asCModule::Build() r = builder->Build(); asDELETE(builder,asCBuilder); builder = 0; - + if( r < 0 ) { // Reset module again @@ -359,7 +359,7 @@ int asCModule::Build() // interface int asCModule::ResetGlobalVars(asIScriptContext *ctx) { - if( isGlobalVarInitialized ) + if( isGlobalVarInitialized ) CallExit(); return CallInit(ctx); @@ -374,7 +374,7 @@ asIScriptFunction *asCModule::GetFunctionByIndex(asUINT index) const // internal int asCModule::CallInit(asIScriptContext *myCtx) { - if( isGlobalVarInitialized ) + if( isGlobalVarInitialized ) return asERROR; // Each global variable needs to be cleared individually @@ -414,19 +414,19 @@ int asCModule::CallInit(asIScriptContext *myCtx) asCScriptFunction *func = desc->GetInitFunc(); engine->WriteMessage(func->scriptData->scriptSectionIdx >= 0 ? engine->scriptSectionNames[func->scriptData->scriptSectionIdx]->AddressOf() : "", - func->GetLineNumber(0, 0) & 0xFFFFF, + func->GetLineNumber(0, 0) & 0xFFFFF, func->GetLineNumber(0, 0) >> 20, asMSGTYPE_ERROR, msg.AddressOf()); - + if( r == asEXECUTION_EXCEPTION ) { const asIScriptFunction *function = ctx->GetExceptionFunction(); msg.Format(TXT_EXCEPTION_s_IN_s, ctx->GetExceptionString(), function->GetDeclaration()); - engine->WriteMessage(function->GetScriptSectionName(), - ctx->GetExceptionLineNumber(), + engine->WriteMessage(function->GetScriptSectionName(), + ctx->GetExceptionLineNumber(), 0, asMSGTYPE_INFORMATION, msg.AddressOf()); @@ -442,9 +442,9 @@ int asCModule::CallInit(asIScriptContext *myCtx) ctx = 0; } - // Even if the initialization failed we need to set the + // Even if the initialization failed we need to set the // flag that the variables have been initialized, otherwise - // the module won't free those variables that really were + // the module won't free those variables that really were // initialized. isGlobalVarInitialized = true; @@ -454,6 +454,48 @@ int asCModule::CallInit(asIScriptContext *myCtx) return asSUCCESS; } +// internal +void asCModule::UninitializeGlobalProp(asCGlobalProperty *prop) +{ + if (prop == 0) + return; + + if (prop->type.IsObject()) + { + void **obj = (void**)prop->GetAddressOfValue(); + if (*obj) + { + asCObjectType *ot = CastToObjectType(prop->type.GetTypeInfo()); + + if (ot->flags & asOBJ_REF) + { + asASSERT((ot->flags & asOBJ_NOCOUNT) || ot->beh.release); + if (ot->beh.release) + engine->CallObjectMethod(*obj, ot->beh.release); + } + else + { + if (ot->beh.destruct) + engine->CallObjectMethod(*obj, ot->beh.destruct); + + engine->CallFree(*obj); + } + + // Set the address to 0 as someone might try to access the variable afterwards + *obj = 0; + } + } + else if (prop->type.IsFuncdef()) + { + asCScriptFunction **func = (asCScriptFunction**)prop->GetAddressOfValue(); + if (*func) + { + (*func)->Release(); + *func = 0; + } + } +} + // internal void asCModule::CallExit() { @@ -462,31 +504,7 @@ void asCModule::CallExit() asCSymbolTableIterator it = scriptGlobals.List(); while( it ) { - if( (*it)->type.IsObject() ) - { - void **obj = (void**)(*it)->GetAddressOfValue(); - if( *obj ) - { - asCObjectType *ot = (*it)->type.GetObjectType(); - - if( ot->flags & asOBJ_REF ) - { - asASSERT( (ot->flags & asOBJ_NOCOUNT) || ot->beh.release ); - if( ot->beh.release ) - engine->CallObjectMethod(*obj, ot->beh.release); - } - else - { - if( ot->beh.destruct ) - engine->CallObjectMethod(*obj, ot->beh.destruct); - - engine->CallFree(*obj); - } - - // Set the address to 0 as someone might try to access the variable afterwards - *obj = 0; - } - } + UninitializeGlobalProp(*it); it++; } @@ -498,7 +516,30 @@ bool asCModule::HasExternalReferences(bool shuttingDown) { // Check all entiteis in the module for any external references. // If there are any external references the module cannot be deleted yet. - + + asCSymbolTableIterator it = scriptGlobals.List(); + while (it) + { + asCGlobalProperty *desc = *it; + if (desc->GetInitFunc() && desc->GetInitFunc()->externalRefCount.get()) + { + if( !shuttingDown ) + return true; + else + { + asCString msg; + msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf()); + engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf()); + + // TODO: Use a better error message + asCString tmpName = "init " + desc->name; + msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, tmpName.AddressOf(), desc->GetInitFunc()->GetFuncType()); + engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf()); + } + } + it++; + } + for( asUINT n = 0; n < scriptFunctions.GetLength(); n++ ) if( scriptFunctions[n] && scriptFunctions[n]->externalRefCount.get() ) { @@ -542,7 +583,7 @@ bool asCModule::HasExternalReferences(bool shuttingDown) msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf()); engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf()); - msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, funcDefs[n]->GetName(), funcDefs[n]->GetFuncType()); + msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, funcDefs[n]->GetName(), funcDefs[n]->funcdef->GetFuncType()); engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf()); } } @@ -576,7 +617,7 @@ void asCModule::InternalReset() // Remove all global functions globalFunctions.Clear(); - // Destroy the internals of the global properties here, but do not yet remove them from the + // Destroy the internals of the global properties here, but do not yet remove them from the // engine, because functions need the engine's varAddressMap to get to the property. If the // property is removed already, it may leak as the refCount doesn't reach 0. asCSymbolTableIterator globIt = scriptGlobals.List(); @@ -650,7 +691,7 @@ void asCModule::InternalReset() classTypes.SetLength(0); for( n = 0; n < enumTypes.GetLength(); n++ ) { - asCObjectType *type = enumTypes[n]; + asCEnumType *type = enumTypes[n]; if( type->IsShared() ) { // The type is shared, so transfer ownership to another module that also uses it @@ -662,9 +703,6 @@ void asCModule::InternalReset() } } - // The type should be destroyed now - type->DestroyInternal(); - // Remove the type from the engine if( type->IsShared() ) { @@ -679,7 +717,7 @@ void asCModule::InternalReset() enumTypes.SetLength(0); for( n = 0; n < typeDefs.GetLength(); n++ ) { - asCObjectType *type = typeDefs[n]; + asCTypedefType *type = typeDefs[n]; // The type should be destroyed now type->DestroyInternal(); @@ -693,13 +731,14 @@ void asCModule::InternalReset() // Free funcdefs for( n = 0; n < funcDefs.GetLength(); n++ ) { - asCScriptFunction *func = funcDefs[n]; - if( func->IsShared() ) + asCFuncdefType *func = funcDefs[n]; + asASSERT(func); + if( func->funcdef && func->funcdef->IsShared() ) { - // The func is shared, so transfer ownership to another module that also uses it - if( engine->FindNewOwnerForSharedFunc(func, this) != this ) + // The funcdef is shared, so transfer ownership to another module that also uses it + if( engine->FindNewOwnerForSharedType(func, this) != this ) { - // The func is owned by another module, just release our reference + // The funcdef is owned by another module, just release our reference func->ReleaseInternal(); continue; } @@ -748,12 +787,12 @@ void asCModule::InternalReset() } // interface -asIScriptFunction *asCModule::GetFunctionByName(const char *name) const +asIScriptFunction *asCModule::GetFunctionByName(const char *in_name) const { asSNameSpace *ns = defaultNamespace; while( ns ) { - const asCArray &idxs = globalFunctions.GetIndexes(ns, name); + const asCArray &idxs = globalFunctions.GetIndexes(ns, in_name); if( idxs.GetLength() != 1 ) return 0; @@ -790,7 +829,7 @@ int asCModule::GetImportedFunctionIndexByDecl(const char *decl) const int id = -1; for( asUINT n = 0; n < bindInformations.GetLength(); ++n ) { - if( func.name == bindInformations[n]->importedFunctionSignature->name && + if( func.name == bindInformations[n]->importedFunctionSignature->name && func.returnType == bindInformations[n]->importedFunctionSignature->returnType && func.parameterTypes.GetLength() == bindInformations[n]->importedFunctionSignature->parameterTypes.GetLength() ) { @@ -898,14 +937,14 @@ asUINT asCModule::GetGlobalVarCount() const } // interface -int asCModule::GetGlobalVarIndexByName(const char *name) const +int asCModule::GetGlobalVarIndexByName(const char *in_name) const { asSNameSpace *ns = defaultNamespace; // Find the global var id while( ns ) { - int id = scriptGlobals.GetFirstIndex(ns, name); + int id = scriptGlobals.GetFirstIndex(ns, in_name); if( id >= 0 ) return id; // Recursively search parent namespaces @@ -922,17 +961,22 @@ int asCModule::RemoveGlobalVar(asUINT index) if( !prop ) return asINVALID_ARG; + // If the global variables have already been initialized + // then uninitialize the variable before it is removed + if (isGlobalVarInitialized) + UninitializeGlobalProp(prop); + // Destroy the internal of the global variable (removes the initialization function) prop->DestroyInternal(); - // Check if the module is the only one referring to the module, if so remove it from the engine too + // Check if the module is the only one referring to the property, if so remove it from the engine too // If the property is not removed now, it will be removed later when the module is discarded if( prop->refCount.get() == 2 ) engine->RemoveGlobalProperty(prop); // Remove the global variable from the module - prop->Release(); scriptGlobals.Erase(index); + prop->Release(); return 0; } @@ -945,17 +989,17 @@ int asCModule::GetGlobalVarIndexByDecl(const char *decl) const // Don't write parser errors to the message callback bld.silent = true; - asCString name; + asCString declName; asSNameSpace *nameSpace; asCDataType dt; - int r = bld.ParseVariableDeclaration(decl, defaultNamespace, name, nameSpace, dt); + int r = bld.ParseVariableDeclaration(decl, defaultNamespace, declName, nameSpace, dt); if( r < 0 ) return r; // Search global variables for a match while( nameSpace ) { - int id = scriptGlobals.GetFirstIndex(nameSpace, name, asCCompGlobPropType(dt)); + int id = scriptGlobals.GetFirstIndex(nameSpace, declName, asCCompGlobPropType(dt)); if( id != -1 ) return id; @@ -970,7 +1014,7 @@ int asCModule::GetGlobalVarIndexByDecl(const char *decl) const void *asCModule::GetAddressOfGlobalVar(asUINT index) { asCGlobalProperty *prop = scriptGlobals.Get(index); - if( !prop ) + if( !prop ) return 0; // For object variables it's necessary to dereference the pointer to get the address of the value @@ -998,19 +1042,19 @@ const char *asCModule::GetGlobalVarDeclaration(asUINT index, bool includeNamespa } // interface -int asCModule::GetGlobalVar(asUINT index, const char **name, const char **nameSpace, int *typeId, bool *isConst) const +int asCModule::GetGlobalVar(asUINT index, const char **out_name, const char **out_nameSpace, int *out_typeId, bool *out_isConst) const { const asCGlobalProperty *prop = scriptGlobals.Get(index); if (!prop) return 0; - if( name ) - *name = prop->name.AddressOf(); - if( nameSpace ) - *nameSpace = prop->nameSpace->name.AddressOf(); - if( typeId ) - *typeId = engine->GetTypeIdFromDataType(prop->type); - if( isConst ) - *isConst = prop->type.IsReadOnly(); + if( out_name ) + *out_name = prop->name.AddressOf(); + if( out_nameSpace ) + *out_nameSpace = prop->nameSpace->name.AddressOf(); + if( out_typeId ) + *out_typeId = engine->GetTypeIdFromDataType(prop->type); + if( out_isConst ) + *out_isConst = prop->type.IsReadOnly(); return asSUCCESS; } @@ -1021,29 +1065,45 @@ asUINT asCModule::GetObjectTypeCount() const return (asUINT)classTypes.GetLength(); } -// interface -asIObjectType *asCModule::GetObjectTypeByIndex(asUINT index) const +// interface +asITypeInfo *asCModule::GetObjectTypeByIndex(asUINT index) const { - if( index >= classTypes.GetLength() ) + if( index >= classTypes.GetLength() ) return 0; return classTypes[index]; } // interface -asIObjectType *asCModule::GetObjectTypeByName(const char *name) const +asITypeInfo *asCModule::GetTypeInfoByName(const char *in_name) const { asSNameSpace *ns = defaultNamespace; - while( ns ) + while (ns) { - for( asUINT n = 0; n < classTypes.GetLength(); n++ ) + for (asUINT n = 0; n < classTypes.GetLength(); n++) { - if( classTypes[n] && - classTypes[n]->name == name && - classTypes[n]->nameSpace == ns ) + if (classTypes[n] && + classTypes[n]->name == in_name && + classTypes[n]->nameSpace == ns) return classTypes[n]; } + for (asUINT n = 0; n < enumTypes.GetLength(); n++) + { + if (enumTypes[n] && + enumTypes[n]->name == in_name && + enumTypes[n]->nameSpace == ns) + return enumTypes[n]; + } + + for (asUINT n = 0; n < typeDefs.GetLength(); n++) + { + if (typeDefs[n] && + typeDefs[n]->name == in_name && + typeDefs[n]->nameSpace == ns) + return typeDefs[n]; + } + // Recursively search parent namespace ns = engine->GetParentNameSpace(ns); } @@ -1070,7 +1130,7 @@ int asCModule::GetTypeIdByDecl(const char *decl) const } // interface -asIObjectType *asCModule::GetObjectTypeByDecl(const char *decl) const +asITypeInfo *asCModule::GetTypeInfoByDecl(const char *decl) const { asCDataType dt; @@ -1081,59 +1141,25 @@ asIObjectType *asCModule::GetObjectTypeByDecl(const char *decl) const bld.silent = true; int r = bld.ParseDataType(decl, &dt, defaultNamespace); - if( r < 0 ) + if (r < 0) return 0; - return dt.GetObjectType(); + return dt.GetTypeInfo(); } // interface asUINT asCModule::GetEnumCount() const { - return (asUINT)enumTypes.GetLength(); + return enumTypes.GetLength(); } // interface -const char *asCModule::GetEnumByIndex(asUINT index, int *enumTypeId, const char **nameSpace) const +asITypeInfo *asCModule::GetEnumByIndex(asUINT index) const { if( index >= enumTypes.GetLength() ) return 0; - if( enumTypeId ) - *enumTypeId = engine->GetTypeIdFromDataType(asCDataType::CreateObject(enumTypes[index], false)); - - if( nameSpace ) - *nameSpace = enumTypes[index]->nameSpace->name.AddressOf(); - - return enumTypes[index]->name.AddressOf(); -} - -// interface -int asCModule::GetEnumValueCount(int enumTypeId) const -{ - asCDataType dt = engine->GetDataTypeFromTypeId(enumTypeId); - asCObjectType *t = dt.GetObjectType(); - if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) ) - return asINVALID_TYPE; - - return (int)t->enumValues.GetLength(); -} - -// interface -const char *asCModule::GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const -{ - asCDataType dt = engine->GetDataTypeFromTypeId(enumTypeId); - asCObjectType *t = dt.GetObjectType(); - if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) ) - return 0; - - if( index >= t->enumValues.GetLength() ) - return 0; - - if( outValue ) - *outValue = t->enumValues[index]->value; - - return t->enumValues[index]->name.AddressOf(); + return enumTypes[index]; } // interface @@ -1143,21 +1169,14 @@ asUINT asCModule::GetTypedefCount() const } // interface -const char *asCModule::GetTypedefByIndex(asUINT index, int *typeId, const char **nameSpace) const +asITypeInfo *asCModule::GetTypedefByIndex(asUINT index) const { if( index >= typeDefs.GetLength() ) return 0; - if( typeId ) - *typeId = engine->GetTypeIdFromDataType(typeDefs[index]->templateSubTypes[0]); - - if( nameSpace ) - *nameSpace = typeDefs[index]->nameSpace->name.AddressOf(); - - return typeDefs[index]->name.AddressOf(); + return typeDefs[index]; } - // internal int asCModule::GetNextImportedFunctionId() { @@ -1170,7 +1189,7 @@ int asCModule::GetNextImportedFunctionId() #ifndef AS_NO_COMPILER // internal -int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &name, const asCDataType &returnType, const asCArray ¶ms, const asCArray ¶mNames, const asCArray &inOutFlags, const asCArray &defaultArgs, bool isInterface, asCObjectType *objType, bool isConstMethod, bool isGlobalFunction, bool isPrivate, bool isProtected, bool isFinal, bool isOverride, bool isShared, asSNameSpace *ns) +int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &funcName, const asCDataType &returnType, const asCArray ¶ms, const asCArray ¶mNames, const asCArray &inOutFlags, const asCArray &defaultArgs, bool isInterface, asCObjectType *objType, bool isGlobalFunction, asSFunctionTraits funcTraits, asSNameSpace *ns) { asASSERT(id >= 0); @@ -1191,9 +1210,9 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a // All methods of shared objects are also shared if( objType && objType->IsShared() ) - isShared = true; + funcTraits.SetTrait(asTRAIT_SHARED, true); - func->name = name; + func->name = funcName; func->nameSpace = ns; func->id = id; func->returnType = returnType; @@ -1209,18 +1228,13 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a func->objectType = objType; if( objType ) objType->AddRefInternal(); - func->isReadOnly = isConstMethod; - func->isPrivate = isPrivate; - func->isProtected = isProtected; - func->isFinal = isFinal; - func->isOverride = isOverride; - func->isShared = isShared; + func->traits = funcTraits; asASSERT( params.GetLength() == inOutFlags.GetLength() && params.GetLength() == defaultArgs.GetLength() ); // Verify that we are not assigning either the final or override specifier(s) if we are registering a non-member function - asASSERT( !(!objType && isFinal) ); - asASSERT( !(!objType && isOverride) ); + asASSERT( !(!objType && funcTraits.GetTrait(asTRAIT_FINAL)) ); + asASSERT( !(!objType && funcTraits.GetTrait(asTRAIT_OVERRIDE)) ); // The internal ref count was already set by the constructor scriptFunctions.PushLast(func); @@ -1237,7 +1251,7 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a return 0; } -// internal +// internal int asCModule::AddScriptFunction(asCScriptFunction *func) { scriptFunctions.PushLast(func); @@ -1247,9 +1261,9 @@ int asCModule::AddScriptFunction(asCScriptFunction *func) // If the function that is being added is an already compiled shared function // then it is necessary to look for anonymous functions that may be declared // within it and add those as well - if( func->isShared && func->funcType == asFUNC_SCRIPT ) + if( func->IsShared() && func->funcType == asFUNC_SCRIPT ) { - // Loop through the byte code and check all the + // Loop through the byte code and check all the // asBC_FuncPtr instructions for anonymous functions asDWORD *bc = func->scriptData->byteCode.AddressOf(); asUINT bcLength = (asUINT)func->scriptData->byteCode.GetLength(); @@ -1275,7 +1289,7 @@ int asCModule::AddScriptFunction(asCScriptFunction *func) } // internal -int asCModule::AddImportedFunction(int id, const asCString &name, const asCDataType &returnType, const asCArray ¶ms, const asCArray &inOutFlags, const asCArray &defaultArgs, asSNameSpace *ns, const asCString &moduleName) +int asCModule::AddImportedFunction(int id, const asCString &funcName, const asCDataType &returnType, const asCArray ¶ms, const asCArray &inOutFlags, const asCArray &defaultArgs, asSNameSpace *ns, const asCString &moduleName) { asASSERT(id >= 0); @@ -1291,7 +1305,7 @@ int asCModule::AddImportedFunction(int id, const asCString &name, const asCDataT return asOUT_OF_MEMORY; } - func->name = name; + func->name = funcName; func->id = id; func->returnType = returnType; func->nameSpace = ns; @@ -1343,7 +1357,7 @@ int asCModule::BindImportedFunction(asUINT index, asIScriptFunction *func) return asINVALID_ARG; asCScriptFunction *src = engine->GetScriptFunction(func->GetId()); - if( src == 0 ) + if( src == 0 ) return asNO_FUNCTION; // Verify return type @@ -1454,6 +1468,35 @@ int asCModule::UnbindAllImportedFunctions() return asSUCCESS; } +// internal +asCTypeInfo *asCModule::GetType(const char *type, asSNameSpace *ns) +{ + asUINT n; + + // TODO: optimize: Improve linear search + for (n = 0; n < classTypes.GetLength(); n++) + if (classTypes[n]->name == type && + classTypes[n]->nameSpace == ns) + return classTypes[n]; + + for (n = 0; n < enumTypes.GetLength(); n++) + if (enumTypes[n]->name == type && + enumTypes[n]->nameSpace == ns) + return enumTypes[n]; + + for (n = 0; n < typeDefs.GetLength(); n++) + if (typeDefs[n]->name == type && + typeDefs[n]->nameSpace == ns) + return typeDefs[n]; + + for (n = 0; n < funcDefs.GetLength(); n++) + if (funcDefs[n]->name == type && + funcDefs[n]->nameSpace == ns) + return funcDefs[n]; + + return 0; +} + // internal asCObjectType *asCModule::GetObjectType(const char *type, asSNameSpace *ns) { @@ -1465,24 +1508,14 @@ asCObjectType *asCModule::GetObjectType(const char *type, asSNameSpace *ns) classTypes[n]->nameSpace == ns ) return classTypes[n]; - for( n = 0; n < enumTypes.GetLength(); n++ ) - if( enumTypes[n]->name == type && - enumTypes[n]->nameSpace == ns ) - return enumTypes[n]; - - for( n = 0; n < typeDefs.GetLength(); n++ ) - if( typeDefs[n]->name == type && - typeDefs[n]->nameSpace == ns ) - return typeDefs[n]; - return 0; } // internal -asCGlobalProperty *asCModule::AllocateGlobalProperty(const char *name, const asCDataType &dt, asSNameSpace *ns) +asCGlobalProperty *asCModule::AllocateGlobalProperty(const char *propName, const asCDataType &dt, asSNameSpace *ns) { asCGlobalProperty *prop = engine->AllocateGlobalProperty(); - prop->name = name; + prop->name = propName; prop->nameSpace = ns; // Allocate the memory for this property based on its type @@ -1538,7 +1571,7 @@ int asCModule::LoadByteCode(asIBinaryStream *in, bool *wasDebugInfoStripped) { if( in == 0 ) return asINVALID_ARG; - // Don't allow the module to be rebuilt if there are still + // Don't allow the module to be rebuilt if there are still // external references that will need the previous code if( HasExternalReferences(false) ) { @@ -1554,6 +1587,11 @@ int asCModule::LoadByteCode(asIBinaryStream *in, bool *wasDebugInfoStripped) asCReader read(this, in, engine); r = read.Read(wasDebugInfoStripped); + if (r < 0) + { + engine->BuildCompleted(); + return r; + } JITCompile(); @@ -1601,33 +1639,33 @@ int asCModule::CompileGlobalVar(const char *sectionName, const char *code, int l } // Compile the global variable and add it to the module scope - asCBuilder builder(engine, this); + asCBuilder varBuilder(engine, this); asCString str = code; - r = builder.CompileGlobalVar(sectionName, str.AddressOf(), lineOffset); + r = varBuilder.CompileGlobalVar(sectionName, str.AddressOf(), lineOffset); engine->BuildCompleted(); // Initialize the variable if( r >= 0 && engine->ep.initGlobalVarsAfterBuild ) { - // Clear the memory + // Clear the memory asCGlobalProperty *prop = scriptGlobals.GetLast(); if( prop ) { memset(prop->GetAddressOfValue(), 0, sizeof(asDWORD)*prop->type.GetSizeOnStackDWords()); - + if( prop->GetInitFunc() ) { // Call the init function for the global variable asIScriptContext *ctx = 0; - int r = engine->CreateContext(&ctx, true); + r = engine->CreateContext(&ctx, true); if( r < 0 ) return r; - + r = ctx->Prepare(prop->GetInitFunc()); if( r >= 0 ) r = ctx->Execute(); - + ctx->Release(); } } @@ -1640,7 +1678,7 @@ int asCModule::CompileGlobalVar(const char *sectionName, const char *code, int l // interface int asCModule::CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asIScriptFunction **outFunc) { - // Make sure the outFunc is null if the function fails, so the + // Make sure the outFunc is null if the function fails, so the // application doesn't attempt to release a non-existent function if( outFunc ) *outFunc = 0; @@ -1653,7 +1691,7 @@ int asCModule::CompileFunction(const char *sectionName, const char *code, int li return asNOT_SUPPORTED; #else // Validate arguments - if( code == 0 || + if( code == 0 || (compileFlags != 0 && compileFlags != asCOMP_ADD_TO_MODULE) ) return asINVALID_ARG; @@ -1673,10 +1711,10 @@ int asCModule::CompileFunction(const char *sectionName, const char *code, int li } // Compile the single function - asCBuilder builder(engine, this); + asCBuilder funcBuilder(engine, this); asCString str = code; asCScriptFunction *func = 0; - r = builder.CompileFunction(sectionName, str.AddressOf(), lineOffset, compileFlags, &func); + r = funcBuilder.CompileFunction(sectionName, str.AddressOf(), lineOffset, compileFlags, &func); engine->BuildCompleted(); @@ -1714,22 +1752,32 @@ int asCModule::RemoveFunction(asIScriptFunction *func) #ifndef AS_NO_COMPILER // internal -int asCModule::AddFuncDef(const asCString &name, asSNameSpace *ns) +int asCModule::AddFuncDef(const asCString &funcName, asSNameSpace *ns, asCObjectType *parent) { + // namespace and parent are mutually exclusive + asASSERT((ns == 0 && parent) || (ns && parent == 0)); + asCScriptFunction *func = asNEW(asCScriptFunction)(engine, 0, asFUNC_FUNCDEF); - if( func == 0 ) + if (func == 0) return asOUT_OF_MEMORY; - func->name = name; + func->name = funcName; func->nameSpace = ns; func->module = this; - funcDefs.PushLast(func); + asCFuncdefType *fdt = asNEW(asCFuncdefType)(engine, func); + funcDefs.PushLast(fdt); // The constructor set the refcount to 1 - engine->funcDefs.PushLast(func); + engine->funcDefs.PushLast(fdt); // doesn't increase refcount func->id = engine->GetNextScriptFunctionId(); engine->AddScriptFunction(func); + if (parent) + { + parent->childFuncDefs.PushLast(fdt); + fdt->parentClass = parent; + } + return (int)funcDefs.GetLength()-1; } #endif diff --git a/lib/angelscript/source/as_module.h b/lib/angelscript/source/as_module.h index 22ad598d4..6915fe40e 100644 --- a/lib/angelscript/source/as_module.h +++ b/lib/angelscript/source/as_module.h @@ -1,24 +1,24 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; you + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product + this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source + 3. This notice may not be removed or altered from any source distribution. The original version of this library can be located at: @@ -58,12 +58,14 @@ class asCCompiler; class asCBuilder; class asCContext; class asCConfigGroup; +class asCTypedefType; +class asCFuncdefType; struct asSNameSpace; struct sBindInfo { asCScriptFunction *importedFunctionSignature; - asCString importFromModule; + asCString importFromModule; int boundFunctionId; }; @@ -74,17 +76,17 @@ struct sObjectTypePair }; -// TODO: import: Remove function imports. When I have implemented function +// TODO: import: Remove function imports. When I have implemented function // pointers the function imports should be deprecated. // TODO: Need a separate interface for compiling scripts. The asIScriptCompiler // will have a target module, and will allow the compilation of an entire // script or just individual functions within the scope of the module -// +// // With this separation it will be possible to compile the library without // the compiler, thus giving a much smaller binary executable. -// TODO: There should be an special compile option that will let the application +// TODO: There should be a special compile option that will let the application // recompile an already compiled script. The compiler should check if no // destructive changes have been made (changing function signatures, etc) // then it should simply replace the bytecode within the functions without @@ -130,20 +132,18 @@ public: // Type identification virtual asUINT GetObjectTypeCount() const; - virtual asIObjectType *GetObjectTypeByIndex(asUINT index) const; - virtual asIObjectType *GetObjectTypeByName(const char *name) const; - virtual asIObjectType *GetObjectTypeByDecl(const char *decl) const; + virtual asITypeInfo *GetObjectTypeByIndex(asUINT index) const; virtual int GetTypeIdByDecl(const char *decl) const; + virtual asITypeInfo *GetTypeInfoByName(const char *name) const; + virtual asITypeInfo *GetTypeInfoByDecl(const char *decl) const; // Enums - virtual asUINT GetEnumCount() const; - virtual const char *GetEnumByIndex(asUINT index, int *enumTypeId, const char **nameSpace) const; - virtual int GetEnumValueCount(int enumTypeId) const; - virtual const char *GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const; + virtual asUINT GetEnumCount() const; + virtual asITypeInfo *GetEnumByIndex(asUINT index) const; // Typedefs - virtual asUINT GetTypedefCount() const; - virtual const char *GetTypedefByIndex(asUINT index, int *typeId, const char **nameSpace) const; + virtual asUINT GetTypedefCount() const; + virtual asITypeInfo *GetTypedefByIndex(asUINT index) const; // Dynamic binding between modules virtual asUINT GetImportedFunctionCount() const; @@ -186,16 +186,18 @@ public: void JITCompile(); #ifndef AS_NO_COMPILER - int AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &name, const asCDataType &returnType, const asCArray ¶ms, const asCArray ¶mNames, const asCArray &inOutFlags, const asCArray &defaultArgs, bool isInterface, asCObjectType *objType = 0, bool isConstMethod = false, bool isGlobalFunction = false, bool isPrivate = false, bool isProtected = false, bool isFinal = false, bool isOverride = false, bool isShared = false, asSNameSpace *ns = 0); + int AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &name, const asCDataType &returnType, const asCArray ¶ms, const asCArray ¶mNames, const asCArray &inOutFlags, const asCArray &defaultArgs, bool isInterface, asCObjectType *objType = 0, bool isGlobalFunction = false, asSFunctionTraits funcTraits = asSFunctionTraits(), asSNameSpace *ns = 0); int AddScriptFunction(asCScriptFunction *func); int AddImportedFunction(int id, const asCString &name, const asCDataType &returnType, const asCArray ¶ms, const asCArray &inOutFlags, const asCArray &defaultArgs, asSNameSpace *ns, const asCString &moduleName); - int AddFuncDef(const asCString &name, asSNameSpace *ns); + int AddFuncDef(const asCString &name, asSNameSpace *ns, asCObjectType *parent); #endif int GetNextImportedFunctionId(); asCScriptFunction *GetImportedFunction(int funcId) const; + asCTypeInfo *GetType(const char *type, asSNameSpace *ns); asCObjectType *GetObjectType(const char *type, asSNameSpace *ns); asCGlobalProperty *AllocateGlobalProperty(const char *name, const asCDataType &dt, asSNameSpace *ns); + void UninitializeGlobalProp(asCGlobalProperty *prop); asCString name; @@ -208,7 +210,7 @@ public: // This array holds all functions, class members, factories, etc that were compiled with the module. // These references hold an internal reference to the function object. asCArray scriptFunctions; // increases ref count - // This array holds global functions declared in the module. These references are not counted, + // This array holds global functions declared in the module. These references are not counted, // as the same pointer is always present in the scriptFunctions array too. asCSymbolTable globalFunctions; // doesn't increase ref count // This array holds imported functions in the module. @@ -223,11 +225,16 @@ public: // This array holds class and interface types asCArray classTypes; // increases ref count // This array holds enum types - asCArray enumTypes; // increases ref count + asCArray enumTypes; // increases ref count // This array holds typedefs - asCArray typeDefs; // increases ref count + asCArray typeDefs; // increases ref count // This array holds the funcdefs declared in the module - asCArray funcDefs; // increases ref count + asCArray funcDefs; // increases ref count + + // This array holds types that have been explicitly declared with 'external' + asCArray externalTypes; // doesn't increase ref count + // This array holds functions that have been explicitly declared with 'external' + asCArray externalFunctions; // doesn't increase ref count }; END_AS_NAMESPACE diff --git a/lib/angelscript/source/as_objecttype.cpp b/lib/angelscript/source/as_objecttype.cpp index 8bded269d..626cb11b1 100644 --- a/lib/angelscript/source/as_objecttype.cpp +++ b/lib/angelscript/source/as_objecttype.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -45,155 +45,46 @@ BEGIN_AS_NAMESPACE -asCObjectType::asCObjectType() +asCObjectType::asCObjectType() : asCTypeInfo() { - externalRefCount.set(0); - internalRefCount.set(1); // start with one internal ref-count - engine = 0; - module = 0; derivedFrom = 0; - size = 0; - typeId = -1; // start as -1 to signal that it hasn't been defined acceptValueSubType = true; acceptRefSubType = true; - scriptSectionIdx = -1; - declaredAt = 0; - - accessMask = 0xFFFFFFFF; - nameSpace = 0; #ifdef WIP_16BYTE_ALIGN alignment = 4; #endif } -asCObjectType::asCObjectType(asCScriptEngine *engine) +asCObjectType::asCObjectType(asCScriptEngine *in_engine) : asCTypeInfo(in_engine) { - externalRefCount.set(0); - internalRefCount.set(1); // start with one internal ref count - this->engine = engine; - module = 0; derivedFrom = 0; - typeId = -1; // start as -1 to signal that it hasn't been defined acceptValueSubType = true; - acceptRefSubType = true; + acceptRefSubType = true; - scriptSectionIdx = -1; - declaredAt = 0; - - accessMask = 0xFFFFFFFF; - nameSpace = engine->nameSpaces[0]; #ifdef WIP_16BYTE_ALIGN alignment = 4; #endif } -int asCObjectType::AddRef() const -{ - return externalRefCount.atomicInc(); -} - -int asCObjectType::Release() const -{ - int r = externalRefCount.atomicDec(); - - if( r == 0 ) - { - // There are no more external references, if there are also no - // internal references then it is time to delete the object type - if( internalRefCount.get() == 0 ) - { - // If the engine is no longer set, then it has already been - // released and we must take care of the deletion ourselves - asDELETE(const_cast(this), asCObjectType); - } - } - - return r; -} - -int asCObjectType::AddRefInternal() -{ - return internalRefCount.atomicInc(); -} - -int asCObjectType::ReleaseInternal() -{ - int r = internalRefCount.atomicDec(); - - if( r == 0 ) - { - // There are no more internal references, if there are also no - // external references then it is time to delete the object type - if( externalRefCount.get() == 0 ) - { - // If the engine is no longer set, then it has already been - // released and we must take care of the deletion ourselves - asDELETE(const_cast(this), asCObjectType); - } - } - - return r; -} - // interface -asIScriptModule *asCObjectType::GetModule() const +asUINT asCObjectType::GetChildFuncdefCount() const { - return module; + return childFuncDefs.GetLength(); } -void *asCObjectType::SetUserData(void *data, asPWORD type) +// interface +asITypeInfo *asCObjectType::GetChildFuncdef(asUINT index) const { - // As a thread might add a new new user data at the same time as another - // it is necessary to protect both read and write access to the userData member - ACQUIREEXCLUSIVE(engine->engineRWLock); + if (index >= childFuncDefs.GetLength()) + return 0; - // It is not intended to store a lot of different types of userdata, - // so a more complex structure like a associative map would just have - // more overhead than a simple array. - for( asUINT n = 0; n < userData.GetLength(); n += 2 ) - { - if( userData[n] == type ) - { - void *oldData = reinterpret_cast(userData[n+1]); - userData[n+1] = reinterpret_cast(data); - - RELEASEEXCLUSIVE(engine->engineRWLock); - - return oldData; - } - } - - userData.PushLast(type); - userData.PushLast(reinterpret_cast(data)); - - RELEASEEXCLUSIVE(engine->engineRWLock); - - return 0; -} - -void *asCObjectType::GetUserData(asPWORD type) const -{ - // There may be multiple threads reading, but when - // setting the user data nobody must be reading. - ACQUIRESHARED(engine->engineRWLock); - - for( asUINT n = 0; n < userData.GetLength(); n += 2 ) - { - if( userData[n] == type ) - { - RELEASESHARED(engine->engineRWLock); - return reinterpret_cast(userData[n+1]); - } - } - - RELEASESHARED(engine->engineRWLock); - - return 0; + return childFuncDefs[index]; } +// internal void asCObjectType::DestroyInternal() { if( engine == 0 ) return; @@ -207,13 +98,38 @@ void asCObjectType::DestroyInternal() } // Release the object types held by the templateSubTypes + bool isTemplateInstance = templateSubTypes.GetLength() > 0; for( asUINT subtypeIndex = 0; subtypeIndex < templateSubTypes.GetLength(); subtypeIndex++ ) { - if( templateSubTypes[subtypeIndex].GetObjectType() ) - templateSubTypes[subtypeIndex].GetObjectType()->ReleaseInternal(); + if( templateSubTypes[subtypeIndex].GetTypeInfo() ) + templateSubTypes[subtypeIndex].GetTypeInfo()->ReleaseInternal(); } templateSubTypes.SetLength(0); + // Clear the child types + for (asUINT n = 0; n < childFuncDefs.GetLength(); n++) + { + asCFuncdefType *func = childFuncDefs[n]; + if (func) + { + func->parentClass = 0; + if (isTemplateInstance) + { + // Any child funcdefs that have been created as part of the template + // instantiation must be destroyed too + // TODO: Before destroying the funcdef, make sure no external references to it is held + if (func->externalRefCount.get() == 0) + { + func->DestroyInternal(); + engine->RemoveFuncdef(func); + func->module = 0; + func->ReleaseInternal(); + } + } + } + } + childFuncDefs.SetLength(0); + if( derivedFrom ) derivedFrom->ReleaseInternal(); derivedFrom = 0; @@ -222,25 +138,7 @@ void asCObjectType::DestroyInternal() ReleaseAllFunctions(); - asUINT n; - for( n = 0; n < enumValues.GetLength(); n++ ) - { - if( enumValues[n] ) - asDELETE(enumValues[n],asSEnumValue); - } - enumValues.SetLength(0); - - // Clean the user data - for( n = 0; n < userData.GetLength(); n += 2 ) - { - if( userData[n+1] ) - { - for( asUINT c = 0; c < engine->cleanObjectTypeFuncs.GetLength(); c++ ) - if( engine->cleanObjectTypeFuncs[c].type == userData[n] ) - engine->cleanObjectTypeFuncs[c].cleanFunc(this); - } - } - userData.SetLength(0); + CleanUserData(); // Remove the type from the engine if( typeId != -1 ) @@ -252,14 +150,11 @@ void asCObjectType::DestroyInternal() asCObjectType::~asCObjectType() { - if( engine == 0 ) - return; - DestroyInternal(); } // interface -bool asCObjectType::Implements(const asIObjectType *objType) const +bool asCObjectType::Implements(const asITypeInfo *objType) const { if( this == objType ) return true; @@ -271,7 +166,7 @@ bool asCObjectType::Implements(const asIObjectType *objType) const } // interface -bool asCObjectType::DerivesFrom(const asIObjectType *objType) const +bool asCObjectType::DerivesFrom(const asITypeInfo *objType) const { if( this == objType ) return true; @@ -288,56 +183,6 @@ bool asCObjectType::DerivesFrom(const asIObjectType *objType) const return false; } -bool asCObjectType::IsShared() const -{ - // Objects that can be declared by scripts need to have the explicit flag asOBJ_SHARED - if( flags & (asOBJ_SCRIPT_OBJECT|asOBJ_ENUM) ) return flags & asOBJ_SHARED ? true : false; - - // Otherwise we assume the object to be shared - return true; -} - -// interface -const char *asCObjectType::GetName() const -{ - return name.AddressOf(); -} - -// interface -const char *asCObjectType::GetNamespace() const -{ - return nameSpace->name.AddressOf(); -} - -// interface -asDWORD asCObjectType::GetFlags() const -{ - return flags; -} - -// interface -asUINT asCObjectType::GetSize() const -{ - return size; -} - -// interface -int asCObjectType::GetTypeId() const -{ - if( typeId == -1 ) - { - // We need a non const pointer to create the asCDataType object. - // We're not breaking anything here because this function is not - // modifying the object, so this const cast is safe. - asCObjectType *ot = const_cast(this); - - // The engine will define the typeId for this object type - engine->GetTypeIdFromDataType(asCDataType::CreateObject(ot, false)); - } - - return typeId; -} - // interface int asCObjectType::GetSubTypeId(asUINT subtypeIndex) const { @@ -352,12 +197,12 @@ int asCObjectType::GetSubTypeId(asUINT subtypeIndex) const } // interface -asIObjectType *asCObjectType::GetSubType(asUINT subtypeIndex) const +asITypeInfo *asCObjectType::GetSubType(asUINT subtypeIndex) const { if( subtypeIndex >= templateSubTypes.GetLength() ) return 0; - return templateSubTypes[subtypeIndex].GetObjectType(); + return templateSubTypes[subtypeIndex].GetTypeInfo(); } asUINT asCObjectType::GetSubTypeCount() const @@ -370,7 +215,7 @@ asUINT asCObjectType::GetInterfaceCount() const return asUINT(interfaces.GetLength()); } -asIObjectType *asCObjectType::GetInterface(asUINT index) const +asITypeInfo *asCObjectType::GetInterface(asUINT index) const { return interfaces[index]; } @@ -384,11 +229,6 @@ bool asCObjectType::IsInterface() const return false; } -asIScriptEngine *asCObjectType::GetEngine() const -{ - return engine; -} - // interface asUINT asCObjectType::GetFactoryCount() const { @@ -437,12 +277,12 @@ asIScriptFunction *asCObjectType::GetMethodByIndex(asUINT index, bool getVirtual } // interface -asIScriptFunction *asCObjectType::GetMethodByName(const char *name, bool getVirtual) const +asIScriptFunction *asCObjectType::GetMethodByName(const char *in_name, bool in_getVirtual) const { int id = -1; for( asUINT n = 0; n < methods.GetLength(); n++ ) { - if( engine->scriptFunctions[methods[n]]->name == name ) + if( engine->scriptFunctions[methods[n]]->name == in_name ) { if( id == -1 ) id = methods[n]; @@ -454,7 +294,7 @@ asIScriptFunction *asCObjectType::GetMethodByName(const char *name, bool getVirt if( id == -1 ) return 0; asCScriptFunction *func = engine->scriptFunctions[id]; - if( !getVirtual ) + if( !in_getVirtual ) { if( func && func->funcType == asFUNC_VIRTUAL ) return virtualFunctionTable[func->vfTableIdx]; @@ -497,26 +337,30 @@ asUINT asCObjectType::GetPropertyCount() const } // interface -int asCObjectType::GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, bool *isProtected, int *offset, bool *isReference, asDWORD *accessMask) const +int asCObjectType::GetProperty(asUINT index, const char **out_name, int *out_typeId, bool *out_isPrivate, bool *out_isProtected, int *out_offset, bool *out_isReference, asDWORD *out_accessMask, int *out_compositeOffset, bool *out_isCompositeIndirect) const { if( index >= properties.GetLength() ) return asINVALID_ARG; asCObjectProperty *prop = properties[index]; - if( name ) - *name = prop->name.AddressOf(); - if( typeId ) - *typeId = engine->GetTypeIdFromDataType(prop->type); - if( isPrivate ) - *isPrivate = prop->isPrivate; - if( isProtected ) - *isProtected = prop->isProtected; - if( offset ) - *offset = prop->byteOffset; - if( isReference ) - *isReference = prop->type.IsReference(); - if( accessMask ) - *accessMask = prop->accessMask; + if( out_name ) + *out_name = prop->name.AddressOf(); + if( out_typeId ) + *out_typeId = engine->GetTypeIdFromDataType(prop->type); + if( out_isPrivate ) + *out_isPrivate = prop->isPrivate; + if( out_isProtected ) + *out_isProtected = prop->isProtected; + if( out_offset ) + *out_offset = prop->byteOffset; + if( out_isReference ) + *out_isReference = prop->type.IsReference(); + if( out_accessMask ) + *out_accessMask = prop->accessMask; + if (out_compositeOffset) + *out_compositeOffset = prop->compositeOffset; + if (out_isCompositeIndirect) + *out_isCompositeIndirect = prop->isCompositeIndirect; return 0; } @@ -541,7 +385,7 @@ const char *asCObjectType::GetPropertyDeclaration(asUINT index, bool includeName return tempString->AddressOf(); } -asIObjectType *asCObjectType::GetBaseType() const +asITypeInfo *asCObjectType::GetBaseType() const { return derivedFrom; } @@ -661,24 +505,8 @@ asIScriptFunction *asCObjectType::GetBehaviourByIndex(asUINT index, asEBehaviour return 0; } -// interface -const char *asCObjectType::GetConfigGroup() const -{ - asCConfigGroup *group = engine->FindConfigGroupForObjectType(this); - if( group == 0 ) - return 0; - - return group->groupName.AddressOf(); -} - -// interface -asDWORD asCObjectType::GetAccessMask() const -{ - return accessMask; -} - // internal -asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &name, const asCDataType &dt, bool isPrivate, bool isProtected, bool isInherited) +asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &propName, const asCDataType &dt, bool isPrivate, bool isProtected, bool isInherited) { asASSERT( flags & asOBJ_SCRIPT_OBJECT ); asASSERT( dt.CanBeInstantiated() ); @@ -692,7 +520,7 @@ asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &name, cons return 0; } - prop->name = name; + prop->name = propName; prop->type = dt; prop->isPrivate = isPrivate; prop->isProtected = isProtected; @@ -705,7 +533,7 @@ asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &name, cons // because there is a risk that the script might // try to access the content without knowing that // it hasn't been initialized yet. - if( dt.GetObjectType()->flags & asOBJ_POD ) + if( dt.GetTypeInfo()->flags & asOBJ_POD ) propSize = dt.GetSizeInMemoryBytes(); else { @@ -714,6 +542,12 @@ asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &name, cons prop->type.MakeReference(true); } } + else if (dt.IsFuncdef()) + { + // Funcdefs don't have a size, as they must always be stored as handles + asASSERT(dt.IsObjectHandle()); + propSize = AS_PTR_SIZE * 4; + } else propSize = dt.GetSizeInMemoryBytes(); @@ -738,11 +572,11 @@ asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &name, cons properties.PushLast(prop); // Make sure the struct holds a reference to the config group where the object is registered - asCConfigGroup *group = engine->FindConfigGroupForObjectType(prop->type.GetObjectType()); + asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(prop->type.GetTypeInfo()); if( group != 0 ) group->AddRef(); // Add reference to object types - asCObjectType *type = prop->type.GetObjectType(); + asCTypeInfo *type = prop->type.GetTypeInfo(); if( type ) type->AddRefInternal(); @@ -759,18 +593,18 @@ void asCObjectType::ReleaseAllProperties() if( flags & asOBJ_SCRIPT_OBJECT ) { // Release the config group for script classes that are being destroyed - asCConfigGroup *group = engine->FindConfigGroupForObjectType(properties[n]->type.GetObjectType()); + asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(properties[n]->type.GetTypeInfo()); if( group != 0 ) group->Release(); // Release references to objects types - asCObjectType *type = properties[n]->type.GetObjectType(); + asCTypeInfo *type = properties[n]->type.GetTypeInfo(); if( type ) type->ReleaseInternal(); } else { // Release template instance types (ref increased by RegisterObjectProperty) - asCObjectType *type = properties[n]->type.GetObjectType(); + asCTypeInfo *type = properties[n]->type.GetTypeInfo(); if( type ) type->ReleaseInternal(); } diff --git a/lib/angelscript/source/as_objecttype.h b/lib/angelscript/source/as_objecttype.h index 7c84b7831..4b7bd5d0f 100644 --- a/lib/angelscript/source/as_objecttype.h +++ b/lib/angelscript/source/as_objecttype.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -41,17 +41,13 @@ #ifndef AS_OBJECTTYPE_H #define AS_OBJECTTYPE_H -#include "as_atomic.h" -#include "as_string.h" #include "as_property.h" #include "as_array.h" #include "as_scriptfunction.h" +#include "as_typeinfo.h" BEGIN_AS_NAMESPACE -// TODO: memory: Need to minimize used memory here, because not all types use all properties of the class - - struct asSTypeBehaviour { asSTypeBehaviour() @@ -99,134 +95,75 @@ struct asSTypeBehaviour asCArray constructors; }; -struct asSEnumValue -{ - asCString name; - int value; -}; - class asCScriptEngine; struct asSNameSpace; -class asCObjectType : public asIObjectType +class asCObjectType : public asCTypeInfo { public: -//===================================== -// From asIObjectType -//===================================== - asIScriptEngine *GetEngine() const; - const char *GetConfigGroup() const; - asDWORD GetAccessMask() const; - asIScriptModule *GetModule() const; - - // Memory management - int AddRef() const; - int Release() const; - - // Type info - const char *GetName() const; - const char *GetNamespace() const; - asIObjectType *GetBaseType() const; - bool DerivesFrom(const asIObjectType *objType) const; - asDWORD GetFlags() const; - asUINT GetSize() const; - int GetTypeId() const; - int GetSubTypeId(asUINT subtypeIndex = 0) const; - asIObjectType *GetSubType(asUINT subtypeIndex = 0) const; - asUINT GetSubTypeCount() const; - - // Interfaces - asUINT GetInterfaceCount() const; - asIObjectType *GetInterface(asUINT index) const; - bool Implements(const asIObjectType *objType) const; - - // Factories + asITypeInfo *GetBaseType() const; + bool DerivesFrom(const asITypeInfo *objType) const; + int GetSubTypeId(asUINT subtypeIndex = 0) const; + asITypeInfo *GetSubType(asUINT subtypeIndex = 0) const; + asUINT GetSubTypeCount() const; + asUINT GetInterfaceCount() const; + asITypeInfo *GetInterface(asUINT index) const; + bool Implements(const asITypeInfo *objType) const; asUINT GetFactoryCount() const; asIScriptFunction *GetFactoryByIndex(asUINT index) const; asIScriptFunction *GetFactoryByDecl(const char *decl) const; - - // Methods asUINT GetMethodCount() const; asIScriptFunction *GetMethodByIndex(asUINT index, bool getVirtual) const; asIScriptFunction *GetMethodByName(const char *name, bool getVirtual) const; asIScriptFunction *GetMethodByDecl(const char *decl, bool getVirtual) const; - - // Properties - asUINT GetPropertyCount() const; - int GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, bool *isProtected, int *offset, bool *isReference, asDWORD *accessMask) const; - const char *GetPropertyDeclaration(asUINT index, bool includeNamespace = false) const; - - // Behaviours + asUINT GetPropertyCount() const; + int GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, bool *isProtected, int *offset, bool *isReference, asDWORD *accessMask, int *compositeOffset, bool *isCompositeIndirect) const; + const char *GetPropertyDeclaration(asUINT index, bool includeNamespace = false) const; asUINT GetBehaviourCount() const; asIScriptFunction *GetBehaviourByIndex(asUINT index, asEBehaviours *outBehaviour) const; + asUINT GetChildFuncdefCount() const; + asITypeInfo *GetChildFuncdef(asUINT index) const; - // User data - void *SetUserData(void *data, asPWORD type); - void *GetUserData(asPWORD type) const; - -//=========================================== -// Internal -//=========================================== public: asCObjectType(asCScriptEngine *engine); ~asCObjectType(); void DestroyInternal(); - // Keep an internal reference counter to separate references coming from - // application or script objects and references coming from the script code - int AddRefInternal(); - int ReleaseInternal(); - void ReleaseAllFunctions(); bool IsInterface() const; - bool IsShared() const; asCObjectProperty *AddPropertyToClass(const asCString &name, const asCDataType &dt, bool isPrivate, bool isProtected, bool isInherited); void ReleaseAllProperties(); - asCString name; - asSNameSpace *nameSpace; - int size; #ifdef WIP_16BYTE_ALIGN int alignment; #endif - mutable int typeId; asCArray properties; asCArray methods; + + // TODO: These are not used by template types. Should perhaps create a derived class to save memory on ordinary object types asCArray interfaces; asCArray interfaceVFTOffsets; - asCArray enumValues; asCObjectType * derivedFrom; asCArray virtualFunctionTable; - asDWORD flags; - asDWORD accessMask; + // Used for funcdefs declared as members of class. + // TODO: child funcdef: Should be possible to enumerate these from application + asCArray childFuncDefs; asSTypeBehaviour beh; // Used for template types - asCArray templateSubTypes; + asCArray templateSubTypes; // increases refCount for typeinfo held in datatype bool acceptValueSubType; bool acceptRefSubType; - // Store the script section where the code was declared - int scriptSectionIdx; - // Store the location where the function was declared (row in the lower 20 bits, and column in the upper 12) - int declaredAt; - - asCScriptEngine *engine; - asCModule *module; - asCArray userData; - protected: friend class asCScriptEngine; friend class asCConfigGroup; friend class asCModule; asCObjectType(); - - mutable asCAtomic externalRefCount; - asCAtomic internalRefCount; }; END_AS_NAMESPACE diff --git a/lib/angelscript/source/as_parser.cpp b/lib/angelscript/source/as_parser.cpp index fca02fe68..1f21bd7d1 100644 --- a/lib/angelscript/source/as_parser.cpp +++ b/lib/angelscript/source/as_parser.cpp @@ -1,24 +1,24 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; you + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product + this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source + 3. This notice may not be removed or altered from any source distribution. The original version of this library can be located at: @@ -35,7 +35,7 @@ // This class parses the script code and builds a tree for compilation // // -// I've documented the syntax in Extended BNF. You'll find it by doing a search in +// I've documented the syntax in Extended BNF. You'll find it by doing a search in // this file by "BNF:". The starting point for the script language is SCRIPT ::=. // // Ref: http://matt.might.net/articles/grammars-bnf-ebnf/ @@ -103,18 +103,18 @@ asCScriptNode *asCParser::GetScriptNode() return scriptNode; } -int asCParser::ParseFunctionDefinition(asCScriptCode *script, bool expectListPattern) +int asCParser::ParseFunctionDefinition(asCScriptCode *in_script, bool in_expectListPattern) { Reset(); // Set flag that permits ? as datatype for parameters isParsingAppInterface = true; - this->script = script; + this->script = in_script; scriptNode = ParseFunctionDefinition(); - if( expectListPattern ) + if( in_expectListPattern ) scriptNode->AddChildLast(ParseListPattern()); // The declaration should end after the definition @@ -149,19 +149,19 @@ asCScriptNode *asCParser::CreateNode(eScriptNode type) return new(ptr) asCScriptNode(type); } -int asCParser::ParseDataType(asCScriptCode *script, bool isReturnType) +int asCParser::ParseDataType(asCScriptCode *in_script, bool in_isReturnType) { Reset(); - this->script = script; + this->script = in_script; scriptNode = CreateNode(snDataType); if( scriptNode == 0 ) return -1; - + scriptNode->AddChildLast(ParseType(true)); if( isSyntaxError ) return -1; - if( isReturnType ) + if( in_isReturnType ) { scriptNode->AddChildLast(ParseTypeMod(false)); if( isSyntaxError ) return -1; @@ -185,11 +185,11 @@ int asCParser::ParseDataType(asCScriptCode *script, bool isReturnType) // Parse a template declaration: IDENTIFIER '<' 'class'? IDENTIFIER '>' -int asCParser::ParseTemplateDecl(asCScriptCode *script) +int asCParser::ParseTemplateDecl(asCScriptCode *in_script) { Reset(); - this->script = script; + this->script = in_script; scriptNode = CreateNode(snUndefined); if( scriptNode == 0 ) return -1; @@ -249,11 +249,11 @@ int asCParser::ParseTemplateDecl(asCScriptCode *script) return 0; } -int asCParser::ParsePropertyDeclaration(asCScriptCode *script) +int asCParser::ParsePropertyDeclaration(asCScriptCode *in_script) { Reset(); - this->script = script; + this->script = in_script; scriptNode = CreateNode(snDeclaration); if( scriptNode == 0 ) return -1; @@ -287,28 +287,79 @@ int asCParser::ParsePropertyDeclaration(asCScriptCode *script) return 0; } -// BNF: SCOPE ::= [[IDENTIFIER] '::' {IDENTIFIER '::'}] +// BNF: SCOPE ::= ['::'] {IDENTIFIER '::'} [IDENTIFIER ['<' TYPE {',' TYPE} '>'] '::'] void asCParser::ParseOptionalScope(asCScriptNode *node) { + asCScriptNode *scope = CreateNode(snScope); + sToken t1, t2; GetToken(&t1); GetToken(&t2); if( t1.type == ttScope ) { RewindTo(&t1); - node->AddChildLast(ParseToken(ttScope)); + scope->AddChildLast(ParseToken(ttScope)); GetToken(&t1); GetToken(&t2); } while( t1.type == ttIdentifier && t2.type == ttScope ) { RewindTo(&t1); - node->AddChildLast(ParseIdentifier()); - node->AddChildLast(ParseToken(ttScope)); + scope->AddChildLast(ParseIdentifier()); + scope->AddChildLast(ParseToken(ttScope)); GetToken(&t1); GetToken(&t2); } + + // The innermost scope may be a template type + if( t1.type == ttIdentifier && t2.type == ttLessThan ) + { + tempString.Assign(&script->code[t1.pos], t1.length); + if (engine->IsTemplateType(tempString.AddressOf())) + { + RewindTo(&t1); + asCScriptNode *restore = scope->lastChild; + scope->AddChildLast(ParseIdentifier()); + if (ParseTemplTypeList(scope, false)) + { + GetToken(&t2); + if (t2.type == ttScope) + { + // Template type is part of the scope + // Nothing more needs to be done + node->AddChildLast(scope); + return; + } + else + { + // The template type is not part of the scope + // Rewind to the template type and end the scope + RewindTo(&t1); + + // Restore the previously parsed node + while (scope->lastChild != restore) + { + asCScriptNode *last = scope->lastChild; + last->DisconnectParent(); + last->Destroy(engine); + } + if( scope->lastChild ) + node->AddChildLast(scope); + else + scope->Destroy(engine); + return; + } + } + } + } + + // The identifier is not part of the scope RewindTo(&t1); + + if (scope->lastChild) + node->AddChildLast(scope); + else + scope->Destroy(engine); } asCScriptNode *asCParser::ParseFunctionDefinition() @@ -369,7 +420,7 @@ asCScriptNode *asCParser::ParseTypeMod(bool isParam) } } - // Parse possible + token + // Parse possible + token GetToken(&t); RewindTo(&t); if( t.type == ttPlus ) @@ -378,6 +429,15 @@ asCScriptNode *asCParser::ParseTypeMod(bool isParam) if( isSyntaxError ) return node; } + // Parse possible if_handle_then_const token + GetToken(&t); + RewindTo(&t); + if (IdentifierIs(t, IF_HANDLE_TOKEN)) + { + node->AddChildLast(ParseToken(ttIdentifier)); + if (isSyntaxError) return node; + } + return node; } @@ -414,41 +474,8 @@ asCScriptNode *asCParser::ParseType(bool allowConst, bool allowVariableType, boo tempString.Assign(&script->code[type->tokenPos], type->tokenLength); if( engine->IsTemplateType(tempString.AddressOf()) && t.type == ttLessThan ) { - GetToken(&t); - if( t.type != ttLessThan ) - { - Error(ExpectedToken(asCTokenizer::GetDefinition(ttLessThan)), &t); - Error(InsteadFound(t), &t); - return node; - } - - node->AddChildLast(ParseType(true, false)); - if( isSyntaxError ) return node; - - GetToken(&t); - - // Parse template types by list separator - while(t.type == ttListSeparator) - { - node->AddChildLast(ParseType(true, false)); - - if( isSyntaxError ) return node; - GetToken(&t); - } - - // Accept >> and >>> tokens too. But then force the tokenizer to move - // only 1 character ahead (thus splitting the token in two). - if( script->code[t.pos] != '>' ) - { - Error(ExpectedToken(asCTokenizer::GetDefinition(ttGreaterThan)), &t); - Error(InsteadFound(t), &t); - return node; - } - else - { - // Break the token so that only the first > is parsed - SetPos(t.pos + 1); - } + ParseTemplTypeList(node); + if (isSyntaxError) return node; } // Parse [] and @ @@ -482,6 +509,82 @@ asCScriptNode *asCParser::ParseType(bool allowConst, bool allowVariableType, boo return node; } +// This parses a template type list, e.g. +// If 'required' is false, and the template type list is not valid, +// then no change will be done and the function returns false. This +// can be used as do an optional parsing +bool asCParser::ParseTemplTypeList(asCScriptNode *node, bool required) +{ + sToken t; + bool isValid = true; + + // Remember the last child, so we can restore the state if needed + asCScriptNode *last = node->lastChild; + + // Starts with '<' + GetToken(&t); + if (t.type != ttLessThan) + { + if (required) + { + Error(ExpectedToken(asCTokenizer::GetDefinition(ttLessThan)), &t); + Error(InsteadFound(t), &t); + } + return false; + } + + // At least one type + // TODO: child funcdef: Make this work with !required + node->AddChildLast(ParseType(true, false)); + if (isSyntaxError) return false; + + GetToken(&t); + + // Parse template types by list separator + while (t.type == ttListSeparator) + { + // TODO: child funcdef: Make this work with !required + node->AddChildLast(ParseType(true, false)); + if (isSyntaxError) return false; + GetToken(&t); + } + + // End with '>' + // Accept >> and >>> tokens too. But then force the tokenizer to move + // only 1 character ahead (thus splitting the token in two). + if (script->code[t.pos] != '>') + { + if (required) + { + Error(ExpectedToken(asCTokenizer::GetDefinition(ttGreaterThan)), &t); + Error(InsteadFound(t), &t); + } + else + isValid = false; + } + else + { + // Break the token so that only the first > is parsed + SetPos(t.pos + 1); + } + + if (!required && !isValid) + { + // Restore the original state before returning + while (node->lastChild != last) + { + asCScriptNode *n = node->lastChild; + n->DisconnectParent(); + n->Destroy(engine); + } + + return false; + } + + // The template type list was parsed OK + return true; +} + asCScriptNode *asCParser::ParseToken(int token) { asCScriptNode *node = CreateNode(snUndefined); @@ -708,7 +811,7 @@ asCScriptNode *asCParser::SuperficiallyParseExpression() asCScriptNode *node = CreateNode(snExpression); if( node == 0 ) return 0; - // Simply parse everything until the first , or ), whichever comes first. + // Simply parse everything until the first , or ), whichever comes first. // Keeping in mind that () and {} can group expressions. sToken start; @@ -839,7 +942,7 @@ void asCParser::GetToken(sToken *token) sourcePos += token->length; } // Filter out whitespace and comments - while( token->type == ttWhiteSpace || + while( token->type == ttWhiteSpace || token->type == ttOnelineComment || token->type == ttMultilineComment ); } @@ -852,8 +955,8 @@ void asCParser::SetPos(size_t pos) void asCParser::RewindTo(const sToken *token) { - // TODO: optimize: Perhaps we can optimize this further by having the parser - // set an explicit return point, after which each token will + // TODO: optimize: Perhaps we can optimize this further by having the parser + // set an explicit return point, after which each token will // be stored. That way not just one token will be reused but // no token will have to be tokenized more than once. @@ -995,10 +1098,13 @@ asCString asCParser::InsteadFound(sToken &t) if( t.type == ttIdentifier ) { asCString id(&script->code[t.pos], t.length); - str.Format(TXT_INSTEAD_FOUND_s, id.AddressOf()); + str.Format(TXT_INSTEAD_FOUND_IDENTIFIER_s, id.AddressOf()); } + else if( t.type >= ttIf ) + str.Format(TXT_INSTEAD_FOUND_KEYWORD_s, asCTokenizer::GetDefinition(t.type)); else str.Format(TXT_INSTEAD_FOUND_s, asCTokenizer::GetDefinition(t.type)); + return str; } @@ -1095,7 +1201,7 @@ asCScriptNode *asCParser::ParseListPattern() bool asCParser::IdentifierIs(const sToken &t, const char *str) { - if( t.type != ttIdentifier ) + if( t.type != ttIdentifier ) return false; return script->TokenEquals(t.pos, t.length, str); @@ -1103,79 +1209,80 @@ bool asCParser::IdentifierIs(const sToken &t, const char *str) #ifndef AS_NO_COMPILER -// This function will return true if the current token is not a template, or if it is and -// the following has a valid syntax for a template type. The source position will be left +// This function will return true if the current token is not a template, or if it is and +// the following has a valid syntax for a template type. The source position will be left // at the first token after the type in case of success -bool asCParser::CheckTemplateType(sToken &t) +bool asCParser::CheckTemplateType(const sToken &t) { // Is this a template type? tempString.Assign(&script->code[t.pos], t.length); if( engine->IsTemplateType(tempString.AddressOf()) ) { // If the next token is a < then parse the sub-type too - GetToken(&t); - if( t.type != ttLessThan ) + sToken t1; + GetToken(&t1); + if( t1.type != ttLessThan ) { - RewindTo(&t); + RewindTo(&t1); return true; } for(;;) { // There might optionally be a 'const' - GetToken(&t); - if( t.type == ttConst ) - GetToken(&t); + GetToken(&t1); + if( t1.type == ttConst ) + GetToken(&t1); // The type may be initiated with the scope operator - if( t.type == ttScope ) - GetToken(&t); + if( t1.type == ttScope ) + GetToken(&t1); // There may be multiple levels of scope operators sToken t2; GetToken(&t2); - while( t.type == ttIdentifier && t2.type == ttScope ) + while( t1.type == ttIdentifier && t2.type == ttScope ) { - GetToken(&t); + GetToken(&t1); GetToken(&t2); } RewindTo(&t2); // Now there must be a data type - if( !IsDataType(t) ) + if( !IsDataType(t1) ) return false; - if( !CheckTemplateType(t) ) + if( !CheckTemplateType(t1) ) return false; - GetToken(&t); + GetToken(&t1); // Is it a handle or array? - while( t.type == ttHandle || t.type == ttOpenBracket ) + while( t1.type == ttHandle || t1.type == ttOpenBracket ) { - if( t.type == ttOpenBracket ) + if( t1.type == ttOpenBracket ) { - GetToken(&t); - if( t.type != ttCloseBracket ) + GetToken(&t1); + if( t1.type != ttCloseBracket ) return false; } - GetToken(&t); + GetToken(&t1); } // Was this the last template subtype? - if( t.type != ttListSeparator ) + if( t1.type != ttListSeparator ) break; } - // Accept >> and >>> tokens too. But then force the tokenizer to move + // Accept >> and >>> tokens too. But then force the tokenizer to move // only 1 character ahead (thus splitting the token in two). - if( script->code[t.pos] != '>' ) + if( script->code[t1.pos] != '>' ) return false; - else if( t.length != 1 ) + else if( t1.length != 1 ) { // We need to break the token, so that only the first character is parsed - SetPos(t.pos + 1); + SetPos(t1.pos + 1); } } @@ -1279,7 +1386,7 @@ asCScriptNode *asCParser::ParseExprValue() GetToken(&t); if( t.type == ttScope ) GetToken(&t); - else + else break; } @@ -1294,13 +1401,14 @@ asCScriptNode *asCParser::ParseExprValue() } GetToken(&t2); - + // Rewind so the real parsing can be done, after deciding what to parse RewindTo(&t1); // Check if this is a construct call - if( isDataType && (t.type == ttOpenParanthesis || // type() - (t.type == ttOpenBracket && t2.type == ttCloseBracket)) ) // type[]() + // Just 'type()' isn't considered a construct call, because type may just be a function/method name. + // The compiler will have to sort this out, since the parser doesn't have enough information. + if( isDataType && (t.type == ttOpenBracket && t2.type == ttCloseBracket) ) // type[]() node->AddChildLast(ParseConstructCall()); else if( isTemplateType && t.type == ttLessThan ) // type() node->AddChildLast(ParseConstructCall()); @@ -1446,7 +1554,7 @@ asCScriptNode *asCParser::ParseLambda() return node; } - // We should just find the end of the statement block here. The statements + // We should just find the end of the statement block here. The statements // will be parsed on request by the compiler once it starts the compilation. node->AddChildLast(SuperficiallyParseStatementBlock()); @@ -1613,7 +1721,7 @@ asCScriptNode *asCParser::ParseArgList(bool withParenthesis) Error(InsteadFound(t1), &t1); } } - else + else RewindTo(&t1); return node; @@ -1642,7 +1750,11 @@ bool asCParser::IsFunctionCall() } // A function call starts with an identifier followed by an argument list - if( t1.type != ttIdentifier || IsDataType(t1) ) + // The parser doesn't have enough information about scope to determine if the + // identifier is a datatype, so even if it happens to be the parser will + // identify the expression as a function call rather than a construct call. + // The compiler will sort this out later + if( t1.type != ttIdentifier ) { RewindTo(&s); return false; @@ -1716,35 +1828,12 @@ asCScriptNode *asCParser::ParseCondition() return node; } -// BNF: EXPR ::= (TYPE '=' INITLIST) | (EXPRTERM {EXPROP EXPRTERM}) +// BNF: EXPR ::= EXPRTERM {EXPROP EXPRTERM} asCScriptNode *asCParser::ParseExpression() { asCScriptNode *node = CreateNode(snExpression); if( node == 0 ) return 0; - // Check if the expression is a initialization of a temp object with init list, i.e. type = {...} - sToken t; - GetToken(&t); - sToken t2 = t, t3; - if( IsDataType(t2) && CheckTemplateType(t2) ) - { - // The next token must be a = followed by a { - GetToken(&t2); - GetToken(&t3); - if( t2.type == ttAssignment && t3.type == ttStartStatementBlock ) - { - // It is an initialization, now parse it for real - RewindTo(&t); - node->AddChildLast(ParseType(false)); - GetToken(&t2); - node->AddChildLast(ParseInitList()); - return node; - } - } - - // It wasn't an initialization, so it must be an ordinary expression - RewindTo(&t); - node->AddChildLast(ParseExprTerm()); if( isSyntaxError ) return node; @@ -1766,15 +1855,44 @@ asCScriptNode *asCParser::ParseExpression() UNREACHABLE_RETURN; } -// BNF: EXPRTERM ::= {EXPRPREOP} EXPRVALUE {EXPRPOSTOP} +// BNF: EXPRTERM ::= ([TYPE '='] INITLIST) | ({EXPRPREOP} EXPRVALUE {EXPRPOSTOP}) asCScriptNode *asCParser::ParseExprTerm() { asCScriptNode *node = CreateNode(snExprTerm); if( node == 0 ) return 0; + // Check if the expression term is an initialization of a temp object with init list, i.e. type = {...} + sToken t; + GetToken(&t); + sToken t2 = t, t3; + if (IsDataType(t2) && CheckTemplateType(t2)) + { + // The next token must be a = followed by a { + GetToken(&t2); + GetToken(&t3); + if (t2.type == ttAssignment && t3.type == ttStartStatementBlock) + { + // It is an initialization, now parse it for real + RewindTo(&t); + node->AddChildLast(ParseType(false)); + GetToken(&t2); + node->AddChildLast(ParseInitList()); + return node; + } + } + // Or an anonymous init list, i.e. {...} + else if( t.type == ttStartStatementBlock ) + { + RewindTo(&t); + node->AddChildLast(ParseInitList()); + return node; + } + + // It wasn't an initialization, so it must be an ordinary expression term + RewindTo(&t); + for(;;) { - sToken t; GetToken(&t); RewindTo(&t); if( !IsPreOperator(t.type) ) @@ -1787,10 +1905,9 @@ asCScriptNode *asCParser::ParseExprTerm() node->AddChildLast(ParseExprValue()); if( isSyntaxError ) return node; - + for(;;) { - sToken t; GetToken(&t); RewindTo(&t); if( !IsPostOperator(t.type) ) @@ -1900,7 +2017,7 @@ asCScriptNode *asCParser::ParseExprOperator() return node; } -// BNF: ASSIGNOP ::= '=' | '+=' | '-=' | '*=' | '/=' | '|=' | '&=' | '^=' | '%=' | '**=' | '<<=' | '>>=' | '>>>=' +// BNF: ASSIGNOP ::= '=' | '+=' | '-=' | '*=' | '/=' | '|=' | '&=' | '^=' | '%=' | '**=' | '<<=' | '>>=' | '>>>=' asCScriptNode *asCParser::ParseAssignOperator() { asCScriptNode *node = CreateNode(snExprOperator); @@ -2012,18 +2129,18 @@ bool asCParser::IsConstant(int tokenType) return false; } -int asCParser::ParseScript(asCScriptCode *script) +int asCParser::ParseScript(asCScriptCode *in_script) { Reset(); - this->script = script; + this->script = in_script; scriptNode = ParseScript(false); if( errorWhileParsing ) return -1; - // TODO: Should allow application to request this warning to be generated. + // TODO: Should allow application to request this warning to be generated. // It should be off by default, since pre-processor may remove all // code from a section while still being meant as valid code /* @@ -2037,11 +2154,11 @@ int asCParser::ParseScript(asCScriptCode *script) return 0; } -int asCParser::ParseExpression(asCScriptCode *script) +int asCParser::ParseExpression(asCScriptCode *in_script) { Reset(); - this->script = script; + this->script = in_script; checkValidTypes = true; @@ -2127,29 +2244,33 @@ asCScriptNode *asCParser::ParseScript(bool inBlock) if( node == 0 ) return 0; // Determine type of node - sToken t1, t2; - for(;;) { while( !isSyntaxError ) { - GetToken(&t1); - GetToken(&t2); - RewindTo(&t1); + sToken tStart; + GetToken(&tStart); + + // Optimize by skipping tokens 'shared', 'external', 'final', 'abstract' so they don't have to be checked in every condition + sToken t1 = tStart; + while (IdentifierIs(t1, SHARED_TOKEN) || + IdentifierIs(t1, EXTERNAL_TOKEN) || + IdentifierIs(t1, FINAL_TOKEN) || + IdentifierIs(t1, ABSTRACT_TOKEN)) + GetToken(&t1); + RewindTo(&tStart); if( t1.type == ttImport ) node->AddChildLast(ParseImport()); - else if( t1.type == ttEnum || (IdentifierIs(t1, SHARED_TOKEN) && t2.type == ttEnum) ) + else if( t1.type == ttEnum ) node->AddChildLast(ParseEnumeration()); // Handle enumerations else if( t1.type == ttTypedef ) node->AddChildLast(ParseTypedef()); // Handle primitive typedefs - else if( t1.type == ttClass || - ((IdentifierIs(t1, SHARED_TOKEN) || IdentifierIs(t1, FINAL_TOKEN) || IdentifierIs(t1, ABSTRACT_TOKEN)) && t2.type == ttClass) || - (IdentifierIs(t1, SHARED_TOKEN) && (IdentifierIs(t2, FINAL_TOKEN) || IdentifierIs(t2, ABSTRACT_TOKEN))) ) + else if( t1.type == ttClass ) node->AddChildLast(ParseClass()); else if( t1.type == ttMixin ) node->AddChildLast(ParseMixin()); - else if( t1.type == ttInterface || (t1.type == ttIdentifier && t2.type == ttInterface) ) + else if( t1.type == ttInterface ) node->AddChildLast(ParseInterface()); else if( t1.type == ttFuncDef ) node->AddChildLast(ParseFuncDef()); @@ -2188,6 +2309,7 @@ asCScriptNode *asCParser::ParseScript(bool inBlock) if( isSyntaxError ) { // Search for either ';' or '{' or end + sToken t1; GetToken(&t1); while( t1.type != ttEndStatement && t1.type != ttEnd && t1.type != ttStartStatementBlock ) @@ -2269,7 +2391,7 @@ asCScriptNode *asCParser::ParseNamespace() return node; } -int asCParser::ParseStatementBlock(asCScriptCode *script, asCScriptNode *block) +int asCParser::ParseStatementBlock(asCScriptCode *in_script, asCScriptNode *in_block) { TimeIt("asCParser::ParseStatementBlock"); @@ -2278,8 +2400,8 @@ int asCParser::ParseStatementBlock(asCScriptCode *script, asCScriptNode *block) // Tell the parser to validate the identifiers as valid types checkValidTypes = true; - this->script = script; - sourcePos = block->tokenPos; + this->script = in_script; + sourcePos = in_block->tokenPos; scriptNode = ParseStatementBlock(); @@ -2289,7 +2411,7 @@ int asCParser::ParseStatementBlock(asCScriptCode *script, asCScriptNode *block) return 0; } -// BNF: ENUM ::= ['shared'] 'enum' IDENTIFIER '{' IDENTIFIER ['=' EXPR] {',' IDENTIFIER ['=' EXPR]} '}' +// BNF: ENUM ::= {'shared' | 'external'} 'enum' IDENTIFIER (';' | ('{' IDENTIFIER ['=' EXPR] {',' IDENTIFIER ['=' EXPR]} '}')) asCScriptNode *asCParser::ParseEnumeration() { asCScriptNode *ident; @@ -2298,12 +2420,13 @@ asCScriptNode *asCParser::ParseEnumeration() asCScriptNode *node = CreateNode(snEnum); if( node == 0 ) return 0; - sToken token; + sToken token; - // Optional 'shared' token + // Optional 'shared' and 'external' token GetToken(&token); - if( IdentifierIs(token, SHARED_TOKEN) ) - { + while( IdentifierIs(token, SHARED_TOKEN) || + IdentifierIs(token, EXTERNAL_TOKEN) ) + { RewindTo(&token); node->AddChildLast(ParseIdentifier()); if( isSyntaxError ) return node; @@ -2324,7 +2447,7 @@ asCScriptNode *asCParser::ParseEnumeration() // Get the identifier GetToken(&token); - if(ttIdentifier != token.type) + if(ttIdentifier != token.type) { Error(TXT_EXPECTED_IDENTIFIER, &token); Error(InsteadFound(token), &token); @@ -2332,47 +2455,56 @@ asCScriptNode *asCParser::ParseEnumeration() } dataType = CreateNode(snDataType); - if( dataType == 0 ) return 0; + if( dataType == 0 ) return node; node->AddChildLast(dataType); ident = CreateNode(snIdentifier); - if( ident == 0 ) return 0; + if( ident == 0 ) return node; ident->SetToken(&token); ident->UpdateSourcePos(token.pos, token.length); dataType->AddChildLast(ident); - // check for the start of the declaration block + // External shared declarations are ended with ';' GetToken(&token); - if( token.type != ttStartStatementBlock ) + if (token.type == ttEndStatement) { RewindTo(&token); - Error(ExpectedToken(asCTokenizer::GetDefinition(token.type)), &token); + node->AddChildLast(ParseToken(ttEndStatement)); + return node; + } + + // check for the start of the declaration block + if( token.type != ttStartStatementBlock ) + { + RewindTo(&token); + int tokens[] = { ttStartStatementBlock, ttEndStatement }; + Error(ExpectedOneOf(tokens, 2), &token); Error(InsteadFound(token), &token); return node; } - while(ttEnd != token.type) + while(ttEnd != token.type) { GetToken(&token); - if( ttEndStatementBlock == token.type ) + if( ttEndStatementBlock == token.type ) { RewindTo(&token); break; } - if(ttIdentifier != token.type) + if(ttIdentifier != token.type) { Error(TXT_EXPECTED_IDENTIFIER, &token); Error(InsteadFound(token), &token); return node; } - // Add the enum element + // Add the enum element ident = CreateNode(snIdentifier); - if( ident == 0 ) return 0; + if( ident == 0 ) return node; ident->SetToken(&token); ident->UpdateSourcePos(token.pos, token.length); @@ -2393,16 +2525,16 @@ asCScriptNode *asCParser::ParseEnumeration() GetToken(&token); } - if(ttListSeparator != token.type) + if(ttListSeparator != token.type) { RewindTo(&token); break; } } - // check for the end of the declaration block + // check for the end of the declaration block GetToken(&token); - if( token.type != ttEndStatementBlock ) + if( token.type != ttEndStatementBlock ) { RewindTo(&token); Error(ExpectedToken("}"), &token); @@ -2410,7 +2542,6 @@ asCScriptNode *asCParser::ParseEnumeration() return node; } - // Parse the declarations return node; } @@ -2441,10 +2572,32 @@ bool asCParser::IsVarDecl() // The type may be preceeded with a multilevel scope GetToken(&t2); - while( t1.type == ttIdentifier && t2.type == ttScope ) + while( t1.type == ttIdentifier ) { - GetToken(&t1); - GetToken(&t2); + if (t2.type == ttScope) + { + GetToken(&t1); + GetToken(&t2); + continue; + } + else if(t2.type == ttLessThan) + { + // Template types can also be used as scope identifiers + RewindTo(&t2); + if (CheckTemplateType(t1)) + { + sToken t3; + GetToken(&t3); + if (t3.type == ttScope) + { + GetToken(&t1); + GetToken(&t2); + continue; + } + } + } + + break; } RewindTo(&t2); } @@ -2466,7 +2619,7 @@ bool asCParser::IsVarDecl() } // Object handles can be interleaved with the array brackets - // Even though declaring variables with & is invalid we'll accept + // Even though declaring variables with & is invalid we'll accept // it here to give an appropriate error message later GetToken(&t2); while( t2.type == ttHandle || t2.type == ttAmp || t2.type == ttOpenBracket ) @@ -2496,9 +2649,9 @@ bool asCParser::IsVarDecl() RewindTo(&t); return true; } - if( t2.type == ttOpenParanthesis ) - { - // If the closing paranthesis is followed by a statement + if( t2.type == ttOpenParanthesis ) + { + // If the closing paranthesis is followed by a statement // block or end-of-file, then treat it as a function. A // function decl may have nested paranthesis so we need to // check for this too. @@ -2516,8 +2669,11 @@ bool asCParser::IsVarDecl() GetToken(&t2); } - if( t2.type == ttEnd ) + if (t2.type == ttEnd) + { + RewindTo(&t); return false; + } else { GetToken(&t1); @@ -2527,7 +2683,6 @@ bool asCParser::IsVarDecl() } RewindTo(&t); - return true; } @@ -2713,10 +2868,10 @@ bool asCParser::IsFuncDecl(bool isMethod) } GetToken(&t2); - if( t2.type == ttOpenParanthesis ) - { - // If the closing parenthesis is not followed by a - // statement block then it is not a function. + if( t2.type == ttOpenParanthesis ) + { + // If the closing parenthesis is not followed by a + // statement block then it is not a function. // It's possible that there are nested parenthesis due to default // arguments so this should be checked for. int nest = 0; @@ -2741,7 +2896,7 @@ bool asCParser::IsFuncDecl(bool isMethod) GetToken(&t1); if( t1.type != ttConst ) RewindTo(&t1); - + // A class method may also have any number of additional inheritance behavior specifiers for( ; ; ) { @@ -2768,14 +2923,25 @@ bool asCParser::IsFuncDecl(bool isMethod) return false; } -// BNF: FUNCDEF ::= 'funcdef' TYPE ['&'] IDENTIFIER PARAMLIST ';' +// BNF: FUNCDEF ::= {'external' | 'shared'} 'funcdef' TYPE ['&'] IDENTIFIER PARAMLIST ';' asCScriptNode *asCParser::ParseFuncDef() { asCScriptNode *node = CreateNode(snFuncDef); if( node == 0 ) return 0; + // Allow keywords 'external' and 'shared' before 'interface' sToken t1; GetToken(&t1); + while (IdentifierIs(t1, SHARED_TOKEN) || + IdentifierIs(t1, EXTERNAL_TOKEN)) + { + RewindTo(&t1); + node->AddChildLast(ParseIdentifier()); + if (isSyntaxError) return node; + + GetToken(&t1); + } + if( t1.type != ttFuncDef ) { Error(asCTokenizer::GetDefinition(ttFuncDef), &t1); @@ -2809,32 +2975,52 @@ asCScriptNode *asCParser::ParseFuncDef() return node; } -// BNF: FUNC ::= ['private' | 'protected' | 'shared'] [((TYPE ['&']) | '~')] IDENTIFIER PARAMLIST ['const'] {'override' | 'final'} STATBLOCK +// BNF: FUNC ::= {'shared' | 'external'} ['private' | 'protected'] [((TYPE ['&']) | '~')] IDENTIFIER PARAMLIST ['const'] {'override' | 'final'} (';' | STATBLOCK) asCScriptNode *asCParser::ParseFunction(bool isMethod) { asCScriptNode *node = CreateNode(snFunction); if( node == 0 ) return 0; - sToken t1,t2; + sToken t1; GetToken(&t1); - GetToken(&t2); - RewindTo(&t1); - - // A class method can start with 'private' or 'protected' - if( isMethod && t1.type == ttPrivate ) - node->AddChildLast(ParseToken(ttPrivate)); - else if( isMethod && t1.type == ttProtected ) - node->AddChildLast(ParseToken(ttProtected)); - if( isSyntaxError ) return node; - - // A global function can be marked as shared - if( !isMethod && IdentifierIs(t1, SHARED_TOKEN) ) + if (!isMethod) { - node->AddChildLast(ParseIdentifier()); - if( isSyntaxError ) return node; + // A global function can be marked as shared and external + while (t1.type == ttIdentifier) + { + if (IdentifierIs(t1, SHARED_TOKEN) || + IdentifierIs(t1, EXTERNAL_TOKEN)) + { + RewindTo(&t1); + node->AddChildLast(ParseIdentifier()); + if (isSyntaxError) return node; + } + else + break; + + GetToken(&t1); + } } + // A class method can start with 'private' or 'protected' + if (isMethod && t1.type == ttPrivate) + { + RewindTo(&t1); + node->AddChildLast(ParseToken(ttPrivate)); + GetToken(&t1); + } + else if (isMethod && t1.type == ttProtected) + { + RewindTo(&t1); + node->AddChildLast(ParseToken(ttProtected)); + GetToken(&t1); + } + if( isSyntaxError ) return node; + // If it is a global function, or a method, except constructor and destructor, then the return type is parsed + sToken t2; + GetToken(&t2); + RewindTo(&t1); if( !isMethod || (t1.type != ttBitNot && t2.type != ttOpenParanthesis) ) { node->AddChildLast(ParseType(true)); @@ -2871,7 +3057,16 @@ asCScriptNode *asCParser::ParseFunction(bool isMethod) if( isSyntaxError ) return node; } - // We should just find the end of the statement block here. The statements + // External shared functions must be ended with ';' + GetToken(&t1); + RewindTo(&t1); + if (t1.type == ttEndStatement) + { + node->AddChildLast(ParseToken(ttEndStatement)); + return node; + } + + // We should just find the end of the statement block here. The statements // will be parsed on request by the compiler once it starts the compilation. node->AddChildLast(SuperficiallyParseStatementBlock()); @@ -2965,7 +3160,7 @@ asCScriptNode *asCParser::ParseVirtualPropertyDecl(bool isMethod, bool isInterfa RewindTo(&t1); accessorNode->AddChildLast(ParseIdentifier()); - + if( isMethod ) { GetToken(&t1); @@ -3021,28 +3216,23 @@ asCScriptNode *asCParser::ParseVirtualPropertyDecl(bool isMethod, bool isInterfa return node; } -// BNF: INTERFACE ::= ['shared'] 'interface' IDENTIFIER [':' IDENTIFIER {',' IDENTIFIER}] '{' {VIRTPROP | INTFMTHD} '}' +// BNF: INTERFACE ::= {'external' | 'shared'} 'interface' IDENTIFIER (';' | ([':' IDENTIFIER {',' IDENTIFIER}] '{' {VIRTPROP | INTFMTHD} '}')) asCScriptNode *asCParser::ParseInterface() { asCScriptNode *node = CreateNode(snInterface); if( node == 0 ) return 0; sToken t; + + // Allow keywords 'external' and 'shared' before 'interface' GetToken(&t); - - // Allow keyword 'shared' before 'interface' - if( t.type == ttIdentifier ) + while( IdentifierIs(t, SHARED_TOKEN) || + IdentifierIs(t, EXTERNAL_TOKEN) ) { - tempString.Assign(&script->code[t.pos], t.length); - if( tempString != SHARED_TOKEN ) - { - Error(ExpectedToken(SHARED_TOKEN), &t); - Error(InsteadFound(t), &t); - return node; - } - RewindTo(&t); node->AddChildLast(ParseIdentifier()); + if (isSyntaxError) return node; + GetToken(&t); } @@ -3054,11 +3244,18 @@ asCScriptNode *asCParser::ParseInterface() } node->SetToken(&t); - node->AddChildLast(ParseIdentifier()); - // Can optionally have a list of interfaces that are inherited + // External shared declarations are ended with ';' GetToken(&t); + if (t.type == ttEndStatement) + { + RewindTo(&t); + node->AddChildLast(ParseToken(ttEndStatement)); + return node; + } + + // Can optionally have a list of interfaces that are inherited if( t.type == ttColon ) { asCScriptNode *inherit = CreateNode(snIdentifier); @@ -3100,7 +3297,7 @@ asCScriptNode *asCParser::ParseInterface() node->AddChildLast(ParseInterfaceMethod()); if( isSyntaxError ) return node; - + GetToken(&t); RewindTo(&t); } @@ -3142,7 +3339,7 @@ asCScriptNode *asCParser::ParseMixin() return node; } -// BNF: CLASS ::= {'shared' | 'abstract' | 'final'} 'class' IDENTIFIER [':' IDENTIFIER {',' IDENTIFIER}] '{' {VIRTPROP | FUNC | VAR} '}' +// BNF: CLASS ::= {'shared' | 'abstract' | 'final' | 'external'} 'class' IDENTIFIER (';' | ([':' IDENTIFIER {',' IDENTIFIER}] '{' {VIRTPROP | FUNC | VAR | FUNCDEF} '}')) asCScriptNode *asCParser::ParseClass() { asCScriptNode *node = CreateNode(snClass); @@ -3151,10 +3348,11 @@ asCScriptNode *asCParser::ParseClass() sToken t; GetToken(&t); - // Allow the keywords 'shared', 'abstract', and 'final' before 'class' + // Allow the keywords 'shared', 'abstract', 'final', and 'external' before 'class' while( IdentifierIs(t, SHARED_TOKEN) || IdentifierIs(t, ABSTRACT_TOKEN) || - IdentifierIs(t, FINAL_TOKEN) ) + IdentifierIs(t, FINAL_TOKEN) || + IdentifierIs(t, EXTERNAL_TOKEN) ) { RewindTo(&t); node->AddChildLast(ParseIdentifier()); @@ -3174,7 +3372,7 @@ asCScriptNode *asCParser::ParseClass() { // Parse 'implicit handle class' construct GetToken(&t); - + if ( t.type == ttHandle ) node->SetToken(&t); else @@ -3183,7 +3381,14 @@ asCScriptNode *asCParser::ParseClass() node->AddChildLast(ParseIdentifier()); + // External shared declarations are ended with ';' GetToken(&t); + if (t.type == ttEndStatement) + { + RewindTo(&t); + node->AddChildLast(ParseToken(ttEndStatement)); + return node; + } // Optional list of interfaces that are being implemented and classes that are being inherited if( t.type == ttColon ) @@ -3218,7 +3423,9 @@ asCScriptNode *asCParser::ParseClass() while( t.type != ttEndStatementBlock && t.type != ttEnd ) { // Is it a property or a method? - if( IsFuncDecl(true) ) + if (t.type == ttFuncDef) + node->AddChildLast(ParseFuncDef()); + else if( IsFuncDecl(true) ) node->AddChildLast(ParseFunction(true)); else if( IsVirtualPropertyDecl() ) node->AddChildLast(ParseVirtualPropertyDecl(true, false)); @@ -3227,7 +3434,7 @@ asCScriptNode *asCParser::ParseClass() else if( t.type == ttEndStatement ) // Skip empty declarations GetToken(&t); - else + else { Error(TXT_EXPECTED_METHOD_OR_PROPERTY, &t); Error(InsteadFound(t), &t); @@ -3253,15 +3460,15 @@ asCScriptNode *asCParser::ParseClass() return node; } -int asCParser::ParseVarInit(asCScriptCode *script, asCScriptNode *init) +int asCParser::ParseVarInit(asCScriptCode *in_script, asCScriptNode *in_init) { Reset(); // Tell the parser to validate the identifiers as valid types checkValidTypes = true; - this->script = script; - sourcePos = init->tokenPos; + this->script = in_script; + sourcePos = in_init->tokenPos; // If next token is assignment, parse expression sToken t; @@ -3275,7 +3482,7 @@ int asCParser::ParseVarInit(asCScriptCode *script, asCScriptNode *init) else scriptNode = ParseAssignment(); } - else if( t.type == ttOpenParanthesis ) + else if( t.type == ttOpenParanthesis ) { RewindTo(&t); scriptNode = ParseArgList(); @@ -3545,10 +3752,10 @@ asCScriptNode *asCParser::ParseInitList() GetToken(&t1); if( t1.type == ttListSeparator ) { - // No expression + // No expression node->AddChildLast(CreateNode(snUndefined)); node->lastChild->UpdateSourcePos(t1.pos, 1); - + GetToken(&t1); if( t1.type == ttEndStatementBlock ) { @@ -3562,7 +3769,7 @@ asCScriptNode *asCParser::ParseInitList() } else if( t1.type == ttEndStatementBlock ) { - // No expression + // No expression node->AddChildLast(CreateNode(snUndefined)); node->lastChild->UpdateSourcePos(t1.pos, 1); node->UpdateSourcePos(t1.pos, t1.length); @@ -3637,7 +3844,7 @@ asCScriptNode *asCParser::ParseDeclaration(bool isClassProp, bool isGlobalVar) node->AddChildLast(ParseToken(ttPrivate)); else if( t.type == ttProtected && isClassProp ) node->AddChildLast(ParseToken(ttProtected)); - + // Parse data type node->AddChildLast(ParseType(true, false, !isClassProp)); if( isSyntaxError ) return node; @@ -3821,11 +4028,11 @@ asCScriptNode *asCParser::ParseSwitch() Error(InsteadFound(t), &t); return node; } - + while( !isSyntaxError ) { GetToken(&t); - + if( t.type == ttEndStatementBlock ) break; @@ -3886,9 +4093,9 @@ asCScriptNode *asCParser::ParseCase() // Parse statements until we find either of }, case, default, and break GetToken(&t); RewindTo(&t); - while( t.type != ttCase && - t.type != ttDefault && - t.type != ttEndStatementBlock && + while( t.type != ttCase && + t.type != ttDefault && + t.type != ttEndStatementBlock && t.type != ttBreak ) { if( IsVarDecl() ) @@ -4025,7 +4232,7 @@ asCScriptNode *asCParser::ParseFor() } node->AddChildLast(ParseStatement()); - + return node; } @@ -4246,7 +4453,7 @@ asCScriptNode *asCParser::ParseTypedef() Error(InsteadFound(token), &token); return node; } - + node->SetToken(&token); node->UpdateSourcePos(token.pos, token.length); @@ -4268,7 +4475,7 @@ asCScriptNode *asCParser::ParseTypedef() // Check for the end of the typedef GetToken(&token); - if( token.type != ttEndStatement ) + if( token.type != ttEndStatement ) { RewindTo(&token); Error(ExpectedToken(asCTokenizer::GetDefinition(token.type)), &token); diff --git a/lib/angelscript/source/as_parser.h b/lib/angelscript/source/as_parser.h index 06fd93ff8..0f08368b2 100644 --- a/lib/angelscript/source/as_parser.h +++ b/lib/angelscript/source/as_parser.h @@ -1,24 +1,24 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; you + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product + this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source + 3. This notice may not be removed or altered from any source distribution. The original version of this library can be located at: @@ -66,7 +66,7 @@ public: int ParseVarInit(asCScriptCode *script, asCScriptNode *init); int ParseExpression(asCScriptCode *script); #endif - + asCScriptNode *GetScriptNode(); protected: @@ -90,6 +90,7 @@ protected: asCScriptNode *ParseRealType(); asCScriptNode *ParseDataType(bool allowVariableType = false, bool allowAuto = false); asCScriptNode *ParseIdentifier(); + bool ParseTemplTypeList(asCScriptNode *node, bool required = true); asCScriptNode *ParseListPattern(); @@ -161,7 +162,7 @@ protected: bool IsPostOperator(int tokenType); bool IsAssignOperator(int tokenType); - bool CheckTemplateType(sToken &t); + bool CheckTemplateType(const sToken &t); #endif asCScriptNode *ParseToken(int token); diff --git a/lib/angelscript/source/as_property.h b/lib/angelscript/source/as_property.h index 983ee644f..c318ec4a3 100644 --- a/lib/angelscript/source/as_property.h +++ b/lib/angelscript/source/as_property.h @@ -1,24 +1,24 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; you + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product + this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source + 3. This notice may not be removed or altered from any source distribution. The original version of this library can be located at: @@ -53,12 +53,14 @@ struct asSNameSpace; class asCObjectProperty { public: - asCObjectProperty() {accessMask = 0xFFFFFFFF;} - asCObjectProperty(const asCObjectProperty &o) : name(o.name), type(o.type), byteOffset(o.byteOffset), accessMask(o.accessMask), isPrivate(o.isPrivate), isProtected(o.isProtected), isInherited(o.isInherited) {} + asCObjectProperty() : byteOffset(0), accessMask(0xFFFFFFFF), compositeOffset(0), isCompositeIndirect(false), isPrivate(false), isProtected(false), isInherited(false) {} + asCObjectProperty(const asCObjectProperty &o) : name(o.name), type(o.type), byteOffset(o.byteOffset), accessMask(o.accessMask), compositeOffset(o.compositeOffset), isCompositeIndirect(o.isCompositeIndirect), isPrivate(o.isPrivate), isProtected(o.isProtected), isInherited(o.isInherited) {} asCString name; asCDataType type; int byteOffset; asDWORD accessMask; + int compositeOffset; + bool isCompositeIndirect; bool isPrivate; bool isProtected; bool isInherited; diff --git a/lib/angelscript/source/as_restore.cpp b/lib/angelscript/source/as_restore.cpp index 4e13157b8..6beda7cec 100644 --- a/lib/angelscript/source/as_restore.cpp +++ b/lib/angelscript/source/as_restore.cpp @@ -1,24 +1,24 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; you + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product + this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source + 3. This notice may not be removed or altered from any source distribution. The original version of this library can be located at: @@ -44,6 +44,10 @@ BEGIN_AS_NAMESPACE +// Macros for doing endianess agnostic bitmask serialization +#define SAVE_TO_BIT(dst, val, bit) ((dst) |= ((val) << (bit))) +#define LOAD_FROM_BIT(dst, val, bit) ((dst) = ((val) >> (bit)) & 1) + asCReader::asCReader(asCModule* _module, asIBinaryStream* _stream, asCScriptEngine* _engine) : module(_module), stream(_stream), engine(_engine) { @@ -51,24 +55,28 @@ asCReader::asCReader(asCModule* _module, asIBinaryStream* _stream, asCScriptEngi bytesRead = 0; } -void asCReader::ReadData(void *data, asUINT size) +int asCReader::ReadData(void *data, asUINT size) { asASSERT(size == 1 || size == 2 || size == 4 || size == 8); + int ret = 0; #if defined(AS_BIG_ENDIAN) - for( asUINT n = 0; n < size; n++ ) - stream->Read(((asBYTE*)data)+n, 1); + for( asUINT n = 0; ret >= 0 && n < size; n++ ) + ret = stream->Read(((asBYTE*)data)+n, 1); #else - for( int n = size-1; n >= 0; n-- ) - stream->Read(((asBYTE*)data)+n, 1); + for( int n = size-1; ret >= 0 && n >= 0; n-- ) + ret = stream->Read(((asBYTE*)data)+n, 1); #endif + if (ret < 0) + Error(TXT_UNEXPECTED_END_OF_FILE); bytesRead += size; + return ret; } int asCReader::Read(bool *wasDebugInfoStripped) { TimeIt("asCReader::Read"); - // Before starting the load, make sure that + // Before starting the load, make sure that // any existing resources have been freed module->InternalReset(); @@ -108,6 +116,11 @@ int asCReader::Read(bool *wasDebugInfoStripped) *wasDebugInfoStripped = noDebugInfo; } + // Clean up the loaded string constants + for (asUINT n = 0; n < usedStringConstants.GetLength(); n++) + engine->stringFactory->ReleaseStringConstant(usedStringConstants[n]); + usedStringConstants.SetLength(0); + return r; } @@ -125,12 +138,12 @@ int asCReader::Error(const char *msg) return asERROR; } -int asCReader::ReadInner() +int asCReader::ReadInner() { TimeIt("asCReader::ReadInner"); // This function will load each entity one by one from the stream. - // If any error occurs, it will return to the caller who is + // If any error occurs, it will return to the caller who is // responsible for cleaning up the partially loaded entities. engine->deferValidationOfTemplateTypes = true; @@ -138,61 +151,77 @@ int asCReader::ReadInner() unsigned long i, count; asCScriptFunction* func; - ReadData(&noDebugInfo, 1); + // Read the flag as 1 byte even on platforms with 4byte booleans + noDebugInfo = ReadEncodedUInt() ? VALUE_OF_BOOLEAN_TRUE : 0; // Read enums count = ReadEncodedUInt(); module->enumTypes.Allocate(count, false); for( i = 0; i < count && !error; i++ ) { - asCObjectType *ot = asNEW(asCObjectType)(engine); - if( ot == 0 ) + asCEnumType *et = asNEW(asCEnumType)(engine); + if( et == 0 ) { error = true; return asOUT_OF_MEMORY; } - ReadObjectTypeDeclaration(ot, 1); + bool isExternal = false; + ReadTypeDeclaration(et, 1, &isExternal); // If the type is shared then we should use the original if it exists bool sharedExists = false; - if( ot->IsShared() ) + if( et->IsShared() ) { for( asUINT n = 0; n < engine->sharedScriptTypes.GetLength(); n++ ) { - asCObjectType *t = engine->sharedScriptTypes[n]; - if( t && + asCTypeInfo *t = engine->sharedScriptTypes[n]; + if( t && t->IsShared() && - t->name == ot->name && - t->nameSpace == ot->nameSpace && + t->name == et->name && + t->nameSpace == et->nameSpace && (t->flags & asOBJ_ENUM) ) { - asDELETE(ot, asCObjectType); - ot = t; + asDELETE(et, asCEnumType); + et = CastToEnumType(t); sharedExists = true; break; } } } + if (isExternal && !sharedExists) + { + asCString msg; + msg.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, et->name.AddressOf()); + engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, msg.AddressOf()); + asDELETE(et, asCEnumType); + error = true; + return asERROR; + } + if( sharedExists ) { - existingShared.Insert(ot, true); - ot->AddRefInternal(); + existingShared.Insert(et, true); + et->AddRefInternal(); } else { - if( ot->IsShared() ) + if( et->IsShared() ) { - engine->sharedScriptTypes.PushLast(ot); - ot->AddRefInternal(); + engine->sharedScriptTypes.PushLast(et); + et->AddRefInternal(); } // Set this module as the owner - ot->module = module; + et->module = module; } - module->enumTypes.PushLast(ot); - ReadObjectTypeDeclaration(ot, 2); + module->enumTypes.PushLast(et); + + if (isExternal) + module->externalTypes.PushLast(et); + + ReadTypeDeclaration(et, 2); } if( error ) return asERROR; @@ -210,7 +239,8 @@ int asCReader::ReadInner() return asOUT_OF_MEMORY; } - ReadObjectTypeDeclaration(ot, 1); + bool isExternal = false; + ReadTypeDeclaration(ot, 1, &isExternal); // If the type is shared, then we should use the original if it exists bool sharedExists = false; @@ -218,7 +248,8 @@ int asCReader::ReadInner() { for( asUINT n = 0; n < engine->sharedScriptTypes.GetLength(); n++ ) { - asCObjectType *t = engine->sharedScriptTypes[n]; + asCTypeInfo *ti = engine->sharedScriptTypes[n]; + asCObjectType *t = CastToObjectType(ti); if( t && t->IsShared() && t->name == ot->name && @@ -226,13 +257,23 @@ int asCReader::ReadInner() t->IsInterface() == ot->IsInterface() ) { asDELETE(ot, asCObjectType); - ot = t; + ot = CastToObjectType(t); sharedExists = true; break; } } } + if (isExternal && !sharedExists) + { + asCString msg; + msg.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, ot->name.AddressOf()); + engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, msg.AddressOf()); + asDELETE(ot, asCObjectType); + error = true; + return asERROR; + } + if( sharedExists ) { existingShared.Insert(ot, true); @@ -250,6 +291,9 @@ int asCReader::ReadInner() ot->module = module; } module->classTypes.PushLast(ot); + + if (isExternal) + module->externalTypes.PushLast(ot); } if( error ) return asERROR; @@ -259,44 +303,75 @@ int asCReader::ReadInner() module->funcDefs.Allocate(count, false); for( i = 0; i < count && !error; i++ ) { - bool isNew; - asCScriptFunction *func = ReadFunction(isNew, false, true); - if( func ) + bool isNew, isExternal; + asCScriptFunction *funcDef = ReadFunction(isNew, false, true, true, &isExternal); + if(funcDef) { - func->module = module; - module->funcDefs.PushLast(func); - engine->funcDefs.PushLast(func); + funcDef->module = module; + + asCFuncdefType *fdt = funcDef->funcdefType; + fdt->module = module; + + module->funcDefs.PushLast(fdt); + engine->funcDefs.PushLast(fdt); // TODO: clean up: This is also done by the builder. It should probably be moved to a method in the module // Check if there is another identical funcdef from another module and if so reuse that instead - if( func->isShared ) + if(funcDef->IsShared()) { for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ ) { - asCScriptFunction *f2 = engine->funcDefs[n]; - if( f2 == 0 || func == f2 ) + asCFuncdefType *f2 = engine->funcDefs[n]; + if( f2 == 0 || fdt == f2 ) continue; - if( !f2->isShared ) + if( !f2->funcdef->IsShared() ) continue; - if( f2->name == func->name && - f2->nameSpace == func->nameSpace && - f2->IsSignatureExceptNameEqual(func) ) + if( f2->name == fdt->name && + f2->nameSpace == fdt->nameSpace && + f2->parentClass == fdt->parentClass && + f2->funcdef->IsSignatureExceptNameEqual(funcDef) ) { // Replace our funcdef for the existing one - module->funcDefs[module->funcDefs.IndexOf(func)] = f2; + module->funcDefs[module->funcDefs.IndexOf(fdt)] = f2; f2->AddRefInternal(); - engine->funcDefs.RemoveValue(func); + if (isExternal) + module->externalTypes.PushLast(f2); - savedFunctions[savedFunctions.IndexOf(func)] = f2; + engine->funcDefs.RemoveValue(fdt); - func->ReleaseInternal(); + savedFunctions[savedFunctions.IndexOf(funcDef)] = f2->funcdef; + + if (fdt->parentClass) + { + // The real funcdef should already be in the object + asASSERT(fdt->parentClass->childFuncDefs.IndexOf(f2) >= 0); + + fdt->parentClass = 0; + } + + fdt->ReleaseInternal(); + funcDef = 0; break; } } } + + // Add the funcdef to the parentClass if this is a child funcdef + if (funcDef && fdt->parentClass) + fdt->parentClass->childFuncDefs.PushLast(fdt); + + // Check if an external shared funcdef was really found + if (isExternal && funcDef) + { + asCString msg; + msg.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, funcDef->name.AddressOf()); + engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, msg.AddressOf()); + error = true; + return asERROR; + } } else Error(TXT_INVALID_BYTECODE_d); @@ -306,21 +381,21 @@ int asCReader::ReadInner() for( i = 0; i < module->classTypes.GetLength() && !error; i++ ) { if( module->classTypes[i]->IsInterface() ) - ReadObjectTypeDeclaration(module->classTypes[i], 2); + ReadTypeDeclaration(module->classTypes[i], 2); } // Read class methods and behaviours for( i = 0; i < module->classTypes.GetLength() && !error; ++i ) { if( !module->classTypes[i]->IsInterface() ) - ReadObjectTypeDeclaration(module->classTypes[i], 2); + ReadTypeDeclaration(module->classTypes[i], 2); } // Read class properties for( i = 0; i < module->classTypes.GetLength() && !error; ++i ) { if( !module->classTypes[i]->IsInterface() ) - ReadObjectTypeDeclaration(module->classTypes[i], 3); + ReadTypeDeclaration(module->classTypes[i], 3); } if( error ) return asERROR; @@ -330,17 +405,18 @@ int asCReader::ReadInner() module->typeDefs.Allocate(count, false); for( i = 0; i < count && !error; i++ ) { - asCObjectType *ot = asNEW(asCObjectType)(engine); - if( ot == 0 ) + asCTypedefType *td = asNEW(asCTypedefType)(engine); + if( td == 0 ) { error = true; return asOUT_OF_MEMORY; } - ReadObjectTypeDeclaration(ot, 1); - ot->module = module; - module->typeDefs.PushLast(ot); - ReadObjectTypeDeclaration(ot, 2); + bool isExternal = false; + ReadTypeDeclaration(td, 1, &isExternal); + td->module = module; + module->typeDefs.PushLast(td); + ReadTypeDeclaration(td, 2); } if( error ) return asERROR; @@ -353,26 +429,26 @@ int asCReader::ReadInner() Error(TXT_INVALID_BYTECODE_d); } module->scriptGlobals.Allocate(count, false); - for( i = 0; i < count && !error; ++i ) + for( i = 0; i < count && !error; ++i ) { ReadGlobalProperty(); } // scriptFunctions[] count = ReadEncodedUInt(); - for( i = 0; i < count && !error; ++i ) + for( i = 0; i < count && !error; ++i ) { size_t len = module->scriptFunctions.GetLength(); - bool isNew; - func = ReadFunction(isNew); + bool isNew, isExternal; + func = ReadFunction(isNew, true, true, true, &isExternal); if( func == 0 ) { Error(TXT_INVALID_BYTECODE_d); break; } - + // Is the function shared and was it created now? - if( func->isShared && len != module->scriptFunctions.GetLength() ) + if( func->IsShared() && len != module->scriptFunctions.GetLength() ) { // If the function already existed in another module, then // we need to replace it with previously existing one @@ -393,14 +469,29 @@ int asCReader::ReadInner() // Insert the function in the dontTranslate array dontTranslate.Insert(realFunc, true); + if (isExternal) + module->externalFunctions.PushLast(realFunc); + // Release the function, but make sure nothing else is released func->id = 0; - func->scriptData->byteCode.SetLength(0); + if( func->scriptData ) + func->scriptData->byteCode.SetLength(0); func->ReleaseInternal(); + func = 0; break; } } } + + // Check if an external shared func was really found + if (isExternal && func) + { + asCString msg; + msg.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, func->name.AddressOf()); + engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, msg.AddressOf()); + error = true; + return asERROR; + } } // globalFunctions[] @@ -466,8 +557,8 @@ int asCReader::ReadInner() usedTypes.Allocate(count, false); for( i = 0; i < count && !error; ++i ) { - asCObjectType *ot = ReadObjectType(); - usedTypes.PushLast(ot); + asCTypeInfo *ti = ReadTypeInfo(); + usedTypes.PushLast(ti); } // usedTypeIds[] @@ -483,7 +574,7 @@ int asCReader::ReadInner() ReadUsedGlobalProps(); // usedStringConstants[] - if( !error ) + if( !error ) ReadUsedStringConstants(); // usedObjectProperties @@ -495,22 +586,24 @@ int asCReader::ReadInner() { for( i = 0; i < usedTypes.GetLength() && !error; i++ ) { - if( !(usedTypes[i]->flags & asOBJ_TEMPLATE) || - !usedTypes[i]->beh.templateCallback ) + asCObjectType *ot = CastToObjectType(usedTypes[i]); + if( !ot || + !(ot->flags & asOBJ_TEMPLATE) || + !ot->beh.templateCallback ) continue; - + bool dontGarbageCollect = false; - asCScriptFunction *callback = engine->scriptFunctions[usedTypes[i]->beh.templateCallback]; - if( !engine->CallGlobalFunctionRetBool(usedTypes[i], &dontGarbageCollect, callback->sysFuncIntf, callback) ) + asCScriptFunction *callback = engine->scriptFunctions[ot->beh.templateCallback]; + if( !engine->CallGlobalFunctionRetBool(ot, &dontGarbageCollect, callback->sysFuncIntf, callback) ) { - asCString sub = usedTypes[i]->templateSubTypes[0].Format(usedTypes[i]->nameSpace); - for( asUINT n = 1; n < usedTypes[i]->templateSubTypes.GetLength(); n++ ) + asCString sub = ot->templateSubTypes[0].Format(ot->nameSpace); + for( asUINT n = 1; n < ot->templateSubTypes.GetLength(); n++ ) { sub += ","; - sub += usedTypes[i]->templateSubTypes[n].Format(usedTypes[i]->nameSpace); + sub += ot->templateSubTypes[n].Format(ot->nameSpace); } asCString str; - str.Format(TXT_INSTANCING_INVLD_TMPL_TYPE_s_s, usedTypes[i]->name.AddressOf(), sub.AddressOf()); + str.Format(TXT_INSTANCING_INVLD_TMPL_TYPE_s_s, ot->name.AddressOf(), sub.AddressOf()); engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); Error(TXT_INVALID_BYTECODE_d); } @@ -518,7 +611,7 @@ int asCReader::ReadInner() { // If the callback said this template instance won't be garbage collected then remove the flag if( dontGarbageCollect ) - usedTypes[i]->flags &= ~asOBJ_GC; + ot->flags &= ~asOBJ_GC; } } } @@ -567,11 +660,18 @@ void asCReader::ReadUsedStringConstants() asUINT count; count = ReadEncodedUInt(); + + if (count > 0 && engine->stringFactory == 0) + { + Error(TXT_STRINGS_NOT_RECOGNIZED); + return; + } + usedStringConstants.Allocate(count, false); - for( asUINT i = 0; i < count; ++i ) + for( asUINT i = 0; i < count; ++i ) { ReadString(&str); - usedStringConstants.PushLast(engine->AddConstantString(str.AddressOf(), str.GetLength())); + usedStringConstants.PushLast(const_cast(engine->stringFactory->GetStringConstant(str.AddressOf(), (asUINT)str.GetLength()))); } } @@ -607,7 +707,8 @@ void asCReader::ReadUsedFunctions() else { asCScriptFunction func(engine, c == 'm' ? module : 0, asFUNC_DUMMY); - ReadFunctionSignature(&func); + asCObjectType *parentClass = 0; + ReadFunctionSignature(&func, &parentClass); if( error ) { func.funcType = asFUNC_DUMMY; @@ -623,7 +724,7 @@ void asCReader::ReadUsedFunctions() { asCScriptFunction *f = module->bindInformations[i]->importedFunctionSignature; if( func.objectType != f->objectType || - func.funcType != f->funcType || + func.funcType != f->funcType || func.nameSpace != f->nameSpace || !func.IsSignatureEqual(f) ) continue; @@ -634,14 +735,16 @@ void asCReader::ReadUsedFunctions() } else if( func.funcType == asFUNC_FUNCDEF ) { - const asCArray &funcs = module->funcDefs; + const asCArray &funcs = module->funcDefs; for( asUINT i = 0; i < funcs.GetLength(); i++ ) { - asCScriptFunction *f = funcs[i]; - if( f == 0 || func.name != f->name || !func.IsSignatureExceptNameAndObjectTypeEqual(f) ) + asCScriptFunction *f = funcs[i]->funcdef; + if( f == 0 || + func.name != f->name || + !func.IsSignatureExceptNameAndObjectTypeEqual(f) || + funcs[i]->parentClass != parentClass ) continue; - // Funcdefs are always global so there is no need to compare object type asASSERT( f->objectType == 0 ); usedFunctions[n] = f; @@ -657,7 +760,7 @@ void asCReader::ReadUsedFunctions() { asCScriptFunction *f = module->scriptFunctions[i]; if( func.objectType != f->objectType || - func.funcType != f->funcType || + func.funcType != f->funcType || func.nameSpace != f->nameSpace || !func.IsSignatureEqual(f) ) continue; @@ -667,19 +770,59 @@ void asCReader::ReadUsedFunctions() } } } + else if (c == 's') + { + // Look for shared entities in the engine, as they may not necessarily be part + // of the scope of the module if they have been inhereted from other modules. + if (func.funcType == asFUNC_FUNCDEF) + { + const asCArray &funcs = engine->funcDefs; + for (asUINT i = 0; i < funcs.GetLength(); i++) + { + asCScriptFunction *f = funcs[i]->funcdef; + if (f == 0 || + func.name != f->name || + !func.IsSignatureExceptNameAndObjectTypeEqual(f) || + funcs[i]->parentClass != parentClass) + continue; + + asASSERT(f->objectType == 0); + + usedFunctions[n] = f; + break; + } + } + else + { + for (asUINT i = 0; i < engine->scriptFunctions.GetLength(); i++) + { + asCScriptFunction *f = engine->scriptFunctions[i]; + if (f == 0 || !f->IsShared() || + func.objectType != f->objectType || + func.funcType != f->funcType || + func.nameSpace != f->nameSpace || + !func.IsSignatureEqual(f)) + continue; + + usedFunctions[n] = f; + break; + } + } + } else { + asASSERT(c == 'a'); + if( func.funcType == asFUNC_FUNCDEF ) { // This is a funcdef (registered or shared) - const asCArray &funcs = engine->funcDefs; + const asCArray &funcs = engine->funcDefs; for( asUINT i = 0; i < funcs.GetLength(); i++ ) { - asCScriptFunction *f = funcs[i]; - if( f == 0 || func.name != f->name || !func.IsSignatureExceptNameAndObjectTypeEqual(f) ) + asCScriptFunction *f = funcs[i]->funcdef; + if( f == 0 || func.name != f->name || !func.IsSignatureExceptNameAndObjectTypeEqual(f) || funcs[i]->parentClass != parentClass ) continue; - // Funcdefs are always global so there is no need to compare object type asASSERT( f->objectType == 0 ); usedFunctions[n] = f; @@ -690,11 +833,7 @@ void asCReader::ReadUsedFunctions() { // This is a special function - // Check for string factory - if( func.name == "$str" && engine->stringFactory && - func.IsSignatureExceptNameAndObjectTypeEqual(engine->stringFactory) ) - usedFunctions[n] = engine->stringFactory; - else if( func.name == "$beh0" && func.objectType ) + if( func.name == "$beh0" && func.objectType ) { // This is a class constructor, so we can search directly in the object type's constructors for( asUINT i = 0; i < func.objectType->beh.constructors.GetLength(); i++ ) @@ -711,7 +850,7 @@ void asCReader::ReadUsedFunctions() else if( func.name == "$fact" || func.name == "$beh3" ) { // This is a factory (or stub), so look for the function in the return type's factories - asCObjectType *objType = func.returnType.GetObjectType(); + asCObjectType *objType = CastToObjectType(func.returnType.GetTypeInfo()); if( objType ) { for( asUINT i = 0; i < objType->beh.factories.GetLength(); i++ ) @@ -729,7 +868,7 @@ void asCReader::ReadUsedFunctions() else if( func.name == "$list" ) { // listFactory is used for both factory is global and returns a handle and constructor that is a method - asCObjectType *objType = func.objectType ? func.objectType : func.returnType.GetObjectType(); + asCObjectType *objType = func.objectType ? func.objectType : CastToObjectType(func.returnType.GetTypeInfo()); if( objType ) { asCScriptFunction *f = engine->scriptFunctions[objType->beh.listFactory]; @@ -751,7 +890,7 @@ void asCReader::ReadUsedFunctions() else if( func.name == "$beh4" ) { // This is a list factory, so check the return type's list factory - asCObjectType *objType = func.returnType.GetObjectType(); + asCObjectType *objType = CastToObjectType(func.returnType.GetTypeInfo()); if( objType ) { asCScriptFunction *f = engine->scriptFunctions[objType->beh.listFactory]; @@ -800,10 +939,10 @@ void asCReader::ReadUsedFunctions() if( usedFunctions[n] == 0 ) { - // TODO: clean up: This part of the code should never happen. All functions should - // be found in the above logic. The only valid reason to come here + // TODO: clean up: This part of the code should never happen. All functions should + // be found in the above logic. The only valid reason to come here // is if the bytecode is wrong and the function doesn't exist anyway. - // This loop is kept temporarily until we can be certain all scenarios + // This loop is kept temporarily until we can be certain all scenarios // are covered. for( asUINT i = 0; i < engine->scriptFunctions.GetLength(); i++ ) { @@ -835,7 +974,7 @@ void asCReader::ReadUsedFunctions() } } -void asCReader::ReadFunctionSignature(asCScriptFunction *func) +void asCReader::ReadFunctionSignature(asCScriptFunction *func, asCObjectType **parentClass) { asUINT i, count; asCDataType dt; @@ -844,7 +983,7 @@ void asCReader::ReadFunctionSignature(asCScriptFunction *func) ReadString(&func->name); if( func->name == DELEGATE_FACTORY ) { - // It's not necessary to read anymore, everything is known + // It's not necessary to read anymore, everything is known asCScriptFunction *f = engine->registeredGlobalFuncs.GetFirst(engine->nameSpaces[0], DELEGATE_FACTORY); asASSERT( f ); func->returnType = f->returnType; @@ -866,7 +1005,7 @@ void asCReader::ReadFunctionSignature(asCScriptFunction *func) return; } func->parameterTypes.Allocate(count, false); - for( i = 0; i < count; ++i ) + for( i = 0; i < count; ++i ) { ReadDataType(&dt); func->parameterTypes.PushLast(dt); @@ -926,30 +1065,55 @@ void asCReader::ReadFunctionSignature(asCScriptFunction *func) ReadString(str); } } - - func->objectType = ReadObjectType(); + + func->objectType = CastToObjectType(ReadTypeInfo()); if( func->objectType ) { func->objectType->AddRefInternal(); asBYTE b; ReadData(&b, 1); - func->isReadOnly = (b & 1) ? true : false; - func->isPrivate = (b & 2) ? true : false; - func->isProtected = (b & 4) ? true : false; + func->SetReadOnly((b & 1) ? true : false); + func->SetPrivate((b & 2) ? true : false); + func->SetProtected((b & 4) ? true : false); func->nameSpace = engine->nameSpaces[0]; } else { - asCString ns; - ReadString(&ns); - func->nameSpace = engine->AddNameSpace(ns.AddressOf()); + if (func->funcType == asFUNC_FUNCDEF) + { + asBYTE b; + ReadData(&b, 1); + if (b == 'n') + { + asCString ns; + ReadString(&ns); + func->nameSpace = engine->AddNameSpace(ns.AddressOf()); + } + else if (b == 'o') + { + func->nameSpace = 0; + if (parentClass) + *parentClass = CastToObjectType(ReadTypeInfo()); + else + error = true; + } + else + error = true; + } + else + { + asCString ns; + ReadString(&ns); + func->nameSpace = engine->AddNameSpace(ns.AddressOf()); + } } } -asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool addToEngine, bool addToGC) +asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool addToEngine, bool addToGC, bool *isExternal) { isNew = false; + if (isExternal) *isExternal = false; if( error ) return 0; char c; @@ -989,7 +1153,8 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a asCDataType dt; int num; - ReadFunctionSignature(func); + asCObjectType *parentClass = 0; + ReadFunctionSignature(func, &parentClass); if( error ) { func->DestroyHalfCreated(); @@ -998,150 +1163,160 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a if( func->funcType == asFUNC_SCRIPT ) { - func->AllocateScriptFunctionData(); - if( func->scriptData == 0 ) + char bits; + ReadData(&bits, 1); + func->SetShared((bits & 1) ? true : false); + func->dontCleanUpOnException = (bits & 2) ? true : false; + if ((bits & 4) && isExternal) + *isExternal = true; + + // for external shared functions the rest is not needed + if (!(bits & 4)) { - // Out of memory - error = true; - func->DestroyHalfCreated(); - return 0; - } - - if( addToGC && !addToModule ) - engine->gc.AddScriptObjectToGC(func, &engine->functionBehaviours); - - ReadByteCode(func); - - func->scriptData->variableSpace = ReadEncodedUInt(); - - count = ReadEncodedUInt(); - func->scriptData->objVariablePos.Allocate(count, false); - func->scriptData->objVariableTypes.Allocate(count, false); - func->scriptData->funcVariableTypes.Allocate(count, false); - for( i = 0; i < count; ++i ) - { - func->scriptData->objVariableTypes.PushLast(ReadObjectType()); - asUINT idx = ReadEncodedUInt(); - func->scriptData->funcVariableTypes.PushLast((asCScriptFunction*)(asPWORD)idx); - num = ReadEncodedUInt(); - func->scriptData->objVariablePos.PushLast(num); - - if( error ) - { - // No need to continue (the error has already been reported before) - func->DestroyHalfCreated(); - return 0; - } - } - if( count > 0 ) - func->scriptData->objVariablesOnHeap = ReadEncodedUInt(); - else - func->scriptData->objVariablesOnHeap = 0; - - int length = ReadEncodedUInt(); - func->scriptData->objVariableInfo.SetLength(length); - for( i = 0; i < length; ++i ) - { - func->scriptData->objVariableInfo[i].programPos = ReadEncodedUInt(); - func->scriptData->objVariableInfo[i].variableOffset = ReadEncodedUInt(); - func->scriptData->objVariableInfo[i].option = ReadEncodedUInt(); - } - - if( !noDebugInfo ) - { - length = ReadEncodedUInt(); - func->scriptData->lineNumbers.SetLength(length); - if( int(func->scriptData->lineNumbers.GetLength()) != length ) + func->AllocateScriptFunctionData(); + if (func->scriptData == 0) { // Out of memory error = true; func->DestroyHalfCreated(); return 0; } - for( i = 0; i < length; ++i ) - func->scriptData->lineNumbers[i] = ReadEncodedUInt(); - // Read the array of script sections - length = ReadEncodedUInt(); - func->scriptData->sectionIdxs.SetLength(length); - if( int(func->scriptData->sectionIdxs.GetLength()) != length ) + if (addToGC && !addToModule) + engine->gc.AddScriptObjectToGC(func, &engine->functionBehaviours); + + ReadByteCode(func); + + func->scriptData->variableSpace = ReadEncodedUInt(); + + count = ReadEncodedUInt(); + func->scriptData->objVariablePos.Allocate(count, false); + func->scriptData->objVariableTypes.Allocate(count, false); + for (i = 0; i < count; ++i) { - // Out of memory - error = true; - func->DestroyHalfCreated(); - return 0; - } - for( i = 0; i < length; ++i ) - { - if( (i & 1) == 0 ) - func->scriptData->sectionIdxs[i] = ReadEncodedUInt(); - else - { - asCString str; - ReadString(&str); - func->scriptData->sectionIdxs[i] = engine->GetScriptSectionNameIndex(str.AddressOf()); - } - } - } + func->scriptData->objVariableTypes.PushLast(ReadTypeInfo()); + num = ReadEncodedUInt(); + func->scriptData->objVariablePos.PushLast(num); - // Read the variable information - if( !noDebugInfo ) - { - length = ReadEncodedUInt(); - func->scriptData->variables.Allocate(length, false); - for( i = 0; i < length; i++ ) - { - asSScriptVariable *var = asNEW(asSScriptVariable); - if( var == 0 ) - { - // Out of memory - error = true; - func->DestroyHalfCreated(); - return 0; - } - func->scriptData->variables.PushLast(var); - - var->declaredAtProgramPos = ReadEncodedUInt(); - var->stackOffset = ReadEncodedUInt(); - ReadString(&var->name); - ReadDataType(&var->type); - - if( error ) + if (error) { // No need to continue (the error has already been reported before) func->DestroyHalfCreated(); return 0; } } - } + if (count > 0) + func->scriptData->objVariablesOnHeap = ReadEncodedUInt(); + else + func->scriptData->objVariablesOnHeap = 0; - char bits; - ReadData(&bits, 1); - func->isShared = bits & 1 ? true : false; - func->dontCleanUpOnException = bits & 2 ? true : false; - - // Read script section name - if( !noDebugInfo ) - { - asCString name; - ReadString(&name); - func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(name.AddressOf()); - func->scriptData->declaredAt = ReadEncodedUInt(); - } - - // Read parameter names - if( !noDebugInfo ) - { - asUINT count = asUINT(ReadEncodedUInt64()); - if( count > func->parameterTypes.GetLength() ) + int length = ReadEncodedUInt(); + func->scriptData->objVariableInfo.SetLength(length); + for (i = 0; i < length; ++i) { - error = true; - func->DestroyHalfCreated(); - return 0; + func->scriptData->objVariableInfo[i].programPos = ReadEncodedUInt(); + func->scriptData->objVariableInfo[i].variableOffset = ReadEncodedUInt(); + asEObjVarInfoOption option = (asEObjVarInfoOption)ReadEncodedUInt(); + func->scriptData->objVariableInfo[i].option = option; + if (option != asOBJ_INIT && option != asOBJ_UNINIT && option != asBLOCK_BEGIN && option != asBLOCK_END) + { + error = true; + func->DestroyHalfCreated(); + return 0; + } + } + + if (!noDebugInfo) + { + length = ReadEncodedUInt(); + func->scriptData->lineNumbers.SetLength(length); + if (int(func->scriptData->lineNumbers.GetLength()) != length) + { + // Out of memory + error = true; + func->DestroyHalfCreated(); + return 0; + } + for (i = 0; i < length; ++i) + func->scriptData->lineNumbers[i] = ReadEncodedUInt(); + + // Read the array of script sections + length = ReadEncodedUInt(); + func->scriptData->sectionIdxs.SetLength(length); + if (int(func->scriptData->sectionIdxs.GetLength()) != length) + { + // Out of memory + error = true; + func->DestroyHalfCreated(); + return 0; + } + for (i = 0; i < length; ++i) + { + if ((i & 1) == 0) + func->scriptData->sectionIdxs[i] = ReadEncodedUInt(); + else + { + asCString str; + ReadString(&str); + func->scriptData->sectionIdxs[i] = engine->GetScriptSectionNameIndex(str.AddressOf()); + } + } + } + + // Read the variable information + if (!noDebugInfo) + { + length = ReadEncodedUInt(); + func->scriptData->variables.Allocate(length, false); + for (i = 0; i < length; i++) + { + asSScriptVariable *var = asNEW(asSScriptVariable); + if (var == 0) + { + // Out of memory + error = true; + func->DestroyHalfCreated(); + return 0; + } + func->scriptData->variables.PushLast(var); + + var->declaredAtProgramPos = ReadEncodedUInt(); + var->stackOffset = ReadEncodedUInt(); + ReadString(&var->name); + ReadDataType(&var->type); + + if (error) + { + // No need to continue (the error has already been reported before) + func->DestroyHalfCreated(); + return 0; + } + } + } + + // Read script section name + if (!noDebugInfo) + { + asCString name; + ReadString(&name); + func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(name.AddressOf()); + func->scriptData->declaredAt = ReadEncodedUInt(); + } + + // Read parameter names + if (!noDebugInfo) + { + asUINT countParam = asUINT(ReadEncodedUInt64()); + if (countParam > func->parameterTypes.GetLength()) + { + error = true; + func->DestroyHalfCreated(); + return 0; + } + func->parameterNames.SetLength(countParam); + for (asUINT n = 0; n < countParam; n++) + ReadString(&func->parameterNames[n]); } - func->parameterNames.SetLength(count); - for( asUINT n = 0; n < count; n++ ) - ReadString(&func->parameterNames[n]); } } else if( func->funcType == asFUNC_VIRTUAL || func->funcType == asFUNC_INTERFACE ) @@ -1152,8 +1327,14 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a { asBYTE bits; ReadData(&bits, 1); - if( bits ) - func->isShared = true; + if( bits & 1 ) + func->SetShared(true); + if ((bits & 2) && isExternal) + *isExternal = true; + + // The asCFuncdefType constructor adds itself to the func->funcdefType member + asCFuncdefType *fdt = asNEW(asCFuncdefType)(engine, func); + fdt->parentClass = parentClass; } if( addToModule ) @@ -1173,48 +1354,84 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a return func; } -void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) +void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExternal) { if( phase == 1 ) { + asASSERT(isExternal); + if (isExternal) + *isExternal = false; + // Read the initial attributes - ReadString(&ot->name); - ReadData(&ot->flags, 4); - ot->size = ReadEncodedUInt(); + ReadString(&type->name); + ReadData(&type->flags, 4); + type->size = ReadEncodedUInt(); asCString ns; ReadString(&ns); - ot->nameSpace = engine->AddNameSpace(ns.AddressOf()); + type->nameSpace = engine->AddNameSpace(ns.AddressOf()); + + // Verify that the flags match the asCTypeInfo + if ((CastToEnumType(type) && !(type->flags & asOBJ_ENUM)) || + (CastToFuncdefType(type) && !(type->flags & asOBJ_FUNCDEF)) || + (CastToObjectType(type) && !(type->flags & (asOBJ_REF | asOBJ_VALUE)))) + { + error = true; + return; + } // Reset the size of script classes, since it will be recalculated as properties are added - if( (ot->flags & asOBJ_SCRIPT_OBJECT) && ot->size != 0 ) - ot->size = sizeof(asCScriptObject); + if( (type->flags & asOBJ_SCRIPT_OBJECT) && type->size != 0 ) + type->size = sizeof(asCScriptObject); - // Use the default script class behaviours - ot->beh = engine->scriptTypeBehaviours.beh; - ot->beh.construct = 0; - ot->beh.factory = 0; - ot->beh.constructors.PopLast(); // These will be read from the file - ot->beh.factories.PopLast(); // These will be read from the file - engine->scriptFunctions[ot->beh.addref]->AddRefInternal(); - engine->scriptFunctions[ot->beh.release]->AddRefInternal(); - engine->scriptFunctions[ot->beh.gcEnumReferences]->AddRefInternal(); - engine->scriptFunctions[ot->beh.gcGetFlag]->AddRefInternal(); - engine->scriptFunctions[ot->beh.gcGetRefCount]->AddRefInternal(); - engine->scriptFunctions[ot->beh.gcReleaseAllReferences]->AddRefInternal(); - engine->scriptFunctions[ot->beh.gcSetFlag]->AddRefInternal(); - engine->scriptFunctions[ot->beh.copy]->AddRefInternal(); - // TODO: weak: Should not do this if the class has been declared with 'noweak' - engine->scriptFunctions[ot->beh.getWeakRefFlag]->AddRefInternal(); + asCObjectType *ot = CastToObjectType(type); + if (ot) + { + // Use the default script class behaviours + ot->beh = engine->scriptTypeBehaviours.beh; + ot->beh.construct = 0; + ot->beh.factory = 0; + ot->beh.constructors.PopLast(); // These will be read from the file + ot->beh.factories.PopLast(); // These will be read from the file + engine->scriptFunctions[ot->beh.addref]->AddRefInternal(); + engine->scriptFunctions[ot->beh.release]->AddRefInternal(); + engine->scriptFunctions[ot->beh.gcEnumReferences]->AddRefInternal(); + engine->scriptFunctions[ot->beh.gcGetFlag]->AddRefInternal(); + engine->scriptFunctions[ot->beh.gcGetRefCount]->AddRefInternal(); + engine->scriptFunctions[ot->beh.gcReleaseAllReferences]->AddRefInternal(); + engine->scriptFunctions[ot->beh.gcSetFlag]->AddRefInternal(); + engine->scriptFunctions[ot->beh.copy]->AddRefInternal(); + // TODO: weak: Should not do this if the class has been declared with 'noweak' + engine->scriptFunctions[ot->beh.getWeakRefFlag]->AddRefInternal(); + } + + // external shared flag + if (type->flags & asOBJ_SHARED) + { + char c; + ReadData(&c, 1); + if (c == 'e') + *isExternal = true; + else if (c != ' ') + { + error = true; + return; + } + } } else if( phase == 2 ) { - if( ot->flags & asOBJ_ENUM ) + // external shared types doesn't store this + if ((type->flags & asOBJ_SHARED) && module->externalTypes.IndexOf(type) >= 0) + return; + + if( type->flags & asOBJ_ENUM ) { + asCEnumType *t = CastToEnumType(type); int count = ReadEncodedUInt(); - bool sharedExists = existingShared.MoveTo(0, ot); + bool sharedExists = existingShared.MoveTo(0, type); if( !sharedExists ) { - ot->enumValues.Allocate(count, false); + t->enumValues.Allocate(count, false); for( int n = 0; n < count; n++ ) { asSEnumValue *e = asNEW(asSEnumValue); @@ -1226,7 +1443,7 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) } ReadString(&e->name); ReadData(&e->value, 4); // TODO: Should be encoded - ot->enumValues.PushLast(e); + t->enumValues.PushLast(e); } } else @@ -1239,10 +1456,10 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) ReadString(&name); ReadData(&value, 4); // TODO: Should be encoded bool found = false; - for( asUINT e = 0; e < ot->enumValues.GetLength(); e++ ) + for( asUINT e = 0; e < t->enumValues.GetLength(); e++ ) { - if( ot->enumValues[e]->name == name && - ot->enumValues[e]->value == value ) + if( t->enumValues[e]->name == name && + t->enumValues[e]->value == value ) { found = true; break; @@ -1251,37 +1468,42 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) if( !found ) { asCString str; - str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName()); + str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, type->GetName()); engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); Error(TXT_INVALID_BYTECODE_d); } } } } - else if( ot->flags & asOBJ_TYPEDEF ) + else if( type->flags & asOBJ_TYPEDEF ) { + asCTypedefType *td = CastToTypedefType(type); + asASSERT(td); eTokenType t = (eTokenType)ReadEncodedUInt(); - ot->templateSubTypes.PushLast(asCDataType::CreatePrimitive(t, false)); + td->aliasForType = asCDataType::CreatePrimitive(t, false); } else { - // If the type is shared and pre-existing, we should just - // validate that the loaded methods match the original - bool sharedExists = existingShared.MoveTo(0, ot); + asCObjectType *ot = CastToObjectType(type); + asASSERT(ot); + + // If the type is shared and pre-existing, we should just + // validate that the loaded methods match the original + bool sharedExists = existingShared.MoveTo(0, type); if( sharedExists ) { - asCObjectType *dt = ReadObjectType(); + asCObjectType *dt = CastToObjectType(ReadTypeInfo()); if( ot->derivedFrom != dt ) { asCString str; - str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName()); + str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, type->GetName()); engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); Error(TXT_INVALID_BYTECODE_d); } } else { - ot->derivedFrom = ReadObjectType(); + ot->derivedFrom = CastToObjectType(ReadTypeInfo()); if( ot->derivedFrom ) ot->derivedFrom->AddRefInternal(); } @@ -1292,13 +1514,13 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) { for( int n = 0; n < size; n++ ) { - asCObjectType *intf = ReadObjectType(); + asCObjectType *intf = CastToObjectType(ReadTypeInfo()); ReadEncodedUInt(); - if( !ot->Implements(intf) ) + if( !type->Implements(intf) ) { asCString str; - str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName()); + str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, type->GetName()); engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); Error(TXT_INVALID_BYTECODE_d); } @@ -1310,7 +1532,7 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) ot->interfaceVFTOffsets.Allocate(size, false); for( int n = 0; n < size; n++ ) { - asCObjectType *intf = ReadObjectType(); + asCObjectType *intf = CastToObjectType(ReadTypeInfo()); ot->interfaces.PushLast(intf); asUINT offset = ReadEncodedUInt(); @@ -1319,7 +1541,7 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) } // behaviours - if( !ot->IsInterface() && ot->flags != asOBJ_TYPEDEF && ot->flags != asOBJ_ENUM ) + if( !ot->IsInterface() && type->flags != asOBJ_TYPEDEF && type->flags != asOBJ_ENUM ) { bool isNew; asCScriptFunction *func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists); @@ -1336,7 +1558,7 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) else { asCString str; - str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName()); + str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, type->GetName()); engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); Error(TXT_INVALID_BYTECODE_d); } @@ -1368,17 +1590,16 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) size = ReadEncodedUInt(); for( int n = 0; n < size; n++ ) { - bool isNew; - asCScriptFunction *func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists); + func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists); if( func ) { if( sharedExists ) { // Find the real function in the object, and update the savedFunctions array bool found = false; - for( asUINT n = 0; n < ot->beh.constructors.GetLength(); n++ ) + for( asUINT f = 0; f < ot->beh.constructors.GetLength(); f++ ) { - asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.constructors[n]); + asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.constructors[f]); if( realFunc->IsSignatureEqual(func) ) { // If the function is not the last, then the substitution has already occurred before @@ -1394,7 +1615,7 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) if( !found ) { asCString str; - str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName()); + str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, type->GetName()); engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); Error(TXT_INVALID_BYTECODE_d); } @@ -1427,9 +1648,9 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) { // Find the real function in the object, and update the savedFunctions array bool found = false; - for( asUINT n = 0; n < ot->beh.factories.GetLength(); n++ ) + for( asUINT f = 0; f < ot->beh.factories.GetLength(); f++ ) { - asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.factories[n]); + asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.factories[f]); if( realFunc->IsSignatureEqual(func) ) { // If the function is not the last, then the substitution has already occurred before @@ -1445,7 +1666,7 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) if( !found ) { asCString str; - str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName()); + str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, type->GetName()); engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); Error(TXT_INVALID_BYTECODE_d); } @@ -1476,7 +1697,7 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) // methods[] size = ReadEncodedUInt(); int n; - for( n = 0; n < size; n++ ) + for( n = 0; n < size; n++ ) { bool isNew; asCScriptFunction *func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists); @@ -1486,9 +1707,9 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) { // Find the real function in the object, and update the savedFunctions array bool found = false; - for( asUINT n = 0; n < ot->methods.GetLength(); n++ ) + for( asUINT f = 0; f < ot->methods.GetLength(); f++ ) { - asCScriptFunction *realFunc = engine->GetScriptFunction(ot->methods[n]); + asCScriptFunction *realFunc = engine->GetScriptFunction(ot->methods[f]); if( realFunc->IsSignatureEqual(func) ) { // If the function is not the last, then the substitution has already occurred before @@ -1504,7 +1725,7 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) if( !found ) { asCString str; - str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName()); + str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, type->GetName()); engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); Error(TXT_INVALID_BYTECODE_d); } @@ -1521,14 +1742,14 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) { // If the method is the assignment operator we need to replace the default implementation if( func->name == "opAssign" && func->parameterTypes.GetLength() == 1 && - func->parameterTypes[0].GetObjectType() == func->objectType && + func->parameterTypes[0].GetTypeInfo() == func->objectType && (func->inOutFlags[0] & asTM_INREF) ) { engine->scriptFunctions[ot->beh.copy]->ReleaseInternal(); ot->beh.copy = func->id; func->AddRefInternal(); } - + ot->methods.PushLast(func->id); func->AddRefInternal(); } @@ -1551,9 +1772,9 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) { // Find the real function in the object, and update the savedFunctions array bool found = false; - for( asUINT n = 0; n < ot->virtualFunctionTable.GetLength(); n++ ) + for( asUINT f = 0; f < ot->virtualFunctionTable.GetLength(); f++ ) { - asCScriptFunction *realFunc = ot->virtualFunctionTable[n]; + asCScriptFunction *realFunc = ot->virtualFunctionTable[f]; if( realFunc->IsSignatureEqual(func) ) { // If the function is not the last, then the substitution has already occurred before @@ -1569,7 +1790,7 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) if( !found ) { asCString str; - str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName()); + str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, type->GetName()); engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); Error(TXT_INVALID_BYTECODE_d); } @@ -1597,6 +1818,15 @@ void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase) } else if( phase == 3 ) { + // external shared types doesn't store this + if ((type->flags & asOBJ_SHARED) && module->externalTypes.IndexOf(type) >= 0) + return; + + asCObjectType *ot = CastToObjectType(type); + + // This is only done for object types + asASSERT(ot); + // properties[] asUINT size = ReadEncodedUInt(); for( asUINT n = 0; n < size; n++ ) @@ -1633,7 +1863,7 @@ asQWORD asCReader::ReadEncodedUInt64() ReadData(&b, 1); bool isNegative = ( b & 0x80 ) ? true : false; b &= 0x7F; - + if( (b & 0x7F) == 0x7F ) { ReadData(&b, 1); i = asQWORD(b) << 56; @@ -1654,7 +1884,7 @@ asQWORD asCReader::ReadEncodedUInt64() ReadData(&b, 1); i += asUINT(b) << 16; ReadData(&b, 1); i += asUINT(b) << 8; ReadData(&b, 1); i += b; - } + } else if( (b & 0x7C) == 0x7C ) { i = asQWORD(b & 0x03) << 40; @@ -1663,7 +1893,7 @@ asQWORD asCReader::ReadEncodedUInt64() ReadData(&b, 1); i += asUINT(b) << 16; ReadData(&b, 1); i += asUINT(b) << 8; ReadData(&b, 1); i += b; - } + } else if( (b & 0x78) == 0x78 ) { i = asQWORD(b & 0x07) << 32; @@ -1671,7 +1901,7 @@ asQWORD asCReader::ReadEncodedUInt64() ReadData(&b, 1); i += asUINT(b) << 16; ReadData(&b, 1); i += asUINT(b) << 8; ReadData(&b, 1); i += b; - } + } else if( (b & 0x70) == 0x70 ) { i = asUINT(b & 0x0F) << 24; @@ -1700,7 +1930,7 @@ asQWORD asCReader::ReadEncodedUInt64() return i; } -void asCReader::ReadString(asCString* str) +void asCReader::ReadString(asCString* str) { asUINT len = ReadEncodedUInt(); if( len & 1 ) @@ -1715,7 +1945,9 @@ void asCReader::ReadString(asCString* str) { len /= 2; str->SetLength(len); - stream->Read(str->AddressOf(), len); + int r = stream->Read(str->AddressOf(), len); + if (r < 0) + Error(TXT_UNEXPECTED_END_OF_FILE); savedStrings.PushLast(*str); } @@ -1723,7 +1955,7 @@ void asCReader::ReadString(asCString* str) str->SetLength(0); } -void asCReader::ReadGlobalProperty() +void asCReader::ReadGlobalProperty() { asCString name; asCDataType type; @@ -1740,7 +1972,7 @@ void asCReader::ReadGlobalProperty() // Read the initialization function bool isNew; - // Do not add the function to the GC at this time. It will + // Do not add the function to the GC at this time. It will // only be added to the GC when the module releases the property asCScriptFunction *func = ReadFunction(isNew, false, true, false); if( func ) @@ -1753,7 +1985,7 @@ void asCReader::ReadGlobalProperty() } } -void asCReader::ReadObjectProperty(asCObjectType *ot) +void asCReader::ReadObjectProperty(asCObjectType *ot) { asCString name; ReadString(&name); @@ -1764,20 +1996,20 @@ void asCReader::ReadObjectProperty(asCObjectType *ot) bool isProtected = (flags & 2) ? true : false; bool isInherited = (flags & 4) ? true : false; - // TODO: shared: If the type is shared and pre-existing, we should just - // validate that the loaded methods match the original + // TODO: shared: If the type is shared and pre-existing, we should just + // validate that the loaded methods match the original if( !existingShared.MoveTo(0, ot) ) ot->AddPropertyToClass(name, dt, isPrivate, isProtected, isInherited); } -void asCReader::ReadDataType(asCDataType *dt) +void asCReader::ReadDataType(asCDataType *dt) { // Check if this is a previously used type - asUINT n = ReadEncodedUInt(); - if( n != 0 ) + asUINT idx = ReadEncodedUInt(); + if( idx != 0 ) { // Get the datatype from the cache - *dt = savedDataTypes[n-1]; + *dt = savedDataTypes[idx-1]; return; } @@ -1789,78 +2021,42 @@ void asCReader::ReadDataType(asCDataType *dt) savedDataTypes.PushLast(asCDataType()); // Read the datatype for the first time - asCObjectType *objType = 0; + asCTypeInfo *ti = 0; if( tokenType == ttIdentifier ) - objType = ReadObjectType(); + ti = ReadTypeInfo(); - struct - { - char isObjectHandle :1; - char isHandleToConst:1; - char isReference :1; - char isReadOnly :1; - } bits = {0}; - asASSERT( sizeof(bits) == 1 ); - ReadData(&bits, 1); + // Read type flags as a bitmask + // Endian-safe code + bool isObjectHandle, isHandleToConst, isReference, isReadOnly; + char b = 0; + ReadData(&b, 1); + LOAD_FROM_BIT(isObjectHandle, b, 0); + LOAD_FROM_BIT(isHandleToConst, b, 1); + LOAD_FROM_BIT(isReference, b, 2); + LOAD_FROM_BIT(isReadOnly, b, 3); - asCScriptFunction *funcDef = 0; - if( tokenType == ttIdentifier && objType && objType->name == "$func" ) - { - asCScriptFunction func(engine, module, asFUNC_DUMMY); - ReadFunctionSignature(&func); - if( error ) return; - for( asUINT n = 0; n < engine->registeredFuncDefs.GetLength(); n++ ) - { - // TODO: access: Only return the definitions that the module has access to - if( engine->registeredFuncDefs[n]->name == func.name && - engine->registeredFuncDefs[n]->nameSpace == func.nameSpace ) - { - funcDef = engine->registeredFuncDefs[n]; - break; - } - } - - if( !funcDef && module ) - { - for( asUINT n = 0; n < module->funcDefs.GetLength(); n++ ) - { - if( module->funcDefs[n]->name == func.name && - module->funcDefs[n]->nameSpace == func.nameSpace ) - { - funcDef = module->funcDefs[n]; - break; - } - } - } - - // Set to dummy to avoid unwanted release of resources - func.funcType = asFUNC_DUMMY; - } - - if( funcDef ) - *dt = asCDataType::CreateFuncDef(funcDef); - else if( tokenType == ttIdentifier ) - *dt = asCDataType::CreateObject(objType, false); + if( tokenType == ttIdentifier ) + *dt = asCDataType::CreateType(ti, false); else *dt = asCDataType::CreatePrimitive(tokenType, false); - if( bits.isObjectHandle ) + if( isObjectHandle ) { - dt->MakeReadOnly(bits.isHandleToConst ? true : false); - - // Here we must allow a scoped type to be a handle + dt->MakeReadOnly(isHandleToConst ? true : false); + + // Here we must allow a scoped type to be a handle // e.g. if the datatype is for a system function dt->MakeHandle(true, true); } - dt->MakeReadOnly(bits.isReadOnly ? true : false); - dt->MakeReference(bits.isReference ? true : false); + dt->MakeReadOnly(isReadOnly ? true : false); + dt->MakeReference(isReference ? true : false); // Update the previously saved slot savedDataTypes[saveSlot] = *dt; } -asCObjectType* asCReader::ReadObjectType() +asCTypeInfo* asCReader::ReadTypeInfo() { - asCObjectType *ot = 0; + asCTypeInfo *ot = 0; char ch; ReadData(&ch, 1); if( ch == 'a' ) @@ -1871,7 +2067,8 @@ asCObjectType* asCReader::ReadObjectType() ReadString(&ns); asSNameSpace *nameSpace = engine->AddNameSpace(ns.AddressOf()); - asCObjectType *tmpl = engine->GetRegisteredObjectType(typeName.AddressOf(), nameSpace); + asCTypeInfo *tmp = engine->GetRegisteredType(typeName.AddressOf(), nameSpace); + asCObjectType *tmpl = CastToObjectType(tmp); if( tmpl == 0 ) { asCString str; @@ -1927,7 +2124,7 @@ asCObjectType* asCReader::ReadObjectType() } else if( ch == 'l' ) { - asCObjectType *st = ReadObjectType(); + asCObjectType *st = CastToObjectType(ReadTypeInfo()); if( st == 0 || st->beh.listFactory == 0 ) { Error(TXT_INVALID_BYTECODE_d); @@ -1972,10 +2169,10 @@ asCObjectType* asCReader::ReadObjectType() if( typeName.GetLength() && typeName != "$obj" && typeName != "$func" ) { // Find the object type - ot = module->GetObjectType(typeName.AddressOf(), nameSpace); - if( !ot ) - ot = engine->GetRegisteredObjectType(typeName.AddressOf(), nameSpace); - + ot = module->GetType(typeName.AddressOf(), nameSpace); + if (!ot) + ot = engine->GetRegisteredType(typeName.AddressOf(), nameSpace); + if( ot == 0 ) { asCString str; @@ -1996,6 +2193,36 @@ asCObjectType* asCReader::ReadObjectType() else asASSERT( false ); } + else if (ch == 'c') + { + // Read the object type name + asCString typeName, ns; + ReadString(&typeName); + + // Read the parent class + asCObjectType *parentClass = CastToObjectType(ReadTypeInfo()); + if (parentClass == 0) + { + Error(TXT_INVALID_BYTECODE_d); + return 0; + } + + // Find the child type in the parentClass + for (asUINT n = 0; n < parentClass->childFuncDefs.GetLength(); n++) + { + if (parentClass->childFuncDefs[n]->name == typeName) + ot = parentClass->childFuncDefs[n]; + } + + if (ot == 0) + { + asCString str; + str.Format(TXT_OBJECT_TYPE_s_DOESNT_EXIST, typeName.AddressOf()); + engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); + Error(TXT_INVALID_BYTECODE_d); + return 0; + } + } else { // No object type @@ -2151,7 +2378,7 @@ void asCReader::ReadByteCode(asCScriptFunction *func) w = ReadEncodedUInt16(); *(asWORD*)bc = w; bc++; - + // Read the third argument asDWORD dw = ReadEncodedUInt(); *bc++ = dw; @@ -2314,7 +2541,7 @@ void asCReader::ReadUsedObjectProps() usedObjectProperties.SetLength(c); for( asUINT n = 0; n < c; n++ ) { - asCObjectType *objType = ReadObjectType(); + asCObjectType *objType = CastToObjectType(ReadTypeInfo()); if( objType == 0 ) { Error(TXT_INVALID_BYTECODE_d); @@ -2324,14 +2551,14 @@ void asCReader::ReadUsedObjectProps() asCString name; ReadString(&name); - // Find the property offset + // Find the property bool found = false; for( asUINT p = 0; p < objType->properties.GetLength(); p++ ) { if( objType->properties[p]->name == name ) { usedObjectProperties[n].objType = objType; - usedObjectProperties[n].offset = objType->properties[p]->byteOffset; + usedObjectProperties[n].prop = objType->properties[p]; found = true; break; } @@ -2347,13 +2574,32 @@ void asCReader::ReadUsedObjectProps() short asCReader::FindObjectPropOffset(asWORD index) { + static asCObjectProperty *lastCompositeProp = 0; + if (lastCompositeProp) + { + if (index != 0) + { + Error(TXT_INVALID_BYTECODE_d); + return 0; + } + + short offset = (short)lastCompositeProp->byteOffset; + lastCompositeProp = 0; + return offset; + } + if( index >= usedObjectProperties.GetLength() ) { Error(TXT_INVALID_BYTECODE_d); return 0; } - return (short)usedObjectProperties[index].offset; + if (usedObjectProperties[index].prop->compositeOffset || usedObjectProperties[index].prop->isCompositeIndirect) + { + lastCompositeProp = usedObjectProperties[index].prop; + return (short)lastCompositeProp->compositeOffset; + } + return (short)usedObjectProperties[index].prop->byteOffset; } asCScriptFunction *asCReader::FindFunction(int idx) @@ -2398,13 +2644,13 @@ void asCReader::TranslateFunction(asCScriptFunction *func) for( n = 0; n < bcLength; bcNum++ ) { int c = *(asBYTE*)&bc[n]; - if( c == asBC_REFCPY || + if( c == asBC_REFCPY || c == asBC_RefCpyV || c == asBC_OBJTYPE ) { // Translate the index to the true object type asPWORD *ot = (asPWORD*)&bc[n+1]; - *(asCObjectType**)ot = FindObjectType(*(int*)ot); + *(asCObjectType**)ot = CastToObjectType(FindType(int(*ot))); } else if( c == asBC_TYPEID || c == asBC_Cast ) @@ -2449,7 +2695,7 @@ void asCReader::TranslateFunction(asCScriptFunction *func) int *tid = (int*)&bc[n+1]; *tid = FindTypeId(*tid); - // COPY is used to copy POD types that don't have the opAssign method. It is + // COPY is used to copy POD types that don't have the opAssign method. It is // also used to copy references to scoped types during variable initializations. // Update the number of dwords to copy as it may be different on the target platform if( (*tid) & asTYPEID_OBJHANDLE ) @@ -2496,13 +2742,13 @@ void asCReader::TranslateFunction(asCScriptFunction *func) { // Translate the index to the func pointer asPWORD *fid = (asPWORD*)&bc[n+1]; - *fid = (asPWORD)FindFunction((int)*fid); + *fid = (asPWORD)FindFunction(int(*fid)); } else if( c == asBC_ALLOC ) { // Translate the index to the true object type asPWORD *arg = (asPWORD*)&bc[n+1]; - *(asCObjectType**)arg = FindObjectType(*(int*)arg); + *(asCObjectType**)arg = CastToObjectType(FindType(int(*arg))); // The constructor function id must be translated, unless it is zero int *fid = (int*)&bc[n+1+AS_PTR_SIZE]; @@ -2521,16 +2767,8 @@ void asCReader::TranslateFunction(asCScriptFunction *func) } else if( c == asBC_STR ) { - // Translate the index to the true string id - asWORD *arg = ((asWORD*)&bc[n])+1; - - if( *arg < usedStringConstants.GetLength() ) - *arg = (asWORD)usedStringConstants[*arg]; - else - { - Error(TXT_INVALID_BYTECODE_d); - return; - } + Error(TXT_INVALID_BYTECODE_d); + return; } else if( c == asBC_CALLBND ) { @@ -2562,14 +2800,30 @@ void asCReader::TranslateFunction(asCScriptFunction *func) c == asBC_CpyVtoG4 || c == asBC_SetG4 ) { - // Translate the global var index to pointer - asPWORD *index = (asPWORD*)&bc[n+1]; - if( *(asUINT*)index < usedGlobalProperties.GetLength() ) - *(void**)index = usedGlobalProperties[*(asUINT*)index]; + // Translate the index to pointer + asPWORD *index = (asPWORD*)&bc[n + 1]; + if ((*index & 1)) + { + if ((asUINT(*index)>>1) < usedGlobalProperties.GetLength()) + *(void**)index = usedGlobalProperties[asUINT(*index)>>1]; + else + { + Error(TXT_INVALID_BYTECODE_d); + return; + } + } else { - Error(TXT_INVALID_BYTECODE_d); - return; + // Only PGA and PshGPtr can hold string constants + asASSERT(c == asBC_PGA || c == asBC_PshGPtr); + + if ((asUINT(*index)>>1) < usedStringConstants.GetLength()) + *(void**)index = usedStringConstants[asUINT(*index)>>1]; + else + { + Error(TXT_INVALID_BYTECODE_d); + return; + } } } else if( c == asBC_JMP || @@ -2582,7 +2836,7 @@ void asCReader::TranslateFunction(asCScriptFunction *func) c == asBC_JP || c == asBC_JNP ) // The JMPP instruction doesn't need modification { - // Get the offset + // Get the offset int offset = int(bc[n+1]); // Count the instruction sizes to the destination instruction @@ -2596,24 +2850,24 @@ void asCReader::TranslateFunction(asCScriptFunction *func) for( asUINT num = bcNum; offset++ < 0; num-- ) size -= bcSizes[num]; - // The size is dword offset + // The size is dword offset bc[n+1] = size; } else if( c == asBC_AllocMem ) { // The size of the allocated memory is only known after all the elements has been seen. - // This helper class will collect this information and adjust the size when the + // This helper class will collect this information and adjust the size when the // corresponding asBC_FREE is encountered // The adjuster also needs to know the list type so it can know the type of the elements - asCObjectType *ot = func->GetObjectTypeOfLocalVar(asBC_SWORDARG0(&bc[n])); + asCObjectType *ot = CastToObjectType(func->GetTypeInfoOfLocalVar(asBC_SWORDARG0(&bc[n]))); listAdjusters.PushLast(asNEW(SListAdjuster)(this, &bc[n], ot)); } else if( c == asBC_FREE ) { // Translate the index to the true object type asPWORD *pot = (asPWORD*)&bc[n+1]; - *(asCObjectType**)pot = FindObjectType(*(int*)pot); + *(asCObjectType**)pot = CastToObjectType(FindType(int(*pot))); asCObjectType *ot = *(asCObjectType**)pot; if( ot && (ot->flags & asOBJ_LIST_PATTERN) ) @@ -2722,17 +2976,14 @@ void asCReader::TranslateFunction(asCScriptFunction *func) // objVariablePos for( n = 0; n < func->scriptData->objVariablePos.GetLength(); n++ ) - { func->scriptData->objVariablePos[n] = AdjustStackPosition(func->scriptData->objVariablePos[n]); - func->scriptData->funcVariableTypes[n] = FindFunction((int)(asPWORD)func->scriptData->funcVariableTypes[n]); - } // Adjust the get offsets. This must be done in the second iteration because - // it relies on the function ids and variable position already being correct in the + // it relies on the function ids and variable position already being correct in the // bytecodes that come after the GET instructions. // TODO: optimize: Instead of doing a full extra loop. We can push the GET instructions // on a stack, and then when a call instruction is found update all of them. - // This will also make the AdjustGetOffset() function quicker as it can + // This will also make the AdjustGetOffset() function quicker as it can // receive the called function directly instead of having to search for it. bc = func->scriptData->byteCode.AddressOf(); for( n = 0; n < bcLength; ) @@ -2741,7 +2992,8 @@ void asCReader::TranslateFunction(asCScriptFunction *func) if( c == asBC_GETREF || c == asBC_GETOBJ || - c == asBC_GETOBJREF ) + c == asBC_GETOBJREF || + c == asBC_ChkNullS ) { asBC_WORDARG0(&bc[n]) = (asWORD)AdjustGetOffset(asBC_WORDARG0(&bc[n]), func, n); } @@ -2757,7 +3009,7 @@ void asCReader::TranslateFunction(asCScriptFunction *func) } // The program position (every even number) needs to be adjusted - // for the line numbers to be in number of dwords instead of number of instructions + // for the line numbers to be in number of dwords instead of number of instructions for( n = 0; n < func->scriptData->lineNumbers.GetLength(); n += 2 ) func->scriptData->lineNumbers[n] = instructionNbrToPos[func->scriptData->lineNumbers[n]]; for( n = 0; n < func->scriptData->sectionIdxs.GetLength(); n += 2 ) @@ -2766,7 +3018,7 @@ void asCReader::TranslateFunction(asCScriptFunction *func) CalculateStackNeeded(func); } -asCReader::SListAdjuster::SListAdjuster(asCReader *rd, asDWORD *bc, asCObjectType *listType) : +asCReader::SListAdjuster::SListAdjuster(asCReader *rd, asDWORD *bc, asCObjectType *listType) : reader(rd), allocMemBC(bc), maxOffset(0), patternType(listType), repeatCount(0), lastOffset(-1), nextOffset(0), nextTypeId(-1) { asASSERT( patternType && (patternType->flags & asOBJ_LIST_PATTERN) ); @@ -2817,12 +3069,12 @@ int asCReader::SListAdjuster::AdjustOffset(int offset) if( repeatCount > 0 ) repeatCount--; - asCDataType dt = patternType->engine->GetDataTypeFromTypeId(nextTypeId); + asCDataType nextdt = patternType->engine->GetDataTypeFromTypeId(nextTypeId); asUINT size; - if( dt.IsObjectHandle() || (dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_REF)) ) + if(nextdt.IsObjectHandle() || (nextdt.GetTypeInfo() && (nextdt.GetTypeInfo()->flags & asOBJ_REF)) ) size = AS_PTR_SIZE*4; else - size = dt.GetSizeInMemoryBytes(); + size = nextdt.GetSizeInMemoryBytes(); // Align the offset to 4 bytes boundary if( size >= 4 && (maxOffset & 0x3) ) @@ -2860,8 +3112,7 @@ int asCReader::SListAdjuster::AdjustOffset(int offset) { // Determine the size of the element asUINT size; - asCDataType dt = reinterpret_cast(patternNode)->dataType; - if( dt.IsObjectHandle() || (dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_REF)) ) + if( dt.IsObjectHandle() || (dt.GetTypeInfo() && (dt.GetTypeInfo()->flags & asOBJ_REF)) ) size = AS_PTR_SIZE*4; else size = dt.GetSizeInMemoryBytes(); @@ -2964,7 +3215,7 @@ void asCReader::CalculateStackNeeded(asCScriptFunction *func) stackSize.SetLength(func->scriptData->byteCode.GetLength()); memset(&stackSize[0], -1, stackSize.GetLength()*4); - // Add the first instruction to the list of unchecked code + // Add the first instruction to the list of unchecked code // paths and set the stack size at that instruction to variableSpace asCArray paths; paths.PushLast(0); @@ -2975,7 +3226,7 @@ void asCReader::CalculateStackNeeded(asCScriptFunction *func) { asUINT pos = paths[p]; int currStackSize = stackSize[pos]; - + asBYTE bc = *(asBYTE*)&func->scriptData->byteCode[pos]; if( bc == asBC_RET ) continue; @@ -3010,7 +3261,7 @@ void asCReader::CalculateStackNeeded(asCScriptFunction *func) } } } - + currStackSize += stackInc; asASSERT( currStackSize >= 0 ); @@ -3040,7 +3291,7 @@ void asCReader::CalculateStackNeeded(asCScriptFunction *func) { // Find the label that is being jumped to int offset = asBC_INTARG(&func->scriptData->byteCode[pos]); - + // Add both paths to the code paths pos += 2; if( stackSize[pos] == -1 ) @@ -3065,7 +3316,7 @@ void asCReader::CalculateStackNeeded(asCScriptFunction *func) else if( bc == asBC_JMPP ) { pos++; - + // Add all subsequent JMP instructions to the path while( *(asBYTE*)&func->scriptData->byteCode[pos] == asBC_JMP ) { @@ -3077,8 +3328,8 @@ void asCReader::CalculateStackNeeded(asCScriptFunction *func) else asASSERT(stackSize[pos] == currStackSize); pos += 2; - } - continue; + } + continue; } else { @@ -3101,7 +3352,7 @@ void asCReader::CalculateStackNeeded(asCScriptFunction *func) void asCReader::CalculateAdjustmentByPos(asCScriptFunction *func) { - // Adjust the offset of all negative variables (parameters) as + // Adjust the offset of all negative variables (parameters) as // all pointers have been stored as having a size of 1 dword asUINT n; asCArray adjustments; @@ -3146,35 +3397,35 @@ void asCReader::CalculateAdjustmentByPos(asCScriptFunction *func) adjustNegativeStackByPos[i] += adjust; } - // The bytecode has been stored as if all object variables take up only 1 dword. + // The bytecode has been stored as if all object variables take up only 1 dword. // It is necessary to adjust to the size according to the current platform. adjustments.SetLength(0); int highestPos = 0; for( n = 0; n < func->scriptData->objVariableTypes.GetLength(); n++ ) { - if( func->scriptData->objVariableTypes[n] ) + // Determine the size the variable currently occupies on the stack + int size = AS_PTR_SIZE; + + // objVariableTypes is null if the type is a null pointer + if( func->scriptData->objVariableTypes[n] && + (func->scriptData->objVariableTypes[n]->GetFlags() & asOBJ_VALUE) && + n >= func->scriptData->objVariablesOnHeap ) { - // Determine the size the variable currently occupies on the stack - int size = AS_PTR_SIZE; - if( (func->scriptData->objVariableTypes[n]->GetFlags() & asOBJ_VALUE) && - n >= func->scriptData->objVariablesOnHeap ) - { - size = func->scriptData->objVariableTypes[n]->GetSize(); - if( size < 4 ) - size = 1; - else - size /= 4; - } + size = func->scriptData->objVariableTypes[n]->GetSize(); + if( size < 4 ) + size = 1; + else + size /= 4; + } - // Check if type has a different size than stored - if( size > 1 ) - { - if( func->scriptData->objVariablePos[n] > highestPos ) - highestPos = func->scriptData->objVariablePos[n]; + // Check if type has a different size than stored + if( size > 1 ) + { + if( func->scriptData->objVariablePos[n] > highestPos ) + highestPos = func->scriptData->objVariablePos[n]; - adjustments.PushLast(func->scriptData->objVariablePos[n]); - adjustments.PushLast(size-1); - } + adjustments.PushLast(func->scriptData->objVariablePos[n]); + adjustments.PushLast(size-1); } } @@ -3201,7 +3452,7 @@ int asCReader::AdjustStackPosition(int pos) if( adjustByPos.GetLength() ) pos += (short)adjustByPos[adjustByPos.GetLength()-1]; } - else if( pos >= 0 ) + else if( pos >= 0 ) pos += (short)adjustByPos[pos]; else if( -pos >= (int)adjustNegativeStackByPos.GetLength() ) Error(TXT_INVALID_BYTECODE_d); @@ -3244,7 +3495,7 @@ asCScriptFunction *asCReader::GetCalledFunction(asCScriptFunction *func, asDWORD // Find the funcdef from the local variable for( v = 0; v < func->scriptData->objVariablePos.GetLength(); v++ ) if( func->scriptData->objVariablePos[v] == var ) - return func->scriptData->funcVariableTypes[v]; + return CastToFuncdefType(func->scriptData->objVariableTypes[v])->funcdef; // Look in parameters int paramPos = 0; @@ -3254,8 +3505,16 @@ asCScriptFunction *asCReader::GetCalledFunction(asCScriptFunction *func, asDWORD paramPos -= AS_PTR_SIZE; for( v = 0; v < func->parameterTypes.GetLength(); v++ ) { - if( var == paramPos ) - return func->parameterTypes[v].GetFuncDef(); + if (var == paramPos) + { + if (func->parameterTypes[v].IsFuncdef()) + return CastToFuncdefType(func->parameterTypes[v].GetTypeInfo())->funcdef; + else + { + error = true; + return 0; + } + } paramPos -= func->parameterTypes[v].GetSizeOnStackDWords(); } } @@ -3271,6 +3530,8 @@ int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog // Get offset 0 doesn't need adjustment if( offset == 0 ) return 0; + bool bcAlloc = false; + // Find out which function that will be called asCScriptFunction *calledFunc = 0; int stackDelta = 0; @@ -3280,11 +3541,16 @@ int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog if( bc == asBC_CALL || bc == asBC_CALLSYS || bc == asBC_Thiscall1 || - bc == asBC_CALLINTF || + bc == asBC_CALLINTF || bc == asBC_ALLOC || bc == asBC_CALLBND || bc == asBC_CallPtr ) { + // The alloc instruction allocates the object memory + // so it doesn't take the this pointer as input + if (bc == asBC_ALLOC) + bcAlloc = true; + calledFunc = GetCalledFunction(func, n); break; } @@ -3296,7 +3562,7 @@ int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog return offset - (1 - AS_PTR_SIZE); } - // Keep track of the stack size between the + // Keep track of the stack size between the // instruction that needs to be adjusted and the call stackDelta += asBCInfo[bc].stackInc; @@ -3309,17 +3575,17 @@ int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog return offset; } - // Count the number of pointers pushed on the stack above the + // Count the number of pointers pushed on the stack above the // current offset, and then adjust the offset accordingly asUINT numPtrs = 0; int currOffset = -stackDelta; - if( offset > currOffset && calledFunc->GetObjectType() ) + if( offset > currOffset && calledFunc->GetObjectType() && !bcAlloc ) { currOffset++; if( currOffset > 0 ) numPtrs++; #if AS_PTR_SIZE == 2 - // For 64bit platforms it is necessary to increment the currOffset by one more + // For 64bit platforms it is necessary to increment the currOffset by one more // DWORD since the stackDelta was counting the full 64bit size of the pointer else if( stackDelta ) currOffset++; @@ -3331,7 +3597,7 @@ int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog if( currOffset > 0 ) numPtrs++; #if AS_PTR_SIZE == 2 - // For 64bit platforms it is necessary to increment the currOffset by one more + // For 64bit platforms it is necessary to increment the currOffset by one more // DWORD since the stackDelta was counting the full 64bit size of the pointer else if( stackDelta ) currOffset++; @@ -3348,7 +3614,7 @@ int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog if( currOffset > 0 ) numPtrs++; #if AS_PTR_SIZE == 2 - // For 64bit platforms it is necessary to increment the currOffset by one more + // For 64bit platforms it is necessary to increment the currOffset by one more // DWORD since the stackDelta was counting the full 64bit size of the pointer else if( stackDelta ) currOffset++; @@ -3380,7 +3646,7 @@ int asCReader::FindTypeId(int idx) } } -asCObjectType *asCReader::FindObjectType(int idx) +asCTypeInfo *asCReader::FindType(int idx) { if( idx < 0 || idx >= (int)usedTypes.GetLength() ) { @@ -3394,23 +3660,42 @@ asCObjectType *asCReader::FindObjectType(int idx) #ifndef AS_NO_COMPILER asCWriter::asCWriter(asCModule* _module, asIBinaryStream* _stream, asCScriptEngine* _engine, bool _stripDebug) - : module(_module), stream(_stream), engine(_engine), stripDebugInfo(_stripDebug) + : module(_module), stream(_stream), engine(_engine), stripDebugInfo(_stripDebug), error(false), bytesWritten(0) { } -void asCWriter::WriteData(const void *data, asUINT size) +int asCWriter::Error(const char *msg) +{ + // Don't write if it has already been reported an error earlier + if (!error) + { + asCString str; + str.Format(msg, bytesWritten); + engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); + error = true; + } + + return asERROR; +} + +int asCWriter::WriteData(const void *data, asUINT size) { asASSERT(size == 1 || size == 2 || size == 4 || size == 8); + int ret = 0; #if defined(AS_BIG_ENDIAN) - for( asUINT n = 0; n < size; n++ ) - stream->Write(((asBYTE*)data)+n, 1); + for( asUINT n = 0; ret >= 0 && n < size; n++ ) + ret = stream->Write(((asBYTE*)data)+n, 1); #else - for( int n = size-1; n >= 0; n-- ) - stream->Write(((asBYTE*)data)+n, 1); + for( int n = size-1; ret >= 0 && n >= 0; n-- ) + ret = stream->Write(((asBYTE*)data)+n, 1); #endif + if (ret < 0) + Error(TXT_UNEXPECTED_END_OF_FILE); + bytesWritten += size; + return ret; } -int asCWriter::Write() +int asCWriter::Write() { TimeIt("asCWriter::Write"); @@ -3421,7 +3706,9 @@ int asCWriter::Write() // TODO: Should be possible to skip saving the enum values. They are usually not needed after the script is compiled anyway // TODO: Should be possible to skip saving the typedefs. They are usually not needed after the script is compiled anyway // TODO: Should be possible to skip saving constants. They are usually not needed after the script is compiled anyway - WriteData(&stripDebugInfo, sizeof(stripDebugInfo)); + + // Write the flag as 1byte even on platforms with 4byte booleans + WriteEncodedInt64(stripDebugInfo ? 1 : 0); // Store enums { @@ -3431,8 +3718,8 @@ int asCWriter::Write() WriteEncodedInt64(count); for( i = 0; i < count; i++ ) { - WriteObjectTypeDeclaration(module->enumTypes[i], 1); - WriteObjectTypeDeclaration(module->enumTypes[i], 2); + WriteTypeDeclaration(module->enumTypes[i], 1); + WriteTypeDeclaration(module->enumTypes[i], 2); } } @@ -3445,7 +3732,7 @@ int asCWriter::Write() for( i = 0; i < count; i++ ) { // Store only the name of the class/interface types - WriteObjectTypeDeclaration(module->classTypes[i], 1); + WriteTypeDeclaration(module->classTypes[i], 1); } } @@ -3456,7 +3743,7 @@ int asCWriter::Write() count = (asUINT)module->funcDefs.GetLength(); WriteEncodedInt64(count); for( i = 0; i < count; i++ ) - WriteFunction(module->funcDefs[i]); + WriteFunction(module->funcDefs[i]->funcdef); } // Now store all interface methods @@ -3467,7 +3754,7 @@ int asCWriter::Write() for( i = 0; i < count; i++ ) { if( module->classTypes[i]->IsInterface() ) - WriteObjectTypeDeclaration(module->classTypes[i], 2); + WriteTypeDeclaration(module->classTypes[i], 2); } } @@ -3478,7 +3765,7 @@ int asCWriter::Write() for( i = 0; i < count; ++i ) { if( !module->classTypes[i]->IsInterface() ) - WriteObjectTypeDeclaration(module->classTypes[i], 2); + WriteTypeDeclaration(module->classTypes[i], 2); } } @@ -3489,7 +3776,7 @@ int asCWriter::Write() for( i = 0; i < count; ++i ) { if( !module->classTypes[i]->IsInterface() ) - WriteObjectTypeDeclaration(module->classTypes[i], 3); + WriteTypeDeclaration(module->classTypes[i], 3); } } @@ -3501,8 +3788,8 @@ int asCWriter::Write() WriteEncodedInt64(count); for( i = 0; i < count; i++ ) { - WriteObjectTypeDeclaration(module->typeDefs[i], 1); - WriteObjectTypeDeclaration(module->typeDefs[i], 2); + WriteTypeDeclaration(module->typeDefs[i], 1); + WriteTypeDeclaration(module->typeDefs[i], 2); } } @@ -3565,7 +3852,7 @@ int asCWriter::Write() count = (asUINT)usedTypes.GetLength(); WriteEncodedInt64(count); for( i = 0; i < count; ++i ) - WriteObjectType(usedTypes[i]); + WriteTypeInfo(usedTypes[i]); } // usedTypeIds[] @@ -3583,18 +3870,18 @@ int asCWriter::Write() // usedObjectProperties[] WriteUsedObjectProps(); - return asSUCCESS; + return error ? asERROR : asSUCCESS; } -int asCWriter::FindStringConstantIndex(int id) +int asCWriter::FindStringConstantIndex(void *str) { - asSMapNode *cursor = 0; - if (stringIdToIndexMap.MoveTo(&cursor, id)) + asSMapNode *cursor = 0; + if (stringToIndexMap.MoveTo(&cursor, str)) return cursor->value; - usedStringConstants.PushLast(id); + usedStringConstants.PushLast(str); int index = int(usedStringConstants.GetLength() - 1); - stringIdToIndexMap.Insert(id, index); + stringToIndexMap.Insert(str, index); return index; } @@ -3604,8 +3891,16 @@ void asCWriter::WriteUsedStringConstants() asUINT count = (asUINT)usedStringConstants.GetLength(); WriteEncodedInt64(count); - for( asUINT i = 0; i < count; ++i ) - WriteString(engine->stringConstants[usedStringConstants[i]]); + + asCString str; + for (asUINT i = 0; i < count; ++i) + { + asUINT length; + engine->stringFactory->GetRawStringData(usedStringConstants[i], 0, &length); + str.SetLength(length); + engine->stringFactory->GetRawStringData(usedStringConstants[i], str.AddressOf(), &length); + WriteString(&str); + } } void asCWriter::WriteUsedFunctions() @@ -3620,18 +3915,24 @@ void asCWriter::WriteUsedFunctions() char c; // Write enough data to be able to uniquely identify the function upon load - - if( usedFunctions[n] ) + asCScriptFunction *func = usedFunctions[n]; + if(func) { // Is the function from the module or the application? - c = usedFunctions[n]->module ? 'm' : 'a'; + c = func->module ? 'm' : 'a'; + + // Functions and methods that are shared and not owned by the module can be + // stored as 's' to tell the reader that these are received from other modules. + if (c == 'm' && func->IsShared() && module->scriptFunctions.IndexOf(func) < 0 ) + c = 's'; + WriteData(&c, 1); - WriteFunctionSignature(usedFunctions[n]); + WriteFunctionSignature(func); } else { // null function pointer - c = 'n'; + c = 'n'; WriteData(&c, 1); } } @@ -3652,9 +3953,9 @@ void asCWriter::WriteFunctionSignature(asCScriptFunction *func) count = (asUINT)func->parameterTypes.GetLength(); WriteEncodedInt64(count); - for( i = 0; i < count; ++i ) + for( i = 0; i < count; ++i ) WriteDataType(&func->parameterTypes[i]); - + // Only write the inout flags if any of them are set count = 0; for( i = asUINT(func->inOutFlags.GetLength()); i > 0; i-- ) @@ -3679,23 +3980,41 @@ void asCWriter::WriteFunctionSignature(asCScriptFunction *func) if( func->defaultArgs[i] ) WriteString(func->defaultArgs[i]); - WriteObjectType(func->objectType); + WriteTypeInfo(func->objectType); if( func->objectType ) { asBYTE b = 0; - b += func->isReadOnly ? 1 : 0; - b += func->isPrivate ? 2 : 0; - b += func->isProtected ? 4 : 0; + b += func->IsReadOnly() ? 1 : 0; + b += func->IsPrivate() ? 2 : 0; + b += func->IsProtected() ? 4 : 0; WriteData(&b, 1); } else { - WriteString(&func->nameSpace->name); + if (func->funcType == asFUNC_FUNCDEF) + { + if (func->nameSpace) + { + // This funcdef was declared as global entity + asBYTE b = 'n'; + WriteData(&b, 1); + WriteString(&func->nameSpace->name); + } + else + { + // This funcdef was declared as class member + asBYTE b = 'o'; + WriteData(&b, 1); + WriteTypeInfo(func->funcdefType->parentClass); + } + } + else + WriteString(&func->nameSpace->name); } } -void asCWriter::WriteFunction(asCScriptFunction* func) +void asCWriter::WriteFunction(asCScriptFunction* func) { char c; @@ -3731,6 +4050,17 @@ void asCWriter::WriteFunction(asCScriptFunction* func) if( func->funcType == asFUNC_SCRIPT ) { + char bits = 0; + bits += func->IsShared() ? 1 : 0; + bits += func->dontCleanUpOnException ? 2 : 0; + if (module->externalFunctions.IndexOf(func) >= 0) + bits += 4; + WriteData(&bits, 1); + + // For external shared functions the rest is not needed + if (bits & 4) + return; + // Calculate the adjustment by position lookup table CalculateAdjustmentByPos(func); @@ -3743,9 +4073,7 @@ void asCWriter::WriteFunction(asCScriptFunction* func) WriteEncodedInt64(count); for( i = 0; i < count; ++i ) { - WriteObjectType(func->scriptData->objVariableTypes[i]); - // TODO: Only write this if the object type is the builtin function type - WriteEncodedInt64(FindFunctionIndex(func->scriptData->funcVariableTypes[i])); + WriteTypeInfo(func->scriptData->objVariableTypes[i]); WriteEncodedInt64(AdjustStackPosition(func->scriptData->objVariablePos[i])); } if( count > 0 ) @@ -3787,7 +4115,7 @@ void asCWriter::WriteFunction(asCScriptFunction* func) WriteString(engine->scriptSectionNames[func->scriptData->sectionIdxs[i]]); else { - char c = 0; + c = 0; WriteData(&c, 1); } } @@ -3809,11 +4137,6 @@ void asCWriter::WriteFunction(asCScriptFunction* func) } } - char bits = 0; - bits += func->isShared ? 1 : 0; - bits += func->dontCleanUpOnException ? 2 : 0; - WriteData(&bits,1); - // Store script section name if( !stripDebugInfo ) { @@ -3821,7 +4144,7 @@ void asCWriter::WriteFunction(asCScriptFunction* func) WriteString(engine->scriptSectionNames[func->scriptData->scriptSectionIdx]); else { - char c = 0; + c = 0; WriteData(&c, 1); } WriteEncodedInt64(func->scriptData->declaredAt); @@ -3830,7 +4153,7 @@ void asCWriter::WriteFunction(asCScriptFunction* func) // Store the parameter names if( !stripDebugInfo ) { - asUINT count = asUINT(func->parameterNames.GetLength()); + count = asUINT(func->parameterNames.GetLength()); WriteEncodedInt64(count); for( asUINT n = 0; n < count; n++ ) WriteString(&func->parameterNames[n]); @@ -3844,117 +4167,144 @@ void asCWriter::WriteFunction(asCScriptFunction* func) else if( func->funcType == asFUNC_FUNCDEF ) { char bits = 0; - bits += func->isShared ? 1 : 0; + bits += func->IsShared() ? 1 : 0; + if (module->externalTypes.IndexOf(func->funcdefType) >= 0) + bits += 2; WriteData(&bits,1); } } -void asCWriter::WriteObjectTypeDeclaration(asCObjectType *ot, int phase) +void asCWriter::WriteTypeDeclaration(asCTypeInfo *type, int phase) { if( phase == 1 ) { // name - WriteString(&ot->name); + WriteString(&type->name); // flags - WriteData(&ot->flags, 4); + WriteData(&type->flags, 4); // size - // TODO: Do we really need to store this? The reader should be able to + // TODO: Do we really need to store this? The reader should be able to // determine the correct size from the object type's flags - if( (ot->flags & asOBJ_SCRIPT_OBJECT) && ot->size > 0 ) + if( (type->flags & asOBJ_SCRIPT_OBJECT) && type->size > 0 ) { - // The size for script objects may vary from platform to platform so + // The size for script objects may vary from platform to platform so // only store 1 to diferentiate from interfaces that have size 0. - WriteEncodedInt64(1); + WriteEncodedInt64(1); } else { // Enums, typedefs, and interfaces have fixed sizes independently // of platform so it is safe to serialize the size directly. - WriteEncodedInt64(ot->size); + WriteEncodedInt64(type->size); } // namespace - WriteString(&ot->nameSpace->name); + WriteString(&type->nameSpace->name); + + // external shared flag + if ((type->flags & asOBJ_SHARED)) + { + char c = ' '; + if (module->externalTypes.IndexOf(type) >= 0) + c = 'e'; + WriteData(&c, 1); + } } else if( phase == 2 ) { - if( ot->flags & asOBJ_ENUM ) + // external shared types doesn't need to save this + if ((type->flags & asOBJ_SHARED) && module->externalTypes.IndexOf(type) >= 0) + return; + + if(type->flags & asOBJ_ENUM ) { // enumValues[] - int size = (int)ot->enumValues.GetLength(); + asCEnumType *t = CastToEnumType(type); + int size = (int)t->enumValues.GetLength(); WriteEncodedInt64(size); for( int n = 0; n < size; n++ ) { - WriteString(&ot->enumValues[n]->name); - WriteData(&ot->enumValues[n]->value, 4); + WriteString(&t->enumValues[n]->name); + WriteData(&t->enumValues[n]->value, 4); } } - else if( ot->flags & asOBJ_TYPEDEF ) + else if(type->flags & asOBJ_TYPEDEF ) { - eTokenType t = ot->templateSubTypes[0].GetTokenType(); + asCTypedefType *td = CastToTypedefType(type); + eTokenType t = td->aliasForType.GetTokenType(); WriteEncodedInt64(t); } else { - WriteObjectType(ot->derivedFrom); + asCObjectType *t = CastToObjectType(type); + WriteTypeInfo(t->derivedFrom); // interfaces[] / interfaceVFTOffsets[] // TOOD: Is it really necessary to store the VFTOffsets? Can't the reader calculate those? - int size = (asUINT)ot->interfaces.GetLength(); + int size = (asUINT)t->interfaces.GetLength(); WriteEncodedInt64(size); asUINT n; - asASSERT( ot->interfaces.GetLength() == ot->interfaceVFTOffsets.GetLength() ); - for( n = 0; n < ot->interfaces.GetLength(); n++ ) + asASSERT( t->interfaces.GetLength() == t->interfaceVFTOffsets.GetLength() ); + for( n = 0; n < t->interfaces.GetLength(); n++ ) { - WriteObjectType(ot->interfaces[n]); - WriteEncodedInt64(ot->interfaceVFTOffsets[n]); + WriteTypeInfo(t->interfaces[n]); + WriteEncodedInt64(t->interfaceVFTOffsets[n]); } // behaviours - // TODO: Default behaviours should just be stored as a indicator + // TODO: Default behaviours should just be stored as a indicator // to avoid storing the actual function object - if( !ot->IsInterface() && ot->flags != asOBJ_TYPEDEF && ot->flags != asOBJ_ENUM ) + if( !t->IsInterface() && type->flags != asOBJ_TYPEDEF && type->flags != asOBJ_ENUM ) { - WriteFunction(engine->scriptFunctions[ot->beh.destruct]); - size = (int)ot->beh.constructors.GetLength(); + WriteFunction(engine->scriptFunctions[t->beh.destruct]); + size = (int)t->beh.constructors.GetLength(); WriteEncodedInt64(size); - for( n = 0; n < ot->beh.constructors.GetLength(); n++ ) + for( n = 0; n < t->beh.constructors.GetLength(); n++ ) { - WriteFunction(engine->scriptFunctions[ot->beh.constructors[n]]); - WriteFunction(engine->scriptFunctions[ot->beh.factories[n]]); + WriteFunction(engine->scriptFunctions[t->beh.constructors[n]]); + WriteFunction(engine->scriptFunctions[t->beh.factories[n]]); } } // methods[] // TODO: Avoid storing inherited methods in interfaces, as the reader // can add those directly from the base interface - size = (int)ot->methods.GetLength(); + size = (int)t->methods.GetLength(); WriteEncodedInt64(size); - for( n = 0; n < ot->methods.GetLength(); n++ ) + for( n = 0; n < t->methods.GetLength(); n++ ) { - WriteFunction(engine->scriptFunctions[ot->methods[n]]); + WriteFunction(engine->scriptFunctions[t->methods[n]]); } // virtualFunctionTable[] // TODO: Is it really necessary to store this? Can't it be easily rebuilt by the reader - size = (int)ot->virtualFunctionTable.GetLength(); + size = (int)t->virtualFunctionTable.GetLength(); WriteEncodedInt64(size); for( n = 0; n < (asUINT)size; n++ ) { - WriteFunction(ot->virtualFunctionTable[n]); + WriteFunction(t->virtualFunctionTable[n]); } } } else if( phase == 3 ) { + // external shared types doesn't need to save this + if ((type->flags & asOBJ_SHARED) && module->externalTypes.IndexOf(type) >= 0) + return; + // properties[] - asUINT size = (asUINT)ot->properties.GetLength(); + asCObjectType *t = CastToObjectType(type); + + // This is only done for object types + asASSERT(t); + + asUINT size = (asUINT)t->properties.GetLength(); WriteEncodedInt64(size); - for( asUINT n = 0; n < ot->properties.GetLength(); n++ ) + for (asUINT n = 0; n < t->properties.GetLength(); n++) { - WriteObjectProperty(ot->properties[n]); + WriteObjectProperty(t->properties[n]); } } } @@ -4014,7 +4364,7 @@ void asCWriter::WriteEncodedInt64(asINT64 i) b = asBYTE((i >> 8) & 0xFF); WriteData(&b, 1); b = asBYTE(i & 0xFF); WriteData(&b, 1); } - else + else { b = asBYTE(0x7F + signBit); WriteData(&b, 1); b = asBYTE((i >> 56) & 0xFF); WriteData(&b, 1); @@ -4028,11 +4378,11 @@ void asCWriter::WriteEncodedInt64(asINT64 i) } } -void asCWriter::WriteString(asCString* str) +void asCWriter::WriteString(asCString* str) { // First check if the string hasn't been saved already - asSMapNode *cursor = 0; - if (stringToIdMap.MoveTo(&cursor, asCStringPointer(str))) + asSMapNode *cursor = 0; + if (stringToIdMap.MoveTo(&cursor, *str)) { // Save a reference to the existing string // The lowest bit is set to 1 to indicate a reference @@ -4048,16 +4398,17 @@ void asCWriter::WriteString(asCString* str) if( len > 0 ) { stream->Write(str->AddressOf(), (asUINT)len); + bytesWritten += len; savedStrings.PushLast(*str); - stringToIdMap.Insert(asCStringPointer(str), int(savedStrings.GetLength()) - 1); + stringToIdMap.Insert(*str, int(savedStrings.GetLength()) - 1); } } -void asCWriter::WriteGlobalProperty(asCGlobalProperty* prop) +void asCWriter::WriteGlobalProperty(asCGlobalProperty* prop) { - // TODO: We might be able to avoid storing the name and type of the global - // properties twice if we merge this with the WriteUsedGlobalProperties. + // TODO: We might be able to avoid storing the name and type of the global + // properties twice if we merge this with the WriteUsedGlobalProperties. WriteString(&prop->name); WriteString(&prop->nameSpace->name); WriteDataType(&prop->type); @@ -4066,7 +4417,7 @@ void asCWriter::WriteGlobalProperty(asCGlobalProperty* prop) WriteFunction(prop->GetInitFunc()); } -void asCWriter::WriteObjectProperty(asCObjectProperty* prop) +void asCWriter::WriteObjectProperty(asCObjectProperty* prop) { WriteString(&prop->name); WriteDataType(&prop->type); @@ -4077,7 +4428,7 @@ void asCWriter::WriteObjectProperty(asCObjectProperty* prop) WriteEncodedInt64(flags); } -void asCWriter::WriteDataType(const asCDataType *dt) +void asCWriter::WriteDataType(const asCDataType *dt) { // First check if the datatype has already been saved for( asUINT n = 0; n < savedDataTypes.GetLength(); n++ ) @@ -4099,47 +4450,37 @@ void asCWriter::WriteDataType(const asCDataType *dt) int t = dt->GetTokenType(); WriteEncodedInt64(t); if( t == ttIdentifier ) - WriteObjectType(dt->GetObjectType()); + WriteTypeInfo(dt->GetTypeInfo()); - struct - { - char isObjectHandle :1; - char isHandleToConst:1; - char isReference :1; - char isReadOnly :1; - } bits = {0}; - - bits.isObjectHandle = dt->IsObjectHandle(); - bits.isHandleToConst = dt->IsHandleToConst(); - bits.isReference = dt->IsReference(); - bits.isReadOnly = dt->IsReadOnly(); + // Endianess safe bitmask + char bits = 0; + SAVE_TO_BIT(bits, dt->IsObjectHandle(), 0); + SAVE_TO_BIT(bits, dt->IsHandleToConst(), 1); + SAVE_TO_BIT(bits, dt->IsReference(), 2); + SAVE_TO_BIT(bits, dt->IsReadOnly(), 3); WriteData(&bits, 1); - - if( t == ttIdentifier && dt->GetObjectType()->name == "$func" ) - { - WriteFunctionSignature(dt->GetFuncDef()); - } } -void asCWriter::WriteObjectType(asCObjectType* ot) +void asCWriter::WriteTypeInfo(asCTypeInfo* ti) { char ch; - if( ot ) + if( ti ) { // Check for template instances/specializations - if( ot->templateSubTypes.GetLength() ) + asCObjectType *ot = CastToObjectType(ti); + if( ot && ot->templateSubTypes.GetLength() ) { // Check for list pattern type or template type if( ot->flags & asOBJ_LIST_PATTERN ) { - ch = 'l'; + ch = 'l'; // list WriteData(&ch, 1); - WriteObjectType(ot->templateSubTypes[0].GetObjectType()); + WriteTypeInfo(ot->templateSubTypes[0].GetTypeInfo()); } else { - ch = 'a'; + ch = 'a'; // array WriteData(&ch, 1); WriteString(&ot->name); WriteString(&ot->nameSpace->name); @@ -4147,15 +4488,15 @@ void asCWriter::WriteObjectType(asCObjectType* ot) WriteEncodedInt64(ot->templateSubTypes.GetLength()); for( asUINT n = 0; n < ot->templateSubTypes.GetLength(); n++ ) { - if( ot->templateSubTypes[n].IsObject() || ot->templateSubTypes[n].IsEnumType() ) + if( !ot->templateSubTypes[n].IsPrimitive() || ot->templateSubTypes[n].IsEnumType() ) { - ch = 's'; + ch = 's'; // sub type WriteData(&ch, 1); WriteDataType(&ot->templateSubTypes[n]); } else { - ch = 't'; + ch = 't'; // token WriteData(&ch, 1); eTokenType t = ot->templateSubTypes[n].GetTokenType(); WriteEncodedInt64(t); @@ -4163,18 +4504,27 @@ void asCWriter::WriteObjectType(asCObjectType* ot) } } } - else if( ot->flags & asOBJ_TEMPLATE_SUBTYPE ) + else if( ti->flags & asOBJ_TEMPLATE_SUBTYPE ) { - ch = 's'; + ch = 's'; // sub type WriteData(&ch, 1); - WriteString(&ot->name); + WriteString(&ti->name); + } + else if( !ti->GetParentType() ) + { + ch = 'o'; // object + WriteData(&ch, 1); + WriteString(&ti->name); + WriteString(&ti->nameSpace->name); } else { - ch = 'o'; + asASSERT(ti->flags & asOBJ_FUNCDEF); + + ch = 'c'; // child type WriteData(&ch, 1); - WriteString(&ot->name); - WriteString(&ot->nameSpace->name); + WriteString(&ti->name); + WriteTypeInfo(CastToFuncdefType(ti)->parentClass); } } else @@ -4235,27 +4585,27 @@ void asCWriter::CalculateAdjustmentByPos(asCScriptFunction *func) adjustments.SetLength(0); for( n = 0; n < func->scriptData->objVariableTypes.GetLength(); n++ ) { - if( func->scriptData->objVariableTypes[n] ) - { - // Determine the size the variable currently occupies on the stack - int size = AS_PTR_SIZE; - if( (func->scriptData->objVariableTypes[n]->GetFlags() & asOBJ_VALUE) && - n >= func->scriptData->objVariablesOnHeap ) - { - size = func->scriptData->objVariableTypes[n]->GetSize(); - if( size < 4 ) - size = 1; - else - size /= 4; - } + // Determine the size the variable currently occupies on the stack + int size = AS_PTR_SIZE; - // If larger than 1 dword, adjust the offsets accordingly - if( size > 1 ) - { - // How much needs to be adjusted? - adjustments.PushLast(func->scriptData->objVariablePos[n]); - adjustments.PushLast(-(size-1)); - } + // objVariableTypes is null if the variable type is a null pointer + if( func->scriptData->objVariableTypes[n] && + (func->scriptData->objVariableTypes[n]->GetFlags() & asOBJ_VALUE) && + n >= func->scriptData->objVariablesOnHeap ) + { + size = func->scriptData->objVariableTypes[n]->GetSize(); + if( size < 4 ) + size = 1; + else + size /= 4; + } + + // If larger than 1 dword, adjust the offsets accordingly + if (size > 1) + { + // How much needs to be adjusted? + adjustments.PushLast(func->scriptData->objVariablePos[n]); + adjustments.PushLast(-(size - 1)); } } @@ -4282,7 +4632,7 @@ void asCWriter::CalculateAdjustmentByPos(asCScriptFunction *func) offset += asBCTypeSize[asBCInfo[*(asBYTE*)(bc+offset)].type]; num++; } - // The last instruction is always a BC_RET. This make it possible to query + // The last instruction is always a BC_RET. This make it possible to query // the number of instructions by checking the last entry in bytecodeNbrByPos asASSERT(*(asBYTE*)(bc+length-1) == asBC_RET); } @@ -4315,6 +4665,8 @@ int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog // Get offset 0 doesn't need adjustment if( offset == 0 ) return 0; + bool bcAlloc = false; + // Find out which function that will be called asCScriptFunction *calledFunc = 0; int stackDelta = 0; @@ -4333,6 +4685,10 @@ int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog } else if( bc == asBC_ALLOC ) { + // The alloc instruction doesn't take the object pointer on the stack, + // as the memory will be allocated by the instruction itself + bcAlloc = true; + // Find the function from the function id in the bytecode int funcId = asBC_INTARG(&func->scriptData->byteCode[n+AS_PTR_SIZE]); calledFunc = engine->scriptFunctions[funcId]; @@ -4354,7 +4710,7 @@ int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog { if( func->scriptData->objVariablePos[v] == var ) { - calledFunc = func->scriptData->funcVariableTypes[v]; + calledFunc = CastToFuncdefType(func->scriptData->objVariableTypes[v])->funcdef; break; } } @@ -4370,7 +4726,7 @@ int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog { if( var == paramPos ) { - calledFunc = func->parameterTypes[v].GetFuncDef(); + calledFunc = CastToFuncdefType(func->parameterTypes[v].GetTypeInfo())->funcdef; break; } paramPos -= func->parameterTypes[v].GetSizeOnStackDWords(); @@ -4386,7 +4742,7 @@ int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog return offset + (1 - AS_PTR_SIZE); } - // Keep track of the stack size between the + // Keep track of the stack size between the // instruction that needs to be adjusted and the call stackDelta += asBCInfo[bc].stackInc; @@ -4395,11 +4751,11 @@ int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog asASSERT( calledFunc ); - // Count the number of pointers pushed on the stack above the + // Count the number of pointers pushed on the stack above the // current offset, and then adjust the offset accordingly asUINT numPtrs = 0; int currOffset = -stackDelta; - if( offset > currOffset && calledFunc->GetObjectType() ) + if( offset > currOffset && calledFunc->GetObjectType() && !bcAlloc ) { currOffset += AS_PTR_SIZE; if( currOffset > 0 ) @@ -4437,7 +4793,7 @@ int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog // The get offset must match one of the parameter offsets asASSERT( offset == currOffset ); - + return offset + numPtrs * (1 - AS_PTR_SIZE); } @@ -4446,7 +4802,7 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) asDWORD *bc = func->scriptData->byteCode.AddressOf(); size_t length = func->scriptData->byteCode.GetLength(); - // The length cannot be stored, because it is platform dependent, + // The length cannot be stored, because it is platform dependent, // instead we store the number of instructions asUINT count = bytecodeNbrByPos[bytecodeNbrByPos.GetLength()-1] + 1; WriteEncodedInt64(count); @@ -4454,23 +4810,23 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) asDWORD *startBC = bc; while( length ) { - asDWORD tmp[4]; // The biggest instructions take up 4 DWORDs + asDWORD tmpBC[4]; // The biggest instructions take up 4 DWORDs asDWORD c = *(asBYTE*)bc; // Copy the instruction to a temp buffer so we can work on it before saving - memcpy(tmp, bc, asBCTypeSize[asBCInfo[c].type]*sizeof(asDWORD)); + memcpy(tmpBC, bc, asBCTypeSize[asBCInfo[c].type]*sizeof(asDWORD)); if( c == asBC_ALLOC ) // PTR_DW_ARG { - // Translate the object type - asCObjectType *ot = *(asCObjectType**)(tmp+1); - *(asPWORD*)(tmp+1) = FindObjectTypeIdx(ot); + // Translate the object type + asCObjectType *ot = *(asCObjectType**)(tmpBC+1); + *(asPWORD*)(tmpBC+1) = FindTypeInfoIdx(ot); // Translate the constructor func id, unless it is 0 - if( *(int*)&tmp[1+AS_PTR_SIZE] != 0 ) + if( *(int*)&tmpBC[1+AS_PTR_SIZE] != 0 ) { // Increment 1 to the translated function id, as 0 will be reserved for no function - *(int*)&tmp[1+AS_PTR_SIZE] = 1+FindFunctionIndex(engine->scriptFunctions[*(int*)&tmp[1+AS_PTR_SIZE]]); + *(int*)&tmpBC[1+AS_PTR_SIZE] = 1+FindFunctionIndex(engine->scriptFunctions[*(int*)&tmpBC[1+AS_PTR_SIZE]]); } } else if( c == asBC_REFCPY || // PTR_ARG @@ -4478,60 +4834,59 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) c == asBC_OBJTYPE ) // PTR_ARG { // Translate object type pointers into indices - *(asPWORD*)(tmp+1) = FindObjectTypeIdx(*(asCObjectType**)(tmp+1)); + *(asPWORD*)(tmpBC+1) = FindTypeInfoIdx(*(asCObjectType**)(tmpBC+1)); } else if( c == asBC_JitEntry ) // PTR_ARG { // We don't store the JIT argument - *(asPWORD*)(tmp+1) = 0; + *(asPWORD*)(tmpBC+1) = 0; } else if( c == asBC_TYPEID || // DW_ARG c == asBC_Cast ) // DW_ARG { // Translate type ids into indices - *(int*)(tmp+1) = FindTypeIdIdx(*(int*)(tmp+1)); + *(int*)(tmpBC+1) = FindTypeIdIdx(*(int*)(tmpBC+1)); } else if( c == asBC_ADDSi || // W_DW_ARG c == asBC_LoadThisR ) // W_DW_ARG { // Translate property offsets into indices - *(((short*)tmp)+1) = (short)FindObjectPropIndex(*(((short*)tmp)+1), *(int*)(tmp+1)); + *(((short*)tmpBC)+1) = (short)FindObjectPropIndex(*(((short*)tmpBC)+1), *(int*)(tmpBC+1), bc); // Translate type ids into indices - *(int*)(tmp+1) = FindTypeIdIdx(*(int*)(tmp+1)); + *(int*)(tmpBC+1) = FindTypeIdIdx(*(int*)(tmpBC+1)); } else if( c == asBC_LoadRObjR || // rW_W_DW_ARG c == asBC_LoadVObjR ) // rW_W_DW_ARG { - asCObjectType *ot = engine->GetObjectTypeFromTypeId(*(int*)(tmp+2)); + asCObjectType *ot = engine->GetObjectTypeFromTypeId(*(int*)(tmpBC+2)); if( ot->flags & asOBJ_LIST_PATTERN ) { // List patterns have a different way of translating the offsets SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1]; - *(((short*)tmp)+2) = (short)listAdj->AdjustOffset(*(((short*)tmp)+2), ot); + *(((short*)tmpBC)+2) = (short)listAdj->AdjustOffset(*(((short*)tmpBC)+2), ot); } else { // Translate property offsets into indices - // TODO: optimize: Pass the object type directly to the method instead of the type id - *(((short*)tmp)+2) = (short)FindObjectPropIndex(*(((short*)tmp)+2), *(int*)(tmp+2)); + *(((short*)tmpBC)+2) = (short)FindObjectPropIndex(*(((short*)tmpBC)+2), *(int*)(tmpBC+2), bc); } // Translate type ids into indices - *(int*)(tmp+2) = FindTypeIdIdx(*(int*)(tmp+2)); + *(int*)(tmpBC+2) = FindTypeIdIdx(*(int*)(tmpBC+2)); } else if( c == asBC_COPY ) // W_DW_ARG { // Translate type ids into indices - *(int*)(tmp+1) = FindTypeIdIdx(*(int*)(tmp+1)); + *(int*)(tmpBC+1) = FindTypeIdIdx(*(int*)(tmpBC+1)); // Update the WORDARG0 to 0, as this will be recalculated on the target platform - asBC_WORDARG0(tmp) = 0; + asBC_WORDARG0(tmpBC) = 0; } else if( c == asBC_RET ) // W_ARG { // Save with arg 0, as this will be recalculated on the target platform - asBC_WORDARG0(tmp) = 0; + asBC_WORDARG0(tmpBC) = 0; } else if( c == asBC_CALL || // DW_ARG c == asBC_CALLINTF || // DW_ARG @@ -4539,23 +4894,17 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) c == asBC_Thiscall1 ) // DW_ARG { // Translate the function id - *(int*)(tmp+1) = FindFunctionIndex(engine->scriptFunctions[*(int*)(tmp+1)]); + *(int*)(tmpBC+1) = FindFunctionIndex(engine->scriptFunctions[*(int*)(tmpBC+1)]); } else if( c == asBC_FuncPtr ) // PTR_ARG { // Translate the function pointer - *(asPWORD*)(tmp+1) = FindFunctionIndex(*(asCScriptFunction**)(tmp+1)); - } - else if( c == asBC_STR ) // W_ARG - { - // Translate the string constant id - asWORD *arg = ((asWORD*)tmp)+1; - *arg = (asWORD)FindStringConstantIndex(*arg); + *(asPWORD*)(tmpBC+1) = FindFunctionIndex(*(asCScriptFunction**)(tmpBC+1)); } else if( c == asBC_CALLBND ) // DW_ARG { // Translate the function id - int funcId = tmp[1]; + int funcId = tmpBC[1]; for( asUINT n = 0; n < module->bindInformations.GetLength(); n++ ) if( module->bindInformations[n]->importedFunctionSignature->id == funcId ) { @@ -4563,10 +4912,10 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) break; } - tmp[1] = funcId; + tmpBC[1] = funcId; } else if( c == asBC_PGA || // PTR_ARG - c == asBC_PshGPtr || // PTR_ARG + c == asBC_PshGPtr || // PTR_ARG c == asBC_LDG || // PTR_ARG c == asBC_PshG4 || // PTR_ARG c == asBC_LdGRdR4 || // wW_PTR_ARG @@ -4574,8 +4923,23 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) c == asBC_CpyVtoG4 || // rW_PTR_ARG c == asBC_SetG4 ) // PTR_DW_ARG { - // Translate global variable pointers into indices - *(asPWORD*)(tmp+1) = FindGlobalPropPtrIndex(*(void**)(tmp+1)); + // Check if the address is a global property or a string constant + void *ptr = *(void**)(tmpBC + 1); + if (engine->varAddressMap.MoveTo(0, ptr)) + { + // Translate global variable pointers into indices + // Flag the first bit to signal global property + *(asPWORD*)(tmpBC + 1) = (FindGlobalPropPtrIndex(*(void**)(tmpBC + 1)) << 1) + 1; + } + else + { + // Only PGA and PshGPtr can hold string constants + asASSERT(c == asBC_PGA || c == asBC_PshGPtr); + + // Translate string constants into indices + // Leave the first bit clear to signal string constant + *(asPWORD*)(tmpBC + 1) = FindStringConstantIndex(*(void**)(tmpBC + 1)) << 1; + } } else if( c == asBC_JMP || // DW_ARG c == asBC_JZ || @@ -4588,7 +4952,7 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) c == asBC_JNP ) // The JMPP instruction doesn't need modification { // Get the DWORD offset from arg - int offset = *(int*)(tmp+1); + int offset = *(int*)(tmpBC+1); // Determine instruction number for next instruction and destination int bcSeqNum = bytecodeNbrByPos[asUINT(bc - startBC)] + 1; @@ -4596,23 +4960,24 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) int targetBcSeqNum = bytecodeNbrByPos[asUINT(targetBC - startBC)]; // Set the offset in number of instructions - *(int*)(tmp+1) = targetBcSeqNum - bcSeqNum; + *(int*)(tmpBC+1) = targetBcSeqNum - bcSeqNum; } else if( c == asBC_GETOBJ || // W_ARG c == asBC_GETOBJREF || - c == asBC_GETREF ) + c == asBC_GETREF || + c == asBC_ChkNullS ) { // Adjust the offset according to the function call that comes after - asBC_WORDARG0(tmp) = (asWORD)AdjustGetOffset(asBC_WORDARG0(tmp), func, asDWORD(bc - startBC)); + asBC_WORDARG0(tmpBC) = (asWORD)AdjustGetOffset(asBC_WORDARG0(tmpBC), func, asDWORD(bc - startBC)); } else if( c == asBC_AllocMem ) { // It's not necessary to store the size of the list buffer, as it will be recalculated in the reader - asBC_DWORDARG(tmp) = 0; + asBC_DWORDARG(tmpBC) = 0; // Determine the type of the list pattern from the variable - short var = asBC_WORDARG0(tmp); - asCObjectType *ot = func->GetObjectTypeOfLocalVar(var); + short var = asBC_WORDARG0(tmpBC); + asCObjectType *ot = CastToObjectType(func->GetTypeInfoOfLocalVar(var)); // Create this helper object to adjust the offset of the elements accessed in the buffer listAdjusters.PushLast(asNEW(SListAdjuster)(ot)); @@ -4620,8 +4985,8 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) else if( c == asBC_FREE ) // wW_PTR_ARG { // Translate object type pointers into indices - asCObjectType *ot = *(asCObjectType**)(tmp+1); - *(asPWORD*)(tmp+1) = FindObjectTypeIdx(ot); + asCObjectType *ot = *(asCObjectType**)(tmpBC+1); + *(asPWORD*)(tmpBC+1) = FindTypeInfoIdx(ot); // Pop and destroy the list adjuster helper that was created with asBC_AllocMem if( ot && (ot->flags & asOBJ_LIST_PATTERN) ) @@ -4634,28 +4999,28 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) { // Adjust the offset in the initialization list SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1]; - tmp[1] = listAdj->AdjustOffset(tmp[1], listAdj->patternType); + tmpBC[1] = listAdj->AdjustOffset(tmpBC[1], listAdj->patternType); // Tell the adjuster how many repeated values there are - listAdj->SetRepeatCount(tmp[2]); + listAdj->SetRepeatCount(tmpBC[2]); } else if( c == asBC_PshListElmnt ) // W_DW_ARG { // Adjust the offset in the initialization list SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1]; - tmp[1] = listAdj->AdjustOffset(tmp[1], listAdj->patternType); + tmpBC[1] = listAdj->AdjustOffset(tmpBC[1], listAdj->patternType); } else if( c == asBC_SetListType ) { // Adjust the offset in the initialization list SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1]; - tmp[1] = listAdj->AdjustOffset(tmp[1], listAdj->patternType); + tmpBC[1] = listAdj->AdjustOffset(tmpBC[1], listAdj->patternType); // Inform the adjuster of the type id of the next element - listAdj->SetNextType(tmp[2]); + listAdj->SetNextType(tmpBC[2]); // Translate the type id - tmp[2] = FindTypeIdIdx(tmp[2]); + tmpBC[2] = FindTypeIdIdx(tmpBC[2]); } // Adjust the variable offsets switch( asBCInfo[c].type ) @@ -4670,7 +5035,7 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) case asBCTYPE_rW_W_DW_ARG: case asBCTYPE_rW_DW_DW_ARG: { - asBC_SWORDARG0(tmp) = (short)AdjustStackPosition(asBC_SWORDARG0(tmp)); + asBC_SWORDARG0(tmpBC) = (short)AdjustStackPosition(asBC_SWORDARG0(tmpBC)); } break; @@ -4678,16 +5043,16 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) case asBCTYPE_wW_rW_DW_ARG: case asBCTYPE_rW_rW_ARG: { - asBC_SWORDARG0(tmp) = (short)AdjustStackPosition(asBC_SWORDARG0(tmp)); - asBC_SWORDARG1(tmp) = (short)AdjustStackPosition(asBC_SWORDARG1(tmp)); + asBC_SWORDARG0(tmpBC) = (short)AdjustStackPosition(asBC_SWORDARG0(tmpBC)); + asBC_SWORDARG1(tmpBC) = (short)AdjustStackPosition(asBC_SWORDARG1(tmpBC)); } break; case asBCTYPE_wW_rW_rW_ARG: { - asBC_SWORDARG0(tmp) = (short)AdjustStackPosition(asBC_SWORDARG0(tmp)); - asBC_SWORDARG1(tmp) = (short)AdjustStackPosition(asBC_SWORDARG1(tmp)); - asBC_SWORDARG2(tmp) = (short)AdjustStackPosition(asBC_SWORDARG2(tmp)); + asBC_SWORDARG0(tmpBC) = (short)AdjustStackPosition(asBC_SWORDARG0(tmpBC)); + asBC_SWORDARG1(tmpBC) = (short)AdjustStackPosition(asBC_SWORDARG1(tmpBC)); + asBC_SWORDARG2(tmpBC) = (short)AdjustStackPosition(asBC_SWORDARG2(tmpBC)); } break; @@ -4696,9 +5061,9 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) break; } - // TODO: bytecode: Must make sure that floats and doubles are always stored the same way regardless of platform. + // TODO: bytecode: Must make sure that floats and doubles are always stored the same way regardless of platform. // Some platforms may not use the IEEE 754 standard, in which case it is necessary to encode the values - + // Now store the instruction in the smallest possible way switch( asBCInfo[c].type ) { @@ -4716,9 +5081,9 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) // Write the instruction code asBYTE b = (asBYTE)c; WriteData(&b, 1); - + // Write the argument - short w = *(((short*)tmp)+1); + short w = *(((short*)tmpBC)+1); WriteEncodedInt64(w); } break; @@ -4731,11 +5096,11 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) WriteData(&b, 1); // Write the word argument - short w = *(((short*)tmp)+1); + short w = *(((short*)tmpBC)+1); WriteEncodedInt64(w); // Write the dword argument - WriteEncodedInt64((int)tmp[1]); + WriteEncodedInt64((int)tmpBC[1]); } break; case asBCTYPE_DW_ARG: @@ -4745,7 +5110,7 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) WriteData(&b, 1); // Write the argument - WriteEncodedInt64((int)tmp[1]); + WriteEncodedInt64((int)tmpBC[1]); } break; case asBCTYPE_DW_DW_ARG: @@ -4755,10 +5120,10 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) WriteData(&b, 1); // Write the dword argument - WriteEncodedInt64((int)tmp[1]); + WriteEncodedInt64((int)tmpBC[1]); // Write the dword argument - WriteEncodedInt64((int)tmp[2]); + WriteEncodedInt64((int)tmpBC[2]); } break; case asBCTYPE_wW_rW_rW_ARG: @@ -4768,15 +5133,15 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) WriteData(&b, 1); // Write the first argument - short w = *(((short*)tmp)+1); + short w = *(((short*)tmpBC)+1); WriteEncodedInt64(w); // Write the second argument - w = *(((short*)tmp)+2); + w = *(((short*)tmpBC)+2); WriteEncodedInt64(w); // Write the third argument - w = *(((short*)tmp)+3); + w = *(((short*)tmpBC)+3); WriteEncodedInt64(w); } break; @@ -4789,11 +5154,11 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) WriteData(&b, 1); // Write the first argument - short w = *(((short*)tmp)+1); + short w = *(((short*)tmpBC)+1); WriteEncodedInt64(w); // Write the second argument - w = *(((short*)tmp)+2); + w = *(((short*)tmpBC)+2); WriteEncodedInt64(w); } break; @@ -4805,15 +5170,15 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) WriteData(&b, 1); // Write the first argument - short w = *(((short*)tmp)+1); + short w = *(((short*)tmpBC)+1); WriteEncodedInt64(w); // Write the second argument - w = *(((short*)tmp)+2); + w = *(((short*)tmpBC)+2); WriteEncodedInt64(w); // Write the third argument - int dw = tmp[2]; + int dw = tmpBC[2]; WriteEncodedInt64(dw); } break; @@ -4824,7 +5189,7 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) WriteData(&b, 1); // Write the argument - asQWORD qw = *(asQWORD*)&tmp[1]; + asQWORD qw = *(asQWORD*)&tmpBC[1]; WriteEncodedInt64(qw); } break; @@ -4835,11 +5200,11 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) WriteData(&b, 1); // Write the argument - asQWORD qw = *(asQWORD*)&tmp[1]; + asQWORD qw = *(asQWORD*)&tmpBC[1]; WriteEncodedInt64(qw); // Write the second argument - int dw = tmp[3]; + int dw = tmpBC[3]; WriteEncodedInt64(dw); } break; @@ -4851,11 +5216,11 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) WriteData(&b, 1); // Write the first argument - short w = *(((short*)tmp)+1); + short w = *(((short*)tmpBC)+1); WriteEncodedInt64(w); // Write the argument - asQWORD qw = *(asQWORD*)&tmp[1]; + asQWORD qw = *(asQWORD*)&tmpBC[1]; WriteEncodedInt64(qw); } break; @@ -4866,14 +5231,14 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) WriteData(&b, 1); // Write the short argument - short w = *(((short*)tmp)+1); + short w = *(((short*)tmpBC)+1); WriteEncodedInt64(w); // Write the dword argument - WriteEncodedInt64((int)tmp[1]); + WriteEncodedInt64((int)tmpBC[1]); // Write the dword argument - WriteEncodedInt64((int)tmp[2]); + WriteEncodedInt64((int)tmpBC[2]); } break; default: @@ -4883,7 +5248,7 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) // Store the bc as is for( int n = 0; n < asBCTypeSize[asBCInfo[c].type]; n++ ) - WriteData(&tmp[n], 4); + WriteData(&tmpBC[n], 4); } } @@ -4894,8 +5259,8 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) } asCWriter::SListAdjuster::SListAdjuster(asCObjectType *ot) : patternType(ot), repeatCount(0), entries(0), lastOffset(-1), nextOffset(0), nextTypeId(-1) -{ - asASSERT( ot && (ot->flags & asOBJ_LIST_PATTERN) ); +{ + asASSERT( ot && (ot->flags & asOBJ_LIST_PATTERN) ); // Find the first expected value in the list asSListPatternNode *node = ot->engine->scriptFunctions[patternType->templateSubTypes[0].GetBehaviour()->listFactory]->listPattern; @@ -4908,7 +5273,7 @@ int asCWriter::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter // TODO: cleanup: The listPatternType parameter is not needed asASSERT( patternType == listPatternType ); UNUSED_VAR(listPatternType); - + asASSERT( offset >= lastOffset ); // If it is the same offset being accessed again, just return the same adjusted value @@ -4932,8 +5297,8 @@ int asCWriter::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter const asCDataType &dt = reinterpret_cast(patternNode)->dataType; if( dt.GetTokenType() == ttQuestion ) { - // The bytecode need to inform the type that will - // come next and then adjust that position too before + // The bytecode need to inform the type that will + // come next and then adjust that position too before // we can move to the next node if( nextTypeId != -1 ) { @@ -4949,13 +5314,13 @@ int asCWriter::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter nextTypeId = -1; } } - else + else { if( repeatCount > 0 ) { // Was any value skipped? asUINT size; - if( dt.IsObjectHandle() || (dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_REF)) ) + if( dt.IsObjectHandle() || (dt.GetTypeInfo() && (dt.GetTypeInfo()->flags & asOBJ_REF)) ) size = AS_PTR_SIZE*4; else size = dt.GetSizeInMemoryBytes(); @@ -5037,10 +5402,10 @@ void asCWriter::SListAdjuster::SetRepeatCount(asUINT rc) void asCWriter::SListAdjuster::SetNextType(int typeId) { // Make sure the list is expecting a type at this location - asASSERT( patternNode->type == asLPT_TYPE && + asASSERT( patternNode->type == asLPT_TYPE && reinterpret_cast(patternNode)->dataType.GetTokenType() == ttQuestion ); - // Inform the type id for the next adjustment + // Inform the type id for the next adjustment nextTypeId = typeId; } @@ -5069,14 +5434,14 @@ int asCWriter::FindGlobalPropPtrIndex(void *ptr) void asCWriter::WriteUsedGlobalProps() { TimeIt("asCWriter::WriteUsedGlobalProps"); - + int c = (int)usedGlobalProperties.GetLength(); WriteEncodedInt64(c); for( int n = 0; n < c; n++ ) { asPWORD *p = (asPWORD*)usedGlobalProperties[n]; - + // Find the property descriptor from the address asCGlobalProperty *prop = 0; asSMapNode *cursor; @@ -5109,32 +5474,86 @@ void asCWriter::WriteUsedObjectProps() for( asUINT n = 0; n < usedObjectProperties.GetLength(); n++ ) { - asCObjectType *objType = usedObjectProperties[n].objType; - WriteObjectType(objType); - - // Find the property name - for( asUINT p = 0; p < objType->properties.GetLength(); p++ ) - { - if( objType->properties[p]->byteOffset == usedObjectProperties[n].offset ) - { - WriteString(&objType->properties[p]->name); - break; - } - } + WriteTypeInfo(usedObjectProperties[n].objType); + WriteString(&usedObjectProperties[n].prop->name); } } -int asCWriter::FindObjectPropIndex(short offset, int typeId) +int asCWriter::FindObjectPropIndex(short offset, int typeId, asDWORD *bc) { + // If the last property was a composite property, then just return 0, because it won't be translated + static bool lastWasComposite = false; + if (lastWasComposite) + { + lastWasComposite = false; + return 0; + } + asCObjectType *objType = engine->GetObjectTypeFromTypeId(typeId); + asCObjectProperty *objProp = 0; + + // Look for composite properties first + for (asUINT n = 0; objProp == 0 && n < objType->properties.GetLength(); n++) + { + // TODO: Composite: Perhaps it would be better to add metadata to the bytecode instruction to give the exact property. + // That would also allow me to remove the typeId from the bytecode instruction itself + // Or perhaps a new bytecode instruction all together for accessing composite properties + // One that would do both offsets and indirection in a single go. + // TODO: Composite: Need to be able to handle instructions replaced in bytecode optimizations too + if (objType->properties[n]->compositeOffset == offset) + { + // This is a potential composite property. Need to check the following instructions to be sure + objProp = objType->properties[n]; + asDWORD *bcTemp = bc; + bcTemp += asBCTypeSize[asBCInfo[*(asBYTE*)bcTemp].type]; + if (objProp->isCompositeIndirect) + { + // The next instruction would be a asBC_RDSPtr + if ((*(asBYTE*)bcTemp) != asBC_RDSPtr) + { + objProp = 0; + continue; + } + bcTemp += asBCTypeSize[asBCInfo[*(asBYTE*)bcTemp].type]; + } + // The next instruction would be asBC_ADDSi + if ((*(asBYTE*)bcTemp) != asBC_ADDSi) + { + objProp = 0; + continue; + } + // Make sure the offset is the expected one + if (*(((short*)bcTemp) + 1) != objProp->byteOffset) + { + objProp = 0; + continue; + } + } + } + + // If none of the composite properties matched, then look for ordinary property + for (asUINT n = 0; objProp == 0 && n < objType->properties.GetLength(); n++) + { + if (objType->properties[n]->byteOffset == offset && !(objType->properties[n]->compositeOffset || objType->properties[n]->isCompositeIndirect)) + objProp = objType->properties[n]; + } + + asASSERT(objProp); + + // Remember if this is a composite property as the next call will then be for the same property + if (objProp->compositeOffset || objProp->isCompositeIndirect) + lastWasComposite = true; + + // Now check if the same property has already been accessed for( asUINT n = 0; n < usedObjectProperties.GetLength(); n++ ) { if( usedObjectProperties[n].objType == objType && - usedObjectProperties[n].offset == offset ) + usedObjectProperties[n].prop == objProp ) return n; } - SObjProp prop = {objType, offset}; + // Insert the new property + SObjProp prop = {objType, objProp}; usedObjectProperties.PushLast(prop); return (int)usedObjectProperties.GetLength() - 1; } @@ -5164,7 +5583,7 @@ int asCWriter::FindTypeIdIdx(int typeId) return (int)usedTypeIds.GetLength() - 1; } -int asCWriter::FindObjectTypeIdx(asCObjectType *obj) +int asCWriter::FindTypeInfoIdx(asCTypeInfo *obj) { asUINT n; for( n = 0; n < usedTypes.GetLength(); n++ ) diff --git a/lib/angelscript/source/as_restore.h b/lib/angelscript/source/as_restore.h index bfd2725bc..462c2ae5e 100644 --- a/lib/angelscript/source/as_restore.h +++ b/lib/angelscript/source/as_restore.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -64,15 +64,15 @@ protected: int ReadInner(); - void ReadData(void *data, asUINT size); + int ReadData(void *data, asUINT size); void ReadString(asCString *str); - asCScriptFunction *ReadFunction(bool &isNew, bool addToModule = true, bool addToEngine = true, bool addToGC = true); - void ReadFunctionSignature(asCScriptFunction *func); + asCScriptFunction *ReadFunction(bool &isNew, bool addToModule = true, bool addToEngine = true, bool addToGC = true, bool *isExternal = 0); + void ReadFunctionSignature(asCScriptFunction *func, asCObjectType **parentClass = 0); void ReadGlobalProperty(); void ReadObjectProperty(asCObjectType *ot); void ReadDataType(asCDataType *dt); - asCObjectType * ReadObjectType(); - void ReadObjectTypeDeclaration(asCObjectType *ot, int phase); + asCTypeInfo *ReadTypeInfo(); + void ReadTypeDeclaration(asCTypeInfo *ot, int phase, bool *isExternal = 0); void ReadByteCode(asCScriptFunction *func); asWORD ReadEncodedUInt16(); asUINT ReadEncodedUInt(); @@ -84,7 +84,7 @@ protected: void ReadUsedStringConstants(); void ReadUsedObjectProps(); - asCObjectType * FindObjectType(int idx); + asCTypeInfo * FindType(int idx); int FindTypeId(int idx); short FindObjectPropOffset(asWORD index); asCScriptFunction *FindFunction(int idx); @@ -99,10 +99,10 @@ protected: // Temporary storage for persisting variable data asCArray usedTypeIds; - asCArray usedTypes; + asCArray usedTypes; asCArray usedFunctions; asCArray usedGlobalProperties; - asCArray usedStringConstants; + asCArray usedStringConstants; asCArray savedFunctions; asCArray savedDataTypes; @@ -113,8 +113,8 @@ protected: struct SObjProp { - asCObjectType *objType; - int offset; + asCObjectType *objType; + asCObjectProperty *prop; }; asCArray usedObjectProperties; @@ -165,8 +165,12 @@ protected: asIBinaryStream *stream; asCScriptEngine *engine; bool stripDebugInfo; + bool error; + asUINT bytesWritten; - void WriteData(const void *data, asUINT size); + int Error(const char *msg); + + int WriteData(const void *data, asUINT size); void WriteString(asCString *str); void WriteFunction(asCScriptFunction *func); @@ -174,18 +178,18 @@ protected: void WriteGlobalProperty(asCGlobalProperty *prop); void WriteObjectProperty(asCObjectProperty *prop); void WriteDataType(const asCDataType *dt); - void WriteObjectType(asCObjectType *ot); - void WriteObjectTypeDeclaration(asCObjectType *ot, int phase); + void WriteTypeInfo(asCTypeInfo *ot); + void WriteTypeDeclaration(asCTypeInfo *ot, int phase); void WriteByteCode(asCScriptFunction *func); void WriteEncodedInt64(asINT64 i); // Helper functions for storing variable data - int FindObjectTypeIdx(asCObjectType*); + int FindTypeInfoIdx(asCTypeInfo *ti); int FindTypeIdIdx(int typeId); int FindFunctionIndex(asCScriptFunction *func); int FindGlobalPropPtrIndex(void *); - int FindStringConstantIndex(int id); - int FindObjectPropIndex(short offset, int typeId); + int FindStringConstantIndex(void *str); + int FindObjectPropIndex(short offset, int typeId, asDWORD *bc); void CalculateAdjustmentByPos(asCScriptFunction *func); int AdjustStackPosition(int pos); @@ -201,24 +205,24 @@ protected: // Temporary storage for persisting variable data asCArray usedTypeIds; - asCArray usedTypes; + asCArray usedTypes; asCArray usedFunctions; asCArray usedGlobalProperties; - asCArray usedStringConstants; - asCMap stringIdToIndexMap; + asCArray usedStringConstants; + asCMap stringToIndexMap; asCArray savedFunctions; asCArray savedDataTypes; asCArray savedStrings; - asCMap stringToIdMap; + asCMap stringToIdMap; asCArray adjustStackByPos; asCArray adjustNegativeStackByPos; asCArray bytecodeNbrByPos; struct SObjProp { - asCObjectType *objType; - int offset; + asCObjectType *objType; + asCObjectProperty *prop; }; asCArray usedObjectProperties; diff --git a/lib/angelscript/source/as_scriptcode.cpp b/lib/angelscript/source/as_scriptcode.cpp index ef576c64c..833b401b6 100644 --- a/lib/angelscript/source/as_scriptcode.cpp +++ b/lib/angelscript/source/as_scriptcode.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2013 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -58,41 +58,41 @@ asCScriptCode::~asCScriptCode() } } -int asCScriptCode::SetCode(const char *name, const char *code, bool makeCopy) +int asCScriptCode::SetCode(const char *in_name, const char *in_code, bool in_makeCopy) { - return SetCode(name, code, 0, makeCopy); + return SetCode(in_name, in_code, 0, in_makeCopy); } -int asCScriptCode::SetCode(const char *name, const char *code, size_t length, bool makeCopy) +int asCScriptCode::SetCode(const char *in_name, const char *in_code, size_t in_length, bool in_makeCopy) { - if( !code ) return asINVALID_ARG; - this->name = name ? name : ""; - if( !sharedCode && this->code ) - asDELETEARRAY(this->code); + if( !in_code) return asINVALID_ARG; + this->name = in_name ? in_name : ""; + if( !sharedCode && code ) + asDELETEARRAY(code); - if( length == 0 ) - length = strlen(code); - if( makeCopy ) + if( in_length == 0 ) + in_length = strlen(in_code); + if( in_makeCopy ) { - codeLength = length; + codeLength = in_length; sharedCode = false; - this->code = asNEWARRAY(char,length); - if( this->code == 0 ) + code = asNEWARRAY(char, in_length); + if( code == 0 ) return asOUT_OF_MEMORY; - memcpy((char*)this->code, code, length); + memcpy(code, in_code, in_length); } else { - codeLength = length; - this->code = const_cast(code); + codeLength = in_length; + code = const_cast(in_code); sharedCode = true; } // Find the positions of each line linePositions.PushLast(0); - for( size_t n = 0; n < length; n++ ) - if( code[n] == '\n' ) linePositions.PushLast(n+1); - linePositions.PushLast(length); + for( size_t n = 0; n < in_length; n++ ) + if( in_code[n] == '\n' ) linePositions.PushLast(n+1); + linePositions.PushLast(in_length); return asSUCCESS; } diff --git a/lib/angelscript/source/as_scriptengine.cpp b/lib/angelscript/source/as_scriptengine.cpp index ecc489840..3f8507a12 100644 --- a/lib/angelscript/source/as_scriptengine.cpp +++ b/lib/angelscript/source/as_scriptengine.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -401,6 +401,24 @@ int asCScriptEngine::SetEngineProperty(asEEngineProp property, asPWORD value) ep.privatePropAsProtected = value ? true : false; break; + case asEP_ALLOW_UNICODE_IDENTIFIERS: + ep.allowUnicodeIdentifiers = value ? true : false; + break; + + case asEP_HEREDOC_TRIM_MODE: + if (value <= 2) + ep.heredocTrimMode = (int)value; + else + return asINVALID_ARG; + break; + + case asEP_MAX_NESTED_CALLS: + if (value > 0xFFFFFFFF) + ep.maxNestedCalls = 0xFFFFFFFF; + else + ep.maxNestedCalls = (asUINT)value; + break; + default: return asINVALID_ARG; } @@ -485,6 +503,15 @@ asPWORD asCScriptEngine::GetEngineProperty(asEEngineProp property) const case asEP_PRIVATE_PROP_AS_PROTECTED: return ep.privatePropAsProtected; + case asEP_ALLOW_UNICODE_IDENTIFIERS: + return ep.allowUnicodeIdentifiers; + + case asEP_HEREDOC_TRIM_MODE: + return ep.heredocTrimMode; + + case asEP_MAX_NESTED_CALLS: + return ep.maxNestedCalls; + default: return 0; } @@ -499,7 +526,7 @@ asIScriptFunction *asCScriptEngine::CreateDelegate(asIScriptFunction *func, void return 0; // The function must be a class method - asIObjectType *type = func->GetObjectType(); + asITypeInfo *type = func->GetObjectType(); if( type == 0 ) return 0; @@ -547,6 +574,9 @@ asCScriptEngine::asCScriptEngine() ep.disableIntegerDivision = false; ep.disallowEmptyListElements = false; ep.privatePropAsProtected = false; + ep.allowUnicodeIdentifiers = false; + ep.heredocTrimMode = 1; // 0 = never trim, 1 = don't trim on single line, 2 = trim initial and final empty line + ep.maxNestedCalls = 100; } gc.engine = this; @@ -566,7 +596,7 @@ asCScriptEngine::asCScriptEngine() typeIdSeqNbr = 0; currentGroup = &defaultGroup; - defaultAccessMask = 1; + defaultAccessMask = 0xFFFFFFFF; // All bits set so that built-in functions/types will be available to all modules msgCallback = 0; jitCompiler = 0; @@ -612,7 +642,7 @@ asCScriptEngine::asCScriptEngine() void asCScriptEngine::DeleteDiscardedModules() { - // TODO: redesign: Prevent more than one thread from entering this function at the same time. + // TODO: redesign: Prevent more than one thread from entering this function at the same time. // If a thread is already doing the work for the clean-up the other thread should // simply return, as the first thread will continue. @@ -652,7 +682,6 @@ asCScriptEngine::~asCScriptEngine() { // TODO: clean-up: Clean up redundant code - asUINT n = 0; inDestructor = true; asASSERT(refCount.get() == 0); @@ -672,13 +701,13 @@ asCScriptEngine::~asCScriptEngine() } // Delete the functions for generated template types that may references object types - for( n = 0; n < templateInstanceTypes.GetLength(); n++ ) + for( asUINT n = 0; n < templateInstanceTypes.GetLength(); n++ ) { asCObjectType *templateType = templateInstanceTypes[n]; if( templateInstanceTypes[n] ) templateType->DestroyInternal(); } - for( n = 0; n < listPatternTypes.GetLength(); n++ ) + for( asUINT n = 0; n < listPatternTypes.GetLength(); n++ ) { asCObjectType *type = listPatternTypes[n]; if( type ) @@ -694,8 +723,7 @@ asCScriptEngine::~asCScriptEngine() if( refCount.get() > 0 ) WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ENGINE_REF_COUNT_ERROR_DURING_SHUTDOWN); - mapTypeIdToObjectType.EraseAll(); - mapTypeIdToFunction.EraseAll(); + mapTypeIdToTypeInfo.EraseAll(); // First remove what is not used, so that other groups can be deleted safely defaultGroup.RemoveConfiguration(this, true); @@ -713,7 +741,7 @@ asCScriptEngine::~asCScriptEngine() defaultGroup.RemoveConfiguration(this); // Any remaining objects in templateInstanceTypes is from generated template instances - for( n = 0; n < templateInstanceTypes.GetLength(); n++ ) + for( asUINT n = 0; n < templateInstanceTypes.GetLength(); n++ ) { asCObjectType *templateType = templateInstanceTypes[n]; if( templateInstanceTypes[n] ) @@ -729,7 +757,7 @@ asCScriptEngine::~asCScriptEngine() } registeredGlobalProps.Clear(); - for( n = 0; n < templateSubTypes.GetLength(); n++ ) + for( asUINT n = 0; n < templateSubTypes.GetLength(); n++ ) { if( templateSubTypes[n] ) { @@ -750,7 +778,7 @@ asCScriptEngine::~asCScriptEngine() scriptTypeBehaviours.ReleaseAllFunctions(); functionBehaviours.ReleaseAllFunctions(); - for( n = 0; n < scriptFunctions.GetLength(); n++ ) + for( asUINT n = 0; n < scriptFunctions.GetLength(); n++ ) if( scriptFunctions[n] ) { scriptFunctions[n]->DestroyInternal(); @@ -766,7 +794,7 @@ asCScriptEngine::~asCScriptEngine() // Destroy the funcdefs // As funcdefs are shared between modules it shouldn't be a problem to keep the objects until the engine is released - for( n = 0; n < funcDefs.GetLength(); n++ ) + for( asUINT n = 0; n < funcDefs.GetLength(); n++ ) if( funcDefs[n] ) { funcDefs[n]->DestroyInternal(); @@ -785,19 +813,13 @@ asCScriptEngine::~asCScriptEngine() } } - // Free string constants - for( n = 0; n < stringConstants.GetLength(); n++ ) - asDELETE(stringConstants[n],asCString); - stringConstants.SetLength(0); - stringToIdMap.EraseAll(); - // Free the script section names - for( n = 0; n < scriptSectionNames.GetLength(); n++ ) + for( asUINT n = 0; n < scriptSectionNames.GetLength(); n++ ) asDELETE(scriptSectionNames[n],asCString); scriptSectionNames.SetLength(0); // Clean the user data - for( n = 0; n < userData.GetLength(); n += 2 ) + for( asUINT n = 0; n < userData.GetLength(); n += 2 ) { if( userData[n+1] ) { @@ -808,7 +830,7 @@ asCScriptEngine::~asCScriptEngine() } // Free namespaces - for( n = 0; n < nameSpaces.GetLength(); n++ ) + for( asUINT n = 0; n < nameSpaces.GetLength(); n++ ) asDELETE(nameSpaces[n], asSNameSpace); nameSpaces.SetLength(0); @@ -846,63 +868,63 @@ asIScriptContext *asCScriptEngine::RequestContext() } // internal -asCModule *asCScriptEngine::FindNewOwnerForSharedType(asCObjectType *type, asCModule *mod) +asCModule *asCScriptEngine::FindNewOwnerForSharedType(asCTypeInfo *in_type, asCModule *in_mod) { - asASSERT( type->IsShared() ); + asASSERT( in_type->IsShared() ); - if( type->module != mod ) - return type->module; + if( in_type->module != in_mod) + return in_type->module; for( asUINT n = 0; n < scriptModules.GetLength(); n++ ) { // TODO: optimize: If the modules already stored the shared types separately, this would be quicker int foundIdx = -1; asCModule *mod = scriptModules[n]; - if( mod == type->module ) continue; - if( type->flags & asOBJ_ENUM ) - foundIdx = mod->enumTypes.IndexOf(type); - else if( type->flags & asOBJ_TYPEDEF ) - foundIdx = mod->typeDefs.IndexOf(type); + if( mod == in_type->module ) continue; + if( in_type->flags & asOBJ_ENUM ) + foundIdx = mod->enumTypes.IndexOf(CastToEnumType(in_type)); + else if (in_type->flags & asOBJ_TYPEDEF) + foundIdx = mod->typeDefs.IndexOf(CastToTypedefType(in_type)); + else if (in_type->flags & asOBJ_FUNCDEF) + foundIdx = mod->funcDefs.IndexOf(CastToFuncdefType(in_type)); else - foundIdx = mod->classTypes.IndexOf(type); - + foundIdx = mod->classTypes.IndexOf(CastToObjectType(in_type)); + if( foundIdx >= 0 ) { - type->module = mod; + in_type->module = mod; break; } } - return type->module; + return in_type->module; } // internal -asCModule *asCScriptEngine::FindNewOwnerForSharedFunc(asCScriptFunction *func, asCModule *mod) +asCModule *asCScriptEngine::FindNewOwnerForSharedFunc(asCScriptFunction *in_func, asCModule *in_mod) { - asASSERT( func->IsShared() ); + asASSERT( in_func->IsShared() ); + asASSERT(!(in_func->funcType & asFUNC_FUNCDEF)); - if( func->module != mod ) - return func->module; + if( in_func->module != in_mod) + return in_func->module; for( asUINT n = 0; n < scriptModules.GetLength(); n++ ) { // TODO: optimize: If the modules already stored the shared types separately, this would be quicker int foundIdx = -1; asCModule *mod = scriptModules[n]; - if( mod == func->module ) continue; - if( func->funcType == asFUNC_FUNCDEF ) - foundIdx = mod->funcDefs.IndexOf(func); - else - foundIdx = mod->scriptFunctions.IndexOf(func); - + if( mod == in_func->module ) continue; + foundIdx = mod->scriptFunctions.IndexOf(in_func); + if( foundIdx >= 0 ) { - func->module = mod; + in_func->module = mod; break; } } - return func->module; + return in_func->module; } // interface @@ -1041,6 +1063,10 @@ int asCScriptEngine::SetDefaultNamespace(const char *nameSpace) if( (expectIdentifier && t != ttIdentifier) || (!expectIdentifier && t != ttScope) ) return ConfigError(asINVALID_DECLARATION, "SetDefaultNamespace", nameSpace, 0); + // Make sure parent namespaces are registred in case of nested namespaces + if (expectIdentifier) + AddNameSpace(ns.SubString(0, pos + len).AddressOf()); + expectIdentifier = !expectIdentifier; } @@ -1261,31 +1287,6 @@ asIScriptModule *asCScriptEngine::GetModuleByIndex(asUINT index) const return mod; } -// Internal -void asCScriptEngine::RemoveTypeAndRelatedFromList(asCMap &types, asCObjectType *ot) -{ - // Remove the type from the list - asSMapNode* node; - if( !types.MoveTo(&node, ot) ) - return; - - types.Erase(node); - - // If the type is an template type then remove all sub types as well - for( asUINT n = 0; n < ot->templateSubTypes.GetLength(); n++ ) - { - if( ot->templateSubTypes[n].GetObjectType() ) - RemoveTypeAndRelatedFromList(types, ot->templateSubTypes[n].GetObjectType()); - } - - // If the type is a class then remove all properties types as well - if( ot->properties.GetLength() ) - { - for( asUINT n = 0; n < ot->properties.GetLength(); n++ ) - RemoveTypeAndRelatedFromList(types, ot->properties[n]->type.GetObjectType()); - } -} - // internal int asCScriptEngine::GetFactoryIdByDecl(const asCObjectType *ot, const char *decl) { @@ -1405,7 +1406,7 @@ int asCScriptEngine::CreateContext(asIScriptContext **context, bool isInternal) } // interface -int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset) +int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset, int compositeOffset, bool isCompositeIndirect) { int r; asCDataType dt; @@ -1414,12 +1415,15 @@ int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declara if( r < 0 ) return ConfigError(r, "RegisterObjectProperty", obj, declaration); + if (dt.GetTypeInfo() == 0 || (dt.IsObjectHandle() && !(dt.GetTypeInfo()->GetFlags() & asOBJ_IMPLICIT_HANDLE))) + return ConfigError(asINVALID_OBJECT, "RegisterObjectProperty", obj, declaration); + // Don't allow modifying generated template instances - if( dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_TEMPLATE) && generatedTemplateTypes.Exists(dt.GetObjectType()) ) + if( dt.GetTypeInfo() && (dt.GetTypeInfo()->flags & asOBJ_TEMPLATE) && generatedTemplateTypes.Exists(CastToObjectType(dt.GetTypeInfo())) ) return ConfigError(asINVALID_TYPE, "RegisterObjectProperty", obj, declaration); // Verify that the correct config group is used - if( currentGroup->FindType(dt.GetObjectType()->name.AddressOf()) == 0 ) + if( currentGroup->FindType(dt.GetTypeInfo()->name.AddressOf()) == 0 ) return ConfigError(asWRONG_CONFIG_GROUP, "RegisterObjectProperty", obj, declaration); asCDataType type; @@ -1428,10 +1432,6 @@ int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declara if( (r = bld.VerifyProperty(&dt, declaration, name, type, 0)) < 0 ) return ConfigError(r, "RegisterObjectProperty", obj, declaration); - // Store the property info - if( dt.GetObjectType() == 0 || dt.IsObjectHandle() ) - return ConfigError(asINVALID_OBJECT, "RegisterObjectProperty", obj, declaration); - // The VM currently only supports 16bit offsets // TODO: The VM needs to have support for 32bit offsets. Probably with a second ADDSi instruction // However, when implementing this it is necessary for the bytecode serialization to support @@ -1439,31 +1439,36 @@ int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declara // same on all platforms if( byteOffset > 32767 || byteOffset < -32768 ) return ConfigError(asINVALID_ARG, "RegisterObjectProperty", obj, declaration); + // The composite offset must also obey the ADDSi restriction + if (compositeOffset > 32767 || compositeOffset < -32768) + return ConfigError(asINVALID_ARG, "RegisterObjectProperty", obj, declaration); asCObjectProperty *prop = asNEW(asCObjectProperty); if( prop == 0 ) return ConfigError(asOUT_OF_MEMORY, "RegisterObjectProperty", obj, declaration); - prop->name = name; - prop->type = type; - prop->byteOffset = byteOffset; - prop->isPrivate = false; - prop->isProtected = false; - prop->accessMask = defaultAccessMask; + prop->name = name; + prop->type = type; + prop->byteOffset = byteOffset; + prop->isPrivate = false; + prop->isProtected = false; + prop->compositeOffset = compositeOffset; + prop->isCompositeIndirect = isCompositeIndirect; + prop->accessMask = defaultAccessMask; - dt.GetObjectType()->properties.PushLast(prop); + CastToObjectType(dt.GetTypeInfo())->properties.PushLast(prop); // Add references to types so they are not released too early - if( type.GetObjectType() ) + if( type.GetTypeInfo() ) { - type.GetObjectType()->AddRefInternal(); + type.GetTypeInfo()->AddRefInternal(); // Add template instances to the config group - if( (type.GetObjectType()->flags & asOBJ_TEMPLATE) && !currentGroup->objTypes.Exists(type.GetObjectType()) ) - currentGroup->objTypes.PushLast(type.GetObjectType()); + if( (type.GetTypeInfo()->flags & asOBJ_TEMPLATE) && !currentGroup->types.Exists(type.GetTypeInfo()) ) + currentGroup->types.PushLast(type.GetTypeInfo()); } - currentGroup->AddReferencesForType(this, type.GetObjectType()); + currentGroup->AddReferencesForType(this, type.GetTypeInfo()); return asSUCCESS; } @@ -1474,7 +1479,7 @@ int asCScriptEngine::RegisterInterface(const char *name) if( name == 0 ) return ConfigError(asINVALID_NAME, "RegisterInterface", 0, 0); // Verify if the name has been registered as a type already - if( GetRegisteredObjectType(name, defaultNamespace) ) + if( GetRegisteredType(name, defaultNamespace) ) return asALREADY_REGISTERED; // Use builder to parse the datatype @@ -1487,7 +1492,7 @@ int asCScriptEngine::RegisterInterface(const char *name) { // If it is not in the defaultNamespace then the type was successfully parsed because // it is declared in a parent namespace which shouldn't be treated as an error - if( dt.GetObjectType() && dt.GetObjectType()->nameSpace == defaultNamespace ) + if( dt.GetTypeInfo() && dt.GetTypeInfo()->nameSpace == defaultNamespace ) return ConfigError(asERROR, "RegisterInterface", name, 0); } @@ -1525,9 +1530,9 @@ int asCScriptEngine::RegisterInterface(const char *name) allRegisteredTypes.Insert(asSNameSpaceNamePair(st->nameSpace, st->name), st); registeredObjTypes.PushLast(st); - currentGroup->objTypes.PushLast(st); + currentGroup->types.PushLast(st); - return asSUCCESS; + return GetTypeIdByDecl(name); } // interface @@ -1547,7 +1552,7 @@ int asCScriptEngine::RegisterInterfaceMethod(const char *intf, const char *decla if( func == 0 ) return ConfigError(asOUT_OF_MEMORY, "RegisterInterfaceMethod", intf, declaration); - func->objectType = dt.GetObjectType(); + func->objectType = CastToObjectType(dt.GetTypeInfo()); func->objectType->AddRefInternal(); r = bld.ParseFunctionDeclaration(func->objectType, declaration, func, false); @@ -1559,7 +1564,7 @@ int asCScriptEngine::RegisterInterfaceMethod(const char *intf, const char *decla } // Check name conflicts - r = bld.CheckNameConflictMember(dt.GetObjectType(), func->name.AddressOf(), 0, 0, false); + r = bld.CheckNameConflictMember(dt.GetTypeInfo(), func->name.AddressOf(), 0, 0, false); if( r < 0 ) { func->funcType = asFUNC_DUMMY; @@ -1697,7 +1702,7 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD return ConfigError(r, "RegisterObjectType", name, 0); // Verify that the template name hasn't been registered as a type already - if( GetRegisteredObjectType(typeName, defaultNamespace) ) + if( GetRegisteredType(typeName, defaultNamespace) ) // This is not an irrepairable error, as it may just be that the same type is registered twice return asALREADY_REGISTERED; @@ -1717,14 +1722,14 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD // Store it in the object types allRegisteredTypes.Insert(asSNameSpaceNamePair(type->nameSpace, type->name), type); - currentGroup->objTypes.PushLast(type); + currentGroup->types.PushLast(type); registeredObjTypes.PushLast(type); registeredTemplateTypes.PushLast(type); // Define the template subtypes for( asUINT subTypeIdx = 0; subTypeIdx < subtypeNames.GetLength(); subTypeIdx++ ) { - asCObjectType *subtype = 0; + asCTypeInfo *subtype = 0; for( asUINT n = 0; n < templateSubTypes.GetLength(); n++ ) { if( templateSubTypes[n]->name == subtypeNames[subTypeIdx] ) @@ -1736,19 +1741,16 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD if( subtype == 0 ) { // Create the new subtype if not already existing - subtype = asNEW(asCObjectType)(this); + subtype = asNEW(asCTypeInfo)(this); if( subtype == 0 ) return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0); subtype->name = subtypeNames[subTypeIdx]; subtype->size = 0; -#ifdef WIP_16BYTE_ALIGN - type->alignment = 0; // template subtypes cannot be instantiated and don't need alignment -#endif subtype->flags = asOBJ_TEMPLATE_SUBTYPE; templateSubTypes.PushLast(subtype); } - type->templateSubTypes.PushLast(asCDataType::CreateObject(subtype, false)); + type->templateSubTypes.PushLast(asCDataType::CreateType(subtype, false)); subtype->AddRefInternal(); } } @@ -1757,7 +1759,7 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD typeName = name; // Verify if the name has been registered as a type already - if( GetRegisteredObjectType(typeName, defaultNamespace) ) + if( GetRegisteredType(typeName, defaultNamespace) ) // This is not an irrepairable error, as it may just be that the same type is registered twice return asALREADY_REGISTERED; @@ -1785,7 +1787,7 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD // If the builder fails or the namespace is different than the default // namespace, then the type name is new and it should be registered - if( r < 0 || dt.GetObjectType()->nameSpace != defaultNamespace ) + if( r < 0 || dt.GetTypeInfo()->nameSpace != defaultNamespace ) { // Make sure the name is not a reserved keyword size_t tokenLen; @@ -1793,7 +1795,7 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD if( token != ttIdentifier || typeName.GetLength() != tokenLen ) return ConfigError(asINVALID_NAME, "RegisterObjectType", name, 0); - int r = bld.CheckNameConflict(name, 0, 0, defaultNamespace); + r = bld.CheckNameConflict(name, 0, 0, defaultNamespace); if( r < 0 ) return ConfigError(asNAME_TAKEN, "RegisterObjectType", name, 0); @@ -1818,7 +1820,7 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD allRegisteredTypes.Insert(asSNameSpaceNamePair(type->nameSpace, type->name), type); registeredObjTypes.PushLast(type); - currentGroup->objTypes.PushLast(type); + currentGroup->types.PushLast(type); } else { @@ -1836,7 +1838,7 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD return ConfigError(asINVALID_TYPE, "RegisterObjectType", name, 0); // Was the template instance type generated before? - if( generatedTemplateTypes.Exists(dt.GetObjectType()) && + if( generatedTemplateTypes.Exists(CastToObjectType(dt.GetTypeInfo())) && generatedTemplateTypes[generatedTemplateTypes.GetLength()-1] == mostRecentTemplateInstanceType ) { asCString str; @@ -1847,12 +1849,12 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD // If this is not a generated template instance type, then it means it is an // already registered template specialization - if( !generatedTemplateTypes.Exists(dt.GetObjectType()) ) + if( !generatedTemplateTypes.Exists(CastToObjectType(dt.GetTypeInfo())) ) return ConfigError(asALREADY_REGISTERED, "RegisterObjectType", name, 0); // TODO: Add this again. The type is used by the factory stubs so we need to discount that // Is the template instance type already being used? -// if( dt.GetObjectType()->GetRefCount() > 1 ) +// if( dt.GetTypeInfo()->GetRefCount() > 1 ) // return ConfigError(asNOT_SUPPORTED, "RegisterObjectType", name, 0); // Put the data type in the list @@ -1860,13 +1862,13 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD if( type == 0 ) return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0); - type->name = dt.GetObjectType()->name; + type->name = dt.GetTypeInfo()->name; // The namespace will be the same as the original template type - type->nameSpace = dt.GetObjectType()->nameSpace; + type->nameSpace = dt.GetTypeInfo()->nameSpace; type->templateSubTypes.PushLast(dt.GetSubType()); for( asUINT s = 0; s < type->templateSubTypes.GetLength(); s++ ) - if( type->templateSubTypes[s].GetObjectType() ) - type->templateSubTypes[s].GetObjectType()->AddRefInternal(); + if( type->templateSubTypes[s].GetTypeInfo() ) + type->templateSubTypes[s].GetTypeInfo()->AddRefInternal(); type->size = byteSize; #ifdef WIP_16BYTE_ALIGN // TODO: Types smaller than 4 don't need to be aligned to 4 byte boundaries @@ -1877,7 +1879,7 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD templateInstanceTypes.PushLast(type); - currentGroup->objTypes.PushLast(type); + currentGroup->types.PushLast(type); // Remove the template instance type, which will no longer be used. // It is possible that multiple template instances are generated if @@ -1895,7 +1897,7 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD } // interface -int asCScriptEngine::RegisterObjectBehaviour(const char *datatype, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall) +int asCScriptEngine::RegisterObjectBehaviour(const char *datatype, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary, int compositeOffset, bool isCompositeIndirect) { if( datatype == 0 ) return ConfigError(asINVALID_ARG, "RegisterObjectBehaviour", datatype, decl); @@ -1906,26 +1908,26 @@ int asCScriptEngine::RegisterObjectBehaviour(const char *datatype, asEBehaviours if( r < 0 ) return ConfigError(r, "RegisterObjectBehaviour", datatype, decl); - if( type.GetObjectType() == 0 || type.IsObjectHandle() ) + if( type.GetTypeInfo() == 0 || (type.IsObjectHandle() && !(type.GetTypeInfo()->GetFlags() & asOBJ_IMPLICIT_HANDLE)) ) return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl); // Don't allow application to modify built-in types - if( type.GetObjectType() == &functionBehaviours || - type.GetObjectType() == &scriptTypeBehaviours ) + if( type.GetTypeInfo() == &functionBehaviours || + type.GetTypeInfo() == &scriptTypeBehaviours ) return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl); if( type.IsReadOnly() || type.IsReference() ) return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl); // Don't allow modifying generated template instances - if( type.GetObjectType() && (type.GetObjectType()->flags & asOBJ_TEMPLATE) && generatedTemplateTypes.Exists(type.GetObjectType()) ) + if( type.GetTypeInfo() && (type.GetTypeInfo()->flags & asOBJ_TEMPLATE) && generatedTemplateTypes.Exists(CastToObjectType(type.GetTypeInfo())) ) return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl); - return RegisterBehaviourToObjectType(type.GetObjectType(), behaviour, decl, funcPointer, callConv, objForThiscall); + return RegisterBehaviourToObjectType(CastToObjectType(type.GetTypeInfo()), behaviour, decl, funcPointer, callConv, auxiliary, compositeOffset, isCompositeIndirect); } // internal -int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall) +int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary, int compositeOffset, bool isCompositeIndirect) { #ifdef AS_MAX_PORTABILITY if( callConv != asCALL_GENERIC ) @@ -1936,10 +1938,15 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as bool isMethod = !(behaviour == asBEHAVE_FACTORY || behaviour == asBEHAVE_LIST_FACTORY || behaviour == asBEHAVE_TEMPLATE_CALLBACK); - int r = DetectCallingConvention(isMethod, funcPointer, callConv, objForThiscall, &internal); + int r = DetectCallingConvention(isMethod, funcPointer, callConv, auxiliary, &internal); if( r < 0 ) return ConfigError(r, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl); + internal.compositeOffset = compositeOffset; + internal.isCompositeIndirect = isCompositeIndirect; + if( (compositeOffset || isCompositeIndirect) && callConv != asCALL_THISCALL ) + return ConfigError(asINVALID_ARG, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl); + // TODO: cleanup: This is identical to what is in RegisterMethodToObjectType // If the object type is a template, make sure there are no generated instances already if( objectType->flags & asOBJ_TEMPLATE ) @@ -1949,10 +1956,10 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as asCObjectType *tmpl = generatedTemplateTypes[n]; if( tmpl->name == objectType->name && tmpl->nameSpace == objectType->nameSpace && - !(tmpl->templateSubTypes[0].GetObjectType() && (tmpl->templateSubTypes[0].GetObjectType()->flags & asOBJ_TEMPLATE_SUBTYPE)) ) + !(tmpl->templateSubTypes[0].GetTypeInfo() && (tmpl->templateSubTypes[0].GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE)) ) { asCString msg; - msg.Format(TXT_TEMPLATE_s_ALREADY_GENERATED_CANT_REGISTER, asCDataType::CreateObject(tmpl, false).Format(tmpl->nameSpace).AddressOf()); + msg.Format(TXT_TEMPLATE_s_ALREADY_GENERATED_CANT_REGISTER, asCDataType::CreateType(tmpl, false).Format(tmpl->nameSpace).AddressOf()); WriteMessage("",0,0, asMSGTYPE_ERROR, msg.AddressOf()); return ConfigError(asERROR, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl); } @@ -1984,40 +1991,12 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as func.objectType->AddRefInternal(); } - // TODO: cleanup: This is identical to what is in RegisterMethodToObjectType // Check if the method restricts that use of the template to value types or reference types if( objectType->flags & asOBJ_TEMPLATE ) { - for( asUINT subTypeIdx = 0; subTypeIdx < objectType->templateSubTypes.GetLength(); subTypeIdx++ ) - { - if( func.returnType.GetObjectType() == objectType->templateSubTypes[subTypeIdx].GetObjectType() ) - { - if( func.returnType.IsObjectHandle() ) - objectType->acceptValueSubType = false; - else if( !func.returnType.IsReference() ) - objectType->acceptRefSubType = false; - - // Can't support template subtypes by value, since each type is treated differently in the ABI - if( !func.returnType.IsObjectHandle() && !func.returnType.IsReference() ) - return ConfigError(asNOT_SUPPORTED, "RegisterObjectMethod", objectType->name.AddressOf(), decl); - } - - for( asUINT n = 0; n < func.parameterTypes.GetLength(); n++ ) - { - if( func.parameterTypes[n].GetObjectType() == objectType->templateSubTypes[subTypeIdx].GetObjectType() ) - { - // TODO: If unsafe references are allowed, then inout references allow value types - if( func.parameterTypes[n].IsObjectHandle() || (func.parameterTypes[n].IsReference() && func.inOutFlags[n] == asTM_INOUTREF) ) - objectType->acceptValueSubType = false; - else if( !func.parameterTypes[n].IsReference() ) - objectType->acceptRefSubType = false; - - // Can't support template subtypes by value, since each type is treated differently in the ABI - if( !func.parameterTypes[n].IsObjectHandle() && !func.parameterTypes[n].IsReference() ) - return ConfigError(asNOT_SUPPORTED, "RegisterObjectMethod", objectType->name.AddressOf(), decl); - } - } - } + r = SetTemplateRestrictions(objectType, &func, "RegisterObjectBehaviour", decl); + if (r < 0) + return r; } if( behaviour == asBEHAVE_CONSTRUCT ) @@ -2074,7 +2053,7 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as // If the parameter is object, and const reference for input or inout, // and same type as this class, then this is a copy constructor. if( paramType.IsObject() && paramType.IsReference() && paramType.IsReadOnly() && - (func.inOutFlags[0] & asTM_INREF) && paramType.GetObjectType() == objectType ) + (func.inOutFlags[0] & asTM_INREF) && paramType.GetTypeInfo() == objectType ) beh->copyconstruct = func.id; } } @@ -2148,7 +2127,7 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as beh->listFactory = func.id; // Store the list pattern for this function - int r = scriptFunctions[func.id]->RegisterListPattern(decl, listPattern); + r = scriptFunctions[func.id]->RegisterListPattern(decl, listPattern); if( listPattern ) listPattern->Destroy(this); @@ -2245,7 +2224,7 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as beh->listFactory = func.id; // Store the list pattern for this function - int r = scriptFunctions[func.id]->RegisterListPattern(decl, listPattern); + r = scriptFunctions[func.id]->RegisterListPattern(decl, listPattern); if( listPattern ) listPattern->Destroy(this); @@ -2260,7 +2239,7 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as // If the parameter is object, and const reference for input, // and same type as this class, then this is a copy constructor. - if( paramType.IsObject() && paramType.IsReference() && paramType.IsReadOnly() && func.inOutFlags[func.parameterTypes.GetLength()-1] == asTM_INREF && paramType.GetObjectType() == objectType ) + if( paramType.IsObject() && paramType.IsReference() && paramType.IsReadOnly() && func.inOutFlags[func.parameterTypes.GetLength()-1] == asTM_INREF && paramType.GetTypeInfo() == objectType ) beh->copyfactory = func.id; } } @@ -2389,58 +2368,6 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as else if( behaviour == asBEHAVE_RELEASEREFS ) func.id = beh->gcReleaseAllReferences = AddBehaviourFunction(func, internal); } -#ifdef AS_DEPRECATED - // Deprecated since 2.30.0. 2014-10-24 - else if( behaviour == asBEHAVE_IMPLICIT_VALUE_CAST || - behaviour == asBEHAVE_VALUE_CAST ) - { - // There are two allowed signatures - // 1. type f() - // 2. void f(?&out) - - if( !(func.parameterTypes.GetLength() == 1 && func.parameterTypes[0].GetTokenType() == ttQuestion && func.inOutFlags[0] == asTM_OUTREF && func.returnType.GetTokenType() == ttVoid) && - !(func.parameterTypes.GetLength() == 0 && func.returnType.GetTokenType() != ttVoid) ) - return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl); - - // It is not allowed to implement a value cast to bool - if( func.returnType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, false)) ) - return ConfigError(asNOT_SUPPORTED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl); - - asCString decl; - decl += func.returnType.Format(defaultNamespace); - decl += behaviour == asBEHAVE_VALUE_CAST ? " opConv(" : " opImplConv("; - if( func.parameterTypes.GetLength() ) - decl += "?&out"; - decl += ")"; - func.id = RegisterMethodToObjectType(objectType, decl.AddressOf(), funcPointer, callConv, objForThiscall); - } - // Deprecated since 2.30.0, 2014-12-30 - else if( behaviour == asBEHAVE_REF_CAST || - behaviour == asBEHAVE_IMPLICIT_REF_CAST ) - { - // There are two allowed signatures - // 1. obj @f() - // 2. void f(?&out) - - if( !(func.parameterTypes.GetLength() == 0 && func.returnType.IsObjectHandle()) && - !(func.parameterTypes.GetLength() == 1 && func.parameterTypes[0].GetTokenType() == ttQuestion && func.inOutFlags[0] == asTM_OUTREF && func.returnType.GetTokenType() == ttVoid) ) - return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl); - - // Currently it is not supported to register const overloads for the ref cast behaviour - if( func.IsReadOnly() ) - return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl); - - asCString decl; - decl += func.returnType.Format(defaultNamespace); - if( internal.returnAutoHandle ) - decl += "+"; - decl += behaviour == asBEHAVE_REF_CAST ? " opCast(" : " opImplCast("; - if( func.parameterTypes.GetLength() ) - decl += "?&out"; - decl += ")"; - func.id = RegisterMethodToObjectType(objectType, decl.AddressOf(), funcPointer, callConv, objForThiscall); - } -#endif else if ( behaviour == asBEHAVE_GET_WEAKREF_FLAG ) { // This behaviour is only allowed for reference types @@ -2484,6 +2411,43 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as return func.id; } +int asCScriptEngine::SetTemplateRestrictions(asCObjectType *templateType, asCScriptFunction *func, const char *caller, const char *decl) +{ + asASSERT(templateType->flags & asOBJ_TEMPLATE); + + for (asUINT subTypeIdx = 0; subTypeIdx < templateType->templateSubTypes.GetLength(); subTypeIdx++) + { + if (func->returnType.GetTypeInfo() == templateType->templateSubTypes[subTypeIdx].GetTypeInfo()) + { + if (func->returnType.IsObjectHandle()) + templateType->acceptValueSubType = false; + else if (!func->returnType.IsReference()) + templateType->acceptRefSubType = false; + + // Can't support template subtypes by value, since each type is treated differently in the ABI + if (!func->returnType.IsObjectHandle() && !func->returnType.IsReference()) + return ConfigError(asNOT_SUPPORTED, caller, templateType->name.AddressOf(), decl); + } + + for (asUINT n = 0; n < func->parameterTypes.GetLength(); n++) + { + if (func->parameterTypes[n].GetTypeInfo() == templateType->templateSubTypes[subTypeIdx].GetTypeInfo()) + { + // TODO: If unsafe references are allowed, then inout references allow value types + if (func->parameterTypes[n].IsObjectHandle() || (func->parameterTypes[n].IsReference() && func->inOutFlags[n] == asTM_INOUTREF)) + templateType->acceptValueSubType = false; + else if (!func->parameterTypes[n].IsReference()) + templateType->acceptRefSubType = false; + + // Can't support template subtypes by value, since each type is treated differently in the ABI + if (!func->parameterTypes[n].IsObjectHandle() && !func->parameterTypes[n].IsReference()) + return ConfigError(asNOT_SUPPORTED, caller, templateType->name.AddressOf(), decl); + } + } + } + + return asSUCCESS; +} int asCScriptEngine::VerifyVarTypeNotInFunction(asCScriptFunction *func) { @@ -2523,9 +2487,10 @@ int asCScriptEngine::AddBehaviourFunction(asCScriptFunction &func, asSSystemFunc if( f->objectType ) f->objectType->AddRefInternal(); f->id = id; - f->isReadOnly = func.isReadOnly; + f->SetReadOnly(func.IsReadOnly()); f->accessMask = defaultAccessMask; f->parameterTypes = func.parameterTypes; + f->parameterNames = func.parameterNames; f->inOutFlags = func.inOutFlags; for( n = 0; n < func.defaultArgs.GetLength(); n++ ) if( func.defaultArgs[n] ) @@ -2574,7 +2539,7 @@ int asCScriptEngine::RegisterGlobalProperty(const char *declaration, void *point prop->AddRef(); currentGroup->globalProps.PushLast(prop); - currentGroup->AddReferencesForType(this, type.GetObjectType()); + currentGroup->AddReferencesForType(this, type.GetTypeInfo()); return asSUCCESS; } @@ -2663,7 +2628,7 @@ int asCScriptEngine::GetGlobalPropertyIndexByName(const char *name) const while( ns ) { int id = registeredGlobalProps.GetFirstIndex(ns, name); - if( id >= 0 ) + if( id >= 0 ) return id; // Recursively search parent namespace @@ -2703,7 +2668,7 @@ int asCScriptEngine::GetGlobalPropertyIndexByDecl(const char *decl) const } // interface -int asCScriptEngine::RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall) +int asCScriptEngine::RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary, int compositeOffset, bool isCompositeIndirect) { if( obj == 0 ) return ConfigError(asINVALID_ARG, "RegisterObjectMethod", obj, declaration); @@ -2715,23 +2680,25 @@ int asCScriptEngine::RegisterObjectMethod(const char *obj, const char *declarati if( r < 0 ) return ConfigError(r, "RegisterObjectMethod", obj, declaration); - if( dt.GetObjectType() == 0 || dt.IsObjectHandle() ) + // Don't allow application to modify primitives or handles + if( dt.GetTypeInfo() == 0 || (dt.IsObjectHandle() && !(dt.GetTypeInfo()->GetFlags() & asOBJ_IMPLICIT_HANDLE))) return ConfigError(asINVALID_ARG, "RegisterObjectMethod", obj, declaration); - // Don't allow application to modify built-in types - if( dt.GetObjectType() == &functionBehaviours || - dt.GetObjectType() == &scriptTypeBehaviours ) + // Don't allow application to modify built-in types or funcdefs + if( dt.GetTypeInfo() == &functionBehaviours || + dt.GetTypeInfo() == &scriptTypeBehaviours || + CastToFuncdefType(dt.GetTypeInfo()) ) return ConfigError(asINVALID_ARG, "RegisterObjectMethod", obj, declaration); // Don't allow modifying generated template instances - if( dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_TEMPLATE) && generatedTemplateTypes.Exists(dt.GetObjectType()) ) + if( dt.GetTypeInfo() && (dt.GetTypeInfo()->flags & asOBJ_TEMPLATE) && generatedTemplateTypes.Exists(CastToObjectType(dt.GetTypeInfo())) ) return ConfigError(asINVALID_TYPE, "RegisterObjectMethod", obj, declaration); - return RegisterMethodToObjectType(dt.GetObjectType(), declaration, funcPointer, callConv, objForThiscall); + return RegisterMethodToObjectType(CastToObjectType(dt.GetTypeInfo()), declaration, funcPointer, callConv, auxiliary, compositeOffset, isCompositeIndirect); } // internal -int asCScriptEngine::RegisterMethodToObjectType(asCObjectType *objectType, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall) +int asCScriptEngine::RegisterMethodToObjectType(asCObjectType *objectType, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary, int compositeOffset, bool isCompositeIndirect) { #ifdef AS_MAX_PORTABILITY if( callConv != asCALL_GENERIC ) @@ -2739,10 +2706,15 @@ int asCScriptEngine::RegisterMethodToObjectType(asCObjectType *objectType, const #endif asSSystemFunctionInterface internal; - int r = DetectCallingConvention(true, funcPointer, callConv, objForThiscall, &internal); + int r = DetectCallingConvention(true, funcPointer, callConv, auxiliary, &internal); if( r < 0 ) return ConfigError(r, "RegisterObjectMethod", objectType->name.AddressOf(), declaration); + internal.compositeOffset = compositeOffset; + internal.isCompositeIndirect = isCompositeIndirect; + if( (compositeOffset || isCompositeIndirect) && callConv != asCALL_THISCALL ) + return ConfigError(asINVALID_ARG, "RegisterObjectMethod", objectType->name.AddressOf(), declaration); + // TODO: cleanup: This is identical to what is in RegisterMethodToObjectType // If the object type is a template, make sure there are no generated instances already if( objectType->flags & asOBJ_TEMPLATE ) @@ -2752,10 +2724,10 @@ int asCScriptEngine::RegisterMethodToObjectType(asCObjectType *objectType, const asCObjectType *tmpl = generatedTemplateTypes[n]; if( tmpl->name == objectType->name && tmpl->nameSpace == objectType->nameSpace && - !(tmpl->templateSubTypes[0].GetObjectType() && (tmpl->templateSubTypes[0].GetObjectType()->flags & asOBJ_TEMPLATE_SUBTYPE)) ) + !(tmpl->templateSubTypes[0].GetTypeInfo() && (tmpl->templateSubTypes[0].GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE)) ) { asCString msg; - msg.Format(TXT_TEMPLATE_s_ALREADY_GENERATED_CANT_REGISTER, asCDataType::CreateObject(tmpl, false).Format(tmpl->nameSpace).AddressOf()); + msg.Format(TXT_TEMPLATE_s_ALREADY_GENERATED_CANT_REGISTER, asCDataType::CreateType(tmpl, false).Format(tmpl->nameSpace).AddressOf()); WriteMessage("",0,0, asMSGTYPE_ERROR, msg.AddressOf()); return ConfigError(asERROR, "RegisterObjectMethod", objectType->name.AddressOf(), declaration); } @@ -2800,11 +2772,10 @@ int asCScriptEngine::RegisterMethodToObjectType(asCObjectType *objectType, const } // Check against duplicate methods - asUINT n; if( func->name == "opConv" || func->name == "opImplConv" || func->name == "opCast" || func->name == "opImplCast" ) { // opConv and opCast are special methods that the compiler differentiates between by the return type - for( n = 0; n < func->objectType->methods.GetLength(); n++ ) + for( asUINT n = 0; n < func->objectType->methods.GetLength(); n++ ) { asCScriptFunction *f = scriptFunctions[func->objectType->methods[n]]; if( f->name == func->name && @@ -2818,7 +2789,7 @@ int asCScriptEngine::RegisterMethodToObjectType(asCObjectType *objectType, const } else { - for( n = 0; n < func->objectType->methods.GetLength(); n++ ) + for( asUINT n = 0; n < func->objectType->methods.GetLength(); n++ ) { asCScriptFunction *f = scriptFunctions[func->objectType->methods[n]]; if( f->name == func->name && @@ -2842,42 +2813,15 @@ int asCScriptEngine::RegisterMethodToObjectType(asCObjectType *objectType, const // Check if the method restricts that use of the template to value types or reference types if( func->objectType->flags & asOBJ_TEMPLATE ) { - for( asUINT subTypeIdx = 0; subTypeIdx < func->objectType->templateSubTypes.GetLength(); subTypeIdx++ ) - { - if( func->returnType.GetObjectType() == func->objectType->templateSubTypes[subTypeIdx].GetObjectType() ) - { - if( func->returnType.IsObjectHandle() ) - func->objectType->acceptValueSubType = false; - else if( !func->returnType.IsReference() ) - func->objectType->acceptRefSubType = false; - - // Can't support template subtypes by value, since each type is treated differently in the ABI - if( !func->returnType.IsObjectHandle() && !func->returnType.IsReference() ) - return ConfigError(asNOT_SUPPORTED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration); - } - - for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ ) - { - if( func->parameterTypes[n].GetObjectType() == func->objectType->templateSubTypes[subTypeIdx].GetObjectType() ) - { - // TODO: If unsafe references are allowed, then inout references allow value types - if( func->parameterTypes[n].IsObjectHandle() || (func->parameterTypes[n].IsReference() && func->inOutFlags[n] == asTM_INOUTREF) ) - func->objectType->acceptValueSubType = false; - else if( !func->parameterTypes[n].IsReference() ) - func->objectType->acceptRefSubType = false; - - // Can't support template subtypes by value, since each type is treated differently in the ABI - if( !func->parameterTypes[n].IsObjectHandle() && !func->parameterTypes[n].IsReference() ) - return ConfigError(asNOT_SUPPORTED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration); - } - } - } + r = SetTemplateRestrictions(func->objectType, func, "RegisterObjectMethod", declaration); + if (r < 0) + return r; } // TODO: beh.copy member will be removed, so this is not necessary // Is this the default copy behaviour? - if( func->name == "opAssign" && func->parameterTypes.GetLength() == 1 && func->isReadOnly == false && - ((objectType->flags & asOBJ_SCRIPT_OBJECT) || func->parameterTypes[0].IsEqualExceptRefAndConst(asCDataType::CreateObject(func->objectType, false))) ) + if( func->name == "opAssign" && func->parameterTypes.GetLength() == 1 && !func->IsReadOnly() && + ((objectType->flags & asOBJ_SCRIPT_OBJECT) || func->parameterTypes[0].IsEqualExceptRefAndConst(asCDataType::CreateType(func->objectType, false))) ) { if( func->objectType->beh.copy != 0 ) return ConfigError(asALREADY_REGISTERED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration); @@ -2891,7 +2835,7 @@ int asCScriptEngine::RegisterMethodToObjectType(asCObjectType *objectType, const } // interface -int asCScriptEngine::RegisterGlobalFunction(const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall) +int asCScriptEngine::RegisterGlobalFunction(const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary) { #ifdef AS_MAX_PORTABILITY if( callConv != asCALL_GENERIC ) @@ -2899,7 +2843,7 @@ int asCScriptEngine::RegisterGlobalFunction(const char *declaration, const asSFu #endif asSSystemFunctionInterface internal; - int r = DetectCallingConvention(false, funcPointer, callConv, objForThiscall, &internal); + int r = DetectCallingConvention(false, funcPointer, callConv, auxiliary, &internal); if( r < 0 ) return ConfigError(r, "RegisterGlobalFunction", declaration, 0); @@ -3048,9 +2992,9 @@ asIScriptFunction *asCScriptEngine::GetGlobalFunctionByDecl(const char *decl) co } -asCObjectType *asCScriptEngine::GetRegisteredObjectType(const asCString &type, asSNameSpace *ns) const +asCTypeInfo *asCScriptEngine::GetRegisteredType(const asCString &type, asSNameSpace *ns) const { - asSMapNode *cursor; + asSMapNode *cursor; if( allRegisteredTypes.MoveTo(&cursor, asSNameSpaceNamePair(ns, type)) ) return cursor->value; @@ -3128,7 +3072,7 @@ void asCScriptEngine::PrepareEngine() else if( (type->flags & asOBJ_VALUE) && !(type->flags & asOBJ_POD) ) { - if( type->beh.construct == 0 || + if( type->beh.constructors.GetLength() == 0 || type->beh.destruct == 0 ) { infoMsg = TXT_NON_POD_REQUIRE_CONSTR_DESTR_BEHAVIOUR; @@ -3179,11 +3123,11 @@ int asCScriptEngine::RegisterDefaultArrayType(const char *type) int r = bld.ParseDataType(type, &dt, defaultNamespace); if( r < 0 ) return r; - if( dt.GetObjectType() == 0 || - !(dt.GetObjectType()->GetFlags() & asOBJ_TEMPLATE) ) + if( dt.GetTypeInfo() == 0 || + !(dt.GetTypeInfo()->GetFlags() & asOBJ_TEMPLATE) ) return asINVALID_TYPE; - defaultArrayObjectType = dt.GetObjectType(); + defaultArrayObjectType = CastToObjectType(dt.GetTypeInfo()); defaultArrayObjectType->AddRefInternal(); return 0; @@ -3193,78 +3137,35 @@ int asCScriptEngine::RegisterDefaultArrayType(const char *type) int asCScriptEngine::GetDefaultArrayTypeId() const { if( defaultArrayObjectType ) - return GetTypeIdFromDataType(asCDataType::CreateObject(defaultArrayObjectType, false)); + return GetTypeIdFromDataType(asCDataType::CreateType(defaultArrayObjectType, false)); return asINVALID_TYPE; } // interface -int asCScriptEngine::RegisterStringFactory(const char *datatype, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall) +int asCScriptEngine::RegisterStringFactory(const char *datatype, asIStringFactory *factory) { - asSSystemFunctionInterface internal; - int r = DetectCallingConvention(false, funcPointer, callConv, objForThiscall, &internal); - if( r < 0 ) - return ConfigError(r, "RegisterStringFactory", datatype, 0); - -#ifdef AS_MAX_PORTABILITY - if( callConv != asCALL_GENERIC ) - return ConfigError(asNOT_SUPPORTED, "RegisterStringFactory", datatype, 0); -#else - if( callConv != asCALL_CDECL && - callConv != asCALL_STDCALL && - callConv != asCALL_THISCALL_ASGLOBAL && - callConv != asCALL_GENERIC ) - return ConfigError(asNOT_SUPPORTED, "RegisterStringFactory", datatype, 0); -#endif - - // Put the system function in the list of system functions - asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal); - if( newInterface == 0 ) - return ConfigError(asOUT_OF_MEMORY, "RegisterStringFactory", datatype, 0); - - asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM); - if( func == 0 ) - { - asDELETE(newInterface, asSSystemFunctionInterface); - return ConfigError(asOUT_OF_MEMORY, "RegisterStringFactory", datatype, 0); - } - - func->name = "$str"; - func->sysFuncIntf = newInterface; + if (factory == 0) + return ConfigError(asINVALID_ARG, "RegisterStringFactory", datatype, 0); + // Parse the data type asCBuilder bld(this, 0); - asCDataType dt; - r = bld.ParseDataType(datatype, &dt, defaultNamespace, true); - if( r < 0 ) - { - // Set as dummy before deleting - func->funcType = asFUNC_DUMMY; - asDELETE(func,asCScriptFunction); + int r = bld.ParseDataType(datatype, &dt, defaultNamespace, true); + if (r < 0) return ConfigError(asINVALID_TYPE, "RegisterStringFactory", datatype, 0); - } - func->returnType = dt; - func->parameterTypes.PushLast(asCDataType::CreatePrimitive(ttInt, true)); - func->inOutFlags.PushLast(asTM_NONE); - asCDataType parm1 = asCDataType::CreatePrimitive(ttUInt8, true); - parm1.MakeReference(true); - func->parameterTypes.PushLast(parm1); - func->inOutFlags.PushLast(asTM_INREF); - func->id = GetNextScriptFunctionId(); - AddScriptFunction(func); + // Validate the type. It must not be reference or handle + if (dt.IsReference() || dt.IsObjectHandle()) + return ConfigError(asINVALID_TYPE, "RegisterStringFactory", datatype, 0); - stringFactory = func; + // All string literals will be treated as const + dt.MakeReadOnly(true); - if( func->returnType.GetObjectType() ) - { - asCConfigGroup *group = FindConfigGroupForObjectType(func->returnType.GetObjectType()); - if( group == 0 ) group = &defaultGroup; - group->scriptFunctions.PushLast(func); - } + stringType = dt; + stringFactory = factory; - // Register function id as success - return func->id; + return asSUCCESS; } // interface @@ -3273,7 +3174,9 @@ int asCScriptEngine::GetStringFactoryReturnTypeId(asDWORD *flags) const if( stringFactory == 0 ) return asNO_FUNCTION; - return stringFactory->GetReturnTypeId(flags); + if( flags ) + *flags = 0; + return GetTypeIdFromDataType(stringType); } // internal @@ -3403,7 +3306,7 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT if( type->module == 0 ) { // Set the ownership of this template type - // It may be without ownership if it was previously created from application with for example GetObjectTypeByDecl + // It may be without ownership if it was previously created from application with for example GetTypeInfoByDecl type->module = requestingModule; } if( !requestingModule->templateInstances.Exists(type) ) @@ -3422,10 +3325,10 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT // Make sure this template supports the subtype for( n = 0; n < subTypes.GetLength(); n++ ) { - if( !templateType->acceptValueSubType && (subTypes[n].IsPrimitive() || (subTypes[n].GetObjectType()->flags & asOBJ_VALUE)) ) + if( !templateType->acceptValueSubType && (subTypes[n].IsPrimitive() || (subTypes[n].GetTypeInfo()->flags & asOBJ_VALUE)) ) return 0; - if( !templateType->acceptRefSubType && (subTypes[n].IsObject() && (subTypes[n].GetObjectType()->flags & asOBJ_REF)) ) + if( !templateType->acceptRefSubType && (subTypes[n].IsObject() && (subTypes[n].GetTypeInfo()->flags & asOBJ_REF)) ) return 0; } @@ -3459,9 +3362,9 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT // engine at any time (unless the application holds an external reference). for( n = 0; n < subTypes.GetLength(); n++ ) { - if( subTypes[n].GetObjectType() ) + if( subTypes[n].GetTypeInfo() ) { - ot->module = subTypes[n].GetObjectType()->module; + ot->module = subTypes[n].GetTypeInfo()->module; if( ot->module ) { ot->module->templateInstances.PushLast(ot); @@ -3534,6 +3437,15 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT // The object types in templateInstanceTypes that are not also in generatedTemplateTypes are registered template specializations generatedTemplateTypes.PushLast(ot); + // Any child funcdefs must be copied to the template instance (with adjustments in case of template subtypes) + // This must be done before resolving other methods, to make sure the other methods that may refer to the + // templated funcdef will resolve to the new funcdef + for (n = 0; n < templateType->childFuncDefs.GetLength(); n++) + { + asCFuncdefType *funcdef = GenerateNewTemplateFuncdef(templateType, ot, templateType->childFuncDefs[n]); + funcdef->parentClass = ot; + ot->childFuncDefs.PushLast(funcdef); + } // As the new template type is instantiated the engine should // generate new functions to substitute the ones with the template subtype. @@ -3590,7 +3502,7 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT if( templateType->beh.listFactory ) { asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, templateType->beh.listFactory); - + // Rename the function to easily identify it in LoadByteCode func->name = "$list"; @@ -3635,23 +3547,23 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT // Increase ref counter for sub type if it is an object type for( n = 0; n < ot->templateSubTypes.GetLength(); n++ ) - if( ot->templateSubTypes[n].GetObjectType() ) - ot->templateSubTypes[n].GetObjectType()->AddRefInternal(); + if( ot->templateSubTypes[n].GetTypeInfo() ) + ot->templateSubTypes[n].GetTypeInfo()->AddRefInternal(); // Copy the properties to the template instance for( n = 0; n < templateType->properties.GetLength(); n++ ) { asCObjectProperty *prop = templateType->properties[n]; ot->properties.PushLast(asNEW(asCObjectProperty)(*prop)); - if( prop->type.GetObjectType() ) - prop->type.GetObjectType()->AddRefInternal(); + if( prop->type.GetTypeInfo() ) + prop->type.GetTypeInfo()->AddRefInternal(); } return ot; } // interface -asILockableSharedBool *asCScriptEngine::GetWeakRefFlagOfScriptObject(void *obj, const asIObjectType *type) const +asILockableSharedBool *asCScriptEngine::GetWeakRefFlagOfScriptObject(void *obj, const asITypeInfo *type) const { // Make sure it is not a null pointer if( obj == 0 || type == 0 ) return 0; @@ -3667,21 +3579,25 @@ asILockableSharedBool *asCScriptEngine::GetWeakRefFlagOfScriptObject(void *obj, } // internal +// orig is the parameter type that is to be replaced +// tmpl is the registered template. Used to find which subtype is being replaced +// ot is the new template instance that is being created. Used to find the target type asCDataType asCScriptEngine::DetermineTypeForTemplate(const asCDataType &orig, asCObjectType *tmpl, asCObjectType *ot) { asCDataType dt; - if( orig.GetObjectType() && (orig.GetObjectType()->flags & asOBJ_TEMPLATE_SUBTYPE) ) + if( orig.GetTypeInfo() && (orig.GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE) ) { bool found = false; for( asUINT n = 0; n < tmpl->templateSubTypes.GetLength(); n++ ) { - if( orig.GetObjectType() == tmpl->templateSubTypes[n].GetObjectType() ) + if( orig.GetTypeInfo() == tmpl->templateSubTypes[n].GetTypeInfo() ) { found = true; dt = ot->templateSubTypes[n]; if( orig.IsObjectHandle() && !ot->templateSubTypes[n].IsObjectHandle() ) { dt.MakeHandle(true, true); + asASSERT(dt.IsObjectHandle()); if( orig.IsHandleToConst() ) dt.MakeHandleToConst(true); dt.MakeReference(orig.IsReference()); @@ -3689,6 +3605,12 @@ asCDataType asCScriptEngine::DetermineTypeForTemplate(const asCDataType &orig, a } else { + // The target type is a handle, then check if the application + // wants this handle to be to a const object. This is done by + // flagging the type with 'if_handle_then_const' in the declaration. + if (dt.IsObjectHandle() && orig.HasIfHandleThenConst()) + dt.MakeHandleToConst(true); + dt.MakeReference(orig.IsReference()); dt.MakeReadOnly(ot->templateSubTypes[n].IsReadOnly() || orig.IsReadOnly()); } @@ -3698,28 +3620,28 @@ asCDataType asCScriptEngine::DetermineTypeForTemplate(const asCDataType &orig, a asASSERT( found ); UNUSED_VAR( found ); } - else if( orig.GetObjectType() == tmpl ) + else if( orig.GetTypeInfo() == tmpl ) { if( orig.IsObjectHandle() ) dt = asCDataType::CreateObjectHandle(ot, false); else - dt = asCDataType::CreateObject(ot, false); + dt = asCDataType::CreateType(ot, false); dt.MakeReference(orig.IsReference()); dt.MakeReadOnly(orig.IsReadOnly()); } - else if( orig.GetObjectType() && (orig.GetObjectType()->flags & asOBJ_TEMPLATE) ) + else if( orig.GetTypeInfo() && (orig.GetTypeInfo()->flags & asOBJ_TEMPLATE) ) { // The type is itself a template, so it is necessary to find the correct template instance type asCArray tmplSubTypes; - asCObjectType *origType = orig.GetObjectType(); + asCObjectType *origType = CastToObjectType(orig.GetTypeInfo()); bool needInstance = true; // Find the matching replacements for the subtypes for( asUINT n = 0; n < origType->templateSubTypes.GetLength(); n++ ) { - if( origType->templateSubTypes[n].GetObjectType() == 0 || - !(origType->templateSubTypes[n].GetObjectType()->flags & asOBJ_TEMPLATE_SUBTYPE) ) + if( origType->templateSubTypes[n].GetTypeInfo() == 0 || + !(origType->templateSubTypes[n].GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE) ) { // The template is already an instance so we shouldn't attempt to create another instance needInstance = false; @@ -3727,7 +3649,7 @@ asCDataType asCScriptEngine::DetermineTypeForTemplate(const asCDataType &orig, a } for( asUINT m = 0; m < tmpl->templateSubTypes.GetLength(); m++ ) - if( origType->templateSubTypes[n].GetObjectType() == tmpl->templateSubTypes[m].GetObjectType() ) + if( origType->templateSubTypes[n].GetTypeInfo() == tmpl->templateSubTypes[m].GetTypeInfo() ) tmplSubTypes.PushLast(ot->templateSubTypes[m]); if( tmplSubTypes.GetLength() != n+1 ) @@ -3761,11 +3683,23 @@ asCDataType asCScriptEngine::DetermineTypeForTemplate(const asCDataType &orig, a if( orig.IsObjectHandle() ) dt = asCDataType::CreateObjectHandle(ntype, false); else - dt = asCDataType::CreateObject(ntype, false); + dt = asCDataType::CreateType(ntype, false); dt.MakeReference(orig.IsReference()); dt.MakeReadOnly(orig.IsReadOnly()); } + else if (orig.GetTypeInfo() && (orig.GetTypeInfo()->flags & asOBJ_FUNCDEF) && CastToFuncdefType(orig.GetTypeInfo())->parentClass == tmpl) + { + // The type is a child funcdef. Find the corresponding child funcdef in the template instance + for (asUINT n = 0; n < ot->childFuncDefs.GetLength(); n++) + { + if (ot->childFuncDefs[n]->name == orig.GetTypeInfo()->name) + { + dt = orig; + dt.SetTypeInfo(ot->childFuncDefs[n]); + } + } + } else dt = orig; @@ -3788,34 +3722,39 @@ asCScriptFunction *asCScriptEngine::GenerateTemplateFactoryStub(asCObjectType *t return 0; } - func->funcType = asFUNC_SCRIPT; + func->funcType = asFUNC_SCRIPT; func->AllocateScriptFunctionData(); - func->name = "$fact"; - func->id = GetNextScriptFunctionId(); + func->id = GetNextScriptFunctionId(); AddScriptFunction(func); - func->isShared = true; + func->SetShared(true); if( templateType->flags & asOBJ_REF ) { - func->returnType = asCDataType::CreateObjectHandle(ot, false); + func->name = "$fact"; + func->returnType = asCDataType::CreateObjectHandle(ot, false); } else { - func->returnType = factory->returnType; // constructors return nothing - func->objectType = ot; + func->name = "$beh0"; + func->returnType = factory->returnType; // constructors return nothing + func->objectType = ot; func->objectType->AddRefInternal(); } // Skip the first parameter as this is the object type pointer that the stub will add func->parameterTypes.SetLength(factory->parameterTypes.GetLength()-1); + func->parameterNames.SetLength(factory->parameterNames.GetLength()-1); func->inOutFlags.SetLength(factory->inOutFlags.GetLength()-1); + func->defaultArgs.SetLength(factory->defaultArgs.GetLength()-1); for( asUINT p = 1; p < factory->parameterTypes.GetLength(); p++ ) { func->parameterTypes[p-1] = factory->parameterTypes[p]; + func->parameterNames[p-1] = factory->parameterNames[p]; func->inOutFlags[p-1] = factory->inOutFlags[p]; + func->defaultArgs[p-1] = factory->defaultArgs[p] ? asNEW(asCString)(*factory->defaultArgs[p]) : 0; } func->scriptData->objVariablesOnHeap = 0; - + // Generate the bytecode for the factory stub asUINT bcLength = asBCTypeSize[asBCInfo[asBC_OBJTYPE].type] + asBCTypeSize[asBCInfo[asBC_CALLSYS].type] + @@ -3889,15 +3828,18 @@ asCScriptFunction *asCScriptEngine::GenerateTemplateFactoryStub(asCObjectType *t bool asCScriptEngine::RequireTypeReplacement(asCDataType &type, asCObjectType *templateType) { - if( type.GetObjectType() == templateType ) return true; - if( type.GetObjectType() && (type.GetObjectType()->flags & asOBJ_TEMPLATE_SUBTYPE) ) return true; - if( type.GetObjectType() && (type.GetObjectType()->flags & asOBJ_TEMPLATE) ) + if( type.GetTypeInfo() == templateType ) return true; + if( type.GetTypeInfo() && (type.GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE) ) return true; + if( type.GetTypeInfo() && (type.GetTypeInfo()->flags & asOBJ_TEMPLATE) ) { - for( asUINT n = 0; n < type.GetObjectType()->templateSubTypes.GetLength(); n++ ) - if( type.GetObjectType()->templateSubTypes[n].GetObjectType() && - type.GetObjectType()->templateSubTypes[n].GetObjectType()->flags & asOBJ_TEMPLATE_SUBTYPE ) + asCObjectType *ot = CastToObjectType(type.GetTypeInfo()); + for( asUINT n = 0; n < ot->templateSubTypes.GetLength(); n++ ) + if( ot->templateSubTypes[n].GetTypeInfo() && + ot->templateSubTypes[n].GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE ) return true; } + if (type.GetTypeInfo() && (type.GetTypeInfo()->flags & asOBJ_FUNCDEF) && CastToFuncdefType(type.GetTypeInfo())->parentClass == templateType) + return true; return false; } @@ -3933,16 +3875,23 @@ bool asCScriptEngine::GenerateNewTemplateFunction(asCObjectType *templateType, a func2->returnType = DetermineTypeForTemplate(func->returnType, templateType, ot); func2->parameterTypes.SetLength(func->parameterTypes.GetLength()); - for( asUINT p = 0; p < func->parameterTypes.GetLength(); p++ ) + for (asUINT p = 0; p < func->parameterTypes.GetLength(); p++) func2->parameterTypes[p] = DetermineTypeForTemplate(func->parameterTypes[p], templateType, ot); + for (asUINT n = 0; n < func->defaultArgs.GetLength(); n++) + if (func->defaultArgs[n]) + func2->defaultArgs.PushLast(asNEW(asCString)(*func->defaultArgs[n])); + else + func2->defaultArgs.PushLast(0); + // TODO: template: Must be careful when instantiating templates for garbage collected types // If the template hasn't been registered with the behaviours, it shouldn't // permit instantiation of garbage collected types that in turn may refer to // this instance. + func2->parameterNames = func->parameterNames; func2->inOutFlags = func->inOutFlags; - func2->isReadOnly = func->isReadOnly; + func2->SetReadOnly(func->IsReadOnly()); func2->objectType = ot; func2->objectType->AddRefInternal(); func2->sysFuncIntf = asNEW(asSSystemFunctionInterface)(*func->sysFuncIntf); @@ -3963,6 +3912,48 @@ bool asCScriptEngine::GenerateNewTemplateFunction(asCObjectType *templateType, a return true; } +asCFuncdefType *asCScriptEngine::GenerateNewTemplateFuncdef(asCObjectType *templateType, asCObjectType *ot, asCFuncdefType *func) +{ + // TODO: Only generate the new funcdef if it used the template subtypes. + // Remember to also update the clean up in asCObjectType::DestroyInternal so it doesn't delete + // child funcdefs that have not been created specificially for the template instance. + // Perhaps a new funcdef is always needed, since the funcdef will have a reference to the + // parent class (in this case the template instance). + + asCScriptFunction *func2 = asNEW(asCScriptFunction)(this, 0, func->funcdef->funcType); + if (func2 == 0) + { + // Out of memory + return 0; + } + + func2->name = func->name; + + func2->returnType = DetermineTypeForTemplate(func->funcdef->returnType, templateType, ot); + func2->parameterTypes.SetLength(func->funcdef->parameterTypes.GetLength()); + for (asUINT p = 0; p < func->funcdef->parameterTypes.GetLength(); p++) + func2->parameterTypes[p] = DetermineTypeForTemplate(func->funcdef->parameterTypes[p], templateType, ot); + + // TODO: template: Must be careful when instantiating templates for garbage collected types + // If the template hasn't been registered with the behaviours, it shouldn't + // permit instantiation of garbage collected types that in turn may refer to + // this instance. + + func2->inOutFlags = func->funcdef->inOutFlags; + func2->SetReadOnly(func->funcdef->IsReadOnly()); + asASSERT(func->funcdef->objectType == 0); + asASSERT(func->funcdef->sysFuncIntf == 0); + + func2->id = GetNextScriptFunctionId(); + AddScriptFunction(func2); + + asCFuncdefType *fdt2 = asNEW(asCFuncdefType)(this, func2); + funcDefs.PushLast(fdt2); // don't increase refCount as the constructor already set it to 1 + + // Return the new function + return fdt2; +} + void asCScriptEngine::CallObjectMethod(void *obj, int func) const { asCScriptFunction *s = scriptFunctions[func]; @@ -3992,6 +3983,11 @@ void asCScriptEngine::CallObjectMethod(void *obj, asSSystemFunctionInterface *i, asPWORD baseOffset; // Same size as the pointer } f; } p; + + obj = (void*) ((char*) obj + i->compositeOffset); + if(i->isCompositeIndirect) + obj = *((void**)obj); + p.f.func = (asFUNCTION_t)(i->func); p.f.baseOffset = asPWORD(i->baseOffset); void (asCSimpleDummy::*f)() = p.mthd; @@ -4013,6 +4009,11 @@ void asCScriptEngine::CallObjectMethod(void *obj, asSSystemFunctionInterface *i, } p; p.func = (asFUNCTION_t)(i->func); void (asCSimpleDummy::*f)() = p.mthd; + + obj = (void*) ((char*) obj + i->compositeOffset); + if(i->isCompositeIndirect) + obj = *((void**)obj); + obj = (void*)(asPWORD(obj) + i->baseOffset); (((asCSimpleDummy*)obj)->*f)(); } @@ -4058,6 +4059,11 @@ bool asCScriptEngine::CallObjectMethodRetBool(void *obj, int func) const asPWORD baseOffset; } f; } p; + + obj = (void*) ((char*) obj + i->compositeOffset); + if(i->isCompositeIndirect) + obj = *((void**)obj); + p.f.func = (asFUNCTION_t)(i->func); p.f.baseOffset = asPWORD(i->baseOffset); bool (asCSimpleDummy::*f)() = (bool (asCSimpleDummy::*)())(p.mthd); @@ -4079,6 +4085,11 @@ bool asCScriptEngine::CallObjectMethodRetBool(void *obj, int func) const } p; p.func = (asFUNCTION_t)(i->func); bool (asCSimpleDummy::*f)() = (bool (asCSimpleDummy::*)())p.mthd; + + obj = (void*) ((char*) obj + i->compositeOffset); + if(i->isCompositeIndirect) + obj = *((void**)obj); + obj = (void*)(asPWORD(obj) + i->baseOffset); return (((asCSimpleDummy*)obj)->*f)(); } @@ -4127,6 +4138,11 @@ int asCScriptEngine::CallObjectMethodRetInt(void *obj, int func) const } p; p.f.func = (asFUNCTION_t)(i->func); p.f.baseOffset = asPWORD(i->baseOffset); + + obj = (void*) ((char*) obj + i->compositeOffset); + if(i->isCompositeIndirect) + obj = *((void**)obj); + int (asCSimpleDummy::*f)() = (int (asCSimpleDummy::*)())(p.mthd); return (((asCSimpleDummy*)obj)->*f)(); } @@ -4146,6 +4162,11 @@ int asCScriptEngine::CallObjectMethodRetInt(void *obj, int func) const } p; p.func = (asFUNCTION_t)(i->func); int (asCSimpleDummy::*f)() = (int (asCSimpleDummy::*)())p.mthd; + + obj = (void*) ((char*) obj + i->compositeOffset); + if(i->isCompositeIndirect) + obj = *((void**)obj); + obj = (void*)(asPWORD(obj) + i->baseOffset); return (((asCSimpleDummy*)obj)->*f)(); } @@ -4194,6 +4215,11 @@ void *asCScriptEngine::CallObjectMethodRetPtr(void *obj, int func) const } p; p.f.func = (asFUNCTION_t)(i->func); p.f.baseOffset = asPWORD(i->baseOffset); + + obj = (void*) ((char*) obj + i->compositeOffset); + if(i->isCompositeIndirect) + obj = *((void**)obj); + void *(asCSimpleDummy::*f)() = (void *(asCSimpleDummy::*)())(p.mthd); return (((asCSimpleDummy*)obj)->*f)(); } @@ -4213,6 +4239,11 @@ void *asCScriptEngine::CallObjectMethodRetPtr(void *obj, int func) const } p; p.func = (asFUNCTION_t)(i->func); void *(asCSimpleDummy::*f)() = (void *(asCSimpleDummy::*)())p.mthd; + + obj = (void*) ((char*) obj + i->compositeOffset); + if(i->isCompositeIndirect) + obj = *((void**)obj); + obj = (void*)(asPWORD(obj) + i->baseOffset); return (((asCSimpleDummy*)obj)->*f)(); } @@ -4235,6 +4266,7 @@ void *asCScriptEngine::CallObjectMethodRetPtr(void *obj, int func) const void *asCScriptEngine::CallObjectMethodRetPtr(void *obj, int param1, asCScriptFunction *func) const { + asASSERT( obj != 0 ); asASSERT( func != 0 ); asSSystemFunctionInterface *i = func->sysFuncIntf; @@ -4254,6 +4286,11 @@ void *asCScriptEngine::CallObjectMethodRetPtr(void *obj, int param1, asCScriptFu } p; p.f.func = (asFUNCTION_t)(i->func); p.f.baseOffset = asPWORD(i->baseOffset); + + obj = (void*) ((char*) obj + i->compositeOffset); + if(i->isCompositeIndirect) + obj = *((void**)obj); + void *(asCSimpleDummy::*f)(int) = (void *(asCSimpleDummy::*)(int))(p.mthd); return (((asCSimpleDummy*)obj)->*f)(param1); #else @@ -4264,6 +4301,11 @@ void *asCScriptEngine::CallObjectMethodRetPtr(void *obj, int param1, asCScriptFu } p; p.func = (asFUNCTION_t)(i->func); void *(asCSimpleDummy::*f)(int) = (void *(asCSimpleDummy::*)(int))p.mthd; + + obj = (void*) ((char*) obj + i->compositeOffset); + if(i->isCompositeIndirect) + obj = *((void**)obj); + obj = (void*)(asPWORD(obj) + i->baseOffset); return (((asCSimpleDummy*)obj)->*f)(param1); #endif @@ -4383,6 +4425,11 @@ void asCScriptEngine::CallObjectMethod(void *obj, void *param, asSSystemFunction } p; p.f.func = (asFUNCTION_t)(i->func); p.f.baseOffset = asPWORD(i->baseOffset); + + obj = (void*) ((char*) obj + i->compositeOffset); + if(i->isCompositeIndirect) + obj = *((void**)obj); + void (asCSimpleDummy::*f)(void*) = (void (asCSimpleDummy::*)(void*))(p.mthd); (((asCSimpleDummy*)obj)->*f)(param); } @@ -4402,6 +4449,11 @@ void asCScriptEngine::CallObjectMethod(void *obj, void *param, asSSystemFunction } p; p.func = (asFUNCTION_t)(i->func); void (asCSimpleDummy::*f)(void *) = (void (asCSimpleDummy::*)(void *))(p.mthd); + + obj = (void*) ((char*) obj + i->compositeOffset); + if(i->isCompositeIndirect) + obj = *((void**)obj); + obj = (void*)(asPWORD(obj) + i->baseOffset); (((asCSimpleDummy*)obj)->*f)(param); } @@ -4516,13 +4568,13 @@ void asCScriptEngine::CallFree(void *obj) const } // interface -int asCScriptEngine::NotifyGarbageCollectorOfNewObject(void *obj, asIObjectType *type) +int asCScriptEngine::NotifyGarbageCollectorOfNewObject(void *obj, asITypeInfo *type) { return gc.AddScriptObjectToGC(obj, static_cast(type)); } // interface -int asCScriptEngine::GetObjectInGC(asUINT idx, asUINT *seqNbr, void **obj, asIObjectType **type) +int asCScriptEngine::GetObjectInGC(asUINT idx, asUINT *seqNbr, void **obj, asITypeInfo **type) { return gc.GetObjectInGC(idx, seqNbr, obj, type); } @@ -4559,7 +4611,7 @@ int asCScriptEngine::GetTypeIdFromDataType(const asCDataType &dtIn) const { if( dtIn.IsNullHandle() ) return asTYPEID_VOID; - if( dtIn.GetObjectType() == 0 ) + if( dtIn.GetTypeInfo() == 0 ) { // Primitives have pre-fixed typeIds switch( dtIn.GetTokenType() ) @@ -4584,68 +4636,32 @@ int asCScriptEngine::GetTypeIdFromDataType(const asCDataType &dtIn) const } int typeId = -1; - asCObjectType *ot = dtIn.GetObjectType(); - if( ot != &functionBehaviours ) + asCTypeInfo *ot = dtIn.GetTypeInfo(); + asASSERT(ot != &functionBehaviours); + // Object's hold the typeId themselves + typeId = ot->typeId; + + if( typeId == -1 ) { - // Object's hold the typeId themselves - typeId = ot->typeId; - - if( typeId == -1 ) - { - ACQUIREEXCLUSIVE(engineRWLock); - // Make sure another thread didn't determine the typeId while we were waiting for the lock - if( ot->typeId == -1 ) - { - typeId = typeIdSeqNbr++; - if( ot->flags & asOBJ_SCRIPT_OBJECT ) typeId |= asTYPEID_SCRIPTOBJECT; - else if( ot->flags & asOBJ_TEMPLATE ) typeId |= asTYPEID_TEMPLATE; - else if( ot->flags & asOBJ_ENUM ) {} // TODO: Should we have a specific bit for this? - else typeId |= asTYPEID_APPOBJECT; - - ot->typeId = typeId; - - mapTypeIdToObjectType.Insert(typeId, ot); - } - RELEASEEXCLUSIVE(engineRWLock); - } - } - else - { - // This a funcdef, so we'll need to look in the map for the funcdef - - // TODO: optimize: It shouldn't be necessary to exclusive lock when the typeId already exists ACQUIREEXCLUSIVE(engineRWLock); - - // Find the existing type id - asCScriptFunction *func = dtIn.GetFuncDef(); - asASSERT(func); - asSMapNode *cursor = 0; - mapTypeIdToFunction.MoveFirst(&cursor); - while( cursor ) + // Make sure another thread didn't determine the typeId while we were waiting for the lock + if( ot->typeId == -1 ) { - if( mapTypeIdToFunction.GetValue(cursor) == func ) - { - typeId = mapTypeIdToFunction.GetKey(cursor); - break; - } - - mapTypeIdToFunction.MoveNext(&cursor, cursor); - } - - // The type id doesn't exist, create it - if( typeId == -1 ) - { - // Setup the type id for the funcdef typeId = typeIdSeqNbr++; - typeId |= asTYPEID_APPOBJECT; - mapTypeIdToFunction.Insert(typeId, func); - } + if( ot->flags & asOBJ_SCRIPT_OBJECT ) typeId |= asTYPEID_SCRIPTOBJECT; + else if( ot->flags & asOBJ_TEMPLATE ) typeId |= asTYPEID_TEMPLATE; + else if( ot->flags & asOBJ_ENUM ) {} // TODO: Should we have a specific bit for this? + else typeId |= asTYPEID_APPOBJECT; + ot->typeId = typeId; + + mapTypeIdToTypeInfo.Insert(typeId, ot); + } RELEASEEXCLUSIVE(engineRWLock); } // Add flags according to the requested type - if( dtIn.GetObjectType() && !(dtIn.GetObjectType()->flags & asOBJ_ASHANDLE) ) + if( dtIn.GetTypeInfo() && !(dtIn.GetTypeInfo()->flags & asOBJ_ASHANDLE) ) { // The ASHANDLE types behave like handles, but are really // value types so the typeId is never returned as a handle @@ -4669,35 +4685,16 @@ asCDataType asCScriptEngine::GetDataTypeFromTypeId(int typeId) const } // First check if the typeId is an object type - asCObjectType *ot = 0; + asCTypeInfo *ot = 0; ACQUIRESHARED(engineRWLock); - asSMapNode *cursor = 0; - if( mapTypeIdToObjectType.MoveTo(&cursor, baseId) ) - ot = mapTypeIdToObjectType.GetValue(cursor); + asSMapNode *cursor = 0; + if( mapTypeIdToTypeInfo.MoveTo(&cursor, baseId) ) + ot = mapTypeIdToTypeInfo.GetValue(cursor); RELEASESHARED(engineRWLock); if( ot ) { - asCDataType dt = asCDataType::CreateObject(ot, false); - if( typeId & asTYPEID_OBJHANDLE ) - dt.MakeHandle(true, true); - if( typeId & asTYPEID_HANDLETOCONST ) - dt.MakeHandleToConst(true); - - return dt; - } - - // Then check if it is a funcdef - asCScriptFunction *func = 0; - ACQUIRESHARED(engineRWLock); - asSMapNode *cursor2 = 0; - if( mapTypeIdToFunction.MoveTo(&cursor2, baseId) ) - func = mapTypeIdToFunction.GetValue(cursor2); - RELEASESHARED(engineRWLock); - - if( func ) - { - asCDataType dt = asCDataType::CreateFuncDef(func); + asCDataType dt = asCDataType::CreateType(ot, false); if( typeId & asTYPEID_OBJHANDLE ) dt.MakeHandle(true, true); if( typeId & asTYPEID_HANDLETOCONST ) @@ -4712,28 +4709,28 @@ asCDataType asCScriptEngine::GetDataTypeFromTypeId(int typeId) const asCObjectType *asCScriptEngine::GetObjectTypeFromTypeId(int typeId) const { asCDataType dt = GetDataTypeFromTypeId(typeId); - return dt.GetObjectType(); + return CastToObjectType(dt.GetTypeInfo()); } -void asCScriptEngine::RemoveFromTypeIdMap(asCObjectType *type) +void asCScriptEngine::RemoveFromTypeIdMap(asCTypeInfo *type) { ACQUIREEXCLUSIVE(engineRWLock); - asSMapNode *cursor = 0; - mapTypeIdToObjectType.MoveFirst(&cursor); + asSMapNode *cursor = 0; + mapTypeIdToTypeInfo.MoveFirst(&cursor); while( cursor ) { - if( mapTypeIdToObjectType.GetValue(cursor) == type ) + if(mapTypeIdToTypeInfo.GetValue(cursor) == type ) { - mapTypeIdToObjectType.Erase(cursor); + mapTypeIdToTypeInfo.Erase(cursor); break; } - mapTypeIdToObjectType.MoveNext(&cursor, cursor); + mapTypeIdToTypeInfo.MoveNext(&cursor, cursor); } RELEASEEXCLUSIVE(engineRWLock); } // interface -asIObjectType *asCScriptEngine::GetObjectTypeByDecl(const char *decl) const +asITypeInfo *asCScriptEngine::GetTypeInfoByDecl(const char *decl) const { asCDataType dt; // This cast is ok, because we are not changing anything in the engine @@ -4743,10 +4740,10 @@ asIObjectType *asCScriptEngine::GetObjectTypeByDecl(const char *decl) const bld.silent = true; int r = bld.ParseDataType(decl, &dt, defaultNamespace); - if( r < 0 ) + if (r < 0) return 0; - return dt.GetObjectType(); + return dt.GetTypeInfo(); } // interface @@ -4787,7 +4784,7 @@ int asCScriptEngine::GetSizeOfPrimitiveType(int typeId) const } // interface -int asCScriptEngine::RefCastObject(void *obj, asIObjectType *fromType, asIObjectType *toType, void **newPtr, bool useOnlyImplicitCast) +int asCScriptEngine::RefCastObject(void *obj, asITypeInfo *fromType, asITypeInfo *toType, void **newPtr, bool useOnlyImplicitCast) { if( newPtr == 0 ) return asINVALID_ARG; *newPtr = 0; @@ -4798,10 +4795,6 @@ int asCScriptEngine::RefCastObject(void *obj, asIObjectType *fromType, asIObject if( obj == 0 ) return asSUCCESS; - // This method doesn't support casting function pointers, since they cannot be described with just an object type - if( fromType->GetFlags() & asOBJ_SCRIPT_FUNCTION ) - return asNOT_SUPPORTED; - if( fromType == toType ) { *newPtr = obj; @@ -4809,6 +4802,22 @@ int asCScriptEngine::RefCastObject(void *obj, asIObjectType *fromType, asIObject return asSUCCESS; } + // Check for funcdefs + if ((fromType->GetFlags() & asOBJ_FUNCDEF) && (toType->GetFlags() & asOBJ_FUNCDEF)) + { + asCFuncdefType *fromFunc = CastToFuncdefType(reinterpret_cast(fromType)); + asCFuncdefType *toFunc = CastToFuncdefType(reinterpret_cast(toType)); + + if (fromFunc && toFunc && fromFunc->funcdef->IsSignatureExceptNameEqual(toFunc->funcdef)) + { + *newPtr = obj; + AddRefScriptObject(*newPtr, toType); + return asSUCCESS; + } + + return asSUCCESS; + } + // Look for ref cast behaviours asCScriptFunction *universalCastFunc = 0; asCObjectType *from = reinterpret_cast(fromType); @@ -4818,7 +4827,7 @@ int asCScriptEngine::RefCastObject(void *obj, asIObjectType *fromType, asIObject if( func->name == "opImplCast" || (!useOnlyImplicitCast && func->name == "opCast") ) { - if( func->returnType.GetObjectType() == toType ) + if( func->returnType.GetTypeInfo() == toType ) { *newPtr = CallObjectMethodRetPtr(obj, func->id); // The ref cast behaviour returns a handle with incremented @@ -4830,8 +4839,8 @@ int asCScriptEngine::RefCastObject(void *obj, asIObjectType *fromType, asIObject } else { - asASSERT( func->returnType.GetTokenType() == ttVoid && - func->parameterTypes.GetLength() == 1 && + asASSERT( func->returnType.GetTokenType() == ttVoid && + func->parameterTypes.GetLength() == 1 && func->parameterTypes[0].GetTokenType() == ttQuestion ); universalCastFunc = func; } @@ -4875,18 +4884,10 @@ int asCScriptEngine::RefCastObject(void *obj, asIObjectType *fromType, asIObject // Down casts to derived class or from interface can only be done explicitly if( !useOnlyImplicitCast ) { - if( toType->Implements(fromType) || - toType->DerivesFrom(fromType) ) - { - *newPtr = obj; - reinterpret_cast(*newPtr)->AddRef(); - return asSUCCESS; - } - // Get the true type of the object so the explicit cast can evaluate all possibilities - asIObjectType *from = reinterpret_cast(obj)->GetObjectType(); - if( from->DerivesFrom(toType) || - from->Implements(toType) ) + asITypeInfo *trueType = reinterpret_cast(obj)->GetObjectType(); + if (trueType->DerivesFrom(toType) || + trueType->Implements(toType)) { *newPtr = obj; reinterpret_cast(*newPtr)->AddRef(); @@ -4900,7 +4901,7 @@ int asCScriptEngine::RefCastObject(void *obj, asIObjectType *fromType, asIObject } // interface -void *asCScriptEngine::CreateScriptObject(const asIObjectType *type) +void *asCScriptEngine::CreateScriptObject(const asITypeInfo *type) { if( type == 0 ) return 0; @@ -4922,7 +4923,7 @@ void *asCScriptEngine::CreateScriptObject(const asIObjectType *type) // Call the script class' default factory with a context ptr = ScriptObjectFactory(objType, this); } - else if( objType->flags & asOBJ_TEMPLATE ) + else if( (objType->flags & asOBJ_TEMPLATE) && (objType->flags & asOBJ_REF) ) { // The registered factory that takes the object type is moved // to the construct behaviour when the type is instantiated @@ -4933,10 +4934,10 @@ void *asCScriptEngine::CreateScriptObject(const asIObjectType *type) { ptr = CallGlobalFunctionRetPtr(objType->beh.construct, objType); } - catch(...) + catch (...) { asIScriptContext *ctx = asGetActiveContext(); - if( ctx ) + if (ctx) ctx->SetException(TXT_EXCEPTION_CAUGHT); } #endif @@ -4973,34 +4974,127 @@ void *asCScriptEngine::CreateScriptObject(const asIObjectType *type) // Manually allocate the memory, then call the default constructor ptr = CallAlloc(objType); int funcIndex = objType->beh.construct; - if( funcIndex ) + if (funcIndex) { + if (objType->flags & asOBJ_TEMPLATE) + { + // Templates of value types create script functions as the constructors + CallScriptObjectMethod(ptr, funcIndex); + } + else + { #ifdef AS_NO_EXCEPTIONS - CallObjectMethod(ptr, funcIndex); -#else - try - { CallObjectMethod(ptr, funcIndex); - } - catch(...) - { - asIScriptContext *ctx = asGetActiveContext(); - if( ctx ) - ctx->SetException(TXT_EXCEPTION_CAUGHT); +#else + try + { + CallObjectMethod(ptr, funcIndex); + } + catch (...) + { + asIScriptContext *ctx = asGetActiveContext(); + if (ctx) + ctx->SetException(TXT_EXCEPTION_CAUGHT); - // Free the memory - CallFree(ptr); - ptr = 0; - } + // Free the memory + CallFree(ptr); + ptr = 0; + } #endif + } } } return ptr; } +// internal +int asCScriptEngine::CallScriptObjectMethod(void *obj, int funcId) +{ + asIScriptContext *ctx = 0; + int r = 0; + bool isNested = false; + + // Use nested call in the context if there is an active context + ctx = asGetActiveContext(); + if (ctx) + { + // It may not always be possible to reuse the current context, + // in which case we'll have to create a new one any way. + if (ctx->GetEngine() == this && ctx->PushState() == asSUCCESS) + isNested = true; + else + ctx = 0; + } + + if (ctx == 0) + { + // Request a context from the engine + ctx = RequestContext(); + if (ctx == 0) + { + // TODO: How to best report this failure? + return asERROR; + } + } + + r = ctx->Prepare(scriptFunctions[funcId]); + if (r < 0) + { + if (isNested) + ctx->PopState(); + else + ReturnContext(ctx); + // TODO: How to best report this failure? + return asERROR; + } + + // Set the object + ctx->SetObject(obj); + + for (;;) + { + r = ctx->Execute(); + + // We can't allow this execution to be suspended + // so resume the execution immediately + if (r != asEXECUTION_SUSPENDED) + break; + } + + if (r != asEXECUTION_FINISHED) + { + if (isNested) + { + ctx->PopState(); + + // If the execution was aborted or an exception occurred, + // then we should forward that to the outer execution. + if (r == asEXECUTION_EXCEPTION) + { + // TODO: How to improve this exception + ctx->SetException(TXT_EXCEPTION_IN_NESTED_CALL); + } + else if (r == asEXECUTION_ABORTED) + ctx->Abort(); + } + else + ReturnContext(ctx); + + // TODO: How to best report the error? + return asERROR; + } + + if (isNested) + ctx->PopState(); + else + ReturnContext(ctx); + + return asSUCCESS; +} + // interface -void *asCScriptEngine::CreateUninitializedScriptObject(const asIObjectType *type) +void *asCScriptEngine::CreateUninitializedScriptObject(const asITypeInfo *type) { // This function only works for script classes. Registered types cannot be created this way. if( type == 0 || !(type->GetFlags() & asOBJ_SCRIPT_OBJECT) ) @@ -5019,7 +5113,7 @@ void *asCScriptEngine::CreateUninitializedScriptObject(const asIObjectType *type } // interface -void *asCScriptEngine::CreateScriptObjectCopy(void *origObj, const asIObjectType *type) +void *asCScriptEngine::CreateScriptObjectCopy(void *origObj, const asITypeInfo *type) { if( origObj == 0 || type == 0 ) return 0; @@ -5087,7 +5181,7 @@ void asCScriptEngine::ConstructScriptObjectCopy(void *mem, void *obj, asCObjectT } // interface -int asCScriptEngine::AssignScriptObject(void *dstObj, void *srcObj, const asIObjectType *type) +int asCScriptEngine::AssignScriptObject(void *dstObj, void *srcObj, const asITypeInfo *type) { // TODO: Warn about invalid call in message stream // TODO: Should a script exception be set in case a context is active? @@ -5121,88 +5215,66 @@ int asCScriptEngine::AssignScriptObject(void *dstObj, void *srcObj, const asIObj } // interface -void asCScriptEngine::AddRefScriptObject(void *obj, const asIObjectType *type) +void asCScriptEngine::AddRefScriptObject(void *obj, const asITypeInfo *type) { // Make sure it is not a null pointer if( obj == 0 || type == 0 ) return; - const asCObjectType *objType = static_cast(type); - if( objType->beh.addref ) + const asCTypeInfo *ti = static_cast(type); + if (ti->flags & asOBJ_FUNCDEF) { - // Call the addref behaviour - CallObjectMethod(obj, objType->beh.addref); - } -} - -// interface -void asCScriptEngine::ReleaseScriptObject(void *obj, const asIObjectType *type) -{ - // Make sure it is not a null pointer - if( obj == 0 || type == 0 ) return; - - const asCObjectType *objType = static_cast(type); - if( objType->flags & asOBJ_REF ) - { - asASSERT( (objType->flags & asOBJ_NOCOUNT) || objType->beh.release ); - if( objType->beh.release ) - { - // Call the release behaviour - CallObjectMethod(obj, objType->beh.release); - } + CallObjectMethod(obj, functionBehaviours.beh.addref); } else { - // Call the destructor - if( objType->beh.destruct ) - CallObjectMethod(obj, objType->beh.destruct); - else if( objType->flags & asOBJ_LIST_PATTERN ) - DestroyList((asBYTE*)obj, objType); - - // We'll have to trust that the memory for the object was allocated with CallAlloc. - // This is true if the object was created in the context, or with CreateScriptObject. - - // Then free the memory - CallFree(obj); + asCObjectType *objType = CastToObjectType(const_cast(ti)); + if (objType && objType->beh.addref) + { + // Call the addref behaviour + CallObjectMethod(obj, objType->beh.addref); + } } } -#ifdef AS_DEPRECATED -// Deprecated since 2.30.0, 2014-11-04 // interface -bool asCScriptEngine::IsHandleCompatibleWithObject(void *obj, int objTypeId, int handleTypeId) const +void asCScriptEngine::ReleaseScriptObject(void *obj, const asITypeInfo *type) { - // if equal, then it is obvious they are compatible - if( objTypeId == handleTypeId ) - return true; + // Make sure it is not a null pointer + if( obj == 0 || type == 0 ) return; - // Get the actual data types from the type ids - asCDataType objDt = GetDataTypeFromTypeId(objTypeId); - asCDataType hdlDt = GetDataTypeFromTypeId(handleTypeId); - - // A handle to const cannot be passed to a handle that is not referencing a const object - if( objDt.IsHandleToConst() && !hdlDt.IsHandleToConst() ) - return false; - - if( objDt.GetObjectType() == hdlDt.GetObjectType() ) + const asCTypeInfo *ti = static_cast(type); + if (ti->flags & asOBJ_FUNCDEF) { - // The object type is equal - return true; + CallObjectMethod(obj, functionBehaviours.beh.release); } - else if( objDt.IsScriptObject() && obj ) + else { - // Get the true type from the object instance - asCObjectType *objType = ((asCScriptObject*)obj)->objType; + asCObjectType *objType = CastToObjectType(const_cast(ti)); + if (objType && objType->flags & asOBJ_REF) + { + asASSERT((objType->flags & asOBJ_NOCOUNT) || objType->beh.release); + if (objType->beh.release) + { + // Call the release behaviour + CallObjectMethod(obj, objType->beh.release); + } + } + else if( objType ) + { + // Call the destructor + if (objType->beh.destruct) + CallObjectMethod(obj, objType->beh.destruct); + else if (objType->flags & asOBJ_LIST_PATTERN) + DestroyList((asBYTE*)obj, objType); - // Check if the object implements the interface, or derives from the base class - // This will also return true, if the requested handle type is an exact match for the object type - if( objType->Implements(hdlDt.GetObjectType()) || - objType->DerivesFrom(hdlDt.GetObjectType()) ) - return true; + // We'll have to trust that the memory for the object was allocated with CallAlloc. + // This is true if the object was created in the context, or with CreateScriptObject. + + // Then free the memory + CallFree(obj); + } } - - return false; } -#endif // interface int asCScriptEngine::BeginConfigGroup(const char *groupName) @@ -5259,7 +5331,7 @@ int asCScriptEngine::RemoveConfigGroup(const char *groupName) { asCConfigGroup *group = configGroups[n]; - // Remove any unused generated template instances + // Remove any unused generated template instances // before verifying if the config group is still in use. // RemoveTemplateInstanceType() checks if the instance is in use for( asUINT g = generatedTemplateTypes.GetLength(); g-- > 0; ) @@ -5320,13 +5392,13 @@ asCConfigGroup *asCScriptEngine::FindConfigGroupForGlobalVar(int gvarId) const return 0; } -asCConfigGroup *asCScriptEngine::FindConfigGroupForObjectType(const asCObjectType *objType) const +asCConfigGroup *asCScriptEngine::FindConfigGroupForTypeInfo(const asCTypeInfo *objType) const { for( asUINT n = 0; n < configGroups.GetLength(); n++ ) { - for( asUINT m = 0; m < configGroups[n]->objTypes.GetLength(); m++ ) + for( asUINT m = 0; m < configGroups[n]->types.GetLength(); m++ ) { - if( configGroups[n]->objTypes[m] == objType ) + if( configGroups[n]->types[m] == objType ) return configGroups[n]; } } @@ -5334,12 +5406,12 @@ asCConfigGroup *asCScriptEngine::FindConfigGroupForObjectType(const asCObjectTyp return 0; } -asCConfigGroup *asCScriptEngine::FindConfigGroupForFuncDef(const asCScriptFunction *funcDef) const +asCConfigGroup *asCScriptEngine::FindConfigGroupForFuncDef(const asCFuncdefType *funcDef) const { for( asUINT n = 0; n < configGroups.GetLength(); n++ ) { - asCScriptFunction *f = const_cast(funcDef); - if( configGroups[n]->funcDefs.Exists(f) ) + asCFuncdefType *f = const_cast(funcDef); + if( configGroups[n]->types.Exists(f) ) return configGroups[n]; } @@ -5447,7 +5519,7 @@ void asCScriptEngine::RemoveScriptFunction(asCScriptFunction *func) } // internal -void asCScriptEngine::RemoveFuncdef(asCScriptFunction *funcdef) +void asCScriptEngine::RemoveFuncdef(asCFuncdefType *funcdef) { funcDefs.RemoveValue(funcdef); } @@ -5463,7 +5535,8 @@ int asCScriptEngine::RegisterFuncdef(const char *decl) return ConfigError(asOUT_OF_MEMORY, "RegisterFuncdef", decl, 0); asCBuilder bld(this, 0); - int r = bld.ParseFunctionDeclaration(0, decl, func, false, 0, 0, defaultNamespace); + asCObjectType *parentClass = 0; + int r = bld.ParseFunctionDeclaration(0, decl, func, false, 0, 0, defaultNamespace, 0, &parentClass); if( r < 0 ) { // Set as dummy function before deleting @@ -5483,16 +5556,31 @@ int asCScriptEngine::RegisterFuncdef(const char *decl) func->id = GetNextScriptFunctionId(); AddScriptFunction(func); - funcDefs.PushLast(func); - func->AddRefInternal(); - registeredFuncDefs.PushLast(func); - currentGroup->funcDefs.PushLast(func); + asCFuncdefType *fdt = asNEW(asCFuncdefType)(this, func); + funcDefs.PushLast(fdt); // doesn't increase refcount + registeredFuncDefs.PushLast(fdt); // doesn't increase refcount + allRegisteredTypes.Insert(asSNameSpaceNamePair(fdt->nameSpace, fdt->name), fdt); // constructor already set the ref count to 1 + + currentGroup->types.PushLast(fdt); + if (parentClass) + { + parentClass->childFuncDefs.PushLast(fdt); + fdt->parentClass = parentClass; + + // Check if the method restricts that use of the template to value types or reference types + if (parentClass->flags & asOBJ_TEMPLATE) + { + r = SetTemplateRestrictions(parentClass, func, "RegisterFuncdef", decl); + if (r < 0) + return r; + } + } // If parameter type from other groups are used, add references currentGroup->AddReferencesForFunc(this, func); - // Return the function id as success - return func->id; + // Return the type id as success + return GetTypeIdFromDataType(asCDataType::CreateType(fdt, false)); } // interface @@ -5502,7 +5590,7 @@ asUINT asCScriptEngine::GetFuncdefCount() const } // interface -asIScriptFunction *asCScriptEngine::GetFuncdefByIndex(asUINT index) const +asITypeInfo *asCScriptEngine::GetFuncdefByIndex(asUINT index) const { if( index >= registeredFuncDefs.GetLength() ) return 0; @@ -5510,6 +5598,75 @@ asIScriptFunction *asCScriptEngine::GetFuncdefByIndex(asUINT index) const return registeredFuncDefs[index]; } +// internal +asCFuncdefType *asCScriptEngine::FindMatchingFuncdef(asCScriptFunction *func, asCModule *module) +{ + asCFuncdefType *funcDef = func->funcdefType; + + if (funcDef == 0) + { + // Check if there is any matching funcdefs already in the engine that can be reused + for (asUINT n = 0; n < funcDefs.GetLength(); n++) + { + if (funcDefs[n]->funcdef->IsSignatureExceptNameEqual(func)) + { + if (func->IsShared() && !funcDefs[n]->funcdef->IsShared()) + continue; + funcDef = funcDefs[n]; + break; + } + } + } + + if (funcDef == 0) + { + // Create a matching funcdef + asCScriptFunction *fd = asNEW(asCScriptFunction)(this, 0, asFUNC_FUNCDEF); + fd->name = func->name; + fd->nameSpace = func->nameSpace; + fd->SetShared(func->IsShared()); + + fd->returnType = func->returnType; + fd->parameterTypes = func->parameterTypes; + fd->inOutFlags = func->inOutFlags; + + funcDef = asNEW(asCFuncdefType)(this, fd); + funcDefs.PushLast(funcDef); // doesn't increase the refCount + + fd->id = GetNextScriptFunctionId(); + AddScriptFunction(fd); + + if (module) + { + // Add the new funcdef to the module so it will + // be available when saving the bytecode + funcDef->module = module; + module->funcDefs.PushLast(funcDef); // the refCount was already accounted for in the constructor + } + + // Observe, if the funcdef is created without informing a module a reference will be stored in the + // engine's funcDefs array, but it will not be owned by any module. This means that it will live on + // until the engine is released. + } + + if (funcDef && module && funcDef->module && funcDef->module != module) + { + // Unless this is a registered funcDef the returned funcDef must + // be stored as part of the module for saving/loading bytecode + if (!module->funcDefs.Exists(funcDef)) + { + module->funcDefs.PushLast(funcDef); + funcDef->AddRefInternal(); + } + else + { + asASSERT(funcDef->IsShared()); + } + } + + return funcDef; +} + // interface // TODO: typedef: Accept complex types for the typedefs int asCScriptEngine::RegisterTypedef(const char *type, const char *decl) @@ -5518,7 +5675,7 @@ int asCScriptEngine::RegisterTypedef(const char *type, const char *decl) // Verify if the name has been registered as a type already // TODO: Must check against registered funcdefs too - if( GetRegisteredObjectType(type, defaultNamespace) ) + if( GetRegisteredType(type, defaultNamespace) ) // Let the application recover from this error, for example if the same typedef is registered twice return asALREADY_REGISTERED; @@ -5568,22 +5725,22 @@ int asCScriptEngine::RegisterTypedef(const char *type, const char *decl) // types as they are allowed to use the names // Put the data type in the list - asCObjectType *object = asNEW(asCObjectType)(this); - if( object == 0 ) + asCTypedefType *td = asNEW(asCTypedefType)(this); + if( td == 0 ) return ConfigError(asOUT_OF_MEMORY, "RegisterTypedef", type, decl); - object->flags = asOBJ_TYPEDEF; - object->size = dataType.GetSizeInMemoryBytes(); - object->name = type; - object->nameSpace = defaultNamespace; - object->templateSubTypes.PushLast(dataType); + td->flags = asOBJ_TYPEDEF; + td->size = dataType.GetSizeInMemoryBytes(); + td->name = type; + td->nameSpace = defaultNamespace; + td->aliasForType = dataType; - allRegisteredTypes.Insert(asSNameSpaceNamePair(object->nameSpace, object->name), object); - registeredTypeDefs.PushLast(object); + allRegisteredTypes.Insert(asSNameSpaceNamePair(td->nameSpace, td->name), td); + registeredTypeDefs.PushLast(td); - currentGroup->objTypes.PushLast(object); + currentGroup->types.PushLast(td); - return asSUCCESS; + return GetTypeIdByDecl(type); } // interface @@ -5593,30 +5750,12 @@ asUINT asCScriptEngine::GetTypedefCount() const } // interface -const char *asCScriptEngine::GetTypedefByIndex(asUINT index, int *typeId, const char **nameSpace, const char **configGroup, asDWORD *accessMask) const +asITypeInfo *asCScriptEngine::GetTypedefByIndex(asUINT index) const { if( index >= registeredTypeDefs.GetLength() ) return 0; - if( typeId ) - *typeId = GetTypeIdFromDataType(registeredTypeDefs[index]->templateSubTypes[0]); - - if( configGroup ) - { - asCConfigGroup *group = FindConfigGroupForObjectType(registeredTypeDefs[index]); - if( group ) - *configGroup = group->groupName.AddressOf(); - else - *configGroup = 0; - } - - if( accessMask ) - *accessMask = registeredTypeDefs[index]->accessMask; - - if( nameSpace ) - *nameSpace = registeredTypeDefs[index]->nameSpace->name.AddressOf(); - - return registeredTypeDefs[index]->name.AddressOf(); + return registeredTypeDefs[index]; } // interface @@ -5627,7 +5766,7 @@ int asCScriptEngine::RegisterEnum(const char *name) return ConfigError(asINVALID_NAME, "RegisterEnum", name, 0); // Verify if the name has been registered as a type already - if( GetRegisteredObjectType(name, defaultNamespace) ) + if( GetRegisteredType(name, defaultNamespace) ) return asALREADY_REGISTERED; // Use builder to parse the datatype @@ -5640,7 +5779,7 @@ int asCScriptEngine::RegisterEnum(const char *name) { // If it is not in the defaultNamespace then the type was successfully parsed because // it is declared in a parent namespace which shouldn't be treated as an error - if( dt.GetObjectType() && dt.GetObjectType()->nameSpace == defaultNamespace ) + if( dt.GetTypeInfo() && dt.GetTypeInfo()->nameSpace == defaultNamespace ) return ConfigError(asERROR, "RegisterEnum", name, 0); } @@ -5654,7 +5793,7 @@ int asCScriptEngine::RegisterEnum(const char *name) if( r < 0 ) return ConfigError(asNAME_TAKEN, "RegisterEnum", name, 0); - asCObjectType *st = asNEW(asCObjectType)(this); + asCEnumType *st = asNEW(asCEnumType)(this); if( st == 0 ) return ConfigError(asOUT_OF_MEMORY, "RegisterEnum", name, 0); @@ -5669,9 +5808,9 @@ int asCScriptEngine::RegisterEnum(const char *name) allRegisteredTypes.Insert(asSNameSpaceNamePair(st->nameSpace, st->name), st); registeredEnums.PushLast(st); - currentGroup->objTypes.PushLast(st); + currentGroup->types.PushLast(st); - return asSUCCESS; + return GetTypeIdByDecl(name); } // interface @@ -5689,8 +5828,8 @@ int asCScriptEngine::RegisterEnumValue(const char *typeName, const char *valueNa return ConfigError(r, "RegisterEnumValue", typeName, valueName); // Store the enum value - asCObjectType *ot = dt.GetObjectType(); - if( ot == 0 || !(ot->flags & asOBJ_ENUM) ) + asCEnumType *ot = CastToEnumType(dt.GetTypeInfo()); + if( ot == 0 ) return ConfigError(asINVALID_TYPE, "RegisterEnumValue", typeName, valueName); if( NULL == valueName ) @@ -5722,63 +5861,16 @@ int asCScriptEngine::RegisterEnumValue(const char *typeName, const char *valueNa // interface asUINT asCScriptEngine::GetEnumCount() const { - return asUINT(registeredEnums.GetLength()); + return registeredEnums.GetLength(); } // interface -const char *asCScriptEngine::GetEnumByIndex(asUINT index, int *enumTypeId, const char **nameSpace, const char **configGroup, asDWORD *accessMask) const +asITypeInfo *asCScriptEngine::GetEnumByIndex(asUINT index) const { if( index >= registeredEnums.GetLength() ) return 0; - if( configGroup ) - { - asCConfigGroup *group = FindConfigGroupForObjectType(registeredEnums[index]); - if( group ) - *configGroup = group->groupName.AddressOf(); - else - *configGroup = 0; - } - - if( accessMask ) - *accessMask = registeredEnums[index]->accessMask; - - if( enumTypeId ) - *enumTypeId = GetTypeIdFromDataType(asCDataType::CreateObject(registeredEnums[index], false)); - - if( nameSpace ) - *nameSpace = registeredEnums[index]->nameSpace->name.AddressOf(); - - return registeredEnums[index]->name.AddressOf(); -} - -// interface -int asCScriptEngine::GetEnumValueCount(int enumTypeId) const -{ - asCDataType dt = GetDataTypeFromTypeId(enumTypeId); - asCObjectType *t = dt.GetObjectType(); - if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) ) - return asINVALID_TYPE; - - return (int)t->enumValues.GetLength(); -} - -// interface -const char *asCScriptEngine::GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const -{ - // TODO: This same function is implemented in as_module.cpp as well. Perhaps it should be moved to asCObjectType? - asCDataType dt = GetDataTypeFromTypeId(enumTypeId); - asCObjectType *t = dt.GetObjectType(); - if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) ) - return 0; - - if( index >= t->enumValues.GetLength() ) - return 0; - - if( outValue ) - *outValue = t->enumValues[index]->value; - - return t->enumValues[index]->name.AddressOf(); + return registeredEnums[index]; } // interface @@ -5788,7 +5880,7 @@ asUINT asCScriptEngine::GetObjectTypeCount() const } // interface -asIObjectType *asCScriptEngine::GetObjectTypeByIndex(asUINT index) const +asITypeInfo *asCScriptEngine::GetObjectTypeByIndex(asUINT index) const { if( index >= registeredObjTypes.GetLength() ) return 0; @@ -5797,28 +5889,44 @@ asIObjectType *asCScriptEngine::GetObjectTypeByIndex(asUINT index) const } // interface -asIObjectType *asCScriptEngine::GetObjectTypeByName(const char *name) const +asITypeInfo *asCScriptEngine::GetTypeInfoByName(const char *name) const { asSNameSpace *ns = defaultNamespace; - while( ns ) + while (ns) { // Check the object types - for( asUINT n = 0; n < registeredObjTypes.GetLength(); n++ ) + for (asUINT n = 0; n < registeredObjTypes.GetLength(); n++) { - if( registeredObjTypes[n]->name == name && - registeredObjTypes[n]->nameSpace == ns ) + if (registeredObjTypes[n]->name == name && + registeredObjTypes[n]->nameSpace == ns) return registeredObjTypes[n]; } // Perhaps it is a template type? In this case // the returned type will be the generic type - for( asUINT n = 0; n < registeredTemplateTypes.GetLength(); n++ ) + for (asUINT n = 0; n < registeredTemplateTypes.GetLength(); n++) { - if( registeredTemplateTypes[n]->name == name && - registeredTemplateTypes[n]->nameSpace == ns ) + if (registeredTemplateTypes[n]->name == name && + registeredTemplateTypes[n]->nameSpace == ns) return registeredTemplateTypes[n]; } + // Check the enum types + for (asUINT n = 0; n < registeredEnums.GetLength(); n++) + { + if (registeredEnums[n]->name == name && + registeredEnums[n]->nameSpace == ns) + return registeredEnums[n]; + } + + // Check the typedefs + for (asUINT n = 0; n < registeredTypeDefs.GetLength();n++) + { + if (registeredTypeDefs[n]->name == name && + registeredTypeDefs[n]->nameSpace == ns) + return registeredTypeDefs[n]; + } + // Recursively search parent namespace ns = GetParentNameSpace(ns); } @@ -5827,18 +5935,14 @@ asIObjectType *asCScriptEngine::GetObjectTypeByName(const char *name) const } // interface -asIObjectType *asCScriptEngine::GetObjectTypeById(int typeId) const +asITypeInfo *asCScriptEngine::GetTypeInfoById(int typeId) const { asCDataType dt = GetDataTypeFromTypeId(typeId); // Is the type id valid? - if( !dt.IsValid() ) return 0; + if (!dt.IsValid()) return 0; - // Enum types are not objects, so we shouldn't return an object type for them - if( dt.GetObjectType() && dt.GetObjectType()->GetFlags() & asOBJ_ENUM ) - return 0; - - return dt.GetObjectType(); + return dt.GetTypeInfo(); } // interface @@ -5847,12 +5951,6 @@ asIScriptFunction *asCScriptEngine::GetFunctionById(int funcId) const return GetScriptFunction(funcId); } -// interface -asIScriptFunction *asCScriptEngine::GetFuncDefFromTypeId(int typeId) const -{ - return GetDataTypeFromTypeId(typeId).GetFuncDef(); -} - // internal bool asCScriptEngine::IsTemplateType(const char *name) const { @@ -5867,43 +5965,6 @@ bool asCScriptEngine::IsTemplateType(const char *name) const return false; } -// internal -int asCScriptEngine::AddConstantString(const char *str, size_t len) -{ - // This is only called when build a script module, so it is - // known that only one thread can enter the function at a time. - asASSERT( isBuilding ); - - // The str may contain null chars, so we cannot use strlen, or strcmp, or strcpy - - // Has the string been registered before? - asSMapNode *cursor = 0; - if (stringToIdMap.MoveTo(&cursor, asCStringPointer(str, len))) - return cursor->value; - - // No match was found, add the string - asCString *cstr = asNEW(asCString)(str, len); - if( cstr ) - { - stringConstants.PushLast(cstr); - int index = (int)stringConstants.GetLength() - 1; - stringToIdMap.Insert(asCStringPointer(cstr), index); - - // The VM currently doesn't handle string ids larger than 65535 - asASSERT(stringConstants.GetLength() <= 65536); - - return index; - } - - return 0; -} - -// internal -const asCString &asCScriptEngine::GetConstantString(int id) -{ - return *stringConstants[id]; -} - // internal int asCScriptEngine::GetScriptSectionNameIndex(const char *name) { @@ -6022,23 +6083,23 @@ void asCScriptEngine::SetFunctionUserDataCleanupCallback(asCLEANFUNCTIONFUNC_t c } // interface -void asCScriptEngine::SetObjectTypeUserDataCleanupCallback(asCLEANOBJECTTYPEFUNC_t callback, asPWORD type) +void asCScriptEngine::SetTypeInfoUserDataCleanupCallback(asCLEANTYPEINFOFUNC_t callback, asPWORD type) { ACQUIREEXCLUSIVE(engineRWLock); - for( asUINT n = 0; n < cleanObjectTypeFuncs.GetLength(); n++ ) + for( asUINT n = 0; n < cleanTypeInfoFuncs.GetLength(); n++ ) { - if( cleanObjectTypeFuncs[n].type == type ) + if( cleanTypeInfoFuncs[n].type == type ) { - cleanObjectTypeFuncs[n].cleanFunc = callback; + cleanTypeInfoFuncs[n].cleanFunc = callback; RELEASEEXCLUSIVE(engineRWLock); return; } } - SObjTypeClean otc = {type, callback}; - cleanObjectTypeFuncs.PushLast(otc); + STypeInfoClean otc = {type, callback}; + cleanTypeInfoFuncs.PushLast(otc); RELEASEEXCLUSIVE(engineRWLock); } @@ -6072,19 +6133,19 @@ asCObjectType *asCScriptEngine::GetListPatternType(int listPatternFuncId) // or from the factory's return type for reference types asCObjectType *ot = scriptFunctions[listPatternFuncId]->objectType; if( ot == 0 ) - ot = scriptFunctions[listPatternFuncId]->returnType.GetObjectType(); + ot = CastToObjectType(scriptFunctions[listPatternFuncId]->returnType.GetTypeInfo()); asASSERT( ot ); // Check if this object type already has a list pattern type for( asUINT n = 0; n < listPatternTypes.GetLength(); n++ ) { - if( listPatternTypes[n]->templateSubTypes[0].GetObjectType() == ot ) + if( listPatternTypes[n]->templateSubTypes[0].GetTypeInfo() == ot ) return listPatternTypes[n]; } // Create a new list pattern type for the given object type asCObjectType *lpt = asNEW(asCObjectType)(this); - lpt->templateSubTypes.PushLast(asCDataType::CreateObject(ot, false)); + lpt->templateSubTypes.PushLast(asCDataType::CreateType(ot, false)); lpt->flags = asOBJ_LIST_PATTERN; listPatternTypes.PushLast(lpt); @@ -6099,7 +6160,7 @@ void asCScriptEngine::DestroyList(asBYTE *buffer, const asCObjectType *listPatte // Get the list pattern from the listFactory function // TODO: runtime optimize: Store the used list factory in the listPatternType itself // TODO: runtime optimize: Keep a flag to indicate if there is really a need to free anything - asCObjectType *ot = listPatternType->templateSubTypes[0].GetObjectType(); + asCObjectType *ot = CastToObjectType(listPatternType->templateSubTypes[0].GetTypeInfo()); asCScriptFunction *listFactory = scriptFunctions[ot->beh.listFactory]; asASSERT( listFactory ); @@ -6171,19 +6232,20 @@ void asCScriptEngine::DestroySubList(asBYTE *&buffer, asSListPatternNode *&node) dt = GetDataTypeFromTypeId(typeId); } - asCObjectType *ot = dt.GetObjectType(); - if( ot && (ot->flags & asOBJ_ENUM) == 0 ) + asCTypeInfo *ti = dt.GetTypeInfo(); + if( ti && (ti->flags & asOBJ_ENUM) == 0 ) { // Free all instances of this type - if( ot->flags & asOBJ_VALUE ) + if( ti->flags & asOBJ_VALUE ) { - asUINT size = ot->GetSize(); + asUINT size = ti->GetSize(); // Align the offset to 4 bytes boundary if( size >= 4 && (asPWORD(buffer) & 0x3) ) buffer += 4 - (asPWORD(buffer) & 0x3); - if( ot->beh.destruct ) + asCObjectType *ot = CastToObjectType(ti); + if( ot && ot->beh.destruct ) { // Only call the destructor if the object has been created // We'll assume the object has been created if any byte in @@ -6217,7 +6279,7 @@ void asCScriptEngine::DestroySubList(asBYTE *&buffer, asSListPatternNode *&node) // Call the release behaviour void *ptr = *(void**)buffer; if( ptr ) - ReleaseScriptObject(ptr, ot); + ReleaseScriptObject(ptr, ti); buffer += AS_PTR_SIZE*4; } } diff --git a/lib/angelscript/source/as_scriptengine.h b/lib/angelscript/source/as_scriptengine.h index c9a2a487f..ad82858d4 100644 --- a/lib/angelscript/source/as_scriptengine.h +++ b/lib/angelscript/source/as_scriptengine.h @@ -1,24 +1,24 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; you + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product + this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source + 3. This notice may not be removed or altered from any source distribution. The original version of this library can be located at: @@ -86,7 +86,7 @@ public: virtual asIJITCompiler *GetJITCompiler() const; // Global functions - virtual int RegisterGlobalFunction(const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall = 0); + virtual int RegisterGlobalFunction(const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0); virtual asUINT GetGlobalFunctionCount() const; virtual asIScriptFunction *GetGlobalFunctionByIndex(asUINT index) const; virtual asIScriptFunction *GetGlobalFunctionByDecl(const char *declaration) const; @@ -100,18 +100,16 @@ public: // Type registration virtual int RegisterObjectType(const char *obj, int byteSize, asDWORD flags); - virtual int RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset); - virtual int RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall = 0); - virtual int RegisterObjectBehaviour(const char *obj, asEBehaviours behaviour, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall = 0); + virtual int RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset, int compositeOffset = 0, bool isCompositeIndirect = false); + virtual int RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0, int compositeOffset = 0, bool isCompositeIndirect = false); + virtual int RegisterObjectBehaviour(const char *obj, asEBehaviours behaviour, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0, int compositeOffset = 0, bool isCompositeIndirect = false); virtual int RegisterInterface(const char *name); virtual int RegisterInterfaceMethod(const char *intf, const char *declaration); virtual asUINT GetObjectTypeCount() const; - virtual asIObjectType *GetObjectTypeByIndex(asUINT index) const; - virtual asIObjectType *GetObjectTypeByName(const char *name) const; - virtual asIObjectType *GetObjectTypeByDecl(const char *decl) const; + virtual asITypeInfo *GetObjectTypeByIndex(asUINT index) const; // String factory - virtual int RegisterStringFactory(const char *datatype, const asSFuncPtr &factoryFunc, asDWORD callConv, void *objForThiscall = 0); + virtual int RegisterStringFactory(const char *datatype, asIStringFactory *factory); virtual int GetStringFactoryReturnTypeId(asDWORD *flags) const; // Default array type @@ -119,23 +117,21 @@ public: virtual int GetDefaultArrayTypeId() const; // Enums - virtual int RegisterEnum(const char *type); - virtual int RegisterEnumValue(const char *type, const char *name, int value); - virtual asUINT GetEnumCount() const; - virtual const char *GetEnumByIndex(asUINT index, int *enumTypeId, const char **nameSpace, const char **configGroup = 0, asDWORD *accessMask = 0) const; - virtual int GetEnumValueCount(int enumTypeId) const; - virtual const char *GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const; + virtual int RegisterEnum(const char *type); + virtual int RegisterEnumValue(const char *type, const char *name, int value); + virtual asUINT GetEnumCount() const; + virtual asITypeInfo *GetEnumByIndex(asUINT index) const; // Funcdefs - virtual int RegisterFuncdef(const char *decl); - virtual asUINT GetFuncdefCount() const; - virtual asIScriptFunction *GetFuncdefByIndex(asUINT index) const; + virtual int RegisterFuncdef(const char *decl); + virtual asUINT GetFuncdefCount() const; + virtual asITypeInfo *GetFuncdefByIndex(asUINT index) const; // Typedefs // TODO: interface: Should perhaps rename this to Alias, since it doesn't really create a new type - virtual int RegisterTypedef(const char *type, const char *decl); - virtual asUINT GetTypedefCount() const; - virtual const char *GetTypedefByIndex(asUINT index, int *typeId, const char **nameSpace, const char **configGroup = 0, asDWORD *accessMask = 0) const; + virtual int RegisterTypedef(const char *type, const char *decl); + virtual asUINT GetTypedefCount() const; + virtual asITypeInfo *GetTypedefByIndex(asUINT index) const; // Configuration groups virtual int BeginConfigGroup(const char *groupName); @@ -153,29 +149,26 @@ public: // Script functions virtual asIScriptFunction *GetFunctionById(int funcId) const; - virtual asIScriptFunction *GetFuncDefFromTypeId(int typeId) const; // Type identification - virtual asIObjectType *GetObjectTypeById(int typeId) const; virtual int GetTypeIdByDecl(const char *decl) const; virtual const char *GetTypeDeclaration(int typeId, bool includeNamespace = false) const; virtual int GetSizeOfPrimitiveType(int typeId) const; + virtual asITypeInfo *GetTypeInfoById(int typeId) const; + virtual asITypeInfo *GetTypeInfoByName(const char *name) const; + virtual asITypeInfo *GetTypeInfoByDecl(const char *decl) const; // Script execution virtual asIScriptContext *CreateContext(); - virtual void *CreateScriptObject(const asIObjectType *type); - virtual void *CreateScriptObjectCopy(void *obj, const asIObjectType *type); - virtual void *CreateUninitializedScriptObject(const asIObjectType *type); + virtual void *CreateScriptObject(const asITypeInfo *type); + virtual void *CreateScriptObjectCopy(void *obj, const asITypeInfo *type); + virtual void *CreateUninitializedScriptObject(const asITypeInfo *type); virtual asIScriptFunction *CreateDelegate(asIScriptFunction *func, void *obj); - virtual int AssignScriptObject(void *dstObj, void *srcObj, const asIObjectType *type); - virtual void ReleaseScriptObject(void *obj, const asIObjectType *type); - virtual void AddRefScriptObject(void *obj, const asIObjectType *type); - virtual int RefCastObject(void *obj, asIObjectType *fromType, asIObjectType *toType, void **newPtr, bool useOnlyImplicitCast = false); -#ifdef AS_DEPRECATED - // Deprecated since 2.30.0, 2014-11-04 - virtual bool IsHandleCompatibleWithObject(void *obj, int objTypeId, int handleTypeId) const; -#endif - virtual asILockableSharedBool *GetWeakRefFlagOfScriptObject(void *obj, const asIObjectType *type) const; + virtual int AssignScriptObject(void *dstObj, void *srcObj, const asITypeInfo *type); + virtual void ReleaseScriptObject(void *obj, const asITypeInfo *type); + virtual void AddRefScriptObject(void *obj, const asITypeInfo *type); + virtual int RefCastObject(void *obj, asITypeInfo *fromType, asITypeInfo *toType, void **newPtr, bool useOnlyImplicitCast = false); + virtual asILockableSharedBool *GetWeakRefFlagOfScriptObject(void *obj, const asITypeInfo *type) const; // Context pooling virtual asIScriptContext *RequestContext(); @@ -188,8 +181,8 @@ public: // Garbage collection virtual int GarbageCollect(asDWORD flags = asGC_FULL_CYCLE, asUINT numIterations = 1); virtual void GetGCStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected, asUINT *newObjects, asUINT *totalNewDestroyed) const; - virtual int NotifyGarbageCollectorOfNewObject(void *obj, asIObjectType *type); - virtual int GetObjectInGC(asUINT idx, asUINT *seqNbr, void **obj = 0, asIObjectType **type = 0); + virtual int NotifyGarbageCollectorOfNewObject(void *obj, asITypeInfo *type); + virtual int GetObjectInGC(asUINT idx, asUINT *seqNbr, void **obj = 0, asITypeInfo **type = 0); virtual void GCEnumCallback(void *reference); // User data @@ -199,7 +192,7 @@ public: virtual void SetModuleUserDataCleanupCallback(asCLEANMODULEFUNC_t callback, asPWORD type); virtual void SetContextUserDataCleanupCallback(asCLEANCONTEXTFUNC_t callback, asPWORD type); virtual void SetFunctionUserDataCleanupCallback(asCLEANFUNCTIONFUNC_t callback, asPWORD type); - virtual void SetObjectTypeUserDataCleanupCallback(asCLEANOBJECTTYPEFUNC_t callback, asPWORD type); + virtual void SetTypeInfoUserDataCleanupCallback(asCLEANTYPEINFOFUNC_t callback, asPWORD type); virtual void SetScriptObjectUserDataCleanupCallback(asCLEANSCRIPTOBJECTFUNC_t callback, asPWORD type); //=========================================================== @@ -219,8 +212,8 @@ public: friend class asCByteCode; friend int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *internal, asCScriptEngine *engine); - int RegisterMethodToObjectType(asCObjectType *objectType, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall = 0); - int RegisterBehaviourToObjectType(asCObjectType *objectType, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall); + int RegisterMethodToObjectType(asCObjectType *objectType, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0, int compositeOffset = 0, bool isCompositeIndirect = false); + int RegisterBehaviourToObjectType(asCObjectType *objectType, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv, void *auxiliary = 0, int compositeOffset = 0, bool isCompositeIndirect = false); int VerifyVarTypeNotInFunction(asCScriptFunction *func); @@ -241,18 +234,18 @@ public: void *CallObjectMethodRetPtr(void *obj, int param1, asCScriptFunction *func) const; void CallGlobalFunction(void *param1, void *param2, asSSystemFunctionInterface *func, asCScriptFunction *desc) const; bool CallGlobalFunctionRetBool(void *param1, void *param2, asSSystemFunctionInterface *func, asCScriptFunction *desc) const; + int CallScriptObjectMethod(void *obj, int func); void ConstructScriptObjectCopy(void *mem, void *obj, asCObjectType *type); void DeleteDiscardedModules(); void RemoveTemplateInstanceType(asCObjectType *t); - void RemoveTypeAndRelatedFromList(asCMap &types, asCObjectType *ot); asCConfigGroup *FindConfigGroupForFunction(int funcId) const; asCConfigGroup *FindConfigGroupForGlobalVar(int gvarId) const; - asCConfigGroup *FindConfigGroupForObjectType(const asCObjectType *type) const; - asCConfigGroup *FindConfigGroupForFuncDef(const asCScriptFunction *funcDef) const; + asCConfigGroup *FindConfigGroupForTypeInfo(const asCTypeInfo *type) const; + asCConfigGroup *FindConfigGroupForFuncDef(const asCFuncdefType *funcDef) const; int RequestBuild(); void BuildCompleted(); @@ -262,7 +255,7 @@ public: int CreateContext(asIScriptContext **context, bool isInternal); - asCObjectType *GetRegisteredObjectType(const asCString &name, asSNameSpace *ns) const; + asCTypeInfo *GetRegisteredType(const asCString &name, asSNameSpace *ns) const; asCObjectType *GetListPatternType(int listPatternFuncId); void DestroyList(asBYTE *buffer, const asCObjectType *listPatternType); @@ -283,29 +276,28 @@ public: int GetNextScriptFunctionId(); void AddScriptFunction(asCScriptFunction *func); void RemoveScriptFunction(asCScriptFunction *func); - void RemoveFuncdef(asCScriptFunction *func); + void RemoveFuncdef(asCFuncdefType *func); int ConfigError(int err, const char *funcName, const char *arg1, const char *arg2); int GetTypeIdFromDataType(const asCDataType &dt) const; asCDataType GetDataTypeFromTypeId(int typeId) const; asCObjectType *GetObjectTypeFromTypeId(int typeId) const; - void RemoveFromTypeIdMap(asCObjectType *type); + void RemoveFromTypeIdMap(asCTypeInfo *type); bool IsTemplateType(const char *name) const; + int SetTemplateRestrictions(asCObjectType *templateType, asCScriptFunction *func, const char *caller, const char *decl); asCObjectType *GetTemplateInstanceType(asCObjectType *templateType, asCArray &subTypes, asCModule *requestingModule); asCScriptFunction *GenerateTemplateFactoryStub(asCObjectType *templateType, asCObjectType *templateInstanceType, int origFactoryId); bool GenerateNewTemplateFunction(asCObjectType *templateType, asCObjectType *templateInstanceType, asCScriptFunction *templateFunc, asCScriptFunction **newFunc); + asCFuncdefType *GenerateNewTemplateFuncdef(asCObjectType *templateType, asCObjectType *templateInstanceType, asCFuncdefType *templateFuncdef); asCDataType DetermineTypeForTemplate(const asCDataType &orig, asCObjectType *tmpl, asCObjectType *ot); bool RequireTypeReplacement(asCDataType &type, asCObjectType *templateType); - asCModule *FindNewOwnerForSharedType(asCObjectType *type, asCModule *mod); + asCModule *FindNewOwnerForSharedType(asCTypeInfo *type, asCModule *mod); asCModule *FindNewOwnerForSharedFunc(asCScriptFunction *func, asCModule *mod); - // String constants - // TODO: Must free unused string constants, thus the ref count for each must be tracked - int AddConstantString(const char *str, size_t length); - const asCString &GetConstantString(int id); + asCFuncdefType *FindMatchingFuncdef(asCScriptFunction *func, asCModule *mod); // Global property management asCGlobalProperty *AllocateGlobalProperty(); @@ -330,24 +322,26 @@ public: asCObjectType functionBehaviours; // Registered interface - asCArray registeredObjTypes; - asCArray registeredTypeDefs; - asCArray registeredEnums; - asCSymbolTable registeredGlobalProps; // increases ref count // TODO: memory savings: Since there can be only one property with the same name a simpler symbol table should be used + asCArray registeredObjTypes; // doesn't increase ref count + asCArray registeredTypeDefs; // doesn't increase ref count + asCArray registeredEnums; // doesn't increase ref count + // TODO: memory savings: Since there can be only one property with the same name a simpler symbol table should be used for global props + asCSymbolTable registeredGlobalProps; // increases ref count asCSymbolTable registeredGlobalFuncs; - asCArray registeredFuncDefs; - asCArray registeredTemplateTypes; - asCScriptFunction *stringFactory; + asCArray registeredFuncDefs; // doesn't increase ref count + asCArray registeredTemplateTypes; // doesn't increase ref count + asIStringFactory *stringFactory; + asCDataType stringType; bool configFailed; - // Stores all registered types except funcdefs - asCMap allRegisteredTypes; // increases ref count + // Stores all registered types + asCMap allRegisteredTypes; // increases ref count - // Dummy types used to name the subtypes in the template objects - asCArray templateSubTypes; + // Dummy types used to name the subtypes in the template objects + asCArray templateSubTypes; // Store information about template types - // This list will contain all instances of templates, both registered specialized + // This list will contain all instances of templates, both registered specialized // types and those automacially instantiated from scripts asCArray templateInstanceTypes; // increases ref count @@ -378,7 +372,7 @@ public: // This array holds all live script modules asCArray scriptModules; // Synchronized with engineRWLock - // This is a pointer to the last module that was requested. It is used for performance + // This is a pointer to the last module that was requested. It is used for performance // improvement, since it is common that the same module is accessed many times in a row asCModule *lastModule; // Synchronized with engineRWLock @@ -389,29 +383,28 @@ public: // This array holds modules that have been discard (thus are no longer visible to the application) // but cannot yet be deleted due to having external references to some of the entities in them asCArray discardedModules; - // This flag is set to true during compilations of scripts (or loading pre-compiled scripts) - // to delay the validation of template types until the subtypes have been fully declared + // This flag is set to true during compilations of scripts (or loading pre-compiled scripts) + // to delay the validation of template types until the subtypes have been fully declared bool deferValidationOfTemplateTypes; // Tokenizer is instantiated once to share resources asCTokenizer tok; // Stores shared script declared types (classes, interfaces, enums) - asCArray sharedScriptTypes; // increases ref count + asCArray sharedScriptTypes; // increases ref count // This array stores the template instances types that have been automatically generated from template types asCArray generatedTemplateTypes; // Stores the funcdefs // TODO: redesign: Only shared funcdefs should be stored here // a funcdef becomes shared if all arguments and the return type are shared (or application registered) - asCArray funcDefs; // doesn't increase ref count + asCArray funcDefs; // doesn't increases ref count // Stores the names of the script sections for debugging purposes asCArray scriptSectionNames; // Type identifiers mutable int typeIdSeqNbr; - mutable asCMap mapTypeIdToObjectType; - mutable asCMap mapTypeIdToFunction; + mutable asCMap mapTypeIdToTypeInfo; // Garbage collector asCGarbageCollector gc; @@ -441,16 +434,10 @@ public: asIJITCompiler *jitCompiler; // Namespaces - // These are shared between all entities and are + // These are shared between all entities and are // only deleted once the engine is destroyed asCArray nameSpaces; - // String constants - // These are shared between all scripts and are - // only deleted once the engine is destroyed - asCArray stringConstants; - asCMap stringToIdMap; - // Callbacks for context pooling asREQUESTCONTEXTFUNC_t requestCtxFunc; asRETURNCONTEXTFUNC_t returnCtxFunc; @@ -459,16 +446,16 @@ public: // User data asCArray userData; - struct SEngineClean { asPWORD type; asCLEANENGINEFUNC_t cleanFunc; }; + struct SEngineClean { asPWORD type; asCLEANENGINEFUNC_t cleanFunc; }; asCArray cleanEngineFuncs; - struct SModuleClean { asPWORD type; asCLEANMODULEFUNC_t cleanFunc; }; + struct SModuleClean { asPWORD type; asCLEANMODULEFUNC_t cleanFunc; }; asCArray cleanModuleFuncs; - struct SContextClean { asPWORD type; asCLEANCONTEXTFUNC_t cleanFunc; }; + struct SContextClean { asPWORD type; asCLEANCONTEXTFUNC_t cleanFunc; }; asCArray cleanContextFuncs; - struct SFunctionClean { asPWORD type; asCLEANFUNCTIONFUNC_t cleanFunc; }; + struct SFunctionClean { asPWORD type; asCLEANFUNCTIONFUNC_t cleanFunc; }; asCArray cleanFunctionFuncs; - struct SObjTypeClean { asPWORD type; asCLEANOBJECTTYPEFUNC_t cleanFunc; }; - asCArray cleanObjectTypeFuncs; + struct STypeInfoClean { asPWORD type; asCLEANTYPEINFOFUNC_t cleanFunc; }; + asCArray cleanTypeInfoFuncs; struct SScriptObjClean { asPWORD type; asCLEANSCRIPTOBJECTFUNC_t cleanFunc; }; asCArray cleanScriptObjectFuncs; @@ -504,12 +491,15 @@ public: bool disallowEmptyListElements; // TODO: 3.0.0: Remove the privatePropAsProtected bool privatePropAsProtected; + bool allowUnicodeIdentifiers; + int heredocTrimMode; + asUINT maxNestedCalls; } ep; // This flag is to allow a quicker shutdown when releasing the engine bool shuttingDown; - // This flag is set when the engine's destructor is called, this is to + // This flag is set when the engine's destructor is called, this is to // avoid recursive calls if an object happens to increment/decrement // the ref counter during shutdown bool inDestructor; diff --git a/lib/angelscript/source/as_scriptfunction.cpp b/lib/angelscript/source/as_scriptfunction.cpp index efb4a5c07..d007a477b 100644 --- a/lib/angelscript/source/as_scriptfunction.cpp +++ b/lib/angelscript/source/as_scriptfunction.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -123,7 +123,7 @@ void RegisterScriptFunction(asCScriptEngine *engine) int r = 0; UNUSED_VAR(r); // It is only used in debug mode engine->functionBehaviours.engine = engine; - engine->functionBehaviours.flags = asOBJ_REF | asOBJ_GC | asOBJ_SCRIPT_FUNCTION; + engine->functionBehaviours.flags = asOBJ_REF | asOBJ_GC; engine->functionBehaviours.name = "$func"; #ifndef AS_MAX_PORTABILITY r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCScriptFunction,AddRef), asCALL_THISCALL, 0); asASSERT( r >= 0 ); @@ -163,7 +163,7 @@ void RegisterScriptFunction(asCScriptEngine *engine) engine->registeredGlobalFuncs.Put(engine->scriptFunctions[r]); // Change the return type so the VM will know the function really returns a handle - engine->scriptFunctions[r]->returnType = asCDataType::CreateObject(&engine->functionBehaviours, false); + engine->scriptFunctions[r]->returnType = asCDataType::CreateType(&engine->functionBehaviours, false); engine->scriptFunctions[r]->returnType.MakeHandle(true); } @@ -205,6 +205,15 @@ void asCScriptFunction::MakeDelegate(asCScriptFunction *func, void *obj) dontCleanUpOnException = true; } +// interface +void *asCScriptFunction::GetAuxiliary() const +{ + if (sysFuncIntf) + return sysFuncIntf->auxiliary; + + return 0; +} + // interface void *asCScriptFunction::GetDelegateObject() const { @@ -212,7 +221,7 @@ void *asCScriptFunction::GetDelegateObject() const } // interface -asIObjectType *asCScriptFunction::GetDelegateObjectType() const +asITypeInfo *asCScriptFunction::GetDelegateObjectType() const { if( objForDelegate == 0 || funcForDelegate == 0 ) return 0; @@ -297,7 +306,7 @@ int asCScriptFunction::ParseListPattern(asSListPatternNode *&target, const char asCBuilder builder(engine, 0); asCScriptCode code; code.SetCode("", decl, 0, false); - dt = builder.CreateDataTypeFromNode(listNodes, &code, engine->defaultNamespace, false, returnType.GetObjectType()); + dt = builder.CreateDataTypeFromNode(listNodes, &code, engine->defaultNamespace, false, CastToObjectType(returnType.GetTypeInfo())); node->next = asNEW(asSListPatternDataTypeNode)(dt); node = node->next; @@ -350,11 +359,6 @@ asCScriptFunction::asCScriptFunction(asCScriptEngine *engine, asCModule *mod, as module = mod; objectType = 0; name = ""; - isReadOnly = false; - isPrivate = false; - isProtected = false; - isFinal = false; - isOverride = false; sysFuncIntf = 0; signatureId = 0; dontCleanUpOnException = false; @@ -363,11 +367,11 @@ asCScriptFunction::asCScriptFunction(asCScriptEngine *engine, asCModule *mod, as userData = 0; id = 0; accessMask = 0xFFFFFFFF; - isShared = false; nameSpace = engine->nameSpaces[0]; objForDelegate = 0; funcForDelegate = 0; listPattern = 0; + funcdefType = 0; if( funcType == asFUNC_SCRIPT ) AllocateScriptFunctionData(); @@ -552,7 +556,7 @@ int asCScriptFunction::ReleaseInternal() int asCScriptFunction::GetTypeId() const { // This const cast is ok, the object won't be modified - asCDataType dt = asCDataType::CreateFuncDef(const_cast(this)); + asCDataType dt = asCDataType::CreateType(engine->FindMatchingFuncdef(const_cast(this), 0), false); return engine->GetTypeIdFromDataType(dt); } @@ -562,10 +566,10 @@ bool asCScriptFunction::IsCompatibleWithTypeId(int typeId) const asCDataType dt = engine->GetDataTypeFromTypeId(typeId); // Make sure the type is a function - asCScriptFunction *func = dt.GetFuncDef(); - if( func == 0 ) + if (!dt.IsFuncdef()) return false; + asCScriptFunction *func = CastToFuncdefType(dt.GetTypeInfo())->funcdef; if( !IsSignatureExceptNameEqual(func) ) return false; @@ -594,7 +598,7 @@ asIScriptModule *asCScriptFunction::GetModule() const } // interface -asIObjectType *asCScriptFunction::GetObjectType() const +asITypeInfo *asCScriptFunction::GetObjectType() const { return objectType; } @@ -617,25 +621,28 @@ const char *asCScriptFunction::GetName() const // interface const char *asCScriptFunction::GetNamespace() const { - return nameSpace->name.AddressOf(); + if (nameSpace) + return nameSpace->name.AddressOf(); + + return 0; } // interface bool asCScriptFunction::IsReadOnly() const { - return isReadOnly; + return traits.GetTrait(asTRAIT_CONST); } // interface bool asCScriptFunction::IsPrivate() const { - return isPrivate; + return traits.GetTrait(asTRAIT_PRIVATE); } // interface bool asCScriptFunction::IsProtected() const { - return isProtected; + return traits.GetTrait(asTRAIT_PROTECTED); } // internal @@ -658,8 +665,8 @@ int asCScriptFunction::GetSpaceNeededForReturnValue() // internal bool asCScriptFunction::DoesReturnOnStack() const { - if( returnType.GetObjectType() && - (returnType.GetObjectType()->flags & asOBJ_VALUE) && + if( returnType.GetTypeInfo() && + (returnType.GetTypeInfo()->flags & asOBJ_VALUE) && !returnType.IsReference() ) return true; @@ -692,6 +699,16 @@ asCString asCScriptFunction::GetDeclarationStr(bool includeObjectName, bool incl else str += "_unnamed_type_::"; } + else if (funcdefType && funcdefType->parentClass && includeObjectName) + { + if (includeNamespace && funcdefType->parentClass->nameSpace->name != "") + str += funcdefType->parentClass->nameSpace->name + "::"; + + if (funcdefType->parentClass->name != "") + str += funcdefType->parentClass->name + "::"; + else + str += "_unnamed_type_::"; + } else if( includeNamespace && nameSpace->name != "" ) { str += nameSpace->name + "::"; @@ -703,7 +720,7 @@ asCString asCScriptFunction::GetDeclarationStr(bool includeObjectName, bool incl if( name[4] == '0' + asBEHAVE_CONSTRUCT ) str += objectType->name + "("; else if( name[4] == '0' + asBEHAVE_FACTORY ) - str += returnType.GetObjectType()->name + "("; + str += returnType.GetTypeInfo()->name + "("; else if( name[4] == '0' + asBEHAVE_DESTRUCT ) str += "~" + objectType->name + "("; else @@ -766,7 +783,7 @@ asCString asCScriptFunction::GetDeclarationStr(bool includeObjectName, bool incl str += ")"; - if( isReadOnly ) + if( IsReadOnly() ) str += " const"; // Add the declaration of the list pattern @@ -923,17 +940,17 @@ asUINT asCScriptFunction::GetVarCount() const } // interface -int asCScriptFunction::GetVar(asUINT index, const char **name, int *typeId) const +int asCScriptFunction::GetVar(asUINT index, const char **out_name, int *out_typeId) const { if( scriptData == 0 ) return asNOT_SUPPORTED; if( index >= scriptData->variables.GetLength() ) return asINVALID_ARG; - if( name ) - *name = scriptData->variables[index]->name.AddressOf(); - if( typeId ) - *typeId = engine->GetTypeIdFromDataType(scriptData->variables[index]->type); + if( out_name ) + *out_name = scriptData->variables[index]->name.AddressOf(); + if( out_typeId ) + *out_typeId = engine->GetTypeIdFromDataType(scriptData->variables[index]->type); return asSUCCESS; } @@ -952,7 +969,7 @@ const char *asCScriptFunction::GetVarDecl(asUINT index, bool includeNamespace) c } // internal -void asCScriptFunction::AddVariable(asCString &name, asCDataType &type, int stackOffset) +void asCScriptFunction::AddVariable(asCString &in_name, asCDataType &in_type, int in_stackOffset) { asASSERT( scriptData ); asSScriptVariable *var = asNEW(asSScriptVariable); @@ -961,15 +978,15 @@ void asCScriptFunction::AddVariable(asCString &name, asCDataType &type, int stac // Out of memory return; } - var->name = name; - var->type = type; - var->stackOffset = stackOffset; + var->name = in_name; + var->type = in_type; + var->stackOffset = in_stackOffset; var->declaredAtProgramPos = 0; scriptData->variables.PushLast(var); } // internal -asCObjectType *asCScriptFunction::GetObjectTypeOfLocalVar(short varOffset) +asCTypeInfo *asCScriptFunction::GetTypeInfoOfLocalVar(short varOffset) { asASSERT( scriptData ); @@ -1015,7 +1032,7 @@ bool asCScriptFunction::IsSignatureEqual(const asCScriptFunction *func) const // internal bool asCScriptFunction::IsSignatureExceptNameEqual(const asCScriptFunction *func) const { - return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, func->objectType, func->isReadOnly); + return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, func->objectType, func->IsReadOnly()); } // internal @@ -1029,19 +1046,19 @@ bool asCScriptFunction::IsSignatureExceptNameEqual(const asCDataType &retType, c // internal bool asCScriptFunction::IsSignatureExceptNameAndObjectTypeEqual(const asCScriptFunction *func) const { - return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, objectType, isReadOnly); + return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, objectType, IsReadOnly()); } // internal bool asCScriptFunction::IsSignatureExceptNameAndReturnTypeEqual(const asCScriptFunction *func) const { - return IsSignatureExceptNameAndReturnTypeEqual(func->parameterTypes, func->inOutFlags, func->objectType, func->isReadOnly); + return IsSignatureExceptNameAndReturnTypeEqual(func->parameterTypes, func->inOutFlags, func->objectType, func->IsReadOnly()); } // internal bool asCScriptFunction::IsSignatureExceptNameAndReturnTypeEqual(const asCArray ¶mTypes, const asCArray ¶mInOut, const asCObjectType *objType, bool readOnly) const { - if( this->isReadOnly != readOnly ) return false; + if( this->IsReadOnly() != readOnly ) return false; if( (this->objectType != 0) != (objType != 0) ) return false; if( this->inOutFlags != paramInOut ) return false; if( this->parameterTypes != paramTypes ) return false; @@ -1062,20 +1079,20 @@ void asCScriptFunction::AddReferences() // Only count references if there is any bytecode if( scriptData && scriptData->byteCode.GetLength() ) { - if( returnType.GetObjectType() ) + if( returnType.GetTypeInfo() ) { - returnType.GetObjectType()->AddRefInternal(); + returnType.GetTypeInfo()->AddRefInternal(); - asCConfigGroup *group = engine->FindConfigGroupForObjectType(returnType.GetObjectType()); + asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(returnType.GetTypeInfo()); if( group != 0 ) group->AddRef(); } for( asUINT p = 0; p < parameterTypes.GetLength(); p++ ) - if( parameterTypes[p].GetObjectType() ) + if( parameterTypes[p].GetTypeInfo() ) { - parameterTypes[p].GetObjectType()->AddRefInternal(); + parameterTypes[p].GetTypeInfo()->AddRefInternal(); - asCConfigGroup *group = engine->FindConfigGroupForObjectType(parameterTypes[p].GetObjectType()); + asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(parameterTypes[p].GetTypeInfo()); if( group != 0 ) group->AddRef(); } @@ -1084,7 +1101,7 @@ void asCScriptFunction::AddReferences() { scriptData->objVariableTypes[v]->AddRefInternal(); - asCConfigGroup *group = engine->FindConfigGroupForObjectType(scriptData->objVariableTypes[v]); + asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(scriptData->objVariableTypes[v]); if( group != 0 ) group->AddRef(); } @@ -1135,7 +1152,31 @@ void asCScriptFunction::AddReferences() void *gvarPtr = (void*)asBC_PTRARG(&bc[n]); if( !gvarPtr ) break; asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr); - if( !prop ) break; + + if (!prop) + { + // The pointer is a string constant. In order to make sure the correct resource + // management is maintained we request a new string constant here, so the compiler + // or bytecode loader can release its copy afterwards. + asCString str; + asUINT length; + int r = engine->stringFactory->GetRawStringData(gvarPtr, 0, &length); + if (r >= 0) + { + str.SetLength(length); + engine->stringFactory->GetRawStringData(gvarPtr, str.AddressOf(), &length); + + // Get a new pointer (depending on the string factory implementation it may actually be the same) + gvarPtr = const_cast(engine->stringFactory->GetStringConstant(str.AddressOf(), length)); + asBC_PTRARG(&bc[n]) = (asPWORD)gvarPtr; + } + + // If we get an error from the string factory there is not + // anything we can do about it, except report a message. + // TODO: NEWSTRING: Write a message and then exit gracefully + asASSERT(r >= 0); + break; + } // Only addref the properties once if( !ptrs.Exists(gvarPtr) ) @@ -1195,20 +1236,20 @@ void asCScriptFunction::ReleaseReferences() // Only count references if there is any bytecode if( scriptData && scriptData->byteCode.GetLength() ) { - if( returnType.GetObjectType() ) + if( returnType.GetTypeInfo() ) { - returnType.GetObjectType()->ReleaseInternal(); + returnType.GetTypeInfo()->ReleaseInternal(); - asCConfigGroup *group = engine->FindConfigGroupForObjectType(returnType.GetObjectType()); + asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(returnType.GetTypeInfo()); if( group != 0 ) group->Release(); } for( asUINT p = 0; p < parameterTypes.GetLength(); p++ ) - if( parameterTypes[p].GetObjectType() ) + if( parameterTypes[p].GetTypeInfo() ) { - parameterTypes[p].GetObjectType()->ReleaseInternal(); + parameterTypes[p].GetTypeInfo()->ReleaseInternal(); - asCConfigGroup *group = engine->FindConfigGroupForObjectType(parameterTypes[p].GetObjectType()); + asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(parameterTypes[p].GetTypeInfo()); if( group != 0 ) group->Release(); } @@ -1217,7 +1258,7 @@ void asCScriptFunction::ReleaseReferences() { scriptData->objVariableTypes[v]->ReleaseInternal(); - asCConfigGroup *group = engine->FindConfigGroupForObjectType(scriptData->objVariableTypes[v]); + asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(scriptData->objVariableTypes[v]); if( group != 0 ) group->Release(); } @@ -1276,7 +1317,21 @@ void asCScriptFunction::ReleaseReferences() void *gvarPtr = (void*)asBC_PTRARG(&bc[n]); if( !gvarPtr ) break; asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr); - if( !prop ) break; + + if (!prop) + { + // The pointer is a string constant, so it needs to be released by the string factory + int r = engine->stringFactory->ReleaseStringConstant(gvarPtr); + UNUSED_VAR(r); + + // If we get an error from the string factory there is not + // anything we can do about it, except report a message. + // TODO: Write a message showing that the string couldn't be + // released. Include the first 10 characters and the length + // to make it easier to identify which string it was + asASSERT(r >= 0); + break; + } // Only release the properties once if( !ptrs.Exists(gvarPtr) ) @@ -1376,57 +1431,40 @@ asUINT asCScriptFunction::GetParamCount() const } // interface -int asCScriptFunction::GetParam(asUINT index, int *typeId, asDWORD *flags, const char **name, const char **defaultArg) const +int asCScriptFunction::GetParam(asUINT index, int *out_typeId, asDWORD *out_flags, const char **out_name, const char **out_defaultArg) const { if( index >= parameterTypes.GetLength() ) return asINVALID_ARG; - if( typeId ) - *typeId = engine->GetTypeIdFromDataType(parameterTypes[index]); + if( out_typeId ) + *out_typeId = engine->GetTypeIdFromDataType(parameterTypes[index]); - if( flags ) + if( out_flags ) { - *flags = inOutFlags[index]; - *flags |= parameterTypes[index].IsReadOnly() ? asTM_CONST : 0; + *out_flags = inOutFlags[index]; + *out_flags |= parameterTypes[index].IsReadOnly() ? asTM_CONST : 0; } - if( name ) + if( out_name ) { // The parameter names are not stored if loading from bytecode without debug information if( index < parameterNames.GetLength() ) - *name = parameterNames[index].AddressOf(); + *out_name = parameterNames[index].AddressOf(); else - *name = 0; + *out_name = 0; } - if( defaultArg ) + if( out_defaultArg ) { if( index < defaultArgs.GetLength() && defaultArgs[index] ) - *defaultArg = defaultArgs[index]->AddressOf(); + *out_defaultArg = defaultArgs[index]->AddressOf(); else - *defaultArg = 0; + *out_defaultArg = 0; } return asSUCCESS; } -#ifdef AS_DEPRECATED -// Deprecated since 2014-04-06, 2.29.0 -int asCScriptFunction::GetParamTypeId(asUINT index, asDWORD *flags) const -{ - if( index >= parameterTypes.GetLength() ) - return asINVALID_ARG; - - if( flags ) - { - *flags = inOutFlags[index]; - *flags |= parameterTypes[index].IsReadOnly() ? asTM_CONST : 0; - } - - return engine->GetTypeIdFromDataType(parameterTypes[index]); -} -#endif - // interface asIScriptEngine *asCScriptFunction::GetEngine() const { @@ -1457,7 +1495,7 @@ const char *asCScriptFunction::GetConfigGroup() const if( funcType != asFUNC_FUNCDEF ) group = engine->FindConfigGroupForFunction(id); else - group = engine->FindConfigGroupForFuncDef(this); + group = engine->FindConfigGroupForFuncDef(this->funcdefType); if( group == 0 ) return 0; @@ -1655,20 +1693,23 @@ bool asCScriptFunction::IsShared() const asASSERT( objectType == 0 || objectType->engine == engine || objectType->engine == 0 ); if( objectType && (objectType->flags & asOBJ_SHARED) ) return true; + // funcdefs that are registered by the application are shared + if (funcType == asFUNC_FUNCDEF && module == 0) return true; + // Functions that have been specifically marked as shared are shared - return isShared; + return traits.GetTrait(asTRAIT_SHARED); } // internal bool asCScriptFunction::IsFinal() const { - return isFinal; + return traits.GetTrait(asTRAIT_FINAL); } // internal bool asCScriptFunction::IsOverride() const { - return isOverride; + return traits.GetTrait(asTRAIT_OVERRIDE); } END_AS_NAMESPACE diff --git a/lib/angelscript/source/as_scriptfunction.h b/lib/angelscript/source/as_scriptfunction.h index 1ab9a75e3..167af4de9 100644 --- a/lib/angelscript/source/as_scriptfunction.h +++ b/lib/angelscript/source/as_scriptfunction.h @@ -1,24 +1,24 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; you + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product + this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source + 3. This notice may not be removed or altered from any source distribution. The original version of this library can be located at: @@ -53,6 +53,7 @@ class asCModule; class asCConfigGroup; class asCGlobalProperty; class asCScriptNode; +class asCFuncdefType; struct asSNameSpace; struct asSScriptVariable @@ -96,17 +97,39 @@ enum asEObjVarInfoOption asBLOCK_END }; +enum asEFuncTrait +{ + asTRAIT_CONSTRUCTOR = 1, + asTRAIT_DESTRUCTOR = 2, + asTRAIT_CONST = 4, + asTRAIT_PRIVATE = 8, + asTRAIT_PROTECTED = 16, + asTRAIT_FINAL = 32, + asTRAIT_OVERRIDE = 64, + asTRAIT_SHARED = 128, + asTRAIT_EXTERNAL = 256 +}; + +struct asSFunctionTraits +{ + asSFunctionTraits() : traits(0) {} + void SetTrait(asEFuncTrait trait, bool set) { if (set) traits |= trait; else traits &= ~trait; } + bool GetTrait(asEFuncTrait trait) const { return (traits & trait) ? true : false; } +protected: + asDWORD traits; +}; + struct asSObjectVariableInfo { - asUINT programPos; - int variableOffset; - asUINT option; + asUINT programPos; + int variableOffset; + asEObjVarInfoOption option; }; struct asSSystemFunctionInterface; -// TODO: Might be interesting to allow enumeration of accessed global variables, and -// also functions/methods that are being called. This could be used to build a +// TODO: Might be interesting to allow enumeration of accessed global variables, and +// also functions/methods that are being called. This could be used to build a // code database with call graphs, etc. void RegisterScriptFunction(asCScriptEngine *engine); @@ -129,9 +152,10 @@ public: const char *GetScriptSectionName() const; const char *GetConfigGroup() const; asDWORD GetAccessMask() const; + void *GetAuxiliary() const; // Function signature - asIObjectType *GetObjectType() const; + asITypeInfo *GetObjectType() const; const char *GetObjectName() const; const char *GetName() const; const char *GetNamespace() const; @@ -144,19 +168,15 @@ public: bool IsShared() const; asUINT GetParamCount() const; int GetParam(asUINT index, int *typeId, asDWORD *flags = 0, const char **name = 0, const char **defaultArg = 0) const; -#ifdef AS_DEPRECATED - // Deprecated, since 2.29.0, 2014-04-06 - int GetParamTypeId(asUINT index, asDWORD *flags = 0) const; -#endif int GetReturnTypeId(asDWORD *flags = 0) const; - // Type id for function pointers + // Type id for function pointers int GetTypeId() const; bool IsCompatibleWithTypeId(int typeId) const; // Delegates void *GetDelegateObject() const; - asIObjectType *GetDelegateObjectType() const; + asITypeInfo *GetDelegateObjectType() const; asIScriptFunction *GetDelegateFunction() const; // Debug information @@ -176,10 +196,17 @@ public: //----------------------------------- // Internal methods + void SetShared(bool set) {traits.SetTrait(asTRAIT_SHARED, set);} + void SetReadOnly(bool set) { traits.SetTrait(asTRAIT_CONST, set); } + void SetFinal(bool set) { traits.SetTrait(asTRAIT_FINAL, set); } + void SetOverride(bool set) { traits.SetTrait(asTRAIT_OVERRIDE, set); } + void SetProtected(bool set) { traits.SetTrait(asTRAIT_PROTECTED, set); } + void SetPrivate(bool set) { traits.SetTrait(asTRAIT_PRIVATE, set); } + asCScriptFunction(asCScriptEngine *engine, asCModule *mod, asEFuncType funcType); ~asCScriptFunction(); - // Keep an internal reference counter to separate references coming from + // Keep an internal reference counter to separate references coming from // application or script objects and references coming from the script code int AddRefInternal(); int ReleaseInternal(); @@ -210,7 +237,7 @@ public: bool IsSignatureExceptNameAndReturnTypeEqual(const asCArray ¶mTypes, const asCArray &inOutFlags, const asCObjectType *type, bool isReadOnly) const; bool IsSignatureExceptNameAndObjectTypeEqual(const asCScriptFunction *func) const; - asCObjectType *GetObjectTypeOfLocalVar(short varOffset); + asCTypeInfo *GetTypeInfoOfLocalVar(short varOffset); void MakeDelegate(asCScriptFunction *func, void *obj); @@ -255,11 +282,7 @@ public: asCArray parameterNames; asCArray inOutFlags; asCArray defaultArgs; - bool isReadOnly; - bool isPrivate; - bool isProtected; - bool isFinal; - bool isOverride; + asSFunctionTraits traits; asCObjectType *objectType; int signatureId; @@ -267,10 +290,14 @@ public: asEFuncType funcType; asDWORD accessMask; - bool isShared; + // Namespace will be null for funcdefs that are declared as child funcdefs + // of a class. In this case the namespace shall be taken from the parentClass + // in the funcdefType asSNameSpace *nameSpace; + asCFuncdefType *funcdefType; // Doesn't increase refCount + // Used by asFUNC_DELEGATE void *objForDelegate; asCScriptFunction *funcForDelegate; @@ -289,8 +316,7 @@ public: // These hold information on objects and function pointers, including temporary // variables used by exception handler and when saving bytecode - asCArray objVariableTypes; - asCArray funcVariableTypes; + asCArray objVariableTypes; asCArray objVariablePos; // The first variables in above array are allocated on the heap, the rest on the stack. diff --git a/lib/angelscript/source/as_scriptnode.cpp b/lib/angelscript/source/as_scriptnode.cpp index 8ab4454d1..9bd9cfd2b 100644 --- a/lib/angelscript/source/as_scriptnode.cpp +++ b/lib/angelscript/source/as_scriptnode.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2012 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -60,13 +60,13 @@ void asCScriptNode::Destroy(asCScriptEngine *engine) { // Destroy all children asCScriptNode *node = firstChild; - asCScriptNode *next; + asCScriptNode *nxt; while( node ) { - next = node->next; + nxt = node->next; node->Destroy(engine); - node = next; + node = nxt; } // Return the memory to the memory manager diff --git a/lib/angelscript/source/as_scriptnode.h b/lib/angelscript/source/as_scriptnode.h index 66f7bac03..4f32c92d2 100644 --- a/lib/angelscript/source/as_scriptnode.h +++ b/lib/angelscript/source/as_scriptnode.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -89,7 +89,8 @@ enum eScriptNode snNamespace, snMixin, snListPattern, - snNamedArgument + snNamedArgument, + snScope }; struct sToken diff --git a/lib/angelscript/source/as_scriptobject.cpp b/lib/angelscript/source/as_scriptobject.cpp index 80af81e83..21c8cc8c6 100644 --- a/lib/angelscript/source/as_scriptobject.cpp +++ b/lib/angelscript/source/as_scriptobject.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2016 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -271,13 +271,13 @@ asCScriptObject::asCScriptObject(asCObjectType *ot, bool doInitialize) asCObjectProperty *prop = objType->properties[n]; if( prop->type.IsObject() && !prop->type.IsObjectHandle() ) { - if( prop->type.IsReference() || prop->type.GetObjectType()->flags & asOBJ_REF ) + if( prop->type.IsReference() || prop->type.GetTypeInfo()->flags & asOBJ_REF ) { asPWORD *ptr = reinterpret_cast(reinterpret_cast(this) + prop->byteOffset); - if( prop->type.GetObjectType()->flags & asOBJ_SCRIPT_OBJECT ) - *ptr = (asPWORD)ScriptObjectFactory(prop->type.GetObjectType(), ot->engine); + if( prop->type.GetTypeInfo()->flags & asOBJ_SCRIPT_OBJECT ) + *ptr = (asPWORD)ScriptObjectFactory(prop->type.GetTypeInfo(), ot->engine); else - *ptr = (asPWORD)AllocateUninitializedObject(prop->type.GetObjectType(), ot->engine); + *ptr = (asPWORD)AllocateUninitializedObject(prop->type.GetTypeInfo(), ot->engine); } } } @@ -292,10 +292,10 @@ asCScriptObject::asCScriptObject(asCObjectType *ot, bool doInitialize) asCObjectProperty *prop = objType->properties[n]; if( prop->type.IsObject() && !prop->type.IsObjectHandle() ) { - if( prop->type.IsReference() || (prop->type.GetObjectType()->flags & asOBJ_REF) ) + if( prop->type.IsReference() || (prop->type.GetTypeInfo()->flags & asOBJ_REF) ) { asPWORD *ptr = reinterpret_cast(reinterpret_cast(this) + prop->byteOffset); - *ptr = (asPWORD)AllocateUninitializedObject(prop->type.GetObjectType(), engine); + *ptr = (asPWORD)AllocateUninitializedObject(CastToObjectType(prop->type.GetTypeInfo()), engine); } } } @@ -359,7 +359,7 @@ asCScriptObject::~asCScriptObject() if( prop->type.IsObject() ) { // Destroy the object - asCObjectType *propType = prop->type.GetObjectType(); + asCObjectType *propType = CastToObjectType(prop->type.GetTypeInfo()); if( prop->type.IsReference() || propType->flags & asOBJ_REF ) { void **ptr = (void**)(((char*)this) + prop->byteOffset); @@ -381,6 +381,16 @@ asCScriptObject::~asCScriptObject() engine->CallObjectMethod(ptr, propType->beh.destruct); } } + else if( prop->type.IsFuncdef() ) + { + // Release the function descriptor + asCScriptFunction **ptr = (asCScriptFunction**)(((char*)this) + prop->byteOffset); + if (*ptr) + { + (*ptr)->Release(); + *ptr = 0; + } + } } objType->Release(); @@ -647,7 +657,7 @@ void asCScriptObject::CallDestructor() } } -asIObjectType *asCScriptObject::GetObjectType() const +asITypeInfo *asCScriptObject::GetObjectType() const { return objType; } @@ -670,7 +680,7 @@ bool asCScriptObject::GetFlag() // interface int asCScriptObject::GetTypeId() const { - asCDataType dt = asCDataType::CreateObject(objType, false); + asCDataType dt = asCDataType::CreateType(objType, false); return objType->engine->GetTypeIdFromDataType(dt); } @@ -703,7 +713,7 @@ void *asCScriptObject::GetAddressOfProperty(asUINT prop) // Objects are stored by reference, so this must be dereferenced asCDataType *dt = &objType->properties[prop]->type; if( dt->IsObject() && !dt->IsObjectHandle() && - (dt->IsReference() || dt->GetObjectType()->flags & asOBJ_REF) ) + (dt->IsReference() || dt->GetTypeInfo()->flags & asOBJ_REF) ) return *(void**)(((char*)this) + objType->properties[prop]->byteOffset); return (void*)(((char*)this) + objType->properties[prop]->byteOffset); @@ -715,19 +725,21 @@ void asCScriptObject::EnumReferences(asIScriptEngine *engine) for( asUINT n = 0; n < objType->properties.GetLength(); n++ ) { asCObjectProperty *prop = objType->properties[n]; + void *ptr = 0; if( prop->type.IsObject() ) { // TODO: gc: The members of the value type needs to be enumerated // too, since the value type may be holding a reference. - void *ptr; - if( prop->type.IsReference() || (prop->type.GetObjectType()->flags & asOBJ_REF) ) + if( prop->type.IsReference() || (prop->type.GetTypeInfo()->flags & asOBJ_REF) ) ptr = *(void**)(((char*)this) + prop->byteOffset); else ptr = (void*)(((char*)this) + prop->byteOffset); - - if( ptr ) - ((asCScriptEngine*)engine)->GCEnumCallback(ptr); } + else if (prop->type.IsFuncdef()) + ptr = *(void**)(((char*)this) + prop->byteOffset); + + if (ptr) + ((asCScriptEngine*)engine)->GCEnumCallback(ptr); } } @@ -745,12 +757,21 @@ void asCScriptObject::ReleaseAllHandles(asIScriptEngine *engine) void **ptr = (void**)(((char*)this) + prop->byteOffset); if( *ptr ) { - asASSERT( (prop->type.GetObjectType()->flags & asOBJ_NOCOUNT) || prop->type.GetBehaviour()->release ); + asASSERT( (prop->type.GetTypeInfo()->flags & asOBJ_NOCOUNT) || prop->type.GetBehaviour()->release ); if( prop->type.GetBehaviour()->release ) ((asCScriptEngine*)engine)->CallObjectMethod(*ptr, prop->type.GetBehaviour()->release); *ptr = 0; } } + else if (prop->type.IsFuncdef()) + { + asCScriptFunction **ptr = (asCScriptFunction**)(((char*)this) + prop->byteOffset); + if (*ptr) + { + (*ptr)->Release(); + *ptr = 0; + } + } } } @@ -787,13 +808,23 @@ asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other) void **src = (void**)(((char*)&other) + prop->byteOffset); if( !prop->type.IsObjectHandle() ) { - if( prop->type.IsReference() || (prop->type.GetObjectType()->flags & asOBJ_REF) ) - CopyObject(*src, *dst, prop->type.GetObjectType(), engine); + if( prop->type.IsReference() || (prop->type.GetTypeInfo()->flags & asOBJ_REF) ) + CopyObject(*src, *dst, CastToObjectType(prop->type.GetTypeInfo()), engine); else - CopyObject(src, dst, prop->type.GetObjectType(), engine); + CopyObject(src, dst, CastToObjectType(prop->type.GetTypeInfo()), engine); } else - CopyHandle((asPWORD*)src, (asPWORD*)dst, prop->type.GetObjectType(), engine); + CopyHandle((asPWORD*)src, (asPWORD*)dst, CastToObjectType(prop->type.GetTypeInfo()), engine); + } + else if (prop->type.IsFuncdef()) + { + asCScriptFunction **dst = (asCScriptFunction**)(((char*)this) + prop->byteOffset); + asCScriptFunction **src = (asCScriptFunction**)(((char*)&other) + prop->byteOffset); + if (*dst) + (*dst)->Release(); + *dst = *src; + if (*dst) + (*dst)->AddRef(); } else { @@ -905,29 +936,29 @@ int asCScriptObject::CopyFrom(asIScriptObject *other) return 0; } -void *asCScriptObject::AllocateUninitializedObject(asCObjectType *objType, asCScriptEngine *engine) +void *asCScriptObject::AllocateUninitializedObject(asCObjectType *in_objType, asCScriptEngine *engine) { void *ptr = 0; - if( objType->flags & asOBJ_SCRIPT_OBJECT ) + if( in_objType->flags & asOBJ_SCRIPT_OBJECT ) { - ptr = engine->CallAlloc(objType); - ScriptObject_ConstructUnitialized(objType, reinterpret_cast(ptr)); + ptr = engine->CallAlloc(in_objType); + ScriptObject_ConstructUnitialized(in_objType, reinterpret_cast(ptr)); } - else if( objType->flags & asOBJ_TEMPLATE ) + else if( in_objType->flags & asOBJ_TEMPLATE ) { // Templates store the original factory that takes the object // type as a hidden parameter in the construct behaviour - ptr = engine->CallGlobalFunctionRetPtr(objType->beh.construct, objType); + ptr = engine->CallGlobalFunctionRetPtr(in_objType->beh.construct, in_objType); } - else if( objType->flags & asOBJ_REF ) + else if( in_objType->flags & asOBJ_REF ) { - ptr = engine->CallGlobalFunctionRetPtr(objType->beh.factory); + ptr = engine->CallGlobalFunctionRetPtr(in_objType->beh.factory); } else { - ptr = engine->CallAlloc(objType); - int funcIndex = objType->beh.construct; + ptr = engine->CallAlloc(in_objType); + int funcIndex = in_objType->beh.construct; if( funcIndex ) engine->CallObjectMethod(ptr, funcIndex); } @@ -935,52 +966,52 @@ void *asCScriptObject::AllocateUninitializedObject(asCObjectType *objType, asCSc return ptr; } -void asCScriptObject::FreeObject(void *ptr, asCObjectType *objType, asCScriptEngine *engine) +void asCScriptObject::FreeObject(void *ptr, asCObjectType *in_objType, asCScriptEngine *engine) { - if( objType->flags & asOBJ_REF ) + if( in_objType->flags & asOBJ_REF ) { - asASSERT( (objType->flags & asOBJ_NOCOUNT) || objType->beh.release ); - if( objType->beh.release ) - engine->CallObjectMethod(ptr, objType->beh.release); + asASSERT( (in_objType->flags & asOBJ_NOCOUNT) || in_objType->beh.release ); + if(in_objType->beh.release ) + engine->CallObjectMethod(ptr, in_objType->beh.release); } else { - if( objType->beh.destruct ) - engine->CallObjectMethod(ptr, objType->beh.destruct); + if( in_objType->beh.destruct ) + engine->CallObjectMethod(ptr, in_objType->beh.destruct); engine->CallFree(ptr); } } -void asCScriptObject::CopyObject(void *src, void *dst, asCObjectType *objType, asCScriptEngine *engine) +void asCScriptObject::CopyObject(void *src, void *dst, asCObjectType *in_objType, asCScriptEngine *engine) { - int funcIndex = objType->beh.copy; + int funcIndex = in_objType->beh.copy; if( funcIndex ) { - asCScriptFunction *func = engine->scriptFunctions[objType->beh.copy]; + asCScriptFunction *func = engine->scriptFunctions[in_objType->beh.copy]; if( func->funcType == asFUNC_SYSTEM ) engine->CallObjectMethod(dst, src, funcIndex); else { // Call the script class' opAssign method - asASSERT( objType->flags & asOBJ_SCRIPT_OBJECT ); + asASSERT(in_objType->flags & asOBJ_SCRIPT_OBJECT ); reinterpret_cast(dst)->CopyFrom(reinterpret_cast(src)); } } - else if( objType->size && (objType->flags & asOBJ_POD) ) - memcpy(dst, src, objType->size); + else if( in_objType->size && (in_objType->flags & asOBJ_POD) ) + memcpy(dst, src, in_objType->size); } -void asCScriptObject::CopyHandle(asPWORD *src, asPWORD *dst, asCObjectType *objType, asCScriptEngine *engine) +void asCScriptObject::CopyHandle(asPWORD *src, asPWORD *dst, asCObjectType *in_objType, asCScriptEngine *engine) { // asOBJ_NOCOUNT doesn't have addref or release behaviours - asASSERT( (objType->flags & asOBJ_NOCOUNT) || (objType->beh.release && objType->beh.addref) ); + asASSERT( (in_objType->flags & asOBJ_NOCOUNT) || (in_objType->beh.release && in_objType->beh.addref) ); - if( *dst && objType->beh.release ) - engine->CallObjectMethod(*(void**)dst, objType->beh.release); + if( *dst && in_objType->beh.release ) + engine->CallObjectMethod(*(void**)dst, in_objType->beh.release); *dst = *src; - if( *dst && objType->beh.addref ) - engine->CallObjectMethod(*(void**)dst, objType->beh.addref); + if( *dst && in_objType->beh.addref ) + engine->CallObjectMethod(*(void**)dst, in_objType->beh.addref); } // TODO: weak: Should move to its own file diff --git a/lib/angelscript/source/as_scriptobject.h b/lib/angelscript/source/as_scriptobject.h index dcdc5f371..7d357ec46 100644 --- a/lib/angelscript/source/as_scriptobject.h +++ b/lib/angelscript/source/as_scriptobject.h @@ -1,24 +1,24 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; you + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product + this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source + 3. This notice may not be removed or altered from any source distribution. The original version of this library can be located at: @@ -60,14 +60,14 @@ public: bool Get() const; void Set(bool); - + void Lock() const; void Unlock() const; protected: mutable asCAtomic refCount; bool value; - DECLARECRITICALSECTION(mutable lock); + DECLARECRITICALSECTION(mutable lock) }; class asCScriptObject : public asIScriptObject @@ -84,7 +84,7 @@ public: // Type info int GetTypeId() const; - asIObjectType *GetObjectType() const; + asITypeInfo *GetObjectType() const; // Class properties asUINT GetPropertyCount() const; @@ -137,7 +137,7 @@ protected: bool isDestructCalled; // Most script classes instances won't have neither the weakRefFlags nor - // userData so we only allocate this if requested. Even when used it is + // userData so we only allocate this if requested. Even when used it is // not something that will be accessed all the time so having the extra // indirection will not affect the performance significantly. struct SExtra diff --git a/lib/angelscript/source/as_string.cpp b/lib/angelscript/source/as_string.cpp index aaa280c23..8bd3edfe3 100644 --- a/lib/angelscript/source/as_string.cpp +++ b/lib/angelscript/source/as_string.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -283,20 +283,24 @@ size_t asCString::Format(const char *format, ...) va_list args; va_start(args, format); - char tmp[256]; - int r = asVSNPRINTF(tmp, 255, format, args); + const size_t startSize = 1024; + char tmp[startSize]; + int r = asVSNPRINTF(tmp, startSize-1, format, args); - if( r > 0 ) + if( r > 0 && r < int(startSize) ) { Assign(tmp, r); } else { - size_t n = 512; + // TODO: For some reason this doesn't work properly on Linux. Perhaps the + // problem is related to vsnprintf not keeping the state of va_arg. + // Perhaps I need to rewrite this in some way to keep the state + size_t n = startSize*2; asCString str; // Use temporary string in case the current buffer is a parameter str.Allocate(n, false); - while( (r = asVSNPRINTF(str.AddressOf(), n, format, args)) < 0 ) + while( (r = asVSNPRINTF(str.AddressOf(), n, format, args)) < 0 || r >= int(n) ) { n *= 2; str.Allocate(n, false); @@ -324,15 +328,15 @@ const char &asCString::operator [](size_t index) const return AddressOf()[index]; } -asCString asCString::SubString(size_t start, size_t length) const +asCString asCString::SubString(size_t in_start, size_t in_length) const { - if( start >= GetLength() || length == 0 ) + if( in_start >= GetLength() || in_length == 0 ) return asCString(""); - if( length == (size_t)(-1) ) length = GetLength() - start; + if( in_length == (size_t)(-1) ) in_length = GetLength() - in_start; asCString tmp; - tmp.Assign(AddressOf() + start, length); + tmp.Assign(AddressOf() + in_start, in_length); return tmp; } diff --git a/lib/angelscript/source/as_string_util.cpp b/lib/angelscript/source/as_string_util.cpp index 8ee210dc5..32edbedb0 100644 --- a/lib/angelscript/source/as_string_util.cpp +++ b/lib/angelscript/source/as_string_util.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2013 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -171,17 +171,24 @@ static int asCharToNbr(char ch, int radix) } // If base is 0 the string should be prefixed by 0x, 0d, 0o, or 0b to allow the function to automatically determine the radix -asQWORD asStringScanUInt64(const char *string, int base, size_t *numScanned) +asQWORD asStringScanUInt64(const char *string, int base, size_t *numScanned, bool *overflow) { asASSERT(base == 10 || base == 16 || base == 0); + if (overflow) + *overflow = false; + const char *end = string; + static const asQWORD QWORD_MAX = (~asQWORD(0)); + asQWORD res = 0; if( base == 10 ) { while( *end >= '0' && *end <= '9' ) { + if( overflow && ((res > QWORD_MAX / 10) || ((asUINT(*end - '0') > (QWORD_MAX - (QWORD_MAX / 10) * 10)) && res == QWORD_MAX / 10)) ) + *overflow = true; res *= 10; res += *end++ - '0'; } @@ -205,8 +212,13 @@ asQWORD asStringScanUInt64(const char *string, int base, size_t *numScanned) if( base ) { - for( int nbr; (nbr = asCharToNbr(*end, base)) >= 0; end++ ) + for (int nbr; (nbr = asCharToNbr(*end, base)) >= 0; end++) + { + if (overflow && ((res > QWORD_MAX / base) || ((asUINT(nbr) > (QWORD_MAX - (QWORD_MAX / base) * base)) && res == QWORD_MAX / base)) ) + *overflow = true; + res = res * base + nbr; + } } } diff --git a/lib/angelscript/source/as_string_util.h b/lib/angelscript/source/as_string_util.h index 788e3d4b2..29174dfb8 100644 --- a/lib/angelscript/source/as_string_util.h +++ b/lib/angelscript/source/as_string_util.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2011 Andreas Jonsson + Copyright (c) 2003-2016 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -39,7 +39,7 @@ BEGIN_AS_NAMESPACE int asCompareStrings(const char *str1, size_t len1, const char *str2, size_t len2); double asStringScanDouble(const char *string, size_t *numScanned); -asQWORD asStringScanUInt64(const char *string, int base, size_t *numScanned); +asQWORD asStringScanUInt64(const char *string, int base, size_t *numScanned, bool *overflow); int asStringEncodeUTF8(unsigned int value, char *outEncodedBuffer); int asStringDecodeUTF8(const char *encodedBuffer, unsigned int *outLength); diff --git a/lib/angelscript/source/as_texts.h b/lib/angelscript/source/as_texts.h index b43648b16..6814ae0f3 100644 --- a/lib/angelscript/source/as_texts.h +++ b/lib/angelscript/source/as_texts.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -105,6 +105,8 @@ #define TXT_EXPECTED_STRING "Expected string" #define TXT_EXPR_DOESNT_EVAL_TO_FUNC "Expression doesn't evaluate to a function" #define TXT_EXPR_MUST_BE_BOOL "Expression must be of boolean type" +#define TXT_EXTERNAL_SHARED_s_NOT_FOUND "External shared entity '%s' not found" +#define TXT_EXTERNAL_SHARED_s_CANNOT_REDEF "External shared entity '%s' cannot redefine the original entity" #define TXT_FAILED_TO_COMPILE_DEF_ARG_d_IN_FUNC_s "Failed while compiling default arg for parameter %d in function '%s'" #define TXT_FAILED_TO_CREATE_TEMP_OBJ "Previous error occurred while attempting to create a temporary copy of object" @@ -135,6 +137,8 @@ #define TXT_INIT_LIST_CANNOT_BE_USED_WITH_s "Initialization lists cannot be used with '%s'" #define TXT_INSTANCING_INVLD_TMPL_TYPE_s_s "Attempting to instantiate invalid template type '%s<%s>'" #define TXT_INSTEAD_FOUND_s "Instead found '%s'" +#define TXT_INSTEAD_FOUND_IDENTIFIER_s "Instead found identifier '%s'" +#define TXT_INSTEAD_FOUND_KEYWORD_s "Instead found reserved keyword '%s'" #define TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED "Interface '%s' cannot be instantiated" #define TXT_INTERFACE_CAN_ONLY_IMPLEMENT_INTERFACE "Interfaces can only implement other interfaces" #define TXT_INVALID_BREAK "Invalid 'break'" @@ -150,15 +154,18 @@ #define TXT_INVALID_UNICODE_FORMAT_EXPECTED_d "Invalid unicode escape sequence, expected %d hex digits" #define TXT_INVALID_UNICODE_VALUE "Invalid unicode code point" #define TXT_INVALID_UNICODE_SEQUENCE_IN_SRC "Invalid unicode sequence in source" +#define TXT_INVALID_USE_OF_NAMED_ARGS "Invalid use of named arguments" #define TXT_METHOD_CANNOT_OVERRIDE_s "Method '%s' declared as final and cannot be overridden" #define TXT_METHOD_CANT_HAVE_NAME_OF_CLASS "The method cannot be named with the class name" #define TXT_METHOD_s_DOES_NOT_OVERRIDE "Method '%s' marked as override but does not replace any base class or interface method" #define TXT_METHOD_s_s_HAS_NO_RETURN_TYPE "Method '%s::%s' is missing the return type, nor is it the same name as object to be a constructor" #define TXT_MISSING_IMPLEMENTATION_OF_s "Missing implementation of '%s'" +#define TXT_MISSING_DEFINITION_OF_s "Missing definition of '%s'" #define TXT_MIXIN_CANNOT_BE_DECLARED_AS_s "Mixin class cannot be declared as '%s'" #define TXT_MIXIN_CANNOT_HAVE_CONSTRUCTOR "Mixin classes cannot have constructors or destructors" #define TXT_MIXIN_CLASS_CANNOT_INHERIT "Mixin class cannot inherit from classes" +#define TXT_MIXIN_CANNOT_HAVE_CHILD_TYPES "Mixin classes cannot have child types" #define TXT_MORE_THAN_ONE_MATCHING_OP "Found more than one matching operator" #define TXT_MULTIPLE_MATCHING_SIGNATURES_TO_s "Multiple matching signatures to '%s'" #define TXT_MULTIPLE_PROP_GET_ACCESSOR_FOR_s "Found multiple get accessors for property '%s'" @@ -192,7 +199,7 @@ #define TXT_NO_MATCHING_OP_FOUND_FOR_TYPES_s_AND_s "No matching operator that takes the types '%s' and '%s' found" #define TXT_NON_CONST_METHOD_ON_CONST_OBJ "Non-const method call on read-only object reference" #define TXT_NONTERMINATED_STRING "Non-terminated string literal" -#define TXT_NOT_A_FUNC_s_IS_VAR "Expression doesn't form a function call. '%s' is a variable of a non-function type" +#define TXT_NOT_A_FUNC_s_IS_TYPE_s "Expression doesn't form a function call. '%s' evaluates to the non-function type '%s'" #define TXT_NOT_ALL_PATHS_RETURN "Not all paths return a value" #define TXT_NOT_ENOUGH_VALUES_FOR_LIST "Not enough values to match pattern" #define TXT_s_NOT_DECLARED "'%s' is not declared" @@ -216,10 +223,12 @@ #define TXT_PARAMETER_ALREADY_DECLARED "Parameter already declared" #define TXT_PARAMETER_CANT_BE_s "Parameter type can't be '%s', because the type cannot be instantiated." #define TXT_POS_ARG_AFTER_NAMED_ARG "Positional arguments cannot be passed after named arguments" +#define TXT_PREV_ERROR_WHILE_COMP_LIST_FOR_TYPE_s "Previous error occurred while attempting to compile initialization list for type '%s'" #define TXT_PRIVATE_METHOD_CALL_s "Illegal call to private method '%s'" #define TXT_PRIVATE_PROP_ACCESS_s "Illegal access to private property '%s'" #define TXT_PROTECTED_METHOD_CALL_s "Illegal call to protected method '%s'" #define TXT_PROTECTED_PROP_ACCESS_s "Illegal access to protected property '%s'" +#define TXT_PROP_ACCESS_WITH_INDEX_ONE_ARG "Property accessor with index must have 1 and only 1 index argument" #define TXT_PROPERTY_ACCESSOR_DISABLED "Property accessors have been disabled by the application" #define TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED "Property accessor must be implemented" #define TXT_PROPERTY_CANT_BE_CONST "Class properties cannot be declared as const" @@ -252,6 +261,7 @@ #define TXT_TMPL_SUBTYPE_MUST_NOT_BE_READ_ONLY "Template subtype must not be read-only" #define TXT_TOO_MANY_JUMP_LABELS "The function has too many jump labels to handle. Split the function into smaller ones." #define TXT_TOO_MANY_VALUES_FOR_LIST "Too many values to match pattern" +#define TXT_TYPE_s_CANNOT_BE_REFERENCE "Type '%s' cannot be a reference" #define TXT_TYPE_s_NOT_AVAILABLE_FOR_MODULE "Type '%s' is not available for this module" #define TXT_TYPE_s_NOT_TEMPLATE "Type '%s' is not a template type" @@ -291,7 +301,7 @@ #define TXT_GC_REQUIRE_ADD_REL_GC_BEHAVIOUR "A garbage collected type must have the addref, release, and all gc behaviours" #define TXT_SCOPE_REQUIRE_REL_BEHAVIOUR "A scoped reference type must have the release behaviour" #define TXT_REF_REQUIRE_ADD_REL_BEHAVIOUR "A reference type must have the addref and release behaviours" -#define TXT_NON_POD_REQUIRE_CONSTR_DESTR_BEHAVIOUR "A non-pod value type must have the default constructor and destructor behaviours" +#define TXT_NON_POD_REQUIRE_CONSTR_DESTR_BEHAVIOUR "A non-pod value type must have at least one constructor and the destructor behaviours" #define TXT_CANNOT_PASS_TYPE_s_BY_VAL "Can't pass type '%s' by value unless the application type is informed in the registration" #define TXT_CANNOT_RET_TYPE_s_BY_VAL "Can't return type '%s' by value unless the application type is informed in the registration" // TODO: Should be something like "This platform requires that AngelScript knows the exact content of the type '%s' in order to pass by value to application in native calling convention" @@ -341,5 +351,6 @@ #define TXT_OUT_OF_BOUNDS "Out of range" #define TXT_EXCEPTION_CAUGHT "Caught an exception from the application" #define TXT_MISMATCH_IN_VALUE_ASSIGN "Mismatching types in value assignment" +#define TXT_TOO_MANY_NESTED_CALLS "Too many nested calls" #endif diff --git a/lib/angelscript/source/as_thread.h b/lib/angelscript/source/as_thread.h index f4abf88a1..813d4c0f0 100644 --- a/lib/angelscript/source/as_thread.h +++ b/lib/angelscript/source/as_thread.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -80,7 +80,7 @@ protected: #else asDWORD tlsKey; #endif - DECLARECRITICALSECTION(criticalSection); + DECLARECRITICALSECTION(criticalSection) #else asCThreadLocalData *tld; #endif diff --git a/lib/angelscript/source/as_tokendef.h b/lib/angelscript/source/as_tokendef.h index a88d2605a..0ad6d4a4d 100644 --- a/lib/angelscript/source/as_tokendef.h +++ b/lib/angelscript/source/as_tokendef.h @@ -1,24 +1,24 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; you + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product + this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source + 3. This notice may not be removed or altered from any source distribution. The original version of this library can be located at: @@ -244,7 +244,7 @@ sTokenWord const tokenWords[] = asTokenDef("auto" , ttAuto), asTokenDef("bool" , ttBool), asTokenDef("break" , ttBreak), - asTokenDef("case" , ttCase), + asTokenDef("case" , ttCase), asTokenDef("cast" , ttCast), asTokenDef("class" , ttClass), asTokenDef("const" , ttConst), @@ -269,7 +269,7 @@ sTokenWord const tokenWords[] = asTokenDef("int" , ttInt), asTokenDef("int8" , ttInt8), asTokenDef("int16" , ttInt16), - asTokenDef("int32" , ttInt), + asTokenDef("int32" , ttInt), asTokenDef("int64" , ttInt64), asTokenDef("interface" , ttInterface), asTokenDef("is" , ttIs), @@ -302,16 +302,18 @@ const char * const whiteSpace = " \t\r\n"; // Some keywords that are not considered tokens by the parser // These only have meaning in specific situations. Outside these // situations they are treated as normal identifiers. -const char * const THIS_TOKEN = "this"; -const char * const FROM_TOKEN = "from"; -const char * const SUPER_TOKEN = "super"; -const char * const SHARED_TOKEN = "shared"; -const char * const FINAL_TOKEN = "final"; -const char * const OVERRIDE_TOKEN = "override"; -const char * const GET_TOKEN = "get"; -const char * const SET_TOKEN = "set"; -const char * const ABSTRACT_TOKEN = "abstract"; -const char * const FUNCTION_TOKEN = "function"; +const char * const THIS_TOKEN = "this"; +const char * const FROM_TOKEN = "from"; +const char * const SUPER_TOKEN = "super"; +const char * const SHARED_TOKEN = "shared"; +const char * const FINAL_TOKEN = "final"; +const char * const OVERRIDE_TOKEN = "override"; +const char * const GET_TOKEN = "get"; +const char * const SET_TOKEN = "set"; +const char * const ABSTRACT_TOKEN = "abstract"; +const char * const FUNCTION_TOKEN = "function"; +const char * const IF_HANDLE_TOKEN = "if_handle_then_const"; +const char * const EXTERNAL_TOKEN = "external"; END_AS_NAMESPACE diff --git a/lib/angelscript/source/as_tokenizer.cpp b/lib/angelscript/source/as_tokenizer.cpp index 82c1b80e0..2017a12ec 100644 --- a/lib/angelscript/source/as_tokenizer.cpp +++ b/lib/angelscript/source/as_tokenizer.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2014 Andreas Jonsson + Copyright (c) 2003-2015 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -395,20 +395,27 @@ bool asCTokenizer::IsConstant(const char *source, size_t sourceLength, size_t &t bool asCTokenizer::IsIdentifier(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const { + // char is unsigned by default on some architectures, e.g. ppc and arm + // Make sure the value is always treated as signed in the below comparisons + signed char c = source[0]; + // Starting with letter or underscore - if( (source[0] >= 'a' && source[0] <= 'z') || - (source[0] >= 'A' && source[0] <= 'Z') || - source[0] == '_' ) + if( (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c == '_' || + (c < 0 && engine->ep.allowUnicodeIdentifiers) ) { tokenType = ttIdentifier; tokenLength = 1; for( size_t n = 1; n < sourceLength; n++ ) { - if( (source[n] >= 'a' && source[n] <= 'z') || - (source[n] >= 'A' && source[n] <= 'Z') || - (source[n] >= '0' && source[n] <= '9') || - source[n] == '_' ) + c = source[n]; + if( (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c == '_' || + (c < 0 && engine->ep.allowUnicodeIdentifiers) ) tokenLength++; else break; diff --git a/lib/angelscript/source/as_typeinfo.cpp b/lib/angelscript/source/as_typeinfo.cpp index 230aff05f..f407ecc73 100644 --- a/lib/angelscript/source/as_typeinfo.cpp +++ b/lib/angelscript/source/as_typeinfo.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -32,13 +32,9 @@ // // as_typeinfo.cpp // -// This class holds extra type info for the compiler -// + #include "as_config.h" - -#ifndef AS_NO_COMPILER - #include "as_typeinfo.h" #include "as_scriptengine.h" @@ -46,144 +42,434 @@ BEGIN_AS_NAMESPACE asCTypeInfo::asCTypeInfo() { - isTemporary = false; - stackOffset = 0; - isConstant = false; - isVariable = false; - isExplicitHandle = false; - qwordValue = 0; - isLValue = false; - isRefToLocal = false; + externalRefCount.set(0); + internalRefCount.set(1); // start with one internal ref-count + engine = 0; + module = 0; + size = 0; + flags = 0; + typeId = -1; // start as -1 to signal that it hasn't been defined + + scriptSectionIdx = -1; + declaredAt = 0; + + accessMask = 0xFFFFFFFF; + nameSpace = 0; } -void asCTypeInfo::Set(const asCDataType &dt) +asCTypeInfo::asCTypeInfo(asCScriptEngine *in_engine) { - dataType = dt; + externalRefCount.set(0); + internalRefCount.set(1); // start with one internal ref count + engine = in_engine; + module = 0; + size = 0; + flags = 0; + typeId = -1; // start as -1 to signal that it hasn't been defined - isTemporary = false; - stackOffset = 0; - isConstant = false; - isVariable = false; - isExplicitHandle = false; - qwordValue = 0; - isLValue = false; - isRefToLocal = false; + scriptSectionIdx = -1; + declaredAt = 0; + + accessMask = 0xFFFFFFFF; + nameSpace = engine->nameSpaces[0]; } -void asCTypeInfo::SetVariable(const asCDataType &dt, int stackOffset, bool isTemporary) +asCTypeInfo::~asCTypeInfo() { - Set(dt); - - this->isVariable = true; - this->isTemporary = isTemporary; - this->stackOffset = (short)stackOffset; } -void asCTypeInfo::SetConstantQW(const asCDataType &dt, asQWORD value) +// interface +int asCTypeInfo::AddRef() const { - Set(dt); - - isConstant = true; - qwordValue = value; + return externalRefCount.atomicInc(); } -void asCTypeInfo::SetConstantDW(const asCDataType &dt, asDWORD value) +// interface +int asCTypeInfo::Release() const { - Set(dt); + int r = externalRefCount.atomicDec(); - isConstant = true; - dwordValue = value; + if (r == 0) + { + // There are no more external references, if there are also no + // internal references then it is time to delete the object type + if (internalRefCount.get() == 0) + { + // If the engine is no longer set, then it has already been + // released and we must take care of the deletion ourselves + asDELETE(const_cast(this), asCTypeInfo); + } + } + + return r; } -void asCTypeInfo::SetConstantB(const asCDataType &dt, asBYTE value) +int asCTypeInfo::AddRefInternal() { - Set(dt); - - isConstant = true; - byteValue = value; + return internalRefCount.atomicInc(); } -void asCTypeInfo::SetConstantF(const asCDataType &dt, float value) +int asCTypeInfo::ReleaseInternal() { - Set(dt); + int r = internalRefCount.atomicDec(); - isConstant = true; - floatValue = value; + if (r == 0) + { + // There are no more internal references, if there are also no + // external references then it is time to delete the object type + if (externalRefCount.get() == 0) + { + // If the engine is no longer set, then it has already been + // released and we must take care of the deletion ourselves + asDELETE(const_cast(this), asCTypeInfo); + } + } + + return r; } -void asCTypeInfo::SetConstantD(const asCDataType &dt, double value) +// interface +asIScriptModule *asCTypeInfo::GetModule() const { - Set(dt); - - isConstant = true; - doubleValue = value; + return module; } -void asCTypeInfo::SetUndefinedFuncHandle(asCScriptEngine *engine) +void *asCTypeInfo::SetUserData(void *data, asPWORD type) { - // This is used for when the expression evaluates to a - // function, but it is not yet known exactly which. The - // owner expression will hold the name of the function - // to determine the exact function when the signature is - // known. - Set(asCDataType::CreateObjectHandle(&engine->functionBehaviours, true)); - isConstant = true; - isExplicitHandle = false; - qwordValue = 1; // Set to a different value than 0 to differentiate from null constant - isLValue = false; + // As a thread might add a new new user data at the same time as another + // it is necessary to protect both read and write access to the userData member + ACQUIREEXCLUSIVE(engine->engineRWLock); + + // It is not intended to store a lot of different types of userdata, + // so a more complex structure like a associative map would just have + // more overhead than a simple array. + for (asUINT n = 0; n < userData.GetLength(); n += 2) + { + if (userData[n] == type) + { + void *oldData = reinterpret_cast(userData[n + 1]); + userData[n + 1] = reinterpret_cast(data); + + RELEASEEXCLUSIVE(engine->engineRWLock); + + return oldData; + } + } + + userData.PushLast(type); + userData.PushLast(reinterpret_cast(data)); + + RELEASEEXCLUSIVE(engine->engineRWLock); + + return 0; } -bool asCTypeInfo::IsUndefinedFuncHandle() const +void *asCTypeInfo::GetUserData(asPWORD type) const { - if( isConstant == false ) return false; - if( qwordValue == 0 ) return false; - if( isLValue ) return false; - if( dataType.GetObjectType() == 0 ) return false; - if( dataType.GetObjectType()->name != "$func" ) return false; - if( dataType.GetFuncDef() ) return false; + // There may be multiple threads reading, but when + // setting the user data nobody must be reading. + ACQUIRESHARED(engine->engineRWLock); + for (asUINT n = 0; n < userData.GetLength(); n += 2) + { + if (userData[n] == type) + { + RELEASESHARED(engine->engineRWLock); + return reinterpret_cast(userData[n + 1]); + } + } + + RELEASESHARED(engine->engineRWLock); + + return 0; +} + +// interface +const char *asCTypeInfo::GetName() const +{ + return name.AddressOf(); +} + +// interface +const char *asCTypeInfo::GetNamespace() const +{ + if( nameSpace ) + return nameSpace->name.AddressOf(); + + return 0; +} + +// interface +asDWORD asCTypeInfo::GetFlags() const +{ + return flags; +} + +// interface +asUINT asCTypeInfo::GetSize() const +{ + return size; +} + +// interface +int asCTypeInfo::GetTypeId() const +{ + if (typeId == -1) + { + // We need a non const pointer to create the asCDataType object. + // We're not breaking anything here because this function is not + // modifying the object, so this const cast is safe. + asCTypeInfo *ot = const_cast(this); + + // The engine will define the typeId for this object type + engine->GetTypeIdFromDataType(asCDataType::CreateType(ot, false)); + } + + return typeId; +} + +// interface +asIScriptEngine *asCTypeInfo::GetEngine() const +{ + return engine; +} + +// interface +const char *asCTypeInfo::GetConfigGroup() const +{ + asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(this); + if (group == 0) + return 0; + + return group->groupName.AddressOf(); +} + +// interface +asDWORD asCTypeInfo::GetAccessMask() const +{ + return accessMask; +} + +// interface +int asCTypeInfo::GetProperty(asUINT index, const char **out_name, int *out_typeId, bool *out_isPrivate, bool *out_isProtected, int *out_offset, bool *out_isReference, asDWORD *out_accessMask, int *out_compositeOffset, bool *out_isCompositeIndirect) const +{ + UNUSED_VAR(index); + if (out_name) *out_name = 0; + if (out_typeId) *out_typeId = 0; + if (out_isPrivate) *out_isPrivate = false; + if (out_isProtected) *out_isProtected = false; + if (out_offset) *out_offset = 0; + if (out_isReference) *out_isReference = false; + if (out_accessMask) *out_accessMask = 0; + if (out_compositeOffset) *out_compositeOffset = 0; + if (out_isCompositeIndirect) *out_isCompositeIndirect = false; + return -1; +} + +// internal +asCObjectType *CastToObjectType(asCTypeInfo *ti) +{ + // Allow call on null pointer + if (ti == 0) return 0; + + // TODO: type: Should List pattern have its own type class? + if ((ti->flags & (asOBJ_VALUE | asOBJ_REF | asOBJ_LIST_PATTERN)) && !(ti->flags & asOBJ_FUNCDEF)) + return reinterpret_cast(ti); + + return 0; +} + +// internal +asCEnumType *CastToEnumType(asCTypeInfo *ti) +{ + // Allow call on null pointer + if (ti == 0) return 0; + + if (ti->flags & (asOBJ_ENUM)) + return reinterpret_cast(ti); + + return 0; +} + +// internal +asCTypedefType *CastToTypedefType(asCTypeInfo *ti) +{ + // Allow call on null pointer + if (ti == 0) return 0; + + if (ti->flags & (asOBJ_TYPEDEF)) + return reinterpret_cast(ti); + + return 0; +} + +// internal +asCFuncdefType *CastToFuncdefType(asCTypeInfo *ti) +{ + // Allow call on null pointer + if (ti == 0) return 0; + + if (ti->flags & (asOBJ_FUNCDEF)) + return reinterpret_cast(ti); + + return 0; +} + +// internal +void asCTypeInfo::CleanUserData() +{ + asASSERT(engine); + for (asUINT n = 0; n < userData.GetLength(); n += 2) + { + if (userData[n + 1]) + { + for (asUINT c = 0; c < engine->cleanTypeInfoFuncs.GetLength(); c++) + if (engine->cleanTypeInfoFuncs[c].type == userData[n]) + engine->cleanTypeInfoFuncs[c].cleanFunc(this); + } + } + userData.SetLength(0); +} + +// internal +bool asCTypeInfo::IsShared() const +{ + // Types that can be declared by scripts need to have the explicit flag asOBJ_SHARED + if (flags & (asOBJ_SCRIPT_OBJECT | asOBJ_ENUM)) return flags & asOBJ_SHARED ? true : false; + + // Otherwise we assume the type to be shared return true; } -void asCTypeInfo::SetNullConstant() +//////////////////////////////////////////////////////////////////////////////////////// + +asCEnumType::~asCEnumType() { - Set(asCDataType::CreateNullHandle()); - isConstant = true; - isExplicitHandle = false; - qwordValue = 0; - isLValue = false; + asUINT n; + for (n = 0; n < enumValues.GetLength(); n++) + { + if (enumValues[n]) + asDELETE(enumValues[n], asSEnumValue); + } + enumValues.SetLength(0); } -bool asCTypeInfo::IsNullConstant() const +// interface +asUINT asCEnumType::GetEnumValueCount() const { - // We can't check the actual object type, because the null constant may have been cast to another type - if( isConstant && dataType.IsObjectHandle() && qwordValue == 0 ) - return true; - - return false; + return enumValues.GetLength(); } -void asCTypeInfo::SetVoid() +// interface +const char *asCEnumType::GetEnumValueByIndex(asUINT index, int *outValue) const { - Set(asCDataType::CreatePrimitive(ttVoid, false)); - isLValue = false; - isConstant = true; + if (outValue) + *outValue = 0; + + if (index >= enumValues.GetLength()) + return 0; + + if (outValue) + *outValue = enumValues[index]->value; + + return enumValues[index]->name.AddressOf(); } -bool asCTypeInfo::IsVoid() const -{ - if( dataType.GetTokenType() == ttVoid ) - return true; +////////////////////////////////////////////////////////////////////////////////////////// - return false; +asCTypedefType::~asCTypedefType() +{ + DestroyInternal(); } -void asCTypeInfo::SetDummy() +void asCTypedefType::DestroyInternal() { - SetConstantQW(asCDataType::CreatePrimitive(ttInt, true), 0); + if (engine == 0) return; + + // Release the object types held by the alias + if (aliasForType.GetTypeInfo()) + aliasForType.GetTypeInfo()->ReleaseInternal(); + + aliasForType = asCDataType::CreatePrimitive(ttVoid, false); + + CleanUserData(); + + // Remove the type from the engine + if (typeId != -1) + engine->RemoveFromTypeIdMap(this); + + // Clear the engine pointer to mark the object type as invalid + engine = 0; } +// interface +int asCTypedefType::GetTypedefTypeId() const +{ + return engine->GetTypeIdFromDataType(aliasForType); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +asCFuncdefType::asCFuncdefType(asCScriptEngine *en, asCScriptFunction *func) : asCTypeInfo(en) +{ + asASSERT(func->funcType == asFUNC_FUNCDEF); + asASSERT(func->funcdefType == 0); + + // A function pointer is special kind of reference type + flags = asOBJ_REF | asOBJ_FUNCDEF | (func->IsShared() ? asOBJ_SHARED : 0); + name = func->name; + nameSpace = func->nameSpace; + module = func->module; + accessMask = func->accessMask; + funcdef = func; // reference already counted by the asCScriptFunction constructor + parentClass = 0; + + func->funcdefType = this; +} + +asCFuncdefType::~asCFuncdefType() +{ + DestroyInternal(); +} + +void asCFuncdefType::DestroyInternal() +{ + if (engine == 0) return; + + // Release the funcdef + if( funcdef ) + funcdef->ReleaseInternal(); + funcdef = 0; + + // Detach from parent class + if (parentClass) + { + parentClass->childFuncDefs.RemoveValue(this); + parentClass = 0; + } + + CleanUserData(); + + // Remove the type from the engine + if (typeId != -1) + engine->RemoveFromTypeIdMap(this); + + // Clear the engine pointer to mark the object type as invalid + engine = 0; +} + +// interface +asIScriptFunction *asCFuncdefType::GetFuncdefSignature() const +{ + return funcdef; +} + +// interface +asITypeInfo *asCFuncdefType::GetParentType() const +{ + return parentClass; +} END_AS_NAMESPACE -#endif // AS_NO_COMPILER + diff --git a/lib/angelscript/source/as_typeinfo.h b/lib/angelscript/source/as_typeinfo.h index 724411e82..a5643dda5 100644 --- a/lib/angelscript/source/as_typeinfo.h +++ b/lib/angelscript/source/as_typeinfo.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2015 Andreas Jonsson + Copyright (c) 2003-2017 Andreas Jonsson This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any @@ -32,8 +32,6 @@ // // as_typeinfo.h // -// This class holds extra type info for the compiler -// @@ -41,56 +39,204 @@ #define AS_TYPEINFO_H #include "as_config.h" - -#ifndef AS_NO_COMPILER - +#include "as_string.h" +#include "as_atomic.h" #include "as_datatype.h" BEGIN_AS_NAMESPACE -struct asCTypeInfo +class asCScriptEngine; +class asCModule; +class asCObjectType; +class asCEnumType; +class asCTypedefType; +class asCFuncdefType; +struct asSNameSpace; + +// TODO: type: asCPrimitiveType shall be implemented to represent primitives (void, int, double, etc) + +// TODO: type: asCTypeInfo should have an internal virtual method GetBehaviours. For asCObjectType it +// should return the beh member. For asCFuncdefType it should return the beh member of +// engine->functionBehaviours. This will allow the code that needs the behaviour to handle +// both object types and funcdefs the same way + +class asCTypeInfo : public asITypeInfo { +public: + //===================================== + // From asITypeInfo + //===================================== + asIScriptEngine *GetEngine() const; + const char *GetConfigGroup() const; + asDWORD GetAccessMask() const; + asIScriptModule *GetModule() const; + + // Memory management + int AddRef() const; + int Release() const; + + // Type info + const char *GetName() const; + const char *GetNamespace() const; + asITypeInfo *GetBaseType() const { return 0; } + bool DerivesFrom(const asITypeInfo *objType) const { UNUSED_VAR(objType); return 0; } + asDWORD GetFlags() const; + asUINT GetSize() const; + int GetTypeId() const; + int GetSubTypeId(asUINT subtypeIndex = 0) const { UNUSED_VAR(subtypeIndex); return -1; } + asITypeInfo *GetSubType(asUINT subtypeIndex = 0) const { UNUSED_VAR(subtypeIndex); return 0; } + asUINT GetSubTypeCount() const { return 0; } + + // Interfaces + asUINT GetInterfaceCount() const { return 0; } + asITypeInfo *GetInterface(asUINT index) const { UNUSED_VAR(index); return 0; } + bool Implements(const asITypeInfo *objType) const { UNUSED_VAR(objType); return false; } + + // Factories + asUINT GetFactoryCount() const { return 0; } + asIScriptFunction *GetFactoryByIndex(asUINT index) const { UNUSED_VAR(index); return 0; } + asIScriptFunction *GetFactoryByDecl(const char *decl) const { UNUSED_VAR(decl); return 0; } + + // Methods + asUINT GetMethodCount() const { return 0; } + asIScriptFunction *GetMethodByIndex(asUINT index, bool getVirtual) const { UNUSED_VAR(index); UNUSED_VAR(getVirtual); return 0; } + asIScriptFunction *GetMethodByName(const char *in_name, bool getVirtual) const { UNUSED_VAR(in_name); UNUSED_VAR(getVirtual); return 0; } + asIScriptFunction *GetMethodByDecl(const char *decl, bool getVirtual) const { UNUSED_VAR(decl); UNUSED_VAR(getVirtual); return 0; } + + // Properties + asUINT GetPropertyCount() const { return 0; } + int GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, bool *isProtected, int *offset, bool *isReference, asDWORD *accessMask, int *compositeOffset, bool *isCompositeIndirect) const; + const char *GetPropertyDeclaration(asUINT index, bool includeNamespace = false) const { UNUSED_VAR(index); UNUSED_VAR(includeNamespace); return 0; } + + // Behaviours + asUINT GetBehaviourCount() const { return 0; } + asIScriptFunction *GetBehaviourByIndex(asUINT index, asEBehaviours *outBehaviour) const { UNUSED_VAR(index); UNUSED_VAR(outBehaviour); return 0; } + + // Child types + asUINT GetChildFuncdefCount() const { return 0; } + asITypeInfo *GetChildFuncdef(asUINT index) const { UNUSED_VAR(index); return 0; } + asITypeInfo *GetParentType() const { return 0; } + + // Enums + virtual asUINT GetEnumValueCount() const { return 0; } + virtual const char *GetEnumValueByIndex(asUINT index, int *outValue) const { UNUSED_VAR(index); if (outValue) *outValue = 0; return 0; } + + // Typedef + virtual int GetTypedefTypeId() const { return asERROR; } + + // Funcdef + virtual asIScriptFunction *GetFuncdefSignature() const { return 0; } + + // User data + void *SetUserData(void *data, asPWORD type); + void *GetUserData(asPWORD type) const; + + //=========================================== + // Internal + //=========================================== +public: + asCTypeInfo(asCScriptEngine *engine); + virtual ~asCTypeInfo(); + + // Keep an internal reference counter to separate references coming from + // application or script objects and references coming from the script code + virtual int AddRefInternal(); + virtual int ReleaseInternal(); + + virtual void DestroyInternal() {} + + void CleanUserData(); + + bool IsShared() const; + + // These can be safely used on null pointers (which will return null) + friend asCObjectType *CastToObjectType(asCTypeInfo *); + friend asCEnumType *CastToEnumType(asCTypeInfo *); + friend asCTypedefType *CastToTypedefType(asCTypeInfo *); + friend asCFuncdefType *CastToFuncdefType(asCTypeInfo *); + + + asCString name; + asSNameSpace *nameSpace; + int size; + mutable int typeId; + asDWORD flags; + asDWORD accessMask; + + // Store the script section where the code was declared + int scriptSectionIdx; + // Store the location where the function was declared (row in the lower 20 bits, and column in the upper 12) + int declaredAt; + + asCScriptEngine *engine; + asCModule *module; + asCArray userData; + +protected: + friend class asCScriptEngine; + friend class asCConfigGroup; + friend class asCModule; + friend class asCObjectType; asCTypeInfo(); - void Set(const asCDataType &dataType); - void SetVariable(const asCDataType &dataType, int stackOffset, bool isTemporary); - void SetConstantB(const asCDataType &dataType, asBYTE value); - void SetConstantQW(const asCDataType &dataType, asQWORD value); - void SetConstantDW(const asCDataType &dataType, asDWORD value); - void SetConstantF(const asCDataType &dataType, float value); - void SetConstantD(const asCDataType &dataType, double value); - void SetNullConstant(); - void SetUndefinedFuncHandle(asCScriptEngine *engine); - void SetVoid(); - void SetDummy(); + mutable asCAtomic externalRefCount; + asCAtomic internalRefCount; +}; - bool IsUndefinedFuncHandle() const; - bool IsNullConstant() const; - bool IsVoid() const; +struct asSEnumValue +{ + asCString name; + int value; +}; - asCDataType dataType; - bool isLValue : 1; // Can this value be updated in assignment, or increment operators, etc - bool isTemporary : 1; - bool isConstant : 1; - bool isVariable : 1; - bool isExplicitHandle : 1; - bool isRefToLocal : 1; // The reference may be to a local variable - short dummy : 10; - short stackOffset; - union - { - asQWORD qwordValue; - double doubleValue; - asDWORD dwordValue; - float floatValue; - int intValue; - asWORD wordValue; - asBYTE byteValue; - }; +class asCEnumType : public asCTypeInfo +{ +public: + asCEnumType(asCScriptEngine *engine) : asCTypeInfo(engine) {} + ~asCEnumType(); + + asCArray enumValues; + + asUINT GetEnumValueCount() const; + const char *GetEnumValueByIndex(asUINT index, int *outValue) const; + +protected: + asCEnumType() : asCTypeInfo() {} +}; + +class asCTypedefType : public asCTypeInfo +{ +public: + asCTypedefType(asCScriptEngine *engine) : asCTypeInfo(engine) {} + ~asCTypedefType(); + + void DestroyInternal(); + + asCDataType aliasForType; // increase refCount for typeinfo inside datatype + + int GetTypedefTypeId() const; + +protected: + asCTypedefType() : asCTypeInfo() {} +}; + +class asCFuncdefType : public asCTypeInfo +{ +public: + asCFuncdefType(asCScriptEngine *engine, asCScriptFunction *func); + ~asCFuncdefType(); + + asIScriptFunction *GetFuncdefSignature() const; + asITypeInfo *GetParentType() const; + + void DestroyInternal(); + asCScriptFunction *funcdef; // increases refCount + asCObjectType *parentClass; // doesn't increase refCount + +protected: + asCFuncdefType() : asCTypeInfo(), funcdef(0), parentClass(0) {} }; END_AS_NAMESPACE -#endif // AS_NO_COMPILER - #endif diff --git a/lib/bullet/src/BulletDynamics/Dynamics/btActionInterface.h b/lib/bullet/src/BulletDynamics/Dynamics/btActionInterface.h index e1fea3a49..910752402 100644 --- a/lib/bullet/src/BulletDynamics/Dynamics/btActionInterface.h +++ b/lib/bullet/src/BulletDynamics/Dynamics/btActionInterface.h @@ -39,7 +39,7 @@ public: virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTimeStep)=0; virtual void debugDraw(btIDebugDraw* debugDrawer) = 0; - + virtual void resetMaxSpeed() = 0; }; #endif //_BT_ACTION_INTERFACE_H diff --git a/lib/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/lib/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index b006c67b1..a54e6d336 100644 --- a/lib/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/lib/bullet/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -297,6 +297,12 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, } clearForces(); + // Reset the max speeds of all karts, so that supertuxkart can + // set any new max_speed. + for (int i = 0; iresetMaxSpeed(); + } #ifndef BT_NO_PROFILE CProfileManager::Increment_Frame_Counter(); diff --git a/lib/enet/ChangeLog b/lib/enet/ChangeLog index 861d51f58..727f853cb 100644 --- a/lib/enet/ChangeLog +++ b/lib/enet/ChangeLog @@ -1,3 +1,58 @@ +ENet 1.3.12 (April 24, 2014): + +* added maximumPacketSize and maximumWaitingData fields to ENetHost to limit the amount of +data waiting to be delivered on a peer (beware that the default maximumPacketSize is +32MB and should be set higher if desired as should maximumWaitingData) + +ENet 1.3.11 (December 26, 2013): + +* allow an ENetHost to connect to itself +* fixed possible bug with disconnect notifications during connect attempts +* fixed some preprocessor definition bugs + +ENet 1.3.10 (October 23, 2013); + +* doubled maximum reliable window size +* fixed RCVTIMEO/SNDTIMEO socket options and also added NODELAY + +ENet 1.3.9 (August 19, 2013): + +* added duplicatePeers option to ENetHost which can limit the number of peers from duplicate IPs +* added enet_socket_get_option() and ENET_SOCKOPT_ERROR +* added enet_host_random_seed() platform stub + +ENet 1.3.8 (June 2, 2013): + +* added enet_linked_version() for checking the linked version +* added enet_socket_get_address() for querying the local address of a socket +* silenced some debugging prints unless ENET_DEBUG is defined during compilation +* handle EINTR in enet_socket_wait() so that enet_host_service() doesn't propagate errors from signals +* optimized enet_host_bandwidth_throttle() to be less expensive for large numbers of peers + +ENet 1.3.7 (March 6, 2013): + +* added ENET_PACKET_FLAG_SENT to indicate that a packet is being freed because it has been sent +* added userData field to ENetPacket +* changed how random seed is generated on Windows to avoid import warnings +* fixed case where disconnects could be generated with no preceding connect event + +ENet 1.3.6 (December 11, 2012): + +* added support for intercept callback in ENetHost that can be used to process raw packets before ENet +* added enet_socket_shutdown() for issuing shutdown on a socket +* fixed enet_socket_connect() to not error on non-blocking connects +* fixed bug in MTU negotiation during connections + +ENet 1.3.5 (July 31, 2012): + +* fixed bug in unreliable packet fragment queuing + +ENet 1.3.4 (May 29, 2012): + +* added enet_peer_ping_interval() for configuring per-peer ping intervals +* added enet_peer_timeout() for configuring per-peer timeouts +* added protocol packet size limits + ENet 1.3.3 (June 28, 2011): * fixed bug with simultaneous disconnects not dispatching events diff --git a/lib/enet/LICENSE b/lib/enet/LICENSE index 357a4e5c2..ebb7cf4ba 100644 --- a/lib/enet/LICENSE +++ b/lib/enet/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2002-2011 Lee Salzman +Copyright (c) 2002-2014 Lee Salzman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/lib/enet/Makefile.am b/lib/enet/Makefile.am deleted file mode 100644 index 760978d28..000000000 --- a/lib/enet/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -noinst_LIBRARIES = libenet.a -EXTRA_DIST = ChangeLog configure design.txt Doxyfile LICENSE tutorial.txt CMakeLists.txt\ - $(shell find $(srcdir) -maxdepth 2 -name "*.dox") -libenet_a_SOURCES = callbacks.c compress.c host.c list.c packet.c peer.c \ - protocol.c unix.c win32.c \ - include/enet/callbacks.h \ - include/enet/enet.h \ - include/enet/list.h \ - include/enet/protocol.h \ - include/enet/time.h \ - include/enet/types.h \ - include/enet/unix.h \ - include/enet/utility.h \ - include/enet/win32.h - -AM_CPPFLAGS = -I$(srcdir)/include/ diff --git a/lib/enet/README b/lib/enet/README index 7f7a0ad01..54b2d2130 100644 --- a/lib/enet/README +++ b/lib/enet/README @@ -1,7 +1,7 @@ Please visit the ENet homepage at http://enet.bespin.org for installation and usage instructions. -If you obtained this package from CVS, the quick description on how to build +If you obtained this package from github, the quick description on how to build is: # Generate the build system. diff --git a/lib/enet/aclocal.m4 b/lib/enet/aclocal.m4 deleted file mode 100644 index 91c7b2417..000000000 --- a/lib/enet/aclocal.m4 +++ /dev/null @@ -1,8917 +0,0 @@ -# generated automatically by aclocal 1.11.1 -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -m4_ifndef([AC_AUTOCONF_VERSION], - [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.65],, -[m4_warning([this file was generated for autoconf 2.65. -You have another version of autoconf. It may work, but is not guaranteed to. -If you have problems, you may need to regenerate the build system entirely. -To do so, use the procedure documented by the package, typically `autoreconf'.])]) - -# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -m4_define([_LT_COPYING], [dnl -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is part of GNU Libtool. -# -# GNU Libtool 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 2 of -# the License, or (at your option) any later version. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, or -# obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -]) - -# serial 56 LT_INIT - - -# LT_PREREQ(VERSION) -# ------------------ -# Complain and exit if this libtool version is less that VERSION. -m4_defun([LT_PREREQ], -[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, - [m4_default([$3], - [m4_fatal([Libtool version $1 or higher is required], - 63)])], - [$2])]) - - -# _LT_CHECK_BUILDDIR -# ------------------ -# Complain if the absolute build directory name contains unusual characters -m4_defun([_LT_CHECK_BUILDDIR], -[case `pwd` in - *\ * | *\ *) - AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; -esac -]) - - -# LT_INIT([OPTIONS]) -# ------------------ -AC_DEFUN([LT_INIT], -[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT -AC_BEFORE([$0], [LT_LANG])dnl -AC_BEFORE([$0], [LT_OUTPUT])dnl -AC_BEFORE([$0], [LTDL_INIT])dnl -m4_require([_LT_CHECK_BUILDDIR])dnl - -dnl Autoconf doesn't catch unexpanded LT_ macros by default: -m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl -m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl -dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 -dnl unless we require an AC_DEFUNed macro: -AC_REQUIRE([LTOPTIONS_VERSION])dnl -AC_REQUIRE([LTSUGAR_VERSION])dnl -AC_REQUIRE([LTVERSION_VERSION])dnl -AC_REQUIRE([LTOBSOLETE_VERSION])dnl -m4_require([_LT_PROG_LTMAIN])dnl - -dnl Parse OPTIONS -_LT_SET_OPTIONS([$0], [$1]) - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ltmain" - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' -AC_SUBST(LIBTOOL)dnl - -_LT_SETUP - -# Only expand once: -m4_define([LT_INIT]) -])# LT_INIT - -# Old names: -AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) -AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_PROG_LIBTOOL], []) -dnl AC_DEFUN([AM_PROG_LIBTOOL], []) - - -# _LT_CC_BASENAME(CC) -# ------------------- -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -m4_defun([_LT_CC_BASENAME], -[for cc_temp in $1""; do - case $cc_temp in - compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; - distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` -]) - - -# _LT_FILEUTILS_DEFAULTS -# ---------------------- -# It is okay to use these file commands and assume they have been set -# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. -m4_defun([_LT_FILEUTILS_DEFAULTS], -[: ${CP="cp -f"} -: ${MV="mv -f"} -: ${RM="rm -f"} -])# _LT_FILEUTILS_DEFAULTS - - -# _LT_SETUP -# --------- -m4_defun([_LT_SETUP], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -_LT_DECL([], [host_alias], [0], [The host system])dnl -_LT_DECL([], [host], [0])dnl -_LT_DECL([], [host_os], [0])dnl -dnl -_LT_DECL([], [build_alias], [0], [The build system])dnl -_LT_DECL([], [build], [0])dnl -_LT_DECL([], [build_os], [0])dnl -dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([LT_PATH_LD])dnl -AC_REQUIRE([LT_PATH_NM])dnl -dnl -AC_REQUIRE([AC_PROG_LN_S])dnl -test -z "$LN_S" && LN_S="ln -s" -_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl -dnl -AC_REQUIRE([LT_CMD_MAX_LEN])dnl -_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl -_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl -dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_CHECK_SHELL_FEATURES])dnl -m4_require([_LT_CMD_RELOAD])dnl -m4_require([_LT_CHECK_MAGIC_METHOD])dnl -m4_require([_LT_CMD_OLD_ARCHIVE])dnl -m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl - -_LT_CONFIG_LIBTOOL_INIT([ -# See if we are running on zsh, and set the options which allow our -# commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST -fi -]) -if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST -fi - -_LT_CHECK_OBJDIR - -m4_require([_LT_TAG_COMPILER])dnl -_LT_PROG_ECHO_BACKSLASH - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\([["`\\]]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -# Global variables: -ofile=libtool -can_build_shared=yes - -# All known linkers require a `.a' archive for static linking (except MSVC, -# which needs '.lib'). -libext=a - -with_gnu_ld="$lt_cv_prog_gnu_ld" - -old_CC="$CC" -old_CFLAGS="$CFLAGS" - -# Set sane defaults for various variables -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS -test -z "$LD" && LD=ld -test -z "$ac_objext" && ac_objext=o - -_LT_CC_BASENAME([$compiler]) - -# Only perform the check for file, if the check method requires it -test -z "$MAGIC_CMD" && MAGIC_CMD=file -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - _LT_PATH_MAGIC - fi - ;; -esac - -# Use C for the default configuration in the libtool script -LT_SUPPORTED_TAG([CC]) -_LT_LANG_C_CONFIG -_LT_LANG_DEFAULT_CONFIG -_LT_CONFIG_COMMANDS -])# _LT_SETUP - - -# _LT_PROG_LTMAIN -# --------------- -# Note that this code is called both from `configure', and `config.status' -# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, -# `config.status' has no value for ac_aux_dir unless we are using Automake, -# so we pass a copy along to make sure it has a sensible value anyway. -m4_defun([_LT_PROG_LTMAIN], -[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl -_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) -ltmain="$ac_aux_dir/ltmain.sh" -])# _LT_PROG_LTMAIN - - - -# So that we can recreate a full libtool script including additional -# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS -# in macros and then make a single call at the end using the `libtool' -# label. - - -# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) -# ---------------------------------------- -# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. -m4_define([_LT_CONFIG_LIBTOOL_INIT], -[m4_ifval([$1], - [m4_append([_LT_OUTPUT_LIBTOOL_INIT], - [$1 -])])]) - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_INIT]) - - -# _LT_CONFIG_LIBTOOL([COMMANDS]) -# ------------------------------ -# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. -m4_define([_LT_CONFIG_LIBTOOL], -[m4_ifval([$1], - [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], - [$1 -])])]) - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) - - -# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) -# ----------------------------------------------------- -m4_defun([_LT_CONFIG_SAVE_COMMANDS], -[_LT_CONFIG_LIBTOOL([$1]) -_LT_CONFIG_LIBTOOL_INIT([$2]) -]) - - -# _LT_FORMAT_COMMENT([COMMENT]) -# ----------------------------- -# Add leading comment marks to the start of each line, and a trailing -# full-stop to the whole comment if one is not present already. -m4_define([_LT_FORMAT_COMMENT], -[m4_ifval([$1], [ -m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], - [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) -)]) - - - - - -# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) -# ------------------------------------------------------------------- -# CONFIGNAME is the name given to the value in the libtool script. -# VARNAME is the (base) name used in the configure script. -# VALUE may be 0, 1 or 2 for a computed quote escaped value based on -# VARNAME. Any other value will be used directly. -m4_define([_LT_DECL], -[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], - [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], - [m4_ifval([$1], [$1], [$2])]) - lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) - m4_ifval([$4], - [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) - lt_dict_add_subkey([lt_decl_dict], [$2], - [tagged?], [m4_ifval([$5], [yes], [no])])]) -]) - - -# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) -# -------------------------------------------------------- -m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) - - -# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) -# ------------------------------------------------ -m4_define([lt_decl_tag_varnames], -[_lt_decl_filter([tagged?], [yes], $@)]) - - -# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) -# --------------------------------------------------------- -m4_define([_lt_decl_filter], -[m4_case([$#], - [0], [m4_fatal([$0: too few arguments: $#])], - [1], [m4_fatal([$0: too few arguments: $#: $1])], - [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], - [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], - [lt_dict_filter([lt_decl_dict], $@)])[]dnl -]) - - -# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) -# -------------------------------------------------- -m4_define([lt_decl_quote_varnames], -[_lt_decl_filter([value], [1], $@)]) - - -# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) -# --------------------------------------------------- -m4_define([lt_decl_dquote_varnames], -[_lt_decl_filter([value], [2], $@)]) - - -# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) -# --------------------------------------------------- -m4_define([lt_decl_varnames_tagged], -[m4_assert([$# <= 2])dnl -_$0(m4_quote(m4_default([$1], [[, ]])), - m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), - m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) -m4_define([_lt_decl_varnames_tagged], -[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) - - -# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) -# ------------------------------------------------ -m4_define([lt_decl_all_varnames], -[_$0(m4_quote(m4_default([$1], [[, ]])), - m4_if([$2], [], - m4_quote(lt_decl_varnames), - m4_quote(m4_shift($@))))[]dnl -]) -m4_define([_lt_decl_all_varnames], -[lt_join($@, lt_decl_varnames_tagged([$1], - lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl -]) - - -# _LT_CONFIG_STATUS_DECLARE([VARNAME]) -# ------------------------------------ -# Quote a variable value, and forward it to `config.status' so that its -# declaration there will have the same value as in `configure'. VARNAME -# must have a single quote delimited value for this to work. -m4_define([_LT_CONFIG_STATUS_DECLARE], -[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`']) - - -# _LT_CONFIG_STATUS_DECLARATIONS -# ------------------------------ -# We delimit libtool config variables with single quotes, so when -# we write them to config.status, we have to be sure to quote all -# embedded single quotes properly. In configure, this macro expands -# each variable declared with _LT_DECL (and _LT_TAGDECL) into: -# -# ='`$ECHO "X$" | $Xsed -e "$delay_single_quote_subst"`' -m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], -[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), - [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) - - -# _LT_LIBTOOL_TAGS -# ---------------- -# Output comment and list of tags supported by the script -m4_defun([_LT_LIBTOOL_TAGS], -[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl -available_tags="_LT_TAGS"dnl -]) - - -# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) -# ----------------------------------- -# Extract the dictionary values for VARNAME (optionally with TAG) and -# expand to a commented shell variable setting: -# -# # Some comment about what VAR is for. -# visible_name=$lt_internal_name -m4_define([_LT_LIBTOOL_DECLARE], -[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], - [description])))[]dnl -m4_pushdef([_libtool_name], - m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl -m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), - [0], [_libtool_name=[$]$1], - [1], [_libtool_name=$lt_[]$1], - [2], [_libtool_name=$lt_[]$1], - [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl -m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl -]) - - -# _LT_LIBTOOL_CONFIG_VARS -# ----------------------- -# Produce commented declarations of non-tagged libtool config variables -# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' -# script. Tagged libtool config variables (even for the LIBTOOL CONFIG -# section) are produced by _LT_LIBTOOL_TAG_VARS. -m4_defun([_LT_LIBTOOL_CONFIG_VARS], -[m4_foreach([_lt_var], - m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), - [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) - - -# _LT_LIBTOOL_TAG_VARS(TAG) -# ------------------------- -m4_define([_LT_LIBTOOL_TAG_VARS], -[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), - [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) - - -# _LT_TAGVAR(VARNAME, [TAGNAME]) -# ------------------------------ -m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) - - -# _LT_CONFIG_COMMANDS -# ------------------- -# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of -# variables for single and double quote escaping we saved from calls -# to _LT_DECL, we can put quote escaped variables declarations -# into `config.status', and then the shell code to quote escape them in -# for loops in `config.status'. Finally, any additional code accumulated -# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. -m4_defun([_LT_CONFIG_COMMANDS], -[AC_PROVIDE_IFELSE([LT_OUTPUT], - dnl If the libtool generation code has been placed in $CONFIG_LT, - dnl instead of duplicating it all over again into config.status, - dnl then we will have config.status run $CONFIG_LT later, so it - dnl needs to know what name is stored there: - [AC_CONFIG_COMMANDS([libtool], - [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], - dnl If the libtool generation code is destined for config.status, - dnl expand the accumulated commands and init code now: - [AC_CONFIG_COMMANDS([libtool], - [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) -])#_LT_CONFIG_COMMANDS - - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], -[ - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -sed_quote_subst='$sed_quote_subst' -double_quote_subst='$double_quote_subst' -delay_variable_subst='$delay_variable_subst' -_LT_CONFIG_STATUS_DECLARATIONS -LTCC='$LTCC' -LTCFLAGS='$LTCFLAGS' -compiler='$compiler_DEFAULT' - -# Quote evaled strings. -for var in lt_decl_all_varnames([[ \ -]], lt_decl_quote_varnames); do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in - *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -# Double-quote double-evaled strings. -for var in lt_decl_all_varnames([[ \ -]], lt_decl_dquote_varnames); do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in - *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -# Fix-up fallback echo if it was mangled by the above quoting rules. -case \$lt_ECHO in -*'\\\[$]0 --fallback-echo"')dnl " - lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\` - ;; -esac - -_LT_OUTPUT_LIBTOOL_INIT -]) - - -# LT_OUTPUT -# --------- -# This macro allows early generation of the libtool script (before -# AC_OUTPUT is called), incase it is used in configure for compilation -# tests. -AC_DEFUN([LT_OUTPUT], -[: ${CONFIG_LT=./config.lt} -AC_MSG_NOTICE([creating $CONFIG_LT]) -cat >"$CONFIG_LT" <<_LTEOF -#! $SHELL -# Generated by $as_me. -# Run this file to recreate a libtool stub with the current configuration. - -lt_cl_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_LTEOF - -cat >>"$CONFIG_LT" <<\_LTEOF -AS_SHELL_SANITIZE -_AS_PREPARE - -exec AS_MESSAGE_FD>&1 -exec AS_MESSAGE_LOG_FD>>config.log -{ - echo - AS_BOX([Running $as_me.]) -} >&AS_MESSAGE_LOG_FD - -lt_cl_help="\ -\`$as_me' creates a local libtool stub from the current configuration, -for use in further configure time tests before the real libtool is -generated. - -Usage: $[0] [[OPTIONS]] - - -h, --help print this help, then exit - -V, --version print version number, then exit - -q, --quiet do not print progress messages - -d, --debug don't remove temporary files - -Report bugs to ." - -lt_cl_version="\ -m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl -m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) -configured by $[0], generated by m4_PACKAGE_STRING. - -Copyright (C) 2008 Free Software Foundation, Inc. -This config.lt script is free software; the Free Software Foundation -gives unlimited permision to copy, distribute and modify it." - -while test $[#] != 0 -do - case $[1] in - --version | --v* | -V ) - echo "$lt_cl_version"; exit 0 ;; - --help | --h* | -h ) - echo "$lt_cl_help"; exit 0 ;; - --debug | --d* | -d ) - debug=: ;; - --quiet | --q* | --silent | --s* | -q ) - lt_cl_silent=: ;; - - -*) AC_MSG_ERROR([unrecognized option: $[1] -Try \`$[0] --help' for more information.]) ;; - - *) AC_MSG_ERROR([unrecognized argument: $[1] -Try \`$[0] --help' for more information.]) ;; - esac - shift -done - -if $lt_cl_silent; then - exec AS_MESSAGE_FD>/dev/null -fi -_LTEOF - -cat >>"$CONFIG_LT" <<_LTEOF -_LT_OUTPUT_LIBTOOL_COMMANDS_INIT -_LTEOF - -cat >>"$CONFIG_LT" <<\_LTEOF -AC_MSG_NOTICE([creating $ofile]) -_LT_OUTPUT_LIBTOOL_COMMANDS -AS_EXIT(0) -_LTEOF -chmod +x "$CONFIG_LT" - -# configure is writing to config.log, but config.lt does its own redirection, -# appending to config.log, which fails on DOS, as config.log is still kept -# open by configure. Here we exec the FD to /dev/null, effectively closing -# config.log, so it can be properly (re)opened and appended to by config.lt. -if test "$no_create" != yes; then - lt_cl_success=: - test "$silent" = yes && - lt_config_lt_args="$lt_config_lt_args --quiet" - exec AS_MESSAGE_LOG_FD>/dev/null - $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false - exec AS_MESSAGE_LOG_FD>>config.log - $lt_cl_success || AS_EXIT(1) -fi -])# LT_OUTPUT - - -# _LT_CONFIG(TAG) -# --------------- -# If TAG is the built-in tag, create an initial libtool script with a -# default configuration from the untagged config vars. Otherwise add code -# to config.status for appending the configuration named by TAG from the -# matching tagged config vars. -m4_defun([_LT_CONFIG], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -_LT_CONFIG_SAVE_COMMANDS([ - m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl - m4_if(_LT_TAG, [C], [ - # See if we are running on zsh, and set the options which allow our - # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - - cfgfile="${ofile}T" - trap "$RM \"$cfgfile\"; exit 1" 1 2 15 - $RM "$cfgfile" - - cat <<_LT_EOF >> "$cfgfile" -#! $SHELL - -# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: -# NOTE: Changes made to this file will be lost: look at ltmain.sh. -# -_LT_COPYING -_LT_LIBTOOL_TAGS - -# ### BEGIN LIBTOOL CONFIG -_LT_LIBTOOL_CONFIG_VARS -_LT_LIBTOOL_TAG_VARS -# ### END LIBTOOL CONFIG - -_LT_EOF - - case $host_os in - aix3*) - cat <<\_LT_EOF >> "$cfgfile" -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -_LT_EOF - ;; - esac - - _LT_PROG_LTMAIN - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - _LT_PROG_XSI_SHELLFNS - - sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" -], -[cat <<_LT_EOF >> "$ofile" - -dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded -dnl in a comment (ie after a #). -# ### BEGIN LIBTOOL TAG CONFIG: $1 -_LT_LIBTOOL_TAG_VARS(_LT_TAG) -# ### END LIBTOOL TAG CONFIG: $1 -_LT_EOF -])dnl /m4_if -], -[m4_if([$1], [], [ - PACKAGE='$PACKAGE' - VERSION='$VERSION' - TIMESTAMP='$TIMESTAMP' - RM='$RM' - ofile='$ofile'], []) -])dnl /_LT_CONFIG_SAVE_COMMANDS -])# _LT_CONFIG - - -# LT_SUPPORTED_TAG(TAG) -# --------------------- -# Trace this macro to discover what tags are supported by the libtool -# --tag option, using: -# autoconf --trace 'LT_SUPPORTED_TAG:$1' -AC_DEFUN([LT_SUPPORTED_TAG], []) - - -# C support is built-in for now -m4_define([_LT_LANG_C_enabled], []) -m4_define([_LT_TAGS], []) - - -# LT_LANG(LANG) -# ------------- -# Enable libtool support for the given language if not already enabled. -AC_DEFUN([LT_LANG], -[AC_BEFORE([$0], [LT_OUTPUT])dnl -m4_case([$1], - [C], [_LT_LANG(C)], - [C++], [_LT_LANG(CXX)], - [Java], [_LT_LANG(GCJ)], - [Fortran 77], [_LT_LANG(F77)], - [Fortran], [_LT_LANG(FC)], - [Windows Resource], [_LT_LANG(RC)], - [m4_ifdef([_LT_LANG_]$1[_CONFIG], - [_LT_LANG($1)], - [m4_fatal([$0: unsupported language: "$1"])])])dnl -])# LT_LANG - - -# _LT_LANG(LANGNAME) -# ------------------ -m4_defun([_LT_LANG], -[m4_ifdef([_LT_LANG_]$1[_enabled], [], - [LT_SUPPORTED_TAG([$1])dnl - m4_append([_LT_TAGS], [$1 ])dnl - m4_define([_LT_LANG_]$1[_enabled], [])dnl - _LT_LANG_$1_CONFIG($1)])dnl -])# _LT_LANG - - -# _LT_LANG_DEFAULT_CONFIG -# ----------------------- -m4_defun([_LT_LANG_DEFAULT_CONFIG], -[AC_PROVIDE_IFELSE([AC_PROG_CXX], - [LT_LANG(CXX)], - [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) - -AC_PROVIDE_IFELSE([AC_PROG_F77], - [LT_LANG(F77)], - [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) - -AC_PROVIDE_IFELSE([AC_PROG_FC], - [LT_LANG(FC)], - [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) - -dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal -dnl pulling things in needlessly. -AC_PROVIDE_IFELSE([AC_PROG_GCJ], - [LT_LANG(GCJ)], - [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], - [LT_LANG(GCJ)], - [AC_PROVIDE_IFELSE([LT_PROG_GCJ], - [LT_LANG(GCJ)], - [m4_ifdef([AC_PROG_GCJ], - [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) - m4_ifdef([A][M_PROG_GCJ], - [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) - m4_ifdef([LT_PROG_GCJ], - [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) - -AC_PROVIDE_IFELSE([LT_PROG_RC], - [LT_LANG(RC)], - [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) -])# _LT_LANG_DEFAULT_CONFIG - -# Obsolete macros: -AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) -AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) -AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) -AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_CXX], []) -dnl AC_DEFUN([AC_LIBTOOL_F77], []) -dnl AC_DEFUN([AC_LIBTOOL_FC], []) -dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) - - -# _LT_TAG_COMPILER -# ---------------- -m4_defun([_LT_TAG_COMPILER], -[AC_REQUIRE([AC_PROG_CC])dnl - -_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl -_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl -_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl -_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC -])# _LT_TAG_COMPILER - - -# _LT_COMPILER_BOILERPLATE -# ------------------------ -# Check for compiler boilerplate output or warnings with -# the simple compiler test code. -m4_defun([_LT_COMPILER_BOILERPLATE], -[m4_require([_LT_DECL_SED])dnl -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$RM conftest* -])# _LT_COMPILER_BOILERPLATE - - -# _LT_LINKER_BOILERPLATE -# ---------------------- -# Check for linker boilerplate output or warnings with -# the simple link test code. -m4_defun([_LT_LINKER_BOILERPLATE], -[m4_require([_LT_DECL_SED])dnl -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$RM -r conftest* -])# _LT_LINKER_BOILERPLATE - -# _LT_REQUIRED_DARWIN_CHECKS -# ------------------------- -m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ - case $host_os in - rhapsody* | darwin*) - AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) - AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) - AC_CHECK_TOOL([LIPO], [lipo], [:]) - AC_CHECK_TOOL([OTOOL], [otool], [:]) - AC_CHECK_TOOL([OTOOL64], [otool64], [:]) - _LT_DECL([], [DSYMUTIL], [1], - [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) - _LT_DECL([], [NMEDIT], [1], - [Tool to change global to local symbols on Mac OS X]) - _LT_DECL([], [LIPO], [1], - [Tool to manipulate fat objects and archives on Mac OS X]) - _LT_DECL([], [OTOOL], [1], - [ldd/readelf like tool for Mach-O binaries on Mac OS X]) - _LT_DECL([], [OTOOL64], [1], - [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) - - AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], - [lt_cv_apple_cc_single_mod=no - if test -z "${LT_MULTI_MODULE}"; then - # By default we will add the -single_module flag. You can override - # by either setting the environment variable LT_MULTI_MODULE - # non-empty at configure time, or by adding -multi_module to the - # link flags. - rm -rf libconftest.dylib* - echo "int foo(void){return 1;}" > conftest.c - echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ --dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD - $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ - -dynamiclib -Wl,-single_module conftest.c 2>conftest.err - _lt_result=$? - if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then - lt_cv_apple_cc_single_mod=yes - else - cat conftest.err >&AS_MESSAGE_LOG_FD - fi - rm -rf libconftest.dylib* - rm -f conftest.* - fi]) - AC_CACHE_CHECK([for -exported_symbols_list linker flag], - [lt_cv_ld_exported_symbols_list], - [lt_cv_ld_exported_symbols_list=no - save_LDFLAGS=$LDFLAGS - echo "_main" > conftest.sym - LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" - AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], - [lt_cv_ld_exported_symbols_list=yes], - [lt_cv_ld_exported_symbols_list=no]) - LDFLAGS="$save_LDFLAGS" - ]) - case $host_os in - rhapsody* | darwin1.[[012]]) - _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; - darwin1.*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - darwin*) # darwin 5.x on - # if running on 10.5 or later, the deployment target defaults - # to the OS version, if on x86, and 10.4, the deployment - # target defaults to 10.4. Don't you love it? - case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in - 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - 10.[[012]]*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - 10.*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - esac - ;; - esac - if test "$lt_cv_apple_cc_single_mod" = "yes"; then - _lt_dar_single_mod='$single_module' - fi - if test "$lt_cv_ld_exported_symbols_list" = "yes"; then - _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' - else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - if test "$DSYMUTIL" != ":"; then - _lt_dsymutil='~$DSYMUTIL $lib || :' - else - _lt_dsymutil= - fi - ;; - esac -]) - - -# _LT_DARWIN_LINKER_FEATURES -# -------------------------- -# Checks for linker and compiler features on darwin -m4_defun([_LT_DARWIN_LINKER_FEATURES], -[ - m4_require([_LT_REQUIRED_DARWIN_CHECKS]) - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_automatic, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_TAGVAR(whole_archive_flag_spec, $1)='' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" - case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; - *) _lt_dar_can_shared=$GCC ;; - esac - if test "$_lt_dar_can_shared" = "yes"; then - output_verbose_link_cmd=echo - _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" - m4_if([$1], [CXX], -[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then - _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" - fi -],[]) - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi -]) - -# _LT_SYS_MODULE_PATH_AIX -# ----------------------- -# Links a minimal program and checks the executable -# for the system default hardcoded library path. In most cases, -# this is /usr/lib:/lib, but when the MPI compilers are used -# the location of the communication and MPI libs are included too. -# If we don't find anything, use the default library path according -# to the aix ld manual. -m4_defun([_LT_SYS_MODULE_PATH_AIX], -[m4_require([_LT_DECL_SED])dnl -AC_LINK_IFELSE(AC_LANG_PROGRAM,[ -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi],[]) -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi -])# _LT_SYS_MODULE_PATH_AIX - - -# _LT_SHELL_INIT(ARG) -# ------------------- -m4_define([_LT_SHELL_INIT], -[ifdef([AC_DIVERSION_NOTICE], - [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], - [AC_DIVERT_PUSH(NOTICE)]) -$1 -AC_DIVERT_POP -])# _LT_SHELL_INIT - - -# _LT_PROG_ECHO_BACKSLASH -# ----------------------- -# Add some code to the start of the generated configure script which -# will find an echo command which doesn't interpret backslashes. -m4_defun([_LT_PROG_ECHO_BACKSLASH], -[_LT_SHELL_INIT([ -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} - -case X$lt_ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` - ;; -esac - -ECHO=${lt_ECHO-echo} -if test "X[$]1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X[$]1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then - # Yippee, $ECHO works! - : -else - # Restart under the correct shell. - exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} -fi - -if test "X[$]1" = X--fallback-echo; then - # used as fallback echo - shift - cat <<_LT_EOF -[$]* -_LT_EOF - exit 0 -fi - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -if test -z "$lt_ECHO"; then - if test "X${echo_test_string+set}" != Xset; then - # find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if { echo_test_string=`eval $cmd`; } 2>/dev/null && - { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null - then - break - fi - done - fi - - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : - else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$ECHO" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - ECHO='print -r' - elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} - else - # Try using printf. - ECHO='printf %s\n' - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - ECHO="$CONFIG_SHELL [$]0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$CONFIG_SHELL [$]0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do - if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null - then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "[$]0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} - else - # Oops. We lost completely, so just stick with echo. - ECHO=echo - fi - fi - fi - fi - fi -fi - -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -lt_ECHO=$ECHO -if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then - lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" -fi - -AC_SUBST(lt_ECHO) -]) -_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) -_LT_DECL([], [ECHO], [1], - [An echo program that does not interpret backslashes]) -])# _LT_PROG_ECHO_BACKSLASH - - -# _LT_ENABLE_LOCK -# --------------- -m4_defun([_LT_ENABLE_LOCK], -[AC_ARG_ENABLE([libtool-lock], - [AS_HELP_STRING([--disable-libtool-lock], - [avoid locking (might break parallel builds)])]) -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE="32" - ;; - *ELF-64*) - HPUX_IA64_MODE="64" - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out which ABI we are using. - echo '[#]line __oline__ "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - if test "$lt_cv_prog_gnu_ld" = yes; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ -s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in - *32-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_i386_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_i386" - ;; - ppc64-*linux*|powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_x86_64_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - ppc*-*linux*|powerpc*-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*|s390*-*tpf*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -belf" - AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, - [AC_LANG_PUSH(C) - AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) - AC_LANG_POP]) - if test x"$lt_cv_cc_needs_belf" != x"yes"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" - fi - ;; -sparc*-*solaris*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in - *64-bit*) - case $lt_cv_prog_gnu_ld in - yes*) LD="${LD-ld} -m elf64_sparc" ;; - *) - if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then - LD="${LD-ld} -64" - fi - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; -esac - -need_locks="$enable_libtool_lock" -])# _LT_ENABLE_LOCK - - -# _LT_CMD_OLD_ARCHIVE -# ------------------- -m4_defun([_LT_CMD_OLD_ARCHIVE], -[AC_CHECK_TOOL(AR, ar, false) -test -z "$AR" && AR=ar -test -z "$AR_FLAGS" && AR_FLAGS=cru -_LT_DECL([], [AR], [1], [The archiver]) -_LT_DECL([], [AR_FLAGS], [1]) - -AC_CHECK_TOOL(STRIP, strip, :) -test -z "$STRIP" && STRIP=: -_LT_DECL([], [STRIP], [1], [A symbol stripping program]) - -AC_CHECK_TOOL(RANLIB, ranlib, :) -test -z "$RANLIB" && RANLIB=: -_LT_DECL([], [RANLIB], [1], - [Commands used to install an old-style archive]) - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" - ;; - *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" -fi -_LT_DECL([], [old_postinstall_cmds], [2]) -_LT_DECL([], [old_postuninstall_cmds], [2]) -_LT_TAGDECL([], [old_archive_cmds], [2], - [Commands used to build an old-style archive]) -])# _LT_CMD_OLD_ARCHIVE - - -# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------------------- -# Check whether the given compiler option works -AC_DEFUN([_LT_COMPILER_OPTION], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_SED])dnl -AC_CACHE_CHECK([$1], [$2], - [$2=no - m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$3" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - $2=yes - fi - fi - $RM conftest* -]) - -if test x"[$]$2" = xyes; then - m4_if([$5], , :, [$5]) -else - m4_if([$6], , :, [$6]) -fi -])# _LT_COMPILER_OPTION - -# Old name: -AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) - - -# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------- -# Check whether the given linker option works -AC_DEFUN([_LT_LINKER_OPTION], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_SED])dnl -AC_CACHE_CHECK([$1], [$2], - [$2=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $3" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&AS_MESSAGE_LOG_FD - $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - $2=yes - fi - else - $2=yes - fi - fi - $RM -r conftest* - LDFLAGS="$save_LDFLAGS" -]) - -if test x"[$]$2" = xyes; then - m4_if([$4], , :, [$4]) -else - m4_if([$5], , :, [$5]) -fi -])# _LT_LINKER_OPTION - -# Old name: -AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) - - -# LT_CMD_MAX_LEN -#--------------- -AC_DEFUN([LT_CMD_MAX_LEN], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -# find the maximum length of command line arguments -AC_MSG_CHECKING([the maximum length of command line arguments]) -AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl - i=0 - teststring="ABCD" - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw* | cegcc*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) - # This has been around since 386BSD, at least. Likely further. - if test -x /sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` - elif test -x /usr/sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` - else - lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs - fi - # And add a safety zone - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - ;; - - interix*) - # We know the value 262144 and hardcode it with a safety zone (like BSD) - lt_cv_sys_max_cmd_len=196608 - ;; - - osf*) - # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure - # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not - # nice to cause kernel panics so lets avoid the loop below. - # First set a reasonable default. - lt_cv_sys_max_cmd_len=16384 - # - if test -x /sbin/sysconfig; then - case `/sbin/sysconfig -q proc exec_disable_arg_limit` in - *1*) lt_cv_sys_max_cmd_len=-1 ;; - esac - fi - ;; - sco3.2v5*) - lt_cv_sys_max_cmd_len=102400 - ;; - sysv5* | sco5v6* | sysv4.2uw2*) - kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` - if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` - else - lt_cv_sys_max_cmd_len=32768 - fi - ;; - *) - lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len"; then - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - else - # Make teststring a little bigger before we do anything with it. - # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8 ; do - teststring=$teststring$teststring - done - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ - = "XX$teststring$teststring"; } >/dev/null 2>&1 && - test $i != 17 # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - # Only check the string length outside the loop. - lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` - teststring= - # Add a significant safety factor because C++ compilers can tack on - # massive amounts of additional arguments before passing them to the - # linker. It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - fi - ;; - esac -]) -if test -n $lt_cv_sys_max_cmd_len ; then - AC_MSG_RESULT($lt_cv_sys_max_cmd_len) -else - AC_MSG_RESULT(none) -fi -max_cmd_len=$lt_cv_sys_max_cmd_len -_LT_DECL([], [max_cmd_len], [0], - [What is the maximum length of a command?]) -])# LT_CMD_MAX_LEN - -# Old name: -AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) - - -# _LT_HEADER_DLFCN -# ---------------- -m4_defun([_LT_HEADER_DLFCN], -[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl -])# _LT_HEADER_DLFCN - - -# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, -# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) -# ---------------------------------------------------------------- -m4_defun([_LT_TRY_DLOPEN_SELF], -[m4_require([_LT_HEADER_DLFCN])dnl -if test "$cross_compiling" = yes; then : - [$4] -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext <<_LT_EOF -[#line __oline__ "configure" -#include "confdefs.h" - -#if HAVE_DLFCN_H -#include -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - else - puts (dlerror ()); - - return status; -}] -_LT_EOF - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) $1 ;; - x$lt_dlneed_uscore) $2 ;; - x$lt_dlunknown|x*) $3 ;; - esac - else : - # compilation failed - $3 - fi -fi -rm -fr conftest* -])# _LT_TRY_DLOPEN_SELF - - -# LT_SYS_DLOPEN_SELF -# ------------------ -AC_DEFUN([LT_SYS_DLOPEN_SELF], -[m4_require([_LT_HEADER_DLFCN])dnl -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32* | cegcc*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ]) - ;; - - *) - AC_CHECK_FUNC([shl_load], - [lt_cv_dlopen="shl_load"], - [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], - [AC_CHECK_FUNC([dlopen], - [lt_cv_dlopen="dlopen"], - [AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], - [AC_CHECK_LIB([svld], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], - [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) - ]) - ]) - ]) - ]) - ]) - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - AC_CACHE_CHECK([whether a program can dlopen itself], - lt_cv_dlopen_self, [dnl - _LT_TRY_DLOPEN_SELF( - lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, - lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) - ]) - - if test "x$lt_cv_dlopen_self" = xyes; then - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" - AC_CACHE_CHECK([whether a statically linked program can dlopen itself], - lt_cv_dlopen_self_static, [dnl - _LT_TRY_DLOPEN_SELF( - lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, - lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) - ]) - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi -_LT_DECL([dlopen_support], [enable_dlopen], [0], - [Whether dlopen is supported]) -_LT_DECL([dlopen_self], [enable_dlopen_self], [0], - [Whether dlopen of programs is supported]) -_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], - [Whether dlopen of statically linked programs is supported]) -])# LT_SYS_DLOPEN_SELF - -# Old name: -AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) - - -# _LT_COMPILER_C_O([TAGNAME]) -# --------------------------- -# Check to see if options -c and -o are simultaneously supported by compiler. -# This macro does not hard code the compiler like AC_PROG_CC_C_O. -m4_defun([_LT_COMPILER_C_O], -[m4_require([_LT_DECL_SED])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_TAG_COMPILER])dnl -AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], - [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], - [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - fi - fi - chmod u+w . 2>&AS_MESSAGE_LOG_FD - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* -]) -_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], - [Does compiler simultaneously support -c and -o options?]) -])# _LT_COMPILER_C_O - - -# _LT_COMPILER_FILE_LOCKS([TAGNAME]) -# ---------------------------------- -# Check to see if we can do hard links to lock some files if needed -m4_defun([_LT_COMPILER_FILE_LOCKS], -[m4_require([_LT_ENABLE_LOCK])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -_LT_COMPILER_C_O([$1]) - -hard_links="nottested" -if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - AC_MSG_CHECKING([if we can lock with hard links]) - hard_links=yes - $RM conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - AC_MSG_RESULT([$hard_links]) - if test "$hard_links" = no; then - AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) - need_locks=warn - fi -else - need_locks=no -fi -_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) -])# _LT_COMPILER_FILE_LOCKS - - -# _LT_CHECK_OBJDIR -# ---------------- -m4_defun([_LT_CHECK_OBJDIR], -[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], -[rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null]) -objdir=$lt_cv_objdir -_LT_DECL([], [objdir], [0], - [The name of the directory that contains temporary libtool files])dnl -m4_pattern_allow([LT_OBJDIR])dnl -AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", - [Define to the sub-directory in which libtool stores uninstalled libraries.]) -])# _LT_CHECK_OBJDIR - - -# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) -# -------------------------------------- -# Check hardcoding attributes. -m4_defun([_LT_LINKER_HARDCODE_LIBPATH], -[AC_MSG_CHECKING([how to hardcode library paths into programs]) -_LT_TAGVAR(hardcode_action, $1)= -if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || - test -n "$_LT_TAGVAR(runpath_var, $1)" || - test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then - - # We can hardcode non-existent directories. - if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && - test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then - # Linking always hardcodes the temporary library directory. - _LT_TAGVAR(hardcode_action, $1)=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - _LT_TAGVAR(hardcode_action, $1)=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - _LT_TAGVAR(hardcode_action, $1)=unsupported -fi -AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) - -if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || - test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi -_LT_TAGDECL([], [hardcode_action], [0], - [How to hardcode a shared library path into an executable]) -])# _LT_LINKER_HARDCODE_LIBPATH - - -# _LT_CMD_STRIPLIB -# ---------------- -m4_defun([_LT_CMD_STRIPLIB], -[m4_require([_LT_DECL_EGREP]) -striplib= -old_striplib= -AC_MSG_CHECKING([whether stripping libraries is possible]) -if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - AC_MSG_RESULT([yes]) -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - old_striplib="$STRIP -S" - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - ;; - *) - AC_MSG_RESULT([no]) - ;; - esac -fi -_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) -_LT_DECL([], [striplib], [1]) -])# _LT_CMD_STRIPLIB - - -# _LT_SYS_DYNAMIC_LINKER([TAG]) -# ----------------------------- -# PORTME Fill in your ld.so characteristics -m4_defun([_LT_SYS_DYNAMIC_LINKER], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_OBJDUMP])dnl -m4_require([_LT_DECL_SED])dnl -AC_MSG_CHECKING([dynamic linker characteristics]) -m4_if([$1], - [], [ -if test "$GCC" = yes; then - case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; - esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` - else - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. - lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` - for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else - test -d "$lt_sys_path" && \ - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" - fi - done - lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; - for (lt_i = NF; lt_i > 0; lt_i--) { - if ($lt_i != "" && $lt_i != ".") { - if ($lt_i == "..") { - lt_count++; - } else { - if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; - } else { - lt_count--; - } - } - } - } - if (lt_foo != "") { lt_freq[[lt_foo]]++; } - if (lt_freq[[lt_foo]] == 1) { print lt_foo; } -}'` - sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi]) -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix[[4-9]]*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[[01]] | aix4.[[01]].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - case $host_cpu in - powerpc) - # Since July 2007 AmigaOS4 officially supports .so libraries. - # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - ;; - m68k) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - esac - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[[45]]*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32* | cegcc*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw* | cegcc*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' -m4_if([$1], [],[ - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[[123]]*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[[01]]* | freebsdelf3.[[01]]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ - freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -interix[[3-9]]*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # Some binutils ld are patched to set DT_RUNPATH - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ - LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" - AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], - [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], - [shlibpath_overrides_runpath=yes])]) - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -*nto* | *qnx*) - version_type=qnx - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='ldqnx.so' - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[[89]] | openbsd2.[[89]].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -tpf*) - # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -AC_MSG_RESULT([$dynamic_linker]) -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" -fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" -fi - -_LT_DECL([], [variables_saved_for_relink], [1], - [Variables whose values should be saved in libtool wrapper scripts and - restored at link time]) -_LT_DECL([], [need_lib_prefix], [0], - [Do we need the "lib" prefix for modules?]) -_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) -_LT_DECL([], [version_type], [0], [Library versioning type]) -_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) -_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) -_LT_DECL([], [shlibpath_overrides_runpath], [0], - [Is shlibpath searched before the hard-coded library search path?]) -_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) -_LT_DECL([], [library_names_spec], [1], - [[List of archive names. First name is the real one, the rest are links. - The last name is the one that the linker finds with -lNAME]]) -_LT_DECL([], [soname_spec], [1], - [[The coded name of the library, if different from the real name]]) -_LT_DECL([], [postinstall_cmds], [2], - [Command to use after installation of a shared archive]) -_LT_DECL([], [postuninstall_cmds], [2], - [Command to use after uninstallation of a shared archive]) -_LT_DECL([], [finish_cmds], [2], - [Commands used to finish a libtool library installation in a directory]) -_LT_DECL([], [finish_eval], [1], - [[As "finish_cmds", except a single script fragment to be evaled but - not shown]]) -_LT_DECL([], [hardcode_into_libs], [0], - [Whether we should hardcode library paths into libraries]) -_LT_DECL([], [sys_lib_search_path_spec], [2], - [Compile-time system search path for libraries]) -_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], - [Run-time system search path for libraries]) -])# _LT_SYS_DYNAMIC_LINKER - - -# _LT_PATH_TOOL_PREFIX(TOOL) -# -------------------------- -# find a file program which can recognize shared library -AC_DEFUN([_LT_PATH_TOOL_PREFIX], -[m4_require([_LT_DECL_EGREP])dnl -AC_MSG_CHECKING([for $1]) -AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, -[case $MAGIC_CMD in -[[\\/*] | ?:[\\/]*]) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR -dnl $ac_dummy forces splitting on constant user-supplied paths. -dnl POSIX.2 word splitting is done only on the output of word expansions, -dnl not every word. This closes a longstanding sh security hole. - ac_dummy="m4_if([$2], , $PATH, [$2])" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$1; then - lt_cv_path_MAGIC_CMD="$ac_dir/$1" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <<_LT_EOF 1>&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -_LT_EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac]) -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - AC_MSG_RESULT($MAGIC_CMD) -else - AC_MSG_RESULT(no) -fi -_LT_DECL([], [MAGIC_CMD], [0], - [Used to examine libraries when file_magic_cmd begins with "file"])dnl -])# _LT_PATH_TOOL_PREFIX - -# Old name: -AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) - - -# _LT_PATH_MAGIC -# -------------- -# find a file program which can recognize a shared library -m4_defun([_LT_PATH_MAGIC], -[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) - else - MAGIC_CMD=: - fi -fi -])# _LT_PATH_MAGIC - - -# LT_PATH_LD -# ---------- -# find the pathname to the GNU or non-GNU linker -AC_DEFUN([LT_PATH_LD], -[AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_DECL_EGREP])dnl - -AC_ARG_WITH([gnu-ld], - [AS_HELP_STRING([--with-gnu-ld], - [assume the C compiler uses GNU ld @<:@default=no@:>@])], - [test "$withval" = no || with_gnu_ld=yes], - [with_gnu_ld=no])dnl - -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - AC_MSG_CHECKING([for ld used by $CC]) - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [[\\/]]* | ?:[[\\/]]*) - re_direlt='/[[^/]][[^/]]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` - while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do - ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - AC_MSG_CHECKING([for GNU ld]) -else - AC_MSG_CHECKING([for non-GNU ld]) -fi -AC_CACHE_VAL(lt_cv_path_LD, -[if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - else - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - fi - ;; - -cegcc) - # use the weaker test based on 'objdump'. See mingw*. - lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - ;; - -darwin* | rhapsody*) - lt_cv_deplibs_check_method=pass_all - ;; - -freebsd* | dragonfly*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case $host_cpu in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -interix[[3-9]]*) - # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be Linux ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -*nto* | *qnx*) - lt_cv_deplibs_check_method=pass_all - ;; - -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -rdos*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.3*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - pc) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -tpf*) - lt_cv_deplibs_check_method=pass_all - ;; -esac -]) -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown - -_LT_DECL([], [deplibs_check_method], [1], - [Method to check whether dependent libraries are shared objects]) -_LT_DECL([], [file_magic_cmd], [1], - [Command to use when deplibs_check_method == "file_magic"]) -])# _LT_CHECK_MAGIC_METHOD - - -# LT_PATH_NM -# ---------- -# find the pathname to a BSD- or MS-compatible name lister -AC_DEFUN([LT_PATH_NM], -[AC_REQUIRE([AC_PROG_CC])dnl -AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, -[if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM="$NM" -else - lt_nm_to_check="${ac_tool_prefix}nm" - if test -n "$ac_tool_prefix" && test "$build" = "$host"; then - lt_nm_to_check="$lt_nm_to_check nm" - fi - for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - ;; - esac - fi - done - IFS="$lt_save_ifs" - done - : ${lt_cv_path_NM=no} -fi]) -if test "$lt_cv_path_NM" != "no"; then - NM="$lt_cv_path_NM" -else - # Didn't find any BSD compatible name lister, look for dumpbin. - AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :) - AC_SUBST([DUMPBIN]) - if test "$DUMPBIN" != ":"; then - NM="$DUMPBIN" - fi -fi -test -z "$NM" && NM=nm -AC_SUBST([NM]) -_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl - -AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], - [lt_cv_nm_interface="BSD nm" - echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$ac_compile" 2>conftest.err) - cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) - (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) - cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD) - cat conftest.out >&AS_MESSAGE_LOG_FD - if $GREP 'External.*some_variable' conftest.out > /dev/null; then - lt_cv_nm_interface="MS dumpbin" - fi - rm -f conftest*]) -])# LT_PATH_NM - -# Old names: -AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) -AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_PROG_NM], []) -dnl AC_DEFUN([AC_PROG_NM], []) - - -# LT_LIB_M -# -------- -# check for math library -AC_DEFUN([LT_LIB_M], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -LIBM= -case $host in -*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) - # These system don't have libm, or don't need it - ;; -*-ncr-sysv4.3*) - AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") - AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") - ;; -*) - AC_CHECK_LIB(m, cos, LIBM="-lm") - ;; -esac -AC_SUBST([LIBM]) -])# LT_LIB_M - -# Old name: -AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_CHECK_LIBM], []) - - -# _LT_COMPILER_NO_RTTI([TAGNAME]) -# ------------------------------- -m4_defun([_LT_COMPILER_NO_RTTI], -[m4_require([_LT_TAG_COMPILER])dnl - -_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= - -if test "$GCC" = yes; then - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' - - _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], - lt_cv_prog_compiler_rtti_exceptions, - [-fno-rtti -fno-exceptions], [], - [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) -fi -_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], - [Compiler flag to turn off builtin functions]) -])# _LT_COMPILER_NO_RTTI - - -# _LT_CMD_GLOBAL_SYMBOLS -# ---------------------- -m4_defun([_LT_CMD_GLOBAL_SYMBOLS], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([LT_PATH_NM])dnl -AC_REQUIRE([LT_PATH_LD])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_TAG_COMPILER])dnl - -# Check for command to grab the raw symbol name followed by C symbol from nm. -AC_MSG_CHECKING([command to parse $NM output from $compiler object]) -AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], -[ -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[[BCDEGRST]]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[[BCDT]]' - ;; -cygwin* | mingw* | pw32* | cegcc*) - symcode='[[ABCDGISTW]]' - ;; -hpux*) - if test "$host_cpu" = ia64; then - symcode='[[ABCDEGRST]]' - fi - ;; -irix* | nonstopux*) - symcode='[[BCDEGRST]]' - ;; -osf*) - symcode='[[BCDEGQRST]]' - ;; -solaris*) - symcode='[[BDRT]]' - ;; -sco3.2v5*) - symcode='[[DT]]' - ;; -sysv4.2uw2*) - symcode='[[DT]]' - ;; -sysv5* | sco5v6* | unixware* | OpenUNIX*) - symcode='[[ABDT]]' - ;; -sysv4) - symcode='[[DFNSTU]]' - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[[ABCDGIRSTW]]' ;; -esac - -# Transform an extracted symbol line into a proper C declaration. -# Some systems (esp. on ia64) link data and code symbols differently, -# so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# Try without a prefix underscore, then with it. -for ac_symprfx in "" "_"; do - - # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. - symxfrm="\\1 $ac_symprfx\\2 \\2" - - # Write the raw and C identifiers. - if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function - # and D for any global variable. - # Also find C++ and __fastcall symbols from MSVC++, - # which start with @ or ?. - lt_cv_sys_global_symbol_pipe="$AWK ['"\ -" {last_section=section; section=\$ 3};"\ -" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ -" \$ 0!~/External *\|/{next};"\ -" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ -" {if(hide[section]) next};"\ -" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ -" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ -" s[1]~/^[@?]/{print s[1], s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ -" ' prfx=^$ac_symprfx]" - else - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" - fi - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext <<_LT_EOF -#ifdef __cplusplus -extern "C" { -#endif -char nm_test_var; -void nm_test_func(void); -void nm_test_func(void){} -#ifdef __cplusplus -} -#endif -int main(){nm_test_var='a';nm_test_func();return(0);} -_LT_EOF - - if AC_TRY_EVAL(ac_compile); then - # Now try to grab the symbols. - nlist=conftest.nm - if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if $GREP ' nm_test_var$' "$nlist" >/dev/null; then - if $GREP ' nm_test_func$' "$nlist" >/dev/null; then - cat <<_LT_EOF > conftest.$ac_ext -#ifdef __cplusplus -extern "C" { -#endif - -_LT_EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' - - cat <<_LT_EOF >> conftest.$ac_ext - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - void *address; -} -lt__PROGRAM__LTX_preloaded_symbols[[]] = -{ - { "@PROGRAM@", (void *) 0 }, -_LT_EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext - cat <<\_LT_EOF >> conftest.$ac_ext - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt__PROGRAM__LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif -_LT_EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_save_LIBS="$LIBS" - lt_save_CFLAGS="$CFLAGS" - LIBS="conftstm.$ac_objext" - CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then - pipe_works=yes - fi - LIBS="$lt_save_LIBS" - CFLAGS="$lt_save_CFLAGS" - else - echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD - fi - else - echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD - cat conftest.$ac_ext >&5 - fi - rm -rf conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done -]) -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - AC_MSG_RESULT(failed) -else - AC_MSG_RESULT(ok) -fi - -_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], - [Take the output of nm and produce a listing of raw symbols and C names]) -_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], - [Transform the output of nm in a proper C declaration]) -_LT_DECL([global_symbol_to_c_name_address], - [lt_cv_sys_global_symbol_to_c_name_address], [1], - [Transform the output of nm in a C name address pair]) -_LT_DECL([global_symbol_to_c_name_address_lib_prefix], - [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], - [Transform the output of nm in a C name address pair when lib prefix is needed]) -]) # _LT_CMD_GLOBAL_SYMBOLS - - -# _LT_COMPILER_PIC([TAGNAME]) -# --------------------------- -m4_defun([_LT_COMPILER_PIC], -[m4_require([_LT_TAG_COMPILER])dnl -_LT_TAGVAR(lt_prog_compiler_wl, $1)= -_LT_TAGVAR(lt_prog_compiler_pic, $1)= -_LT_TAGVAR(lt_prog_compiler_static, $1)= - -AC_MSG_CHECKING([for $compiler option to produce PIC]) -m4_if([$1], [CXX], [ - # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - interix[[3-9]]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - else - case $host_os in - aix[[4-9]]*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68*) - # Green Hills C++ Compiler - # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - dgux*) - case $cc_basename in - ec++*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - ghcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | dragonfly*) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - if test "$host_cpu" != ia64; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - fi - ;; - aCC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - interix*) - # This is c89, which is MS Visual C++ (no shared libs) - # Anyone wants to do a port? - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) - case $cc_basename in - KCC*) - # KAI C++ Compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - ecpc* ) - # old Intel C++ for x86_64 which still supported -KPIC. - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - icpc* ) - # Intel C++, used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - cxx*) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - xlc* | xlC*) - # IBM XL 8.0 on PPC - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - esac - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd* | netbsdelf*-gnu) - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - ;; - RCC*) - # Rational C++ 2.4.1 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - cxx*) - # Digital/Compaq C++ - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - solaris*) - case $cc_basename in - CC*) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - gcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - lcc*) - # Lucid - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - *) - ;; - esac - ;; - vxworks*) - ;; - *) - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -], -[ - if test "$GCC" = yes; then - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - - interix[[3-9]]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - enable_shared=no - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - ;; - - hpux9* | hpux10* | hpux11*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC (with -KPIC) is the default. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu) - case $cc_basename in - # old Intel for x86_64 which still supported -KPIC. - ecc*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - # icc used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - icc* | ifort*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - # Lahey Fortran 8.1. - lf95*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' - _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' - ;; - pgcc* | pgf77* | pgf90* | pgf95*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - ccc*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All Alpha code is PIC. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - xl*) - # IBM XL C 8.0/Fortran 10.1 on PPC - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C 5.9 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - ;; - *Sun\ F*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='' - ;; - esac - ;; - esac - ;; - - newsos6) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - - osf3* | osf4* | osf5*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All OSF/1 code is PIC. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - rdos*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - solaris*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - case $cc_basename in - f77* | f90* | f95*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; - *) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; - esac - ;; - - sunos4*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - unicos*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - - uts4*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - *) - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -]) -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" - ;; -esac -AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) -_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], - [How to pass a linker flag through the compiler]) - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then - _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], - [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], - [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], - [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in - "" | " "*) ;; - *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; - esac], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) -fi -_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], - [Additional compiler flags for building library objects]) - -# -# Check to make sure the static flag actually works. -# -wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" -_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], - _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), - $lt_tmp_static_flag, - [], - [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) -_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], - [Compiler flag to prevent dynamic linking]) -])# _LT_COMPILER_PIC - - -# _LT_LINKER_SHLIBS([TAGNAME]) -# ---------------------------- -# See if the linker supports building shared libraries. -m4_defun([_LT_LINKER_SHLIBS], -[AC_REQUIRE([LT_PATH_LD])dnl -AC_REQUIRE([LT_PATH_NM])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl -m4_require([_LT_TAG_COMPILER])dnl -AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) -m4_if([$1], [CXX], [ - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - case $host_os in - aix[[4-9]]*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - else - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" - ;; - cygwin* | mingw* | cegcc*) - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' - ;; - linux* | k*bsd*-gnu) - _LT_TAGVAR(link_all_deplibs, $1)=no - ;; - *) - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac - _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] -], [ - runpath_var= - _LT_TAGVAR(allow_undefined_flag, $1)= - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(archive_cmds, $1)= - _LT_TAGVAR(archive_expsym_cmds, $1)= - _LT_TAGVAR(compiler_needs_object, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - _LT_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(hardcode_automatic, $1)=no - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= - _LT_TAGVAR(hardcode_libdir_separator, $1)= - _LT_TAGVAR(hardcode_minus_L, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_TAGVAR(inherit_rpath, $1)=no - _LT_TAGVAR(link_all_deplibs, $1)=unknown - _LT_TAGVAR(module_cmds, $1)= - _LT_TAGVAR(module_expsym_cmds, $1)= - _LT_TAGVAR(old_archive_from_new_cmds, $1)= - _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= - _LT_TAGVAR(thread_safe_flag_spec, $1)= - _LT_TAGVAR(whole_archive_flag_spec, $1)= - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - _LT_TAGVAR(include_expsyms, $1)= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - # Exclude shared library initialization/finalization symbols. -dnl Note also adjust exclude_expsyms for C++ above. - extract_expsyms_cmds= - - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd*) - with_gnu_ld=no - ;; - linux* | k*bsd*-gnu) - _LT_TAGVAR(link_all_deplibs, $1)=no - ;; - esac - - _LT_TAGVAR(ld_shlibs, $1)=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - supports_anon_versioning=no - case `$LD -v 2>&1` in - *GNU\ gold*) supports_anon_versioning=yes ;; - *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix[[3-9]]*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -_LT_EOF - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='' - ;; - m68k) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - interix[[3-9]]*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) - tmp_diet=no - if test "$host_os" = linux-dietlibc; then - case $cc_basename in - diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) - esac - fi - if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test "$tmp_diet" = no - then - tmp_addflag= - tmp_sharedflag='-shared' - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - lf95*) # Lahey Fortran 8.1 - _LT_TAGVAR(whole_archive_flag_spec, $1)= - tmp_sharedflag='--shared' ;; - xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) - tmp_sharedflag='-qmkshrobj' - tmp_addflag= ;; - esac - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C 5.9 - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' - _LT_TAGVAR(compiler_needs_object, $1)=yes - tmp_sharedflag='-G' ;; - *Sun\ F*) # Sun Fortran 8.3 - tmp_sharedflag='-G' ;; - esac - _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - - if test "x$supports_anon_versioning" = xyes; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - - case $cc_basename in - xlf*) - # IBM XL Fortran 10.1 on PPC cannot create shared libs itself - _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' - _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' - fi - ;; - esac - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - # For security reasons, it is highly recommended that you always - # use absolute paths for naming shared libraries, and exclude the - # DT_RUNPATH tag from executables and libraries. But doing so - # requires that you compile everything twice, which is a pain. - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - sunos4*) - _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - - if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then - runpath_var= - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=yes - _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - _LT_TAGVAR(hardcode_direct, $1)=unsupported - fi - ;; - - aix[[4-9]]*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - else - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_TAGVAR(archive_cmds, $1)='' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' - - if test "$GCC" = yes; then - case $host_os in aix4.[[012]]|aix4.[[012]].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - _LT_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - _LT_TAGVAR(link_all_deplibs, $1)=no - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - _LT_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' - _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='' - ;; - m68k) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - ;; - - bsdi[[45]]*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' - # FIXME: Should let the user specify the lib program. - _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' - _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - - darwin* | rhapsody*) - _LT_DARWIN_LINKER_FEATURES($1) - ;; - - dgux*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - freebsd1*) - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - hpux9*) - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_direct, $1)=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - ;; - - hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - fi - ;; - - hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - case $host_cpu in - hppa*64*|ia64*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - *) - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - # Try to use the -exported_symbol ld option, if it does not - # work, assume that -exports_file does not work either and - # implicitly export all symbols. - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" - AC_LINK_IFELSE(int foo(void) {}, - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' - ) - LDFLAGS="$save_LDFLAGS" - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(inherit_rpath, $1)=yes - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - newsos6) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *nto* | *qnx*) - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - else - case $host_os in - openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - ;; - esac - fi - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - os2*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - else - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' - - # Both c and cxx compiler support -rpath directly - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - solaris*) - _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' - if test "$GCC" = yes; then - wlarc='${wl}' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - else - case `$CC -V 2>&1` in - *"Compilers 5.0"*) - wlarc='' - _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' - ;; - *) - wlarc='${wl}' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - ;; - esac - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', - # but is careful enough not to reorder. - # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' - fi - ;; - esac - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4) - case $host_vendor in - sni) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' - _LT_TAGVAR(hardcode_direct, $1)=no - ;; - motorola) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4.3*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - _LT_TAGVAR(ld_shlibs, $1)=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - - if test x$host_vendor = xsni; then - case $host in - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' - ;; - esac - fi - fi -]) -AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) -test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - -_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld - -_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl -_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl -_LT_DECL([], [extract_expsyms_cmds], [2], - [The commands to extract the exported symbol list from a shared archive]) - -# -# Do we need to explicitly link libc? -# -case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in -x|xyes) - # Assume -lc should be added - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $_LT_TAGVAR(archive_cmds, $1) in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - AC_MSG_CHECKING([whether -lc should be explicitly linked in]) - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if AC_TRY_EVAL(ac_compile) 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) - pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) - _LT_TAGVAR(allow_undefined_flag, $1)= - if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) - then - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - else - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - fi - _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)]) - ;; - esac - fi - ;; -esac - -_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], - [Whether or not to add -lc for building shared libraries]) -_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], - [enable_shared_with_static_runtimes], [0], - [Whether or not to disallow shared libs when runtime libs are static]) -_LT_TAGDECL([], [export_dynamic_flag_spec], [1], - [Compiler flag to allow reflexive dlopens]) -_LT_TAGDECL([], [whole_archive_flag_spec], [1], - [Compiler flag to generate shared objects directly from archives]) -_LT_TAGDECL([], [compiler_needs_object], [1], - [Whether the compiler copes with passing no objects directly]) -_LT_TAGDECL([], [old_archive_from_new_cmds], [2], - [Create an old-style archive from a shared archive]) -_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], - [Create a temporary old-style archive to link instead of a shared archive]) -_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) -_LT_TAGDECL([], [archive_expsym_cmds], [2]) -_LT_TAGDECL([], [module_cmds], [2], - [Commands used to build a loadable module if different from building - a shared archive.]) -_LT_TAGDECL([], [module_expsym_cmds], [2]) -_LT_TAGDECL([], [with_gnu_ld], [1], - [Whether we are building with GNU ld or not]) -_LT_TAGDECL([], [allow_undefined_flag], [1], - [Flag that allows shared libraries with undefined symbols to be built]) -_LT_TAGDECL([], [no_undefined_flag], [1], - [Flag that enforces no undefined symbols]) -_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], - [Flag to hardcode $libdir into a binary during linking. - This must work even if $libdir does not exist]) -_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], - [[If ld is used when linking, flag to hardcode $libdir into a binary - during linking. This must work even if $libdir does not exist]]) -_LT_TAGDECL([], [hardcode_libdir_separator], [1], - [Whether we need a single "-rpath" flag with a separated argument]) -_LT_TAGDECL([], [hardcode_direct], [0], - [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes - DIR into the resulting binary]) -_LT_TAGDECL([], [hardcode_direct_absolute], [0], - [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes - DIR into the resulting binary and the resulting library dependency is - "absolute", i.e impossible to change by setting ${shlibpath_var} if the - library is relocated]) -_LT_TAGDECL([], [hardcode_minus_L], [0], - [Set to "yes" if using the -LDIR flag during linking hardcodes DIR - into the resulting binary]) -_LT_TAGDECL([], [hardcode_shlibpath_var], [0], - [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR - into the resulting binary]) -_LT_TAGDECL([], [hardcode_automatic], [0], - [Set to "yes" if building a shared library automatically hardcodes DIR - into the library and all subsequent libraries and executables linked - against it]) -_LT_TAGDECL([], [inherit_rpath], [0], - [Set to yes if linker adds runtime paths of dependent libraries - to runtime path list]) -_LT_TAGDECL([], [link_all_deplibs], [0], - [Whether libtool must link a program against all its dependency libraries]) -_LT_TAGDECL([], [fix_srcfile_path], [1], - [Fix the shell variable $srcfile for the compiler]) -_LT_TAGDECL([], [always_export_symbols], [0], - [Set to "yes" if exported symbols are required]) -_LT_TAGDECL([], [export_symbols_cmds], [2], - [The commands to list exported symbols]) -_LT_TAGDECL([], [exclude_expsyms], [1], - [Symbols that should not be listed in the preloaded symbols]) -_LT_TAGDECL([], [include_expsyms], [1], - [Symbols that must always be exported]) -_LT_TAGDECL([], [prelink_cmds], [2], - [Commands necessary for linking programs (against libraries) with templates]) -_LT_TAGDECL([], [file_list_spec], [1], - [Specify filename containing input files]) -dnl FIXME: Not yet implemented -dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], -dnl [Compiler flag to generate thread safe objects]) -])# _LT_LINKER_SHLIBS - - -# _LT_LANG_C_CONFIG([TAG]) -# ------------------------ -# Ensure that the configuration variables for a C compiler are suitably -# defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to `libtool'. -m4_defun([_LT_LANG_C_CONFIG], -[m4_require([_LT_DECL_EGREP])dnl -lt_save_CC="$CC" -AC_LANG_PUSH(C) - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}' - -_LT_TAG_COMPILER -# Save the default compiler, since it gets overwritten when the other -# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. -compiler_DEFAULT=$CC - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -if test -n "$compiler"; then - _LT_COMPILER_NO_RTTI($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - LT_SYS_DLOPEN_SELF - _LT_CMD_STRIPLIB - - # Report which library types will actually be built - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - - aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_CONFIG($1) -fi -AC_LANG_POP -CC="$lt_save_CC" -])# _LT_LANG_C_CONFIG - - -# _LT_PROG_CXX -# ------------ -# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++ -# compiler, we have our own version here. -m4_defun([_LT_PROG_CXX], -[ -pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes]) -AC_PROG_CXX -if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - AC_PROG_CXXCPP -else - _lt_caught_CXX_error=yes -fi -popdef([AC_MSG_ERROR]) -])# _LT_PROG_CXX - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([_LT_PROG_CXX], []) - - -# _LT_LANG_CXX_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for a C++ compiler are suitably -# defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to `libtool'. -m4_defun([_LT_LANG_CXX_CONFIG], -[AC_REQUIRE([_LT_PROG_CXX])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_EGREP])dnl - -AC_LANG_PUSH(C++) -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(compiler_needs_object, $1)=no -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for C++ test sources. -ac_ext=cpp - -# Object file extension for compiled C++ test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the CXX compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_caught_CXX_error" != yes; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="int some_variable = 0;" - - # Code to be used in simple link tests - lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC=$CC - lt_save_LD=$LD - lt_save_GCC=$GCC - GCC=$GXX - lt_save_with_gnu_ld=$with_gnu_ld - lt_save_path_LD=$lt_cv_path_LD - if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx - else - $as_unset lt_cv_prog_gnu_ld - fi - if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX - else - $as_unset lt_cv_path_LD - fi - test -z "${LDCXX+set}" || LD=$LDCXX - CC=${CXX-"c++"} - compiler=$CC - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - - if test -n "$compiler"; then - # We don't want -fno-exception when compiling C++ code, so set the - # no_builtin_flag separately - if test "$GXX" = yes; then - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' - else - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= - fi - - if test "$GXX" = yes; then - # Set up default GNU C++ configuration - - LT_PATH_LD - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='${wl}' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | - $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' - - else - GXX=no - with_gnu_ld=no - wlarc= - fi - - # PORTME: fill in a description of your system's C++ link characteristics - AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) - _LT_TAGVAR(ld_shlibs, $1)=yes - case $host_os in - aix3*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aix[[4-9]]*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_TAGVAR(archive_cmds, $1)='' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' - - if test "$GXX" = yes; then - case $host_os in aix4.[[012]]|aix4.[[012]].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - _LT_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)= - fi - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to - # export. - _LT_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an empty - # executable. - _LT_SYS_MODULE_PATH_AIX - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' - _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared - # libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - darwin* | rhapsody*) - _LT_DARWIN_LINKER_FEATURES($1) - ;; - - dgux*) - case $cc_basename in - ec++*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - ghcx*) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - freebsd[[12]]*) - # C++ shared libraries reported to be fairly broken before - # switch to ELF - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - freebsd-elf*) - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - ;; - - freebsd* | dragonfly*) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - _LT_TAGVAR(ld_shlibs, $1)=yes - ;; - - gnu*) - ;; - - hpux9*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aCC*) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' - ;; - *) - if test "$GXX" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - hpux10*|hpux11*) - if test $with_gnu_ld = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - case $host_cpu in - hppa*64*|ia64*) - ;; - *) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - ;; - esac - fi - case $host_cpu in - hppa*64*|ia64*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - *) - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aCC*) - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' - ;; - *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - interix[[3-9]]*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - irix5* | irix6*) - case $cc_basename in - CC*) - # SGI C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib' - fi - fi - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(inherit_rpath, $1)=yes - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc* | ecpc* ) - # Intel C++ - with_gnu_ld=yes - # version 8.0 and above of icpc choke on multiply defined symbols - # if we add $predep_objects and $postdep_objects, however 7.1 and - # earlier do not add the objects themselves. - case `$CC -V 2>&1` in - *"Version 7."*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 8.0 or newer - tmp_idyn= - case $host_cpu in - ia64*) tmp_idyn=' -i_dynamic';; - esac - _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - case `$CC -V` in - *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*) - _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"' - _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~ - $RANLIB $oldlib' - _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' - ;; - *) # Version 6 will use weak symbols - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' - ;; - cxx*) - # Compaq C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' - ;; - xl*) - # IBM XL 8.0 on PPC, with GNU ld - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' - _LT_TAGVAR(compiler_needs_object, $1)=yes - - # Not sure whether something based on - # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 - # would be better. - output_verbose_link_cmd='echo' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - esac - ;; - esac - ;; - - lynxos*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - m88k*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - mvs*) - case $cc_basename in - cxx*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - - *nto* | *qnx*) - _LT_TAGVAR(ld_shlibs, $1)=yes - ;; - - openbsd2*) - # C++ shared libraries are fairly broken - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - fi - output_verbose_link_cmd=echo - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - case $host in - osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; - *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; - esac - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - cxx*) - case $host in - osf3*) - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - ;; - *) - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~ - $RM $lib.exp' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - case $host in - osf3*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' - - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - psos*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - lcc*) - # Lucid - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - solaris*) - case $cc_basename in - CC*) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_TAGVAR(archive_cmds_need_lc,$1)=yes - _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. - # Supported since Solaris 2.6 (maybe 2.5.1?) - _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' - ;; - esac - _LT_TAGVAR(link_all_deplibs, $1)=yes - - output_verbose_link_cmd='echo' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - gcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' - if $CC --version | $GREP -v '^2\.7' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' - else - # g++ 2.7 appears to require `-G' NOT `-shared' on this - # platform. - _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' - fi - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - ;; - esac - fi - ;; - esac - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - vxworks*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - - AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) - test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - - _LT_TAGVAR(GCC, $1)="$GXX" - _LT_TAGVAR(LD, $1)="$LD" - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_SYS_HIDDEN_LIBDEPS($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - CC=$lt_save_CC - LDCXX=$LD - LD=$lt_save_LD - GCC=$lt_save_GCC - with_gnu_ld=$lt_save_with_gnu_ld - lt_cv_path_LDCXX=$lt_cv_path_LD - lt_cv_path_LD=$lt_save_path_LD - lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld - lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -fi # test "$_lt_caught_CXX_error" != yes - -AC_LANG_POP -])# _LT_LANG_CXX_CONFIG - - -# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) -# --------------------------------- -# Figure out "hidden" library dependencies from verbose -# compiler output when linking a shared library. -# Parse the compiler output and extract the necessary -# objects, libraries and library flags. -m4_defun([_LT_SYS_HIDDEN_LIBDEPS], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -# Dependencies to place before and after the object being linked: -_LT_TAGVAR(predep_objects, $1)= -_LT_TAGVAR(postdep_objects, $1)= -_LT_TAGVAR(predeps, $1)= -_LT_TAGVAR(postdeps, $1)= -_LT_TAGVAR(compiler_lib_search_path, $1)= - -dnl we can't use the lt_simple_compile_test_code here, -dnl because it contains code intended for an executable, -dnl not a library. It's possible we should let each -dnl tag define a new lt_????_link_test_code variable, -dnl but it's only used here... -m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF -int a; -void foo (void) { a = 0; } -_LT_EOF -], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF -class Foo -{ -public: - Foo (void) { a = 0; } -private: - int a; -}; -_LT_EOF -], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF - subroutine foo - implicit none - integer*4 a - a=0 - return - end -_LT_EOF -], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF - subroutine foo - implicit none - integer a - a=0 - return - end -_LT_EOF -], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF -public class foo { - private int a; - public void bar (void) { - a = 0; - } -}; -_LT_EOF -]) -dnl Parse the compiler output and extract the necessary -dnl objects, libraries and library flags. -if AC_TRY_EVAL(ac_compile); then - # Parse the compiler output and extract the necessary - # objects, libraries and library flags. - - # Sentinel used to keep track of whether or not we are before - # the conftest object file. - pre_test_object_deps_done=no - - for p in `eval "$output_verbose_link_cmd"`; do - case $p in - - -L* | -R* | -l*) - # Some compilers place space between "-{L,R}" and the path. - # Remove the space. - if test $p = "-L" || - test $p = "-R"; then - prev=$p - continue - else - prev= - fi - - if test "$pre_test_object_deps_done" = no; then - case $p in - -L* | -R*) - # Internal compiler library paths should come after those - # provided the user. The postdeps already come after the - # user supplied libs so there is no need to process them. - if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then - _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" - else - _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" - fi - ;; - # The "-l" case would never come before the object being - # linked, so don't bother handling this case. - esac - else - if test -z "$_LT_TAGVAR(postdeps, $1)"; then - _LT_TAGVAR(postdeps, $1)="${prev}${p}" - else - _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" - fi - fi - ;; - - *.$objext) - # This assumes that the test object file only shows up - # once in the compiler output. - if test "$p" = "conftest.$objext"; then - pre_test_object_deps_done=yes - continue - fi - - if test "$pre_test_object_deps_done" = no; then - if test -z "$_LT_TAGVAR(predep_objects, $1)"; then - _LT_TAGVAR(predep_objects, $1)="$p" - else - _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" - fi - else - if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then - _LT_TAGVAR(postdep_objects, $1)="$p" - else - _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" - fi - fi - ;; - - *) ;; # Ignore the rest. - - esac - done - - # Clean up. - rm -f a.out a.exe -else - echo "libtool.m4: error: problem compiling $1 test program" -fi - -$RM -f confest.$objext - -# PORTME: override above test on systems where it is broken -m4_if([$1], [CXX], -[case $host_os in -interix[[3-9]]*) - # Interix 3.5 installs completely hosed .la files for C++, so rather than - # hack all around it, let's just trust "g++" to DTRT. - _LT_TAGVAR(predep_objects,$1)= - _LT_TAGVAR(postdep_objects,$1)= - _LT_TAGVAR(postdeps,$1)= - ;; - -linux*) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - if test "$solaris_use_stlport4" != yes; then - _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; - -solaris*) - case $cc_basename in - CC*) - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - # Adding this requires a known-good setup of shared libraries for - # Sun compiler versions before 5.6, else PIC objects from an old - # archive will be linked into the output, leading to subtle bugs. - if test "$solaris_use_stlport4" != yes; then - _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; -esac -]) - -case " $_LT_TAGVAR(postdeps, $1) " in -*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; -esac - _LT_TAGVAR(compiler_lib_search_dirs, $1)= -if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then - _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` -fi -_LT_TAGDECL([], [compiler_lib_search_dirs], [1], - [The directories searched by this compiler when creating a shared library]) -_LT_TAGDECL([], [predep_objects], [1], - [Dependencies to place before and after the objects being linked to - create a shared library]) -_LT_TAGDECL([], [postdep_objects], [1]) -_LT_TAGDECL([], [predeps], [1]) -_LT_TAGDECL([], [postdeps], [1]) -_LT_TAGDECL([], [compiler_lib_search_path], [1], - [The library search path used internally by the compiler when linking - a shared library]) -])# _LT_SYS_HIDDEN_LIBDEPS - - -# _LT_PROG_F77 -# ------------ -# Since AC_PROG_F77 is broken, in that it returns the empty string -# if there is no fortran compiler, we have our own version here. -m4_defun([_LT_PROG_F77], -[ -pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes]) -AC_PROG_F77 -if test -z "$F77" || test "X$F77" = "Xno"; then - _lt_disable_F77=yes -fi -popdef([AC_MSG_ERROR]) -])# _LT_PROG_F77 - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([_LT_PROG_F77], []) - - -# _LT_LANG_F77_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for a Fortran 77 compiler are -# suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. -m4_defun([_LT_LANG_F77_CONFIG], -[AC_REQUIRE([_LT_PROG_F77])dnl -AC_LANG_PUSH(Fortran 77) - -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for f77 test sources. -ac_ext=f - -# Object file extension for compiled f77 test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the F77 compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_disable_F77" != yes; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="\ - subroutine t - return - end -" - - # Code to be used in simple link tests - lt_simple_link_test_code="\ - program t - end -" - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC="$CC" - lt_save_GCC=$GCC - CC=${F77-"f77"} - compiler=$CC - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - GCC=$G77 - if test -n "$compiler"; then - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_TAGVAR(GCC, $1)="$G77" - _LT_TAGVAR(LD, $1)="$LD" - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - GCC=$lt_save_GCC - CC="$lt_save_CC" -fi # test "$_lt_disable_F77" != yes - -AC_LANG_POP -])# _LT_LANG_F77_CONFIG - - -# _LT_PROG_FC -# ----------- -# Since AC_PROG_FC is broken, in that it returns the empty string -# if there is no fortran compiler, we have our own version here. -m4_defun([_LT_PROG_FC], -[ -pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes]) -AC_PROG_FC -if test -z "$FC" || test "X$FC" = "Xno"; then - _lt_disable_FC=yes -fi -popdef([AC_MSG_ERROR]) -])# _LT_PROG_FC - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([_LT_PROG_FC], []) - - -# _LT_LANG_FC_CONFIG([TAG]) -# ------------------------- -# Ensure that the configuration variables for a Fortran compiler are -# suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. -m4_defun([_LT_LANG_FC_CONFIG], -[AC_REQUIRE([_LT_PROG_FC])dnl -AC_LANG_PUSH(Fortran) - -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for fc test sources. -ac_ext=${ac_fc_srcext-f} - -# Object file extension for compiled fc test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the FC compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_disable_FC" != yes; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="\ - subroutine t - return - end -" - - # Code to be used in simple link tests - lt_simple_link_test_code="\ - program t - end -" - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC="$CC" - lt_save_GCC=$GCC - CC=${FC-"f95"} - compiler=$CC - GCC=$ac_cv_fc_compiler_gnu - - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - - if test -n "$compiler"; then - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" - _LT_TAGVAR(LD, $1)="$LD" - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_SYS_HIDDEN_LIBDEPS($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - GCC=$lt_save_GCC - CC="$lt_save_CC" -fi # test "$_lt_disable_FC" != yes - -AC_LANG_POP -])# _LT_LANG_FC_CONFIG - - -# _LT_LANG_GCJ_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for the GNU Java Compiler compiler -# are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. -m4_defun([_LT_LANG_GCJ_CONFIG], -[AC_REQUIRE([LT_PROG_GCJ])dnl -AC_LANG_SAVE - -# Source file extension for Java test sources. -ac_ext=java - -# Object file extension for compiled Java test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="class foo {}" - -# Code to be used in simple link tests -lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_TAG_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -lt_save_GCC=$GCC -GCC=yes -CC=${GCJ-"gcj"} -compiler=$CC -_LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)="$LD" -_LT_CC_BASENAME([$compiler]) - -# GCJ did not exist at the time GCC didn't implicitly link libc in. -_LT_TAGVAR(archive_cmds_need_lc, $1)=no - -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds - -if test -n "$compiler"; then - _LT_COMPILER_NO_RTTI($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) -fi - -AC_LANG_RESTORE - -GCC=$lt_save_GCC -CC="$lt_save_CC" -])# _LT_LANG_GCJ_CONFIG - - -# _LT_LANG_RC_CONFIG([TAG]) -# ------------------------- -# Ensure that the configuration variables for the Windows resource compiler -# are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. -m4_defun([_LT_LANG_RC_CONFIG], -[AC_REQUIRE([LT_PROG_RC])dnl -AC_LANG_SAVE - -# Source file extension for RC test sources. -ac_ext=rc - -# Object file extension for compiled RC test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' - -# Code to be used in simple link tests -lt_simple_link_test_code="$lt_simple_compile_test_code" - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_TAG_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -lt_save_GCC=$GCC -GCC= -CC=${RC-"windres"} -compiler=$CC -_LT_TAGVAR(compiler, $1)=$CC -_LT_CC_BASENAME([$compiler]) -_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - -if test -n "$compiler"; then - : - _LT_CONFIG($1) -fi - -GCC=$lt_save_GCC -AC_LANG_RESTORE -CC="$lt_save_CC" -])# _LT_LANG_RC_CONFIG - - -# LT_PROG_GCJ -# ----------- -AC_DEFUN([LT_PROG_GCJ], -[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], - [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], - [AC_CHECK_TOOL(GCJ, gcj,) - test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" - AC_SUBST(GCJFLAGS)])])[]dnl -]) - -# Old name: -AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_GCJ], []) - - -# LT_PROG_RC -# ---------- -AC_DEFUN([LT_PROG_RC], -[AC_CHECK_TOOL(RC, windres,) -]) - -# Old name: -AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_RC], []) - - -# _LT_DECL_EGREP -# -------------- -# If we don't have a new enough Autoconf to choose the best grep -# available, choose the one first in the user's PATH. -m4_defun([_LT_DECL_EGREP], -[AC_REQUIRE([AC_PROG_EGREP])dnl -AC_REQUIRE([AC_PROG_FGREP])dnl -test -z "$GREP" && GREP=grep -_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) -_LT_DECL([], [EGREP], [1], [An ERE matcher]) -_LT_DECL([], [FGREP], [1], [A literal string matcher]) -dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too -AC_SUBST([GREP]) -]) - - -# _LT_DECL_OBJDUMP -# -------------- -# If we don't have a new enough Autoconf to choose the best objdump -# available, choose the one first in the user's PATH. -m4_defun([_LT_DECL_OBJDUMP], -[AC_CHECK_TOOL(OBJDUMP, objdump, false) -test -z "$OBJDUMP" && OBJDUMP=objdump -_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) -AC_SUBST([OBJDUMP]) -]) - - -# _LT_DECL_SED -# ------------ -# Check for a fully-functional sed program, that truncates -# as few characters as possible. Prefer GNU sed if found. -m4_defun([_LT_DECL_SED], -[AC_PROG_SED -test -z "$SED" && SED=sed -Xsed="$SED -e 1s/^X//" -_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) -_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], - [Sed that helps us avoid accidentally triggering echo(1) options like -n]) -])# _LT_DECL_SED - -m4_ifndef([AC_PROG_SED], [ -# NOTE: This macro has been submitted for inclusion into # -# GNU Autoconf as AC_PROG_SED. When it is available in # -# a released version of Autoconf we should remove this # -# macro and use it instead. # - -m4_defun([AC_PROG_SED], -[AC_MSG_CHECKING([for a sed that does not truncate output]) -AC_CACHE_VAL(lt_cv_path_SED, -[# Loop through the user's path and test for sed and gsed. -# Then use that list of sed's as ones to test for truncation. -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for lt_ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then - lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" - fi - done - done -done -IFS=$as_save_IFS -lt_ac_max=0 -lt_ac_count=0 -# Add /usr/xpg4/bin/sed as it is typically found on Solaris -# along with /bin/sed that truncates output. -for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && continue - cat /dev/null > conftest.in - lt_ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >conftest.in - # Check for GNU sed and select it if it is found. - if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then - lt_cv_path_SED=$lt_ac_sed - break - fi - while true; do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo >>conftest.nl - $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break - cmp -s conftest.out conftest.nl || break - # 10000 chars as input seems more than enough - test $lt_ac_count -gt 10 && break - lt_ac_count=`expr $lt_ac_count + 1` - if test $lt_ac_count -gt $lt_ac_max; then - lt_ac_max=$lt_ac_count - lt_cv_path_SED=$lt_ac_sed - fi - done -done -]) -SED=$lt_cv_path_SED -AC_SUBST([SED]) -AC_MSG_RESULT([$SED]) -])#AC_PROG_SED -])#m4_ifndef - -# Old name: -AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_SED], []) - - -# _LT_CHECK_SHELL_FEATURES -# ------------------------ -# Find out whether the shell is Bourne or XSI compatible, -# or has some other useful features. -m4_defun([_LT_CHECK_SHELL_FEATURES], -[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) -# Try some XSI features -xsi_shell=no -( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,, \ - && eval 'test $(( 1 + 1 )) -eq 2 \ - && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ - && xsi_shell=yes -AC_MSG_RESULT([$xsi_shell]) -_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) - -AC_MSG_CHECKING([whether the shell understands "+="]) -lt_shell_append=no -( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ - >/dev/null 2>&1 \ - && lt_shell_append=yes -AC_MSG_RESULT([$lt_shell_append]) -_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) - -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - lt_unset=unset -else - lt_unset=false -fi -_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl - -# test EBCDIC or ASCII -case `echo X|tr X '\101'` in - A) # ASCII based system - # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr - lt_SP2NL='tr \040 \012' - lt_NL2SP='tr \015\012 \040\040' - ;; - *) # EBCDIC based system - lt_SP2NL='tr \100 \n' - lt_NL2SP='tr \r\n \100\100' - ;; -esac -_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl -_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl -])# _LT_CHECK_SHELL_FEATURES - - -# _LT_PROG_XSI_SHELLFNS -# --------------------- -# Bourne and XSI compatible variants of some useful shell functions. -m4_defun([_LT_PROG_XSI_SHELLFNS], -[case $xsi_shell in - yes) - cat << \_LT_EOF >> "$cfgfile" - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac -} - -# func_basename file -func_basename () -{ - func_basename_result="${1##*/}" -} - -# func_dirname_and_basename file append nondir_replacement -# perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# Implementation must be kept synchronized with func_dirname -# and func_basename. For efficiency, we do not delegate to -# those functions but instead duplicate the functionality here. -func_dirname_and_basename () -{ - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac - func_basename_result="${1##*/}" -} - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -func_stripname () -{ - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary parameter first. - func_stripname_result=${3} - func_stripname_result=${func_stripname_result#"${1}"} - func_stripname_result=${func_stripname_result%"${2}"} -} - -# func_opt_split -func_opt_split () -{ - func_opt_split_opt=${1%%=*} - func_opt_split_arg=${1#*=} -} - -# func_lo2o object -func_lo2o () -{ - case ${1} in - *.lo) func_lo2o_result=${1%.lo}.${objext} ;; - *) func_lo2o_result=${1} ;; - esac -} - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=${1%.*}.lo -} - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=$(( $[*] )) -} - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=${#1} -} - -_LT_EOF - ;; - *) # Bourne compatible functions. - cat << \_LT_EOF >> "$cfgfile" - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi -} - -# func_basename file -func_basename () -{ - func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` -} - -dnl func_dirname_and_basename -dnl A portable version of this function is already defined in general.m4sh -dnl so there is no need for it here. - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# func_strip_suffix prefix name -func_stripname () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; - esac -} - -# sed scripts: -my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q' -my_sed_long_arg='1s/^-[[^=]]*=//' - -# func_opt_split -func_opt_split () -{ - func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` - func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` -} - -# func_lo2o object -func_lo2o () -{ - func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` -} - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'` -} - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=`expr "$[@]"` -} - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len` -} - -_LT_EOF -esac - -case $lt_shell_append in - yes) - cat << \_LT_EOF >> "$cfgfile" - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "$[1]+=\$[2]" -} -_LT_EOF - ;; - *) - cat << \_LT_EOF >> "$cfgfile" - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "$[1]=\$$[1]\$[2]" -} - -_LT_EOF - ;; - esac -]) - -# Helper functions for option handling. -*- Autoconf -*- -# -# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. -# Written by Gary V. Vaughan, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 6 ltoptions.m4 - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) - - -# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) -# ------------------------------------------ -m4_define([_LT_MANGLE_OPTION], -[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) - - -# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) -# --------------------------------------- -# Set option OPTION-NAME for macro MACRO-NAME, and if there is a -# matching handler defined, dispatch to it. Other OPTION-NAMEs are -# saved as a flag. -m4_define([_LT_SET_OPTION], -[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl -m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), - _LT_MANGLE_DEFUN([$1], [$2]), - [m4_warning([Unknown $1 option `$2'])])[]dnl -]) - - -# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) -# ------------------------------------------------------------ -# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. -m4_define([_LT_IF_OPTION], -[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) - - -# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) -# ------------------------------------------------------- -# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME -# are set. -m4_define([_LT_UNLESS_OPTIONS], -[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), - [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), - [m4_define([$0_found])])])[]dnl -m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 -])[]dnl -]) - - -# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) -# ---------------------------------------- -# OPTION-LIST is a space-separated list of Libtool options associated -# with MACRO-NAME. If any OPTION has a matching handler declared with -# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about -# the unknown option and exit. -m4_defun([_LT_SET_OPTIONS], -[# Set options -m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), - [_LT_SET_OPTION([$1], _LT_Option)]) - -m4_if([$1],[LT_INIT],[ - dnl - dnl Simply set some default values (i.e off) if boolean options were not - dnl specified: - _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no - ]) - _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no - ]) - dnl - dnl If no reference was made to various pairs of opposing options, then - dnl we run the default mode handler for the pair. For example, if neither - dnl `shared' nor `disable-shared' was passed, we enable building of shared - dnl archives by default: - _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) - _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) - _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) - _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], - [_LT_ENABLE_FAST_INSTALL]) - ]) -])# _LT_SET_OPTIONS - - - -# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) -# ----------------------------------------- -m4_define([_LT_MANGLE_DEFUN], -[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) - - -# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) -# ----------------------------------------------- -m4_define([LT_OPTION_DEFINE], -[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl -])# LT_OPTION_DEFINE - - -# dlopen -# ------ -LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes -]) - -AU_DEFUN([AC_LIBTOOL_DLOPEN], -[_LT_SET_OPTION([LT_INIT], [dlopen]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `dlopen' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) - - -# win32-dll -# --------- -# Declare package support for building win32 dll's. -LT_OPTION_DEFINE([LT_INIT], [win32-dll], -[enable_win32_dll=yes - -case $host in -*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*) - AC_CHECK_TOOL(AS, as, false) - AC_CHECK_TOOL(DLLTOOL, dlltool, false) - AC_CHECK_TOOL(OBJDUMP, objdump, false) - ;; -esac - -test -z "$AS" && AS=as -_LT_DECL([], [AS], [0], [Assembler program])dnl - -test -z "$DLLTOOL" && DLLTOOL=dlltool -_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl - -test -z "$OBJDUMP" && OBJDUMP=objdump -_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl -])# win32-dll - -AU_DEFUN([AC_LIBTOOL_WIN32_DLL], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -_LT_SET_OPTION([LT_INIT], [win32-dll]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `win32-dll' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) - - -# _LT_ENABLE_SHARED([DEFAULT]) -# ---------------------------- -# implement the --enable-shared flag, and supports the `shared' and -# `disable-shared' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -m4_define([_LT_ENABLE_SHARED], -[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([shared], - [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], - [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) - - _LT_DECL([build_libtool_libs], [enable_shared], [0], - [Whether or not to build shared libraries]) -])# _LT_ENABLE_SHARED - -LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) - -# Old names: -AC_DEFUN([AC_ENABLE_SHARED], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) -]) - -AC_DEFUN([AC_DISABLE_SHARED], -[_LT_SET_OPTION([LT_INIT], [disable-shared]) -]) - -AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) -AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_ENABLE_SHARED], []) -dnl AC_DEFUN([AM_DISABLE_SHARED], []) - - - -# _LT_ENABLE_STATIC([DEFAULT]) -# ---------------------------- -# implement the --enable-static flag, and support the `static' and -# `disable-static' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -m4_define([_LT_ENABLE_STATIC], -[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([static], - [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], - [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_static=]_LT_ENABLE_STATIC_DEFAULT) - - _LT_DECL([build_old_libs], [enable_static], [0], - [Whether or not to build static libraries]) -])# _LT_ENABLE_STATIC - -LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) - -# Old names: -AC_DEFUN([AC_ENABLE_STATIC], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) -]) - -AC_DEFUN([AC_DISABLE_STATIC], -[_LT_SET_OPTION([LT_INIT], [disable-static]) -]) - -AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) -AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_ENABLE_STATIC], []) -dnl AC_DEFUN([AM_DISABLE_STATIC], []) - - - -# _LT_ENABLE_FAST_INSTALL([DEFAULT]) -# ---------------------------------- -# implement the --enable-fast-install flag, and support the `fast-install' -# and `disable-fast-install' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -m4_define([_LT_ENABLE_FAST_INSTALL], -[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([fast-install], - [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], - [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) - -_LT_DECL([fast_install], [enable_fast_install], [0], - [Whether or not to optimize for fast installation])dnl -])# _LT_ENABLE_FAST_INSTALL - -LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) - -# Old names: -AU_DEFUN([AC_ENABLE_FAST_INSTALL], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you put -the `fast-install' option into LT_INIT's first parameter.]) -]) - -AU_DEFUN([AC_DISABLE_FAST_INSTALL], -[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you put -the `disable-fast-install' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) -dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) - - -# _LT_WITH_PIC([MODE]) -# -------------------- -# implement the --with-pic flag, and support the `pic-only' and `no-pic' -# LT_INIT options. -# MODE is either `yes' or `no'. If omitted, it defaults to `both'. -m4_define([_LT_WITH_PIC], -[AC_ARG_WITH([pic], - [AS_HELP_STRING([--with-pic], - [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], - [pic_mode="$withval"], - [pic_mode=default]) - -test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) - -_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl -])# _LT_WITH_PIC - -LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) -LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) - -# Old name: -AU_DEFUN([AC_LIBTOOL_PICMODE], -[_LT_SET_OPTION([LT_INIT], [pic-only]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `pic-only' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) - - -m4_define([_LTDL_MODE], []) -LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], - [m4_define([_LTDL_MODE], [nonrecursive])]) -LT_OPTION_DEFINE([LTDL_INIT], [recursive], - [m4_define([_LTDL_MODE], [recursive])]) -LT_OPTION_DEFINE([LTDL_INIT], [subproject], - [m4_define([_LTDL_MODE], [subproject])]) - -m4_define([_LTDL_TYPE], []) -LT_OPTION_DEFINE([LTDL_INIT], [installable], - [m4_define([_LTDL_TYPE], [installable])]) -LT_OPTION_DEFINE([LTDL_INIT], [convenience], - [m4_define([_LTDL_TYPE], [convenience])]) - -# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- -# -# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. -# Written by Gary V. Vaughan, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 6 ltsugar.m4 - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) - - -# lt_join(SEP, ARG1, [ARG2...]) -# ----------------------------- -# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their -# associated separator. -# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier -# versions in m4sugar had bugs. -m4_define([lt_join], -[m4_if([$#], [1], [], - [$#], [2], [[$2]], - [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) -m4_define([_lt_join], -[m4_if([$#$2], [2], [], - [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) - - -# lt_car(LIST) -# lt_cdr(LIST) -# ------------ -# Manipulate m4 lists. -# These macros are necessary as long as will still need to support -# Autoconf-2.59 which quotes differently. -m4_define([lt_car], [[$1]]) -m4_define([lt_cdr], -[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], - [$#], 1, [], - [m4_dquote(m4_shift($@))])]) -m4_define([lt_unquote], $1) - - -# lt_append(MACRO-NAME, STRING, [SEPARATOR]) -# ------------------------------------------ -# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. -# Note that neither SEPARATOR nor STRING are expanded; they are appended -# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). -# No SEPARATOR is output if MACRO-NAME was previously undefined (different -# than defined and empty). -# -# This macro is needed until we can rely on Autoconf 2.62, since earlier -# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. -m4_define([lt_append], -[m4_define([$1], - m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) - - - -# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) -# ---------------------------------------------------------- -# Produce a SEP delimited list of all paired combinations of elements of -# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list -# has the form PREFIXmINFIXSUFFIXn. -# Needed until we can rely on m4_combine added in Autoconf 2.62. -m4_define([lt_combine], -[m4_if(m4_eval([$# > 3]), [1], - [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl -[[m4_foreach([_Lt_prefix], [$2], - [m4_foreach([_Lt_suffix], - ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, - [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) - - -# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) -# ----------------------------------------------------------------------- -# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited -# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. -m4_define([lt_if_append_uniq], -[m4_ifdef([$1], - [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], - [lt_append([$1], [$2], [$3])$4], - [$5])], - [lt_append([$1], [$2], [$3])$4])]) - - -# lt_dict_add(DICT, KEY, VALUE) -# ----------------------------- -m4_define([lt_dict_add], -[m4_define([$1($2)], [$3])]) - - -# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) -# -------------------------------------------- -m4_define([lt_dict_add_subkey], -[m4_define([$1($2:$3)], [$4])]) - - -# lt_dict_fetch(DICT, KEY, [SUBKEY]) -# ---------------------------------- -m4_define([lt_dict_fetch], -[m4_ifval([$3], - m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), - m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) - - -# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) -# ----------------------------------------------------------------- -m4_define([lt_if_dict_fetch], -[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], - [$5], - [$6])]) - - -# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) -# -------------------------------------------------------------- -m4_define([lt_dict_filter], -[m4_if([$5], [], [], - [lt_join(m4_quote(m4_default([$4], [[, ]])), - lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), - [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl -]) - -# ltversion.m4 -- version numbers -*- Autoconf -*- -# -# Copyright (C) 2004 Free Software Foundation, Inc. -# Written by Scott James Remnant, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# Generated from ltversion.in. - -# serial 3017 ltversion.m4 -# This file is part of GNU Libtool - -m4_define([LT_PACKAGE_VERSION], [2.2.6b]) -m4_define([LT_PACKAGE_REVISION], [1.3017]) - -AC_DEFUN([LTVERSION_VERSION], -[macro_version='2.2.6b' -macro_revision='1.3017' -_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) -_LT_DECL(, macro_revision, 0) -]) - -# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- -# -# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. -# Written by Scott James Remnant, 2004. -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 4 lt~obsolete.m4 - -# These exist entirely to fool aclocal when bootstrapping libtool. -# -# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) -# which have later been changed to m4_define as they aren't part of the -# exported API, or moved to Autoconf or Automake where they belong. -# -# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN -# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us -# using a macro with the same name in our local m4/libtool.m4 it'll -# pull the old libtool.m4 in (it doesn't see our shiny new m4_define -# and doesn't know about Autoconf macros at all.) -# -# So we provide this file, which has a silly filename so it's always -# included after everything else. This provides aclocal with the -# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything -# because those macros already exist, or will be overwritten later. -# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. -# -# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. -# Yes, that means every name once taken will need to remain here until -# we give up compatibility with versions before 1.7, at which point -# we need to keep only those names which we still refer to. - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) - -m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) -m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) -m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) -m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) -m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) -m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) -m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) -m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) -m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) -m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) -m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) -m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) -m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) -m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) -m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) -m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) -m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) -m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) -m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) -m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) -m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) -m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) -m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) -m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) -m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) -m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) -m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) -m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) -m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) -m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) -m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) -m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) -m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) -m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) -m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) -m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) -m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) -m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) -m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])]) -m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) -m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) -m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) -m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) -m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) -m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) -m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) -m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) - -# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_AUTOMAKE_VERSION(VERSION) -# ---------------------------- -# Automake X.Y traces this macro to ensure aclocal.m4 has been -# generated from the m4 files accompanying Automake X.Y. -# (This private macro should not be called outside this file.) -AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.11' -dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to -dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.11.1], [], - [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl -]) - -# _AM_AUTOCONF_VERSION(VERSION) -# ----------------------------- -# aclocal traces this macro to find the Autoconf version. -# This is a private macro too. Using m4_define simplifies -# the logic in aclocal, which can simply ignore this definition. -m4_define([_AM_AUTOCONF_VERSION], []) - -# AM_SET_CURRENT_AUTOMAKE_VERSION -# ------------------------------- -# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. -# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. -AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.11.1])dnl -m4_ifndef([AC_AUTOCONF_VERSION], - [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) - -# AM_AUX_DIR_EXPAND -*- Autoconf -*- - -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets -# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to -# `$srcdir', `$srcdir/..', or `$srcdir/../..'. -# -# Of course, Automake must honor this variable whenever it calls a -# tool from the auxiliary directory. The problem is that $srcdir (and -# therefore $ac_aux_dir as well) can be either absolute or relative, -# depending on how configure is run. This is pretty annoying, since -# it makes $ac_aux_dir quite unusable in subdirectories: in the top -# source directory, any form will work fine, but in subdirectories a -# relative path needs to be adjusted first. -# -# $ac_aux_dir/missing -# fails when called from a subdirectory if $ac_aux_dir is relative -# $top_srcdir/$ac_aux_dir/missing -# fails if $ac_aux_dir is absolute, -# fails when called from a subdirectory in a VPATH build with -# a relative $ac_aux_dir -# -# The reason of the latter failure is that $top_srcdir and $ac_aux_dir -# are both prefixed by $srcdir. In an in-source build this is usually -# harmless because $srcdir is `.', but things will broke when you -# start a VPATH build or use an absolute $srcdir. -# -# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, -# iff we strip the leading $srcdir from $ac_aux_dir. That would be: -# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` -# and then we would define $MISSING as -# MISSING="\${SHELL} $am_aux_dir/missing" -# This will work as long as MISSING is not called from configure, because -# unfortunately $(top_srcdir) has no meaning in configure. -# However there are other variables, like CC, which are often used in -# configure, and could therefore not use this "fixed" $ac_aux_dir. -# -# Another solution, used here, is to always expand $ac_aux_dir to an -# absolute PATH. The drawback is that using absolute paths prevent a -# configured tree to be moved without reconfiguration. - -AC_DEFUN([AM_AUX_DIR_EXPAND], -[dnl Rely on autoconf to set up CDPATH properly. -AC_PREREQ([2.50])dnl -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` -]) - -# AM_CONDITIONAL -*- Autoconf -*- - -# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 9 - -# AM_CONDITIONAL(NAME, SHELL-CONDITION) -# ------------------------------------- -# Define a conditional. -AC_DEFUN([AM_CONDITIONAL], -[AC_PREREQ(2.52)dnl - ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], - [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl -AC_SUBST([$1_TRUE])dnl -AC_SUBST([$1_FALSE])dnl -_AM_SUBST_NOTMAKE([$1_TRUE])dnl -_AM_SUBST_NOTMAKE([$1_FALSE])dnl -m4_define([_AM_COND_VALUE_$1], [$2])dnl -if $2; then - $1_TRUE= - $1_FALSE='#' -else - $1_TRUE='#' - $1_FALSE= -fi -AC_CONFIG_COMMANDS_PRE( -[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then - AC_MSG_ERROR([[conditional "$1" was never defined. -Usually this means the macro was only invoked conditionally.]]) -fi])]) - -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 10 - -# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be -# written in clear, in which case automake, when reading aclocal.m4, -# will think it sees a *use*, and therefore will trigger all it's -# C support machinery. Also note that it means that autoscan, seeing -# CC etc. in the Makefile, will ask for an AC_PROG_CC use... - - -# _AM_DEPENDENCIES(NAME) -# ---------------------- -# See how the compiler implements dependency checking. -# NAME is "CC", "CXX", "GCJ", or "OBJC". -# We try a few techniques and use that to set a single cache variable. -# -# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was -# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular -# dependency, and given that the user is not expected to run this macro, -# just rely on AC_PROG_CC. -AC_DEFUN([_AM_DEPENDENCIES], -[AC_REQUIRE([AM_SET_DEPDIR])dnl -AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl -AC_REQUIRE([AM_MAKE_INCLUDE])dnl -AC_REQUIRE([AM_DEP_TRACK])dnl - -ifelse([$1], CC, [depcc="$CC" am_compiler_list=], - [$1], CXX, [depcc="$CXX" am_compiler_list=], - [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], - [$1], UPC, [depcc="$UPC" am_compiler_list=], - [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], - [depcc="$$1" am_compiler_list=]) - -AC_CACHE_CHECK([dependency style of $depcc], - [am_cv_$1_dependencies_compiler_type], -[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_$1_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` - fi - am__universal=false - m4_case([$1], [CC], - [case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac], - [CXX], - [case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac]) - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvisualcpp | msvcmsys) - # This compiler won't grok `-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_$1_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_$1_dependencies_compiler_type=none -fi -]) -AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) -AM_CONDITIONAL([am__fastdep$1], [ - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) -]) - - -# AM_SET_DEPDIR -# ------------- -# Choose a directory name for dependency files. -# This macro is AC_REQUIREd in _AM_DEPENDENCIES -AC_DEFUN([AM_SET_DEPDIR], -[AC_REQUIRE([AM_SET_LEADING_DOT])dnl -AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl -]) - - -# AM_DEP_TRACK -# ------------ -AC_DEFUN([AM_DEP_TRACK], -[AC_ARG_ENABLE(dependency-tracking, -[ --disable-dependency-tracking speeds up one-time build - --enable-dependency-tracking do not reject slow dependency extractors]) -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' -fi -AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) -AC_SUBST([AMDEPBACKSLASH])dnl -_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl -]) - -# Generate code to set up dependency tracking. -*- Autoconf -*- - -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -#serial 5 - -# _AM_OUTPUT_DEPENDENCY_COMMANDS -# ------------------------------ -AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], -[{ - # Autoconf 2.62 quotes --file arguments for eval, but not when files - # are listed without --file. Let's play safe and only enable the eval - # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac - shift - for mf - do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done - done -} -])# _AM_OUTPUT_DEPENDENCY_COMMANDS - - -# AM_OUTPUT_DEPENDENCY_COMMANDS -# ----------------------------- -# This macro should only be invoked once -- use via AC_REQUIRE. -# -# This code is only required when automatic dependency tracking -# is enabled. FIXME. This creates each `.P' file that we will -# need in order to bootstrap the dependency handling code. -AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], -[AC_CONFIG_COMMANDS([depfiles], - [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) -]) - -# Do all the work for Automake. -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 16 - -# This macro actually does too much. Some checks are only needed if -# your package does certain things. But this isn't really a big deal. - -# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) -# AM_INIT_AUTOMAKE([OPTIONS]) -# ----------------------------------------------- -# The call with PACKAGE and VERSION arguments is the old style -# call (pre autoconf-2.50), which is being phased out. PACKAGE -# and VERSION should now be passed to AC_INIT and removed from -# the call to AM_INIT_AUTOMAKE. -# We support both call styles for the transition. After -# the next Automake release, Autoconf can make the AC_INIT -# arguments mandatory, and then we can depend on a new Autoconf -# release and drop the old call support. -AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.62])dnl -dnl Autoconf wants to disallow AM_ names. We explicitly allow -dnl the ones we care about. -m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl -AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl -AC_REQUIRE([AC_PROG_INSTALL])dnl -if test "`cd $srcdir && pwd`" != "`pwd`"; then - # Use -I$(srcdir) only when $(srcdir) != ., so that make's output - # is not polluted with repeated "-I." - AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl - # test to see if srcdir already configured - if test -f $srcdir/config.status; then - AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) - fi -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi -AC_SUBST([CYGPATH_W]) - -# Define the identity of the package. -dnl Distinguish between old-style and new-style calls. -m4_ifval([$2], -[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl - AC_SUBST([PACKAGE], [$1])dnl - AC_SUBST([VERSION], [$2])], -[_AM_SET_OPTIONS([$1])dnl -dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. -m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, - [m4_fatal([AC_INIT should be called with package and version arguments])])dnl - AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl - AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl - -_AM_IF_OPTION([no-define],, -[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) - AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl - -# Some tools Automake needs. -AC_REQUIRE([AM_SANITY_CHECK])dnl -AC_REQUIRE([AC_ARG_PROGRAM])dnl -AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) -AM_MISSING_PROG(AUTOCONF, autoconf) -AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) -AM_MISSING_PROG(AUTOHEADER, autoheader) -AM_MISSING_PROG(MAKEINFO, makeinfo) -AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl -AC_REQUIRE([AM_PROG_MKDIR_P])dnl -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -AC_REQUIRE([AC_PROG_AWK])dnl -AC_REQUIRE([AC_PROG_MAKE_SET])dnl -AC_REQUIRE([AM_SET_LEADING_DOT])dnl -_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], - [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], - [_AM_PROG_TAR([v7])])]) -_AM_IF_OPTION([no-dependencies],, -[AC_PROVIDE_IFELSE([AC_PROG_CC], - [_AM_DEPENDENCIES(CC)], - [define([AC_PROG_CC], - defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl -AC_PROVIDE_IFELSE([AC_PROG_CXX], - [_AM_DEPENDENCIES(CXX)], - [define([AC_PROG_CXX], - defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl -AC_PROVIDE_IFELSE([AC_PROG_OBJC], - [_AM_DEPENDENCIES(OBJC)], - [define([AC_PROG_OBJC], - defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl -]) -_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl -dnl The `parallel-tests' driver may need to know about EXEEXT, so add the -dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro -dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. -AC_CONFIG_COMMANDS_PRE(dnl -[m4_provide_if([_AM_COMPILER_EXEEXT], - [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl -]) - -dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not -dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further -dnl mangled by Autoconf and run in a shell conditional statement. -m4_define([_AC_COMPILER_EXEEXT], -m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) - - -# When config.status generates a header, we must update the stamp-h file. -# This file resides in the same directory as the config header -# that is generated. The stamp files are numbered to have different names. - -# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the -# loop where config.status creates the headers, so we can generate -# our stamp files there. -AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], -[# Compute $1's index in $config_headers. -_am_arg=$1 -_am_stamp_count=1 -for _am_header in $config_headers :; do - case $_am_header in - $_am_arg | $_am_arg:* ) - break ;; - * ) - _am_stamp_count=`expr $_am_stamp_count + 1` ;; - esac -done -echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) - -# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_SH -# ------------------ -# Define $install_sh. -AC_DEFUN([AM_PROG_INSTALL_SH], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -if test x"${install_sh}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; - *) - install_sh="\${SHELL} $am_aux_dir/install-sh" - esac -fi -AC_SUBST(install_sh)]) - -# Copyright (C) 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 2 - -# Check whether the underlying file-system supports filenames -# with a leading dot. For instance MS-DOS doesn't. -AC_DEFUN([AM_SET_LEADING_DOT], -[rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null -AC_SUBST([am__leading_dot])]) - -# Check to see how 'make' treats includes. -*- Autoconf -*- - -# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 4 - -# AM_MAKE_INCLUDE() -# ----------------- -# Check to see how make treats includes. -AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo this is the am__doit target -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -AC_MSG_CHECKING([for style of include used by $am_make]) -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from `make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi -AC_SUBST([am__include]) -AC_SUBST([am__quote]) -AC_MSG_RESULT([$_am_result]) -rm -f confinc confmf -]) - -# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- - -# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 6 - -# AM_MISSING_PROG(NAME, PROGRAM) -# ------------------------------ -AC_DEFUN([AM_MISSING_PROG], -[AC_REQUIRE([AM_MISSING_HAS_RUN]) -$1=${$1-"${am_missing_run}$2"} -AC_SUBST($1)]) - - -# AM_MISSING_HAS_RUN -# ------------------ -# Define MISSING if not defined so far and test if it supports --run. -# If it does, set am_missing_run to use it, otherwise, to nothing. -AC_DEFUN([AM_MISSING_HAS_RUN], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([missing])dnl -if test x"${MISSING+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; - *) - MISSING="\${SHELL} $am_aux_dir/missing" ;; - esac -fi -# Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " -else - am_missing_run= - AC_MSG_WARN([`missing' script is too old or missing]) -fi -]) - -# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_MKDIR_P -# --------------- -# Check for `mkdir -p'. -AC_DEFUN([AM_PROG_MKDIR_P], -[AC_PREREQ([2.60])dnl -AC_REQUIRE([AC_PROG_MKDIR_P])dnl -dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, -dnl while keeping a definition of mkdir_p for backward compatibility. -dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. -dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of -dnl Makefile.ins that do not define MKDIR_P, so we do our own -dnl adjustment using top_builddir (which is defined more often than -dnl MKDIR_P). -AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl -case $mkdir_p in - [[\\/$]]* | ?:[[\\/]]*) ;; - */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; -esac -]) - -# Helper functions for option handling. -*- Autoconf -*- - -# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 4 - -# _AM_MANGLE_OPTION(NAME) -# ----------------------- -AC_DEFUN([_AM_MANGLE_OPTION], -[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) - -# _AM_SET_OPTION(NAME) -# ------------------------------ -# Set option NAME. Presently that only means defining a flag for this option. -AC_DEFUN([_AM_SET_OPTION], -[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) - -# _AM_SET_OPTIONS(OPTIONS) -# ---------------------------------- -# OPTIONS is a space-separated list of Automake options. -AC_DEFUN([_AM_SET_OPTIONS], -[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) - -# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) -# ------------------------------------------- -# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. -AC_DEFUN([_AM_IF_OPTION], -[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) - -# Check to make sure that the build environment is sane. -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 5 - -# AM_SANITY_CHECK -# --------------- -AC_DEFUN([AM_SANITY_CHECK], -[AC_MSG_CHECKING([whether build environment is sane]) -# Just in case -sleep 1 -echo timestamp > conftest.file -# Reject unsafe characters in $srcdir or the absolute working directory -# name. Accept space and tab only in the latter. -am_lf=' -' -case `pwd` in - *[[\\\"\#\$\&\'\`$am_lf]]*) - AC_MSG_ERROR([unsafe absolute working directory name]);; -esac -case $srcdir in - *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) - AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; -esac - -# Do `set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$[*]" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - rm -f conftest.file - if test "$[*]" != "X $srcdir/configure conftest.file" \ - && test "$[*]" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken -alias in your environment]) - fi - - test "$[2]" = conftest.file - ) -then - # Ok. - : -else - AC_MSG_ERROR([newly created file is older than distributed files! -Check your system clock]) -fi -AC_MSG_RESULT(yes)]) - -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_STRIP -# --------------------- -# One issue with vendor `install' (even GNU) is that you can't -# specify the program used to strip binaries. This is especially -# annoying in cross-compiling environments, where the build's strip -# is unlikely to handle the host's binaries. -# Fortunately install-sh will honor a STRIPPROG variable, so we -# always use install-sh in `make install-strip', and initialize -# STRIPPROG with the value of the STRIP variable (set by the user). -AC_DEFUN([AM_PROG_INSTALL_STRIP], -[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -dnl Don't test for $cross_compiling = yes, because it might be `maybe'. -if test "$cross_compiling" != no; then - AC_CHECK_TOOL([STRIP], [strip], :) -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" -AC_SUBST([INSTALL_STRIP_PROGRAM])]) - -# Copyright (C) 2006, 2008 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 2 - -# _AM_SUBST_NOTMAKE(VARIABLE) -# --------------------------- -# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. -# This macro is traced by Automake. -AC_DEFUN([_AM_SUBST_NOTMAKE]) - -# AM_SUBST_NOTMAKE(VARIABLE) -# --------------------------- -# Public sister of _AM_SUBST_NOTMAKE. -AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) - -# Check how to create a tarball. -*- Autoconf -*- - -# Copyright (C) 2004, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 2 - -# _AM_PROG_TAR(FORMAT) -# -------------------- -# Check how to create a tarball in format FORMAT. -# FORMAT should be one of `v7', `ustar', or `pax'. -# -# Substitute a variable $(am__tar) that is a command -# writing to stdout a FORMAT-tarball containing the directory -# $tardir. -# tardir=directory && $(am__tar) > result.tar -# -# Substitute a variable $(am__untar) that extract such -# a tarball read from stdin. -# $(am__untar) < result.tar -AC_DEFUN([_AM_PROG_TAR], -[# Always define AMTAR for backward compatibility. -AM_MISSING_PROG([AMTAR], [tar]) -m4_if([$1], [v7], - [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], - [m4_case([$1], [ustar],, [pax],, - [m4_fatal([Unknown tar format])]) -AC_MSG_CHECKING([how to create a $1 tar archive]) -# Loop over all known methods to create a tar archive until one works. -_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' -_am_tools=${am_cv_prog_tar_$1-$_am_tools} -# Do not fold the above two line into one, because Tru64 sh and -# Solaris sh will not grok spaces in the rhs of `-'. -for _am_tool in $_am_tools -do - case $_am_tool in - gnutar) - for _am_tar in tar gnutar gtar; - do - AM_RUN_LOG([$_am_tar --version]) && break - done - am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' - am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' - am__untar="$_am_tar -xf -" - ;; - plaintar) - # Must skip GNU tar: if it does not support --format= it doesn't create - # ustar tarball either. - (tar --version) >/dev/null 2>&1 && continue - am__tar='tar chf - "$$tardir"' - am__tar_='tar chf - "$tardir"' - am__untar='tar xf -' - ;; - pax) - am__tar='pax -L -x $1 -w "$$tardir"' - am__tar_='pax -L -x $1 -w "$tardir"' - am__untar='pax -r' - ;; - cpio) - am__tar='find "$$tardir" -print | cpio -o -H $1 -L' - am__tar_='find "$tardir" -print | cpio -o -H $1 -L' - am__untar='cpio -i -H $1 -d' - ;; - none) - am__tar=false - am__tar_=false - am__untar=false - ;; - esac - - # If the value was cached, stop now. We just wanted to have am__tar - # and am__untar set. - test -n "${am_cv_prog_tar_$1}" && break - - # tar/untar a dummy directory, and stop if the command works - rm -rf conftest.dir - mkdir conftest.dir - echo GrepMe > conftest.dir/file - AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) - rm -rf conftest.dir - if test -s conftest.tar; then - AM_RUN_LOG([$am__untar /dev/null 2>&1 && break - fi -done -rm -rf conftest.dir - -AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) -AC_MSG_RESULT([$am_cv_prog_tar_$1])]) -AC_SUBST([am__tar]) -AC_SUBST([am__untar]) -]) # _AM_PROG_TAR - diff --git a/lib/enet/callbacks.c b/lib/enet/callbacks.c index f94128256..b3990af1f 100644 --- a/lib/enet/callbacks.c +++ b/lib/enet/callbacks.c @@ -27,6 +27,12 @@ enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits return enet_initialize (); } + +ENetVersion +enet_linked_version (void) +{ + return ENET_VERSION; +} void * enet_malloc (size_t size) diff --git a/lib/enet/configure b/lib/enet/configure deleted file mode 100644 index d876cebeb..000000000 --- a/lib/enet/configure +++ /dev/null @@ -1,12791 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.65 for libenet 1-8-2008. -# -# -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. -# -# -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -if test "x$CONFIG_SHELL" = x; then - as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi -" - as_required="as_fn_return () { (exit \$1); } -as_fn_success () { as_fn_return 0; } -as_fn_failure () { as_fn_return 1; } -as_fn_ret_success () { return 0; } -as_fn_ret_failure () { return 1; } - -exitcode=0 -as_fn_success || { exitcode=1; echo as_fn_success failed.; } -as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } -as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } -as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } -if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : - -else - exitcode=1; echo positional parameters were not saved. -fi -test x\$exitcode = x0 || exit 1" - as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO - as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO - eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && - test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 -test \$(( 1 + 1 )) = 2 || exit 1" - if (eval "$as_required") 2>/dev/null; then : - as_have_required=yes -else - as_have_required=no -fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : - -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_found=false -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - as_found=: - case $as_dir in #( - /*) - for as_base in sh bash ksh sh5; do - # Try only shells that exist, to save several forks. - as_shell=$as_dir/$as_base - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : - CONFIG_SHELL=$as_shell as_have_required=yes - if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : - break 2 -fi -fi - done;; - esac - as_found=false -done -$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : - CONFIG_SHELL=$SHELL as_have_required=yes -fi; } -IFS=$as_save_IFS - - - if test "x$CONFIG_SHELL" != x; then : - # We cannot yet assume a decent shell, so we have to provide a - # neutralization value for shells without unset; and this also - # works around shells that cannot unset nonexistent variables. - BASH_ENV=/dev/null - ENV=/dev/null - (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} -fi - - if test x$as_have_required = xno; then : - $as_echo "$0: This script requires a shell more modern than all" - $as_echo "$0: the shells that I found on your system." - if test x${ZSH_VERSION+set} = xset ; then - $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" - $as_echo "$0: be upgraded to zsh 4.3.4 or later." - else - $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, -$0: including any error possibly output before this -$0: message. Then install a modern shell, or manually run -$0: the script under such a shell if you do have one." - fi - exit 1 -fi -fi -fi -SHELL=${CONFIG_SHELL-/bin/sh} -export SHELL -# Unset more variables known to interfere with behavior of common tools. -CLICOLOR_FORCE= GREP_OPTIONS= -unset CLICOLOR_FORCE GREP_OPTIONS - -## --------------------- ## -## M4sh Shell Functions. ## -## --------------------- ## -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -# as_fn_error ERROR [LINENO LOG_FD] -# --------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with status $?, using 1 if that was 0. -as_fn_error () -{ - as_status=$?; test $as_status -eq 0 && as_status=1 - if test "$3"; then - as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 - fi - $as_echo "$as_me: error: $1" >&2 - as_fn_exit $as_status -} # as_fn_error - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - - - as_lineno_1=$LINENO as_lineno_1a=$LINENO - as_lineno_2=$LINENO as_lineno_2a=$LINENO - eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && - test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { - # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -p' - fi -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - - -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} - -case X$lt_ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','` - ;; -esac - -ECHO=${lt_ECHO-echo} -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then - # Yippee, $ECHO works! - : -else - # Restart under the correct shell. - exec $SHELL "$0" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat <<_LT_EOF -$* -_LT_EOF - exit 0 -fi - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -if test -z "$lt_ECHO"; then - if test "X${echo_test_string+set}" != Xset; then - # find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if { echo_test_string=`eval $cmd`; } 2>/dev/null && - { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null - then - break - fi - done - fi - - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : - else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$ECHO" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - ECHO='print -r' - elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} - else - # Try using printf. - ECHO='printf %s\n' - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - ECHO="$CONFIG_SHELL $0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$CONFIG_SHELL $0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do - if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null - then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "$0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} - else - # Oops. We lost completely, so just stick with echo. - ECHO=echo - fi - fi - fi - fi - fi -fi - -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -lt_ECHO=$ECHO -if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then - lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" -fi - - - - -test -n "$DJDIR" || exec 7<&0 &1 - -# Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_clean_files= -ac_config_libobj_dir=. -LIBOBJS= -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= - -# Identity of this package. -PACKAGE_NAME='libenet' -PACKAGE_TARNAME='libenet' -PACKAGE_VERSION='1-8-2008' -PACKAGE_STRING='libenet 1-8-2008' -PACKAGE_BUGREPORT='' -PACKAGE_URL='' - -# Factoring default headers for most tests. -ac_includes_default="\ -#include -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_STRING_H -# if !defined STDC_HEADERS && defined HAVE_MEMORY_H -# include -# endif -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif -#ifdef HAVE_INTTYPES_H -# include -#endif -#ifdef HAVE_STDINT_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif" - -ac_subst_vars='am__EXEEXT_FALSE -am__EXEEXT_TRUE -LTLIBOBJS -LIBOBJS -CPP -OTOOL64 -OTOOL -LIPO -NMEDIT -DSYMUTIL -lt_ECHO -AR -OBJDUMP -LN_S -NM -ac_ct_DUMPBIN -DUMPBIN -LD -FGREP -EGREP -GREP -SED -host_os -host_vendor -host_cpu -host -build_os -build_vendor -build_cpu -build -LIBTOOL -RANLIB -am__fastdepCC_FALSE -am__fastdepCC_TRUE -CCDEPMODE -AMDEPBACKSLASH -AMDEP_FALSE -AMDEP_TRUE -am__quote -am__include -DEPDIR -OBJEXT -EXEEXT -ac_ct_CC -CPPFLAGS -LDFLAGS -CFLAGS -CC -am__untar -am__tar -AMTAR -am__leading_dot -SET_MAKE -AWK -mkdir_p -MKDIR_P -INSTALL_STRIP_PROGRAM -STRIP -install_sh -MAKEINFO -AUTOHEADER -AUTOMAKE -AUTOCONF -ACLOCAL -VERSION -PACKAGE -CYGPATH_W -am__isrc -INSTALL_DATA -INSTALL_SCRIPT -INSTALL_PROGRAM -target_alias -host_alias -build_alias -LIBS -ECHO_T -ECHO_N -ECHO_C -DEFS -mandir -localedir -libdir -psdir -pdfdir -dvidir -htmldir -infodir -docdir -oldincludedir -includedir -localstatedir -sharedstatedir -sysconfdir -datadir -datarootdir -libexecdir -sbindir -bindir -program_transform_name -prefix -exec_prefix -PACKAGE_URL -PACKAGE_BUGREPORT -PACKAGE_STRING -PACKAGE_VERSION -PACKAGE_TARNAME -PACKAGE_NAME -PATH_SEPARATOR -SHELL' -ac_subst_files='' -ac_user_opts=' -enable_option_checking -enable_dependency_tracking -enable_shared -enable_static -with_pic -enable_fast_install -with_gnu_ld -enable_libtool_lock -enable_crc32 -' - ac_precious_vars='build_alias -host_alias -target_alias -CC -CFLAGS -LDFLAGS -LIBS -CPPFLAGS -CPP' - - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -ac_unrecognized_opts= -ac_unrecognized_sep= -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -# (The list follows the same order as the GNU Coding Standards.) -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datarootdir='${prefix}/share' -datadir='${datarootdir}' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -includedir='${prefix}/include' -oldincludedir='/usr/include' -docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' -infodir='${datarootdir}/info' -htmldir='${docdir}' -dvidir='${docdir}' -pdfdir='${docdir}' -psdir='${docdir}' -libdir='${exec_prefix}/lib' -localedir='${datarootdir}/locale' -mandir='${datarootdir}/man' - -ac_prev= -ac_dashdash= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval $ac_prev=\$ac_option - ac_prev= - continue - fi - - case $ac_option in - *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *) ac_optarg=yes ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_dashdash$ac_option in - --) - ac_dashdash=yes ;; - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=*) - datadir=$ac_optarg ;; - - -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ - | --dataroo | --dataro | --datar) - ac_prev=datarootdir ;; - -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ - | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) - datarootdir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=no ;; - - -docdir | --docdir | --docdi | --doc | --do) - ac_prev=docdir ;; - -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) - docdir=$ac_optarg ;; - - -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) - ac_prev=dvidir ;; - -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) - dvidir=$ac_optarg ;; - - -enable-* | --enable-*) - ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=\$ac_optarg ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) - ac_prev=htmldir ;; - -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ - | --ht=*) - htmldir=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localedir | --localedir | --localedi | --localed | --locale) - ac_prev=localedir ;; - -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) - localedir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst | --locals) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) - ac_prev=pdfdir ;; - -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) - pdfdir=$ac_optarg ;; - - -psdir | --psdir | --psdi | --psd | --ps) - ac_prev=psdir ;; - -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) - psdir=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=\$ac_optarg ;; - - -without-* | --without-*) - ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=no ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) as_fn_error "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information." - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - case $ac_envvar in #( - '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error "invalid variable name: \`$ac_envvar'" ;; - esac - eval $ac_envvar=\$ac_optarg - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error "missing argument to $ac_option" -fi - -if test -n "$ac_unrecognized_opts"; then - case $enable_option_checking in - no) ;; - fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; - *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; - esac -fi - -# Check all directory arguments for consistency. -for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ - datadir sysconfdir sharedstatedir localstatedir includedir \ - oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir -do - eval ac_val=\$$ac_var - # Remove trailing slashes. - case $ac_val in - */ ) - ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` - eval $ac_var=\$ac_val;; - esac - # Be sure to have absolute directory names. - case $ac_val in - [\\/$]* | ?:[\\/]* ) continue;; - NONE | '' ) case $ac_var in *prefix ) continue;; esac;; - esac - as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -ac_pwd=`pwd` && test -n "$ac_pwd" && -ac_ls_di=`ls -di .` && -ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error "working directory cannot be determined" -test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error "pwd does not report name of working directory" - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then the parent directory. - ac_confdir=`$as_dirname -- "$as_myself" || -$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_myself" : 'X\(//\)[^/]' \| \ - X"$as_myself" : 'X\(//\)$' \| \ - X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_myself" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r "$srcdir/$ac_unique_file"; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r "$srcdir/$ac_unique_file"; then - test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" -fi -ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" -ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" - pwd)` -# When building in place, set srcdir=. -if test "$ac_abs_confdir" = "$ac_pwd"; then - srcdir=. -fi -# Remove unnecessary trailing slashes from srcdir. -# Double slashes in file names in object file debugging info -# mess up M-x gdb in Emacs. -case $srcdir in -*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; -esac -for ac_var in $ac_precious_vars; do - eval ac_env_${ac_var}_set=\${${ac_var}+set} - eval ac_env_${ac_var}_value=\$${ac_var} - eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} - eval ac_cv_env_${ac_var}_value=\$${ac_var} -done - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures libenet 1-8-2008 to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/libenet] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] -_ACEOF - - cat <<\_ACEOF - -Program names: - --program-prefix=PREFIX prepend PREFIX to installed program names - --program-suffix=SUFFIX append SUFFIX to installed program names - --program-transform-name=PROGRAM run sed PROGRAM on installed program names - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] -_ACEOF -fi - -if test -n "$ac_init_help"; then - case $ac_init_help in - short | recursive ) echo "Configuration of libenet 1-8-2008:";; - esac - cat <<\_ACEOF - -Optional Features: - --disable-option-checking ignore unrecognized --enable/--with options - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --disable-dependency-tracking speeds up one-time build - --enable-dependency-tracking do not reject slow dependency extractors - --enable-shared[=PKGS] build shared libraries [default=yes] - --enable-static[=PKGS] build static libraries [default=yes] - --enable-fast-install[=PKGS] - optimize for fast installation [default=yes] - --disable-libtool-lock avoid locking (might break parallel builds) - --enable-crc32 enable CRC32 packet verification - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-pic try to use only PIC/non-PIC objects [default=use - both] - --with-gnu-ld assume the C compiler uses GNU ld [default=no] - -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - LIBS libraries to pass to the linker, e.g. -l - CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if - you have headers in a nonstandard directory - CPP C preprocessor - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -Report bugs to the package provider. -_ACEOF -ac_status=$? -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d "$ac_dir" || - { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || - continue - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - cd "$ac_dir" || { ac_status=$?; continue; } - # Check for guested configure. - if test -f "$ac_srcdir/configure.gnu"; then - echo && - $SHELL "$ac_srcdir/configure.gnu" --help=recursive - elif test -f "$ac_srcdir/configure"; then - echo && - $SHELL "$ac_srcdir/configure" --help=recursive - else - $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi || ac_status=$? - cd "$ac_pwd" || { ac_status=$?; break; } - done -fi - -test -n "$ac_init_help" && exit $ac_status -if $ac_init_version; then - cat <<\_ACEOF -libenet configure 1-8-2008 -generated by GNU Autoconf 2.65 - -Copyright (C) 2009 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit -fi - -## ------------------------ ## -## Autoconf initialization. ## -## ------------------------ ## - -# ac_fn_c_try_compile LINENO -# -------------------------- -# Try to compile conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext - if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - as_fn_set_status $ac_retval - -} # ac_fn_c_try_compile - -# ac_fn_c_try_link LINENO -# ----------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - as_fn_set_status $ac_retval - -} # ac_fn_c_try_link - -# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists and can be compiled using the include files in -# INCLUDES, setting the cache variable VAR accordingly. -ac_fn_c_check_header_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - -} # ac_fn_c_check_header_compile - -# ac_fn_c_try_cpp LINENO -# ---------------------- -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_cpp () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - as_fn_set_status $ac_retval - -} # ac_fn_c_try_cpp - -# ac_fn_c_try_run LINENO -# ---------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes -# that executables *can* be run. -ac_fn_c_try_run () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then : - ac_retval=0 -else - $as_echo "$as_me: program exited with status $ac_status" >&5 - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=$ac_status -fi - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - as_fn_set_status $ac_retval - -} # ac_fn_c_try_run - -# ac_fn_c_check_func LINENO FUNC VAR -# ---------------------------------- -# Tests whether FUNC exists, setting the cache variable VAR accordingly -ac_fn_c_check_func () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -/* Define $2 to an innocuous variant, in case declares $2. - For example, HP-UX 11i declares gettimeofday. */ -#define $2 innocuous_$2 - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $2 (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $2 - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $2 (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$2 || defined __stub___$2 -choke me -#endif - -int -main () -{ -return $2 (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - -} # ac_fn_c_check_func - -# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES -# ---------------------------------------------------- -# Tries to find if the field MEMBER exists in type AGGR, after including -# INCLUDES, setting cache variable VAR accordingly. -ac_fn_c_check_member () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 -$as_echo_n "checking for $2.$3... " >&6; } -if { as_var=$4; eval "test \"\${$as_var+set}\" = set"; }; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$5 -int -main () -{ -static $2 ac_aggr; -if (ac_aggr.$3) -return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$4=yes" -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$5 -int -main () -{ -static $2 ac_aggr; -if (sizeof ac_aggr.$3) -return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$4=yes" -else - eval "$4=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$4 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - -} # ac_fn_c_check_member - -# ac_fn_c_check_type LINENO TYPE VAR INCLUDES -# ------------------------------------------- -# Tests whether TYPE exists after having included INCLUDES, setting cache -# variable VAR accordingly. -ac_fn_c_check_type () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=no" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -if (sizeof ($2)) - return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -if (sizeof (($2))) - return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - eval "$3=yes" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - -} # ac_fn_c_check_type -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by libenet $as_me 1-8-2008, which was -generated by GNU Autoconf 2.65. Invocation command line was - - $ $0 $@ - -_ACEOF -exec 5>>config.log -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - $as_echo "PATH: $as_dir" - done -IFS=$as_save_IFS - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *\'*) - ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; - 2) - as_fn_append ac_configure_args1 " '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - as_fn_append ac_configure_args " '$ac_arg'" - ;; - esac - done -done -{ ac_configure_args0=; unset ac_configure_args0;} -{ ac_configure_args1=; unset ac_configure_args1;} - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Use '\'' to represent an apostrophe within the trap. -# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - cat <<\_ASBOX -## ---------------- ## -## Cache variables. ## -## ---------------- ## -_ASBOX - echo - # The following way of writing the cache mishandles newlines in values, -( - for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - (set) 2>&1 | - case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - sed -n \ - "s/'\''/'\''\\\\'\'''\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" - ;; #( - *) - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) - echo - - cat <<\_ASBOX -## ----------------- ## -## Output variables. ## -## ----------------- ## -_ASBOX - echo - for ac_var in $ac_subst_vars - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - - if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------------- ## -## File substitutions. ## -## ------------------- ## -_ASBOX - echo - for ac_var in $ac_subst_files - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - fi - - if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## -## confdefs.h. ## -## ----------- ## -_ASBOX - echo - cat confdefs.h - echo - fi - test "$ac_signal" != 0 && - $as_echo "$as_me: caught signal $ac_signal" - $as_echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core core.conftest.* && - rm -f -r conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status -' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -f -r conftest* confdefs.h - -$as_echo "/* confdefs.h */" > confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_URL "$PACKAGE_URL" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer an explicitly selected file to automatically selected ones. -ac_site_file1=NONE -ac_site_file2=NONE -if test -n "$CONFIG_SITE"; then - ac_site_file1=$CONFIG_SITE -elif test "x$prefix" != xNONE; then - ac_site_file1=$prefix/share/config.site - ac_site_file2=$prefix/etc/config.site -else - ac_site_file1=$ac_default_prefix/share/config.site - ac_site_file2=$ac_default_prefix/etc/config.site -fi -for ac_site_file in "$ac_site_file1" "$ac_site_file2" -do - test "x$ac_site_file" = xNONE && continue - if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -$as_echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special files - # actually), so we avoid doing that. DJGPP emulates it as a regular file. - if test /dev/null != "$cache_file" && test -f "$cache_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -$as_echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -$as_echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in $ac_precious_vars; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val=\$ac_cv_env_${ac_var}_value - eval ac_new_val=\$ac_env_${ac_var}_value - case $ac_old_set,$ac_new_set in - set,) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - # differences in whitespace do not lead to failure. - ac_old_val_w=`echo x $ac_old_val` - ac_new_val_w=`echo x $ac_new_val` - if test "$ac_old_val_w" != "$ac_new_val_w"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 -$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - ac_cache_corrupted=: - else - { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} - eval $ac_var=\$ac_old_val - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 -$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 -$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) as_fn_append ac_configure_args " '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 -fi -## -------------------- ## -## Main body of script. ## -## -------------------- ## - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -am__api_version='1.11' - -ac_aux_dir= -for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do - for ac_t in install-sh install.sh shtool; do - if test -f "$ac_dir/$ac_t"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/$ac_t -c" - break 2 - fi - done -done -if test -z "$ac_aux_dir"; then - as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -# Reject install programs that cannot install multiple files. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 -$as_echo_n "checking for a BSD-compatible install... " >&6; } -if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in #(( - ./ | .// | /[cC]/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - rm -rf conftest.one conftest.two conftest.dir - echo one > conftest.one - echo two > conftest.two - mkdir conftest.dir - if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && - test -s conftest.one && test -s conftest.two && - test -s conftest.dir/conftest.one && - test -s conftest.dir/conftest.two - then - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - fi - done - done - ;; -esac - - done -IFS=$as_save_IFS - -rm -rf conftest.one conftest.two conftest.dir - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. Don't cache a - # value for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - INSTALL=$ac_install_sh - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 -$as_echo "$INSTALL" >&6; } - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 -$as_echo_n "checking whether build environment is sane... " >&6; } -# Just in case -sleep 1 -echo timestamp > conftest.file -# Reject unsafe characters in $srcdir or the absolute working directory -# name. Accept space and tab only in the latter. -am_lf=' -' -case `pwd` in - *[\\\"\#\$\&\'\`$am_lf]*) - as_fn_error "unsafe absolute working directory name" "$LINENO" 5;; -esac -case $srcdir in - *[\\\"\#\$\&\'\`$am_lf\ \ ]*) - as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; -esac - -# Do `set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$*" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - rm -f conftest.file - if test "$*" != "X $srcdir/configure conftest.file" \ - && test "$*" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - as_fn_error "ls -t appears to fail. Make sure there is not a broken -alias in your environment" "$LINENO" 5 - fi - - test "$2" = conftest.file - ) -then - # Ok. - : -else - as_fn_error "newly created file is older than distributed files! -Check your system clock" "$LINENO" 5 -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -test "$program_prefix" != NONE && - program_transform_name="s&^&$program_prefix&;$program_transform_name" -# Use a double $ so make ignores it. -test "$program_suffix" != NONE && - program_transform_name="s&\$&$program_suffix&;$program_transform_name" -# Double any \ or $. -# By default was `s,x,x', remove it if useless. -ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' -program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` - -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` - -if test x"${MISSING+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; - *) - MISSING="\${SHELL} $am_aux_dir/missing" ;; - esac -fi -# Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " -else - am_missing_run= - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 -$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} -fi - -if test x"${install_sh}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; - *) - install_sh="\${SHELL} $am_aux_dir/install-sh" - esac -fi - -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -if test "$cross_compiling" != no; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_STRIP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 -$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } -if test -z "$MKDIR_P"; then - if test "${ac_cv_path_mkdir+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in mkdir gmkdir; do - for ac_exec_ext in '' $ac_executable_extensions; do - { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue - case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( - 'mkdir (GNU coreutils) '* | \ - 'mkdir (coreutils) '* | \ - 'mkdir (fileutils) '4.1*) - ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext - break 3;; - esac - done - done - done -IFS=$as_save_IFS - -fi - - test -d ./--version && rmdir ./--version - if test "${ac_cv_path_mkdir+set}" = set; then - MKDIR_P="$ac_cv_path_mkdir -p" - else - # As a last resort, use the slow shell script. Don't cache a - # value for MKDIR_P within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - MKDIR_P="$ac_install_sh -d" - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 -$as_echo "$MKDIR_P" >&6; } - -mkdir_p="$MKDIR_P" -case $mkdir_p in - [\\/$]* | ?:[\\/]*) ;; - */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; -esac - -for ac_prog in gawk mawk nawk awk -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_AWK+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_AWK="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AWK=$ac_cv_prog_AWK -if test -n "$AWK"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 -$as_echo "$AWK" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$AWK" && break -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } -set x ${MAKE-make} -ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then : - $as_echo_n "(cached) " >&6 -else - cat >conftest.make <<\_ACEOF -SHELL = /bin/sh -all: - @echo '@@@%%%=$(MAKE)=@@@%%%' -_ACEOF -# GNU make sometimes prints "make[1]: Entering...", which would confuse us. -case `${MAKE-make} -f conftest.make 2>/dev/null` in - *@@@%%%=?*=@@@%%%*) - eval ac_cv_prog_make_${ac_make}_set=yes;; - *) - eval ac_cv_prog_make_${ac_make}_set=no;; -esac -rm -f conftest.make -fi -if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - SET_MAKE= -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - SET_MAKE="MAKE=${MAKE-make}" -fi - -rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null - -if test "`cd $srcdir && pwd`" != "`pwd`"; then - # Use -I$(srcdir) only when $(srcdir) != ., so that make's output - # is not polluted with repeated "-I." - am__isrc=' -I$(srcdir)' - # test to see if srcdir already configured - if test -f $srcdir/config.status; then - as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 - fi -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi - - -# Define the identity of the package. - PACKAGE=libenet.a - VERSION=1-8-2008 - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE "$PACKAGE" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define VERSION "$VERSION" -_ACEOF - -# Some tools Automake needs. - -ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} - - -AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} - - -AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} - - -AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} - - -MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} - -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -# Always define AMTAR for backward compatibility. - -AMTAR=${AMTAR-"${am_missing_run}tar"} - -am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' - - - - - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "no acceptable C compiler found in \$PATH -See \`config.log' for more details." "$LINENO" 5; } - -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 -$as_echo_n "checking whether the C compiler works... " >&6; } -ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` - -# The possible output files: -ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" - -ac_rmfiles= -for ac_file in $ac_files -do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - * ) ac_rmfiles="$ac_rmfiles $ac_file";; - esac -done -rm -f $ac_rmfiles - -if { { ac_try="$ac_link_default" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link_default") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. -# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' -# in a Makefile. We should not override ac_cv_exeext if it was cached, -# so that the user can short-circuit this test for compilers unknown to -# Autoconf. -for ac_file in $ac_files '' -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; - then :; else - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - fi - # We set ac_cv_exeext here because the later test for it is not - # safe: cross compilers may not add the suffix if given an `-o' - # argument, so we may need to know it at that point already. - # Even if this section looks crufty: it has the advantage of - # actually working. - break;; - * ) - break;; - esac -done -test "$ac_cv_exeext" = no && ac_cv_exeext= - -else - ac_file='' -fi -if test -z "$ac_file"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -$as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ as_fn_set_status 77 -as_fn_error "C compiler cannot create executables -See \`config.log' for more details." "$LINENO" 5; }; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 -$as_echo_n "checking for C compiler default output file name... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 -$as_echo "$ac_file" >&6; } -ac_exeext=$ac_cv_exeext - -rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 -$as_echo_n "checking for suffix of executables... " >&6; } -if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - break;; - * ) break;; - esac -done -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." "$LINENO" 5; } -fi -rm -f conftest conftest$ac_cv_exeext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 -$as_echo "$ac_cv_exeext" >&6; } - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -FILE *f = fopen ("conftest.out", "w"); - return ferror (f) || fclose (f) != 0; - - ; - return 0; -} -_ACEOF -ac_clean_files="$ac_clean_files conftest.out" -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 -$as_echo_n "checking whether we are cross compiling... " >&6; } -if test "$cross_compiling" != yes; then - { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if { ac_try='./conftest$ac_cv_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." "$LINENO" 5; } - fi - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 -$as_echo "$cross_compiling" >&6; } - -rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 -$as_echo_n "checking for suffix of object files... " >&6; } -if test "${ac_cv_objext+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - for ac_file in conftest.o conftest.obj conftest.*; do - test -f "$ac_file" || continue; - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot compute suffix of object files: cannot compile -See \`config.log' for more details." "$LINENO" 5; } -fi -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 -$as_echo "$ac_cv_objext" >&6; } -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_c89=$ac_arg -fi -rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : - -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -DEPDIR="${am__leading_dot}deps" - -ac_config_commands="$ac_config_commands depfiles" - - -am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo this is the am__doit target -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 -$as_echo_n "checking for style of include used by $am_make... " >&6; } -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from `make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 -$as_echo "$_am_result" >&6; } -rm -f confinc confmf - -# Check whether --enable-dependency-tracking was given. -if test "${enable_dependency_tracking+set}" = set; then : - enableval=$enable_dependency_tracking; -fi - -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' -fi - if test "x$enable_dependency_tracking" != xno; then - AMDEP_TRUE= - AMDEP_FALSE='#' -else - AMDEP_TRUE='#' - AMDEP_FALSE= -fi - - - -depcc="$CC" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CC_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvisualcpp | msvcmsys) - # This compiler won't grok `-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CC_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CC_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } -CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then - am__fastdepCC_TRUE= - am__fastdepCC_FALSE='#' -else - am__fastdepCC_TRUE='#' - am__fastdepCC_FALSE= -fi - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. -set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_RANLIB+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -RANLIB=$ac_cv_prog_RANLIB -if test -n "$RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 -$as_echo "$RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_RANLIB"; then - ac_ct_RANLIB=$RANLIB - # Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_RANLIB"; then - ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_RANLIB="ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB -if test -n "$ac_ct_RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 -$as_echo "$ac_ct_RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_RANLIB" = x; then - RANLIB=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - RANLIB=$ac_ct_RANLIB - fi -else - RANLIB="$ac_cv_prog_RANLIB" -fi - -case `pwd` in - *\ * | *\ *) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 -$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; -esac - - - -macro_version='2.2.6b' -macro_revision='1.3017' - - - - - - - - - - - - - -ltmain="$ac_aux_dir/ltmain.sh" - -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -$as_echo_n "checking build system type... " >&6; } -if test "${ac_cv_build+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_build_alias=$build_alias -test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` -test "x$ac_build_alias" = x && - as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5 -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -$as_echo "$ac_cv_build" >&6; } -case $ac_cv_build in -*-*-*) ;; -*) as_fn_error "invalid value of canonical build" "$LINENO" 5;; -esac -build=$ac_cv_build -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_build -shift -build_cpu=$1 -build_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -build_os=$* -IFS=$ac_save_IFS -case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if test "${ac_cv_host+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build -else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) as_fn_error "invalid value of canonical host" "$LINENO" 5;; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 -$as_echo_n "checking for a sed that does not truncate output... " >&6; } -if test "${ac_cv_path_SED+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ - for ac_i in 1 2 3 4 5 6 7; do - ac_script="$ac_script$as_nl$ac_script" - done - echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed - { ac_script=; unset ac_script;} - if test -z "$SED"; then - ac_path_SED_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue -# Check for GNU ac_path_SED and select it if it is found. - # Check for GNU $ac_path_SED -case `"$ac_path_SED" --version 2>&1` in -*GNU*) - ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo '' >> "conftest.nl" - "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_SED_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_SED="$ac_path_SED" - ac_path_SED_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_SED_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_SED"; then - as_fn_error "no acceptable sed could be found in \$PATH" "$LINENO" 5 - fi -else - ac_cv_path_SED=$SED -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 -$as_echo "$ac_cv_path_SED" >&6; } - SED="$ac_cv_path_SED" - rm -f conftest.sed - -test -z "$SED" && SED=sed -Xsed="$SED -e 1s/^X//" - - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 -$as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if test "${ac_cv_path_GREP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$GREP"; then - ac_path_GREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in grep ggrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue -# Check for GNU ac_path_GREP and select it if it is found. - # Check for GNU $ac_path_GREP -case `"$ac_path_GREP" --version 2>&1` in -*GNU*) - ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'GREP' >> "conftest.nl" - "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_GREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_GREP="$ac_path_GREP" - ac_path_GREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_GREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_GREP"; then - as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_GREP=$GREP -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 -$as_echo "$ac_cv_path_GREP" >&6; } - GREP="$ac_cv_path_GREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -$as_echo_n "checking for egrep... " >&6; } -if test "${ac_cv_path_EGREP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 - then ac_cv_path_EGREP="$GREP -E" - else - if test -z "$EGREP"; then - ac_path_EGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue -# Check for GNU ac_path_EGREP and select it if it is found. - # Check for GNU $ac_path_EGREP -case `"$ac_path_EGREP" --version 2>&1` in -*GNU*) - ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'EGREP' >> "conftest.nl" - "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_EGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_EGREP="$ac_path_EGREP" - ac_path_EGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_EGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_EGREP"; then - as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_EGREP=$EGREP -fi - - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -$as_echo "$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 -$as_echo_n "checking for fgrep... " >&6; } -if test "${ac_cv_path_FGREP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 - then ac_cv_path_FGREP="$GREP -F" - else - if test -z "$FGREP"; then - ac_path_FGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in fgrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue -# Check for GNU ac_path_FGREP and select it if it is found. - # Check for GNU $ac_path_FGREP -case `"$ac_path_FGREP" --version 2>&1` in -*GNU*) - ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'FGREP' >> "conftest.nl" - "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_FGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_FGREP="$ac_path_FGREP" - ac_path_FGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_FGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_FGREP"; then - as_fn_error "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_FGREP=$FGREP -fi - - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 -$as_echo "$ac_cv_path_FGREP" >&6; } - FGREP="$ac_cv_path_FGREP" - - -test -z "$GREP" && GREP=grep - - - - - - - - - - - - - - - - - - - -# Check whether --with-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes -else - with_gnu_ld=no -fi - -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 -$as_echo_n "checking for ld used by $CC... " >&6; } - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | ?:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` - while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do - ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 -$as_echo_n "checking for GNU ld... " >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 -$as_echo_n "checking for non-GNU ld... " >&6; } -fi -if test "${lt_cv_path_LD+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &5 -$as_echo "$LD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 -$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } -if test "${lt_cv_prog_gnu_ld+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - # I'd rather use --version here, but apparently some GNU lds only accept -v. -case `$LD -v 2>&1 &5 -$as_echo "$lt_cv_prog_gnu_ld" >&6; } -with_gnu_ld=$lt_cv_prog_gnu_ld - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 -$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } -if test "${lt_cv_path_NM+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM="$NM" -else - lt_nm_to_check="${ac_tool_prefix}nm" - if test -n "$ac_tool_prefix" && test "$build" = "$host"; then - lt_nm_to_check="$lt_nm_to_check nm" - fi - for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - ;; - esac - fi - done - IFS="$lt_save_ifs" - done - : ${lt_cv_path_NM=no} -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 -$as_echo "$lt_cv_path_NM" >&6; } -if test "$lt_cv_path_NM" != "no"; then - NM="$lt_cv_path_NM" -else - # Didn't find any BSD compatible name lister, look for dumpbin. - if test -n "$ac_tool_prefix"; then - for ac_prog in "dumpbin -symbols" "link -dump -symbols" - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_DUMPBIN+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$DUMPBIN"; then - ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -DUMPBIN=$ac_cv_prog_DUMPBIN -if test -n "$DUMPBIN"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 -$as_echo "$DUMPBIN" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$DUMPBIN" && break - done -fi -if test -z "$DUMPBIN"; then - ac_ct_DUMPBIN=$DUMPBIN - for ac_prog in "dumpbin -symbols" "link -dump -symbols" -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_DUMPBIN"; then - ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN -if test -n "$ac_ct_DUMPBIN"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 -$as_echo "$ac_ct_DUMPBIN" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_DUMPBIN" && break -done - - if test "x$ac_ct_DUMPBIN" = x; then - DUMPBIN=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - DUMPBIN=$ac_ct_DUMPBIN - fi -fi - - - if test "$DUMPBIN" != ":"; then - NM="$DUMPBIN" - fi -fi -test -z "$NM" && NM=nm - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 -$as_echo_n "checking the name lister ($NM) interface... " >&6; } -if test "${lt_cv_nm_interface+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_nm_interface="BSD nm" - echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:4573: $ac_compile\"" >&5) - (eval "$ac_compile" 2>conftest.err) - cat conftest.err >&5 - (eval echo "\"\$as_me:4576: $NM \\\"conftest.$ac_objext\\\"\"" >&5) - (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) - cat conftest.err >&5 - (eval echo "\"\$as_me:4579: output\"" >&5) - cat conftest.out >&5 - if $GREP 'External.*some_variable' conftest.out > /dev/null; then - lt_cv_nm_interface="MS dumpbin" - fi - rm -f conftest* -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 -$as_echo "$lt_cv_nm_interface" >&6; } - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 -$as_echo_n "checking whether ln -s works... " >&6; } -LN_S=$as_ln_s -if test "$LN_S" = "ln -s"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 -$as_echo "no, using $LN_S" >&6; } -fi - -# find the maximum length of command line arguments -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 -$as_echo_n "checking the maximum length of command line arguments... " >&6; } -if test "${lt_cv_sys_max_cmd_len+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - i=0 - teststring="ABCD" - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw* | cegcc*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) - # This has been around since 386BSD, at least. Likely further. - if test -x /sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` - elif test -x /usr/sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` - else - lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs - fi - # And add a safety zone - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - ;; - - interix*) - # We know the value 262144 and hardcode it with a safety zone (like BSD) - lt_cv_sys_max_cmd_len=196608 - ;; - - osf*) - # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure - # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not - # nice to cause kernel panics so lets avoid the loop below. - # First set a reasonable default. - lt_cv_sys_max_cmd_len=16384 - # - if test -x /sbin/sysconfig; then - case `/sbin/sysconfig -q proc exec_disable_arg_limit` in - *1*) lt_cv_sys_max_cmd_len=-1 ;; - esac - fi - ;; - sco3.2v5*) - lt_cv_sys_max_cmd_len=102400 - ;; - sysv5* | sco5v6* | sysv4.2uw2*) - kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` - if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` - else - lt_cv_sys_max_cmd_len=32768 - fi - ;; - *) - lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len"; then - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - else - # Make teststring a little bigger before we do anything with it. - # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8 ; do - teststring=$teststring$teststring - done - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ - = "XX$teststring$teststring"; } >/dev/null 2>&1 && - test $i != 17 # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - # Only check the string length outside the loop. - lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` - teststring= - # Add a significant safety factor because C++ compilers can tack on - # massive amounts of additional arguments before passing them to the - # linker. It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - fi - ;; - esac - -fi - -if test -n $lt_cv_sys_max_cmd_len ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 -$as_echo "$lt_cv_sys_max_cmd_len" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 -$as_echo "none" >&6; } -fi -max_cmd_len=$lt_cv_sys_max_cmd_len - - - - - - -: ${CP="cp -f"} -: ${MV="mv -f"} -: ${RM="rm -f"} - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 -$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } -# Try some XSI features -xsi_shell=no -( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,, \ - && eval 'test $(( 1 + 1 )) -eq 2 \ - && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ - && xsi_shell=yes -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 -$as_echo "$xsi_shell" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 -$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } -lt_shell_append=no -( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ - >/dev/null 2>&1 \ - && lt_shell_append=yes -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 -$as_echo "$lt_shell_append" >&6; } - - -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - lt_unset=unset -else - lt_unset=false -fi - - - - - -# test EBCDIC or ASCII -case `echo X|tr X '\101'` in - A) # ASCII based system - # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr - lt_SP2NL='tr \040 \012' - lt_NL2SP='tr \015\012 \040\040' - ;; - *) # EBCDIC based system - lt_SP2NL='tr \100 \n' - lt_NL2SP='tr \r\n \100\100' - ;; -esac - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 -$as_echo_n "checking for $LD option to reload object files... " >&6; } -if test "${lt_cv_ld_reload_flag+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_ld_reload_flag='-r' -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 -$as_echo "$lt_cv_ld_reload_flag" >&6; } -reload_flag=$lt_cv_ld_reload_flag -case $reload_flag in -"" | " "*) ;; -*) reload_flag=" $reload_flag" ;; -esac -reload_cmds='$LD$reload_flag -o $output$reload_objs' -case $host_os in - darwin*) - if test "$GCC" = yes; then - reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' - else - reload_cmds='$LD$reload_flag -o $output$reload_objs' - fi - ;; -esac - - - - - - - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. -set dummy ${ac_tool_prefix}objdump; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_OBJDUMP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$OBJDUMP"; then - ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -OBJDUMP=$ac_cv_prog_OBJDUMP -if test -n "$OBJDUMP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 -$as_echo "$OBJDUMP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_OBJDUMP"; then - ac_ct_OBJDUMP=$OBJDUMP - # Extract the first word of "objdump", so it can be a program name with args. -set dummy objdump; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_OBJDUMP"; then - ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_OBJDUMP="objdump" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP -if test -n "$ac_ct_OBJDUMP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 -$as_echo "$ac_ct_OBJDUMP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_OBJDUMP" = x; then - OBJDUMP="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - OBJDUMP=$ac_ct_OBJDUMP - fi -else - OBJDUMP="$ac_cv_prog_OBJDUMP" -fi - -test -z "$OBJDUMP" && OBJDUMP=objdump - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 -$as_echo_n "checking how to recognize dependent libraries... " >&6; } -if test "${lt_cv_deplibs_check_method+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_file_magic_cmd='$MAGIC_CMD' -lt_cv_file_magic_test_file= -lt_cv_deplibs_check_method='unknown' -# Need to set the preceding variable on all platforms that support -# interlibrary dependencies. -# 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. -# 'pass_all' -- all dependencies passed with no checks. -# 'test_compile' -- check by making test program. -# 'file_magic [[regex]]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given extended regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. - -case $host_os in -aix[4-9]*) - lt_cv_deplibs_check_method=pass_all - ;; - -beos*) - lt_cv_deplibs_check_method=pass_all - ;; - -bsdi[45]*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - lt_cv_file_magic_cmd='/usr/bin/file -L' - lt_cv_file_magic_test_file=/shlib/libc.so - ;; - -cygwin*) - # func_win32_libid is a shell function defined in ltmain.sh - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - ;; - -mingw* | pw32*) - # Base MSYS/MinGW do not provide the 'file' command needed by - # func_win32_libid shell function, so use a weaker test based on 'objdump', - # unless we find 'file', for example because we are cross-compiling. - if ( file / ) >/dev/null 2>&1; then - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - else - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - fi - ;; - -cegcc) - # use the weaker test based on 'objdump'. See mingw*. - lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - ;; - -darwin* | rhapsody*) - lt_cv_deplibs_check_method=pass_all - ;; - -freebsd* | dragonfly*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case $host_cpu in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -interix[3-9]*) - # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be Linux ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -*nto* | *qnx*) - lt_cv_deplibs_check_method=pass_all - ;; - -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -rdos*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.3*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - pc) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -tpf*) - lt_cv_deplibs_check_method=pass_all - ;; -esac - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 -$as_echo "$lt_cv_deplibs_check_method" >&6; } -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown - - - - - - - - - - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. -set dummy ${ac_tool_prefix}ar; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_AR+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AR"; then - ac_cv_prog_AR="$AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_AR="${ac_tool_prefix}ar" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AR=$ac_cv_prog_AR -if test -n "$AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 -$as_echo "$AR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_AR"; then - ac_ct_AR=$AR - # Extract the first word of "ar", so it can be a program name with args. -set dummy ar; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_AR+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_AR"; then - ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_AR="ar" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_AR=$ac_cv_prog_ac_ct_AR -if test -n "$ac_ct_AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 -$as_echo "$ac_ct_AR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_AR" = x; then - AR="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - AR=$ac_ct_AR - fi -else - AR="$ac_cv_prog_AR" -fi - -test -z "$AR" && AR=ar -test -z "$AR_FLAGS" && AR_FLAGS=cru - - - - - - - - - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_STRIP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - -test -z "$STRIP" && STRIP=: - - - - - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. -set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_RANLIB+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -RANLIB=$ac_cv_prog_RANLIB -if test -n "$RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 -$as_echo "$RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_RANLIB"; then - ac_ct_RANLIB=$RANLIB - # Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_RANLIB"; then - ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_RANLIB="ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB -if test -n "$ac_ct_RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 -$as_echo "$ac_ct_RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_RANLIB" = x; then - RANLIB=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - RANLIB=$ac_ct_RANLIB - fi -else - RANLIB="$ac_cv_prog_RANLIB" -fi - -test -z "$RANLIB" && RANLIB=: - - - - - - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" - ;; - *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" -fi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# Check for command to grab the raw symbol name followed by C symbol from nm. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 -$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } -if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[BCDEGRST]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([_A-Za-z][_A-Za-z0-9]*\)' - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[BCDT]' - ;; -cygwin* | mingw* | pw32* | cegcc*) - symcode='[ABCDGISTW]' - ;; -hpux*) - if test "$host_cpu" = ia64; then - symcode='[ABCDEGRST]' - fi - ;; -irix* | nonstopux*) - symcode='[BCDEGRST]' - ;; -osf*) - symcode='[BCDEGQRST]' - ;; -solaris*) - symcode='[BDRT]' - ;; -sco3.2v5*) - symcode='[DT]' - ;; -sysv4.2uw2*) - symcode='[DT]' - ;; -sysv5* | sco5v6* | unixware* | OpenUNIX*) - symcode='[ABDT]' - ;; -sysv4) - symcode='[DFNSTU]' - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[ABCDGIRSTW]' ;; -esac - -# Transform an extracted symbol line into a proper C declaration. -# Some systems (esp. on ia64) link data and code symbols differently, -# so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# Try without a prefix underscore, then with it. -for ac_symprfx in "" "_"; do - - # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. - symxfrm="\\1 $ac_symprfx\\2 \\2" - - # Write the raw and C identifiers. - if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function - # and D for any global variable. - # Also find C++ and __fastcall symbols from MSVC++, - # which start with @ or ?. - lt_cv_sys_global_symbol_pipe="$AWK '"\ -" {last_section=section; section=\$ 3};"\ -" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ -" \$ 0!~/External *\|/{next};"\ -" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ -" {if(hide[section]) next};"\ -" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ -" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ -" s[1]~/^[@?]/{print s[1], s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ -" ' prfx=^$ac_symprfx" - else - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" - fi - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext <<_LT_EOF -#ifdef __cplusplus -extern "C" { -#endif -char nm_test_var; -void nm_test_func(void); -void nm_test_func(void){} -#ifdef __cplusplus -} -#endif -int main(){nm_test_var='a';nm_test_func();return(0);} -_LT_EOF - - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - # Now try to grab the symbols. - nlist=conftest.nm - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5 - (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if $GREP ' nm_test_var$' "$nlist" >/dev/null; then - if $GREP ' nm_test_func$' "$nlist" >/dev/null; then - cat <<_LT_EOF > conftest.$ac_ext -#ifdef __cplusplus -extern "C" { -#endif - -_LT_EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' - - cat <<_LT_EOF >> conftest.$ac_ext - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - void *address; -} -lt__PROGRAM__LTX_preloaded_symbols[] = -{ - { "@PROGRAM@", (void *) 0 }, -_LT_EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext - cat <<\_LT_EOF >> conftest.$ac_ext - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt__PROGRAM__LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif -_LT_EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_save_LIBS="$LIBS" - lt_save_CFLAGS="$CFLAGS" - LIBS="conftstm.$ac_objext" - CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 - (eval $ac_link) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext}; then - pipe_works=yes - fi - LIBS="$lt_save_LIBS" - CFLAGS="$lt_save_CFLAGS" - else - echo "cannot find nm_test_func in $nlist" >&5 - fi - else - echo "cannot find nm_test_var in $nlist" >&5 - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 - fi - else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - fi - rm -rf conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done - -fi - -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 -$as_echo "failed" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 -$as_echo "ok" >&6; } -fi - - - - - - - - - - - - - - - - - - - - - - - -# Check whether --enable-libtool-lock was given. -if test "${enable_libtool_lock+set}" = set; then : - enableval=$enable_libtool_lock; -fi - -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE="32" - ;; - *ELF-64*) - HPUX_IA64_MODE="64" - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out which ABI we are using. - echo '#line 5785 "configure"' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - if test "$lt_cv_prog_gnu_ld" = yes; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ -s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - case `/usr/bin/file conftest.o` in - *32-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_i386_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_i386" - ;; - ppc64-*linux*|powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_x86_64_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - ppc*-*linux*|powerpc*-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*|s390*-*tpf*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -belf" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 -$as_echo_n "checking whether the C compiler needs -belf... " >&6; } -if test "${lt_cv_cc_needs_belf+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - lt_cv_cc_needs_belf=yes -else - lt_cv_cc_needs_belf=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 -$as_echo "$lt_cv_cc_needs_belf" >&6; } - if test x"$lt_cv_cc_needs_belf" != x"yes"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" - fi - ;; -sparc*-*solaris*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - case `/usr/bin/file conftest.o` in - *64-bit*) - case $lt_cv_prog_gnu_ld in - yes*) LD="${LD-ld} -m elf64_sparc" ;; - *) - if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then - LD="${LD-ld} -64" - fi - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; -esac - -need_locks="$enable_libtool_lock" - - - case $host_os in - rhapsody* | darwin*) - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. -set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_DSYMUTIL+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$DSYMUTIL"; then - ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -DSYMUTIL=$ac_cv_prog_DSYMUTIL -if test -n "$DSYMUTIL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 -$as_echo "$DSYMUTIL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_DSYMUTIL"; then - ac_ct_DSYMUTIL=$DSYMUTIL - # Extract the first word of "dsymutil", so it can be a program name with args. -set dummy dsymutil; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_DSYMUTIL"; then - ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL -if test -n "$ac_ct_DSYMUTIL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 -$as_echo "$ac_ct_DSYMUTIL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_DSYMUTIL" = x; then - DSYMUTIL=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - DSYMUTIL=$ac_ct_DSYMUTIL - fi -else - DSYMUTIL="$ac_cv_prog_DSYMUTIL" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. -set dummy ${ac_tool_prefix}nmedit; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_NMEDIT+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$NMEDIT"; then - ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -NMEDIT=$ac_cv_prog_NMEDIT -if test -n "$NMEDIT"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 -$as_echo "$NMEDIT" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_NMEDIT"; then - ac_ct_NMEDIT=$NMEDIT - # Extract the first word of "nmedit", so it can be a program name with args. -set dummy nmedit; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_NMEDIT"; then - ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_NMEDIT="nmedit" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT -if test -n "$ac_ct_NMEDIT"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 -$as_echo "$ac_ct_NMEDIT" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_NMEDIT" = x; then - NMEDIT=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - NMEDIT=$ac_ct_NMEDIT - fi -else - NMEDIT="$ac_cv_prog_NMEDIT" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. -set dummy ${ac_tool_prefix}lipo; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_LIPO+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$LIPO"; then - ac_cv_prog_LIPO="$LIPO" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_LIPO="${ac_tool_prefix}lipo" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -LIPO=$ac_cv_prog_LIPO -if test -n "$LIPO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 -$as_echo "$LIPO" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_LIPO"; then - ac_ct_LIPO=$LIPO - # Extract the first word of "lipo", so it can be a program name with args. -set dummy lipo; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_LIPO"; then - ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_LIPO="lipo" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO -if test -n "$ac_ct_LIPO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 -$as_echo "$ac_ct_LIPO" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_LIPO" = x; then - LIPO=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - LIPO=$ac_ct_LIPO - fi -else - LIPO="$ac_cv_prog_LIPO" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. -set dummy ${ac_tool_prefix}otool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_OTOOL+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$OTOOL"; then - ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_OTOOL="${ac_tool_prefix}otool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -OTOOL=$ac_cv_prog_OTOOL -if test -n "$OTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 -$as_echo "$OTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_OTOOL"; then - ac_ct_OTOOL=$OTOOL - # Extract the first word of "otool", so it can be a program name with args. -set dummy otool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_OTOOL"; then - ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_OTOOL="otool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL -if test -n "$ac_ct_OTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 -$as_echo "$ac_ct_OTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_OTOOL" = x; then - OTOOL=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - OTOOL=$ac_ct_OTOOL - fi -else - OTOOL="$ac_cv_prog_OTOOL" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. -set dummy ${ac_tool_prefix}otool64; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_OTOOL64+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$OTOOL64"; then - ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -OTOOL64=$ac_cv_prog_OTOOL64 -if test -n "$OTOOL64"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 -$as_echo "$OTOOL64" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_OTOOL64"; then - ac_ct_OTOOL64=$OTOOL64 - # Extract the first word of "otool64", so it can be a program name with args. -set dummy otool64; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_OTOOL64"; then - ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_OTOOL64="otool64" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 -if test -n "$ac_ct_OTOOL64"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 -$as_echo "$ac_ct_OTOOL64" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_OTOOL64" = x; then - OTOOL64=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - OTOOL64=$ac_ct_OTOOL64 - fi -else - OTOOL64="$ac_cv_prog_OTOOL64" -fi - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 -$as_echo_n "checking for -single_module linker flag... " >&6; } -if test "${lt_cv_apple_cc_single_mod+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_apple_cc_single_mod=no - if test -z "${LT_MULTI_MODULE}"; then - # By default we will add the -single_module flag. You can override - # by either setting the environment variable LT_MULTI_MODULE - # non-empty at configure time, or by adding -multi_module to the - # link flags. - rm -rf libconftest.dylib* - echo "int foo(void){return 1;}" > conftest.c - echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ --dynamiclib -Wl,-single_module conftest.c" >&5 - $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ - -dynamiclib -Wl,-single_module conftest.c 2>conftest.err - _lt_result=$? - if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then - lt_cv_apple_cc_single_mod=yes - else - cat conftest.err >&5 - fi - rm -rf libconftest.dylib* - rm -f conftest.* - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 -$as_echo "$lt_cv_apple_cc_single_mod" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 -$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } -if test "${lt_cv_ld_exported_symbols_list+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_ld_exported_symbols_list=no - save_LDFLAGS=$LDFLAGS - echo "_main" > conftest.sym - LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - lt_cv_ld_exported_symbols_list=yes -else - lt_cv_ld_exported_symbols_list=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 -$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } - case $host_os in - rhapsody* | darwin1.[012]) - _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; - darwin1.*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - darwin*) # darwin 5.x on - # if running on 10.5 or later, the deployment target defaults - # to the OS version, if on x86, and 10.4, the deployment - # target defaults to 10.4. Don't you love it? - case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in - 10.0,*86*-darwin8*|10.0,*-darwin[91]*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - 10.[012]*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - 10.*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - esac - ;; - esac - if test "$lt_cv_apple_cc_single_mod" = "yes"; then - _lt_dar_single_mod='$single_module' - fi - if test "$lt_cv_ld_exported_symbols_list" = "yes"; then - _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' - else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - if test "$DSYMUTIL" != ":"; then - _lt_dsymutil='~$DSYMUTIL $lib || :' - else - _lt_dsymutil= - fi - ;; - esac - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 -$as_echo_n "checking how to run the C preprocessor... " >&6; } -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 -$as_echo "$CPP" >&6; } -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." "$LINENO" 5; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if test "${ac_cv_header_stdc+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -$as_echo "#define STDC_HEADERS 1" >>confdefs.h - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -" -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - -for ac_header in dlfcn.h -do : - ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default -" -if test "x$ac_cv_header_dlfcn_h" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_DLFCN_H 1 -_ACEOF - -fi - -done - - - -# Set options - - - - enable_dlopen=no - - - enable_win32_dll=no - - - # Check whether --enable-shared was given. -if test "${enable_shared+set}" = set; then : - enableval=$enable_shared; p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_shared=yes -fi - - - - - - - - - - # Check whether --enable-static was given. -if test "${enable_static+set}" = set; then : - enableval=$enable_static; p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_static=yes -fi - - - - - - - - - - -# Check whether --with-pic was given. -if test "${with_pic+set}" = set; then : - withval=$with_pic; pic_mode="$withval" -else - pic_mode=default -fi - - -test -z "$pic_mode" && pic_mode=default - - - - - - - - # Check whether --enable-fast-install was given. -if test "${enable_fast_install+set}" = set; then : - enableval=$enable_fast_install; p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_fast_install=yes -fi - - - - - - - - - - - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ltmain" - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' - - - - - - - - - - - - - - - - - - - - - - - - - -test -z "$LN_S" && LN_S="ln -s" - - - - - - - - - - - - - - -if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 -$as_echo_n "checking for objdir... " >&6; } -if test "${lt_cv_objdir+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 -$as_echo "$lt_cv_objdir" >&6; } -objdir=$lt_cv_objdir - - - - - -cat >>confdefs.h <<_ACEOF -#define LT_OBJDIR "$lt_cv_objdir/" -_ACEOF - - - - - - - - - - - - - - - - - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s/\(["`$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -# Global variables: -ofile=libtool -can_build_shared=yes - -# All known linkers require a `.a' archive for static linking (except MSVC, -# which needs '.lib'). -libext=a - -with_gnu_ld="$lt_cv_prog_gnu_ld" - -old_CC="$CC" -old_CFLAGS="$CFLAGS" - -# Set sane defaults for various variables -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS -test -z "$LD" && LD=ld -test -z "$ac_objext" && ac_objext=o - -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - -# Only perform the check for file, if the check method requires it -test -z "$MAGIC_CMD" && MAGIC_CMD=file -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 -$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } -if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - case $MAGIC_CMD in -[\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/${ac_tool_prefix}file; then - lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <<_LT_EOF 1>&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -_LT_EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac -fi - -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 -$as_echo "$MAGIC_CMD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - - - -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 -$as_echo_n "checking for file... " >&6; } -if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - case $MAGIC_CMD in -[\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/file; then - lt_cv_path_MAGIC_CMD="$ac_dir/file" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <<_LT_EOF 1>&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -_LT_EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac -fi - -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 -$as_echo "$MAGIC_CMD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - else - MAGIC_CMD=: - fi -fi - - fi - ;; -esac - -# Use C for the default configuration in the libtool script - -lt_save_CC="$CC" -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -objext=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}' - - - - - - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - -# Save the default compiler, since it gets overwritten when the other -# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. -compiler_DEFAULT=$CC - -# save warnings/boilerplate of simple test code -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$RM conftest* - -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$RM -r conftest* - - -if test -n "$compiler"; then - -lt_prog_compiler_no_builtin_flag= - -if test "$GCC" = yes; then - lt_prog_compiler_no_builtin_flag=' -fno-builtin' - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 -$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } -if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_rtti_exceptions=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7311: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:7315: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_rtti_exceptions=yes - fi - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 -$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } - -if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then - lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" -else - : -fi - -fi - - - - - - - lt_prog_compiler_wl= -lt_prog_compiler_pic= -lt_prog_compiler_static= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 -$as_echo_n "checking for $compiler option to produce PIC... " >&6; } - - if test "$GCC" = yes; then - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_static='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - lt_prog_compiler_pic='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - lt_prog_compiler_pic='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic='-fno-common' - ;; - - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic='-fPIC' - ;; - esac - ;; - - interix[3-9]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - lt_prog_compiler_can_build_shared=no - enable_shared=no - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - lt_prog_compiler_pic='-fPIC -shared' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic=-Kconform_pic - fi - ;; - - *) - lt_prog_compiler_pic='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - lt_prog_compiler_wl='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - else - lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' - fi - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - lt_prog_compiler_wl='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - lt_prog_compiler_wl='-Wl,' - # PIC (with -KPIC) is the default. - lt_prog_compiler_static='-non_shared' - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu) - case $cc_basename in - # old Intel for x86_64 which still supported -KPIC. - ecc*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-static' - ;; - # icc used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - icc* | ifort*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fPIC' - lt_prog_compiler_static='-static' - ;; - # Lahey Fortran 8.1. - lf95*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='--shared' - lt_prog_compiler_static='--static' - ;; - pgcc* | pgf77* | pgf90* | pgf95*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fpic' - lt_prog_compiler_static='-Bstatic' - ;; - ccc*) - lt_prog_compiler_wl='-Wl,' - # All Alpha code is PIC. - lt_prog_compiler_static='-non_shared' - ;; - xl*) - # IBM XL C 8.0/Fortran 10.1 on PPC - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-qpic' - lt_prog_compiler_static='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C 5.9 - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='-Wl,' - ;; - *Sun\ F*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='' - ;; - esac - ;; - esac - ;; - - newsos6) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - lt_prog_compiler_pic='-fPIC -shared' - ;; - - osf3* | osf4* | osf5*) - lt_prog_compiler_wl='-Wl,' - # All OSF/1 code is PIC. - lt_prog_compiler_static='-non_shared' - ;; - - rdos*) - lt_prog_compiler_static='-non_shared' - ;; - - solaris*) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - case $cc_basename in - f77* | f90* | f95*) - lt_prog_compiler_wl='-Qoption ld ';; - *) - lt_prog_compiler_wl='-Wl,';; - esac - ;; - - sunos4*) - lt_prog_compiler_wl='-Qoption ld ' - lt_prog_compiler_pic='-PIC' - lt_prog_compiler_static='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - lt_prog_compiler_pic='-Kconform_pic' - lt_prog_compiler_static='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - unicos*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_can_build_shared=no - ;; - - uts4*) - lt_prog_compiler_pic='-pic' - lt_prog_compiler_static='-Bstatic' - ;; - - *) - lt_prog_compiler_can_build_shared=no - ;; - esac - fi - -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic= - ;; - *) - lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" - ;; -esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5 -$as_echo "$lt_prog_compiler_pic" >&6; } - - - - - - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 -$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } -if test "${lt_cv_prog_compiler_pic_works+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_pic_works=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic -DPIC" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7650: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:7654: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_pic_works=yes - fi - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 -$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } - -if test x"$lt_cv_prog_compiler_pic_works" = xyes; then - case $lt_prog_compiler_pic in - "" | " "*) ;; - *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; - esac -else - lt_prog_compiler_pic= - lt_prog_compiler_can_build_shared=no -fi - -fi - - - - - - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } -if test "${lt_cv_prog_compiler_static_works+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_static_works=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_static_works=yes - fi - else - lt_cv_prog_compiler_static_works=yes - fi - fi - $RM -r conftest* - LDFLAGS="$save_LDFLAGS" - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 -$as_echo "$lt_cv_prog_compiler_static_works" >&6; } - -if test x"$lt_cv_prog_compiler_static_works" = xyes; then - : -else - lt_prog_compiler_static= -fi - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if test "${lt_cv_prog_compiler_c_o+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_c_o=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7755: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:7759: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o=yes - fi - fi - chmod u+w . 2>&5 - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 -$as_echo "$lt_cv_prog_compiler_c_o" >&6; } - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 -$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if test "${lt_cv_prog_compiler_c_o+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_c_o=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7810: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:7814: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o=yes - fi - fi - chmod u+w . 2>&5 - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 -$as_echo "$lt_cv_prog_compiler_c_o" >&6; } - - - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 -$as_echo_n "checking if we can lock with hard links... " >&6; } - hard_links=yes - $RM conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 -$as_echo "$hard_links" >&6; } - if test "$hard_links" = no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } - - runpath_var= - allow_undefined_flag= - always_export_symbols=no - archive_cmds= - archive_expsym_cmds= - compiler_needs_object=no - enable_shared_with_static_runtimes=no - export_dynamic_flag_spec= - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - hardcode_automatic=no - hardcode_direct=no - hardcode_direct_absolute=no - hardcode_libdir_flag_spec= - hardcode_libdir_flag_spec_ld= - hardcode_libdir_separator= - hardcode_minus_L=no - hardcode_shlibpath_var=unsupported - inherit_rpath=no - link_all_deplibs=unknown - module_cmds= - module_expsym_cmds= - old_archive_from_new_cmds= - old_archive_from_expsyms_cmds= - thread_safe_flag_spec= - whole_archive_flag_spec= - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - include_expsyms= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - # Exclude shared library initialization/finalization symbols. - extract_expsyms_cmds= - - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd*) - with_gnu_ld=no - ;; - linux* | k*bsd*-gnu) - link_all_deplibs=no - ;; - esac - - ld_shlibs=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - export_dynamic_flag_spec='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec= - fi - supports_anon_versioning=no - case `$LD -v 2>&1` in - *GNU\ gold*) supports_anon_versioning=yes ;; - *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix[3-9]*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - ld_shlibs=no - cat <<_LT_EOF 1>&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -_LT_EOF - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='' - ;; - m68k) - archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - ;; - esac - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs=no - fi - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec='-L$libdir' - allow_undefined_flag=unsupported - always_export_symbols=no - enable_shared_with_static_runtimes=yes - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs=no - fi - ;; - - interix[3-9]*) - hardcode_direct=no - hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) - tmp_diet=no - if test "$host_os" = linux-dietlibc; then - case $cc_basename in - diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) - esac - fi - if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test "$tmp_diet" = no - then - tmp_addflag= - tmp_sharedflag='-shared' - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - lf95*) # Lahey Fortran 8.1 - whole_archive_flag_spec= - tmp_sharedflag='--shared' ;; - xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) - tmp_sharedflag='-qmkshrobj' - tmp_addflag= ;; - esac - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' - compiler_needs_object=yes - tmp_sharedflag='-G' ;; - *Sun\ F*) # Sun Fortran 8.3 - tmp_sharedflag='-G' ;; - esac - archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - - if test "x$supports_anon_versioning" = xyes; then - archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - - case $cc_basename in - xlf*) - # IBM XL Fortran 10.1 on PPC cannot create shared libs itself - whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' - hardcode_libdir_flag_spec= - hardcode_libdir_flag_spec_ld='-rpath $libdir' - archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then - archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' - fi - ;; - esac - else - ld_shlibs=no - fi - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then - ld_shlibs=no - cat <<_LT_EOF 1>&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) - ld_shlibs=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - # For security reasons, it is highly recommended that you always - # use absolute paths for naming shared libraries, and exclude the - # DT_RUNPATH tag from executables and libraries. But doing so - # requires that you compile everything twice, which is a pain. - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - ;; - - sunos4*) - archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - *) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - - if test "$ld_shlibs" = no; then - runpath_var= - hardcode_libdir_flag_spec= - export_dynamic_flag_spec= - whole_archive_flag_spec= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - allow_undefined_flag=unsupported - always_export_symbols=yes - archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct=unsupported - fi - ;; - - aix[4-9]*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds='' - hardcode_direct=yes - hardcode_direct_absolute=yes - hardcode_libdir_separator=':' - link_all_deplibs=yes - file_list_spec='${wl}-f,' - - if test "$GCC" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - hardcode_direct=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L=yes - hardcode_libdir_flag_spec='-L$libdir' - hardcode_libdir_separator= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - link_all_deplibs=no - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - export_dynamic_flag_spec='${wl}-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag='-berok' - # Determine the default libpath from the value encoded in an - # empty executable. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag=' ${wl}-bernotok' - allow_undefined_flag=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec='$convenience' - archive_cmds_need_lc=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='' - ;; - m68k) - archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - ;; - esac - ;; - - bsdi[45]*) - export_dynamic_flag_spec=-rdynamic - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_from_new_cmds='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path='`cygpath -w "$srcfile"`' - enable_shared_with_static_runtimes=yes - ;; - - darwin* | rhapsody*) - - - archive_cmds_need_lc=no - hardcode_direct=no - hardcode_automatic=yes - hardcode_shlibpath_var=unsupported - whole_archive_flag_spec='' - link_all_deplibs=yes - allow_undefined_flag="$_lt_dar_allow_undefined" - case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; - *) _lt_dar_can_shared=$GCC ;; - esac - if test "$_lt_dar_can_shared" = "yes"; then - output_verbose_link_cmd=echo - archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" - - else - ld_shlibs=no - fi - - ;; - - dgux*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - freebsd1*) - ld_shlibs=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) - archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - hpux9*) - if test "$GCC" = yes; then - archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - export_dynamic_flag_spec='${wl}-E' - ;; - - hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_flag_spec_ld='+b $libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - hardcode_direct_absolute=yes - export_dynamic_flag_spec='${wl}-E' - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - fi - ;; - - hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case $host_cpu in - hppa*64*) - archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - - case $host_cpu in - hppa*64*|ia64*) - hardcode_direct=no - hardcode_shlibpath_var=no - ;; - *) - hardcode_direct=yes - hardcode_direct_absolute=yes - export_dynamic_flag_spec='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - # Try to use the -exported_symbol ld option, if it does not - # work, assume that -exports_file does not work either and - # implicitly export all symbols. - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -int foo(void) {} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' - -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" - else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' - fi - archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - inherit_rpath=yes - link_all_deplibs=yes - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - newsos6) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_shlibpath_var=no - ;; - - *nto* | *qnx*) - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - hardcode_direct=yes - hardcode_shlibpath_var=no - hardcode_direct_absolute=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' - else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-R$libdir' - ;; - *) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - ;; - esac - fi - else - ld_shlibs=no - fi - ;; - - os2*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - allow_undefined_flag=unsupported - archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - fi - archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' - - # Both c and cxx compiler support -rpath directly - hardcode_libdir_flag_spec='-rpath $libdir' - fi - archive_cmds_need_lc='no' - hardcode_libdir_separator=: - ;; - - solaris*) - no_undefined_flag=' -z defs' - if test "$GCC" = yes; then - wlarc='${wl}' - archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - else - case `$CC -V 2>&1` in - *"Compilers 5.0"*) - wlarc='' - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' - ;; - *) - wlarc='${wl}' - archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - ;; - esac - fi - hardcode_libdir_flag_spec='-R$libdir' - hardcode_shlibpath_var=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', - # but is careful enough not to reorder. - # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - else - whole_archive_flag_spec='-z allextract$convenience -z defaultextract' - fi - ;; - esac - link_all_deplibs=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - hardcode_libdir_flag_spec='-L$libdir' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - sysv4) - case $host_vendor in - sni) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' - reload_cmds='$CC -r -o $output$reload_objs' - hardcode_direct=no - ;; - motorola) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no - ;; - - sysv4.3*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - export_dynamic_flag_spec='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag='${wl}-z,text' - archive_cmds_need_lc=no - hardcode_shlibpath_var=no - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - no_undefined_flag='${wl}-z,text' - allow_undefined_flag='${wl}-z,nodefs' - archive_cmds_need_lc=no - hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-R,$libdir' - hardcode_libdir_separator=':' - link_all_deplibs=yes - export_dynamic_flag_spec='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - *) - ld_shlibs=no - ;; - esac - - if test x$host_vendor = xsni; then - case $host in - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - export_dynamic_flag_spec='${wl}-Blargedynsym' - ;; - esac - fi - fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 -$as_echo "$ld_shlibs" >&6; } -test "$ld_shlibs" = no && can_build_shared=no - -with_gnu_ld=$with_gnu_ld - - - - - - - - - - - - - - - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 -$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl - pic_flag=$lt_prog_compiler_pic - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag - allow_undefined_flag= - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 - (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - then - archive_cmds_need_lc=no - else - archive_cmds_need_lc=yes - fi - allow_undefined_flag=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5 -$as_echo "$archive_cmds_need_lc" >&6; } - ;; - esac - fi - ;; -esac - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 -$as_echo_n "checking dynamic linker characteristics... " >&6; } - -if test "$GCC" = yes; then - case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; - esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` - else - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. - lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` - for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else - test -d "$lt_sys_path" && \ - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" - fi - done - lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; - for (lt_i = NF; lt_i > 0; lt_i--) { - if ($lt_i != "" && $lt_i != ".") { - if ($lt_i == "..") { - lt_count++; - } else { - if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; - } else { - lt_count--; - } - } - } - } - if (lt_foo != "") { lt_freq[lt_foo]++; } - if (lt_freq[lt_foo] == 1) { print lt_foo; } -}'` - sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix[4-9]*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - case $host_cpu in - powerpc) - # Since July 2007 AmigaOS4 officially supports .so libraries. - # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - ;; - m68k) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - esac - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32* | cegcc*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw* | cegcc*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[123]*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -interix[3-9]*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # Some binutils ld are patched to set DT_RUNPATH - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ - LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : - shlibpath_overrides_runpath=yes -fi -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -*nto* | *qnx*) - version_type=qnx - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='ldqnx.so' - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -tpf*) - # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 -$as_echo "$dynamic_linker" >&6; } -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" -fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" -fi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 -$as_echo_n "checking how to hardcode library paths into programs... " >&6; } -hardcode_action= -if test -n "$hardcode_libdir_flag_spec" || - test -n "$runpath_var" || - test "X$hardcode_automatic" = "Xyes" ; then - - # We can hardcode non-existent directories. - if test "$hardcode_direct" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && - test "$hardcode_minus_L" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action=unsupported -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 -$as_echo "$hardcode_action" >&6; } - -if test "$hardcode_action" = relink || - test "$inherit_rpath" = yes; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - - - - - - - if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32* | cegcc*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 -$as_echo_n "checking for dlopen in -ldl... " >&6; } -if test "${ac_cv_lib_dl_dlopen+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dl_dlopen=yes -else - ac_cv_lib_dl_dlopen=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 -$as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - -fi - - ;; - - *) - ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" -if test "x$ac_cv_func_shl_load" = x""yes; then : - lt_cv_dlopen="shl_load" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 -$as_echo_n "checking for shl_load in -ldld... " >&6; } -if test "${ac_cv_lib_dld_shl_load+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char shl_load (); -int -main () -{ -return shl_load (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dld_shl_load=yes -else - ac_cv_lib_dld_shl_load=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 -$as_echo "$ac_cv_lib_dld_shl_load" >&6; } -if test "x$ac_cv_lib_dld_shl_load" = x""yes; then : - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" -else - ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" -if test "x$ac_cv_func_dlopen" = x""yes; then : - lt_cv_dlopen="dlopen" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 -$as_echo_n "checking for dlopen in -ldl... " >&6; } -if test "${ac_cv_lib_dl_dlopen+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dl_dlopen=yes -else - ac_cv_lib_dl_dlopen=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 -$as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 -$as_echo_n "checking for dlopen in -lsvld... " >&6; } -if test "${ac_cv_lib_svld_dlopen+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lsvld $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_svld_dlopen=yes -else - ac_cv_lib_svld_dlopen=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 -$as_echo "$ac_cv_lib_svld_dlopen" >&6; } -if test "x$ac_cv_lib_svld_dlopen" = x""yes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 -$as_echo_n "checking for dld_link in -ldld... " >&6; } -if test "${ac_cv_lib_dld_dld_link+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dld_link (); -int -main () -{ -return dld_link (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dld_dld_link=yes -else - ac_cv_lib_dld_dld_link=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 -$as_echo "$ac_cv_lib_dld_dld_link" >&6; } -if test "x$ac_cv_lib_dld_dld_link" = x""yes; then : - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" -fi - - -fi - - -fi - - -fi - - -fi - - -fi - - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 -$as_echo_n "checking whether a program can dlopen itself... " >&6; } -if test "${lt_cv_dlopen_self+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext <<_LT_EOF -#line 10194 "configure" -#include "confdefs.h" - -#if HAVE_DLFCN_H -#include -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - else - puts (dlerror ()); - - return status; -} -_LT_EOF - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 - (eval $ac_link) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) >&5 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self=no - fi -fi -rm -fr conftest* - - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 -$as_echo "$lt_cv_dlopen_self" >&6; } - - if test "x$lt_cv_dlopen_self" = xyes; then - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 -$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } -if test "${lt_cv_dlopen_self_static+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self_static=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext <<_LT_EOF -#line 10290 "configure" -#include "confdefs.h" - -#if HAVE_DLFCN_H -#include -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - else - puts (dlerror ()); - - return status; -} -_LT_EOF - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 - (eval $ac_link) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) >&5 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self_static=no - fi -fi -rm -fr conftest* - - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 -$as_echo "$lt_cv_dlopen_self_static" >&6; } - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi - - - - - - - - - - - - - - - - - -striplib= -old_striplib= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 -$as_echo_n "checking whether stripping libraries is possible... " >&6; } -if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - old_striplib="$STRIP -S" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - fi - ;; - *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - ;; - esac -fi - - - - - - - - - - - - - # Report which library types will actually be built - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 -$as_echo_n "checking if libtool supports shared libraries... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 -$as_echo "$can_build_shared" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 -$as_echo_n "checking whether to build shared libraries... " >&6; } - test "$can_build_shared" = "no" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - - aix[4-9]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - esac - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 -$as_echo "$enable_shared" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 -$as_echo_n "checking whether to build static libraries... " >&6; } - # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 -$as_echo "$enable_static" >&6; } - - - - -fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - - - - - - - - - - - - - ac_config_commands="$ac_config_commands libtool" - - - - -# Only expand once: - - - -ac_fn_c_check_func "$LINENO" "gethostbyaddr_r" "ac_cv_func_gethostbyaddr_r" -if test "x$ac_cv_func_gethostbyaddr_r" = x""yes; then : - $as_echo "#define HAS_GETHOSTBYADDR_R 1" >>confdefs.h - -fi - -ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r" -if test "x$ac_cv_func_gethostbyname_r" = x""yes; then : - $as_echo "#define HAS_GETHOSTBYNAME_R 1" >>confdefs.h - -fi - -ac_fn_c_check_func "$LINENO" "poll" "ac_cv_func_poll" -if test "x$ac_cv_func_poll" = x""yes; then : - $as_echo "#define HAS_POLL 1" >>confdefs.h - -fi - -ac_fn_c_check_func "$LINENO" "fcntl" "ac_cv_func_fcntl" -if test "x$ac_cv_func_fcntl" = x""yes; then : - $as_echo "#define HAS_FCNTL 1" >>confdefs.h - -fi - -ac_fn_c_check_func "$LINENO" "inet_pton" "ac_cv_func_inet_pton" -if test "x$ac_cv_func_inet_pton" = x""yes; then : - $as_echo "#define HAS_INET_PTON 1" >>confdefs.h - -fi - -ac_fn_c_check_func "$LINENO" "inet_ntop" "ac_cv_func_inet_ntop" -if test "x$ac_cv_func_inet_ntop" = x""yes; then : - $as_echo "#define HAS_INET_NTOP 1" >>confdefs.h - -fi - - -ac_fn_c_check_member "$LINENO" "struct msghdr" "msg_flags" "ac_cv_member_struct_msghdr_msg_flags" "#include -" -if test "x$ac_cv_member_struct_msghdr_msg_flags" = x""yes; then : - $as_echo "#define HAS_MSGHDR_FLAGS 1" >>confdefs.h - -fi - - -ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include - #include - -" -if test "x$ac_cv_type_socklen_t" = x""yes; then : - $as_echo "#define HAS_SOCKLEN_T 1" >>confdefs.h - -fi - - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "MSG_MAXIOVLEN" >/dev/null 2>&1; then : - $as_echo "#define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN" >>confdefs.h - -fi -rm -f conftest* - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "MSG_MAXIOVLEN" >/dev/null 2>&1; then : - $as_echo "#define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN" >>confdefs.h - -fi -rm -f conftest* - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use CRC32" >&5 -$as_echo_n "checking whether to use CRC32... " >&6; } -# Check whether --enable-crc32 was given. -if test "${enable_crc32+set}" = set; then : - enableval=$enable_crc32; if test "$enableval" = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - $as_echo "#define USE_CRC32 1" >>confdefs.h - - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - fi -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -ac_config_files="$ac_config_files Makefile include/Makefile include/enet/Makefile" - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes: double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \. - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file - else - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -ac_script=' -:mline -/\\$/{ - N - s,\\\n,, - b mline -} -t clear -:clear -s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g -t quote -s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g -t quote -b any -:quote -s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g -s/\[/\\&/g -s/\]/\\&/g -s/\$/$$/g -H -:any -${ - g - s/^\n// - s/\n/ /g - p -} -' -DEFS=`sed -n "$ac_script" confdefs.h` - - -ac_libobjs= -ac_ltlibobjs= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`$as_echo "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" - as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - - if test -n "$EXEEXT"; then - am__EXEEXT_TRUE= - am__EXEEXT_FALSE='#' -else - am__EXEEXT_TRUE='#' - am__EXEEXT_FALSE= -fi - -if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then - as_fn_error "conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - as_fn_error "conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi - -: ${CONFIG_STATUS=./config.status} -ac_write_fail=0 -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} -as_write_fail=0 -cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false - -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# as_fn_error ERROR [LINENO LOG_FD] -# --------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with status $?, using 1 if that was 0. -as_fn_error () -{ - as_status=$?; test $as_status -eq 0 && as_status=1 - if test "$3"; then - as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 - fi - $as_echo "$as_me: error: $1" >&2 - as_fn_exit $as_status -} # as_fn_error - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -p' - fi -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -_ASEOF -test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# Save the log message, to keep $0 and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by libenet $as_me 1-8-2008, which was -generated by GNU Autoconf 2.65. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - -case $ac_config_files in *" -"*) set x $ac_config_files; shift; ac_config_files=$*;; -esac - - - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# Files that config.status was made for. -config_files="$ac_config_files" -config_commands="$ac_config_commands" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -ac_cs_usage="\ -\`$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. - -Usage: $0 [OPTION]... [TAG]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - -Configuration files: -$config_files - -Configuration commands: -$config_commands - -Report bugs to the package provider." - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" -ac_cs_version="\\ -libenet config.status 1-8-2008 -configured by $0, generated by GNU Autoconf 2.65, - with options \\"\$ac_cs_config\\" - -Copyright (C) 2009 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -INSTALL='$INSTALL' -MKDIR_P='$MKDIR_P' -AWK='$AWK' -test -n "\$AWK" || AWK=awk -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# The default lists apply if the user does not specify any file. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - as_fn_append CONFIG_FILES " '$ac_optarg'" - ac_need_defaults=false;; - --he | --h | --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) as_fn_error "unrecognized option: \`$1' -Try \`$0 --help' for more information." ;; - - *) as_fn_append ac_config_targets " $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -if \$ac_cs_recheck; then - set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion - shift - \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 - CONFIG_SHELL='$SHELL' - export CONFIG_SHELL - exec "\$@" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - $as_echo "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# -# INIT-COMMANDS -# -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" - - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -sed_quote_subst='$sed_quote_subst' -double_quote_subst='$double_quote_subst' -delay_variable_subst='$delay_variable_subst' -macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' -macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' -enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' -enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' -pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' -enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' -host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' -host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`' -host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`' -build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`' -build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`' -build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`' -SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`' -Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`' -GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`' -EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`' -FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`' -LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`' -NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`' -LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`' -max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`' -ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`' -exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`' -lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`' -lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`' -lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' -reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' -reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' -OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`' -deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' -file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' -AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' -AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`' -STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`' -RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`' -old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' -CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`' -CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`' -compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`' -GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' -objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`' -SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`' -ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`' -MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`' -need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`' -DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`' -NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`' -LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`' -OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`' -OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`' -libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`' -shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`' -extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' -archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`' -enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`' -export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' -whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' -compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' -archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' -archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' -module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`' -module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' -with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`' -allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' -no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`' -inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`' -link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`' -fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`' -always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`' -export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`' -exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`' -include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`' -prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`' -file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`' -variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`' -need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' -need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`' -version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`' -runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`' -shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' -shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`' -libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`' -library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`' -soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`' -postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`' -finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`' -sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`' -sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`' -enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`' -enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`' -enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`' -old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`' -striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`' - -LTCC='$LTCC' -LTCFLAGS='$LTCFLAGS' -compiler='$compiler_DEFAULT' - -# Quote evaled strings. -for var in SED \ -GREP \ -EGREP \ -FGREP \ -LD \ -NM \ -LN_S \ -lt_SP2NL \ -lt_NL2SP \ -reload_flag \ -OBJDUMP \ -deplibs_check_method \ -file_magic_cmd \ -AR \ -AR_FLAGS \ -STRIP \ -RANLIB \ -CC \ -CFLAGS \ -compiler \ -lt_cv_sys_global_symbol_pipe \ -lt_cv_sys_global_symbol_to_cdecl \ -lt_cv_sys_global_symbol_to_c_name_address \ -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ -SHELL \ -ECHO \ -lt_prog_compiler_no_builtin_flag \ -lt_prog_compiler_wl \ -lt_prog_compiler_pic \ -lt_prog_compiler_static \ -lt_cv_prog_compiler_c_o \ -need_locks \ -DSYMUTIL \ -NMEDIT \ -LIPO \ -OTOOL \ -OTOOL64 \ -shrext_cmds \ -export_dynamic_flag_spec \ -whole_archive_flag_spec \ -compiler_needs_object \ -with_gnu_ld \ -allow_undefined_flag \ -no_undefined_flag \ -hardcode_libdir_flag_spec \ -hardcode_libdir_flag_spec_ld \ -hardcode_libdir_separator \ -fix_srcfile_path \ -exclude_expsyms \ -include_expsyms \ -file_list_spec \ -variables_saved_for_relink \ -libname_spec \ -library_names_spec \ -soname_spec \ -finish_eval \ -old_striplib \ -striplib; do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in - *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -# Double-quote double-evaled strings. -for var in reload_cmds \ -old_postinstall_cmds \ -old_postuninstall_cmds \ -old_archive_cmds \ -extract_expsyms_cmds \ -old_archive_from_new_cmds \ -old_archive_from_expsyms_cmds \ -archive_cmds \ -archive_expsym_cmds \ -module_cmds \ -module_expsym_cmds \ -export_symbols_cmds \ -prelink_cmds \ -postinstall_cmds \ -postuninstall_cmds \ -finish_cmds \ -sys_lib_search_path_spec \ -sys_lib_dlsearch_path_spec; do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in - *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -# Fix-up fallback echo if it was mangled by the above quoting rules. -case \$lt_ECHO in -*'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\` - ;; -esac - -ac_aux_dir='$ac_aux_dir' -xsi_shell='$xsi_shell' -lt_shell_append='$lt_shell_append' - -# See if we are running on zsh, and set the options which allow our -# commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST -fi - - - PACKAGE='$PACKAGE' - VERSION='$VERSION' - TIMESTAMP='$TIMESTAMP' - RM='$RM' - ofile='$ofile' - - - - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; - "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; - "include/enet/Makefile") CONFIG_FILES="$CONFIG_FILES include/enet/Makefile" ;; - - *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= - trap 'exit_status=$? - { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status -' 0 - trap 'as_fn_exit 1' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 - -# Set up the scripts for CONFIG_FILES section. -# No need to generate them if there are no CONFIG_FILES. -# This happens for instance with `./config.status config.h'. -if test -n "$CONFIG_FILES"; then - - -ac_cr=`echo X | tr X '\015'` -# On cygwin, bash can eat \r inside `` if the user requested igncr. -# But we know of no other shell where ac_cr would be empty at this -# point, so we can use a bashism as a fallback. -if test "x$ac_cr" = x; then - eval ac_cr=\$\'\\r\' -fi -ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` -if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\r' -else - ac_cs_awk_cr=$ac_cr -fi - -echo 'BEGIN {' >"$tmp/subs1.awk" && -_ACEOF - - -{ - echo "cat >conf$$subs.awk <<_ACEOF" && - echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && - echo "_ACEOF" -} >conf$$subs.sh || - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - . ./conf$$subs.sh || - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 - - ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` - if test $ac_delim_n = $ac_delim_num; then - break - elif $ac_last_try; then - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done -rm -f conf$$subs.sh - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$tmp/subs1.awk" <<\\_ACAWK && -_ACEOF -sed -n ' -h -s/^/S["/; s/!.*/"]=/ -p -g -s/^[^!]*!// -:repl -t repl -s/'"$ac_delim"'$// -t delim -:nl -h -s/\(.\{148\}\)..*/\1/ -t more1 -s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ -p -n -b repl -:more1 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t nl -:delim -h -s/\(.\{148\}\)..*/\1/ -t more2 -s/["\\]/\\&/g; s/^/"/; s/$/"/ -p -b -:more2 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t delim -' >$CONFIG_STATUS || ac_write_fail=1 -rm -f conf$$subs.awk -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACAWK -cat >>"\$tmp/subs1.awk" <<_ACAWK && - for (key in S) S_is_set[key] = 1 - FS = "" - -} -{ - line = $ 0 - nfields = split(line, field, "@") - substed = 0 - len = length(field[1]) - for (i = 2; i < nfields; i++) { - key = field[i] - keylen = length(key) - if (S_is_set[key]) { - value = S[key] - line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) - len += length(value) + length(field[++i]) - substed = 1 - } else - len += 1 + keylen - } - - print line -} - -_ACAWK -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then - sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" -else - cat -fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ - || as_fn_error "could not setup config files machinery" "$LINENO" 5 -_ACEOF - -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/ -s/:*\${srcdir}:*/:/ -s/:*@srcdir@:*/:/ -s/^\([^=]*=[ ]*\):*/\1/ -s/:*$// -s/^[^=]*=[ ]*$// -}' -fi - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -fi # test -n "$CONFIG_FILES" - - -eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" -shift -for ac_tag -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; - esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - as_fn_append ac_file_inputs " '$ac_f'" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} - fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | - sed 's/[\\\\&|]/\\\\&/g'`;; #( - *) ac_sed_conf_input=$configure_input;; - esac - - case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir="$ac_dir"; as_fn_mkdir_p - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; - esac - ac_MKDIR_P=$MKDIR_P - case $MKDIR_P in - [\\/$]* | ?:[\\/]* ) ;; - */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; - esac -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= -ac_sed_dataroot=' -/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p' -case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 - ac_datarootdir_hack=' - s&@datadir@&$datadir&g - s&@docdir@&$docdir&g - s&@infodir@&$infodir&g - s&@localedir@&$localedir&g - s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; -esac -_ACEOF - -# Neutralize VPATH when `$srcdir' = `.'. -# Shell code in configure.ac might set extrasub. -# FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_sed_extra="$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s|@configure_input@|$ac_sed_conf_input|;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@top_build_prefix@&$ac_top_build_prefix&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -s&@INSTALL@&$ac_INSTALL&;t t -s&@MKDIR_P@&$ac_MKDIR_P&;t t -$ac_datarootdir_hack -" -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&2;} - - rm -f "$tmp/stdin" - case $ac_file in - -) cat "$tmp/out" && rm -f "$tmp/out";; - *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; - esac \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 - ;; - - - :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 -$as_echo "$as_me: executing $ac_file commands" >&6;} - ;; - esac - - - case $ac_file$ac_mode in - "depfiles":C) test x"$AMDEP_TRUE" != x"" || { - # Autoconf 2.62 quotes --file arguments for eval, but not when files - # are listed without --file. Let's play safe and only enable the eval - # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac - shift - for mf - do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$mf" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir=$dirpart/$fdir; as_fn_mkdir_p - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done - done -} - ;; - "libtool":C) - - # See if we are running on zsh, and set the options which allow our - # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - - cfgfile="${ofile}T" - trap "$RM \"$cfgfile\"; exit 1" 1 2 15 - $RM "$cfgfile" - - cat <<_LT_EOF >> "$cfgfile" -#! $SHELL - -# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: -# NOTE: Changes made to this file will be lost: look at ltmain.sh. -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is part of GNU Libtool. -# -# GNU Libtool 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 2 of -# the License, or (at your option) any later version. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, or -# obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - -# The names of the tagged configurations supported by this script. -available_tags="" - -# ### BEGIN LIBTOOL CONFIG - -# Which release of libtool.m4 was used? -macro_version=$macro_version -macro_revision=$macro_revision - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# What type of objects to build. -pic_mode=$pic_mode - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# A sed program that does not truncate output. -SED=$lt_SED - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="\$SED -e 1s/^X//" - -# A grep program that handles long lines. -GREP=$lt_GREP - -# An ERE matcher. -EGREP=$lt_EGREP - -# A literal string matcher. -FGREP=$lt_FGREP - -# A BSD- or MS-compatible name lister. -NM=$lt_NM - -# Whether we need soft or hard links. -LN_S=$lt_LN_S - -# What is the maximum length of a command? -max_cmd_len=$max_cmd_len - -# Object file suffix (normally "o"). -objext=$ac_objext - -# Executable file suffix (normally ""). -exeext=$exeext - -# whether the shell understands "unset". -lt_unset=$lt_unset - -# turn spaces into newlines. -SP2NL=$lt_lt_SP2NL - -# turn newlines into spaces. -NL2SP=$lt_lt_NL2SP - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# An object symbol dumper. -OBJDUMP=$lt_OBJDUMP - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == "file_magic". -file_magic_cmd=$lt_file_magic_cmd - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A symbol stripping program. -STRIP=$lt_STRIP - -# Commands used to install an old-style archive. -RANLIB=$lt_RANLIB -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# A C compiler. -LTCC=$lt_CC - -# LTCC compiler flags. -LTCFLAGS=$lt_CFLAGS - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration. -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair. -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# Transform the output of nm in a C name address pair when lib prefix is needed. -global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# An echo program that does not interpret backslashes. -ECHO=$lt_ECHO - -# Used to examine libraries when file_magic_cmd begins with "file". -MAGIC_CMD=$MAGIC_CMD - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Tool to manipulate archived DWARF debug symbol files on Mac OS X. -DSYMUTIL=$lt_DSYMUTIL - -# Tool to change global to local symbols on Mac OS X. -NMEDIT=$lt_NMEDIT - -# Tool to manipulate fat objects and archives on Mac OS X. -LIPO=$lt_LIPO - -# ldd/readelf like tool for Mach-O binaries on Mac OS X. -OTOOL=$lt_OTOOL - -# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. -OTOOL64=$lt_OTOOL64 - -# Old archive suffix (normally "a"). -libext=$libext - -# Shared library suffix (normally ".so"). -shrext_cmds=$lt_shrext_cmds - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at link time. -variables_saved_for_relink=$lt_variables_saved_for_relink - -# Do we need the "lib" prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Library versioning type. -version_type=$version_type - -# Shared library runtime path variable. -runpath_var=$runpath_var - -# Shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Command to use after installation of a shared archive. -postinstall_cmds=$lt_postinstall_cmds - -# Command to use after uninstallation of a shared archive. -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# As "finish_cmds", except a single script fragment to be evaled but -# not shown. -finish_eval=$lt_finish_eval - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Compile-time system search path for libraries. -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries. -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - - -# The linker used to build libraries. -LD=$lt_LD - -# Commands used to build an old-style archive. -old_archive_cmds=$lt_old_archive_cmds - -# A language specific compiler. -CC=$lt_compiler - -# Is the compiler the GNU compiler? -with_gcc=$GCC - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc - -# Whether or not to disallow shared libs when runtime libs are static. -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec - -# Whether the compiler copes with passing no objects directly. -compiler_needs_object=$lt_compiler_needs_object - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds - -# Commands used to build a shared archive. -archive_cmds=$lt_archive_cmds -archive_expsym_cmds=$lt_archive_expsym_cmds - -# Commands used to build a loadable module if different from building -# a shared archive. -module_cmds=$lt_module_cmds -module_expsym_cmds=$lt_module_expsym_cmds - -# Whether we are building with GNU ld or not. -with_gnu_ld=$lt_with_gnu_ld - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag - -# Flag that enforces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec - -# If ld is used when linking, flag to hardcode \$libdir into a binary -# during linking. This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld - -# Whether we need a single "-rpath" flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator - -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes -# DIR into the resulting binary. -hardcode_direct=$hardcode_direct - -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes -# DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \${shlibpath_var} if the -# library is relocated. -hardcode_direct_absolute=$hardcode_direct_absolute - -# Set to "yes" if using the -LDIR flag during linking hardcodes DIR -# into the resulting binary. -hardcode_minus_L=$hardcode_minus_L - -# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR -# into the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var - -# Set to "yes" if building a shared library automatically hardcodes DIR -# into the library and all subsequent libraries and executables linked -# against it. -hardcode_automatic=$hardcode_automatic - -# Set to yes if linker adds runtime paths of dependent libraries -# to runtime path list. -inherit_rpath=$inherit_rpath - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path=$lt_fix_srcfile_path - -# Set to "yes" if exported symbols are required. -always_export_symbols=$always_export_symbols - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms - -# Commands necessary for linking programs (against libraries) with templates. -prelink_cmds=$lt_prelink_cmds - -# Specify filename containing input files. -file_list_spec=$lt_file_list_spec - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action - -# ### END LIBTOOL CONFIG - -_LT_EOF - - case $host_os in - aix3*) - cat <<\_LT_EOF >> "$cfgfile" -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -_LT_EOF - ;; - esac - - -ltmain="$ac_aux_dir/ltmain.sh" - - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - case $xsi_shell in - yes) - cat << \_LT_EOF >> "$cfgfile" - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac -} - -# func_basename file -func_basename () -{ - func_basename_result="${1##*/}" -} - -# func_dirname_and_basename file append nondir_replacement -# perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# Implementation must be kept synchronized with func_dirname -# and func_basename. For efficiency, we do not delegate to -# those functions but instead duplicate the functionality here. -func_dirname_and_basename () -{ - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac - func_basename_result="${1##*/}" -} - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -func_stripname () -{ - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary parameter first. - func_stripname_result=${3} - func_stripname_result=${func_stripname_result#"${1}"} - func_stripname_result=${func_stripname_result%"${2}"} -} - -# func_opt_split -func_opt_split () -{ - func_opt_split_opt=${1%%=*} - func_opt_split_arg=${1#*=} -} - -# func_lo2o object -func_lo2o () -{ - case ${1} in - *.lo) func_lo2o_result=${1%.lo}.${objext} ;; - *) func_lo2o_result=${1} ;; - esac -} - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=${1%.*}.lo -} - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=$(( $* )) -} - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=${#1} -} - -_LT_EOF - ;; - *) # Bourne compatible functions. - cat << \_LT_EOF >> "$cfgfile" - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi -} - -# func_basename file -func_basename () -{ - func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` -} - - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# func_strip_suffix prefix name -func_stripname () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; - esac -} - -# sed scripts: -my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q' -my_sed_long_arg='1s/^-[^=]*=//' - -# func_opt_split -func_opt_split () -{ - func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` - func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` -} - -# func_lo2o object -func_lo2o () -{ - func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` -} - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'` -} - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=`expr "$@"` -} - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` -} - -_LT_EOF -esac - -case $lt_shell_append in - yes) - cat << \_LT_EOF >> "$cfgfile" - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "$1+=\$2" -} -_LT_EOF - ;; - *) - cat << \_LT_EOF >> "$cfgfile" - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "$1=\$$1\$2" -} - -_LT_EOF - ;; - esac - - - sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" - - ;; - - esac -done # for ac_tag - - -as_fn_exit 0 -_ACEOF -ac_clean_files=$ac_clean_files_save - -test $ac_write_fail = 0 || - as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit $? -fi -if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} -fi - - diff --git a/lib/enet/configure.in b/lib/enet/configure.in deleted file mode 100644 index 47da5feb9..000000000 --- a/lib/enet/configure.in +++ /dev/null @@ -1,36 +0,0 @@ -AC_INIT(libenet, 1-8-2008) -AM_INIT_AUTOMAKE(libenet.a, 1-8-2008) - -AC_PROG_CC -AC_PROG_RANLIB - -AC_CHECK_FUNC(gethostbyaddr_r, [AC_DEFINE(HAS_GETHOSTBYADDR_R)]) -AC_CHECK_FUNC(gethostbyname_r, [AC_DEFINE(HAS_GETHOSTBYNAME_R)]) -AC_CHECK_FUNC(poll, [AC_DEFINE(HAS_POLL)]) -AC_CHECK_FUNC(fcntl, [AC_DEFINE(HAS_FCNTL)]) -AC_CHECK_FUNC(inet_pton, [AC_DEFINE(HAS_INET_PTON)]) -AC_CHECK_FUNC(inet_ntop, [AC_DEFINE(HAS_INET_NTOP)]) - -AC_CHECK_MEMBER(struct msghdr.msg_flags, [AC_DEFINE(HAS_MSGHDR_FLAGS)], , [#include ]) - -AC_CHECK_TYPE(socklen_t, [AC_DEFINE(HAS_SOCKLEN_T)], , - #include - #include -) - -AC_EGREP_HEADER(MSG_MAXIOVLEN, /usr/include/sys/socket.h, AC_DEFINE(ENET_BUFFER_MAXIMUM, [MSG_MAXIOVLEN])) -AC_EGREP_HEADER(MSG_MAXIOVLEN, socket.h, AC_DEFINE(ENET_BUFFER_MAXIMUM, [MSG_MAXIOVLEN])) - -AC_MSG_CHECKING(whether to use CRC32) -AC_ARG_ENABLE(crc32, - [ --enable-crc32 enable CRC32 packet verification ], - [if test "$enableval" = yes; then - AC_MSG_RESULT(yes) - AC_DEFINE(USE_CRC32) - else - AC_MSG_RESULT(no) - fi], - [AC_MSG_RESULT(no)]) - -AC_OUTPUT([Makefile include/Makefile include/enet/Makefile]) - diff --git a/lib/enet/depcomp b/lib/enet/depcomp deleted file mode 100644 index df8eea7e4..000000000 --- a/lib/enet/depcomp +++ /dev/null @@ -1,630 +0,0 @@ -#! /bin/sh -# depcomp - compile a program generating dependencies as side-effects - -scriptversion=2009-04-28.21; # UTC - -# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free -# Software Foundation, Inc. - -# 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 2, 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 . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Alexandre Oliva . - -case $1 in - '') - echo "$0: No command. Try \`$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: depcomp [--help] [--version] PROGRAM [ARGS] - -Run PROGRAMS ARGS to compile a file, generating dependencies -as side-effects. - -Environment variables: - depmode Dependency tracking mode. - source Source file read by `PROGRAMS ARGS'. - object Object file output by `PROGRAMS ARGS'. - DEPDIR directory where to store dependencies. - depfile Dependency file to output. - tmpdepfile Temporary file to use when outputing dependencies. - libtool Whether libtool is used (yes/no). - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "depcomp $scriptversion" - exit $? - ;; -esac - -if test -z "$depmode" || test -z "$source" || test -z "$object"; then - echo "depcomp: Variables source, object and depmode must be set" 1>&2 - exit 1 -fi - -# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. -depfile=${depfile-`echo "$object" | - sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} -tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} - -rm -f "$tmpdepfile" - -# Some modes work just like other modes, but use different flags. We -# parameterize here, but still list the modes in the big case below, -# to make depend.m4 easier to write. Note that we *cannot* use a case -# here, because this file can only contain one case statement. -if test "$depmode" = hp; then - # HP compiler uses -M and no extra arg. - gccflag=-M - depmode=gcc -fi - -if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout -fi - -cygpath_u="cygpath -u -f -" -if test "$depmode" = msvcmsys; then - # This is just like msvisualcpp but w/o cygpath translation. - # Just convert the backslash-escaped backslashes to single forward - # slashes to satisfy depend.m4 - cygpath_u="sed s,\\\\\\\\,/,g" - depmode=msvisualcpp -fi - -case "$depmode" in -gcc3) -## gcc 3 implements dependency tracking that does exactly what -## we want. Yay! Note: for some reason libtool 1.4 doesn't like -## it if -MD -MP comes after the -MF stuff. Hmm. -## Unfortunately, FreeBSD c89 acceptance of flags depends upon -## the command line argument order; so add the flags where they -## appear in depend2.am. Note that the slowdown incurred here -## affects only configure: in makefiles, %FASTDEP% shortcuts this. - for arg - do - case $arg in - -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; - *) set fnord "$@" "$arg" ;; - esac - shift # fnord - shift # $arg - done - "$@" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - mv "$tmpdepfile" "$depfile" - ;; - -gcc) -## There are various ways to get dependency output from gcc. Here's -## why we pick this rather obscure method: -## - Don't want to use -MD because we'd like the dependencies to end -## up in a subdir. Having to rename by hand is ugly. -## (We might end up doing this anyway to support other compilers.) -## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). -## - Using -M directly means running the compiler twice (even worse -## than renaming). - if test -z "$gccflag"; then - gccflag=-MD, - fi - "$@" -Wp,"$gccflag$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz -## The second -e expression handles DOS-style file names with drive letters. - sed -e 's/^[^:]*: / /' \ - -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the `deleted header file' problem. -## The problem is that when a header file which appears in a .P file -## is deleted, the dependency causes make to die (because there is -## typically no way to rebuild the header). We avoid this by adding -## dummy dependencies for each header file. Too bad gcc doesn't do -## this for us directly. - tr ' ' ' -' < "$tmpdepfile" | -## Some versions of gcc put a space before the `:'. On the theory -## that the space means something, we add a space to the output as -## well. -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -sgi) - if test "$libtool" = yes; then - "$@" "-Wp,-MDupdate,$tmpdepfile" - else - "$@" -MDupdate "$tmpdepfile" - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - - if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files - echo "$object : \\" > "$depfile" - - # Clip off the initial element (the dependent). Don't try to be - # clever and replace this with sed code, as IRIX sed won't handle - # lines with more than a fixed number of characters (4096 in - # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like `#:fec' to the end of the - # dependency line. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ - tr ' -' ' ' >> "$depfile" - echo >> "$depfile" - - # The second pass generates a dummy entry for each header file. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> "$depfile" - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -aix) - # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. In older versions, this file always lives in the - # current directory. Also, the AIX compiler puts `$object:' at the - # start of each line; $object doesn't have directory information. - # Version 6 uses the directory in both cases. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.u - tmpdepfile2=$base.u - tmpdepfile3=$dir.libs/$base.u - "$@" -Wc,-M - else - tmpdepfile1=$dir$base.u - tmpdepfile2=$dir$base.u - tmpdepfile3=$dir$base.u - "$@" -M - fi - stat=$? - - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - # Each line is of the form `foo.o: dependent.h'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a tab and a space in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -icc) - # Intel's C compiler understands `-MD -MF file'. However on - # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c - # ICC 7.0 will fill foo.d with something like - # foo.o: sub/foo.c - # foo.o: sub/foo.h - # which is wrong. We want: - # sub/foo.o: sub/foo.c - # sub/foo.o: sub/foo.h - # sub/foo.c: - # sub/foo.h: - # ICC 7.1 will output - # foo.o: sub/foo.c sub/foo.h - # and will wrap long lines using \ : - # foo.o: sub/foo.c ... \ - # sub/foo.h ... \ - # ... - - "$@" -MD -MF "$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each line is of the form `foo.o: dependent.h', - # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | - sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp2) - # The "hp" stanza above does not work with aCC (C++) and HP's ia64 - # compilers, which have integrated preprocessors. The correct option - # to use with these is +Maked; it writes dependencies to a file named - # 'foo.d', which lands next to the object file, wherever that - # happens to be. - # Much of this is similar to the tru64 case; see comments there. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir.libs/$base.d - "$@" -Wc,+Maked - else - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir$base.d - "$@" +Maked - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" - # Add `dependent.h:' lines. - sed -ne '2,${ - s/^ *// - s/ \\*$// - s/$/:/ - p - }' "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" "$tmpdepfile2" - ;; - -tru64) - # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in `foo.d' instead, so we check for that too. - # Subdirectories are respected. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - - if test "$libtool" = yes; then - # With Tru64 cc, shared objects can also be used to make a - # static library. This mechanism is used in libtool 1.4 series to - # handle both shared and static libraries in a single compilation. - # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. - # - # With libtool 1.5 this exception was removed, and libtool now - # generates 2 separate objects for the 2 libraries. These two - # compilations output dependencies in $dir.libs/$base.o.d and - # in $dir$base.o.d. We have to check for both files, because - # one of the two compilations can be disabled. We should prefer - # $dir$base.o.d over $dir.libs/$base.o.d because the latter is - # automatically cleaned when .libs/ is deleted, while ignoring - # the former would cause a distcleancheck panic. - tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 - tmpdepfile2=$dir$base.o.d # libtool 1.5 - tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 - tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 - "$@" -Wc,-MD - else - tmpdepfile1=$dir$base.o.d - tmpdepfile2=$dir$base.d - tmpdepfile3=$dir$base.d - tmpdepfile4=$dir$base.d - "$@" -MD - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a tab and a space in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -#nosideeffect) - # This comment above is used by automake to tell side-effect - # dependency tracking mechanisms from slower ones. - -dashmstdout) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - test -z "$dashmflag" && dashmflag=-M - # Require at least two characters before searching for `:' - # in the target name. This is to cope with DOS-style filenames: - # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. - "$@" $dashmflag | - sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - tr ' ' ' -' < "$tmpdepfile" | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -dashXmstdout) - # This case only exists to satisfy depend.m4. It is never actually - # run, as this mode is specially recognized in the preamble. - exit 1 - ;; - -makedepend) - "$@" || exit $? - # Remove any Libtool call - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - # X makedepend - shift - cleared=no eat=no - for arg - do - case $cleared in - no) - set ""; shift - cleared=yes ;; - esac - if test $eat = yes; then - eat=no - continue - fi - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift ;; - # Strip any option that makedepend may not understand. Remove - # the object too, otherwise makedepend will parse it as a source file. - -arch) - eat=yes ;; - -*|$object) - ;; - *) - set fnord "$@" "$arg"; shift ;; - esac - done - obj_suffix=`echo "$object" | sed 's/^.*\././'` - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - sed '1,2d' "$tmpdepfile" | tr ' ' ' -' | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" "$tmpdepfile".bak - ;; - -cpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - "$@" -E | - sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | - sed '$ s: \\$::' > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - cat < "$tmpdepfile" >> "$depfile" - sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvisualcpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - IFS=" " - for arg - do - case "$arg" in - -o) - shift - ;; - $object) - shift - ;; - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") - set fnord "$@" - shift - shift - ;; - *) - set fnord "$@" "$arg" - shift - shift - ;; - esac - done - "$@" -E 2>/dev/null | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" - echo " " >> "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvcmsys) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -none) - exec "$@" - ;; - -*) - echo "Unknown depmode $depmode" 1>&2 - exit 1 - ;; -esac - -exit 0 - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/lib/enet/docs/FAQ.dox b/lib/enet/docs/FAQ.dox index 484b818a4..c3f45fb2c 100644 --- a/lib/enet/docs/FAQ.dox +++ b/lib/enet/docs/FAQ.dox @@ -1,12 +1,12 @@ /** @page FAQ Frequently Answered Questions -@section Q1 Is ENet thread safe? +@section Q1 Is ENet thread-safe? ENet does not use any significant global variables, the vast majority of state is encapsulated in the ENetHost structure. As such, as long as the application guards access to this structure, then ENet should -operate fine in a multithreaded environment. +operate fine in a multi-threaded environment. @section Q2 Isn't ENet just re-inventing TCP?! What's the point? diff --git a/lib/enet/docs/design.dox b/lib/enet/docs/design.dox index daed221c8..f74a2bd70 100644 --- a/lib/enet/docs/design.dox +++ b/lib/enet/docs/design.dox @@ -3,7 +3,7 @@ ENet evolved specifically as a UDP networking layer for the multiplayer first person shooter Cube. Cube necessitated low latency -communcation with data sent out very frequently, so TCP was an +communication with data sent out very frequently, so TCP was an unsuitable choice due to its high latency and stream orientation. UDP, however, lacks many sometimes necessary features from TCP such as reliability, sequencing, unrestricted packet sizes, and connection @@ -44,7 +44,7 @@ packet streams that simplify the transfer of various types of data. ENet provides sequencing for all packets by assigning to each sent packet a sequence number that is incremented as packets are sent. ENet -guarentees that no packet with a higher sequence number will be +guarantees that no packet with a higher sequence number will be delivered before a packet with a lower sequence number, thus ensuring packets are delivered exactly in the order they are sent. diff --git a/lib/enet/docs/install.dox b/lib/enet/docs/install.dox index f5e46fbd1..310fe34cf 100644 --- a/lib/enet/docs/install.dox +++ b/lib/enet/docs/install.dox @@ -12,7 +12,7 @@ by doing the following: ./configure && make && make install -If you obtained the package from CVS, you must have automake and autoconf +If you obtained the package from github, you must have automake and autoconf available to generate the build system first by doing the following command before using the above mentioned build procedure: @@ -27,6 +27,10 @@ is linked in. @section Windows Microsoft Windows +You may simply use the included "enet.lib" or "enet64.lib" static libraries. +However, if you wish to build the library yourself, then the following +instructions apply: + There is an included MSVC 6 project (enet.dsp) which you may use to build a suitable library file. Alternatively, you may simply drag all the ENet source files into your main project. diff --git a/lib/enet/docs/license.dox b/lib/enet/docs/license.dox index c0fffb4bf..dda0037a4 100644 --- a/lib/enet/docs/license.dox +++ b/lib/enet/docs/license.dox @@ -1,7 +1,7 @@ /** @page License License -Copyright (c) 2002-2010 Lee Salzman +Copyright (c) 2002-2014 Lee Salzman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/lib/enet/docs/mainpage.dox b/lib/enet/docs/mainpage.dox index 1ea5b4e7e..496ad2e0a 100644 --- a/lib/enet/docs/mainpage.dox +++ b/lib/enet/docs/mainpage.dox @@ -34,28 +34,12 @@ portable, and easily embeddable. @page SourceDistro Source Distribution You can retrieve the source to ENet by downloading it in either .tar.gz form -or accessing the cvs distribution directly. +or accessing the github distribution directly. -The most recent stable release (1.3.1) can be downloaded here. -The last release that is protocol compatible with the 1.2 series or earlier (1.2.3) can be downloaded here +The most recent stable release (1.3.12) can be downloaded here. +The last release that is protocol compatible with the 1.2 series or earlier (1.2.5) can be downloaded here -To access ENet via anonymous CVS, you must use the CVSROOT -:pserver:anonymous\@bespin.org:/var/lib/cvs/enet with an empty -password. - -@code - $ cvs -z3 -d :pserver:anonymous@bespin.org:/var/lib/cvs/enet login -@endcode - Hit the return key when prompted for a password. -@code - $ cvs -z3 -d :pserver:anonymous@bespin.org:/var/lib/cvs/enet co -l . - $ cvs -z3 co enet -@endcode - -This will create a CVS directory in the current directory, and with -the second command will proceed to check the enet module out of CVS. -Any problems with CVS access or request for write access should be -sent via email to @ref MailingList. +You can find the most recent ENet source at the github repository. */ diff --git a/lib/enet/docs/tutorial.dox b/lib/enet/docs/tutorial.dox index dd911d30b..5dbd0c209 100644 --- a/lib/enet/docs/tutorial.dox +++ b/lib/enet/docs/tutorial.dox @@ -182,7 +182,7 @@ disconnect event and must be explicitly reset. break; case ENET_EVENT_TYPE_DISCONNECT: - printf ("%s disconected.\n", event.peer -> data); + printf ("%s disconnected.\n", event.peer -> data); /* Reset the peer's client information. */ @@ -204,7 +204,7 @@ Certain flags may also be supplied to enet_packet_create() to control various packet features: ENET_PACKET_FLAG_RELIABLE specifies that the packet must use reliable -delivery. A reliable packet is guarenteed to be delivered, and a +delivery. A reliable packet is guaranteed to be delivered, and a number of retry attempts will be made until an acknowledgement is received from the foreign host the packet is sent to. If a certain number of retry attempts is reached without any acknowledgement, ENet diff --git a/lib/enet/host.c b/lib/enet/host.c index f0597b1ff..3be6c0922 100644 --- a/lib/enet/host.c +++ b/lib/enet/host.c @@ -4,7 +4,6 @@ */ #define ENET_BUILDING_LIB 1 #include -#include #include "enet/enet.h" /** @defgroup host ENet host functions @@ -38,6 +37,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL host = (ENetHost *) enet_malloc (sizeof (ENetHost)); if (host == NULL) return NULL; + memset (host, 0, sizeof (ENetHost)); host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer)); if (host -> peers == NULL) @@ -49,7 +49,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL memset (host -> peers, 0, peerCount * sizeof (ENetPeer)); host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM); - if (host -> socket == ENET_SOCKET_NULL || (enet_socket_bind (host -> socket, address) < 0 && address != NULL)) + if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0)) { if (host -> socket != ENET_SOCKET_NULL) enet_socket_destroy (host -> socket); @@ -65,7 +65,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE); enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE); - if (address != NULL) + if (address != NULL && enet_socket_get_address (host -> socket, & host -> address) < 0) host -> address = * address; if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) @@ -74,7 +74,8 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; - host -> randomSeed = (enet_uint32) time(NULL) + (enet_uint32) (size_t) host; + host -> randomSeed = (enet_uint32) (size_t) host; + host -> randomSeed += enet_host_random_seed (); host -> randomSeed = (host -> randomSeed << 16) | (host -> randomSeed >> 16); host -> channelLimit = channelLimit; host -> incomingBandwidth = incomingBandwidth; @@ -96,11 +97,19 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL host -> totalReceivedData = 0; host -> totalReceivedPackets = 0; + host -> connectedPeers = 0; + host -> bandwidthLimitedPeers = 0; + host -> duplicatePeers = ENET_PROTOCOL_MAXIMUM_PEER_ID; + host -> maximumPacketSize = ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE; + host -> maximumWaitingData = ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA; + host -> compressor.context = NULL; host -> compressor.compress = NULL; host -> compressor.decompress = NULL; host -> compressor.destroy = NULL; + host -> intercept = NULL; + enet_list_clear (& host -> dispatchQueue); for (currentPeer = host -> peers; @@ -133,6 +142,9 @@ enet_host_destroy (ENetHost * host) { ENetPeer * currentPeer; + if (host == NULL) + return; + enet_socket_destroy (host -> socket); for (currentPeer = host -> peers; @@ -317,46 +329,44 @@ enet_host_bandwidth_throttle (ENetHost * host) { enet_uint32 timeCurrent = enet_time_get (), elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch, - peersTotal = 0, - dataTotal = 0, - peersRemaining, - bandwidth, + peersRemaining = (enet_uint32) host -> connectedPeers, + dataTotal = ~0, + bandwidth = ~0, throttle = 0, bandwidthLimit = 0; - int needsAdjustment; + int needsAdjustment = host -> bandwidthLimitedPeers > 0 ? 1 : 0; ENetPeer * peer; ENetProtocol command; if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL) return; - for (peer = host -> peers; - peer < & host -> peers [host -> peerCount]; - ++ peer) - { - if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) - continue; + host -> bandwidthThrottleEpoch = timeCurrent; - ++ peersTotal; - dataTotal += peer -> outgoingDataTotal; - } - - if (peersTotal == 0) + if (peersRemaining == 0) return; - peersRemaining = peersTotal; - needsAdjustment = 1; + if (host -> outgoingBandwidth != 0) + { + dataTotal = 0; + bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000; - if (host -> outgoingBandwidth == 0) - bandwidth = ~0; - else - bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000; + for (peer = host -> peers; + peer < & host -> peers [host -> peerCount]; + ++ peer) + { + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + continue; + + dataTotal += peer -> outgoingDataTotal; + } + } while (peersRemaining > 0 && needsAdjustment != 0) { needsAdjustment = 0; - if (dataTotal < bandwidth) + if (dataTotal <= bandwidth) throttle = ENET_PEER_PACKET_THROTTLE_SCALE; else throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal; @@ -387,7 +397,9 @@ enet_host_bandwidth_throttle (ENetHost * host) peer -> outgoingBandwidthThrottleEpoch = timeCurrent; - + peer -> incomingDataTotal = 0; + peer -> outgoingDataTotal = 0; + needsAdjustment = 1; -- peersRemaining; bandwidth -= peerBandwidth; @@ -396,25 +408,35 @@ enet_host_bandwidth_throttle (ENetHost * host) } if (peersRemaining > 0) - for (peer = host -> peers; - peer < & host -> peers [host -> peerCount]; - ++ peer) { - if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) || - peer -> outgoingBandwidthThrottleEpoch == timeCurrent) - continue; + if (dataTotal <= bandwidth) + throttle = ENET_PEER_PACKET_THROTTLE_SCALE; + else + throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal; - peer -> packetThrottleLimit = throttle; + for (peer = host -> peers; + peer < & host -> peers [host -> peerCount]; + ++ peer) + { + if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) || + peer -> outgoingBandwidthThrottleEpoch == timeCurrent) + continue; - if (peer -> packetThrottle > peer -> packetThrottleLimit) - peer -> packetThrottle = peer -> packetThrottleLimit; + peer -> packetThrottleLimit = throttle; + + if (peer -> packetThrottle > peer -> packetThrottleLimit) + peer -> packetThrottle = peer -> packetThrottleLimit; + + peer -> incomingDataTotal = 0; + peer -> outgoingDataTotal = 0; + } } - + if (host -> recalculateBandwidthLimits) { host -> recalculateBandwidthLimits = 0; - peersRemaining = peersTotal; + peersRemaining = (enet_uint32) host -> connectedPeers; bandwidth = host -> incomingBandwidth; needsAdjustment = 1; @@ -465,16 +487,6 @@ enet_host_bandwidth_throttle (ENetHost * host) enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); } } - - host -> bandwidthThrottleEpoch = timeCurrent; - - for (peer = host -> peers; - peer < & host -> peers [host -> peerCount]; - ++ peer) - { - peer -> incomingDataTotal = 0; - peer -> outgoingDataTotal = 0; - } } /** @} */ diff --git a/lib/enet/include/enet/enet.h b/lib/enet/include/enet/enet.h index 716635be6..ddae001a7 100644 --- a/lib/enet/include/enet/enet.h +++ b/lib/enet/include/enet/enet.h @@ -12,7 +12,7 @@ extern "C" #include -#ifdef WIN32 +#ifdef _WIN32 #include "enet/win32.h" #else #include "enet/unix.h" @@ -25,12 +25,19 @@ extern "C" #define ENET_VERSION_MAJOR 1 #define ENET_VERSION_MINOR 3 -#define ENET_VERSION_PATCH 3 +#define ENET_VERSION_PATCH 12 #define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch)) +#define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF) +#define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF) +#define ENET_VERSION_GET_PATCH(version) ((version)&0xFF) #define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH) typedef enet_uint32 ENetVersion; +struct _ENetHost; +struct _ENetEvent; +struct _ENetPacket; + typedef enum _ENetSocketType { ENET_SOCKET_TYPE_STREAM = 1, @@ -39,9 +46,10 @@ typedef enum _ENetSocketType typedef enum _ENetSocketWait { - ENET_SOCKET_WAIT_NONE = 0, - ENET_SOCKET_WAIT_SEND = (1 << 0), - ENET_SOCKET_WAIT_RECEIVE = (1 << 1) + ENET_SOCKET_WAIT_NONE = 0, + ENET_SOCKET_WAIT_SEND = (1 << 0), + ENET_SOCKET_WAIT_RECEIVE = (1 << 1), + ENET_SOCKET_WAIT_INTERRUPT = (1 << 2) } ENetSocketWait; typedef enum _ENetSocketOption @@ -50,16 +58,23 @@ typedef enum _ENetSocketOption ENET_SOCKOPT_BROADCAST = 2, ENET_SOCKOPT_RCVBUF = 3, ENET_SOCKOPT_SNDBUF = 4, - ENET_SOCKOPT_REUSEADDR = 5 + ENET_SOCKOPT_REUSEADDR = 5, + ENET_SOCKOPT_RCVTIMEO = 6, + ENET_SOCKOPT_SNDTIMEO = 7, + ENET_SOCKOPT_ERROR = 8, + ENET_SOCKOPT_NODELAY = 9 } ENetSocketOption; -enum +typedef enum _ENetSocketShutdown { - ENET_HOST_ANY = 0, /**< specifies the default server host */ - ENET_HOST_BROADCAST = 0xFFFFFFFF, /**< specifies a subnet-wide broadcast */ + ENET_SOCKET_SHUTDOWN_READ = 0, + ENET_SOCKET_SHUTDOWN_WRITE = 1, + ENET_SOCKET_SHUTDOWN_READ_WRITE = 2 +} ENetSocketShutdown; - ENET_PORT_ANY = 0 /**< specifies that a port should be automatically chosen */ -}; +#define ENET_HOST_ANY 0 +#define ENET_HOST_BROADCAST 0xFFFFFFFFU +#define ENET_PORT_ANY 0 /** * Portable internet address structure. @@ -99,10 +114,12 @@ typedef enum _ENetPacketFlag ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2), /** packet will be fragmented using unreliable (instead of reliable) sends * if it exceeds the MTU */ - ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3) + ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3), + + /** whether the packet has been sent from all queues it has been entered into */ + ENET_PACKET_FLAG_SENT = (1<<8) } ENetPacketFlag; -struct _ENetPacket; typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *); /** @@ -131,6 +148,7 @@ typedef struct _ENetPacket enet_uint8 * data; /**< allocated data for packet */ size_t dataLength; /**< length of data */ ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */ + void * userData; /**< application private data, may be freely modified */ } ENetPacket; typedef struct _ENetAcknowledgement @@ -191,6 +209,8 @@ enum ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024, ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000, ENET_HOST_DEFAULT_MTU = 1400, + ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024, + ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024, ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500, ENET_PEER_DEFAULT_PACKET_THROTTLE = 32, @@ -267,6 +287,10 @@ typedef struct _ENetPeer enet_uint32 packetThrottleAcceleration; enet_uint32 packetThrottleDeceleration; enet_uint32 packetThrottleInterval; + enet_uint32 pingInterval; + enet_uint32 timeoutLimit; + enet_uint32 timeoutMinimum; + enet_uint32 timeoutMaximum; enet_uint32 lastRoundTripTime; enet_uint32 lowestRoundTripTime; enet_uint32 lastRoundTripTimeVariance; @@ -288,6 +312,7 @@ typedef struct _ENetPeer enet_uint16 outgoingUnsequencedGroup; enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32]; enet_uint32 eventData; + size_t totalWaitingData; } ENetPeer; /** An ENet packet compressor for compressing UDP packets before socket sends or receives. @@ -306,6 +331,9 @@ typedef struct _ENetCompressor /** Callback that computes the checksum of the data held in buffers[0:bufferCount-1] */ typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback) (const ENetBuffer * buffers, size_t bufferCount); + +/** Callback for intercepting received raw UDP packets. Should return 1 to intercept, 0 to ignore, or -1 to propagate an error. */ +typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, struct _ENetEvent * event); /** An ENet host for communicating with peers. * @@ -355,6 +383,12 @@ typedef struct _ENetHost enet_uint32 totalSentPackets; /**< total UDP packets sent, user should reset to 0 as needed to prevent overflow */ enet_uint32 totalReceivedData; /**< total data received, user should reset to 0 as needed to prevent overflow */ enet_uint32 totalReceivedPackets; /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */ + ENetInterceptCallback intercept; /**< callback the user can set to intercept received raw UDP packets */ + size_t connectedPeers; + size_t bandwidthLimitedPeers; + size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */ + size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */ + size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */ } ENetHost; /** @@ -417,7 +451,7 @@ ENET_API int enet_initialize (void); Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant. Make sure the ENetCallbacks structure is zeroed out so that any additional callbacks added in future versions will be properly ignored. @param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use - @param inits user-overriden callbacks where any NULL callbacks will use ENet's defaults + @param inits user-overridden callbacks where any NULL callbacks will use ENet's defaults @returns 0 on success, < 0 on failure */ ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits); @@ -428,6 +462,12 @@ ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCall */ ENET_API void enet_deinitialize (void); +/** + Gives the linked version of the ENet library. + @returns the version number +*/ +ENET_API ENetVersion enet_linked_version (void); + /** @} */ /** @defgroup private ENet private implementation functions */ @@ -447,6 +487,7 @@ ENET_API void enet_time_set (enet_uint32); */ ENET_API ENetSocket enet_socket_create (ENetSocketType); ENET_API int enet_socket_bind (ENetSocket, const ENetAddress *); +ENET_API int enet_socket_get_address (ENetSocket, ENetAddress *); ENET_API int enet_socket_listen (ENetSocket, int); ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *); ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *); @@ -454,6 +495,8 @@ ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENe ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t); ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32); ENET_API int enet_socket_set_option (ENetSocket, ENetSocketOption, int); +ENET_API int enet_socket_get_option (ENetSocket, ENetSocketOption, int *); +ENET_API int enet_socket_shutdown (ENetSocket, ENetSocketShutdown); ENET_API void enet_socket_destroy (ENetSocket); ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32); @@ -472,7 +515,7 @@ ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSock */ ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName); -/** Gives the printable form of the ip address specified in the address parameter. +/** Gives the printable form of the IP address specified in the address parameter. @param address address printed @param hostName destination for name, must not be NULL @param nameLength maximum length of hostName. @@ -497,7 +540,7 @@ ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32); ENET_API void enet_packet_destroy (ENetPacket *); ENET_API int enet_packet_resize (ENetPacket *, size_t); -extern enet_uint32 enet_crc32 (const ENetBuffer *, size_t); +ENET_API enet_uint32 enet_crc32 (const ENetBuffer *, size_t); ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32); ENET_API void enet_host_destroy (ENetHost *); @@ -511,10 +554,13 @@ ENET_API int enet_host_compress_with_range_coder (ENetHost * host); ENET_API void enet_host_channel_limit (ENetHost *, size_t); ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32); extern void enet_host_bandwidth_throttle (ENetHost *); +extern enet_uint32 enet_host_random_seed (void); ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *); ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID); ENET_API void enet_peer_ping (ENetPeer *); +ENET_API void enet_peer_ping_interval (ENetPeer *, enet_uint32); +ENET_API void enet_peer_timeout (ENetPeer *, enet_uint32, enet_uint32, enet_uint32); ENET_API void enet_peer_reset (ENetPeer *); ENET_API void enet_peer_disconnect (ENetPeer *, enet_uint32); ENET_API void enet_peer_disconnect_now (ENetPeer *, enet_uint32); @@ -524,10 +570,12 @@ extern int enet_peer_throttle (ENetPeer *, enet_uint32); extern void enet_peer_reset_queues (ENetPeer *); extern void enet_peer_setup_outgoing_command (ENetPeer *, ENetOutgoingCommand *); extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16); -extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32); +extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32); extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16); extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *); extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *); +extern void enet_peer_on_connect (ENetPeer *); +extern void enet_peer_on_disconnect (ENetPeer *); ENET_API void * enet_range_coder_create (void); ENET_API void enet_range_coder_destroy (void *); diff --git a/lib/enet/include/enet/protocol.h b/lib/enet/include/enet/protocol.h index faef91790..f8c73d8a6 100644 --- a/lib/enet/include/enet/protocol.h +++ b/lib/enet/include/enet/protocol.h @@ -13,10 +13,11 @@ enum ENET_PROTOCOL_MAXIMUM_MTU = 4096, ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32, ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096, - ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 32768, + ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536, ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1, ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255, - ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF + ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF, + ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024 }; typedef enum _ENetProtocolCommand @@ -52,10 +53,10 @@ typedef enum _ENetProtocolFlag ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12 } ENetProtocolFlag; -#ifdef _MSC_VER_ +#ifdef _MSC_VER #pragma pack(push, 1) #define ENET_PACKED -#elif defined(__GNUC__) +#elif defined(__GNUC__) || defined(__clang__) #define ENET_PACKED __attribute__ ((packed)) #else #define ENET_PACKED @@ -189,7 +190,7 @@ typedef union _ENetProtocol ENetProtocolThrottleConfigure throttleConfigure; } ENET_PACKED ENetProtocol; -#ifdef _MSC_VER_ +#ifdef _MSC_VER #pragma pack(pop) #endif diff --git a/lib/enet/include/enet/unix.h b/lib/enet/include/enet/unix.h index 087015e51..a59e34060 100644 --- a/lib/enet/include/enet/unix.h +++ b/lib/enet/include/enet/unix.h @@ -8,15 +8,17 @@ #include #include #include +#include #include #include +#ifdef MSG_MAXIOVLEN +#define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN +#endif + typedef int ENetSocket; -enum -{ - ENET_SOCKET_NULL = -1 -}; +#define ENET_SOCKET_NULL -1 #define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */ #define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */ @@ -38,7 +40,7 @@ typedef fd_set ENetSocketSet; #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) -#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLEAR (socket, & (sockset)) +#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) #endif /* __ENET_UNIX_H__ */ diff --git a/lib/enet/include/enet/win32.h b/lib/enet/include/enet/win32.h index 0e1cf0c5a..e73ca9d05 100644 --- a/lib/enet/include/enet/win32.h +++ b/lib/enet/include/enet/win32.h @@ -5,11 +5,13 @@ #ifndef __ENET_WIN32_H__ #define __ENET_WIN32_H__ +#ifdef _MSC_VER #ifdef ENET_BUILDING_LIB -#pragma warning (disable: 4996) // 'strncpy' was declared deprecated #pragma warning (disable: 4267) // size_t to int conversion #pragma warning (disable: 4244) // 64bit to 32bit int #pragma warning (disable: 4018) // signed/unsigned mismatch +#pragma warning (disable: 4146) // unary minus operator applied to unsigned type +#endif #endif #include @@ -17,10 +19,7 @@ typedef SOCKET ENetSocket; -enum -{ - ENET_SOCKET_NULL = INVALID_SOCKET -}; +#define ENET_SOCKET_NULL INVALID_SOCKET #define ENET_HOST_TO_NET_16(value) (htons (value)) #define ENET_HOST_TO_NET_32(value) (htonl (value)) @@ -36,8 +35,8 @@ typedef struct #define ENET_CALLBACK __cdecl -#if defined ENET_DLL -#if defined ENET_BUILDING_LIB +#ifdef ENET_DLL +#ifdef ENET_BUILDING_LIB #define ENET_API __declspec( dllexport ) #else #define ENET_API __declspec( dllimport ) @@ -50,7 +49,7 @@ typedef fd_set ENetSocketSet; #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) -#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLEAR (socket, & (sockset)) +#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) #endif /* __ENET_WIN32_H__ */ diff --git a/lib/enet/install-sh b/lib/enet/install-sh deleted file mode 100644 index 6781b987b..000000000 --- a/lib/enet/install-sh +++ /dev/null @@ -1,520 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2009-04-28.21; # UTC - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -nl=' -' -IFS=" "" $nl" - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -chgrpprog=${CHGRPPROG-chgrp} -chmodprog=${CHMODPROG-chmod} -chownprog=${CHOWNPROG-chown} -cmpprog=${CMPPROG-cmp} -cpprog=${CPPROG-cp} -mkdirprog=${MKDIRPROG-mkdir} -mvprog=${MVPROG-mv} -rmprog=${RMPROG-rm} -stripprog=${STRIPPROG-strip} - -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -no_target_directory= - -usage="\ -Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: - --help display this help and exit. - --version display version info and exit. - - -c (ignored) - -C install only if different (preserve the last data modification time) - -d create directories instead of installing files. - -g GROUP $chgrpprog installed files to GROUP. - -m MODE $chmodprog installed files to MODE. - -o USER $chownprog installed files to USER. - -s $stripprog installed files. - -t DIRECTORY install into DIRECTORY. - -T report an error if DSTFILE is a directory. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG - RMPROG STRIPPROG -" - -while test $# -ne 0; do - case $1 in - -c) ;; - - -C) copy_on_change=true;; - - -d) dir_arg=true;; - - -g) chgrpcmd="$chgrpprog $2" - shift;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -s) stripcmd=$stripprog;; - - -t) dst_arg=$2 - shift;; - - -T) no_target_directory=true;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dst_arg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dst_arg" - shift # fnord - fi - shift # arg - dst_arg=$arg - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call `install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - trap '(exit $?); exit' 1 2 13 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names starting with `-'. - case $src in - -*) src=./$src;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dst_arg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - - dst=$dst_arg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst;; - esac - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writeable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix='/';; - -*) prefix='./';; - *) prefix='';; - esac - - eval "$initialize_posix_glob" - - oIFS=$IFS - IFS=/ - $posix_glob set -f - set fnord $dstdir - shift - $posix_glob set +f - IFS=$oIFS - - prefixes= - - for d - do - test -z "$d" && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && - { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && - { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # If -C, don't bother to copy if it wouldn't change the file. - if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # Rename the file to the real destination. - $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - fi || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/lib/enet/missing b/lib/enet/missing deleted file mode 100644 index 28055d2ae..000000000 --- a/lib/enet/missing +++ /dev/null @@ -1,376 +0,0 @@ -#! /bin/sh -# Common stub for a few missing GNU programs while installing. - -scriptversion=2009-04-28.21; # UTC - -# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, -# 2008, 2009 Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. - -# 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 2, 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 . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 -fi - -run=: -sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' -sed_minuso='s/.* -o \([^ ]*\).*/\1/p' - -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi - -msg="missing on your system" - -case $1 in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - # Exit code 63 means version mismatch. This often happens - # when the user try to use an ancient version of a tool on - # a file that requires a minimum version. In this case we - # we should proceed has if the program had been absent, or - # if --run hadn't been passed. - if test $? = 63; then - run=: - msg="probably too old" - fi - ;; - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails - -Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - autom4te touch the output file, or create a stub one - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags - yacc create \`y.tab.[ch]', if possible, from existing .[ch] - -Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and -\`g' are ignored when checking the name. - -Send bug reports to ." - exit $? - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing $scriptversion (GNU Automake)" - exit $? - ;; - - -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 - ;; - -esac - -# normalize program name to check for. -program=`echo "$1" | sed ' - s/^gnu-//; t - s/^gnu//; t - s/^g//; t'` - -# Now exit if we have it, but it failed. Also exit now if we -# don't have it and --version was passed (most likely to detect -# the program). This is about non-GNU programs, so use $1 not -# $program. -case $1 in - lex*|yacc*) - # Not GNU programs, they don't have --version. - ;; - - tar*) - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - exit 1 - fi - ;; - - *) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - # Could not run --version or --help. This is probably someone - # running `$TOOL --version' or `$TOOL --help' to check whether - # $TOOL exists and not knowing $TOOL uses missing. - exit 1 - fi - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case $program in - aclocal*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case $f in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - autom4te*) - echo 1>&2 "\ -WARNING: \`$1' is needed, but is $msg. - You might have modified some files without having the - proper tools for further handling them. - You can get \`$1' as part of \`Autoconf' from any GNU - archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo "#! /bin/sh" - echo "# Created by GNU Automake missing as a replacement of" - echo "# $ $@" - echo "exit 0" - chmod +x $file - exit 1 - fi - ;; - - bison*|yacc*) - echo 1>&2 "\ -WARNING: \`$1' $msg. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if test $# -ne 1; then - eval LASTARG="\${$#}" - case $LASTARG in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if test ! -f y.tab.h; then - echo >y.tab.h - fi - if test ! -f y.tab.c; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex*|flex*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if test $# -ne 1; then - eval LASTARG="\${$#}" - case $LASTARG in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if test ! -f lex.yy.c; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit $? - fi - ;; - - makeinfo*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - # The file to touch is that specified with -o ... - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -z "$file"; then - # ... or it is the one specified with @setfilename ... - infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n ' - /^@setfilename/{ - s/.* \([^ ]*\) *$/\1/ - p - q - }' $infile` - # ... or it is derived from the source name (dir/f.texi becomes f.info) - test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info - fi - # If the file does not exist, the user really needs makeinfo; - # let's fail without touching anything. - test -f $file || exit 1 - touch $file - ;; - - tar*) - shift - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar "$@" && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar "$@" && exit 0 - fi - firstarg="$1" - if shift; then - case $firstarg in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - case $firstarg in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and is $msg. - You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequisites for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; -esac - -exit 0 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/lib/enet/packet.c b/lib/enet/packet.c index 2fc9a10e8..5fa78b28a 100644 --- a/lib/enet/packet.c +++ b/lib/enet/packet.c @@ -11,7 +11,7 @@ */ /** Creates a packet that may be sent to a peer. - @param dataContents initial contents of the packet's data; the packet's data will remain uninitialized if dataContents is NULL. + @param data initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL. @param dataLength size of the data allocated for this packet @param flags flags for this packet as described for the ENetPacket structure. @returns the packet on success, NULL on failure @@ -26,6 +26,9 @@ enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) packet -> data = (enet_uint8 *) data; else + if (dataLength <= 0) + packet -> data = NULL; + else { packet -> data = (enet_uint8 *) enet_malloc (dataLength); if (packet -> data == NULL) @@ -42,6 +45,7 @@ enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) packet -> flags = flags; packet -> dataLength = dataLength; packet -> freeCallback = NULL; + packet -> userData = NULL; return packet; } @@ -52,9 +56,13 @@ enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) void enet_packet_destroy (ENetPacket * packet) { + if (packet == NULL) + return; + if (packet -> freeCallback != NULL) (* packet -> freeCallback) (packet); - if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE)) + if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE) && + packet -> data != NULL) enet_free (packet -> data); enet_free (packet); } @@ -108,7 +116,7 @@ reflect_crc (int val, int bits) } static void -initialize_crc32 () +initialize_crc32 (void) { int byte; diff --git a/lib/enet/peer.c b/lib/enet/peer.c index 566f79786..e2d0872bd 100644 --- a/lib/enet/peer.c +++ b/lib/enet/peer.c @@ -25,7 +25,7 @@ the mean round trip time measured over the interval, then the throttle probability is decreased to limit traffic by an amount specified in the deceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant. When the throttle has - a value of ENET_PEER_PACKET_THROTTLE_SCALE, on unreliable packets are dropped by + a value of ENET_PEER_PACKET_THROTTLE_SCALE, no unreliable packets are dropped by ENet, and so 100% of all unreliable packets will be sent. When the throttle has a value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable packets will be sent. Intermediate values for the throttle represent intermediate @@ -104,7 +104,8 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) size_t fragmentLength; if (peer -> state != ENET_PEER_STATE_CONNECTED || - channelID >= peer -> channelCount) + channelID >= peer -> channelCount || + packet -> dataLength > peer -> host -> maximumPacketSize) return -1; fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment); @@ -113,7 +114,7 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) if (packet -> dataLength > fragmentLength) { - enet_uint32 fragmentCount = ENET_HOST_TO_NET_32 ((packet -> dataLength + fragmentLength - 1) / fragmentLength), + enet_uint32 fragmentCount = (packet -> dataLength + fragmentLength - 1) / fragmentLength, fragmentNumber, fragmentOffset; enet_uint8 commandNumber; @@ -121,6 +122,9 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) ENetList fragments; ENetOutgoingCommand * fragment; + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) + return -1; + if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT)) == ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT && channel -> outgoingUnreliableSequenceNumber < 0xFFFF) { @@ -164,7 +168,7 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) fragment -> command.header.channelID = channelID; fragment -> command.sendFragment.startSequenceNumber = startSequenceNumber; fragment -> command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength); - fragment -> command.sendFragment.fragmentCount = fragmentCount; + fragment -> command.sendFragment.fragmentCount = ENET_HOST_TO_NET_32 (fragmentCount); fragment -> command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber); fragment -> command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength); fragment -> command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset); @@ -237,6 +241,8 @@ enet_peer_receive (ENetPeer * peer, enet_uint8 * channelID) enet_free (incomingCommand); + peer -> totalWaitingData -= packet -> dataLength; + return packet; } @@ -292,7 +298,7 @@ enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startComm static void enet_peer_reset_incoming_commands (ENetList * queue) { - enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end(queue)); + enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end (queue)); } void @@ -333,6 +339,30 @@ enet_peer_reset_queues (ENetPeer * peer) peer -> channelCount = 0; } +void +enet_peer_on_connect (ENetPeer * peer) +{ + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + { + if (peer -> incomingBandwidth != 0) + ++ peer -> host -> bandwidthLimitedPeers; + + ++ peer -> host -> connectedPeers; + } +} + +void +enet_peer_on_disconnect (ENetPeer * peer) +{ + if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) + { + if (peer -> incomingBandwidth != 0) + -- peer -> host -> bandwidthLimitedPeers; + + -- peer -> host -> connectedPeers; + } +} + /** Forcefully disconnects a peer. @param peer peer to forcefully disconnect @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout @@ -341,6 +371,8 @@ enet_peer_reset_queues (ENetPeer * peer) void enet_peer_reset (ENetPeer * peer) { + enet_peer_on_disconnect (peer); + peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID; peer -> connectID = 0; @@ -368,6 +400,10 @@ enet_peer_reset (ENetPeer * peer) peer -> packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION; peer -> packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION; peer -> packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL; + peer -> pingInterval = ENET_PEER_PING_INTERVAL; + peer -> timeoutLimit = ENET_PEER_TIMEOUT_LIMIT; + peer -> timeoutMinimum = ENET_PEER_TIMEOUT_MINIMUM; + peer -> timeoutMaximum = ENET_PEER_TIMEOUT_MAXIMUM; peer -> lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; peer -> lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; peer -> lastRoundTripTimeVariance = 0; @@ -381,6 +417,7 @@ enet_peer_reset (ENetPeer * peer) peer -> incomingUnsequencedGroup = 0; peer -> outgoingUnsequencedGroup = 0; peer -> eventData = 0; + peer -> totalWaitingData = 0; memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow)); @@ -390,7 +427,7 @@ enet_peer_reset (ENetPeer * peer) /** Sends a ping request to a peer. @param peer destination for the ping request @remarks ping requests factor into the mean round trip time as designated by the - roundTripTime field in the ENetPeer structure. Enet automatically pings all connected + roundTripTime field in the ENetPeer structure. ENet automatically pings all connected peers at regular intervals, however, this function may be called to ensure more frequent ping requests. */ @@ -408,11 +445,51 @@ enet_peer_ping (ENetPeer * peer) enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); } +/** Sets the interval at which pings will be sent to a peer. + + Pings are used both to monitor the liveness of the connection and also to dynamically + adjust the throttle during periods of low traffic so that the throttle has reasonable + responsiveness during traffic spikes. + + @param peer the peer to adjust + @param pingInterval the interval at which to send pings; defaults to ENET_PEER_PING_INTERVAL if 0 +*/ +void +enet_peer_ping_interval (ENetPeer * peer, enet_uint32 pingInterval) +{ + peer -> pingInterval = pingInterval ? pingInterval : ENET_PEER_PING_INTERVAL; +} + +/** Sets the timeout parameters for a peer. + + The timeout parameter control how and when a peer will timeout from a failure to acknowledge + reliable traffic. Timeout values use an exponential backoff mechanism, where if a reliable + packet is not acknowledge within some multiple of the average RTT plus a variance tolerance, + the timeout will be doubled until it reaches a set limit. If the timeout is thus at this + limit and reliable packets have been sent but not acknowledged within a certain minimum time + period, the peer will be disconnected. Alternatively, if reliable packets have been sent + but not acknowledged for a certain maximum time period, the peer will be disconnected regardless + of the current timeout limit value. + + @param peer the peer to adjust + @param timeoutLimit the timeout limit; defaults to ENET_PEER_TIMEOUT_LIMIT if 0 + @param timeoutMinimum the timeout minimum; defaults to ENET_PEER_TIMEOUT_MINIMUM if 0 + @param timeoutMaximum the timeout maximum; defaults to ENET_PEER_TIMEOUT_MAXIMUM if 0 +*/ + +void +enet_peer_timeout (ENetPeer * peer, enet_uint32 timeoutLimit, enet_uint32 timeoutMinimum, enet_uint32 timeoutMaximum) +{ + peer -> timeoutLimit = timeoutLimit ? timeoutLimit : ENET_PEER_TIMEOUT_LIMIT; + peer -> timeoutMinimum = timeoutMinimum ? timeoutMinimum : ENET_PEER_TIMEOUT_MINIMUM; + peer -> timeoutMaximum = timeoutMaximum ? timeoutMaximum : ENET_PEER_TIMEOUT_MAXIMUM; +} + /** Force an immediate disconnection from a peer. @param peer peer to disconnect @param data data describing the disconnection @remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not - guarenteed to receive the disconnect notification, and is reset immediately upon + guaranteed to receive the disconnect notification, and is reset immediately upon return from this function. */ void @@ -471,7 +548,11 @@ enet_peer_disconnect (ENetPeer * peer, enet_uint32 data) enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) - peer -> state = ENET_PEER_STATE_DISCONNECTING; + { + enet_peer_on_disconnect (peer); + + peer -> state = ENET_PEER_STATE_DISCONNECTING; + } else { enet_host_flush (peer -> host); @@ -536,7 +617,7 @@ void enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand) { ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID]; - + peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength; if (outgoingCommand -> command.header.channelID == 0xFF) @@ -630,42 +711,71 @@ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) continue; - else - if (incomingCommand -> reliableSequenceNumber != channel -> incomingReliableSequenceNumber) - break; - else - if (incomingCommand -> fragmentsRemaining <= 0) - channel -> incomingUnreliableSequenceNumber = incomingCommand -> unreliableSequenceNumber; - else - if (startCommand == currentCommand) - startCommand = enet_list_next (currentCommand); - else - { - enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); - if (! peer -> needsDispatch) - { + if (incomingCommand -> reliableSequenceNumber == channel -> incomingReliableSequenceNumber) + { + if (incomingCommand -> fragmentsRemaining <= 0) + { + channel -> incomingUnreliableSequenceNumber = incomingCommand -> unreliableSequenceNumber; + continue; + } + + if (startCommand != currentCommand) + { + enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); + + if (! peer -> needsDispatch) + { enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); peer -> needsDispatch = 1; - } + } - droppedCommand = startCommand = enet_list_next (currentCommand); + droppedCommand = currentCommand; + } + else + if (droppedCommand != currentCommand) + droppedCommand = enet_list_previous (currentCommand); } + else + { + enet_uint16 reliableWindow = incomingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE, + currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber) + reliableWindow += ENET_PEER_RELIABLE_WINDOWS; + if (reliableWindow >= currentWindow && reliableWindow < currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) + break; + + droppedCommand = enet_list_next (currentCommand); + + if (startCommand != currentCommand) + { + enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); + + if (! peer -> needsDispatch) + { + enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); + + peer -> needsDispatch = 1; + } + } + } + + startCommand = enet_list_next (currentCommand); } if (startCommand != currentCommand) { - enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); + enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); - if (! peer -> needsDispatch) - { - enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); + if (! peer -> needsDispatch) + { + enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); - peer -> needsDispatch = 1; - } + peer -> needsDispatch = 1; + } - droppedCommand = startCommand = enet_list_next (currentCommand); + droppedCommand = currentCommand; } enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand); @@ -706,22 +816,24 @@ enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * ch peer -> needsDispatch = 1; } - enet_peer_dispatch_incoming_unreliable_commands (peer, channel); + if (! enet_list_empty (& channel -> incomingUnreliableCommands)) + enet_peer_dispatch_incoming_unreliable_commands (peer, channel); } ENetIncomingCommand * -enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 fragmentCount) +enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, const void * data, size_t dataLength, enet_uint32 flags, enet_uint32 fragmentCount) { static ENetIncomingCommand dummyCommand; ENetChannel * channel = & peer -> channels [command -> header.channelID]; - enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber; + enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber = 0; enet_uint16 reliableWindow, currentWindow; ENetIncomingCommand * incomingCommand; ENetListIterator currentCommand; + ENetPacket * packet = NULL; if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) - goto freePacket; + goto discardCommand; if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) { @@ -733,7 +845,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, reliableWindow += ENET_PEER_RELIABLE_WINDOWS; if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) - goto freePacket; + goto discardCommand; } switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK) @@ -741,7 +853,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber) - goto freePacket; + goto discardCommand; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands)); currentCommand != enet_list_end (& channel -> incomingReliableCommands); @@ -763,7 +875,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber) break; - goto freePacket; + goto discardCommand; } } break; @@ -774,7 +886,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber && unreliableSequenceNumber <= channel -> incomingUnreliableSequenceNumber) - goto freePacket; + goto discardCommand; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands)); currentCommand != enet_list_end (& channel -> incomingUnreliableCommands); @@ -805,7 +917,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber) break; - goto freePacket; + goto discardCommand; } } break; @@ -815,9 +927,16 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, break; default: - goto freePacket; + goto discardCommand; } + if (peer -> totalWaitingData >= peer -> host -> maximumWaitingData) + goto notifyError; + + packet = enet_packet_create (data, dataLength, flags); + if (packet == NULL) + goto notifyError; + incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand)); if (incomingCommand == NULL) goto notifyError; @@ -832,7 +951,8 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, if (fragmentCount > 0) { - incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32)); + if (fragmentCount <= ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) + incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32)); if (incomingCommand -> fragments == NULL) { enet_free (incomingCommand); @@ -843,7 +963,11 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, } if (packet != NULL) - ++ packet -> referenceCount; + { + ++ packet -> referenceCount; + + peer -> totalWaitingData += packet -> dataLength; + } enet_list_insert (enet_list_next (currentCommand), incomingCommand); @@ -861,7 +985,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, return incomingCommand; -freePacket: +discardCommand: if (fragmentCount > 0) goto notifyError; diff --git a/lib/enet/protocol.c b/lib/enet/protocol.c index bd9864530..101d923e0 100644 --- a/lib/enet/protocol.c +++ b/lib/enet/protocol.c @@ -32,6 +32,30 @@ enet_protocol_command_size (enet_uint8 commandNumber) return commandSizes [commandNumber & ENET_PROTOCOL_COMMAND_MASK]; } +static void +enet_protocol_change_state (ENetHost * host, ENetPeer * peer, ENetPeerState state) +{ + if (state == ENET_PEER_STATE_CONNECTED || state == ENET_PEER_STATE_DISCONNECT_LATER) + enet_peer_on_connect (peer); + else + enet_peer_on_disconnect (peer); + + peer -> state = state; +} + +static void +enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState state) +{ + enet_protocol_change_state (host, peer, state); + + if (! peer -> needsDispatch) + { + enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList); + + peer -> needsDispatch = 1; + } +} + static int enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) { @@ -45,7 +69,7 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) { case ENET_PEER_STATE_CONNECTION_PENDING: case ENET_PEER_STATE_CONNECTION_SUCCEEDED: - peer -> state = ENET_PEER_STATE_CONNECTED; + enet_protocol_change_state (host, peer, ENET_PEER_STATE_CONNECTED); event -> type = ENET_EVENT_TYPE_CONNECT; event -> peer = peer; @@ -83,27 +107,15 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) } return 1; - default: - break; + + default: + break; } } return 0; } -static void -enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState state) -{ - peer -> state = state; - - if (! peer -> needsDispatch) - { - enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList); - - peer -> needsDispatch = 1; - } -} - static void enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * event) { @@ -111,7 +123,7 @@ enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * even if (event != NULL) { - peer -> state = ENET_PEER_STATE_CONNECTED; + enet_protocol_change_state (host, peer, ENET_PEER_STATE_CONNECTED); event -> type = ENET_EVENT_TYPE_CONNECT; event -> peer = peer; @@ -162,7 +174,11 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer) -- outgoingCommand -> packet -> referenceCount; if (outgoingCommand -> packet -> referenceCount == 0) - enet_packet_destroy (outgoingCommand -> packet); + { + outgoingCommand -> packet -> flags |= ENET_PACKET_FLAG_SENT; + + enet_packet_destroy (outgoingCommand -> packet); + } } enet_free (outgoingCommand); @@ -172,7 +188,7 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer) static ENetProtocolCommand enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliableSequenceNumber, enet_uint8 channelID) { - ENetOutgoingCommand * outgoingCommand; + ENetOutgoingCommand * outgoingCommand = NULL; ENetListIterator currentCommand; ENetProtocolCommand commandNumber; int wasSent = 1; @@ -209,6 +225,9 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl wasSent = 0; } + if (outgoingCommand == NULL) + return ENET_PROTOCOL_COMMAND_NONE; + if (channelID < peer -> channelCount) { ENetChannel * channel = & peer -> channels [channelID]; @@ -233,7 +252,11 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl -- outgoingCommand -> packet -> referenceCount; if (outgoingCommand -> packet -> referenceCount == 0) - enet_packet_destroy (outgoingCommand -> packet); + { + outgoingCommand -> packet -> flags |= ENET_PACKET_FLAG_SENT; + + enet_packet_destroy (outgoingCommand -> packet); + } } enet_free (outgoingCommand); @@ -254,8 +277,8 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet enet_uint8 incomingSessionID, outgoingSessionID; enet_uint32 mtu, windowSize; ENetChannel * channel; - size_t channelCount; - ENetPeer * currentPeer; + size_t channelCount, duplicatePeers = 0; + ENetPeer * currentPeer, * peer = NULL; ENetProtocol verifyCommand; channelCount = ENET_NET_TO_HOST_32 (command -> connect.channelCount); @@ -264,59 +287,61 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) return NULL; - for (currentPeer = host -> peers; - currentPeer < & host -> peers [host -> peerCount]; - ++ currentPeer) - { - if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED && - currentPeer -> address.host == host -> receivedAddress.host && - currentPeer -> address.port == host -> receivedAddress.port && - currentPeer -> connectID == command -> connect.connectID) - return NULL; - } - for (currentPeer = host -> peers; currentPeer < & host -> peers [host -> peerCount]; ++ currentPeer) { if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED) - break; + { + if (peer == NULL) + peer = currentPeer; + } + else + if (currentPeer -> state != ENET_PEER_STATE_CONNECTING && + currentPeer -> address.host == host -> receivedAddress.host) + { + if (currentPeer -> address.port == host -> receivedAddress.port && + currentPeer -> connectID == command -> connect.connectID) + return NULL; + + ++ duplicatePeers; + } } - if (currentPeer >= & host -> peers [host -> peerCount]) + if (peer == NULL || duplicatePeers >= host -> duplicatePeers) return NULL; if (channelCount > host -> channelLimit) channelCount = host -> channelLimit; - currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel)); - if (currentPeer -> channels == NULL) + peer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel)); + if (peer -> channels == NULL) return NULL; - currentPeer -> channelCount = channelCount; - currentPeer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT; - currentPeer -> connectID = command -> connect.connectID; - currentPeer -> address = host -> receivedAddress; - currentPeer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID); - currentPeer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth); - currentPeer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth); - currentPeer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleInterval); - currentPeer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleAcceleration); - currentPeer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleDeceleration); - currentPeer -> eventData = ENET_NET_TO_HOST_32 (command -> connect.data); + peer -> channelCount = channelCount; + peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT; + peer -> connectID = command -> connect.connectID; + peer -> address = host -> receivedAddress; + peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID); + peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth); + peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth); + peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleInterval); + peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleAcceleration); + peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleDeceleration); + peer -> eventData = ENET_NET_TO_HOST_32 (command -> connect.data); - incomingSessionID = command -> connect.incomingSessionID == 0xFF ? currentPeer -> outgoingSessionID : command -> connect.incomingSessionID; + incomingSessionID = command -> connect.incomingSessionID == 0xFF ? peer -> outgoingSessionID : command -> connect.incomingSessionID; incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - if (incomingSessionID == currentPeer -> outgoingSessionID) + if (incomingSessionID == peer -> outgoingSessionID) incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - currentPeer -> outgoingSessionID = incomingSessionID; + peer -> outgoingSessionID = incomingSessionID; - outgoingSessionID = command -> connect.outgoingSessionID == 0xFF ? currentPeer -> incomingSessionID : command -> connect.outgoingSessionID; + outgoingSessionID = command -> connect.outgoingSessionID == 0xFF ? peer -> incomingSessionID : command -> connect.outgoingSessionID; outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - if (outgoingSessionID == currentPeer -> incomingSessionID) + if (outgoingSessionID == peer -> incomingSessionID) outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - currentPeer -> incomingSessionID = outgoingSessionID; + peer -> incomingSessionID = outgoingSessionID; - for (channel = currentPeer -> channels; - channel < & currentPeer -> channels [channelCount]; + for (channel = peer -> channels; + channel < & peer -> channels [channelCount]; ++ channel) { channel -> outgoingReliableSequenceNumber = 0; @@ -339,27 +364,27 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet if (mtu > ENET_PROTOCOL_MAXIMUM_MTU) mtu = ENET_PROTOCOL_MAXIMUM_MTU; - currentPeer -> mtu = mtu; + peer -> mtu = mtu; if (host -> outgoingBandwidth == 0 && - currentPeer -> incomingBandwidth == 0) - currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + peer -> incomingBandwidth == 0) + peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; else if (host -> outgoingBandwidth == 0 || - currentPeer -> incomingBandwidth == 0) - currentPeer -> windowSize = (ENET_MAX (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) / + peer -> incomingBandwidth == 0) + peer -> windowSize = (ENET_MAX (host -> outgoingBandwidth, peer -> incomingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; else - currentPeer -> windowSize = (ENET_MIN (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) / + peer -> windowSize = (ENET_MIN (host -> outgoingBandwidth, peer -> incomingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) - currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + if (peer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) + peer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; else - if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) - currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + if (peer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) + peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; if (host -> incomingBandwidth == 0) windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; @@ -378,28 +403,27 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; verifyCommand.header.channelID = 0xFF; - verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID); + verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (peer -> incomingPeerID); verifyCommand.verifyConnect.incomingSessionID = incomingSessionID; verifyCommand.verifyConnect.outgoingSessionID = outgoingSessionID; - verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu); + verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_32 (peer -> mtu); verifyCommand.verifyConnect.windowSize = ENET_HOST_TO_NET_32 (windowSize); verifyCommand.verifyConnect.channelCount = ENET_HOST_TO_NET_32 (channelCount); verifyCommand.verifyConnect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth); verifyCommand.verifyConnect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth); - verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval); - verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration); - verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration); - verifyCommand.verifyConnect.connectID = currentPeer -> connectID; + verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32 (peer -> packetThrottleInterval); + verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (peer -> packetThrottleAcceleration); + verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (peer -> packetThrottleDeceleration); + verifyCommand.verifyConnect.connectID = peer -> connectID; - enet_peer_queue_outgoing_command (currentPeer, & verifyCommand, NULL, 0, 0); + enet_peer_queue_outgoing_command (peer, & verifyCommand, NULL, 0, 0); - return currentPeer; + return peer; } static int enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData) { - ENetPacket * packet; size_t dataLength; if (command -> header.channelID >= peer -> channelCount || @@ -408,14 +432,12 @@ enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENet dataLength = ENET_NET_TO_HOST_16 (command -> sendReliable.dataLength); * currentData += dataLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (dataLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; - packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendReliable), - dataLength, - ENET_PACKET_FLAG_RELIABLE); - if (packet == NULL || - enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL) + if (enet_peer_queue_incoming_command (peer, command, (const enet_uint8 *) command + sizeof (ENetProtocolSendReliable), dataLength, ENET_PACKET_FLAG_RELIABLE, 0) == NULL) return -1; return 0; @@ -424,7 +446,6 @@ enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENet static int enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData) { - ENetPacket * packet; enet_uint32 unsequencedGroup, index; size_t dataLength; @@ -434,7 +455,9 @@ enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const E dataLength = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.dataLength); * currentData += dataLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (dataLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; unsequencedGroup = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.unsequencedGroup); @@ -458,11 +481,7 @@ enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const E if (peer -> unsequencedWindow [index / 32] & (1 << (index % 32))) return 0; - packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnsequenced), - dataLength, - ENET_PACKET_FLAG_UNSEQUENCED); - if (packet == NULL || - enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL) + if (enet_peer_queue_incoming_command (peer, command, (const enet_uint8 *) command + sizeof (ENetProtocolSendUnsequenced), dataLength, ENET_PACKET_FLAG_UNSEQUENCED, 0) == NULL) return -1; peer -> unsequencedWindow [index / 32] |= 1 << (index % 32); @@ -473,7 +492,6 @@ enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const E static int enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData) { - ENetPacket * packet; size_t dataLength; if (command -> header.channelID >= peer -> channelCount || @@ -482,14 +500,12 @@ enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const EN dataLength = ENET_NET_TO_HOST_16 (command -> sendUnreliable.dataLength); * currentData += dataLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (dataLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; - packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable), - dataLength, - 0); - if (packet == NULL || - enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL) + if (enet_peer_queue_incoming_command (peer, command, (const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable), dataLength, 0, 0) == NULL) return -1; return 0; @@ -515,7 +531,9 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength); * currentData += fragmentLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (fragmentLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; channel = & peer -> channels [command -> header.channelID]; @@ -534,9 +552,11 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset); totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength); - if (fragmentOffset >= totalLength || - fragmentOffset + fragmentLength > totalLength || - fragmentNumber >= fragmentCount) + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT || + fragmentNumber >= fragmentCount || + totalLength > host -> maximumPacketSize || + fragmentOffset >= totalLength || + fragmentLength > totalLength - fragmentOffset) return -1; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands)); @@ -572,13 +592,10 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet if (startCommand == NULL) { ENetProtocol hostCommand = * command; - ENetPacket * packet = enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_RELIABLE); - if (packet == NULL) - return -1; hostCommand.header.reliableSequenceNumber = startSequenceNumber; - startCommand = enet_peer_queue_incoming_command (peer, & hostCommand, packet, fragmentCount); + startCommand = enet_peer_queue_incoming_command (peer, & hostCommand, NULL, totalLength, ENET_PACKET_FLAG_RELIABLE, fragmentCount); if (startCommand == NULL) return -1; } @@ -624,7 +641,9 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength); * currentData += fragmentLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (fragmentLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; channel = & peer -> channels [command -> header.channelID]; @@ -649,9 +668,11 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset); totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength); - if (fragmentOffset >= totalLength || - fragmentOffset + fragmentLength > totalLength || - fragmentNumber >= fragmentCount) + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT || + fragmentNumber >= fragmentCount || + totalLength > host -> maximumPacketSize || + fragmentOffset >= totalLength || + fragmentLength > totalLength - fragmentOffset) return -1; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands)); @@ -692,11 +713,7 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, if (startCommand == NULL) { - ENetPacket * packet = enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT); - if (packet == NULL) - return -1; - - startCommand = enet_peer_queue_incoming_command (peer, command, packet, fragmentCount); + startCommand = enet_peer_queue_incoming_command (peer, command, NULL, totalLength, ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT, fragmentCount); if (startCommand == NULL) return -1; } @@ -724,15 +741,27 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, static int enet_protocol_handle_ping (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + return -1; + return 0; } static int enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + return -1; + + if (peer -> incomingBandwidth != 0) + -- host -> bandwidthLimitedPeers; + peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.incomingBandwidth); peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.outgoingBandwidth); + if (peer -> incomingBandwidth != 0) + ++ host -> bandwidthLimitedPeers; + if (peer -> incomingBandwidth == 0 && host -> outgoingBandwidth == 0) peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; else @@ -751,6 +780,9 @@ enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const EN static int enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + return -1; + peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleInterval); peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleAcceleration); peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleDeceleration); @@ -761,12 +793,12 @@ enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const static int enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { - if (peer -> state == ENET_PEER_STATE_ZOMBIE || peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT) + if (peer -> state == ENET_PEER_STATE_DISCONNECTED || peer -> state == ENET_PEER_STATE_ZOMBIE || peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT) return 0; enet_peer_reset_queues (peer); - if (peer -> state == ENET_PEER_STATE_CONNECTION_SUCCEEDED || peer -> state == ENET_PEER_STATE_DISCONNECTING) + if (peer -> state == ENET_PEER_STATE_CONNECTION_SUCCEEDED || peer -> state == ENET_PEER_STATE_DISCONNECTING || peer -> state == ENET_PEER_STATE_CONNECTING) enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE); else if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) @@ -777,7 +809,7 @@ enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetPro } else if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) - peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT; + enet_protocol_change_state (host, peer, ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT); else enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE); @@ -795,6 +827,9 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * receivedReliableSequenceNumber; ENetProtocolCommand commandNumber; + if (peer -> state == ENET_PEER_STATE_DISCONNECTED || peer -> state == ENET_PEER_STATE_ZOMBIE) + return 0; + receivedSentTime = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedSentTime); receivedSentTime |= host -> serviceTime & 0xFFFF0000; if ((receivedSentTime & 0x8000) > (host -> serviceTime & 0x8000)) @@ -865,8 +900,9 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * enet_list_empty (& peer -> sentReliableCommands)) enet_peer_disconnect (peer, peer -> eventData); break; + default: - break; + break; } return 0; @@ -1046,7 +1082,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> header.reliableSequenceNumber); - switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK) + switch (commandNumber) { case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE: if (enet_protocol_handle_acknowledge (host, event, peer, command)) @@ -1054,6 +1090,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) break; case ENET_PROTOCOL_COMMAND_CONNECT: + if (peer != NULL) + goto commandError; peer = enet_protocol_handle_connect (host, header, command); if (peer == NULL) goto commandError; @@ -1127,6 +1165,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) { case ENET_PEER_STATE_DISCONNECTING: case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT: + case ENET_PEER_STATE_DISCONNECTED: + case ENET_PEER_STATE_ZOMBIE: break; case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT: @@ -1175,7 +1215,25 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event) host -> totalReceivedData += receivedLength; host -> totalReceivedPackets ++; - + + if (host -> intercept != NULL) + { + switch (host -> intercept (host, event)) + { + case 1: + if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE) + return 1; + + continue; + + case -1: + return -1; + + default: + break; + } + } + switch (enet_protocol_handle_incoming_commands (host, event)) { case 1: @@ -1199,7 +1257,8 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer) ENetBuffer * buffer = & host -> buffers [host -> bufferCount]; ENetAcknowledgement * acknowledgement; ENetListIterator currentAcknowledgement; - + enet_uint16 reliableSequenceNumber; + currentAcknowledgement = enet_list_begin (& peer -> acknowledgements); while (currentAcknowledgement != enet_list_end (& peer -> acknowledgements)) @@ -1221,10 +1280,13 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer) buffer -> dataLength = sizeof (ENetProtocolAcknowledge); host -> packetSize += buffer -> dataLength; - + + reliableSequenceNumber = ENET_HOST_TO_NET_16 (acknowledgement -> command.header.reliableSequenceNumber); + command -> header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE; command -> header.channelID = acknowledgement -> command.header.channelID; - command -> acknowledge.receivedReliableSequenceNumber = ENET_HOST_TO_NET_16 (acknowledgement -> command.header.reliableSequenceNumber); + command -> header.reliableSequenceNumber = reliableSequenceNumber; + command -> acknowledge.receivedReliableSequenceNumber = reliableSequenceNumber; command -> acknowledge.receivedSentTime = ENET_HOST_TO_NET_16 (acknowledgement -> sentTime); if ((acknowledgement -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT) @@ -1365,9 +1427,9 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even peer -> earliestTimeout = outgoingCommand -> sentTime; if (peer -> earliestTimeout != 0 && - (ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= ENET_PEER_TIMEOUT_MAXIMUM || + (ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMaximum || (outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit && - ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= ENET_PEER_TIMEOUT_MINIMUM))) + ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMinimum))) { enet_protocol_notify_disconnect (host, peer, event); @@ -1476,7 +1538,7 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) if (outgoingCommand -> roundTripTimeout == 0) { outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance; - outgoingCommand -> roundTripTimeoutLimit = ENET_PEER_TIMEOUT_LIMIT * outgoingCommand -> roundTripTimeout; + outgoingCommand -> roundTripTimeoutLimit = peer -> timeoutLimit * outgoingCommand -> roundTripTimeout; } if (enet_list_empty (& peer -> sentReliableCommands)) @@ -1552,12 +1614,17 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch ! enet_list_empty (& currentPeer -> sentReliableCommands) && ENET_TIME_GREATER_EQUAL (host -> serviceTime, currentPeer -> nextTimeout) && enet_protocol_check_timeouts (host, currentPeer, event) == 1) - return 1; + { + if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE) + return 1; + else + continue; + } if ((enet_list_empty (& currentPeer -> outgoingReliableCommands) || enet_protocol_send_reliable_outgoing_commands (host, currentPeer)) && enet_list_empty (& currentPeer -> sentReliableCommands) && - ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= ENET_PEER_PING_INTERVAL && + ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= currentPeer -> pingInterval && currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing)) { enet_peer_ping (currentPeer); @@ -1579,12 +1646,7 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent; #ifdef ENET_DEBUG -#ifdef WIN32 - printf ( -#else - fprintf (stderr, -#endif - "peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0); + printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0); #endif currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4; @@ -1629,12 +1691,7 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED; shouldCompress = compressedSize; #ifdef ENET_DEBUG_COMPRESS -#ifdef WIN32 - printf ( -#else - fprintf (stderr, -#endif - "peer %u: compressed %u -> %u (%u%%)\n", currentPeer -> incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize); + printf ("peer %u: compressed %u -> %u (%u%%)\n", currentPeer -> incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize); #endif } } @@ -1738,7 +1795,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error dispatching incoming packets"); +#endif return -1; @@ -1762,7 +1821,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error sending outgoing packets"); +#endif return -1; @@ -1776,7 +1837,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error receiving incoming packets"); +#endif return -1; @@ -1790,7 +1853,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error sending outgoing packets"); +#endif return -1; @@ -1806,7 +1871,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error dispatching incoming packets"); +#endif return -1; @@ -1815,18 +1882,25 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) } } - host -> serviceTime = enet_time_get (); - if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout)) return 0; - waitCondition = ENET_SOCKET_WAIT_RECEIVE; + do + { + host -> serviceTime = enet_time_get (); + + if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout)) + return 0; + + waitCondition = ENET_SOCKET_WAIT_RECEIVE | ENET_SOCKET_WAIT_INTERRUPT; + + if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0) + return -1; + } + while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT); - if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0) - return -1; - host -> serviceTime = enet_time_get (); - } while (waitCondition == ENET_SOCKET_WAIT_RECEIVE); + } while (waitCondition & ENET_SOCKET_WAIT_RECEIVE); return 0; } diff --git a/lib/enet/unix.c b/lib/enet/unix.c index 45badf7e7..581246942 100644 --- a/lib/enet/unix.c +++ b/lib/enet/unix.c @@ -2,17 +2,14 @@ @file unix.c @brief ENet Unix system specific functions */ -#ifndef WIN32 - -#ifdef sun -#include -#endif +#ifndef _WIN32 #include #include #include #include #include +#include #include #include #include @@ -22,21 +19,36 @@ #define ENET_BUILDING_LIB 1 #include "enet/enet.h" -#ifdef HAS_FCNTL -#include +#ifdef __APPLE__ +#ifdef HAS_POLL +#undef HAS_POLL +#endif +#ifndef HAS_FCNTL +#define HAS_FCNTL 1 +#endif +#ifndef HAS_INET_PTON +#define HAS_INET_PTON 1 +#endif +#ifndef HAS_INET_NTOP +#define HAS_INET_NTOP 1 +#endif +#ifndef HAS_MSGHDR_FLAGS +#define HAS_MSGHDR_FLAGS 1 +#endif +#ifndef HAS_SOCKLEN_T +#define HAS_SOCKLEN_T 1 +#endif #endif -#ifdef __APPLE__ -#undef HAS_POLL +#ifdef HAS_FCNTL +#include #endif #ifdef HAS_POLL #include #endif -// _SOCKLEN_T is used on OSX -#if !defined(HAS_SOCKLEN_T) && !defined(_SOCKLEN_T) \ - && !defined(__socklen_t_defined) +#ifndef HAS_SOCKLEN_T typedef int socklen_t; #endif @@ -57,6 +69,12 @@ enet_deinitialize (void) { } +enet_uint32 +enet_host_random_seed (void) +{ + return (enet_uint32) time (NULL); +} + enet_uint32 enet_time_get (void) { @@ -86,7 +104,7 @@ enet_address_set_host (ENetAddress * address, const char * name) char buffer [2048]; int errnum; -#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__) gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum); #else hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum); @@ -120,7 +138,12 @@ enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameL #else char * addr = inet_ntoa (* (struct in_addr *) & address -> host); if (addr != NULL) - strncpy (name, addr, nameLength); + { + size_t addrLen = strlen(addr); + if (addrLen >= nameLength) + return -1; + memcpy (name, addr, addrLen + 1); + } else #endif return -1; @@ -139,7 +162,7 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng in.s_addr = address -> host; -#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__) gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum); #else hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum); @@ -152,8 +175,13 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng if (hostEntry == NULL) return enet_address_get_host_ip (address, name, nameLength); - - strncpy (name, hostEntry -> h_name, nameLength); + else + { + size_t hostLen = strlen (hostEntry -> h_name); + if (hostLen >= nameLength) + return -1; + memcpy (name, hostEntry -> h_name, hostLen + 1); + } return 0; } @@ -183,6 +211,21 @@ enet_socket_bind (ENetSocket socket, const ENetAddress * address) sizeof (struct sockaddr_in)); } +int +enet_socket_get_address (ENetSocket socket, ENetAddress * address) +{ + struct sockaddr_in sin; + socklen_t sinLength = sizeof (struct sockaddr_in); + + if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1) + return -1; + + address -> host = (enet_uint32) sin.sin_addr.s_addr; + address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); + + return 0; +} + int enet_socket_listen (ENetSocket socket, int backlog) { @@ -225,6 +268,46 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); break; + case ENET_SOCKOPT_RCVTIMEO: + { + struct timeval timeVal; + timeVal.tv_sec = value / 1000; + timeVal.tv_usec = (value % 1000) * 1000; + result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & timeVal, sizeof (struct timeval)); + break; + } + + case ENET_SOCKOPT_SNDTIMEO: + { + struct timeval timeVal; + timeVal.tv_sec = value / 1000; + timeVal.tv_usec = (value % 1000) * 1000; + result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & timeVal, sizeof (struct timeval)); + break; + } + + case ENET_SOCKOPT_NODELAY: + result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int)); + break; + + default: + break; + } + return result == -1 ? -1 : 0; +} + +int +enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value) +{ + int result = -1; + socklen_t len; + switch (option) + { + case ENET_SOCKOPT_ERROR: + len = sizeof (int); + result = getsockopt (socket, SOL_SOCKET, SO_ERROR, value, & len); + break; + default: break; } @@ -235,6 +318,7 @@ int enet_socket_connect (ENetSocket socket, const ENetAddress * address) { struct sockaddr_in sin; + int result; memset (& sin, 0, sizeof (struct sockaddr_in)); @@ -242,7 +326,11 @@ enet_socket_connect (ENetSocket socket, const ENetAddress * address) sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); sin.sin_addr.s_addr = address -> host; - return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); + result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); + if (result == -1 && errno == EINPROGRESS) + return 0; + + return result; } ENetSocket @@ -268,10 +356,17 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address) return result; } +int +enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how) +{ + return shutdown (socket, (int) how); +} + void enet_socket_destroy (ENetSocket socket) { - close (socket); + if (socket != -1) + close (socket); } int @@ -389,7 +484,16 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou pollCount = poll (& pollSocket, 1, timeout); if (pollCount < 0) - return -1; + { + if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT) + { + * condition = ENET_SOCKET_WAIT_INTERRUPT; + + return 0; + } + + return -1; + } * condition = ENET_SOCKET_WAIT_NONE; @@ -423,7 +527,16 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal); if (selectCount < 0) - return -1; + { + if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT) + { + * condition = ENET_SOCKET_WAIT_INTERRUPT; + + return 0; + } + + return -1; + } * condition = ENET_SOCKET_WAIT_NONE; diff --git a/lib/enet/win32.c b/lib/enet/win32.c index 83cd5c979..611077e2b 100644 --- a/lib/enet/win32.c +++ b/lib/enet/win32.c @@ -2,7 +2,7 @@ @file win32.c @brief ENet Win32 system specific functions */ -#ifdef WIN32 +#ifdef _WIN32 #include #define ENET_BUILDING_LIB 1 @@ -43,6 +43,12 @@ enet_deinitialize (void) WSACleanup (); } +enet_uint32 +enet_host_random_seed (void) +{ + return (enet_uint32) timeGetTime (); +} + enet_uint32 enet_time_get (void) { @@ -82,7 +88,13 @@ enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameL char * addr = inet_ntoa (* (struct in_addr *) & address -> host); if (addr == NULL) return -1; - strncpy (name, addr, nameLength); + else + { + size_t addrLen = strlen(addr); + if (addrLen >= nameLength) + return -1; + memcpy (name, addr, addrLen + 1); + } return 0; } @@ -91,14 +103,19 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng { struct in_addr in; struct hostent * hostEntry; - + in.s_addr = address -> host; hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET); if (hostEntry == NULL) return enet_address_get_host_ip (address, name, nameLength); - - strncpy (name, hostEntry -> h_name, nameLength); + else + { + size_t hostLen = strlen (hostEntry -> h_name); + if (hostLen >= nameLength) + return -1; + memcpy (name, hostEntry -> h_name, hostLen + 1); + } return 0; } @@ -128,6 +145,21 @@ enet_socket_bind (ENetSocket socket, const ENetAddress * address) sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0; } +int +enet_socket_get_address (ENetSocket socket, ENetAddress * address) +{ + struct sockaddr_in sin; + int sinLength = sizeof (struct sockaddr_in); + + if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1) + return -1; + + address -> host = (enet_uint32) sin.sin_addr.s_addr; + address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); + + return 0; +} + int enet_socket_listen (ENetSocket socket, int backlog) { @@ -169,6 +201,35 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); break; + case ENET_SOCKOPT_RCVTIMEO: + result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_SNDTIMEO: + result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_NODELAY: + result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int)); + break; + + default: + break; + } + return result == SOCKET_ERROR ? -1 : 0; +} + +int +enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value) +{ + int result = SOCKET_ERROR, len; + switch (option) + { + case ENET_SOCKOPT_ERROR: + len = sizeof(int); + result = getsockopt (socket, SOL_SOCKET, SO_ERROR, (char *) value, & len); + break; + default: break; } @@ -179,6 +240,7 @@ int enet_socket_connect (ENetSocket socket, const ENetAddress * address) { struct sockaddr_in sin; + int result; memset (& sin, 0, sizeof (struct sockaddr_in)); @@ -186,7 +248,11 @@ enet_socket_connect (ENetSocket socket, const ENetAddress * address) sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); sin.sin_addr.s_addr = address -> host; - return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0; + result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); + if (result == SOCKET_ERROR && WSAGetLastError () != WSAEWOULDBLOCK) + return -1; + + return 0; } ENetSocket @@ -212,10 +278,17 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address) return result; } +int +enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how) +{ + return shutdown (socket, (int) how) == SOCKET_ERROR ? -1 : 0; +} + void enet_socket_destroy (ENetSocket socket) { - closesocket (socket); + if (socket != INVALID_SOCKET) + closesocket (socket); } int @@ -241,7 +314,7 @@ enet_socket_send (ENetSocket socket, (DWORD) bufferCount, & sentLength, 0, - address != NULL ? (struct sockaddr *) & sin : 0, + address != NULL ? (struct sockaddr *) & sin : NULL, address != NULL ? sizeof (struct sockaddr_in) : 0, NULL, NULL) == SOCKET_ERROR) diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp index 355070877..154904d29 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp @@ -636,7 +636,7 @@ void CIrrDeviceAndroid::createKeyMap() KeyMap[AKEYCODE_DPAD_DOWN] = IRR_KEY_DOWN; KeyMap[AKEYCODE_DPAD_LEFT] = IRR_KEY_LEFT; KeyMap[AKEYCODE_DPAD_RIGHT] = IRR_KEY_RIGHT; - KeyMap[AKEYCODE_DPAD_CENTER] = IRR_KEY_SELECT; + KeyMap[AKEYCODE_DPAD_CENTER] = IRR_KEY_RETURN; KeyMap[AKEYCODE_VOLUME_UP] = IRR_KEY_VOLUME_DOWN; KeyMap[AKEYCODE_VOLUME_DOWN] = IRR_KEY_VOLUME_UP; KeyMap[AKEYCODE_POWER] = IRR_KEY_UNKNOWN; diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp index 00e03dc0a..97fb7b82f 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp @@ -920,6 +920,13 @@ bool CIrrDeviceLinux::createWindow() &visTempl, &visNumber); visTempl.depth -= 8; } + + if (!visual && !CreationParams.WithAlphaChannel) + { + visTempl.depth = 32; + visual = XGetVisualInfo(display, VisualScreenMask|VisualDepthMask, + &visTempl, &visNumber); + } } if (!visual) diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceWayland.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceWayland.cpp index 42247e4fa..5504123fa 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceWayland.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceWayland.cpp @@ -534,23 +534,23 @@ public: int32_t width, int32_t height, wl_array* states) { - void* state_p; + //void* state_p; - wl_array_for_each(state_p, states) - { - uint32_t state = *(uint32_t*)state_p; - - switch (state) - { - case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN: - case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED: - case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED: - case ZXDG_TOPLEVEL_V6_STATE_RESIZING: - break; - default: - break; - } - } + //wl_array_for_each(state_p, states) + //{ + // uint32_t state = *(uint32_t*)state_p; + // + // switch (state) + // { + // case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN: + // case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED: + // case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED: + // case ZXDG_TOPLEVEL_V6_STATE_RESIZING: + // break; + // default: + // break; + // } + //} } static void xdg_toplevel_close(void* data, zxdg_toplevel_v6* xdg_toplevel) diff --git a/lib/libsquish/CMakeLists.txt b/lib/libsquish/CMakeLists.txt index 7258f7bd0..bb76f6715 100644 --- a/lib/libsquish/CMakeLists.txt +++ b/lib/libsquish/CMakeLists.txt @@ -43,6 +43,11 @@ ELSE (CMAKE_GENERATOR STREQUAL "Xcode") ENDIF (BUILD_SQUISH_WITH_ALTIVEC AND NOT WIN32) ENDIF (CMAKE_GENERATOR STREQUAL "Xcode") +# A fix for MinGW compilation +IF (BUILD_SQUISH_WITH_SSE2 AND MINGW) + ADD_DEFINITIONS(-msse2) +ENDIF () + SET(SQUISH_HDRS squish.h ) diff --git a/src/config/stk_config.cpp b/src/config/stk_config.cpp index bbef18708..2e9cebbb0 100644 --- a/src/config/stk_config.cpp +++ b/src/config/stk_config.cpp @@ -279,10 +279,14 @@ void STKConfig::getAllData(const XMLNode * root) if (const XMLNode *camera = root->getNode("camera")) { - camera->get("fov-1", &m_camera_fov[0]); - camera->get("fov-2", &m_camera_fov[1]); - camera->get("fov-3", &m_camera_fov[2]); - camera->get("fov-4", &m_camera_fov[3]); + for (int i = 0; i < 4; i++) + { + camera->get("fov-" + std::to_string(i + 1), &m_camera_fov[i]); + } + for (int i = 4; i < MAX_PLAYER_COUNT; i++) + { + camera->get("fov-" + std::to_string(4), &m_camera_fov[i]); + } camera->get("cutscene-fov", &m_cutscene_fov); } diff --git a/src/config/stk_config.hpp b/src/config/stk_config.hpp index 1713c1fdd..bffe4bef4 100644 --- a/src/config/stk_config.hpp +++ b/src/config/stk_config.hpp @@ -30,6 +30,7 @@ #include "utils/interpolation_array.hpp" #include "utils/no_copy.hpp" +#include "utils/constants.hpp" #include #include #include @@ -159,7 +160,7 @@ public: float m_replay_delta_angle; /** The field of view for 1, 2, 3, 4 player split screen. */ - float m_camera_fov[4]; + float m_camera_fov[MAX_PLAYER_COUNT]; float m_cutscene_fov; diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index ae414a515..ead7a1a73 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -561,7 +561,10 @@ namespace UserConfigParams PARAM_PREFIX BoolUserConfigParam m_force_legacy_device PARAM_DEFAULT(BoolUserConfigParam(false, "force_legacy_device", &m_video_group, "Force OpenGL 2 context, even if OpenGL 3 is available.")); - + PARAM_PREFIX BoolUserConfigParam split_screen_horizontally + PARAM_DEFAULT(BoolUserConfigParam(true, "split_screen_horizontally", + &m_video_group, "When playing a non-square amount of players (e.g. 2)," + " should it split horizontally (top/bottom)")); PARAM_PREFIX BoolUserConfigParam m_texture_compression PARAM_DEFAULT(BoolUserConfigParam(true, "enable_texture_compression", &m_video_group, "Enable Texture Compression")); @@ -614,7 +617,6 @@ namespace UserConfigParams PARAM_DEFAULT(BoolUserConfigParam(true, "limit_game_fps", &m_recording_group, "Limit game framerate not beyond the fps of" " recording video.")); - PARAM_PREFIX IntUserConfigParam m_video_format PARAM_DEFAULT(IntUserConfigParam(0, "video_format", &m_recording_group, "Specify the video for record, which is the enum" @@ -743,7 +745,7 @@ namespace UserConfigParams "stun.voxgratia.org", "stun.xten.com") ); - // ---- Gamemode setup + // ---- Gamemode setup PARAM_PREFIX IntToIntUserConfigParam m_num_karts_per_gamemode PARAM_DEFAULT(IntToIntUserConfigParam("num_karts_per_gamemode", "The Number of karts per gamemode.", @@ -845,7 +847,7 @@ namespace UserConfigParams PARAM_PREFIX BoolUserConfigParam m_log_errors_to_console PARAM_DEFAULT( BoolUserConfigParam( CONSOLE_DEFAULT, "log_errors", "Enable logging to console.") ); - + // ---- Camera PARAM_PREFIX GroupUserConfigParam m_camera PARAM_DEFAULT( GroupUserConfigParam("camera", diff --git a/src/graphics/abstract_renderer.cpp b/src/graphics/abstract_renderer.cpp index ca58391f4..5aac5d536 100644 --- a/src/graphics/abstract_renderer.cpp +++ b/src/graphics/abstract_renderer.cpp @@ -194,11 +194,3 @@ void AbstractRenderer::drawJoint(bool drawline, bool drawname, } //drawJoint #endif //DEBUG - -AbstractRenderer::AbstractRenderer() -{ - resetObjectCount(); - resetPolyCount(); -} - - diff --git a/src/graphics/abstract_renderer.hpp b/src/graphics/abstract_renderer.hpp index 46950288e..775b9730b 100644 --- a/src/graphics/abstract_renderer.hpp +++ b/src/graphics/abstract_renderer.hpp @@ -26,16 +26,6 @@ class RenderTarget; -enum STKRenderingPass -{ - SOLID_NORMAL_AND_DEPTH_PASS, - SOLID_LIT_PASS, - TRANSPARENT_PASS, - GLOW_PASS, - SHADOW_PASS, - PASS_COUNT, -}; - enum TypeRTT : unsigned int; struct GlowData { @@ -56,10 +46,6 @@ class AbstractRenderer protected: irr::core::vector2df m_current_screen_size; - /** Performance stats */ - unsigned m_object_count[PASS_COUNT]; - unsigned m_poly_count [PASS_COUNT]; - #ifdef DEBUG void drawDebugMeshes() const; @@ -71,7 +57,7 @@ protected: void renderSkybox(const irr::scene::ICameraSceneNode *camera) const; public: - AbstractRenderer(); + AbstractRenderer() {} virtual ~AbstractRenderer(){} virtual void onLoadWorld() = 0; @@ -114,14 +100,6 @@ public: */ virtual std::unique_ptr createRenderTarget(const irr::core::dimension2du &dimension, const std::string &name) = 0; - - void resetObjectCount() { memset(m_object_count, 0, sizeof(m_object_count));} - void resetPolyCount() { memset(m_poly_count, 0, sizeof(m_poly_count)); } - void incObjectCount(STKRenderingPass phase) { m_object_count[phase]++; } - - unsigned getObjectCount(STKRenderingPass pass) const { return m_object_count[pass]; } - unsigned getPolyCount(STKRenderingPass pass) const { return m_poly_count [pass]; } - }; #endif //HEADER_ABSTRACT_RENDERER_HPP diff --git a/src/graphics/camera.cpp b/src/graphics/camera.cpp index 3f26c6e9a..083b28e1d 100644 --- a/src/graphics/camera.cpp +++ b/src/graphics/camera.cpp @@ -53,10 +53,10 @@ Camera::CameraType Camera::m_default_type = Camera::CM_TYPE_NORMAL; * camera index (which determines which viewport to use in split screen) * is set. */ -Camera* Camera::createCamera(AbstractKart* kart) +Camera* Camera::createCamera(AbstractKart* kart, const int index) { - Camera *camera = createCamera((int)m_all_cameras.size(), - m_default_type, kart ); + + Camera *camera = createCamera(index, m_default_type, kart); m_all_cameras.push_back(camera); return camera; } // createCamera(kart) @@ -163,71 +163,15 @@ void Camera::setKart(AbstractKart *new_kart) */ void Camera::setupCamera() { - m_aspect = (float)(irr_driver->getActualScreenSize().Width) - / irr_driver->getActualScreenSize().Height; - switch(race_manager->getNumLocalPlayers()) - { - case 1: m_viewport = core::recti(0, 0, - irr_driver->getActualScreenSize().Width, - irr_driver->getActualScreenSize().Height); - m_scaling = core::vector2df(1.0f, 1.0f); - m_fov = DEGREE_TO_RAD*stk_config->m_camera_fov[0]; - break; - case 2: m_viewport = core::recti(0, - m_index==0 ? 0 - : irr_driver->getActualScreenSize().Height>>1, - irr_driver->getActualScreenSize().Width, - m_index==0 ? irr_driver->getActualScreenSize().Height>>1 - : irr_driver->getActualScreenSize().Height); - m_scaling = core::vector2df(1.0f, 0.5f); - m_aspect *= 2.0f; - m_fov = DEGREE_TO_RAD*stk_config->m_camera_fov[1]; - break; - case 3: - /* - if(m_index<2) - { - m_viewport = core::recti(m_index==0 ? 0 - : irr_driver->getActualScreenSize().Width>>1, - 0, - m_index==0 ? irr_driver->getActualScreenSize().Width>>1 - : irr_driver->getActualScreenSize().Width, - irr_driver->getActualScreenSize().Height>>1); - m_scaling = core::vector2df(0.5f, 0.5f); - m_fov = DEGREE_TO_RAD*50.0f; - } - else - { - m_viewport = core::recti(0, irr_driver->getActualScreenSize().Height>>1, - irr_driver->getActualScreenSize().Width, - irr_driver->getActualScreenSize().Height); - m_scaling = core::vector2df(1.0f, 0.5f); - m_fov = DEGREE_TO_RAD*65.0f; - m_aspect *= 2.0f; - } - break;*/ - case 4: - { // g++ 4.3 whines about the variables in switch/case if not {}-wrapped (???) - const int x1 = (m_index%2==0 ? 0 : irr_driver->getActualScreenSize().Width>>1); - const int y1 = (m_index<2 ? 0 : irr_driver->getActualScreenSize().Height>>1); - const int x2 = (m_index%2==0 ? irr_driver->getActualScreenSize().Width>>1 : irr_driver->getActualScreenSize().Width); - const int y2 = (m_index<2 ? irr_driver->getActualScreenSize().Height>>1 : irr_driver->getActualScreenSize().Height); - m_viewport = core::recti(x1, y1, x2, y2); - m_scaling = core::vector2df(0.5f, 0.5f); - m_fov = DEGREE_TO_RAD*stk_config->m_camera_fov[3]; - } - break; - default: - if(UserConfigParams::logMisc()) - Log::warn("Camera", "Incorrect number of players: '%d' - assuming 1.", - race_manager->getNumLocalPlayers()); - m_viewport = core::recti(0, 0, - irr_driver->getActualScreenSize().Width, - irr_driver->getActualScreenSize().Height); - m_scaling = core::vector2df(1.0f, 1.0f); - m_fov = DEGREE_TO_RAD*75.0f; - break; - } // switch + m_viewport = irr_driver->GetSplitscreenWindow(m_index); + m_aspect = (float)((float)(m_viewport.getWidth()) / (float)(m_viewport.getHeight())); + + m_scaling = core::vector2df( + irr_driver->getActualScreenSize().Width / m_viewport.getWidth() , + irr_driver->getActualScreenSize().Height / m_viewport.getHeight()); + + m_fov = DEGREE_TO_RAD * stk_config->m_camera_fov[race_manager->getNumLocalPlayers() - 1]; + m_camera->setFOV(m_fov); m_camera->setAspectRatio(m_aspect); m_camera->setFarValue(Track::getCurrentTrack()->getCameraFar()); diff --git a/src/graphics/camera.hpp b/src/graphics/camera.hpp index 27f117557..fcdffb7d2 100644 --- a/src/graphics/camera.hpp +++ b/src/graphics/camera.hpp @@ -136,7 +136,7 @@ public: // ======================================================================== // Static functions - static Camera* createCamera(AbstractKart* kart); + static Camera* createCamera(AbstractKart* kart, const int index); static void resetAllCameras(); static void changeCamera(unsigned int camera_index, CameraType type); diff --git a/src/graphics/camera_normal.cpp b/src/graphics/camera_normal.cpp index 2e4c12bc2..7f962a474 100644 --- a/src/graphics/camera_normal.cpp +++ b/src/graphics/camera_normal.cpp @@ -68,10 +68,10 @@ CameraNormal::CameraNormal(Camera::CameraType type, int camera_index, //----------------------------------------------------------------------------- /** Moves the camera smoothly from the current camera position (and target) * to the new position and target. - * \param wanted_position The position the camera wanted to reach. - * \param wanted_target The point the camera wants to point to. + * \param dt Delta time, + * \param if false, the camera instantly moves to the endpoint, or else it smoothly moves */ -void CameraNormal::smoothMoveCamera(float dt) +void CameraNormal::moveCamera(float dt, bool smooth) { if(!m_kart) return; @@ -112,20 +112,24 @@ void CameraNormal::smoothMoveCamera(float dt) //m_smooth_dt = 0.3f * dt + 0.7f * m_smooth_dt; - float delta = (dt*5.0f); - if (delta < 0.0f) - delta = 0.0f; - else if (delta > 1.0f) - delta = 1.0f; - + float delta = 1; + float delta2 = 1; + if (smooth) + { + delta = (dt*5.0f); + if (delta < 0.0f) + delta = 0.0f; + else if (delta > 1.0f) + delta = 1.0f; + + delta2 = dt * 8.0f; + if (delta2 < 0) + delta2 = 0; + else if (delta2 > 1) + delta2 = 1; + } m_camera_offset += (wanted_camera_offset - m_camera_offset) * delta; - float delta2 = dt * 8.0f; - if (delta2 < 0) - delta2 = 0; - else if (delta2 > 1) - delta2 = 1; - btTransform btt = m_kart->getTrans(); m_kart_position = btt.getOrigin(); btQuaternion q1, q2; @@ -133,6 +137,7 @@ void CameraNormal::smoothMoveCamera(float dt) q2 = btt.getRotation().normalized(); if (dot(q1, q2) < 0.0f) q2 = -q2; + m_kart_rotation = q1.slerp(q2, delta2); btt.setOrigin(m_kart_position); @@ -159,8 +164,11 @@ void CameraNormal::smoothMoveCamera(float dt) assert(!std::isnan(m_camera->getPosition().Y)); assert(!std::isnan(m_camera->getPosition().Z)); -} // smoothMoveCamera - +} // MoveCamera +void CameraNormal::snapToPosition() +{ + moveCamera(1, false); +} //----------------------------------------------------------------------------- /** Determine the camera settings for the current frame. * \param above_kart How far above the camera should aim at. @@ -257,7 +265,7 @@ void CameraNormal::update(float dt) + core::vector3df(0, above_kart, 0)); m_camera->setTarget(current_target); } - else // no kart animation + else // no kart animation { float above_kart, cam_angle, side_way, distance; bool smoothing; @@ -266,6 +274,7 @@ void CameraNormal::update(float dt) } } // update + // ---------------------------------------------------------------------------- /** Actually sets the camera based on the given parameter. * \param above_kart How far above the camera should aim at. @@ -296,7 +305,7 @@ void CameraNormal::positionCamera(float dt, float above_kart, float cam_angle, if (smoothing) { - smoothMoveCamera(dt); + moveCamera(dt, true); } else { diff --git a/src/graphics/camera_normal.hpp b/src/graphics/camera_normal.hpp index f80a01626..80853de5b 100644 --- a/src/graphics/camera_normal.hpp +++ b/src/graphics/camera_normal.hpp @@ -51,11 +51,12 @@ private: Vec3 m_camera_offset; - void smoothMoveCamera(float dt); + void moveCamera(float dt, bool smooth); void handleEndCamera(float dt); void getCameraSettings(float *above_kart, float *cam_angle, float *side_way, float *distance, bool *smoothing); + void positionCamera(float dt, float above_kart, float cam_angle, float side_way, float distance, float smoothing); @@ -70,6 +71,9 @@ private: AbstractKart* kart); virtual ~CameraNormal() {} public: + + void snapToPosition(); + // ------------------------------------------------------------------------ bool isDebug() { return false; } // ------------------------------------------------------------------------ bool isFPS() { return false; } diff --git a/src/graphics/central_settings.cpp b/src/graphics/central_settings.cpp index 9891f6482..e1bbaed8b 100644 --- a/src/graphics/central_settings.cpp +++ b/src/graphics/central_settings.cpp @@ -384,7 +384,7 @@ bool CentralVideoSettings::isTextureCompressionEnabled() const return supportsTextureCompression() && UserConfigParams::m_texture_compression; } -bool CentralVideoSettings::isDefferedEnabled() const +bool CentralVideoSettings::isDeferredEnabled() const { return UserConfigParams::m_dynamic_lights && !GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_ADVANCED_PIPELINE); } diff --git a/src/graphics/central_settings.hpp b/src/graphics/central_settings.hpp index 5639ffb3c..6b7c486c0 100644 --- a/src/graphics/central_settings.hpp +++ b/src/graphics/central_settings.hpp @@ -95,7 +95,7 @@ public: // "Macro" around feature support and user config bool isShadowEnabled() const; bool isTextureCompressionEnabled() const; - bool isDefferedEnabled() const; + bool isDeferredEnabled() const; }; extern CentralVideoSettings* CVS; diff --git a/src/graphics/cpu_particle_manager.cpp b/src/graphics/cpu_particle_manager.cpp index f856ffcd1..2316d5661 100644 --- a/src/graphics/cpu_particle_manager.cpp +++ b/src/graphics/cpu_particle_manager.cpp @@ -297,7 +297,8 @@ void CPUParticleManager::drawAll() { ParticleRenderer::getInstance()->setTextureUnits (cur_mat->getTexture()->getOpenGLTextureName(), - irr_driver->getDepthStencilTexture()); + CVS->isDeferredEnabled() ? + irr_driver->getDepthStencilTexture() : 0); ParticleRenderer::getInstance()->setUniforms(flips, billboard); } else diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index f267d41a3..9e1600aa3 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -116,8 +116,7 @@ const bool ALLOW_1280_X_720 = true; IrrDriver::IrrDriver() { m_resolution_changing = RES_CHANGE_NONE; - m_phase = SOLID_NORMAL_AND_DEPTH_PASS; - + struct irr::SIrrlichtCreationParameters p; p.DriverType = video::EDT_NULL; p.WindowSize = core::dimension2d(640,480); @@ -135,10 +134,9 @@ IrrDriver::IrrDriver() m_request_screenshot = false; m_renderer = NULL; m_wind = new Wind(); - - m_mipviz = m_wireframe = m_normals = m_ssaoviz = false; - m_lightviz = m_shadowviz = m_distortviz = m_rsm = m_rh = m_gi = false; - m_boundingboxesviz = false; + m_ssaoviz = false; + m_shadowviz = false; + m_boundingboxesviz = false; m_last_light_bucket_distance = 0; m_clear_color = video::SColor(255, 100, 101, 140); m_skinning_joint = 0; @@ -174,24 +172,6 @@ void IrrDriver::reset() #endif } // reset -// ---------------------------------------------------------------------------- -void IrrDriver::setPhase(STKRenderingPass p) -{ - m_phase = p; -} - -// ---------------------------------------------------------------------------- -STKRenderingPass IrrDriver::getPhase() const -{ - return m_phase; -} - -#// ---------------------------------------------------------------------------- -void IrrDriver::increaseObjectCount() -{ - m_renderer->incObjectCount(m_phase); -} // increaseObjectCount - // ---------------------------------------------------------------------------- core::array &IrrDriver::getMainSetup() { @@ -250,7 +230,31 @@ void IrrDriver::updateConfigIfRelevant() } #endif // !SERVER_ONLY } // updateConfigIfRelevant +core::recti IrrDriver::GetSplitscreenWindow(int WindowNum) +{ + const int playernum = race_manager->getNumLocalPlayers(); + const float playernum_sqrt = sqrt(playernum); + + int rows = UserConfigParams::split_screen_horizontally ? ceil(playernum_sqrt) : round(playernum_sqrt); + int cols = UserConfigParams::split_screen_horizontally ? round(playernum_sqrt) : ceil(playernum_sqrt); + + if (rows == 0){rows = 1;} + if (cols == 0) {cols = 1;} + //This could add a bit of overhang + const int width_of_space = ceil((float)irr_driver->getActualScreenSize().Width / (float)cols); + const int height_of_space = ceil((float)irr_driver->getActualScreenSize().Height / (float)rows); + const int x_grid_Position = WindowNum % cols; + const int y_grid_Position = floor((WindowNum) / cols); + int wid = (int)irr_driver->getActualScreenSize().Width; + +//To prevent the viewport going over the right side, we use std::min to ensure the right corners are never larger than the total width + return core::recti( + x_grid_Position * width_of_space, + y_grid_Position * height_of_space, + (x_grid_Position * width_of_space) + width_of_space, + (y_grid_Position * height_of_space) + height_of_space); +} // ---------------------------------------------------------------------------- /** Gets a list of supported video modes from the irrlicht device. This data * is stored in m_modes. @@ -1673,7 +1677,18 @@ void IrrDriver::displayFPS() m_skinning_joint); } else - fps_string = _("FPS: %d/%d/%d - %d KTris", min, fps, max, (int)roundf(kilotris)); + { + if (CVS->isGLSL()) + { + fps_string = _("FPS: %d/%d/%d - %d KTris", min, fps, max, + SP::sp_solid_poly_count / 1000); + } + else + { + fps_string = _("FPS: %d/%d/%d - %d KTris", min, fps, max, + (int)roundf(kilotris)); + } + } static video::SColor fpsColor = video::SColor(255, 0, 0, 0); @@ -1975,3 +1990,14 @@ GLuint IrrDriver::getDepthStencilTexture() return m_renderer->getDepthStencilTexture(); } // getDepthStencilTexture +// ---------------------------------------------------------------------------- +void IrrDriver::resetDebugModes() +{ + m_ssaoviz = false; + m_shadowviz = false; + m_lightviz = false; + m_boundingboxesviz = false; +#ifndef SERVER_ONLY + SP::sp_debug_view = false; +#endif +} diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index 230fe56d7..706738e6a 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -156,16 +156,9 @@ private: bool m_request_screenshot; - bool m_wireframe; - bool m_mipviz; - bool m_normals; bool m_ssaoviz; - bool m_rsm; - bool m_rh; - bool m_gi; bool m_shadowviz; bool m_lightviz; - bool m_distortviz; bool m_boundingboxesviz; bool m_recording; @@ -175,7 +168,7 @@ private: unsigned m_last_light_bucket_distance; unsigned m_skinning_joint; - u32 m_renderpass; + SP::SPDynamicDrawCall* m_sun_interposer; core::vector3df m_sun_direction; video::SColorf m_suncolor; @@ -187,8 +180,6 @@ private: std::vector m_background; - STKRenderingPass m_phase; - float m_ssao_radius; float m_ssao_k; float m_ssao_sigma; @@ -209,11 +200,10 @@ public: void getOpenGLData(std::string *vendor, std::string *renderer, std::string *version); - void setPhase(STKRenderingPass); - STKRenderingPass getPhase() const; void increaseObjectCount(); core::array &getMainSetup(); void updateConfigIfRelevant(); + core::recti GetSplitscreenWindow(int WindowNum); void setAllMaterialFlags(scene::IMesh *mesh) const; scene::IAnimatedMesh *getAnimatedMesh(const std::string &name); scene::IMesh *getMesh(const std::string &name); @@ -356,61 +346,16 @@ public: GLuint getRenderTargetTexture(TypeRTT which); GLuint getDepthStencilTexture(); // ------------------------------------------------------------------------ - void resetDebugModes() - { - m_wireframe = false; - m_mipviz = false; - m_normals = false; - m_ssaoviz = false; - m_rsm = false; - m_rh = false; - m_gi = false; - m_shadowviz = false; - m_lightviz = false; - m_distortviz = false; - m_boundingboxesviz = false; - } - // ------------------------------------------------------------------------ - void toggleWireframe() { m_wireframe = !m_wireframe; } - // ------------------------------------------------------------------------ - bool getWireframe() { return m_wireframe; } - // ------------------------------------------------------------------------ - void toggleMipVisualization() { m_mipviz = !m_mipviz; } - // ------------------------------------------------------------------------ - bool getMipViz() { return m_mipviz; } - // ------------------------------------------------------------------------ - void toggleNormals() { m_normals = !m_normals; } - // ------------------------------------------------------------------------ - bool getNormals() { return m_normals; } + void resetDebugModes(); // ------------------------------------------------------------------------ void toggleSSAOViz() { m_ssaoviz = !m_ssaoviz; } // ------------------------------------------------------------------------ - void toggleLightViz() { m_lightviz = !m_lightviz; } - // ------------------------------------------------------------------------ - bool getLightViz() { return m_lightviz; } - // ------------------------------------------------------------------------ bool getSSAOViz() { return m_ssaoviz; } // ------------------------------------------------------------------------ - void toggleRSM() { m_rsm = !m_rsm; } - // ------------------------------------------------------------------------ - bool getRSM() { return m_rsm; } - // ------------------------------------------------------------------------ - void toggleRH() { m_rh = !m_rh; } - // ------------------------------------------------------------------------ - bool getRH() { return m_rh; } - // ------------------------------------------------------------------------ - void toggleGI() { m_gi = !m_gi; } - // ------------------------------------------------------------------------ - bool getGI() { return m_gi; } - // ------------------------------------------------------------------------ void toggleShadowViz() { m_shadowviz = !m_shadowviz; } // ------------------------------------------------------------------------ bool getShadowViz() { return m_shadowviz; } // ------------------------------------------------------------------------ - void toggleDistortViz() { m_distortviz = !m_distortviz; } - // ------------------------------------------------------------------------ - bool getDistortViz() { return m_distortviz; } - // ------------------------------------------------------------------------ void toggleBoundingBoxesViz() { m_boundingboxesviz = !m_boundingboxesviz; } // ------------------------------------------------------------------------ bool getBoundingBoxesViz() { return m_boundingboxesviz; } @@ -419,8 +364,6 @@ public: // ------------------------------------------------------------------------ void setRecording(bool val); // ------------------------------------------------------------------------ - u32 getRenderPass() { return m_renderpass; } - // ------------------------------------------------------------------------ std::vector getLights() { return m_lights; } // ------------------------------------------------------------------------ void addGlowingNode(scene::ISceneNode *n, float r = 1.0f, float g = 1.0f, diff --git a/src/graphics/large_mesh_buffer.hpp b/src/graphics/large_mesh_buffer.hpp deleted file mode 100644 index 0350b6c17..000000000 --- a/src/graphics/large_mesh_buffer.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2002-2015 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __LARGE_MESH_BUFFER_H_INCLUDED__ -#define __LARGE_MESH_BUFFER_H_INCLUDED__ - -#include "irrArray.h" -#include "IMeshBuffer.h" -#include "CMeshBuffer.h" - -namespace irr -{ -namespace scene -{ - //! A SMeshBuffer with 32-bit indices - class LargeMeshBuffer : public SMeshBuffer - { - public: - //! Get type of index data which is stored in this meshbuffer. - /** \return Index type of this buffer. */ - virtual video::E_INDEX_TYPE getIndexType() const - { - return video::EIT_32BIT; - } - - //! Get pointer to indices - /** \return Pointer to indices. */ - virtual const u16* getIndices() const - { - return (u16 *) Indices.const_pointer(); - } - - - //! Get pointer to indices - /** \return Pointer to indices. */ - virtual u16* getIndices() - { - return (u16 *) Indices.pointer(); - } - - - //! Get number of indices - /** \return Number of indices. */ - virtual u32 getIndexCount() const - { - return Indices.size(); - } - - //! Indices into the vertices of this buffer. - core::array Indices; - }; -} // end namespace scene -} // end namespace irr - -#endif - - diff --git a/src/graphics/lighting_passes.cpp b/src/graphics/lighting_passes.cpp index b58f2f3b1..051a59b17 100644 --- a/src/graphics/lighting_passes.cpp +++ b/src/graphics/lighting_passes.cpp @@ -106,6 +106,11 @@ public: glVertexAttribDivisorARB(attrib_Color, 1); glVertexAttribDivisorARB(attrib_Radius, 1); } // PointLightShader + ~PointLightShader() + { + glDeleteBuffers(1, &vbo); + glDeleteVertexArrays(1, &vao); + } // PointLightShader }; // PointLightShader @@ -116,7 +121,6 @@ class PointLightScatterShader : public TextureShader { public: - GLuint vbo; GLuint vao; PointLightScatterShader() { @@ -157,6 +161,10 @@ public: glVertexAttribDivisorARB(attrib_Color, 1); glVertexAttribDivisorARB(attrib_Radius, 1); } // PointLightScatterShader + ~PointLightScatterShader() + { + glDeleteVertexArrays(1, &vao); + } // ~PointLightScatterShader }; // ============================================================================ @@ -465,7 +473,6 @@ void LightingPasses::renderLights( bool has_shadow, void LightingPasses::renderLightsScatter(GLuint depth_stencil_texture, const FrameBuffer& half1_framebuffer, const FrameBuffer& half2_framebuffer, - const FrameBuffer& colors_framebuffer, const PostProcessing* post_processing) { half1_framebuffer.bind(); @@ -505,14 +512,6 @@ void LightingPasses::renderLightsScatter(GLuint depth_stencil_texture, glDisable(GL_BLEND); post_processing->renderGaussian6Blur(half1_framebuffer, half2_framebuffer, 5., 5.); - glEnable(GL_BLEND); - - glDisable(GL_DEPTH_TEST); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - colors_framebuffer.bind(); - post_processing->renderPassThrough(half1_framebuffer.getRTT()[0], - colors_framebuffer.getWidth(), - colors_framebuffer.getHeight()); } // renderLightsScatter #endif diff --git a/src/graphics/lighting_passes.hpp b/src/graphics/lighting_passes.hpp index 4fd6bab43..522c2782b 100644 --- a/src/graphics/lighting_passes.hpp +++ b/src/graphics/lighting_passes.hpp @@ -55,11 +55,7 @@ public: void renderLightsScatter(GLuint depth_stencil_texture, const FrameBuffer& half1_framebuffer, const FrameBuffer& half2_framebuffer, - const FrameBuffer& colors_framebuffer, const PostProcessing* post_processing); - - - }; #endif //HEADER_LIGHTING_PASSES_HPP diff --git a/src/graphics/material.cpp b/src/graphics/material.cpp index 48aadf0ad..7cce73b28 100644 --- a/src/graphics/material.cpp +++ b/src/graphics/material.cpp @@ -785,6 +785,7 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m m->DiffuseColor = video::SColor(255, 255, 255, 255); m->EmissiveColor = video::SColor(255, 255, 255, 255); m->SpecularColor = video::SColor(255, 255, 255, 255); + m->MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; } else if (m_shader_name == "alphatest") { diff --git a/src/graphics/post_processing.cpp b/src/graphics/post_processing.cpp index eafe401ed..d4efbb454 100644 --- a/src/graphics/post_processing.cpp +++ b/src/graphics/post_processing.cpp @@ -431,6 +431,7 @@ public: void render(const FrameBuffer &fbo, GLuint rtt, float vignette_weight) { fbo.bind(); + glClear(GL_COLOR_BUFFER_BIT); setTextureUnits(rtt); drawFullScreenEffect(vignette_weight); } // render @@ -741,7 +742,7 @@ public: // ============================================================================ -PostProcessing::PostProcessing(IVideoDriver* video_driver) +PostProcessing::PostProcessing() { // Load the MLAA area map io::IReadFile *areamap = irr_driver->getDevice()->getFileSystem()-> @@ -759,59 +760,16 @@ PostProcessing::PostProcessing(IVideoDriver* video_driver) } // PostProcessing -// ---------------------------------------------------------------------------- -PostProcessing::~PostProcessing() -{ - // TODO: do we have to delete/drop anything? -} // ~PostProcessing - // ---------------------------------------------------------------------------- /** Initialises post processing at the (re-)start of a race. This sets up * the vertices, normals and texture coordinates for each */ void PostProcessing::reset() { - const u32 n = Camera::getNumCameras(); - m_boost_time.resize(n); - m_vertices.resize(n); - - for(unsigned int i=0; igetViewport(); - // Map viewport to [-1,1] x [-1,1]. First define the coordinates - // left, right, top, bottom: - float right = vp.LowerRightCorner.X < (int)irr_driver->getActualScreenSize().Width - ? 0.0f : 1.0f; - float left = vp.UpperLeftCorner.X > 0.0f ? 0.0f : -1.0f; - float top = vp.UpperLeftCorner.Y > 0.0f ? 0.0f : 1.0f; - float bottom = vp.LowerRightCorner.Y < (int)irr_driver->getActualScreenSize().Height - ? 0.0f : -1.0f; - - // Use left etc to define 4 vertices on which the rendered screen - // will be displayed: - m_vertices[i].v0.Pos = core::vector3df(left, bottom, 0); - m_vertices[i].v1.Pos = core::vector3df(left, top, 0); - m_vertices[i].v2.Pos = core::vector3df(right, top, 0); - m_vertices[i].v3.Pos = core::vector3df(right, bottom, 0); - // Define the texture coordinates of each vertex, which must - // be in [0,1]x[0,1] - m_vertices[i].v0.TCoords = core::vector2df(left ==-1.0f ? 0.0f : 0.5f, - bottom==-1.0f ? 0.0f : 0.5f); - m_vertices[i].v1.TCoords = core::vector2df(left ==-1.0f ? 0.0f : 0.5f, - top == 1.0f ? 1.0f : 0.5f); - m_vertices[i].v2.TCoords = core::vector2df(right == 0.0f ? 0.5f : 1.0f, - top == 1.0f ? 1.0f : 0.5f); - m_vertices[i].v3.TCoords = core::vector2df(right == 0.0f ? 0.5f : 1.0f, - bottom==-1.0f ? 0.0f : 0.5f); - // Set normal and color: - core::vector3df normal(0,0,1); - m_vertices[i].v0.Normal = m_vertices[i].v1.Normal = - m_vertices[i].v2.Normal = m_vertices[i].v3.Normal = normal; - SColor white(0xFF, 0xFF, 0xFF, 0xFF); - m_vertices[i].v0.Color = m_vertices[i].v1.Color = - m_vertices[i].v2.Color = m_vertices[i].v3.Color = white; } // for i render(in_fbo, inv_width, - inv_height); - } - { - in_fbo.bind(); - Gaussian3HBlurShader::getInstance()->render(auxiliary, inv_width, - inv_height); - } + auxiliary.bind(); + glClear(GL_COLOR_BUFFER_BIT); + Gaussian3VBlurShader::getInstance()->render(in_fbo, inv_width, + inv_height); + in_fbo.bind(); + glClear(GL_COLOR_BUFFER_BIT); + Gaussian3HBlurShader::getInstance()->render(auxiliary, inv_width, + inv_height); } // renderGaussian3Blur // ---------------------------------------------------------------------------- @@ -904,11 +860,13 @@ void PostProcessing::renderGaussian6Blur(const FrameBuffer &in_fbo, if (!CVS->supportsComputeShadersFiltering()) { auxiliary.bind(); + glClear(GL_COLOR_BUFFER_BIT); Gaussian6VBlurShader::getInstance() ->render(in_fbo.getRTT()[0], in_fbo.getWidth(), in_fbo.getHeight(), sigma_v); in_fbo.bind(); + glClear(GL_COLOR_BUFFER_BIT); Gaussian6HBlurShader::getInstance()->setTextureUnits(auxiliary.getRTT()[0]); Gaussian6HBlurShader::getInstance()->render(auxiliary, in_fbo.getWidth(), in_fbo.getHeight(), sigma_h); @@ -958,9 +916,11 @@ void PostProcessing::renderHorizontalBlur(const FrameBuffer &in_fbo, in_fbo.getHeight() == auxiliary.getHeight()); auxiliary.bind(); + glClear(GL_COLOR_BUFFER_BIT); Gaussian6HBlurShader::getInstance()->render(in_fbo, in_fbo.getWidth(), in_fbo.getHeight(), 2.0f ); in_fbo.bind(); + glClear(GL_COLOR_BUFFER_BIT); Gaussian6HBlurShader::getInstance()->render(auxiliary, in_fbo.getWidth(), in_fbo.getHeight(), 2.0f); } // renderHorizontalBlur @@ -1050,23 +1010,13 @@ void PostProcessing::renderTextureLayer(unsigned tex, unsigned layer) const } // renderTextureLayer // ---------------------------------------------------------------------------- -void PostProcessing::renderGlow(const FrameBuffer& glow_framebuffer, - const FrameBuffer& half_framebuffer, - const FrameBuffer& quarter_framebuffer, - const FrameBuffer& color_framebuffer ) const +void PostProcessing::renderGlow(const FrameBuffer& quarter_framebuffer) const { - // To half - FrameBuffer::blit(glow_framebuffer, half_framebuffer, GL_COLOR_BUFFER_BIT, GL_LINEAR); - - // To quarter - FrameBuffer::blit(half_framebuffer, quarter_framebuffer, GL_COLOR_BUFFER_BIT, GL_LINEAR); - glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glStencilFunc(GL_EQUAL, 0, ~0); glEnable(GL_STENCIL_TEST); - color_framebuffer.bind(); GlowShader::getInstance()->render(quarter_framebuffer.getRTT()[0]); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); @@ -1088,7 +1038,7 @@ void PostProcessing::renderSSAO(const FrameBuffer& linear_depth_framebuffer, } // renderSSAO // ---------------------------------------------------------------------------- -void PostProcessing::renderMotionBlur(unsigned , const FrameBuffer &in_fbo, +void PostProcessing::renderMotionBlur(const FrameBuffer &in_fbo, FrameBuffer &out_fbo, GLuint depth_stencil_texture) { @@ -1110,7 +1060,7 @@ void PostProcessing::renderDoF(const FrameBuffer &framebuffer, GLuint color_text // ---------------------------------------------------------------------------- void PostProcessing::renderGodRays(scene::ICameraSceneNode * const camnode, const FrameBuffer &in_fbo, - const FrameBuffer &out_fbo, + const FrameBuffer &tmp_fbo, const FrameBuffer &quarter1_fbo, const FrameBuffer &quarter2_fbo) { @@ -1118,9 +1068,8 @@ void PostProcessing::renderGodRays(scene::ICameraSceneNode * const camnode, glEnable(GL_DEPTH_TEST); // Grab the sky - out_fbo.bind(); + tmp_fbo.bind(); glClear(GL_COLOR_BUFFER_BIT); -// irr_driver->renderSkybox(camnode); // Set the sun's color const SColor col = track->getGodRaysColor(); @@ -1134,16 +1083,16 @@ void PostProcessing::renderGodRays(scene::ICameraSceneNode * const camnode, SP::SPUniformAssigner* glow_color_assigner = glow_shader ->getUniformAssigner("col"); assert(glow_color_assigner != NULL); - glow_color_assigner->setValue(video::SColorf(track->getGodRaysColor())); + video::SColorf cf(track->getGodRaysColor()); + glow_color_assigner->setValue(core::vector3df(cf.r, cf.g, cf.b)); sun->draw(); glow_shader->unuse(); glDisable(GL_DEPTH_TEST); // Fade to quarter quarter1_fbo.bind(); - glViewport(0, 0, irr_driver->getActualScreenSize().Width / 4, - irr_driver->getActualScreenSize().Height / 4); - GodFadeShader::getInstance()->render(out_fbo.getRTT()[0], col); + glClear(GL_COLOR_BUFFER_BIT); + GodFadeShader::getInstance()->render(tmp_fbo.getRTT()[0], col); // Blur renderGaussian3Blur(quarter1_fbo, quarter2_fbo); @@ -1155,17 +1104,12 @@ void PostProcessing::renderGodRays(scene::ICameraSceneNode * const camnode, trans *= camnode->getViewMatrix(); trans.transformVect(ndc, pos); - - const float texh = - m_vertices[0].v1.TCoords.Y - m_vertices[0].v0.TCoords.Y; - const float texw = - m_vertices[0].v3.TCoords.X - m_vertices[0].v0.TCoords.X; - - const float sunx = ((ndc[0] / ndc[3]) * 0.5f + 0.5f) * texw; - const float suny = ((ndc[1] / ndc[3]) * 0.5f + 0.5f) * texh; + const float sunx = ((ndc[0] / ndc[3]) * 0.5f + 0.5f); + const float suny = ((ndc[1] / ndc[3]) * 0.5f + 0.5f); // Rays please quarter2_fbo.bind(); + glClear(GL_COLOR_BUFFER_BIT); GodRayShader::getInstance() ->render(quarter1_fbo.getRTT()[0], core::vector2df(sunx, suny)); @@ -1181,7 +1125,7 @@ void PostProcessing::renderGodRays(scene::ICameraSceneNode * const camnode, in_fbo.bind(); renderPassThrough(quarter2_fbo.getRTT()[0], in_fbo.getWidth(), in_fbo.getHeight()); glDisable(GL_BLEND); - + } @@ -1195,18 +1139,12 @@ void PostProcessing::applyMLAA(const FrameBuffer& mlaa_tmp_framebuffer, 1.0f / UserConfigParams::m_height); mlaa_tmp_framebuffer.bind(); - glEnable(GL_STENCIL_TEST); glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - glStencilFunc(GL_ALWAYS, 1, ~0); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glClear(GL_COLOR_BUFFER_BIT); // Pass 1: color edge detection MLAAColorEdgeDetectionSHader::getInstance()->render(PIXEL_SIZE, mlaa_colors_framebuffer.getRTT()[0]); - glStencilFunc(GL_EQUAL, 1, ~0); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - // Pass 2: blend weights mlaa_blend_framebuffer.bind(); glClear(GL_COLOR_BUFFER_BIT); @@ -1222,8 +1160,6 @@ void PostProcessing::applyMLAA(const FrameBuffer& mlaa_tmp_framebuffer, MLAAGatherSHader::getInstance() ->render(PIXEL_SIZE, mlaa_blend_framebuffer.getRTT()[0], mlaa_tmp_framebuffer.getRTT()[0]); - // Done. - glDisable(GL_STENCIL_TEST); } // applyMLAA // ---------------------------------------------------------------------------- @@ -1274,7 +1210,8 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode, { PROFILER_PUSH_CPU_MARKER("- Godrays", 0xFF, 0x00, 0x00); ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_GODRAYS)); - renderGodRays(camnode, *in_fbo, *out_fbo, rtts->getFBO(FBO_QUARTER1), rtts->getFBO(FBO_QUARTER2)); + renderGodRays(camnode, *in_fbo, rtts->getFBO(FBO_RGBA_1), + rtts->getFBO(FBO_QUARTER1), rtts->getFBO(FBO_QUARTER2)); PROFILER_POP_CPU_MARKER(); } @@ -1352,14 +1289,15 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode, PROFILER_POP_CPU_MARKER(); } - //computeLogLuminance(in_rtt); { PROFILER_PUSH_CPU_MARKER("- Tonemap", 0xFF, 0x00, 0x00); ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_TONEMAP)); // only enable vignette during race + + out_fbo = &rtts->getFBO(FBO_RGBA_1); ToneMapShader::getInstance()->render(*out_fbo, in_fbo->getRTT()[0], isRace ? 1.0f : 0.0f); - std::swap(in_fbo, out_fbo); + in_fbo = &rtts->getFBO(FBO_RGBA_2); PROFILER_POP_CPU_MARKER(); } @@ -1370,8 +1308,9 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode, if (isRace && UserConfigParams::m_motionblur && World::getWorld() && m_boost_time.at(Camera::getActiveCamera()->getIndex()) > 0.0f) // motion blur { - renderMotionBlur(0, *in_fbo, *out_fbo, irr_driver->getDepthStencilTexture()); - std::swap(in_fbo, out_fbo); + in_fbo = &rtts->getFBO(FBO_RGBA_1); + out_fbo = &rtts->getFBO(FBO_RGBA_2); + renderMotionBlur(*in_fbo, *out_fbo, irr_driver->getDepthStencilTexture()); } PROFILER_POP_CPU_MARKER(); } @@ -1381,25 +1320,19 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode, PROFILER_PUSH_CPU_MARKER("- Lightning", 0xFF, 0x00, 0x00); ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_LIGHTNING)); Weather* weather = Weather::getInstance(); - if ( weather && weather->shouldLightning() ) + if (weather && weather->shouldLightning()) { renderLightning(weather->getIntensity()); } PROFILER_POP_CPU_MARKER(); } - out_fbo = &rtts->getFBO(FBO_MLAA_COLORS); - out_fbo->bind(); - renderPassThrough(in_fbo->getRTT()[0], - out_fbo->getWidth(), - out_fbo->getHeight()); - if (UserConfigParams::m_mlaa) // MLAA. Must be the last pp filter. { PROFILER_PUSH_CPU_MARKER("- MLAA", 0xFF, 0x00, 0x00); ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_MLAA)); - applyMLAA(rtts->getFBO(FBO_MLAA_TMP), - rtts->getFBO(FBO_MLAA_BLEND), + applyMLAA(*in_fbo, + rtts->getFBO(FBO_RGBA_3), *out_fbo); PROFILER_POP_CPU_MARKER(); } diff --git a/src/graphics/post_processing.hpp b/src/graphics/post_processing.hpp index d9fccaeb3..d859c60e3 100644 --- a/src/graphics/post_processing.hpp +++ b/src/graphics/post_processing.hpp @@ -20,7 +20,6 @@ #include "graphics/gl_headers.hpp" -#include #include #include #include @@ -40,7 +39,7 @@ using namespace irr; /** \brief Handles post processing, eg motion blur * \ingroup graphics */ -class PostProcessing: public IReferenceCounted +class PostProcessing { private: /** Boost time, how long the boost should be displayed. This also @@ -48,17 +47,11 @@ private: * have a stronger effect. */ std::vector m_boost_time; - struct Quad { video::S3DVertex v0, v1, v2, v3; }; - - /** The vertices for the rectangle used for each camera. This includes - * the vertex position, normal, and texture coordinate. */ - std::vector m_vertices; - STKTexture* m_areamap; public: - PostProcessing(video::IVideoDriver* video_driver); - virtual ~PostProcessing(); + PostProcessing(); + virtual ~PostProcessing() {} void reset(); /** Those should be called around the part where we render the scene to be @@ -88,7 +81,7 @@ public: void renderDoF(const FrameBuffer &framebuffer, GLuint color_texture, GLuint depth_stencil_texture); void renderGodRays(scene::ICameraSceneNode * const camnode, const FrameBuffer &in_fbo, - const FrameBuffer &out_fbo, + const FrameBuffer &tmp_fbo, const FrameBuffer &quarter1_fbo, const FrameBuffer &quarter2_fbo); @@ -96,13 +89,10 @@ public: const FrameBuffer& mlaa_blend_framebuffer, const FrameBuffer& mlaa_colors_framebuffer); - void renderMotionBlur(unsigned cam, const FrameBuffer &in_fbo, + void renderMotionBlur(const FrameBuffer &in_fbo, FrameBuffer &out_fbo, GLuint depth_stencil_texture); - void renderGlow(const FrameBuffer& glow_framebuffer, - const FrameBuffer& half_framebuffer, - const FrameBuffer& quarter_framebuffer, - const FrameBuffer& color_framebuffer) const; + void renderGlow(const FrameBuffer& quarter_framebuffer) const; void renderLightning(core::vector3df intensity); /** Use motion blur for a short time */ diff --git a/src/graphics/referee.cpp b/src/graphics/referee.cpp index 9a0f7002b..b9de4a69c 100644 --- a/src/graphics/referee.cpp +++ b/src/graphics/referee.cpp @@ -162,7 +162,7 @@ Referee::Referee() m_scene_node->setFrameLoop(m_st_first_start_frame, m_st_last_start_frame); #ifndef SERVER_ONLY - if (CVS->isGLSL() && CVS->isDefferedEnabled()) + if (CVS->isGLSL() && CVS->isDeferredEnabled()) { m_light = irr_driver->addLight(core::vector3df(0.0f, 0.0f, 0.6f), 0.7f, 2.0f, 0.7f /* r */, 0.0 /* g */, 0.0f /* b */, false /* sun */, m_scene_node); diff --git a/src/graphics/rtts.cpp b/src/graphics/rtts.cpp index 1eb0e929d..78890cf0c 100644 --- a/src/graphics/rtts.cpp +++ b/src/graphics/rtts.cpp @@ -53,19 +53,19 @@ static GLuint generateRTT(const core::dimension2du &res, GLint internalFormat, G return result; } -RTT::RTT(unsigned int width, unsigned int height, float rtt_scale) +RTT::RTT(unsigned int width, unsigned int height, float rtt_scale, + bool use_default_fbo_only) { m_width = (unsigned int)(width * rtt_scale); - m_height = (unsigned int)(height * rtt_scale); - m_shadow_FBO = NULL; - using namespace video; + m_height = (unsigned int)(height * rtt_scale); + m_shadow_fbo = NULL; + using namespace core; dimension2du res(m_width, m_height); const dimension2du half = res/2; const dimension2du quarter = res/4; - const dimension2du eighth = res/8; const u16 shadowside = u16(1024 * rtt_scale); const dimension2du shadowsize0(shadowside, shadowside); @@ -75,11 +75,14 @@ RTT::RTT(unsigned int width, unsigned int height, float rtt_scale) unsigned linear_depth_mip_levels = int(ceilf(log2f( float(max_(res.Width, res.Height)) ))); - DepthStencilTexture = generateRTT(res, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8); + if (!use_default_fbo_only) + { + m_depth_stencil_tex = generateRTT(res, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8); + } // All RTTs are currently RGBA16F mostly with stencil. The four tmp RTTs are the same size // as the screen, for use in post-processing. - + GLint rgba_internal_format = GL_RGBA16F; GLint rgba_format = GL_BGRA; GLint red_internal_format = GL_R16F; @@ -88,8 +91,7 @@ RTT::RTT(unsigned int width, unsigned int height, float rtt_scale) GLint rgb_format = GL_BGR; GLint diffuse_specular_internal_format = GL_R11F_G11F_B10F; GLint type = GL_FLOAT; - GLint rgb_internal_format = GL_RGBA8; - + #if defined(USE_GLES2) if (!CVS->isEXTColorBufferFloatUsable()) { @@ -103,190 +105,224 @@ RTT::RTT(unsigned int width, unsigned int height, float rtt_scale) type = GL_UNSIGNED_BYTE; } #endif - - RenderTargetTextures[RTT_TMP1] = generateRTT(res, rgba_internal_format, rgba_format, type); - RenderTargetTextures[RTT_TMP2] = generateRTT(res, rgba_internal_format, rgba_format, type); - RenderTargetTextures[RTT_TMP3] = generateRTT(res, rgba_internal_format, rgba_format, type); - RenderTargetTextures[RTT_TMP4] = generateRTT(res, red_internal_format, red_format, type); - RenderTargetTextures[RTT_LINEAR_DEPTH] = generateRTT(res, red32_internal_format, red_format, type, linear_depth_mip_levels); - RenderTargetTextures[RTT_NORMAL_AND_DEPTH] = generateRTT(res, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV); - RenderTargetTextures[RTT_COLOR] = generateRTT(res, rgba_internal_format, rgba_format, type); - RenderTargetTextures[RTT_MLAA_COLORS] = generateRTT(res, rgb_internal_format, rgb_format, GL_UNSIGNED_BYTE); - RenderTargetTextures[RTT_MLAA_TMP] = generateRTT(res, rgb_internal_format, rgb_format, GL_UNSIGNED_BYTE); - RenderTargetTextures[RTT_MLAA_BLEND] = generateRTT(res, rgb_internal_format, rgb_format, GL_UNSIGNED_BYTE); - RenderTargetTextures[RTT_SSAO] = generateRTT(res, red_internal_format, red_format, type); - RenderTargetTextures[RTT_DISPLACE] = generateRTT(res, rgba_internal_format, rgba_format, type); - RenderTargetTextures[RTT_DIFFUSE] = generateRTT(res, diffuse_specular_internal_format, rgb_format, type); - RenderTargetTextures[RTT_SPECULAR] = generateRTT(res, diffuse_specular_internal_format, rgb_format, type); - - RenderTargetTextures[RTT_HALF1] = generateRTT(half, rgba_internal_format, rgba_format, type); - RenderTargetTextures[RTT_QUARTER1] = generateRTT(quarter, rgba_internal_format, rgba_format, type); - RenderTargetTextures[RTT_EIGHTH1] = generateRTT(eighth, rgba_internal_format, rgba_format, type); - RenderTargetTextures[RTT_HALF1_R] = generateRTT(half, red_internal_format, red_format, type); - - RenderTargetTextures[RTT_HALF2] = generateRTT(half, rgba_internal_format, rgba_format, type); - RenderTargetTextures[RTT_QUARTER2] = generateRTT(quarter, rgba_internal_format, rgba_format, type); - RenderTargetTextures[RTT_EIGHTH2] = generateRTT(eighth, rgba_internal_format, rgba_format, type); - RenderTargetTextures[RTT_HALF2_R] = generateRTT(half, red_internal_format, red_format, type); - - RenderTargetTextures[RTT_BLOOM_1024] = generateRTT(shadowsize0, rgba_internal_format, rgb_format, type); - - RenderTargetTextures[RTT_BLOOM_512] = generateRTT(shadowsize1, rgba_internal_format, rgb_format, type); - RenderTargetTextures[RTT_TMP_512] = generateRTT(shadowsize1, rgba_internal_format, rgb_format, type); - RenderTargetTextures[RTT_LENS_512] = generateRTT(shadowsize1, rgba_internal_format, rgb_format, type); - - RenderTargetTextures[RTT_BLOOM_256] = generateRTT(shadowsize2, rgba_internal_format, rgb_format, type); - RenderTargetTextures[RTT_TMP_256] = generateRTT(shadowsize2, rgba_internal_format, rgb_format, type); - RenderTargetTextures[RTT_LENS_256] = generateRTT(shadowsize2, rgba_internal_format, rgb_format, type); - - RenderTargetTextures[RTT_BLOOM_128] = generateRTT(shadowsize3, rgba_internal_format, rgb_format, type); - RenderTargetTextures[RTT_TMP_128] = generateRTT(shadowsize3, rgba_internal_format, rgb_format, type); - RenderTargetTextures[RTT_LENS_128] = generateRTT(shadowsize3, rgba_internal_format, rgb_format, type); - - RenderTargetTextures[RTT_SP_GLOSS] = generateRTT(res, GL_RG8, GL_RG, GL_UNSIGNED_BYTE); - RenderTargetTextures[RTT_SP_DIFF_COLOR] = generateRTT(res, GL_RGBA8, rgb_format, GL_UNSIGNED_BYTE); - - std::vector somevector; - somevector.push_back(RenderTargetTextures[RTT_SSAO]); - FrameBuffers.push_back(new FrameBuffer(somevector, res.Width, res.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_NORMAL_AND_DEPTH]); - FrameBuffers.push_back(new FrameBuffer(somevector, DepthStencilTexture, res.Width, res.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_DIFFUSE]); - somevector.push_back(RenderTargetTextures[RTT_SPECULAR]); - FrameBuffers.push_back(new FrameBuffer(somevector, DepthStencilTexture, res.Width, res.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_COLOR]); - FrameBuffers.push_back(new FrameBuffer(somevector, DepthStencilTexture, res.Width, res.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_DIFFUSE]); - FrameBuffers.push_back(new FrameBuffer(somevector, res.Width, res.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_SPECULAR]); - FrameBuffers.push_back(new FrameBuffer(somevector, res.Width, res.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_MLAA_COLORS]); - FrameBuffers.push_back(new FrameBuffer(somevector, res.Width, res.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_MLAA_BLEND]); - FrameBuffers.push_back(new FrameBuffer(somevector, res.Width, res.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_MLAA_TMP]); - FrameBuffers.push_back(new FrameBuffer(somevector, res.Width, res.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_TMP1]); - FrameBuffers.push_back(new FrameBuffer(somevector, DepthStencilTexture, res.Width, res.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_TMP2]); - FrameBuffers.push_back(new FrameBuffer(somevector, DepthStencilTexture, res.Width, res.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_TMP4]); - FrameBuffers.push_back(new FrameBuffer(somevector, res.Width, res.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_LINEAR_DEPTH]); - FrameBuffers.push_back(new FrameBuffer(somevector, res.Width, res.Height)); - somevector.clear(); - - somevector.push_back(RenderTargetTextures[RTT_HALF1]); - FrameBuffers.push_back(new FrameBuffer(somevector, half.Width, half.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_HALF1_R]); - FrameBuffers.push_back(new FrameBuffer(somevector, half.Width, half.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_HALF2]); - FrameBuffers.push_back(new FrameBuffer(somevector, half.Width, half.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_HALF2_R]); - FrameBuffers.push_back(new FrameBuffer(somevector, half.Width, half.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_QUARTER1]); - FrameBuffers.push_back(new FrameBuffer(somevector, quarter.Width, quarter.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_QUARTER2]); - FrameBuffers.push_back(new FrameBuffer(somevector, quarter.Width, quarter.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_EIGHTH1]); - FrameBuffers.push_back(new FrameBuffer(somevector, eighth.Width, eighth.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_EIGHTH2]); - FrameBuffers.push_back(new FrameBuffer(somevector, eighth.Width, eighth.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_DISPLACE]); - FrameBuffers.push_back(new FrameBuffer(somevector, DepthStencilTexture, res.Width, res.Height)); - somevector.clear(); - - somevector.push_back(RenderTargetTextures[RTT_BLOOM_1024]); - FrameBuffers.push_back(new FrameBuffer(somevector, shadowsize0.Width, shadowsize0.Height)); - somevector.clear(); - - somevector.push_back(RenderTargetTextures[RTT_BLOOM_512]); - FrameBuffers.push_back(new FrameBuffer(somevector, shadowsize1.Width, shadowsize1.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_TMP_512]); - FrameBuffers.push_back(new FrameBuffer(somevector, shadowsize1.Width, shadowsize1.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_LENS_512]); - FrameBuffers.push_back(new FrameBuffer(somevector, shadowsize1.Width, shadowsize1.Height)); - somevector.clear(); - - somevector.push_back(RenderTargetTextures[RTT_BLOOM_256]); - FrameBuffers.push_back(new FrameBuffer(somevector, shadowsize2.Width, shadowsize2.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_TMP_256]); - FrameBuffers.push_back(new FrameBuffer(somevector, shadowsize2.Width, shadowsize2.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_LENS_256]); - FrameBuffers.push_back(new FrameBuffer(somevector, shadowsize2.Width, shadowsize2.Height)); - somevector.clear(); - - somevector.push_back(RenderTargetTextures[RTT_BLOOM_128]); - FrameBuffers.push_back(new FrameBuffer(somevector, shadowsize3.Width, shadowsize3.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_TMP_128]); - FrameBuffers.push_back(new FrameBuffer(somevector, shadowsize3.Width, shadowsize3.Height)); - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_LENS_128]); - FrameBuffers.push_back(new FrameBuffer(somevector, shadowsize3.Width, shadowsize3.Height)); - - somevector.clear(); - somevector.push_back(RenderTargetTextures[RTT_SP_DIFF_COLOR]); - somevector.push_back(RenderTargetTextures[RTT_NORMAL_AND_DEPTH]); - somevector.push_back(RenderTargetTextures[RTT_SP_GLOSS]); - FrameBuffers.push_back(new FrameBuffer(somevector, DepthStencilTexture, res.Width, res.Height)); - - if (CVS->isShadowEnabled()) + if (!CVS->isDeferredEnabled()) { - shadowDepthTex = generateRTT3D(GL_TEXTURE_2D_ARRAY, UserConfigParams::m_shadows_resolution, UserConfigParams::m_shadows_resolution, 4, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 1); - somevector.clear(); - m_shadow_FBO = new FrameBufferLayer(somevector, shadowDepthTex, UserConfigParams::m_shadows_resolution, UserConfigParams::m_shadows_resolution, 4); + // RTT is used in only deferred shading which need hdr framebuffer + rgba_internal_format = GL_RGBA8; + type = GL_UNSIGNED_BYTE; } - // Clear this FBO to 1s so that if no SSAO is computed we can still use it. - getFBO(FBO_HALF1_R).bind(); - glClearColor(1., 1., 1., 1.); - glClear(GL_COLOR_BUFFER_BIT); + if (!use_default_fbo_only) + { + m_render_target_textures[RTT_COLOR] = generateRTT(res, rgba_internal_format, rgba_format, type); + } + if (CVS->isDeferredEnabled()) + { + m_render_target_textures[RTT_NORMAL_AND_DEPTH] = generateRTT(res, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV); + m_render_target_textures[RTT_SP_GLOSS] = generateRTT(res, GL_RG8, GL_RG, GL_UNSIGNED_BYTE); + m_render_target_textures[RTT_SP_DIFF_COLOR] = generateRTT(res, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); + m_render_target_textures[RTT_RGBA_2] = generateRTT(res, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); + m_render_target_textures[RTT_DIFFUSE] = generateRTT(res, diffuse_specular_internal_format, rgb_format, type); + m_render_target_textures[RTT_SPECULAR] = generateRTT(res, diffuse_specular_internal_format, rgb_format, type); + m_render_target_textures[RTT_TMP1] = generateRTT(res, rgba_internal_format, rgba_format, type); + m_render_target_textures[RTT_HALF1] = generateRTT(half, rgba_internal_format, rgba_format, type); + m_render_target_textures[RTT_HALF1_R] = generateRTT(half, red_internal_format, red_format, type); + m_render_target_textures[RTT_HALF2] = generateRTT(half, rgba_internal_format, rgba_format, type); - getFBO(FBO_COMBINED_DIFFUSE_SPECULAR).bind(); - float color = 0.5; -#if defined(USE_GLES2) - if (!CVS->isDefferedEnabled()) - color = pow(color, 1. / 2.2); -#endif - glClearColor(color, color, color, color); - glClear(GL_COLOR_BUFFER_BIT); + if (UserConfigParams::m_mlaa) + { + m_render_target_textures[RTT_RGBA_3] = generateRTT(res, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE); + } + + if (UserConfigParams::m_ssao) + { + m_render_target_textures[RTT_SSAO] = generateRTT(res, red_internal_format, red_format, type); + m_render_target_textures[RTT_LINEAR_DEPTH] = generateRTT(res, red32_internal_format, red_format, type, linear_depth_mip_levels); + m_render_target_textures[RTT_HALF2_R] = generateRTT(half, red_internal_format, red_format, type); + } + + if (UserConfigParams::m_light_shaft || UserConfigParams::m_glow) + { + m_render_target_textures[RTT_QUARTER1] = generateRTT(quarter, rgba_internal_format, rgba_format, type); + } + if (UserConfigParams::m_light_shaft) + { + m_render_target_textures[RTT_QUARTER2] = generateRTT(quarter, rgba_internal_format, rgba_format, type); + } + + if (UserConfigParams::m_bloom) + { + m_render_target_textures[RTT_BLOOM_1024] = generateRTT(shadowsize0, rgba_internal_format, rgb_format, type); + m_render_target_textures[RTT_BLOOM_512] = generateRTT(shadowsize1, rgba_internal_format, rgb_format, type); + m_render_target_textures[RTT_TMP_512] = generateRTT(shadowsize1, rgba_internal_format, rgb_format, type); + m_render_target_textures[RTT_LENS_512] = generateRTT(shadowsize1, rgba_internal_format, rgb_format, type); + m_render_target_textures[RTT_BLOOM_256] = generateRTT(shadowsize2, rgba_internal_format, rgb_format, type); + m_render_target_textures[RTT_TMP_256] = generateRTT(shadowsize2, rgba_internal_format, rgb_format, type); + m_render_target_textures[RTT_LENS_256] = generateRTT(shadowsize2, rgba_internal_format, rgb_format, type); + m_render_target_textures[RTT_BLOOM_128] = generateRTT(shadowsize3, rgba_internal_format, rgb_format, type); + m_render_target_textures[RTT_TMP_128] = generateRTT(shadowsize3, rgba_internal_format, rgb_format, type); + m_render_target_textures[RTT_LENS_128] = generateRTT(shadowsize3, rgba_internal_format, rgb_format, type); + } + } + + std::vector somevector; + if (!use_default_fbo_only) + { + somevector.push_back(m_render_target_textures[RTT_COLOR]); + m_frame_buffers[FBO_COLORS] = new FrameBuffer(somevector, m_depth_stencil_tex, res.Width, res.Height); + } + + if (CVS->isDeferredEnabled()) + { + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_NORMAL_AND_DEPTH]); + m_frame_buffers[FBO_NORMAL_AND_DEPTHS] = new FrameBuffer(somevector, m_depth_stencil_tex, res.Width, res.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_SP_DIFF_COLOR]); + somevector.push_back(m_render_target_textures[RTT_NORMAL_AND_DEPTH]); + somevector.push_back(m_render_target_textures[RTT_SP_GLOSS]); + m_frame_buffers[FBO_SP] = new FrameBuffer(somevector, m_depth_stencil_tex, res.Width, res.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_SP_DIFF_COLOR]); + m_frame_buffers[FBO_RGBA_1] = new FrameBuffer(somevector, m_depth_stencil_tex, res.Width, res.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_RGBA_2]); + m_frame_buffers[FBO_RGBA_2] = new FrameBuffer(somevector, m_depth_stencil_tex, res.Width, res.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_DIFFUSE]); + somevector.push_back(m_render_target_textures[RTT_SPECULAR]); + m_frame_buffers[FBO_COMBINED_DIFFUSE_SPECULAR] = new FrameBuffer(somevector, m_depth_stencil_tex, res.Width, res.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_TMP1]); + m_frame_buffers[FBO_TMP1_WITH_DS] = new FrameBuffer(somevector, m_depth_stencil_tex, res.Width, res.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_HALF1_R]); + m_frame_buffers[FBO_HALF1_R] = new FrameBuffer(somevector, half.Width, half.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_HALF1]); + m_frame_buffers[FBO_HALF1] = new FrameBuffer(somevector, half.Width, half.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_HALF2]); + m_frame_buffers[FBO_HALF2] = new FrameBuffer(somevector, half.Width, half.Height); + + if (m_render_target_textures[RTT_RGBA_3] != 0) + { + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_RGBA_3]); + m_frame_buffers[FBO_RGBA_3] = new FrameBuffer(somevector, res.Width, res.Height); + } + + if (m_render_target_textures[RTT_SSAO] != 0 && + m_render_target_textures[RTT_LINEAR_DEPTH] != 0 && + m_render_target_textures[RTT_HALF2_R] != 0) + { + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_SSAO]); + m_frame_buffers[FBO_SSAO] = new FrameBuffer(somevector, res.Width, res.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_LINEAR_DEPTH]); + m_frame_buffers[FBO_LINEAR_DEPTH] = new FrameBuffer(somevector, res.Width, res.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_HALF2_R]); + m_frame_buffers[FBO_HALF2_R] = new FrameBuffer(somevector, half.Width, half.Height); + } + + if (m_render_target_textures[RTT_QUARTER1] != 0) + { + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_QUARTER1]); + m_frame_buffers[FBO_QUARTER1] = new FrameBuffer(somevector, quarter.Width, quarter.Height); + } + if (m_render_target_textures[RTT_QUARTER2] != 0) + { + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_QUARTER2]); + m_frame_buffers[FBO_QUARTER2] = new FrameBuffer(somevector, quarter.Width, quarter.Height); + } + + if (UserConfigParams::m_bloom) + { + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_BLOOM_1024]); + m_frame_buffers[FBO_BLOOM_1024] = new FrameBuffer(somevector, shadowsize0.Width, shadowsize0.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_BLOOM_512]); + m_frame_buffers[FBO_BLOOM_512] = new FrameBuffer(somevector, shadowsize1.Width, shadowsize1.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_TMP_512]); + m_frame_buffers[FBO_TMP_512] = new FrameBuffer(somevector, shadowsize1.Width, shadowsize1.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_LENS_512]); + m_frame_buffers[FBO_LENS_512] = new FrameBuffer(somevector, shadowsize1.Width, shadowsize1.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_BLOOM_256]); + m_frame_buffers[FBO_BLOOM_256] = new FrameBuffer(somevector, shadowsize2.Width, shadowsize2.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_TMP_256]); + m_frame_buffers[FBO_TMP_256] = new FrameBuffer(somevector, shadowsize2.Width, shadowsize2.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_LENS_256]); + m_frame_buffers[FBO_LENS_256] = new FrameBuffer(somevector, shadowsize2.Width, shadowsize2.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_BLOOM_128]); + m_frame_buffers[FBO_BLOOM_128] = new FrameBuffer(somevector, shadowsize3.Width, shadowsize3.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_TMP_128]); + m_frame_buffers[FBO_TMP_128] = new FrameBuffer(somevector, shadowsize3.Width, shadowsize3.Height); + + somevector.clear(); + somevector.push_back(m_render_target_textures[RTT_LENS_128]); + m_frame_buffers[FBO_LENS_128] = new FrameBuffer(somevector, shadowsize3.Width, shadowsize3.Height); + } + + if (CVS->isShadowEnabled()) + { + m_shadow_depth_tex = generateRTT3D(GL_TEXTURE_2D_ARRAY, UserConfigParams::m_shadows_resolution, UserConfigParams::m_shadows_resolution, 4, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 1); + somevector.clear(); + m_shadow_fbo = new FrameBufferLayer(somevector, m_shadow_depth_tex, UserConfigParams::m_shadows_resolution, UserConfigParams::m_shadows_resolution, 4); + } + // Clear this FBO to 1s so that if no SSAO is computed we can still use it. + getFBO(FBO_HALF1_R).bind(); + glClearColor(1., 1., 1., 1.); + glClear(GL_COLOR_BUFFER_BIT); + getFBO(FBO_HALF1).bind(); + glClearColor(0., 0., 0., 0.); + glClear(GL_COLOR_BUFFER_BIT); + } glBindFramebuffer(GL_FRAMEBUFFER, 0); } RTT::~RTT() { glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteTextures(RTT_COUNT, RenderTargetTextures); - glDeleteTextures(1, &DepthStencilTexture); + glDeleteTextures(RTT_COUNT, m_render_target_textures); + for (FrameBuffer* fb : m_frame_buffers) + { + delete fb; + } + glDeleteTextures(1, &m_depth_stencil_tex); if (CVS->isShadowEnabled()) { - delete m_shadow_FBO; - glDeleteTextures(1, &shadowDepthTex); + delete m_shadow_fbo; + glDeleteTextures(1, &m_shadow_depth_tex); } } diff --git a/src/graphics/rtts.hpp b/src/graphics/rtts.hpp index 66ec08628..87adef8a4 100644 --- a/src/graphics/rtts.hpp +++ b/src/graphics/rtts.hpp @@ -19,49 +19,34 @@ #define HEADER_RTTS_HPP #include "utils/leak_check.hpp" -#include "utils/ptr_vector.hpp" -#include "utils/types.hpp" -#include +#include class FrameBuffer; class FrameBufferLayer; -namespace irr { - namespace video { - class ITexture; - }; - namespace scene { - class ICameraSceneNode; - } -}; - -using irr::video::ITexture; - enum TypeFBO { - FBO_SSAO, - FBO_NORMAL_AND_DEPTHS, - FBO_COMBINED_DIFFUSE_SPECULAR, FBO_COLORS, - FBO_DIFFUSE, - FBO_SPECULAR, - FBO_MLAA_COLORS, - FBO_MLAA_BLEND, - FBO_MLAA_TMP, + FBO_NORMAL_AND_DEPTHS, + FBO_SP, + FBO_RGBA_1, + FBO_RGBA_2, + FBO_COMBINED_DIFFUSE_SPECULAR, FBO_TMP1_WITH_DS, - FBO_TMP2_WITH_DS, - FBO_TMP4, - FBO_LINEAR_DEPTH, - FBO_HALF1, FBO_HALF1_R, + FBO_HALF1, FBO_HALF2, - FBO_HALF2_R, - FBO_QUARTER1, - FBO_QUARTER2, - FBO_EIGHTH1, - FBO_EIGHTH2, - FBO_DISPLACE, - FBO_BLOOM_1024, + + FBO_RGBA_3, // MLAA + + FBO_SSAO, // SSAO + FBO_LINEAR_DEPTH, // SSAO + FBO_HALF2_R, // SSAO + + FBO_QUARTER1, // Glow || God Ray + FBO_QUARTER2, // God Ray + + FBO_BLOOM_1024, // The reset is for bloom only (may be optimized layer) FBO_BLOOM_512, FBO_TMP_512, FBO_LENS_512, @@ -73,55 +58,31 @@ enum TypeFBO FBO_BLOOM_128, FBO_TMP_128, FBO_LENS_128, - FBO_SP, FBO_COUNT }; enum TypeRTT : unsigned int { - RTT_TMP1 = 0, - RTT_TMP2, - RTT_TMP3, - RTT_TMP4, - RTT_LINEAR_DEPTH, + RTT_COLOR = 0, RTT_NORMAL_AND_DEPTH, - RTT_COLOR, + RTT_SP_GLOSS, + RTT_SP_DIFF_COLOR, // RGBA + RTT_RGBA_2, RTT_DIFFUSE, RTT_SPECULAR, - - + RTT_TMP1, RTT_HALF1, - RTT_HALF2, RTT_HALF1_R, + RTT_HALF2, + + RTT_RGBA_3, + + RTT_SSAO, + RTT_LINEAR_DEPTH, RTT_HALF2_R, RTT_QUARTER1, RTT_QUARTER2, - // RTT_QUARTER3, - // RTT_QUARTER4, - - RTT_EIGHTH1, - RTT_EIGHTH2, - - // RTT_SIXTEENTH1, - // RTT_SIXTEENTH2, - - RTT_SSAO, - - // RTT_COLLAPSE, - // RTT_COLLAPSEH, - // RTT_COLLAPSEV, - // RTT_COLLAPSEH2, - // RTT_COLLAPSEV2, - // RTT_WARPH, - // RTT_WARPV, - - // RTT_HALF_SOFT, - - RTT_DISPLACE, - RTT_MLAA_COLORS, - RTT_MLAA_BLEND, - RTT_MLAA_TMP, RTT_BLOOM_1024, RTT_BLOOM_512, @@ -134,36 +95,46 @@ enum TypeRTT : unsigned int RTT_TMP_128, RTT_LENS_128, - RTT_SP_GLOSS, - RTT_SP_DIFF_COLOR, - RTT_COUNT }; class RTT { public: - RTT(unsigned int width, unsigned int height, float rtt_scale = 1.0f); + RTT(unsigned int width, unsigned int height, float rtt_scale = 1.0f, + bool use_default_fbo_only = false); ~RTT(); - + unsigned int getWidth () const { return m_width ; } unsigned int getHeight() const { return m_height; } - FrameBufferLayer* getShadowFrameBuffer() { return m_shadow_FBO; } - unsigned getDepthStencilTexture() const { return DepthStencilTexture; } - unsigned getRenderTarget(enum TypeRTT target) const { return RenderTargetTextures[target]; } - FrameBuffer& getFBO(enum TypeFBO fbo) { return FrameBuffers[fbo]; } + FrameBufferLayer* getShadowFrameBuffer() { return m_shadow_fbo; } + unsigned getDepthStencilTexture() const + { + assert(m_depth_stencil_tex != 0); + return m_depth_stencil_tex; + } + unsigned getRenderTarget(enum TypeRTT target) const + { + assert(m_render_target_textures[target] != 0); + return m_render_target_textures[target]; + } + FrameBuffer& getFBO(enum TypeFBO fbo) + { + assert(m_frame_buffers[fbo] != NULL); + return *m_frame_buffers[fbo]; + } private: - unsigned RenderTargetTextures[RTT_COUNT]; - PtrVector FrameBuffers; - unsigned DepthStencilTexture; + unsigned m_render_target_textures[RTT_COUNT] = {}; + FrameBuffer* m_frame_buffers[FBO_COUNT] = {}; + unsigned m_depth_stencil_tex = 0; unsigned int m_width; unsigned int m_height; - unsigned shadowDepthTex; - FrameBufferLayer* m_shadow_FBO; + unsigned m_shadow_depth_tex = 0; + FrameBufferLayer* m_shadow_fbo; LEAK_CHECK(); }; diff --git a/src/graphics/screen_quad.cpp b/src/graphics/screen_quad.cpp deleted file mode 100644 index 16c94a515..000000000 --- a/src/graphics/screen_quad.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// SuperTuxKart - a fun racing game with go-kart -// Copyright (C) 2014-2015 SuperTuxKart-Team -// -// 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, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include "graphics/screen_quad.hpp" - -// Just the static parts to our screenquad - -const u16 ScreenQuad::indices[4] = {0, 1, 2, 3}; - -static const SColor white(255, 255, 255, 255); - -const S3DVertex ScreenQuad::vertices[4] = { - S3DVertex(-1, 1, 0, 0, 1, 0, white, 0, 1), - S3DVertex(1, 1, 0, 0, 1, 0, white, 1, 1), - S3DVertex(-1, -1, 0, 0, 1, 0, white, 0, 0), - S3DVertex(1, -1, 0, 0, 1, 0, white, 1, 0), - }; diff --git a/src/graphics/screen_quad.hpp b/src/graphics/screen_quad.hpp deleted file mode 100644 index 87c11dfce..000000000 --- a/src/graphics/screen_quad.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// SuperTuxKart - a fun racing game with go-kart -// Copyright (C) 2014-2015 SuperTuxKart-Team -// -// 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, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef HEADER_SCREENQUAD_H -#define HEADER_SCREENQUAD_H - -#include -#include - -using namespace irr; -using namespace video; - -class ScreenQuad { - -public: - ScreenQuad(IVideoDriver *xy) - { - vd = xy; - - mat.Lighting = false; - mat.ZBuffer = video::ECFN_ALWAYS; - mat.ZWriteEnable = false; - - for(u32 c = 0; c < MATERIAL_MAX_TEXTURES; c++) - { - mat.TextureLayer[c].TextureWrapU = video::ETC_CLAMP_TO_EDGE; - mat.TextureLayer[c].TextureWrapV = video::ETC_CLAMP_TO_EDGE; - } - } - - SMaterial& getMaterial() { return mat; } - - //Set the texture to render with the quad - void setTexture(ITexture* tex, u32 layer = 0) - { - mat.TextureLayer[layer].Texture = tex; - } - - ITexture* getTexture(u32 layer = 0) const { return mat.TextureLayer[layer].Texture; } - - void setMaterialType(E_MATERIAL_TYPE mt) { mat.MaterialType = mt; } - - void render(bool setRTToFrameBuff = true) const - { - if(setRTToFrameBuff) - vd->setRenderTarget(video::ERT_FRAME_BUFFER); - - sq_dorender(); - } - - void render(ITexture* rt) const - { - vd->setRenderTarget(rt); - - sq_dorender(); - } - -protected: - static const S3DVertex vertices[4]; - static const u16 indices[4]; - SMaterial mat; - - IVideoDriver* vd; - - void sq_dorender() const - { - vd->setMaterial(mat); - vd->setTransform(ETS_WORLD, core::IdentityMatrix); - vd->setTransform(ETS_VIEW, core::IdentityMatrix); - vd->setTransform(ETS_PROJECTION, core::IdentityMatrix); - vd->drawVertexPrimitiveList(vertices, 4, indices, 2, EVT_STANDARD, - scene::EPT_TRIANGLE_STRIP); - } -}; - -#endif diff --git a/src/graphics/shader.hpp b/src/graphics/shader.hpp index d19b0d169..0cb5d5d14 100644 --- a/src/graphics/shader.hpp +++ b/src/graphics/shader.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -219,6 +220,15 @@ private: setUniformsImpl(arg...); } // setUniformsImpl + // ------------------------------------------------------------------------ + /** Implementation for setUniforms for a 4 floats uniform. */ + template + void setUniformsImpl(const std::array &ff, Args1... arg) const + { + glUniform4f(m_uniforms[N], ff[0], ff[1], ff[2], ff[3]); + setUniformsImpl(arg...); + } // setUniformsImpl + // ------------------------------------------------------------------------ /** Implementation for setUniforms for a vector3df uniform. */ template diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index d64bed82c..147e86dcf 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -50,9 +50,6 @@ #include // ---------------------------------------------------------------------------- - - - void ShaderBasedRenderer::setRTT(RTT* rtts) { m_rtts = rtts; @@ -70,7 +67,7 @@ void ShaderBasedRenderer::prepareForwardRenderer() glBindFramebuffer(GL_FRAMEBUFFER, 0); glClearColor(clearColor.getRed() / 255.f, clearColor.getGreen() / 255.f, clearColor.getBlue() / 255.f, clearColor.getAlpha() / 255.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } // ---------------------------------------------------------------------------- @@ -111,8 +108,7 @@ void ShaderBasedRenderer::computeMatrixesAndCameras(scene::ICameraSceneNode *con unsigned int width, unsigned int height) { m_current_screen_size = core::vector2df((float)width, (float)height); - m_shadow_matrices.computeMatrixesAndCameras(camnode, width, height, - m_rtts->getDepthStencilTexture()); + m_shadow_matrices.computeMatrixesAndCameras(camnode, width, height); } // computeMatrixesAndCameras // ---------------------------------------------------------------------------- @@ -152,7 +148,7 @@ void ShaderBasedRenderer::renderSSAO() const void ShaderBasedRenderer::renderGlow() const { irr_driver->getSceneManager()->setCurrentRendertime(scene::ESNRP_SOLID); - m_rtts->getFBO(FBO_TMP1_WITH_DS).bind(); + m_rtts->getFBO(FBO_RGBA_2).bind(); glClearStencil(0); glClearColor(0, 0, 0, 0); glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); @@ -199,27 +195,29 @@ void ShaderBasedRenderer::renderShadows() } // ============================================================================ -class CombineDiffuseColor : public TextureShader +class CombineDiffuseColor : public TextureShader > { public: CombineDiffuseColor() { loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert", GL_FRAGMENT_SHADER, "combine_diffuse_color.frag"); - assignUniforms(); + assignUniforms("bg_color"); assignSamplerNames(0, "diffuse_map", ST_NEAREST_FILTERED, 1, "specular_map", ST_NEAREST_FILTERED, 2, "ssao_tex", ST_NEAREST_FILTERED, 3, "gloss_map", ST_NEAREST_FILTERED, 4, "diffuse_color", ST_NEAREST_FILTERED, - 5, "depth_stencil", ST_NEAREST_FILTERED); + 5, "depth_stencil", ST_NEAREST_FILTERED, + 6, "light_scatter", ST_NEAREST_FILTERED); } // CombineDiffuseColor // ------------------------------------------------------------------------ void render(GLuint dm, GLuint sm, GLuint st, GLuint gm, GLuint dc, - GLuint ds) + GLuint ds, GLuint lt, const std::array & bg_color) { - setTextureUnits(dm, sm, st, gm, dc, ds); - drawFullScreenEffect(); + setTextureUnits(dm, sm, st, gm, dc, ds, lt); + drawFullScreenEffect(bg_color); } // render }; // CombineDiffuseColor @@ -229,6 +227,7 @@ void ShaderBasedRenderer::renderSceneDeferred(scene::ICameraSceneNode * const ca bool hasShadow, bool forceRTT) { + if (CVS->isARBUniformBufferObjectUsable()) { glBindBufferBase(GL_UNIFORM_BUFFER, 0, @@ -239,11 +238,7 @@ void ShaderBasedRenderer::renderSceneDeferred(scene::ICameraSceneNode * const ca irr_driver->getSceneManager()->setActiveCamera(camnode); PROFILER_PUSH_CPU_MARKER("- Draw Call Generation", 0xFF, 0xFF, 0xFF); - unsigned solid_poly_count = 0; - unsigned shadow_poly_count = 0; m_draw_calls.prepareDrawCalls(camnode); - m_poly_count[SOLID_NORMAL_AND_DEPTH_PASS] += solid_poly_count; - m_poly_count[SHADOW_PASS] += shadow_poly_count; PROFILER_POP_CPU_MARKER(); PROFILER_PUSH_CPU_MARKER("Update Light Info", 0xFF, 0x0, 0x0); m_lighting_passes.updateLightsInfo(camnode, dt); @@ -263,26 +258,13 @@ void ShaderBasedRenderer::renderSceneDeferred(scene::ICameraSceneNode * const ca { m_rtts->getFBO(FBO_SP).bind(); - std::array clear_color_world = {{ 1.0f, 1.0f, 1.0f, 0.0f }}; - if (World::getWorld() != NULL) - { - clear_color_world[0] = - irr_driver->getClearColor().getRed() / 255.0f; - clear_color_world[1] = - irr_driver->getClearColor().getGreen() / 255.0f; - clear_color_world[2] = - irr_driver->getClearColor().getBlue() / 255.0f; - clear_color_world[3] = - irr_driver->getClearColor().getAlpha() / 255.0f; - } - float clear_color_empty[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; float clear_color_gloss[4] = { 0.1f, 0.1f, 0.0f, 0.0f }; - glClearBufferfv(GL_COLOR, 0, clear_color_world.data()); + glClearBufferfv(GL_COLOR, 0, clear_color_empty); glClearBufferfv(GL_COLOR, 1, clear_color_empty); glClearBufferfv(GL_COLOR, 2, clear_color_gloss); glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0); - ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_SOLID_PASS1)); + ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_SOLID_PASS)); SP::draw(SP::RP_1ST, SP::DCT_NORMAL); } @@ -315,31 +297,75 @@ void ShaderBasedRenderer::renderSceneDeferred(scene::ICameraSceneNode * const ca PROFILER_POP_CPU_MARKER(); } + const Track * const track = Track::getCurrentTrack(); + // Render discrete lights scattering + if (track && track->isFogEnabled()) + { + PROFILER_PUSH_CPU_MARKER("- PointLight Scatter", 0xFF, 0x00, 0x00); + ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_LIGHTSCATTER)); + m_lighting_passes.renderLightsScatter(m_rtts->getDepthStencilTexture(), + m_rtts->getFBO(FBO_HALF1), + m_rtts->getFBO(FBO_HALF2), + m_post_processing); + PROFILER_POP_CPU_MARKER(); + } + + // Render anything glowing. + if (UserConfigParams::m_glow) + { + PROFILER_PUSH_CPU_MARKER("- Glow", 0xFF, 0xFF, 0x00); + ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_GLOW)); + renderGlow(); + // To half + FrameBuffer::blit(m_rtts->getFBO(FBO_RGBA_2), + m_rtts->getFBO(FBO_HALF2), GL_COLOR_BUFFER_BIT, GL_LINEAR); + // To quarter + FrameBuffer::blit(m_rtts->getFBO(FBO_HALF2), + m_rtts->getFBO(FBO_QUARTER1), GL_COLOR_BUFFER_BIT, GL_LINEAR); + PROFILER_POP_CPU_MARKER(); + } // end glow + m_rtts->getFBO(FBO_COLORS).bind(); - glClear(GL_COLOR_BUFFER_BIT); + glClear(UserConfigParams::m_glow ? GL_COLOR_BUFFER_BIT : + GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); { PROFILER_PUSH_CPU_MARKER("- Combine diffuse color", 0x2F, 0x77, 0x33); - ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_SOLID_PASS2)); + ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_COMBINE_DIFFUSE_COLOR)); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glDisable(GL_BLEND); + std::array bg_color = {{ 1.0f, 1.0f, 1.0f, 0.0f }}; + if (World::getWorld() != NULL) + { + bg_color[0] = + irr_driver->getClearColor().getRed() / 255.0f; + bg_color[1] = + irr_driver->getClearColor().getGreen() / 255.0f; + bg_color[2] = + irr_driver->getClearColor().getBlue() / 255.0f; + bg_color[3] = + irr_driver->getClearColor().getAlpha() / 255.0f; + } + CombineDiffuseColor::getInstance()->render( m_rtts->getRenderTarget(RTT_DIFFUSE), m_rtts->getRenderTarget(RTT_SPECULAR), m_rtts->getRenderTarget(RTT_HALF1_R), m_rtts->getRenderTarget(RTT_SP_GLOSS), m_rtts->getRenderTarget(RTT_SP_DIFF_COLOR), - m_rtts->getDepthStencilTexture()); + m_rtts->getDepthStencilTexture(), + m_rtts->getRenderTarget(RTT_HALF1), !m_skybox ? + bg_color : std::array{{0.0f, 0.0f, 0.0f, 0.0f}}); PROFILER_POP_CPU_MARKER(); } - if (irr_driver->getNormals()) + if (SP::sp_debug_view) { glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).bind(); - SP::drawNormal(); + SP::drawSPDebugView(); m_rtts->getFBO(FBO_COLORS).bind(); } @@ -350,33 +376,10 @@ void ShaderBasedRenderer::renderSceneDeferred(scene::ICameraSceneNode * const ca PROFILER_POP_CPU_MARKER(); } - const Track * const track = Track::getCurrentTrack(); - // Render discrete lights scattering - if (track && track->isFogEnabled()) - { - PROFILER_PUSH_CPU_MARKER("- PointLight Scatter", 0xFF, 0x00, 0x00); - ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_FOG)); - m_lighting_passes.renderLightsScatter(m_rtts->getDepthStencilTexture(), - m_rtts->getFBO(FBO_HALF1), - m_rtts->getFBO(FBO_HALF2), - m_rtts->getFBO(FBO_COLORS), - m_post_processing); - PROFILER_POP_CPU_MARKER(); - } - - PROFILER_PUSH_CPU_MARKER("- Glow", 0xFF, 0xFF, 0x00); - // Render anything glowing. if (UserConfigParams::m_glow) { - ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_GLOW)); - irr_driver->setPhase(GLOW_PASS); - renderGlow(); - m_post_processing->renderGlow(m_rtts->getFBO(FBO_TMP1_WITH_DS), - m_rtts->getFBO(FBO_HALF1), - m_rtts->getFBO(FBO_QUARTER1), - m_rtts->getFBO(FBO_COLORS)); - } // end glow - PROFILER_POP_CPU_MARKER(); + m_post_processing->renderGlow(m_rtts->getFBO(FBO_QUARTER1)); + } // Render transparent { @@ -405,11 +408,8 @@ void ShaderBasedRenderer::renderSceneDeferred(scene::ICameraSceneNode * const ca { glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - return; } - // Ensure that no object will be drawn after that by using invalid pass - irr_driver->setPhase(PASS_COUNT); } //renderSceneDeferred // ---------------------------------------------------------------------------- @@ -427,11 +427,7 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode, irr_driver->getSceneManager()->setActiveCamera(camnode); PROFILER_PUSH_CPU_MARKER("- Draw Call Generation", 0xFF, 0xFF, 0xFF); - unsigned solid_poly_count = 0; - unsigned shadow_poly_count = 0; m_draw_calls.prepareDrawCalls(camnode); - m_poly_count[SOLID_NORMAL_AND_DEPTH_PASS] += solid_poly_count; - m_poly_count[SHADOW_PASS] += shadow_poly_count; PROFILER_POP_CPU_MARKER(); glDepthMask(GL_TRUE); @@ -440,27 +436,6 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode, glDisable(GL_BLEND); glEnable(GL_CULL_FACE); - if (!forceRTT) - { - // We need a cleared depth buffer for some effect (eg particles depth blending) - m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).bind(); - // Bind() modifies the viewport. In order not to affect anything else, - // the viewport is just reset here and not removed in Bind(). - const core::recti &vp = Camera::getActiveCamera()->getViewport(); - glViewport(vp.UpperLeftCorner.X, - irr_driver->getActualScreenSize().Height - vp.LowerRightCorner.Y, - vp.LowerRightCorner.X - vp.UpperLeftCorner.X, - vp.LowerRightCorner.Y - vp.UpperLeftCorner.Y); - glClear(GL_DEPTH_BUFFER_BIT); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - } - else - { - m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).bind(); - glClearColor(0., 0., 0., 0.); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - } - if (forceRTT) { m_rtts->getFBO(FBO_COLORS).bind(); @@ -471,13 +446,15 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode, glClearColor(clearColor.getRed() / 255.f, clearColor.getGreen() / 255.f, clearColor.getBlue() / 255.f, clearColor.getAlpha() / 255.f); glClear(GL_COLOR_BUFFER_BIT); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } { glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); - ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_SOLID_PASS1)); + ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_SOLID_PASS)); SP::draw(SP::RP_1ST, SP::DCT_NORMAL); } @@ -511,15 +488,13 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode, // Now all instancing data from mesh and particle are done drawing m_draw_calls.setFenceSync(); - if (!CVS->isDefferedEnabled() && !forceRTT) + if (!forceRTT) { glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - return; } + glBindVertexArray(0); - // Ensure that no object will be drawn after that by using invalid pass - irr_driver->setPhase(PASS_COUNT); } //renderScene // ---------------------------------------------------------------------------- @@ -567,14 +542,15 @@ void ShaderBasedRenderer::debugPhysics() } //debugPhysics // ---------------------------------------------------------------------------- -void ShaderBasedRenderer::renderPostProcessing(Camera * const camera) +void ShaderBasedRenderer::renderPostProcessing(Camera * const camera, + bool first_cam) { scene::ICameraSceneNode * const camnode = camera->getCameraSceneNode(); const core::recti &viewport = camera->getViewport(); - + bool isRace = StateManager::get()->getGameState() == GUIEngine::GAME; FrameBuffer *fbo = m_post_processing->render(camnode, isRace, m_rtts); - + // The viewport has been changed using glViewport function directly // during scene rendering, but irrlicht thinks that nothing changed // when single camera is used. In this case we set the viewport @@ -582,7 +558,7 @@ void ShaderBasedRenderer::renderPostProcessing(Camera * const camera) glViewport(0, 0, irr_driver->getActualScreenSize().Width, irr_driver->getActualScreenSize().Height); - if (irr_driver->getNormals()) + if (SP::sp_debug_view) { m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).blitToDefault( viewport.UpperLeftCorner.X, @@ -593,6 +569,10 @@ void ShaderBasedRenderer::renderPostProcessing(Camera * const camera) else if (irr_driver->getSSAOViz()) { glBindFramebuffer(GL_FRAMEBUFFER, 0); + if (first_cam) + { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } camera->activate(); m_post_processing->renderPassThrough(m_rtts->getFBO(FBO_HALF1_R).getRTT()[0], viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X, viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y); } @@ -603,9 +583,14 @@ void ShaderBasedRenderer::renderPostProcessing(Camera * const camera) else { glBindFramebuffer(GL_FRAMEBUFFER, 0); + if (first_cam) + { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } camera->activate(); m_post_processing->renderPassThrough(fbo->getRTT()[0], viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X, viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y); } + glBindVertexArray(0); } //renderPostProcessing // ---------------------------------------------------------------------------- @@ -617,25 +602,13 @@ ShaderBasedRenderer::ShaderBasedRenderer() SharedGPUObjects::init(); SP::init(); SP::initSTKRenderer(this); - m_post_processing = new PostProcessing(irr_driver->getVideoDriver()); + m_post_processing = new PostProcessing(); } // ---------------------------------------------------------------------------- ShaderBasedRenderer::~ShaderBasedRenderer() { - // Note that we can not simply delete m_post_processing here: - // m_post_processing uses a material that has a reference to - // m_post_processing (for a callback). So when the material is - // removed it will try to drop the ref count of its callback object, - // which is m_post_processing, and which was already deleted. So - // instead we just decrease the ref count here. When the material - // is deleted, it will trigger the actual deletion of - // PostProcessing when decreasing the refcount of its callback object. - if(m_post_processing) - { - // check if we createad the OpenGL device by calling initDevice() - m_post_processing->drop(); - } + delete m_post_processing; delete m_spherical_harmonics; delete m_skybox; delete m_rtts; @@ -650,8 +623,9 @@ void ShaderBasedRenderer::onLoadWorld() const core::recti &viewport = Camera::getCamera(0)->getViewport(); unsigned int width = viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X; unsigned int height = viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y; - RTT* rtts = new RTT(width, height, CVS->isDefferedEnabled() ? - UserConfigParams::m_scale_rtts_factor : 1.0f); + RTT* rtts = new RTT(width, height, CVS->isDeferredEnabled() ? + UserConfigParams::m_scale_rtts_factor : 1.0f, + !CVS->isDeferredEnabled()); setRTT(rtts); } @@ -732,9 +706,6 @@ void ShaderBasedRenderer::addSunLight(const core::vector3df &pos) // ---------------------------------------------------------------------------- void ShaderBasedRenderer::render(float dt) { - resetObjectCount(); - resetPolyCount(); - // Start the RTT for post-processing. // We do this before beginScene() because we want to capture the glClear() // because of tracks that do not have skyboxes (generally add-on tracks) @@ -746,7 +717,7 @@ void ShaderBasedRenderer::render(float dt) RaceGUIBase *rg = world->getRaceGUI(); if (rg) rg->update(dt); - if (!CVS->isDefferedEnabled()) + if (!CVS->isDeferredEnabled()) { prepareForwardRenderer(); } @@ -770,12 +741,12 @@ void ShaderBasedRenderer::render(float dt) oss << "drawAll() for kart " << cam; PROFILER_PUSH_CPU_MARKER(oss.str().c_str(), (cam+1)*60, 0x00, 0x00); - camera->activate(!CVS->isDefferedEnabled()); + camera->activate(!CVS->isDeferredEnabled()); rg->preRenderCallback(camera); // adjusts start referee irr_driver->getSceneManager()->setActiveCamera(camnode); computeMatrixesAndCameras(camnode, m_rtts->getWidth(), m_rtts->getHeight()); - if (CVS->isDefferedEnabled()) + if (CVS->isDeferredEnabled()) { renderSceneDeferred(camnode, dt, track->hasShadows(), false); } @@ -794,9 +765,9 @@ void ShaderBasedRenderer::render(float dt) debugPhysics(); - if (CVS->isDefferedEnabled()) + if (CVS->isDeferredEnabled()) { - renderPostProcessing(camera); + renderPostProcessing(camera, cam == 0); } // Save projection-view matrix for the next frame @@ -872,8 +843,6 @@ void ShaderBasedRenderer::renderToTexture(GL3RenderTarget *render_target, // For render to texture no triple buffering of ubo is used SP::sp_cur_player = 0; SP::sp_cur_buf_id[0] = 0; - resetObjectCount(); - resetPolyCount(); assert(m_rtts != NULL); irr_driver->getSceneManager()->setActiveCamera(camera); @@ -883,7 +852,7 @@ void ShaderBasedRenderer::renderToTexture(GL3RenderTarget *render_target, if (CVS->isARBUniformBufferObjectUsable()) uploadLightingData(); - if (CVS->isDefferedEnabled()) + if (CVS->isDeferredEnabled()) { renderSceneDeferred(camera, dt, false, true); render_target->setFrameBuffer(m_post_processing diff --git a/src/graphics/shader_based_renderer.hpp b/src/graphics/shader_based_renderer.hpp index d15f3bb7f..66593dfe7 100644 --- a/src/graphics/shader_based_renderer.hpp +++ b/src/graphics/shader_based_renderer.hpp @@ -72,7 +72,7 @@ private: float dt, bool hasShadows, bool forceRTT); void debugPhysics(); - void renderPostProcessing(Camera * const camera); + void renderPostProcessing(Camera * const camera, bool first_cam); void preloadShaderFiles(); void renderShadows(); diff --git a/src/graphics/shader_files_manager.cpp b/src/graphics/shader_files_manager.cpp index ecf037ec3..dea661fe9 100644 --- a/src/graphics/shader_files_manager.cpp +++ b/src/graphics/shader_files_manager.cpp @@ -18,9 +18,11 @@ #ifndef SERVER_ONLY #include "graphics/shader_files_manager.hpp" +#include "config/user_config.hpp" #include "config/stk_config.hpp" #include "graphics/central_settings.hpp" #include "graphics/graphics_restrictions.hpp" +#include "guiengine/message_queue.hpp" #include "io/file_manager.hpp" #include "utils/log.hpp" @@ -171,7 +173,7 @@ ShaderFilesManager::SharedShader ShaderFilesManager::loadShader code << "#define UBO_DISABLED\n"; if (CVS->needsVertexIdWorkaround()) code << "#define Needs_Vertex_Id_Workaround\n"; - if (CVS->isDefferedEnabled()) + if (CVS->isDeferredEnabled()) code << "#define Advanced_Lighting_Enabled\n"; #if !defined(USE_GLES2) @@ -227,6 +229,13 @@ ShaderFilesManager::SharedShader ShaderFilesManager::loadShader glGetShaderInfoLog(*ss, info_length, NULL, error_message); Log::error("ShaderFilesManager", error_message); delete[] error_message; + if (UserConfigParams::m_artist_debug_mode) + { + core::stringw err = StringUtils::insertValues(L"Shader file %s" + " failed to compile, check stdout.log or console for details", + full_path.c_str()); + MessageQueue::add(MessageQueue::MT_ERROR, err); + } return NULL; } glGetError(); diff --git a/src/graphics/shadow_matrices.cpp b/src/graphics/shadow_matrices.cpp index 390807258..949804694 100644 --- a/src/graphics/shadow_matrices.cpp +++ b/src/graphics/shadow_matrices.cpp @@ -193,8 +193,7 @@ core::matrix4 ShadowMatrices::getTighestFitOrthoProj(const core::matrix4 &transf * \param height of the rendering viewport */ void ShadowMatrices::computeMatrixesAndCameras(scene::ICameraSceneNode *const camnode, - unsigned int width, unsigned int height, - GLuint depth_stencil_texture) + unsigned int width, unsigned int height) { camnode->render(); irr_driver->setProjMatrix(irr_driver->getVideoDriver() diff --git a/src/graphics/shadow_matrices.hpp b/src/graphics/shadow_matrices.hpp index a7ad04134..793107977 100644 --- a/src/graphics/shadow_matrices.hpp +++ b/src/graphics/shadow_matrices.hpp @@ -62,8 +62,7 @@ public: ~ShadowMatrices(); void computeMatrixesAndCameras(scene::ICameraSceneNode *const camnode, - unsigned int width, unsigned int height, - GLuint depth_stencil_texture); + unsigned int width, unsigned int height); void addLight(const core::vector3df &pos); void updateSunOrthoMatrices(); void renderShadowsDebug(const FrameBuffer* shadow_framebuffer, diff --git a/src/graphics/skid_marks.cpp b/src/graphics/skid_marks.cpp index f7fcadcac..3933eb0f1 100644 --- a/src/graphics/skid_marks.cpp +++ b/src/graphics/skid_marks.cpp @@ -220,7 +220,7 @@ SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left, video::SColor(255, SkidMarks::m_start_grey, SkidMarks::m_start_grey, SkidMarks::m_start_grey)); - if (CVS->isDefferedEnabled()) + if (CVS->isDeferredEnabled()) { m_start_color.setRed(SP::srgb255ToLinear(m_start_color.getRed())); m_start_color.setGreen(SP::srgb255ToLinear(m_start_color.getGreen())); diff --git a/src/graphics/skybox.cpp b/src/graphics/skybox.cpp index 3ec540b80..73027ed5e 100644 --- a/src/graphics/skybox.cpp +++ b/src/graphics/skybox.cpp @@ -179,7 +179,7 @@ void Skybox::generateCubeMapFromTextures() glBindTexture(GL_TEXTURE_CUBE_MAP, m_cube_map); - bool needs_srgb_format = CVS->isDefferedEnabled(); + bool needs_srgb_format = CVS->isDeferredEnabled(); GLint format = GL_RGBA; GLint internal_format = needs_srgb_format ? GL_SRGB8_ALPHA8 : GL_RGBA8; @@ -218,7 +218,7 @@ void Skybox::generateSpecularCubemap() } glGenerateMipmap(GL_TEXTURE_CUBE_MAP); - if (!CVS->isDefferedEnabled()) + if (!CVS->isDeferredEnabled()) return; #if !defined(USE_GLES2) @@ -347,7 +347,11 @@ void Skybox::render(const scene::ICameraSceneNode *camera) const glDisable(GL_CULL_FACE); assert(m_skybox_textures.size() == 6); - glDisable(GL_BLEND); + if (CVS->isDeferredEnabled()) + { + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + } SkyboxShader::getInstance()->use(); SkyboxShader::getInstance()->bindVertexArray(); @@ -357,6 +361,7 @@ void Skybox::render(const scene::ICameraSceneNode *camera) const glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0); + glDisable(GL_BLEND); } // renderSkybox #endif // !SERVER_ONLY diff --git a/src/graphics/sp/sp_base.cpp b/src/graphics/sp/sp_base.cpp index 8a0e093e1..a399789d0 100644 --- a/src/graphics/sp/sp_base.cpp +++ b/src/graphics/sp/sp_base.cpp @@ -67,6 +67,8 @@ std::array* g_joint_ptr = NULL; // ---------------------------------------------------------------------------- bool sp_culling = true; // ---------------------------------------------------------------------------- +bool sp_debug_view = false; +// ---------------------------------------------------------------------------- bool g_handle_shadow = false; // ---------------------------------------------------------------------------- SPShader* g_normal_visualizer = NULL; @@ -83,7 +85,7 @@ std::vector, std::vector > > > > > g_final_draw_calls[DCT_FOR_VAO]; // ---------------------------------------------------------------------------- -std::unordered_map > > g_glow_meshes; // ---------------------------------------------------------------------------- std::unordered_set g_instances; @@ -178,7 +180,7 @@ void displaceShaderInit(SPShader* shader) glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - g_stk_sbr->getRTTs()->getFBO(FBO_TMP1_WITH_DS).bind(), + g_stk_sbr->getRTTs()->getFBO(FBO_RGBA_1).bind(), glClear(GL_COLOR_BUFFER_BIT); }, RP_1ST); shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_RESERVED); @@ -186,7 +188,7 @@ void displaceShaderInit(SPShader* shader) shader->linkShaderFiles(RP_RESERVED); shader->use(RP_RESERVED); shader->addBasicUniforms(RP_RESERVED); - shader->addUniform("direction", typeid(std::array), RP_RESERVED); + shader->addAllUniforms(RP_RESERVED); shader->setUseFunction([]()->void { glEnable(GL_DEPTH_TEST); @@ -196,19 +198,16 @@ void displaceShaderInit(SPShader* shader) glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - g_stk_sbr->getRTTs()->getFBO(FBO_DISPLACE).bind(), + g_stk_sbr->getRTTs()->getFBO(FBO_TMP1_WITH_DS).bind(), glClear(GL_COLOR_BUFFER_BIT); }, RP_RESERVED); - shader->addCustomPrefilledTextures(ST_BILINEAR, - GL_TEXTURE_2D, "displacement_tex", []()->GLuint - { - return irr_driver->getTexture(FileManager::TEXTURE, - "displace.png")->getOpenGLTextureName(); - }, RP_RESERVED); + SPShaderManager::addPrefilledTexturesToShader(shader, + {std::make_tuple("displacement_tex", "displace.png", false/*srgb*/, + ST_BILINEAR)}, RP_RESERVED); shader->addCustomPrefilledTextures(ST_BILINEAR, GL_TEXTURE_2D, "mask_tex", []()->GLuint { - return g_stk_sbr->getRTTs()->getFBO(FBO_TMP1_WITH_DS).getRTT()[0]; + return g_stk_sbr->getRTTs()->getFBO(FBO_RGBA_1).getRTT()[0]; }, RP_RESERVED); shader->addCustomPrefilledTextures(ST_BILINEAR, GL_TEXTURE_2D, "color_tex", []()->GLuint @@ -221,7 +220,7 @@ void displaceShaderInit(SPShader* shader) g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).bind(); glStencilFunc(GL_EQUAL, 1, 0xFF); g_stk_sbr->getPostProcessing()->renderPassThrough - (g_stk_sbr->getRTTs()->getFBO(FBO_DISPLACE).getRTT()[0], + (g_stk_sbr->getRTTs()->getFBO(FBO_TMP1_WITH_DS).getRTT()[0], g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getWidth(), g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getHeight()); glDisable(GL_STENCIL_TEST); @@ -327,7 +326,7 @@ void loadShaders() // Displace shader is not specifiable in XML due to complex callback std::shared_ptr sps; - if (CVS->isDefferedEnabled()) + if (CVS->isDeferredEnabled()) { // This displace shader will be drawn the last in transparent pass sps = std::make_shared("displace", displaceShaderInit, @@ -345,7 +344,7 @@ void loadShaders() // ======================================================================== // Glow shader // ======================================================================== - if (CVS->isDefferedEnabled()) + if (CVS->isDeferredEnabled()) { sps = std::make_shared ("sp_glow_shader", [](SPShader* shader) @@ -357,7 +356,7 @@ void loadShaders() shader->linkShaderFiles(RP_1ST); shader->use(RP_1ST); shader->addBasicUniforms(RP_1ST); - shader->addUniform("col", typeid(irr::video::SColorf), RP_1ST); + shader->addAllUniforms(RP_1ST); }); SPShaderManager::get()->addSPShader(sps->getName(), sps); g_glow_shader = sps.get(); @@ -380,6 +379,7 @@ void loadShaders() shader->linkShaderFiles(RP_1ST); shader->use(RP_1ST); shader->addBasicUniforms(RP_1ST); + shader->addAllUniforms(RP_1ST); shader->addAllTextures(RP_1ST); }); SPShaderManager::get()->addSPShader(sps->getName(), sps); @@ -740,7 +740,7 @@ void prepareDrawCalls() g_skinning_mesh.clear(); mathPlaneFrustumf(g_frustums[0], irr_driver->getProjViewMatrix()); g_handle_shadow = Track::getCurrentTrack() && - Track::getCurrentTrack()->hasShadows() && CVS->isDefferedEnabled() && + Track::getCurrentTrack()->hasShadows() && CVS->isDeferredEnabled() && CVS->isShadowEnabled(); if (g_handle_shadow) @@ -793,9 +793,10 @@ void addObject(SPMeshNode* node) core::aabbox3df bb = mb->getBoundingBox(); model_matrix.transformBoxEx(bb); std::vector discard; - const bool handle_shadow = + const bool handle_shadow = node->isInShadowPass() && g_handle_shadow && shader->hasShader(RP_SHADOW); discard.resize((handle_shadow ? 5 : 1), false); + for (int dc_type = 0; dc_type < (handle_shadow ? 5 : 1); dc_type++) { for (int i = 0; i < 24; i += 4) @@ -921,14 +922,15 @@ void addObject(SPMeshNode* node) } mb->addInstanceData(id, (DrawCallType)dc_type); if (UserConfigParams::m_glow && node->hasGlowColor() && - CVS->isDefferedEnabled() && dc_type == DCT_NORMAL) + CVS->isDeferredEnabled() && dc_type == DCT_NORMAL) { video::SColorf gc = node->getGlowColor(); unsigned key = gc.toSColor().color; auto ret = g_glow_meshes.find(key); if (ret == g_glow_meshes.end()) { - g_glow_meshes[key] = std::make_pair(gc, + g_glow_meshes[key] = std::make_pair( + core::vector3df(gc.r, gc.g, gc.b), std::unordered_set()); } g_glow_meshes.at(key).second.insert(mb); @@ -1216,7 +1218,7 @@ void uploadAll() } // ---------------------------------------------------------------------------- -void drawNormal() +void drawSPDebugView() { if (g_normal_visualizer == NULL) { diff --git a/src/graphics/sp/sp_base.hpp b/src/graphics/sp/sp_base.hpp index d6284bf2b..dd41a672f 100644 --- a/src/graphics/sp/sp_base.hpp +++ b/src/graphics/sp/sp_base.hpp @@ -92,6 +92,7 @@ extern unsigned sp_solid_poly_count; extern unsigned sp_shadow_poly_count; extern int sp_cur_shadow_cascade; extern bool sp_culling; +extern bool sp_debug_view; extern unsigned sp_cur_player; extern unsigned sp_cur_buf_id[MAX_PLAYER_COUNT]; extern irr::core::vector3df sp_wind_dir; @@ -112,7 +113,7 @@ void draw(RenderPass, DrawCallType dct = DCT_NORMAL); // ---------------------------------------------------------------------------- void drawGlow(); // ---------------------------------------------------------------------------- -void drawNormal(); +void drawSPDebugView(); // ---------------------------------------------------------------------------- void addObject(SPMeshNode*); // ---------------------------------------------------------------------------- diff --git a/src/graphics/sp/sp_mesh_buffer.cpp b/src/graphics/sp/sp_mesh_buffer.cpp index 124ecabd5..cd4fde30f 100644 --- a/src/graphics/sp/sp_mesh_buffer.cpp +++ b/src/graphics/sp/sp_mesh_buffer.cpp @@ -167,7 +167,7 @@ void SPMeshBuffer::uploadGLMesh() offset += 4; video::SColor vc = m_vertices[i].m_color; - if (CVS->isDefferedEnabled()) + if (CVS->isDeferredEnabled()) { vc.setRed(srgb255ToLinear(vc.getRed())); vc.setGreen(srgb255ToLinear(vc.getGreen())); diff --git a/src/graphics/sp/sp_mesh_node.cpp b/src/graphics/sp/sp_mesh_node.cpp index ef066d0e0..3e6bd026f 100644 --- a/src/graphics/sp/sp_mesh_node.cpp +++ b/src/graphics/sp/sp_mesh_node.cpp @@ -48,6 +48,7 @@ SPMeshNode::SPMeshNode(IAnimatedMesh* mesh, ISceneNode* parent, m_first_render_info = render_info; m_animated = false; m_skinning_offset = -32768; + m_is_in_shadowpass = true; } // SPMeshNode // ---------------------------------------------------------------------------- diff --git a/src/graphics/sp/sp_mesh_node.hpp b/src/graphics/sp/sp_mesh_node.hpp index 6396d26ae..1565024f2 100644 --- a/src/graphics/sp/sp_mesh_node.hpp +++ b/src/graphics/sp/sp_mesh_node.hpp @@ -50,6 +50,8 @@ private: bool m_animated; + bool m_is_in_shadowpass; + std::vector > m_skinning_matrices; video::SColorf m_glow_color; @@ -115,6 +117,13 @@ public: // ------------------------------------------------------------------------ bool getAnimationState() const { return m_animated; } // ------------------------------------------------------------------------ + bool isInShadowPass() const { return m_is_in_shadowpass; } + // ------------------------------------------------------------------------ + void setInShadowPass(const bool is_in_shadowpass) + { + m_is_in_shadowpass = is_in_shadowpass; + } + // ------------------------------------------------------------------------ SPShader* getShader(unsigned mesh_buffer_id) const; // ------------------------------------------------------------------------ const std::array* getSkinningMatrices() const diff --git a/src/graphics/sp/sp_shader.cpp b/src/graphics/sp/sp_shader.cpp index 0101a3cde..c72aaa3bd 100644 --- a/src/graphics/sp/sp_shader.cpp +++ b/src/graphics/sp/sp_shader.cpp @@ -16,15 +16,19 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "graphics/sp/sp_shader.hpp" +#include "config/user_config.hpp" #include "graphics/central_settings.hpp" #include "graphics/shader_files_manager.hpp" #include "graphics/sp/sp_base.hpp" #include "graphics/sp/sp_uniform_assigner.hpp" +#include "guiengine/message_queue.hpp" #include "utils/string_utils.hpp" +#include + namespace SP { -std::unordered_map > +const std::map > g_prefilled_names = { #ifdef USE_GLES2 @@ -81,6 +85,13 @@ void SPShader::linkShaderFiles(RenderPass rp) } if (result == GL_FALSE) { + if (UserConfigParams::m_artist_debug_mode) + { + core::stringw err = StringUtils::insertValues(L"Shader %s failed" + " to link, check stdout.log or console for details", + m_name.c_str()); + MessageQueue::add(MessageQueue::MT_ERROR, err); + } glDeleteProgram(m_program[rp]); m_program[rp] = 0; } @@ -194,20 +205,49 @@ void SPShader::bindTextures(const std::array& tex, } // bindTextures // ---------------------------------------------------------------------------- -void SPShader::addUniform(const std::string& name, const std::type_index& ti, - RenderPass rp) +void SPShader::addAllUniforms(RenderPass rp) { #ifndef SERVER_ONLY - const char* s = name.c_str(); - GLuint location = glGetUniformLocation(m_program[rp], s); - if (location == GL_INVALID_INDEX) + GLint total_uniforms; + glGetProgramiv(m_program[rp], GL_ACTIVE_UNIFORMS, &total_uniforms); + static const std::map supported_types = + { + { GL_INT, std::type_index(typeid(int)) }, + { GL_FLOAT, std::type_index(typeid(float)) }, + { GL_FLOAT_MAT4, std::type_index(typeid(irr::core::matrix4)) }, + { GL_FLOAT_VEC4, std::type_index(typeid(std::array)) }, + { GL_FLOAT_VEC3, std::type_index(typeid(irr::core::vector3df)) }, + { GL_FLOAT_VEC2, std::type_index(typeid(irr::core::vector2df)) } + }; + + for (int i = 0; i < total_uniforms; i++) { - Log::warn("SPShader", "Missing uniform %s in shader files.", s); - return; + GLint size; + GLenum type; + char name[100] = {}; + glGetActiveUniform(m_program[rp], i, 99, NULL, &size, &type, name); + if (size != 1) + { + Log::debug("SPShader", "Array of uniforms is not supported in" + " shader %s for %s.", m_name.c_str(), name); + continue; + } + auto ret = supported_types.find(type); + if (ret == supported_types.end()) + { + Log::debug("SPShader", "%d type not supported", (unsigned)type); + continue; + } + GLuint location = glGetUniformLocation(m_program[rp], name); + if (location == GL_INVALID_INDEX) + { + Log::debug("SPShader", "%s uniform not found", name); + continue; + } + m_uniforms[rp][name] = new SPUniformAssigner(ret->second, location); } - m_uniforms[rp][name] = new SPUniformAssigner(ti, location); #endif -} // addUniform +} // addAllUniforms // ---------------------------------------------------------------------------- void SPShader::setUniformsPerObject(SPPerObjectUniform* sppou, @@ -271,7 +311,7 @@ void SPShader::unload() bool SPShader::isSrgbForTextureLayer(unsigned layer) const { #ifndef SERVER_ONLY - if (!CVS->isDefferedEnabled()) + if (!CVS->isDeferredEnabled()) { return false; } diff --git a/src/graphics/sp/sp_shader.hpp b/src/graphics/sp/sp_shader.hpp index c1b8ba48d..aa5552c16 100644 --- a/src/graphics/sp/sp_shader.hpp +++ b/src/graphics/sp/sp_shader.hpp @@ -135,6 +135,8 @@ public: // ------------------------------------------------------------------------ bool hasShader(RenderPass rp) { return m_program[rp] != 0; } // ------------------------------------------------------------------------ + GLuint getShaderProgram(RenderPass rp) { return m_program[rp]; } + // ------------------------------------------------------------------------ void use(RenderPass rp = RP_1ST) { if (m_use_function[rp] != NULL) @@ -161,6 +163,8 @@ public: // ------------------------------------------------------------------------ void addAllTextures(RenderPass rp = RP_1ST); // ------------------------------------------------------------------------ + void addAllUniforms(RenderPass rp = RP_1ST); + // ------------------------------------------------------------------------ void addCustomPrefilledTextures(SamplerType st, GLuint texture_type, const std::string& name, std::function func, @@ -190,9 +194,6 @@ public: SPUniformAssigner* getUniformAssigner(const std::string& name, RenderPass rp = RP_1ST) const; // ------------------------------------------------------------------------ - void addUniform(const std::string& name, const std::type_index& ti, - RenderPass rp = RP_1ST); - // ------------------------------------------------------------------------ void setUniformsPerObject(SPPerObjectUniform* sppou, std::vector* ua_used, RenderPass rp = RP_1ST); diff --git a/src/graphics/sp/sp_shader_manager.cpp b/src/graphics/sp/sp_shader_manager.cpp index 631faf42a..e4b491583 100644 --- a/src/graphics/sp/sp_shader_manager.cpp +++ b/src/graphics/sp/sp_shader_manager.cpp @@ -37,16 +37,6 @@ SPShaderManager* SPShaderManager::m_spsm = NULL; SPShaderManager::SPShaderManager() { #ifndef SERVER_ONLY - m_official_types = - { - { "int", std::type_index(typeid(int)) }, - { "float", std::type_index(typeid(float)) }, - { "mat4", std::type_index(typeid(irr::core::matrix4)) }, - { "vec4", std::type_index(typeid(std::array)) }, - { "vec3", std::type_index(typeid(irr::core::vector3df)) }, - { "vec2", std::type_index(typeid(irr::core::vector2df)) } - }; - m_official_sampler_types = { { "nearest", ST_NEAREST }, @@ -138,13 +128,7 @@ SPShaderManager::SPShaderManager() SPShaderManager::~SPShaderManager() { m_official_shaders.clear(); - removeUnusedShaders(); -#ifdef DEBUG - for (auto p : m_shaders) - { - Log::error("SPShaderManager", "%s > 1 ref_count", p.first.c_str()); - } -#endif + m_shaders.clear(); } // ~SPShaderManager // ---------------------------------------------------------------------------- @@ -211,7 +195,7 @@ void SPShaderManager::loadEachShader(const std::string& file_name) std::array pi; loadPassInfo(xml->getNode("first-pass"), pi[0]); - if (!si.m_transparent_shader && CVS->isDefferedEnabled()) + if (!si.m_transparent_shader && CVS->isDeferredEnabled()) { loadPassInfo(xml->getNode("shadow-pass"), pi[1]); } @@ -221,7 +205,7 @@ void SPShaderManager::loadEachShader(const std::string& file_name) " file %s", file_name.c_str()); return; } - if (!si.m_fallback_name.empty() && !CVS->isDefferedEnabled()) + if (!si.m_fallback_name.empty() && !CVS->isDeferredEnabled()) { std::shared_ptr fallback_shader = getSPShader(si.m_fallback_name); @@ -319,32 +303,6 @@ void SPShaderManager::loadPassInfo(const XMLNode* pass, PassInfo& pi) pass->get("skinned-mesh-shader", &pi.m_skinned_mesh_shader); pi.m_skinned_mesh_shader = getShaderFullPath(pi.m_skinned_mesh_shader); - const XMLNode* uniforms = pass->getNode("uniforms"); - if (uniforms) - { - for (unsigned i = 0; i < uniforms->getNumNodes(); i++) - { - const XMLNode* uniform = uniforms->getNode(i); - if (uniform->getName() == "uniform") - { - std::string name, type; - uniform->get("name", &name); - uniform->get("type", &type); - if (!name.empty() && !type.empty() && - m_official_types.find(type) != m_official_types.end()) - { - pi.m_uniforms.emplace_back(name, - m_official_types.at(type)); - } - else - { - Log::error("SPShaderManager", "Invalid uniform type %s", - type.c_str()); - } - } - } - } - const XMLNode* prefilled_textures = pass->getNode("prefilled-textures"); if (prefilled_textures) { @@ -362,7 +320,7 @@ void SPShaderManager::loadPassInfo(const XMLNode* pass, PassInfo& pi) #ifndef SERVER_ONLY if (!srgb_props.empty()) { - srgb = srgb_props == "Y" && CVS->isDefferedEnabled(); + srgb = srgb_props == "Y" && CVS->isDeferredEnabled(); } #endif prefilled_texture->get("sampler", &sampler_props); @@ -414,7 +372,7 @@ std::shared_ptr SPShaderManager::buildSPShader(const ShaderInfo& si, std::shared_ptr sps; #ifndef SERVER_ONLY sps = std::make_shared(si.m_shader_name, - [pi, ua, skinned](SPShader* shader) + [this, pi, ua, skinned](SPShader* shader) { // First pass assert(!pi[0].m_vertex_shader.empty() || @@ -437,7 +395,7 @@ std::shared_ptr SPShaderManager::buildSPShader(const ShaderInfo& si, shader->linkShaderFiles(RP_1ST); shader->use(RP_1ST); shader->addBasicUniforms(RP_1ST); - addUniformsToShader(shader, pi[0].m_uniforms, RP_1ST); + shader->addAllUniforms(RP_1ST); if (pi[0].m_use_function) { shader->setUseFunction(pi[0].m_use_function, RP_1ST); @@ -472,7 +430,7 @@ std::shared_ptr SPShaderManager::buildSPShader(const ShaderInfo& si, shader->linkShaderFiles(RP_SHADOW); shader->use(RP_SHADOW); shader->addBasicUniforms(RP_SHADOW); - addUniformsToShader(shader, pi[1].m_uniforms, RP_SHADOW); + shader->addAllUniforms(RP_SHADOW); if (pi[1].m_use_function) { shader->setUseFunction(pi[1].m_use_function, RP_SHADOW); @@ -490,17 +448,6 @@ std::shared_ptr SPShaderManager::buildSPShader(const ShaderInfo& si, return sps; } // buildSPShader -// ---------------------------------------------------------------------------- -void SPShaderManager::addUniformsToShader(SPShader* s, - const std::vector >& u, - RenderPass rp) -{ - for (auto& p : u) - { - s->addUniform(p.first, p.second, rp); - } -} // addUniformsToShader - // ---------------------------------------------------------------------------- void SPShaderManager::addPrefilledTexturesToShader(SPShader* s, const std::vector > diff --git a/src/graphics/sp/sp_shader_manager.hpp b/src/graphics/sp/sp_shader_manager.hpp index 3695a2e6c..dca4aeb50 100644 --- a/src/graphics/sp/sp_shader_manager.hpp +++ b/src/graphics/sp/sp_shader_manager.hpp @@ -41,7 +41,6 @@ enum RenderPass: unsigned int; class SPShaderManager : public NoCopy { public: - struct PassInfo { std::function m_use_function; @@ -54,8 +53,6 @@ public: std::string m_skinned_mesh_shader; - std::vector > m_uniforms; - std::vector > m_prefilled_textures; }; @@ -87,8 +84,6 @@ private: std::vector > m_official_shaders; - std::unordered_map m_official_types; - std::unordered_map m_official_sampler_types; std::unordered_map > @@ -113,14 +108,6 @@ private: const std::array& pi, const UniformAssigners& ua, bool skinned); - // ------------------------------------------------------------------------ - static void addUniformsToShader(SPShader* s, - const std::vector >& u, - RenderPass rp); - // ------------------------------------------------------------------------ - static void addPrefilledTexturesToShader(SPShader* s, - const std::vector >& t, RenderPass rp); public: // ------------------------------------------------------------------------ @@ -139,6 +126,10 @@ public: m_spsm = NULL; } // ------------------------------------------------------------------------ + static void addPrefilledTexturesToShader(SPShader* s, + const std::vector >& t, RenderPass rp); + // ------------------------------------------------------------------------ SPShaderManager(); // ------------------------------------------------------------------------ ~SPShaderManager(); diff --git a/src/graphics/sp/sp_uniform_assigner.hpp b/src/graphics/sp/sp_uniform_assigner.hpp index f37089d93..4ceddbd3f 100644 --- a/src/graphics/sp/sp_uniform_assigner.hpp +++ b/src/graphics/sp/sp_uniform_assigner.hpp @@ -53,7 +53,7 @@ public: SPUniformAssigner(const std::type_index& ti, GLuint location) : m_location(location), m_type(ti), m_assigned(false) {} // ------------------------------------------------------------------------ - bool rumtimeChecking(const std::type_info& ti) const + bool runtimeChecking(const std::type_info& ti) const { #ifdef DEBUG if (m_type != ti) @@ -66,9 +66,69 @@ public: return true; } // ------------------------------------------------------------------------ + void getValue(const GLuint& p, irr::core::matrix4& mat) const + { + if (runtimeChecking(typeid(mat))) + { +#ifndef SERVER_ONLY + glGetUniformfv(p, m_location, mat.pointer()); +#endif + } + } + // ------------------------------------------------------------------------ + void getValue(const GLuint& p, std::array& v) const + { + if (runtimeChecking(typeid(v))) + { +#ifndef SERVER_ONLY + glGetUniformfv(p, m_location, v.data()); +#endif + } + } + // ------------------------------------------------------------------------ + void getValue(const GLuint& p, irr::core::vector3df& v) const + { + if (runtimeChecking(typeid(v))) + { +#ifndef SERVER_ONLY + glGetUniformfv(p, m_location, &v.X); +#endif + } + } + // ------------------------------------------------------------------------ + void getValue(const GLuint& p, irr::core::vector2df& v) const + { + if (runtimeChecking(typeid(v))) + { +#ifndef SERVER_ONLY + glGetUniformfv(p, m_location, &v.X); +#endif + } + } + // ------------------------------------------------------------------------ + void getValue(const GLuint& p, float& v) const + { + if (runtimeChecking(typeid(v))) + { +#ifndef SERVER_ONLY + glGetUniformfv(p, m_location, &v); +#endif + } + } + // ------------------------------------------------------------------------ + void getValue(const GLuint& p, int& v) const + { + if (runtimeChecking(typeid(v))) + { +#ifndef SERVER_ONLY + glGetUniformiv(p, m_location, &v); +#endif + } + } + // ------------------------------------------------------------------------ void setValue(const irr::core::matrix4& mat) const { - if (rumtimeChecking(typeid(mat))) + if (runtimeChecking(typeid(mat))) { #ifndef SERVER_ONLY glUniformMatrix4fv(m_location, 1, GL_FALSE, mat.pointer()); @@ -79,29 +139,18 @@ public: // ------------------------------------------------------------------------ void setValue(const std::array& v) const { - if (rumtimeChecking(typeid(v))) + if (runtimeChecking(typeid(v))) { #ifndef SERVER_ONLY glUniform4f(m_location, v[0], v[1], v[2], v[3]); m_assigned = true; -#endif - } - } - // ------------------------------------------------------------------------ - void setValue(const irr::video::SColorf& col) const - { - if (rumtimeChecking(typeid(col))) - { -#ifndef SERVER_ONLY - glUniform3f(m_location, col.r, col.g, col.b); - m_assigned = true; #endif } } // ------------------------------------------------------------------------ void setValue(const irr::core::vector3df& v) const { - if (rumtimeChecking(typeid(v))) + if (runtimeChecking(typeid(v))) { #ifndef SERVER_ONLY glUniform3f(m_location, v.X, v.Y, v.Z); @@ -112,29 +161,18 @@ public: // ------------------------------------------------------------------------ void setValue(const irr::core::vector2df& v) const { - if (rumtimeChecking(typeid(v))) + if (runtimeChecking(typeid(v))) { #ifndef SERVER_ONLY glUniform2f(m_location, v.X, v.Y); m_assigned = true; -#endif - } - } - // ------------------------------------------------------------------------ - void setValue(const irr::core::dimension2df& v) const - { - if (rumtimeChecking(typeid(v))) - { -#ifndef SERVER_ONLY - glUniform2f(m_location, v.Width, v.Height); - m_assigned = true; #endif } } // ------------------------------------------------------------------------ void setValue(float v) const { - if (rumtimeChecking(typeid(v))) + if (runtimeChecking(typeid(v))) { #ifndef SERVER_ONLY glUniform1f(m_location, v); @@ -145,7 +183,7 @@ public: // ------------------------------------------------------------------------ void setValue(int v) const { - if (rumtimeChecking(typeid(v))) + if (runtimeChecking(typeid(v))) { #ifndef SERVER_ONLY glUniform1i(m_location, v); @@ -160,37 +198,31 @@ public: { m_assigned = false; #ifndef SERVER_ONLY - if (m_type == typeid(irr::core::matrix4)) + if (m_type == typeid(int)) { - static const char zeroes[64] = {}; - glUniformMatrix4fv(m_location, 1, GL_FALSE, (float*)zeroes); - } - else if (m_type == typeid(irr::video::SColor)) - { - glUniform4i(m_location, 0, 0, 0, 0); - } - else if (m_type == typeid(irr::video::SColorf) || - m_type == typeid(irr::core::vector3df)) - { - glUniform3f(m_location, 0.0f, 0.0f, 0.0f); - } - else if (m_type == typeid(irr::core::vector2df) || - m_type == typeid(irr::core::dimension2df)) - { - glUniform2f(m_location, 0.0f, 0.0f); + glUniform1i(m_location, 0); } else if (m_type == typeid(float)) { glUniform1f(m_location, 0.0f); } - else if (m_type == typeid(int)) + else if (m_type == typeid(irr::core::matrix4)) { - glUniform1i(m_location, 0); + static const char zeroes[64] = {}; + glUniformMatrix4fv(m_location, 1, GL_FALSE, (float*)zeroes); } else if (m_type == typeid(std::array)) { glUniform4f(m_location, 0.0f, 0.0f, 0.0f,0.0f); } + else if (m_type == typeid(irr::core::vector3df)) + { + glUniform3f(m_location, 0.0f, 0.0f, 0.0f); + } + else if (m_type == typeid(irr::core::vector2df)) + { + glUniform2f(m_location, 0.0f, 0.0f); + } #endif } } diff --git a/src/graphics/stk_text_billboard.cpp b/src/graphics/stk_text_billboard.cpp index 583f32705..765dd6631 100644 --- a/src/graphics/stk_text_billboard.cpp +++ b/src/graphics/stk_text_billboard.cpp @@ -35,14 +35,14 @@ STKTextBillboard::STKTextBillboard(const video::SColor& color_top, { using namespace SP; m_color_top = color_top; - if (CVS->isDefferedEnabled()) + if (CVS->isDeferredEnabled()) { m_color_top.setRed(srgb255ToLinear(m_color_top.getRed())); m_color_top.setGreen(srgb255ToLinear(m_color_top.getGreen())); m_color_top.setBlue(srgb255ToLinear(m_color_top.getBlue())); } m_color_bottom = color_bottom; - if (CVS->isDefferedEnabled()) + if (CVS->isDeferredEnabled()) { video::SColorf tmp(m_color_bottom); m_color_bottom.setRed(srgb255ToLinear(m_color_bottom.getRed())); diff --git a/src/graphics/stk_texture.cpp b/src/graphics/stk_texture.cpp index 4ff203081..efe8cb877 100644 --- a/src/graphics/stk_texture.cpp +++ b/src/graphics/stk_texture.cpp @@ -18,9 +18,11 @@ #include "graphics/stk_texture.hpp" #include "config/user_config.hpp" #include "graphics/central_settings.hpp" +#include "graphics/irr_driver.hpp" #include "graphics/graphics_restrictions.hpp" #include "graphics/stk_tex_manager.hpp" -#include "graphics/irr_driver.hpp" +#include "graphics/material.hpp" +#include "graphics/material_manager.hpp" #include "modes/profile_world.hpp" #include "utils/log.hpp" #include "utils/string_utils.hpp" @@ -40,7 +42,7 @@ STKTexture::STKTexture(const std::string& path, TexConfig* tc, bool no_upload) if (m_tex_config) { if (ProfileWorld::isNoGraphics() || - (!CVS->isDefferedEnabled()) || !CVS->isGLSL()) + (!CVS->isDeferredEnabled()) || !CVS->isGLSL()) { m_tex_config->m_srgb = false; } @@ -123,6 +125,7 @@ void STKTexture::reload(bool no_upload, uint8_t* preload_data, return; } orig_img = resizeImage(orig_img, &m_orig_size, &m_size); + applyMask(orig_img); data = orig_img ? (uint8_t*)orig_img->lock() : NULL; } @@ -214,7 +217,7 @@ void STKTexture::formatConversion(uint8_t* data, unsigned int* format, { alpha /= 255.0f; - if (CVS->isDefferedEnabled()) + if (CVS->isDeferredEnabled()) { alpha = pow(alpha, 1.0f / 2.2f); } @@ -279,6 +282,46 @@ video::IImage* STKTexture::resizeImage(video::IImage* orig_img, return image; } // resizeImage +// ---------------------------------------------------------------------------- +void STKTexture::applyMask(video::IImage* orig_img) +{ +#ifndef SERVER_ONLY + Material* material = NULL; + if (material_manager) + { + material = material_manager->getMaterialFor(this); + } + if (material && !material->getAlphaMask().empty()) + { + video::IImage* converted_mask = irr_driver->getVideoDriver() + ->createImageFromFile(material->getAlphaMask().c_str()); + if (converted_mask == NULL) + { + Log::warn("STKTexture", "Applying mask failed for '%s'!", + material->getAlphaMask().c_str()); + return; + } + converted_mask = resizeImage(converted_mask); + if (converted_mask->lock()) + { + const core::dimension2du& dim = orig_img->getDimension(); + for (unsigned int x = 0; x < dim.Width; x++) + { + for (unsigned int y = 0; y < dim.Height; y++) + { + video::SColor col = orig_img->getPixel(x, y); + video::SColor alpha = converted_mask->getPixel(x, y); + col.setAlpha(alpha.getRed()); + orig_img->setPixel(x, y, col, false); + } // for y + } // for x + } + converted_mask->unlock(); + converted_mask->drop(); + } +#endif // !SERVER_ONLY +} // applyMask + //----------------------------------------------------------------------------- bool STKTexture::hasMipMaps() const { diff --git a/src/graphics/stk_texture.hpp b/src/graphics/stk_texture.hpp index 4f8beddfc..4aa398e7a 100644 --- a/src/graphics/stk_texture.hpp +++ b/src/graphics/stk_texture.hpp @@ -54,6 +54,9 @@ private: bool isSrgb() const; // ------------------------------------------------------------------------ bool isPremulAlpha() const; + // ------------------------------------------------------------------------ + void applyMask(video::IImage* orig_img); + // ------------------------------------------------------------------------ public: // ------------------------------------------------------------------------ diff --git a/src/guiengine/skin.cpp b/src/guiengine/skin.cpp index 012d3778b..e49043c7d 100644 --- a/src/guiengine/skin.cpp +++ b/src/guiengine/skin.cpp @@ -912,6 +912,19 @@ void Skin::drawRibbon(const core::recti &rect, Widget* widget, { } // drawRibbon +SColorf GetPlayerColor(int player_id) +{ + + SColorHSL col = { 0,100,50 }; + col.Hue += (360 / 4) * (player_id % 4); + int color_id = player_id % 4; + SColorf color_rgb = { 0,0,0,1 }; + + + col.Saturation = col.Saturation * (1.0F / (floor(player_id / 4) + 1) ); + col.toRGB(color_rgb); + return color_rgb; +} // ---------------------------------------------------------------------------- /** * @param focused whether this element is focus by the master player (whether @@ -1069,8 +1082,8 @@ void Skin::drawRibbonChild(const core::recti &rect, Widget* widget, } } - // if multiple player selected the same ribbon item, we need to know - // to make it visible + + //Handle drawing for the first player int nPlayersOnThisItem = 0; if (mark_focused) @@ -1086,36 +1099,36 @@ void Skin::drawRibbonChild(const core::recti &rect, Widget* widget, const float dt = GUIEngine::getLatestDt(); - glow_effect += dt*3; + glow_effect += dt * 3; if (glow_effect > 6.2832f /* 2*PI */) glow_effect -= 6.2832f; - grow = (int)(45 + 10*sin(glow_effect)); + grow = (int)(45 + 10 * sin(glow_effect)); const int glow_center_x = rect.UpperLeftCorner.X - + rect.getWidth()/2; + + rect.getWidth() / 2; const int glow_center_y = rect.UpperLeftCorner.Y - + rect.getHeight() - 5; + + rect.getHeight() - 5; ITexture* tex_ficonhighlight = SkinConfig::m_render_params["focusHalo::neutral"] - .getImage(); + .getImage(); const int texture_w = tex_ficonhighlight->getSize().Width; const int texture_h = tex_ficonhighlight->getSize().Height; - core::recti source_area(0, 0, texture_w,texture_h); + core::recti source_area(0, 0, texture_w, texture_h); const core::recti rect2(glow_center_x - 45 - grow, - glow_center_y - 25 - grow/2, - glow_center_x + 45 + grow, - glow_center_y + 25 + grow/2); + glow_center_y - 25 - grow / 2, + glow_center_x + 45 + grow, + glow_center_y + 25 + grow / 2); draw2DImage(tex_ficonhighlight, rect2, - source_area, - /*clipping*/ 0, - /*color*/ 0, - /*alpha*/true ); + source_area, + /*clipping*/ 0, + /*color*/ 0, + /*alpha*/true); } // if we're not using glow, draw square focus instead else @@ -1129,80 +1142,51 @@ void Skin::drawRibbonChild(const core::recti &rect, Widget* widget, return; drawBoxFromStretchableTexture(parentRibbonWidget, rect, - SkinConfig::m_render_params["squareFocusHalo::neutral"]); + SkinConfig::m_render_params["squareFocusHalo::neutral"]); nPlayersOnThisItem++; } } // end if mark_focused - // ---- Draw selection for other players than player 1 - if (parentRibbon->isFocusedForPlayer(1) && - parentRibbon->getSelectionIDString(1) == - widget->m_properties[PROP_ID]) + //Handle drawing for everyone else + for (int i = 1; i < MAX_PLAYER_COUNT; i++) { - if (nPlayersOnThisItem > 0) + // ---- Draw selection for other players than player 1 + if (parentRibbon->isFocusedForPlayer(i) && + parentRibbon->getSelectionIDString(i) == + widget->m_properties[PROP_ID]) { - core::recti rect2 = rect; - const int enlarge = nPlayersOnThisItem*6; - rect2.UpperLeftCorner.X -= enlarge; - rect2.UpperLeftCorner.Y -= enlarge; - rect2.LowerRightCorner.X += enlarge; - rect2.LowerRightCorner.Y += enlarge; - drawBoxFromStretchableTexture(parentRibbonWidget, rect2, - SkinConfig::m_render_params["squareFocusHalo2::neutral"]); - } - else - { - drawBoxFromStretchableTexture(parentRibbonWidget, rect, - SkinConfig::m_render_params["squareFocusHalo2::neutral"]); - } + short red_previous = parentRibbonWidget->m_skin_r; + short green_previous = parentRibbonWidget->m_skin_g; + short blue_previous = parentRibbonWidget->m_skin_b; - nPlayersOnThisItem++; - } + SColorf color_rgb = GetPlayerColor(i); + + parentRibbonWidget->m_skin_r = color_rgb.r * 255.0F; + parentRibbonWidget->m_skin_g = color_rgb.g * 255.0F; + parentRibbonWidget->m_skin_b = color_rgb.b * 255.0F; - if (parentRibbon->isFocusedForPlayer(2) && - parentRibbon->getSelectionIDString(2) == - widget->m_properties[PROP_ID]) - { - if (nPlayersOnThisItem > 0) - { - core::recti rect2 = rect; - const int enlarge = nPlayersOnThisItem*6; - rect2.UpperLeftCorner.X -= enlarge; - rect2.UpperLeftCorner.Y -= enlarge; - rect2.LowerRightCorner.X += enlarge; - rect2.LowerRightCorner.Y += enlarge; - drawBoxFromStretchableTexture(parentRibbonWidget, rect2, - SkinConfig::m_render_params["squareFocusHalo3::neutral"]); - } - else - { - drawBoxFromStretchableTexture(parentRibbonWidget, rect, - SkinConfig::m_render_params["squareFocusHalo3::neutral"]); - } - nPlayersOnThisItem++; - } + if (nPlayersOnThisItem > 0) + { + core::recti rect2 = rect; + const int enlarge = nPlayersOnThisItem * 6; + rect2.UpperLeftCorner.X -= enlarge; + rect2.UpperLeftCorner.Y -= enlarge; + rect2.LowerRightCorner.X += enlarge; + rect2.LowerRightCorner.Y += enlarge; - if (parentRibbon->isFocusedForPlayer(3) && - parentRibbon->getSelectionIDString(3) == - widget->m_properties[PROP_ID]) - { - if (nPlayersOnThisItem > 0) - { - core::recti rect2 = rect; - const int enlarge = nPlayersOnThisItem*6; - rect2.UpperLeftCorner.X -= enlarge; - rect2.UpperLeftCorner.Y -= enlarge; - rect2.LowerRightCorner.X += enlarge; - rect2.LowerRightCorner.Y += enlarge; - drawBoxFromStretchableTexture(parentRibbonWidget, rect2, - SkinConfig::m_render_params["squareFocusHalo4::neutral"]); + drawBoxFromStretchableTexture(parentRibbonWidget, rect2, + SkinConfig::m_render_params["squareFocusHaloBW::neutral"]); + } + else + { + drawBoxFromStretchableTexture(parentRibbonWidget, rect, + SkinConfig::m_render_params["squareFocusHaloBW::neutral"]); + } + parentRibbonWidget->m_skin_r = red_previous; + parentRibbonWidget->m_skin_g = green_previous; + parentRibbonWidget->m_skin_b = blue_previous; + nPlayersOnThisItem++; } - else - { - drawBoxFromStretchableTexture(parentRibbonWidget, rect, - SkinConfig::m_render_params["squareFocusHalo4::neutral"]); - } - nPlayersOnThisItem++; } drawIconButton(rect, widget, pressed, focused); @@ -1224,6 +1208,7 @@ void Skin::drawRibbonChild(const core::recti &rect, Widget* widget, #endif } // drawRibbonChild + // ---------------------------------------------------------------------------- /** * @param focused whether this element is focus by the master player (whether @@ -1256,25 +1241,28 @@ void Skin::drawSpinnerBody(const core::recti &rect, Widget* widget, } } + + BoxRenderParams* params; SpinnerWidget* q = dynamic_cast(widget); if(q->getUseBackgroundColor()) { int player_id=q->getSpinnerWidgetPlayerID(); - if(player_id==0) - params=&SkinConfig::m_render_params["spinner1::neutral"]; - else if(player_id==1) - params=&SkinConfig::m_render_params["spinner2::neutral"]; - else if(player_id==2) - params=&SkinConfig::m_render_params["spinner3::neutral"]; - else if(player_id==3) - params=&SkinConfig::m_render_params["spinner4::neutral"]; - else + + params = &SkinConfig::m_render_params[ + "spinner::deactivated"]; + + SColorf color_rgb = GetPlayerColor(player_id); + + widget->m_skin_r = color_rgb.r * 255.0F; + widget->m_skin_g = color_rgb.g * 255.0F; + widget->m_skin_b = color_rgb.b * 255.0F; + + if (player_id == 0) { - Log::fatal("Skin::drawSpinnerBody", "Unknown playerID (more than 4 players?)"); - // Silence compiler warning - params = NULL; + color_rgb = { 1,1,1,1 }; } + } else if (widget->m_deactivated) { @@ -1288,48 +1276,23 @@ void Skin::drawSpinnerBody(const core::recti &rect, Widget* widget, { params=&SkinConfig::m_render_params["spinner::neutral"]; } - if (widget->isFocusedForPlayer(0)) + for (int i = 1; i < MAX_PLAYER_COUNT + 1; i++) { - core::recti rect2 = rect; - rect2.UpperLeftCorner.X += 2; - rect2.UpperLeftCorner.Y -= 3; - rect2.LowerRightCorner.X -= 2; - rect2.LowerRightCorner.Y += 5; - drawBoxFromStretchableTexture(widget, rect2, - SkinConfig::m_render_params["squareFocusHalo::neutral"]); - + if (widget->isFocusedForPlayer(i - 1)) { + core::recti rect2 = rect; + rect2.UpperLeftCorner.X += 2; + rect2.UpperLeftCorner.Y -= 3; + rect2.LowerRightCorner.X -= 2; + rect2.LowerRightCorner.Y += 5; + + + drawBoxFromStretchableTexture(widget, rect2, + SkinConfig::m_render_params["squareFocusHaloBW::neutral"]); + //TODO add squarefocushalo0 + } } - else if (widget->isFocusedForPlayer(1)) - { - core::recti rect2 = rect; - rect2.UpperLeftCorner.X += 2; - rect2.UpperLeftCorner.Y -= 3; - rect2.LowerRightCorner.X -= 2; - rect2.LowerRightCorner.Y += 5; - drawBoxFromStretchableTexture(widget, rect2, - SkinConfig::m_render_params["squareFocusHalo2::neutral"]); - } - else if (widget->isFocusedForPlayer(2)) - { - core::recti rect2 = rect; - rect2.UpperLeftCorner.X += 2; - rect2.UpperLeftCorner.Y -= 3; - rect2.LowerRightCorner.X -= 2; - rect2.LowerRightCorner.Y += 5; - drawBoxFromStretchableTexture(widget, rect2, - SkinConfig::m_render_params["squareFocusHalo3::neutral"]); - } - else if (widget->isFocusedForPlayer(3)) - { - core::recti rect2 = rect; - rect2.UpperLeftCorner.X += 2; - rect2.UpperLeftCorner.Y -= 3; - rect2.LowerRightCorner.X -= 2; - rect2.LowerRightCorner.Y += 5; - drawBoxFromStretchableTexture(widget, rect2, - SkinConfig::m_render_params["squareFocusHalo4::neutral"]); - } + core::recti sized_rect = rect; if (m_dialog && m_dialog_size < 1.0f && widget->m_parent != NULL && @@ -2538,4 +2501,4 @@ void Skin::setSize (EGUI_DEFAULT_SIZE which, s32 texture_size) void Skin::setSpriteBank (IGUISpriteBank *bank) { m_fallback_skin->setSpriteBank(bank); -} // setSpriteBank +} // setSpriteBank \ No newline at end of file diff --git a/src/input/gamepad_device.cpp b/src/input/gamepad_device.cpp index 8fe7fb7ed..c7302d9ba 100644 --- a/src/input/gamepad_device.cpp +++ b/src/input/gamepad_device.cpp @@ -94,7 +94,7 @@ int GamePadDevice::getNumberOfButtons() const // ---------------------------------------------------------------------------- bool GamePadDevice::isButtonPressed(const int i) { - if (i < m_button_pressed.size()) + if (i < (int)m_button_pressed.size()) return m_button_pressed[i]; else return false; @@ -104,7 +104,7 @@ bool GamePadDevice::isButtonPressed(const int i) void GamePadDevice::setButtonPressed(const int i, bool isButtonPressed) { - if (i < m_button_pressed.size()) + if (i < (int)m_button_pressed.size()) m_button_pressed[i] = isButtonPressed; } // setButtonPressed diff --git a/src/io/assets_android.cpp b/src/io/assets_android.cpp index f8de5c8a0..e2964d4d7 100644 --- a/src/io/assets_android.cpp +++ b/src/io/assets_android.cpp @@ -73,22 +73,32 @@ void AssetsAndroid::init() paths.push_back("/sdcard/"); paths.push_back("/storage/sdcard0/"); paths.push_back("/storage/sdcard1/"); - paths.push_back("/data/data/org.supertuxkart.stk/files/"); + +#if !defined(ANDROID_PACKAGE_NAME) || !defined(ANDROID_APP_DIR_NAME) + #error +#endif + + std::string package_name = ANDROID_PACKAGE_NAME; + paths.push_back("/data/data/" + package_name + "/files/"); + + std::string app_dir_name = ANDROID_APP_DIR_NAME; // Check if STK data for current version is available somewhere for (std::string path : paths) { Log::info("AssetsAndroid", "Check data files in: %s", path.c_str()); - if (m_file_manager->fileExists(path + "/stk/data/" + version)) + if (m_file_manager->fileExists(path + "/" + app_dir_name + "/data/" + version)) { - m_stk_dir = path + "/stk"; + m_stk_dir = path + "/" + app_dir_name; break; } - - if (m_file_manager->fileExists(path + "/supertuxkart/data/" + version)) + + // Stk is an alias of supertuxkart for compatibility with older version. + if (app_dir_name == "supertuxkart" && + m_file_manager->fileExists(path + "/stk/data/" + version)) { - m_stk_dir = path + "/supertuxkart"; + m_stk_dir = path + "/stk"; break; } } @@ -103,16 +113,18 @@ void AssetsAndroid::init() Log::info("AssetsAndroid", "Check data files for different STK " "version in: %s", path.c_str()); - if (m_file_manager->fileExists(path + "/stk/.extracted")) + if (m_file_manager->fileExists(path + "/" + app_dir_name + "/.extracted")) { - m_stk_dir = path + "/stk"; + m_stk_dir = path + "/" + app_dir_name; needs_extract_data = true; break; } - if (m_file_manager->fileExists(path + "/supertuxkart/.extracted")) + // Stk is an alias of supertuxkart for compatibility with older version. + if (app_dir_name == "supertuxkart" && + m_file_manager->fileExists(path + "/stk/.extracted")) { - m_stk_dir = path + "/supertuxkart"; + m_stk_dir = path + "/stk"; needs_extract_data = true; break; } @@ -132,12 +144,12 @@ void AssetsAndroid::init() if (preferred_path.length() > 0) { - if (m_file_manager->checkAndCreateDirectoryP(preferred_path + - "/stk/data")) + if (m_file_manager->checkAndCreateDirectoryP(preferred_path + "/" + + app_dir_name + "/data")) { Log::info("AssetsAndroid", "Data directory created in: %s", preferred_path.c_str()); - m_stk_dir = preferred_path + "/stk"; + m_stk_dir = preferred_path + "/" + app_dir_name; needs_extract_data = true; } } @@ -149,11 +161,12 @@ void AssetsAndroid::init() { for (std::string path : paths) { - if (m_file_manager->checkAndCreateDirectoryP(path + "/stk/data")) + if (m_file_manager->checkAndCreateDirectoryP(path + "/" + + app_dir_name + "/data")) { Log::info("AssetsAndroid", "Data directory created in: %s", path.c_str()); - m_stk_dir = path + "/stk"; + m_stk_dir = path + "/" + app_dir_name; needs_extract_data = true; break; } @@ -415,10 +428,12 @@ void AssetsAndroid::removeData() #ifdef ANDROID if (m_stk_dir.length() == 0) return; + + std::string app_dir_name = ANDROID_APP_DIR_NAME; // Make sure that we are not accidentally removing wrong directory - if (m_stk_dir.find("/stk") == std::string::npos && - m_stk_dir.find("/supertuxkart") == std::string::npos) + if (m_stk_dir.find("/" + app_dir_name) == std::string::npos && + m_stk_dir.find("/stk") == std::string::npos) { Log::error("AssetsAndroid", "Invalid data directory: %s", m_stk_dir.c_str()); diff --git a/src/items/attachment.cpp b/src/items/attachment.cpp index f2c01d0b9..3629c6c7c 100644 --- a/src/items/attachment.cpp +++ b/src/items/attachment.cpp @@ -493,8 +493,11 @@ void Attachment::update(float dt) m_time_left -=dt; - bool is_shield = (m_type == ATTACH_BUBBLEGUM_SHIELD|| m_type == ATTACH_NOLOK_BUBBLEGUM_SHIELD); - float m_wanted_node_scale = is_shield ? std::max(1.0f, m_kart->getHighestPoint()*1.1f) : 1.0f; + bool is_shield = m_type == ATTACH_BUBBLEGUM_SHIELD || + m_type == ATTACH_NOLOK_BUBBLEGUM_SHIELD; + float m_wanted_node_scale = is_shield + ? std::max(1.0f, m_kart->getHighestPoint()*1.1f) + : 1.0f; int slow_flashes = 3; if (is_shield && m_time_left < slow_flashes) { @@ -507,22 +510,17 @@ void Attachment::update(float dt) flashes_per_second = 12; } - float mod = (int)(m_time_left * flashes_per_second * 2) % divisor; - if (mod < divisor / 2) - { - m_node->setVisible(false); - } - else - { - m_node->setVisible(true); - } + int mod = (int)(m_time_left * flashes_per_second * 2) % divisor; + m_node->setVisible(2*mod >= divisor); } if (m_node_scale < m_wanted_node_scale) { m_node_scale += dt*1.5f; - if (m_node_scale > m_wanted_node_scale) m_node_scale = m_wanted_node_scale; - m_node->setScale(core::vector3df(m_node_scale,m_node_scale,m_node_scale)); + if (m_node_scale > m_wanted_node_scale) + m_node_scale = m_wanted_node_scale; + m_node->setScale(core::vector3df(m_node_scale,m_node_scale, + m_node_scale) ); } if(m_plugin) @@ -585,7 +583,8 @@ void Attachment::update(float dt) } if(m_time_left<=0.0) { - HitEffect *he = new Explosion(m_kart->getXYZ(), "explosion", "explosion_bomb.xml"); + HitEffect *he = new Explosion(m_kart->getXYZ(), "explosion", + "explosion_bomb.xml" ); if(m_kart->getController()->isLocalPlayerController()) he->setLocalPlayerKartHit(); projectile_manager->addHitEffect(he); @@ -604,7 +603,8 @@ void Attachment::update(float dt) { m_time_left = 0.0f; if (m_bubble_explode_sound) m_bubble_explode_sound->deleteSFX(); - m_bubble_explode_sound = SFXManager::get()->createSoundSource("bubblegum_explode"); + m_bubble_explode_sound = + SFXManager::get()->createSoundSource("bubblegum_explode"); m_bubble_explode_sound->setPosition(m_kart->getXYZ()); m_bubble_explode_sound->play(); @@ -622,8 +622,10 @@ void Attachment::update(float dt) { normal.normalize(); - Vec3 pos = hit_point + m_kart->getTrans().getBasis() * Vec3(0, -0.05f, 0); - ItemManager::get()->newItem(Item::ITEM_BUBBLEGUM, pos, normal, m_kart); + Vec3 pos = hit_point + m_kart->getTrans().getBasis() + * Vec3(0, -0.05f, 0); + ItemManager::get()->newItem(Item::ITEM_BUBBLEGUM, pos, + normal, m_kart ); } } break; @@ -635,10 +637,15 @@ void Attachment::update(float dt) } // update // ---------------------------------------------------------------------------- +/** Return the additional weight of the attachment (some attachments slow + * karts down by also making them heavier). + */ float Attachment::weightAdjust() const { - return m_type == ATTACH_ANVIL ? m_kart->getKartProperties()->getAnvilWeight() : 0.0f; -} + return m_type == ATTACH_ANVIL + ? m_kart->getKartProperties()->getAnvilWeight() + : 0.0f; +} // weightAdjust // ---------------------------------------------------------------------------- /** Inform any eventual plugin when an animation is done. */ @@ -646,4 +653,4 @@ void Attachment::OnAnimationEnd(scene::IAnimatedMeshSceneNode* node) { if(m_plugin) m_plugin->onAnimationEnd(); -} +} // OnAnimationEnd diff --git a/src/items/rubber_band.cpp b/src/items/rubber_band.cpp index aa1a8289f..1d8623722 100644 --- a/src/items/rubber_band.cpp +++ b/src/items/rubber_band.cpp @@ -51,8 +51,8 @@ RubberBand::RubberBand(Plunger *plunger, AbstractKart *kart) { return; } - video::SColor color(77, 179, 0, 0); - if (CVS->isDefferedEnabled()) + video::SColor color(255, 179, 0, 0); + if (CVS->isDeferredEnabled()) { color.setRed(SP::srgb255ToLinear(color.getRed())); color.setGreen(SP::srgb255ToLinear(color.getGreen())); diff --git a/src/karts/controller/local_player_controller.cpp b/src/karts/controller/local_player_controller.cpp index d7912e08f..f5132bcec 100644 --- a/src/karts/controller/local_player_controller.cpp +++ b/src/karts/controller/local_player_controller.cpp @@ -55,16 +55,19 @@ * \param init_pos The start coordinates and heading of the kart. */ LocalPlayerController::LocalPlayerController(AbstractKart *kart, - StateManager::ActivePlayer *player) + const int local_playerID) : PlayerController(kart), m_sky_particles_emitter(NULL) { - m_player = player; - if(player) - player->setKart(kart); + + m_player = StateManager::get()->getActivePlayer(local_playerID); + if(m_player) + m_player->setKart(kart); // Keep a pointer to the camera to remove the need to search for // the right camera once per frame later. - Camera *camera = Camera::createCamera(kart); + + Camera *camera = Camera::createCamera(kart, local_playerID); + m_camera_index = camera->getIndex(); m_wee_sound = SFXManager::get()->createSoundSource("wee"); m_bzzt_sound = SFXManager::get()->getBuffer("bzzt"); diff --git a/src/karts/controller/local_player_controller.hpp b/src/karts/controller/local_player_controller.hpp index a17b3a032..d585b7bec 100644 --- a/src/karts/controller/local_player_controller.hpp +++ b/src/karts/controller/local_player_controller.hpp @@ -58,7 +58,7 @@ private: virtual void displayPenaltyWarning() OVERRIDE; public: LocalPlayerController(AbstractKart *kart, - StateManager::ActivePlayer *player); + const int local_playerID); ~LocalPlayerController(); void update (float) OVERRIDE; bool action (PlayerAction action, int value, diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index d624e8485..a03059c23 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -1208,7 +1208,7 @@ void Kart::eliminate() void Kart::update(float dt) { // Reset any instand speed increase in the bullet kart - m_vehicle->resetInstantSpeed(); + m_vehicle->setMinSpeed(0); // update star effect (call will do nothing if stars are not activated) m_stars_effect->update(dt); diff --git a/src/karts/kart_model.cpp b/src/karts/kart_model.cpp index 9f8271b2b..14aae2ec0 100644 --- a/src/karts/kart_model.cpp +++ b/src/karts/kart_model.cpp @@ -504,7 +504,7 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models, bool human_playe irr_driver->addMesh(obj.getModel(), "kart_headlight", parent, getRenderInfo()); #ifndef SERVER_ONLY - if (human_player && CVS->isGLSL() && CVS->isDefferedEnabled()) + if (human_player && CVS->isGLSL() && CVS->isDeferredEnabled()) { obj.setLight(headlight_model, each_energy, each_radius); } diff --git a/src/karts/kart_rewinder.cpp b/src/karts/kart_rewinder.cpp index c632b47dc..63fdcf343 100644 --- a/src/karts/kart_rewinder.cpp +++ b/src/karts/kart_rewinder.cpp @@ -95,7 +95,7 @@ BareNetworkString* KartRewinder::saveState() const buffer->add(body->getLinearVelocity()); buffer->add(body->getAngularVelocity()); buffer->addUInt8(m_has_started); // necessary for startup speed boost - buffer->addFloat(m_vehicle->getInstantSpeedIncrease()); + buffer->addFloat(m_vehicle->getMinSpeed()); // 2) Steering and other player controls // ------------------------------------- @@ -151,7 +151,7 @@ void KartRewinder::rewindToState(BareNetworkString *buffer) // before Moveable::update() is called (which updates the transform) setTrans(t); m_has_started = buffer->getUInt8()!=0; // necessary for startup speed boost - m_vehicle->instantSpeedIncreaseTo(buffer->getFloat()); + m_vehicle->setMinSpeed(buffer->getFloat()); // 2) Steering and other controls // ------------------------------ diff --git a/src/karts/max_speed.cpp b/src/karts/max_speed.cpp index 9ab14fa50..f9d4e9412 100644 --- a/src/karts/max_speed.cpp +++ b/src/karts/max_speed.cpp @@ -133,7 +133,7 @@ void MaxSpeed::instantSpeedIncrease(unsigned int category, // the speed might be too low for certain jumps). if(speed < m_min_speed) speed = m_min_speed; - m_kart->getVehicle()->instantSpeedIncreaseTo(speed); + m_kart->getVehicle()->setMinSpeed(speed); } // instantSpeedIncrease @@ -318,10 +318,15 @@ void MaxSpeed::update(float dt) // -------------------------------------- if(m_min_speed > 0 && m_kart->getSpeed() < m_min_speed) { - m_kart->getVehicle()->instantSpeedIncreaseTo(m_min_speed); + m_kart->getVehicle()->setMinSpeed(m_min_speed); } - else if ( m_kart->getSpeed()>m_current_max_speed && m_kart->isOnGround() ) - m_kart->getVehicle()->capSpeed(m_current_max_speed); + else + m_kart->getVehicle()->setMinSpeed(0); // no additional acceleration + + if (m_kart->isOnGround()) + m_kart->getVehicle()->setMaxSpeed(m_current_max_speed); + else + m_kart->getVehicle()->setMaxSpeed(9999.9f); } // update diff --git a/src/karts/rescue_animation.cpp b/src/karts/rescue_animation.cpp index 1dfa20ce5..49f6a2a63 100644 --- a/src/karts/rescue_animation.cpp +++ b/src/karts/rescue_animation.cpp @@ -37,6 +37,7 @@ #include +#include "graphics/camera_normal.hpp" /** The constructor stores a pointer to the kart this object is animating, * and initialised the timer. * \param kart Pointer to the kart which is animated. @@ -54,20 +55,8 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue) // Determine maximum rescue height with up-raycast float max_height = m_kart->getKartProperties()->getRescueHeight(); - float hit_dest = 9999999.9f; - Vec3 hit; - const Material* m = NULL; - Vec3 to = m_up_vector * 10000.0f; - const TriangleMesh &tm = Track::getCurrentTrack()->getTriangleMesh(); - if (tm.castRay(m_xyz, to, &hit, &m, NULL/*normal*/, /*interpolate*/true)) - { - hit_dest = (hit - m_xyz).length(); - hit_dest -= Referee::getHeight(); - if (hit_dest < 1.0f) - { - hit_dest = 1.0f; - } - } + float hit_dest = maximumHeight(); + max_height = std::min(hit_dest, max_height); m_velocity = max_height / m_timer; @@ -91,7 +80,7 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue) { m_des_rotation = m_orig_rotation; } - + // Add a hit unless it was auto-rescue if (race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES && !is_auto_rescue) @@ -101,50 +90,87 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue) if (UserConfigParams::m_arena_ai_stats) world->increaseRescueCount(); } + }; // RescueAnimation + //----------------------------------------------------------------------------- /** This object is automatically destroyed when the timer expires. */ RescueAnimation::~RescueAnimation() { - // If m_timer >=0, this object is deleted because the kart - // is deleted (at the end of a race), which means that - // world is in the process of being deleted. In this case - // we can't call removeKartAfterRescue() or getPhysics anymore. - if(m_timer < 0) - World::getWorld()->moveKartAfterRescue(m_kart); + m_kart->getBody()->setLinearVelocity(btVector3(0, 0, 0)); + m_kart->getBody()->setAngularVelocity(btVector3(0, 0, 0)); m_kart->getNode()->removeChild(m_referee->getSceneNode()); delete m_referee; m_referee = NULL; - if(m_timer < 0) - { - m_kart->getBody()->setLinearVelocity(btVector3(0,0,0)); - m_kart->getBody()->setAngularVelocity(btVector3(0,0,0)); - Physics::getInstance()->addKart(m_kart); - for(unsigned int i=0; igetKart()==m_kart && - camera->getType() != Camera::CM_TYPE_END) - camera->setMode(Camera::CM_NORMAL); - } - } } // ~RescueAnimation +// Determine maximum rescue height with up-raycast +float RescueAnimation::maximumHeight() +{ + float hit_dest = 9999999.9f; + + Vec3 hit; + const Material* m = NULL; + Vec3 to = m_up_vector * 10000.0f; + const TriangleMesh &tm = Track::getCurrentTrack()->getTriangleMesh(); + if (tm.castRay(m_xyz, to, &hit, &m, NULL/*normal*/, /*interpolate*/true)) + { + hit_dest = (hit - m_xyz).length(); + hit_dest -= Referee::getHeight(); + if (hit_dest < 1.0f) + { + hit_dest = 1.0f; + } + } + return hit_dest; +} // ---------------------------------------------------------------------------- + /** Updates the kart animation. * \param dt Time step size. * \return True if the explosion is still shown, false if it has finished. */ void RescueAnimation::update(float dt) { - m_xyz += dt * m_velocity * m_up_vector; - m_kart->setXYZ(m_xyz); - btQuaternion result = m_des_rotation.slerp(m_orig_rotation, - m_timer / m_kart->getKartProperties()->getRescueDuration()); - result.normalize(); - m_kart->setRotation(result); + + if (m_timer <= (m_kart->getKartProperties()->getRescueDuration() * rescue_moment)) + { + if (kart_on_track == false) + { + kart_on_track = true; + + World::getWorld()->moveKartAfterRescue(m_kart); + + for (unsigned int i = 0; i < Camera::getNumCameras(); i++) + { + CameraNormal* camera = dynamic_cast(Camera::getCamera(i)); + if (camera && camera->getKart() == m_kart && + dynamic_cast(camera)) + { + camera->setMode(Camera::CM_NORMAL); + camera->snapToPosition(); + } + } + + m_up_vector = m_kart->getTrans().getBasis().getColumn(1); + m_xyz = m_kart->getXYZ(); + + float hit_dest = maximumHeight(); + float max_height = std::min(hit_dest, m_kart->getKartProperties()->getRescueHeight()) * rescue_moment; + m_xyz += max_height * m_up_vector; + } + + m_xyz -= dt * m_velocity * m_up_vector; + m_kart->setXYZ(m_xyz); + } + else + { + m_xyz += dt * m_velocity * m_up_vector; + m_kart->setXYZ(m_xyz); + } + AbstractKartAnimation::update(dt); } // update diff --git a/src/karts/rescue_animation.hpp b/src/karts/rescue_animation.hpp index 211a0062b..2d278652a 100644 --- a/src/karts/rescue_animation.hpp +++ b/src/karts/rescue_animation.hpp @@ -46,11 +46,18 @@ protected: /** The velocity with which the kart is moved. */ float m_velocity; + /* At what percent of the animation should the kart be on the track*/ + /*0.75 means that for 3 quaters of the animation it'll be on track*/ + const float rescue_moment = 0.6F; + /* Has the kart been moved onto the track */ + bool kart_on_track = false; + /** The referee during a rescue operation. */ Referee *m_referee; public: RescueAnimation(AbstractKart *kart, bool is_auto_rescue=false); + float maximumHeight(); virtual ~RescueAnimation(); virtual void update(float dt); }; // RescueAnimation diff --git a/src/main.cpp b/src/main.cpp index 26bbc5777..644f31a7a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1779,10 +1779,8 @@ int main(int argc, char *argv[] ) race_manager->setupPlayerKartInfo(); race_manager->startNew(false); main_loop->run(); - // well, actually run() will never return, since - // it either loops or exits after replaying history (see - // history::updateReplayAndGetDT()). - // So the next line is just to make this obvious here! + // The run() function will only return if the user aborts. + Log::flushBuffers(); exit(-3); } // if !online } diff --git a/src/modes/cutscene_world.cpp b/src/modes/cutscene_world.cpp index 514bf8629..d850a9cf2 100644 --- a/src/modes/cutscene_world.cpp +++ b/src/modes/cutscene_world.cpp @@ -79,7 +79,7 @@ void CutsceneWorld::init() m_duration = -1.0f; - Camera* stk_cam = Camera::createCamera(NULL); + Camera* stk_cam = Camera::createCamera(NULL, 0); m_camera = stk_cam->getCameraSceneNode(); m_camera->setFOV(stk_config->m_cutscene_fov); m_camera->bindTargetAndRotation(true); // no "look-at" diff --git a/src/modes/overworld.cpp b/src/modes/overworld.cpp index 898badb01..4ba075674 100644 --- a/src/modes/overworld.cpp +++ b/src/modes/overworld.cpp @@ -278,7 +278,7 @@ void OverWorld::onMouseClick(int x, int y) // be the location of the challenge bubble. AbstractKart* kart = getKart(0); kart->setXYZ(challenge->m_position); - kart->getVehicle()->capSpeed(0); + kart->getVehicle()->setMaxSpeed(0); unsigned int index = getRescuePositionIndex(kart); btTransform s = getRescueTransform(index); diff --git a/src/modes/profile_world.cpp b/src/modes/profile_world.cpp index 25b1e1be8..3165e4e13 100644 --- a/src/modes/profile_world.cpp +++ b/src/modes/profile_world.cpp @@ -123,7 +123,7 @@ AbstractKart *ProfileWorld::createKart(const std::string &kart_ident, int index, if (index == (int)race_manager->getNumberOfKarts()-1) { // The camera keeps track of all cameras and will free them - Camera::createCamera(new_kart); + Camera::createCamera(new_kart, local_player_id); } return new_kart; } // createKart diff --git a/src/modes/soccer_world.cpp b/src/modes/soccer_world.cpp index ce2e750af..3a418a2ed 100644 --- a/src/modes/soccer_world.cpp +++ b/src/modes/soccer_world.cpp @@ -422,7 +422,7 @@ AbstractKart *SoccerWorld::createKart(const std::string &kart_ident, int index, { case RaceManager::KT_PLAYER: controller = new LocalPlayerController(new_kart, - StateManager::get()->getActivePlayer(local_player_id)); + local_player_id); m_num_players ++; break; case RaceManager::KT_NETWORK_PLAYER: diff --git a/src/modes/world.cpp b/src/modes/world.cpp index 196173562..fed9d0c54 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -238,7 +238,7 @@ void World::init() { // In case that the server is running with gui or watching replay, // create a camera and attach it to the first kart. - Camera::createCamera(World::getWorld()->getKart(0)); + Camera::createCamera(World::getWorld()->getKart(0), 0); } // if server with graphics of is watching replay } // if getNumCameras()==0 @@ -358,13 +358,16 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index, case RaceManager::KT_PLAYER: { controller = new LocalPlayerController(new_kart, - StateManager::get()->getActivePlayer(local_player_id)); + + local_player_id); + const float hue = StateManager::get()->getActivePlayer(local_player_id) ->getConstProfile()->getDefaultKartColor(); if (hue > 0.0f) { ri->setHue(hue); } + m_num_players ++; break; } diff --git a/src/network/network.hpp b/src/network/network.hpp index 9f55198f0..d2f4d09b0 100644 --- a/src/network/network.hpp +++ b/src/network/network.hpp @@ -54,7 +54,7 @@ public: Network(int peer_count, int channel_limit, uint32_t max_incoming_bandwidth, uint32_t max_outgoing_bandwidth, - ENetAddress* address = NULL); + ENetAddress* address); virtual ~Network(); static void openLog(); diff --git a/src/network/protocols/get_public_address.cpp b/src/network/protocols/get_public_address.cpp index 1a82c69cd..5bd89c8e6 100644 --- a/src/network/protocols/get_public_address.cpp +++ b/src/network/protocols/get_public_address.cpp @@ -23,6 +23,7 @@ #include "network/network_config.hpp" #include "network/network_string.hpp" #include "network/protocols/connect_to_server.hpp" +#include "network/stk_host.hpp" #include "utils/log.hpp" #include "utils/string_utils.hpp" @@ -115,7 +116,10 @@ void GetPublicAddress::createStunRequest() m_stun_server_ip = ntohl(current_interface->sin_addr.s_addr); // Create a new socket for the stun server. - m_transaction_host = new Network(1, 1, 0, 0); + ENetAddress addr; + addr.host = STKHost::HOST_ANY; + addr.port = STKHost::PORT_ANY; + m_transaction_host = new Network(1, 1, 0, 0, &addr); // Assemble the message for the stun server BareNetworkString s(20); diff --git a/src/network/servers_manager.cpp b/src/network/servers_manager.cpp index 4dcfe0c27..074904bb6 100644 --- a/src/network/servers_manager.cpp +++ b/src/network/servers_manager.cpp @@ -22,6 +22,7 @@ #include "network/network.hpp" #include "network/network_config.hpp" #include "network/network_string.hpp" +#include "network/stk_host.hpp" #include "online/xml_request.hpp" #include "utils/translation.hpp" #include "utils/time.hpp" @@ -150,7 +151,10 @@ Online::XMLRequest* ServersManager::getLANRefreshRequest() const // -------------------------------------------------------------------- virtual void operation() OVERRIDE { - Network *broadcast = new Network(1, 1, 0, 0); + ENetAddress addr; + addr.host = STKHost::HOST_ANY; + addr.port = STKHost::PORT_ANY; + Network *broadcast = new Network(1, 1, 0, 0, &addr); BareNetworkString s(std::string("stk-server")); TransportAddress broadcast_address(-1, diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index 9ea106195..4d32ae01c 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -118,7 +118,6 @@ void btKart::reset() updateWheelTransform(i, true); } m_visual_wheels_touch_ground = false; - m_zipper_speed = btScalar(0); m_skid_angular_velocity = 0; m_is_skidding = false; m_allow_sliding = false; @@ -128,6 +127,8 @@ void btKart::reset() m_additional_rotation = btVector3(0,0,0); m_time_additional_rotation = 0; m_visual_rotation = 0; + m_max_speed = -1.0f; + m_min_speed = 0.0f; // Set the brakes so that karts don't slide downhill setAllBrakes(5.0f); @@ -551,6 +552,7 @@ void btKart::updateVehicle( btScalar step ) iwt.setRotation(iwt.getRotation()*add_rot); m_time_additional_rotation -= dt; } + adjustSpeed(m_min_speed, m_max_speed); } // updateVehicle // ---------------------------------------------------------------------------- @@ -770,51 +772,35 @@ void btKart::updateFriction(btScalar timeStep) (btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject; if(!groundObject) continue; - if(m_zipper_speed > 0) - { - if (wheel==2 || wheel==3) - { - // The zipper velocity is the speed that should be - // reached. So compute the impulse to accelerate the - // kart up to that speed: - m_forwardImpulse[wheel] = - 0.5f*(m_zipper_speed - - getRigidBody()->getLinearVelocity().length()) - / m_chassisBody->getInvMass(); - } + btScalar rollingFriction = 0.f; + if (wheelInfo.m_engineForce != 0.f) + { + rollingFriction = wheelInfo.m_engineForce* timeStep; } else { - btScalar rollingFriction = 0.f; - - if (wheelInfo.m_engineForce != 0.f) - { - rollingFriction = wheelInfo.m_engineForce* timeStep; - } - else - { - btScalar defaultRollingFrictionImpulse = 0.f; - btScalar maxImpulse = wheelInfo.m_brake - ? wheelInfo.m_brake - : defaultRollingFrictionImpulse; - btWheelContactPoint contactPt(m_chassisBody, groundObject, - wheelInfo.m_raycastInfo.m_contactPointWS, - m_forwardWS[wheel],maxImpulse); - rollingFriction = calcRollingFriction(contactPt); - // This is a work around for the problem that a kart shakes - // if it is braking: we get a minor impulse forward, which - // bullet then tries to offset by applying a backward - // impulse - which is a bit too big, causing a impulse - // backwards, ... till the kart is shaking backwards and - // forwards. By only applying half of the impulse in case - // of low friction this goes away. - if(wheelInfo.m_brake && fabsf(rollingFriction)<10) - rollingFriction*=0.5f; - } - - m_forwardImpulse[wheel] = rollingFriction; + btScalar defaultRollingFrictionImpulse = 0.f; + btScalar maxImpulse = wheelInfo.m_brake + ? wheelInfo.m_brake + : defaultRollingFrictionImpulse; + btWheelContactPoint contactPt(m_chassisBody, groundObject, + wheelInfo.m_raycastInfo.m_contactPointWS, + m_forwardWS[wheel], maxImpulse); + rollingFriction = calcRollingFriction(contactPt); + // This is a work around for the problem that a kart shakes + // if it is braking: we get a minor impulse forward, which + // bullet then tries to offset by applying a backward + // impulse - which is a bit too big, causing a impulse + // backwards, ... till the kart is shaking backwards and + // forwards. By only applying half of the impulse in case + // of low friction this goes away. + if (wheelInfo.m_brake && fabsf(rollingFriction) < 10) + rollingFriction *= 0.5f; } + + m_forwardImpulse[wheel] = rollingFriction; + if(m_time_additional_impulse>0) { sliding = true; @@ -1015,33 +1001,40 @@ void btKart::setSliding(bool active) } // setSliding // ---------------------------------------------------------------------------- -/** Activates an additional speedup for the kart so that it reaches the - * specified speed. - * \param speed The speed to reach. +/** Adjusts the velocity of this kart to be at least the specified minimum, + * and less than or equal to the maximum. If necessary the kart will + * instantaneously change its speed. + * \param min_speed Minimum speed, 0 means no effect. + * \param max_speed Maximum speed the kart is allowed to have. */ -void btKart::instantSpeedIncreaseTo(float speed) -{ - // Avoid that a speed 'increase' might cause a slowdown - if (m_chassisBody->getLinearVelocity().length2() > speed*speed) - { - return; - } - m_zipper_speed = speed; -} // activateZipper - -// ---------------------------------------------------------------------------- -/** Caps the speed at a given value. If necessary the kart will - * instantaneously change its speed. */ -void btKart::capSpeed(float max_speed) +void btKart::adjustSpeed(btScalar min_speed, btScalar max_speed) { const btVector3 &velocity = m_chassisBody->getLinearVelocity(); float speed = velocity.length(); - if(speed!=0) + + + if (speed < min_speed && min_speed > 0) + { + if (speed > 0) + { + // The speedup is only for the direction of the normal. + const btVector3 &normal = m_kart->getNormal(); + btVector3 upright_component = normal * normal.dot(velocity); + // Subtract the upright velocity component, + btVector3 v = velocity - upright_component; + const float velocity_ratio = min_speed / v.length(); + // Scale the velocity in the plane, then add the upright component + // of the velocity back in. + m_chassisBody->setLinearVelocity( v*velocity_ratio + + upright_component ); + } + } + else if (speed >0 && max_speed >= 0 && speed > max_speed) { const float velocity_ratio = max_speed / speed; m_chassisBody->setLinearVelocity(velocity * velocity_ratio); } -} // capSpeed +} // adjustSpeed // ---------------------------------------------------------------------------- //Shorter version of above raycast function. This is used when projecting diff --git a/src/physics/btKart.hpp b/src/physics/btKart.hpp index 9a93f12e8..69eb071ea 100644 --- a/src/physics/btKart.hpp +++ b/src/physics/btKart.hpp @@ -69,10 +69,6 @@ private: btScalar m_damping; btVehicleRaycaster *m_vehicleRaycaster; - /** The zipper speed (i.e. the velocity the kart should reach in - * the first frame that the zipper is active). */ - btScalar m_zipper_speed; - /** The angular velocity to be applied when the kart skids. * 0 means no skidding. */ btScalar m_skid_angular_velocity; @@ -124,6 +120,15 @@ private: * for skid marks. */ float m_visual_rotation; + /** Minimum speed for the kart. Used e.g. for zippers. Setting this value + * will potentially instantaneously accelerate the kart to the minimum + * speed requested (in the next physics step). */ + btScalar m_min_speed; + + /** Maximum speed for the kart. It is reset to -1 at the end of each + * physics steps, so need to be set again by the application. */ + btScalar m_max_speed; + /** True if the visual wheels touch the ground. */ bool m_visual_wheels_touch_ground; @@ -176,8 +181,8 @@ public: virtual void updateFriction(btScalar timeStep); public: void setSliding(bool active); - void instantSpeedIncreaseTo(float speed); - void capSpeed(float max_speed); + void instantSpeedIncreaseTo(btScalar speed); + void adjustSpeed(btScalar min_speed, btScalar max_speed); void updateAllWheelPositions(); // ------------------------------------------------------------------------ /** Returns true if both rear visual wheels touch the ground. */ @@ -273,10 +278,30 @@ public: m_time_additional_rotation = t; } // setTimedTorque // ------------------------------------------------------------------------ - /** Returns the current zipper speed. */ - float getInstantSpeedIncrease() const { return m_zipper_speed; } + /** Sets the maximum speed for this kart. */ + void setMaxSpeed(float new_max_speed) + { + // Only change m_max_speed if it has not been set (<0), or + // the new value is smaller than the current maximum. For example, + // overworld will set the max_speed to 0 in case of teleporting to + // a bubble, but set it again later (based on zipper etc activated). + // We need to make sure that the 0 is maintained. + if(m_max_speed <0 || m_max_speed > new_max_speed) + m_max_speed = new_max_speed; + } // setMaxSpeed // ------------------------------------------------------------------------ - void resetInstantSpeed() { m_zipper_speed = 0; } + /** Resets the maximum so any new maximum value from the application will + * be accepted. */ + virtual void resetMaxSpeed() { m_max_speed = -1.0f; m_min_speed = 0.0f; } + // ------------------------------------------------------------------------ + /** Sets the minimum speed for this kart. */ + void setMinSpeed(float s) + { + if(s > m_min_speed) m_min_speed = s; + } + // ------------------------------------------------------------------------ + /** Returns the minimum speed for this kart. */ + btScalar getMinSpeed() const { return m_min_speed; } }; // class btKart #endif //BT_KART_HPP diff --git a/src/race/race_manager.cpp b/src/race/race_manager.cpp index 1c9ad2b97..2daeb829e 100644 --- a/src/race/race_manager.cpp +++ b/src/race/race_manager.cpp @@ -432,7 +432,7 @@ void RaceManager::startNew(bool from_overworld) if (m_continue_saved_gp) { int next_track = m_saved_gp->getNextTrack(); - if (next_track < m_tracks.size()) + if (next_track < (int)m_tracks.size()) m_track_number = next_track; m_saved_gp->loadKarts(m_kart_status); } diff --git a/src/race/race_manager.hpp b/src/race/race_manager.hpp index 7de4d8eda..875321b25 100644 --- a/src/race/race_manager.hpp +++ b/src/race/race_manager.hpp @@ -489,7 +489,17 @@ public: { return m_num_local_players; } // getNumLocalPlayers + // ------------------------------------------------------------------------ + bool getIfEmptyScreenSpaceExists() const + { + const float Sqrt = sqrt(getNumLocalPlayers()); + const int rows = ceil(Sqrt); + const int cols = round(Sqrt); + const int total_spaces = rows * cols; + return (total_spaces - getNumLocalPlayers() > 0); + } // getNumLocalPlayers + // ------------------------------------------------------------------------ /** Returns the selected number of karts (selected number of players and * AI karts. */ unsigned int getNumberOfKarts() const {return m_num_karts; } diff --git a/src/scriptengine/script_engine.cpp b/src/scriptengine/script_engine.cpp index 47458c93d..2c1ccbf3e 100644 --- a/src/scriptengine/script_engine.cpp +++ b/src/scriptengine/script_engine.cpp @@ -222,7 +222,7 @@ namespace Scripting /* void ScriptEngine::runMethod(asIScriptObject* obj, std::string methodName) { - asIObjectType* type = obj->GetObjectType(); + asITypeInfo* type = obj->GetObjectType(); asIScriptFunction* method = type->GetMethodByName(methodName.c_str()); if (method == NULL) Log::error("Scripting", ("runMethod: object does not implement method " + methodName).c_str()); diff --git a/src/scriptengine/scriptarray.cpp b/src/scriptengine/scriptarray.cpp index 322cdfa17..6121a283f 100644 --- a/src/scriptengine/scriptarray.cpp +++ b/src/scriptengine/scriptarray.cpp @@ -1,31 +1,31 @@ /* -AngelCode Scripting Library -Copyright (c) 2003-2015 Andreas Jonsson + AngelCode Scripting Library + Copyright (c) 2003-2017 Andreas Jonsson -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: -1. The origin of this software must not be misrepresented; you -must not claim that you wrote the original software. If you use -this software in a product, an acknowledgment in the product -documentation would be appreciated but is not required. + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source -distribution. + 3. This notice may not be removed or altered from any source + distribution. -The original version of this library can be located at: -http://www.angelcode.com/angelscript/ + The original version of this library can be located at: + http://www.angelcode.com/angelscript/ -Andreas Jonsson -andreas@angelcode.com + Andreas Jonsson + andreas@angelcode.com */ #include @@ -33,6 +33,7 @@ andreas@angelcode.com #include #include #include // sprintf +#include #include "scriptarray.hpp" @@ -52,8 +53,8 @@ static asFREEFUNC_t userFree = asFreeMem; // Allows the application to set which memory routines should be used by the array object void CScriptArray::SetMemoryFunctions(asALLOCFUNC_t allocFunc, asFREEFUNC_t freeFunc) { - userAlloc = allocFunc; - userFree = freeFunc; + userAlloc = allocFunc; + userFree = freeFunc; } static void RegisterScriptArray_Native(asIScriptEngine *engine); @@ -61,17 +62,17 @@ static void RegisterScriptArray_Generic(asIScriptEngine *engine); struct SArrayBuffer { - asDWORD maxElements; - asDWORD numElements; - asBYTE data[1]; + asDWORD maxElements; + asDWORD numElements; + asBYTE data[1]; }; struct SArrayCache { - asIScriptFunction *cmpFunc; - asIScriptFunction *eqFunc; - int cmpFuncReturnCode; // To allow better error message in case of multiple matches - int eqFuncReturnCode; + asIScriptFunction *cmpFunc; + asIScriptFunction *eqFunc; + int cmpFuncReturnCode; // To allow better error message in case of multiple matches + int eqFuncReturnCode; }; // We just define a number here that we assume nobody else is using for @@ -79,103 +80,76 @@ struct SArrayCache // through 1999 for this purpose, so we should be fine. const asPWORD ARRAY_CACHE = 1000; -static void CleanupObjectTypeArrayCache(asIObjectType *type) +static void CleanupTypeInfoArrayCache(asITypeInfo *type) { - SArrayCache *cache = reinterpret_cast(type->GetUserData(ARRAY_CACHE)); - if( cache ) - { - cache->~SArrayCache(); - userFree(cache); - } + SArrayCache *cache = reinterpret_cast(type->GetUserData(ARRAY_CACHE)); + if( cache ) + { + cache->~SArrayCache(); + userFree(cache); + } } -CScriptArray* CScriptArray::Create(asIObjectType *ot, asUINT length) +CScriptArray* CScriptArray::Create(asITypeInfo *ti, asUINT length) { - asIScriptContext *ctx = asGetActiveContext(); + // Allocate the memory + void *mem = userAlloc(sizeof(CScriptArray)); + if( mem == 0 ) + { + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Out of memory"); - // Allocate the memory - void *mem = userAlloc(sizeof(CScriptArray)); - if( mem == 0 ) - { - if( ctx ) - ctx->SetException("Out of memory"); + return 0; + } - return 0; - } + // Initialize the object + CScriptArray *a = new(mem) CScriptArray(length, ti); - // Initialize the object - CScriptArray *a = new(mem) CScriptArray(length, ot); - - // It's possible the constructor raised a script exception, in which case we - // need to free the memory and return null instead, else we get a memory leak. - if( ctx && ctx->GetState() == asEXECUTION_EXCEPTION ) - { - a->Release(); - return 0; - } - - return a; + return a; } -CScriptArray* CScriptArray::Create(asIObjectType *ot, void *initList) +CScriptArray* CScriptArray::Create(asITypeInfo *ti, void *initList) { - asIScriptContext *ctx = asGetActiveContext(); + // Allocate the memory + void *mem = userAlloc(sizeof(CScriptArray)); + if( mem == 0 ) + { + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Out of memory"); - // Allocate the memory - void *mem = userAlloc(sizeof(CScriptArray)); - if( mem == 0 ) - { - if( ctx ) - ctx->SetException("Out of memory"); + return 0; + } - return 0; - } + // Initialize the object + CScriptArray *a = new(mem) CScriptArray(ti, initList); - // Initialize the object - CScriptArray *a = new(mem) CScriptArray(ot, initList); - - // It's possible the constructor raised a script exception, in which case we - // need to free the memory and return null instead, else we get a memory leak. - if( ctx && ctx->GetState() == asEXECUTION_EXCEPTION ) - { - a->Release(); - return 0; - } - - return a; + return a; } -CScriptArray* CScriptArray::Create(asIObjectType *ot, asUINT length, void *defVal) +CScriptArray* CScriptArray::Create(asITypeInfo *ti, asUINT length, void *defVal) { - asIScriptContext *ctx = asGetActiveContext(); + // Allocate the memory + void *mem = userAlloc(sizeof(CScriptArray)); + if( mem == 0 ) + { + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Out of memory"); - // Allocate the memory - void *mem = userAlloc(sizeof(CScriptArray)); - if( mem == 0 ) - { - if( ctx ) - ctx->SetException("Out of memory"); + return 0; + } - return 0; - } + // Initialize the object + CScriptArray *a = new(mem) CScriptArray(length, defVal, ti); - // Initialize the object - CScriptArray *a = new(mem) CScriptArray(length, defVal, ot); - - // It's possible the constructor raised a script exception, in which case we - // need to free the memory and return null instead, else we get a memory leak. - if( ctx && ctx->GetState() == asEXECUTION_EXCEPTION ) - { - a->Release(); - return 0; - } - - return a; + return a; } -CScriptArray* CScriptArray::Create(asIObjectType *ot) +CScriptArray* CScriptArray::Create(asITypeInfo *ti) { - return CScriptArray::Create(ot, asUINT(0)); + return CScriptArray::Create(ti, asUINT(0)); } // This optional callback is called when the template type is first used by the compiler. @@ -183,1128 +157,1237 @@ CScriptArray* CScriptArray::Create(asIObjectType *ot) // subtype at compile time, instead of at runtime. The output argument dontGarbageCollect // allow the callback to tell the engine if the template instance type shouldn't be garbage collected, // i.e. no asOBJ_GC flag. -static bool ScriptArrayTemplateCallback(asIObjectType *ot, bool &dontGarbageCollect) +static bool ScriptArrayTemplateCallback(asITypeInfo *ti, bool &dontGarbageCollect) { - // Make sure the subtype can be instantiated with a default factory/constructor, - // otherwise we won't be able to instantiate the elements. - int typeId = ot->GetSubTypeId(); - if( typeId == asTYPEID_VOID ) - return false; - if( (typeId & asTYPEID_MASK_OBJECT) && !(typeId & asTYPEID_OBJHANDLE) ) - { - asIObjectType *subtype = ot->GetEngine()->GetObjectTypeById(typeId); - asDWORD flags = subtype->GetFlags(); - if( (flags & asOBJ_VALUE) && !(flags & asOBJ_POD) ) - { - // Verify that there is a default constructor - bool found = false; - for( asUINT n = 0; n < subtype->GetBehaviourCount(); n++ ) - { - asEBehaviours beh; - asIScriptFunction *func = subtype->GetBehaviourByIndex(n, &beh); - if( beh != asBEHAVE_CONSTRUCT ) continue; + // Make sure the subtype can be instantiated with a default factory/constructor, + // otherwise we won't be able to instantiate the elements. + int typeId = ti->GetSubTypeId(); + if( typeId == asTYPEID_VOID ) + return false; + if( (typeId & asTYPEID_MASK_OBJECT) && !(typeId & asTYPEID_OBJHANDLE) ) + { + asITypeInfo *subtype = ti->GetEngine()->GetTypeInfoById(typeId); + asDWORD flags = subtype->GetFlags(); + if( (flags & asOBJ_VALUE) && !(flags & asOBJ_POD) ) + { + // Verify that there is a default constructor + bool found = false; + for( asUINT n = 0; n < subtype->GetBehaviourCount(); n++ ) + { + asEBehaviours beh; + asIScriptFunction *func = subtype->GetBehaviourByIndex(n, &beh); + if( beh != asBEHAVE_CONSTRUCT ) continue; - if( func->GetParamCount() == 0 ) - { - // Found the default constructor - found = true; - break; - } - } + if( func->GetParamCount() == 0 ) + { + // Found the default constructor + found = true; + break; + } + } - if( !found ) - { - // There is no default constructor - ot->GetEngine()->WriteMessage("array", 0, 0, asMSGTYPE_ERROR, "The subtype has no default constructor"); - return false; - } - } - else if( (flags & asOBJ_REF) ) - { - bool found = false; + if( !found ) + { + // There is no default constructor + // TODO: Should format the message to give the name of the subtype for better understanding + ti->GetEngine()->WriteMessage("array", 0, 0, asMSGTYPE_ERROR, "The subtype has no default constructor"); + return false; + } + } + else if( (flags & asOBJ_REF) ) + { + bool found = false; - // If value assignment for ref type has been disabled then the array - // can be created if the type has a default factory function - if( !ot->GetEngine()->GetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE) ) - { - // Verify that there is a default factory - for( asUINT n = 0; n < subtype->GetFactoryCount(); n++ ) - { - asIScriptFunction *func = subtype->GetFactoryByIndex(n); - if( func->GetParamCount() == 0 ) - { - // Found the default factory - found = true; - break; - } - } - } + // If value assignment for ref type has been disabled then the array + // can be created if the type has a default factory function + if( !ti->GetEngine()->GetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE) ) + { + // Verify that there is a default factory + for( asUINT n = 0; n < subtype->GetFactoryCount(); n++ ) + { + asIScriptFunction *func = subtype->GetFactoryByIndex(n); + if( func->GetParamCount() == 0 ) + { + // Found the default factory + found = true; + break; + } + } + } - if( !found ) - { - // No default factory - ot->GetEngine()->WriteMessage("array", 0, 0, asMSGTYPE_ERROR, "The subtype has no default factory"); - return false; - } - } + if( !found ) + { + // No default factory + // TODO: Should format the message to give the name of the subtype for better understanding + ti->GetEngine()->WriteMessage("array", 0, 0, asMSGTYPE_ERROR, "The subtype has no default factory"); + return false; + } + } - // If the object type is not garbage collected then the array also doesn't need to be - if( !(flags & asOBJ_GC) ) - dontGarbageCollect = true; - } - else if( !(typeId & asTYPEID_OBJHANDLE) ) - { - // Arrays with primitives cannot form circular references, - // thus there is no need to garbage collect them - dontGarbageCollect = true; - } - else - { - assert( typeId & asTYPEID_OBJHANDLE ); + // If the object type is not garbage collected then the array also doesn't need to be + if( !(flags & asOBJ_GC) ) + dontGarbageCollect = true; + } + else if( !(typeId & asTYPEID_OBJHANDLE) ) + { + // Arrays with primitives cannot form circular references, + // thus there is no need to garbage collect them + dontGarbageCollect = true; + } + else + { + assert( typeId & asTYPEID_OBJHANDLE ); - // It is not necessary to set the array as garbage collected for all handle types. - // If it is possible to determine that the handle cannot refer to an object type - // that can potentially form a circular reference with the array then it is not - // necessary to make the array garbage collected. - asIObjectType *subtype = ot->GetEngine()->GetObjectTypeById(typeId); - asDWORD flags = subtype->GetFlags(); - if( !(flags & asOBJ_GC) ) - { - if( (flags & asOBJ_SCRIPT_OBJECT) ) - { - // Even if a script class is by itself not garbage collected, it is possible - // that classes that derive from it may be, so it is not possible to know - // that no circular reference can occur. - if( (flags & asOBJ_NOINHERIT) ) - { - // A script class declared as final cannot be inherited from, thus - // we can be certain that the object cannot be garbage collected. - dontGarbageCollect = true; - } - } - else - { - // For application registered classes we assume the application knows - // what it is doing and don't mark the array as garbage collected unless - // the type is also garbage collected. - dontGarbageCollect = true; - } - } - } + // It is not necessary to set the array as garbage collected for all handle types. + // If it is possible to determine that the handle cannot refer to an object type + // that can potentially form a circular reference with the array then it is not + // necessary to make the array garbage collected. + asITypeInfo *subtype = ti->GetEngine()->GetTypeInfoById(typeId); + asDWORD flags = subtype->GetFlags(); + if( !(flags & asOBJ_GC) ) + { + if( (flags & asOBJ_SCRIPT_OBJECT) ) + { + // Even if a script class is by itself not garbage collected, it is possible + // that classes that derive from it may be, so it is not possible to know + // that no circular reference can occur. + if( (flags & asOBJ_NOINHERIT) ) + { + // A script class declared as final cannot be inherited from, thus + // we can be certain that the object cannot be garbage collected. + dontGarbageCollect = true; + } + } + else + { + // For application registered classes we assume the application knows + // what it is doing and don't mark the array as garbage collected unless + // the type is also garbage collected. + dontGarbageCollect = true; + } + } + } - // The type is ok - return true; + // The type is ok + return true; } // Registers the template array type void RegisterScriptArray(asIScriptEngine *engine, bool defaultArray) { - if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") == 0 ) - RegisterScriptArray_Native(engine); - else - RegisterScriptArray_Generic(engine); + if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") == 0 ) + RegisterScriptArray_Native(engine); + else + RegisterScriptArray_Generic(engine); - if( defaultArray ) - { - int r = engine->RegisterDefaultArrayType("array"); assert( r >= 0 ); - UNUSED_VAR(r); - } + if( defaultArray ) + { + int r = engine->RegisterDefaultArrayType("array"); assert( r >= 0 ); + UNUSED_VAR(r); + } } static void RegisterScriptArray_Native(asIScriptEngine *engine) { - int r = 0; - UNUSED_VAR(r); + int r = 0; + UNUSED_VAR(r); - // Register the object type user data clean up - engine->SetObjectTypeUserDataCleanupCallback(CleanupObjectTypeArrayCache, ARRAY_CACHE); + // Register the object type user data clean up + engine->SetTypeInfoUserDataCleanupCallback(CleanupTypeInfoArrayCache, ARRAY_CACHE); - // Register the array type as a template - r = engine->RegisterObjectType("array", 0, asOBJ_REF | asOBJ_GC | asOBJ_TEMPLATE); assert( r >= 0 ); + // Register the array type as a template + r = engine->RegisterObjectType("array", 0, asOBJ_REF | asOBJ_GC | asOBJ_TEMPLATE); assert( r >= 0 ); - // Register a callback for validating the subtype before it is used - r = engine->RegisterObjectBehaviour("array", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in, bool&out)", asFUNCTION(ScriptArrayTemplateCallback), asCALL_CDECL); assert( r >= 0 ); + // Register a callback for validating the subtype before it is used + r = engine->RegisterObjectBehaviour("array", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in, bool&out)", asFUNCTION(ScriptArrayTemplateCallback), asCALL_CDECL); assert( r >= 0 ); - // Templates receive the object type as the first parameter. To the script writer this is hidden - r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in)", asFUNCTIONPR(CScriptArray::Create, (asIObjectType*), CScriptArray*), asCALL_CDECL); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in, uint)", asFUNCTIONPR(CScriptArray::Create, (asIObjectType*, asUINT), CScriptArray*), asCALL_CDECL); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in, uint, const T &in)", asFUNCTIONPR(CScriptArray::Create, (asIObjectType*, asUINT, void *), CScriptArray*), asCALL_CDECL); assert( r >= 0 ); + // Templates receive the object type as the first parameter. To the script writer this is hidden + r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in)", asFUNCTIONPR(CScriptArray::Create, (asITypeInfo*), CScriptArray*), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in, uint length)", asFUNCTIONPR(CScriptArray::Create, (asITypeInfo*, asUINT), CScriptArray*), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in, uint length, const T &in value)", asFUNCTIONPR(CScriptArray::Create, (asITypeInfo*, asUINT, void *), CScriptArray*), asCALL_CDECL); assert( r >= 0 ); - // Register the factory that will be used for initialization lists - r = engine->RegisterObjectBehaviour("array", asBEHAVE_LIST_FACTORY, "array@ f(int&in type, int&in list) {repeat T}", asFUNCTIONPR(CScriptArray::Create, (asIObjectType*, void*), CScriptArray*), asCALL_CDECL); assert( r >= 0 ); + // Register the factory that will be used for initialization lists + r = engine->RegisterObjectBehaviour("array", asBEHAVE_LIST_FACTORY, "array@ f(int&in type, int&in list) {repeat T}", asFUNCTIONPR(CScriptArray::Create, (asITypeInfo*, void*), CScriptArray*), asCALL_CDECL); assert( r >= 0 ); - // The memory management methods - r = engine->RegisterObjectBehaviour("array", asBEHAVE_ADDREF, "void f()", asMETHOD(CScriptArray,AddRef), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_RELEASE, "void f()", asMETHOD(CScriptArray,Release), asCALL_THISCALL); assert( r >= 0 ); + // The memory management methods + r = engine->RegisterObjectBehaviour("array", asBEHAVE_ADDREF, "void f()", asMETHOD(CScriptArray,AddRef), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_RELEASE, "void f()", asMETHOD(CScriptArray,Release), asCALL_THISCALL); assert( r >= 0 ); - // The index operator returns the template subtype - r = engine->RegisterObjectMethod("array", "T &opIndex(uint)", asMETHODPR(CScriptArray, At, (asUINT), void*), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "const T &opIndex(uint) const", asMETHODPR(CScriptArray, At, (asUINT) const, const void*), asCALL_THISCALL); assert( r >= 0 ); + // The index operator returns the template subtype + r = engine->RegisterObjectMethod("array", "T &opIndex(uint index)", asMETHODPR(CScriptArray, At, (asUINT), void*), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "const T &opIndex(uint index) const", asMETHODPR(CScriptArray, At, (asUINT) const, const void*), asCALL_THISCALL); assert( r >= 0 ); - // The assignment operator - r = engine->RegisterObjectMethod("array", "array &opAssign(const array&in)", asMETHOD(CScriptArray, operator=), asCALL_THISCALL); assert( r >= 0 ); + // The assignment operator + r = engine->RegisterObjectMethod("array", "array &opAssign(const array&in)", asMETHOD(CScriptArray, operator=), asCALL_THISCALL); assert( r >= 0 ); - // Other methods - r = engine->RegisterObjectMethod("array", "void insertAt(uint, const T&in)", asMETHOD(CScriptArray, InsertAt), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void removeAt(uint)", asMETHOD(CScriptArray, RemoveAt), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void insertLast(const T&in)", asMETHOD(CScriptArray, InsertLast), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void removeLast()", asMETHOD(CScriptArray, RemoveLast), asCALL_THISCALL); assert( r >= 0 ); - // TODO: Should length() and resize() be deprecated as the property accessors do the same thing? - r = engine->RegisterObjectMethod("array", "uint length() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void reserve(uint)", asMETHOD(CScriptArray, Reserve), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void resize(uint)", asMETHODPR(CScriptArray, Resize, (asUINT), void), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void sortAsc()", asMETHODPR(CScriptArray, SortAsc, (), void), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void sortAsc(uint, uint)", asMETHODPR(CScriptArray, SortAsc, (asUINT, asUINT), void), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void sortDesc()", asMETHODPR(CScriptArray, SortDesc, (), void), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void sortDesc(uint, uint)", asMETHODPR(CScriptArray, SortDesc, (asUINT, asUINT), void), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void reverse()", asMETHOD(CScriptArray, Reverse), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "int find(const T&in) const", asMETHODPR(CScriptArray, Find, (void*) const, int), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "int find(uint, const T&in) const", asMETHODPR(CScriptArray, Find, (asUINT, void*) const, int), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "int findByRef(const T&in) const", asMETHODPR(CScriptArray, FindByRef, (void*) const, int), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "int findByRef(uint, const T&in) const", asMETHODPR(CScriptArray, FindByRef, (asUINT, void*) const, int), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "bool opEquals(const array&in) const", asMETHOD(CScriptArray, operator==), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "bool isEmpty() const", asMETHOD(CScriptArray, IsEmpty), asCALL_THISCALL); assert( r >= 0 ); + // Other methods + r = engine->RegisterObjectMethod("array", "void insertAt(uint index, const T&in value)", asMETHODPR(CScriptArray, InsertAt, (asUINT, void *), void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void insertAt(uint index, const array& arr)", asMETHODPR(CScriptArray, InsertAt, (asUINT, const CScriptArray &), void), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectMethod("array", "void insertLast(const T&in value)", asMETHOD(CScriptArray, InsertLast), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectMethod("array", "void removeAt(uint index)", asMETHOD(CScriptArray, RemoveAt), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectMethod("array", "void removeLast()", asMETHOD(CScriptArray, RemoveLast), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void removeRange(uint start, uint count)", asMETHOD(CScriptArray, RemoveRange), asCALL_THISCALL); assert(r >= 0); + // TODO: Should length() and resize() be deprecated as the property accessors do the same thing? + r = engine->RegisterObjectMethod("array", "uint length() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void reserve(uint length)", asMETHOD(CScriptArray, Reserve), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void resize(uint length)", asMETHODPR(CScriptArray, Resize, (asUINT), void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortAsc()", asMETHODPR(CScriptArray, SortAsc, (), void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortAsc(uint startAt, uint count)", asMETHODPR(CScriptArray, SortAsc, (asUINT, asUINT), void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortDesc()", asMETHODPR(CScriptArray, SortDesc, (), void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortDesc(uint startAt, uint count)", asMETHODPR(CScriptArray, SortDesc, (asUINT, asUINT), void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void reverse()", asMETHOD(CScriptArray, Reverse), asCALL_THISCALL); assert( r >= 0 ); + // The token 'if_handle_then_const' tells the engine that if the type T is a handle, then it should refer to a read-only object + r = engine->RegisterObjectMethod("array", "int find(const T&in if_handle_then_const value) const", asMETHODPR(CScriptArray, Find, (void*) const, int), asCALL_THISCALL); assert( r >= 0 ); + // TODO: It should be "int find(const T&in value, uint startAt = 0) const" + r = engine->RegisterObjectMethod("array", "int find(uint startAt, const T&in if_handle_then_const value) const", asMETHODPR(CScriptArray, Find, (asUINT, void*) const, int), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "int findByRef(const T&in if_handle_then_const value) const", asMETHODPR(CScriptArray, FindByRef, (void*) const, int), asCALL_THISCALL); assert( r >= 0 ); + // TODO: It should be "int findByRef(const T&in value, uint startAt = 0) const" + r = engine->RegisterObjectMethod("array", "int findByRef(uint startAt, const T&in if_handle_then_const value) const", asMETHODPR(CScriptArray, FindByRef, (asUINT, void*) const, int), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "bool opEquals(const array&in) const", asMETHOD(CScriptArray, operator==), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "bool isEmpty() const", asMETHOD(CScriptArray, IsEmpty), asCALL_THISCALL); assert( r >= 0 ); - // Register virtual properties - r = engine->RegisterObjectMethod("array", "uint get_length() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void set_length(uint)", asMETHODPR(CScriptArray, Resize, (asUINT), void), asCALL_THISCALL); assert( r >= 0 ); + // Sort with callback for comparison + r = engine->RegisterFuncdef("bool array::less(const T&in a, const T&in b)"); + r = engine->RegisterObjectMethod("array", "void sort(const less &in, uint startAt = 0, uint count = uint(-1))", asMETHODPR(CScriptArray, Sort, (asIScriptFunction*, asUINT, asUINT), void), asCALL_THISCALL); assert(r >= 0); - // Register GC behaviours in case the array needs to be garbage collected - r = engine->RegisterObjectBehaviour("array", asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(CScriptArray, GetRefCount), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_SETGCFLAG, "void f()", asMETHOD(CScriptArray, SetFlag), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(CScriptArray, GetFlag), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(CScriptArray, EnumReferences), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(CScriptArray, ReleaseAllHandles), asCALL_THISCALL); assert( r >= 0 ); + // Register virtual properties + r = engine->RegisterObjectMethod("array", "uint get_length() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void set_length(uint)", asMETHODPR(CScriptArray, Resize, (asUINT), void), asCALL_THISCALL); assert( r >= 0 ); + + // Register GC behaviours in case the array needs to be garbage collected + r = engine->RegisterObjectBehaviour("array", asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(CScriptArray, GetRefCount), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_SETGCFLAG, "void f()", asMETHOD(CScriptArray, SetFlag), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(CScriptArray, GetFlag), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(CScriptArray, EnumReferences), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(CScriptArray, ReleaseAllHandles), asCALL_THISCALL); assert( r >= 0 ); #if AS_USE_STLNAMES == 1 - // Same as length - r = engine->RegisterObjectMethod("array", "uint size() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL); assert( r >= 0 ); - // Same as isEmpty - r = engine->RegisterObjectMethod("array", "bool empty() const", asMETHOD(CScriptArray, IsEmpty), asCALL_THISCALL); assert( r >= 0 ); - // Same as insertLast - r = engine->RegisterObjectMethod("array", "void push_back(const T&in)", asMETHOD(CScriptArray, InsertLast), asCALL_THISCALL); assert( r >= 0 ); - // Same as removeLast - r = engine->RegisterObjectMethod("array", "void pop_back()", asMETHOD(CScriptArray, RemoveLast), asCALL_THISCALL); assert( r >= 0 ); - // Same as insertAt - r = engine->RegisterObjectMethod("array", "void insert(uint, const T&in)", asMETHOD(CScriptArray, InsertAt), asCALL_THISCALL); assert( r >= 0 ); - // Same as removeAt - r = engine->RegisterObjectMethod("array", "void erase(uint)", asMETHOD(CScriptArray, RemoveAt), asCALL_THISCALL); assert( r >= 0 ); + // Same as length + r = engine->RegisterObjectMethod("array", "uint size() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL); assert( r >= 0 ); + // Same as isEmpty + r = engine->RegisterObjectMethod("array", "bool empty() const", asMETHOD(CScriptArray, IsEmpty), asCALL_THISCALL); assert( r >= 0 ); + // Same as insertLast + r = engine->RegisterObjectMethod("array", "void push_back(const T&in)", asMETHOD(CScriptArray, InsertLast), asCALL_THISCALL); assert( r >= 0 ); + // Same as removeLast + r = engine->RegisterObjectMethod("array", "void pop_back()", asMETHOD(CScriptArray, RemoveLast), asCALL_THISCALL); assert( r >= 0 ); + // Same as insertAt + r = engine->RegisterObjectMethod("array", "void insert(uint index, const T&in value)", asMETHODPR(CScriptArray, InsertAt, (asUINT, void *), void), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectMethod("array", "void insert(uint index, const array& arr)", asMETHODPR(CScriptArray, InsertAt, (asUINT, const CScriptArray &), void), asCALL_THISCALL); assert(r >= 0); + // Same as removeAt + r = engine->RegisterObjectMethod("array", "void erase(uint)", asMETHOD(CScriptArray, RemoveAt), asCALL_THISCALL); assert( r >= 0 ); #endif } CScriptArray &CScriptArray::operator=(const CScriptArray &other) { - // Only perform the copy if the array types are the same - if( &other != this && - other.GetArrayObjectType() == GetArrayObjectType() ) - { - // Make sure the arrays are of the same size - Resize(other.buffer->numElements); + // Only perform the copy if the array types are the same + if( &other != this && + other.GetArrayObjectType() == GetArrayObjectType() ) + { + // Make sure the arrays are of the same size + Resize(other.buffer->numElements); - // Copy the value of each element - CopyBuffer(buffer, other.buffer); - } + // Copy the value of each element + CopyBuffer(buffer, other.buffer); + } - return *this; + return *this; } -CScriptArray::CScriptArray(asIObjectType *ot, void *buf) +CScriptArray::CScriptArray(asITypeInfo *ti, void *buf) { - refCount = 1; - gcFlag = false; - objType = ot; - objType->AddRef(); - buffer = 0; + // The object type should be the template instance of the array + assert( ti && string(ti->GetName()) == "array" ); - Precache(); + refCount = 1; + gcFlag = false; + objType = ti; + objType->AddRef(); + buffer = 0; - asIScriptEngine *engine = ot->GetEngine(); + Precache(); - // Determine element size - if( subTypeId & asTYPEID_MASK_OBJECT ) - elementSize = sizeof(asPWORD); - else - elementSize = engine->GetSizeOfPrimitiveType(subTypeId); + asIScriptEngine *engine = ti->GetEngine(); - // Determine the initial size from the buffer - asUINT length = *(asUINT*)buf; + // Determine element size + if( subTypeId & asTYPEID_MASK_OBJECT ) + elementSize = sizeof(asPWORD); + else + elementSize = engine->GetSizeOfPrimitiveType(subTypeId); - // Make sure the array size isn't too large for us to handle - if( !CheckMaxSize(length) ) - { - // Don't continue with the initialization - return; - } + // Determine the initial size from the buffer + asUINT length = *(asUINT*)buf; - // Copy the values of the array elements from the buffer - if( (ot->GetSubTypeId() & asTYPEID_MASK_OBJECT) == 0 ) - { - CreateBuffer(&buffer, length); + // Make sure the array size isn't too large for us to handle + if( !CheckMaxSize(length) ) + { + // Don't continue with the initialization + return; + } - // Copy the values of the primitive type into the internal buffer - if( length > 0 ) - memcpy(At(0), (((asUINT*)buf)+1), length * elementSize); - } - else if( ot->GetSubTypeId() & asTYPEID_OBJHANDLE ) - { - CreateBuffer(&buffer, length); + // Copy the values of the array elements from the buffer + if( (ti->GetSubTypeId() & asTYPEID_MASK_OBJECT) == 0 ) + { + CreateBuffer(&buffer, length); - // Copy the handles into the internal buffer - if( length > 0 ) - memcpy(At(0), (((asUINT*)buf)+1), length * elementSize); + // Copy the values of the primitive type into the internal buffer + if( length > 0 ) + memcpy(At(0), (((asUINT*)buf)+1), length * elementSize); + } + else if( ti->GetSubTypeId() & asTYPEID_OBJHANDLE ) + { + CreateBuffer(&buffer, length); - // With object handles it is safe to clear the memory in the received buffer - // instead of increasing the ref count. It will save time both by avoiding the - // call the increase ref, and also relieve the engine from having to release - // its references too - memset((((asUINT*)buf)+1), 0, length * elementSize); - } - else if( ot->GetSubType()->GetFlags() & asOBJ_REF ) - { - // Only allocate the buffer, but not the objects - subTypeId |= asTYPEID_OBJHANDLE; - CreateBuffer(&buffer, length); - subTypeId &= ~asTYPEID_OBJHANDLE; + // Copy the handles into the internal buffer + if( length > 0 ) + memcpy(At(0), (((asUINT*)buf)+1), length * elementSize); - // Copy the handles into the internal buffer - if( length > 0 ) - memcpy(buffer->data, (((asUINT*)buf)+1), length * elementSize); + // With object handles it is safe to clear the memory in the received buffer + // instead of increasing the ref count. It will save time both by avoiding the + // call the increase ref, and also relieve the engine from having to release + // its references too + memset((((asUINT*)buf)+1), 0, length * elementSize); + } + else if( ti->GetSubType()->GetFlags() & asOBJ_REF ) + { + // Only allocate the buffer, but not the objects + subTypeId |= asTYPEID_OBJHANDLE; + CreateBuffer(&buffer, length); + subTypeId &= ~asTYPEID_OBJHANDLE; - // For ref types we can do the same as for handles, as they are - // implicitly stored as handles. - memset((((asUINT*)buf)+1), 0, length * elementSize); - } - else - { - // TODO: Optimize by calling the copy constructor of the object instead of - // constructing with the default constructor and then assigning the value - // TODO: With C++11 ideally we should be calling the move constructor, instead - // of the copy constructor as the engine will just discard the objects in the - // buffer afterwards. - CreateBuffer(&buffer, length); + // Copy the handles into the internal buffer + if( length > 0 ) + memcpy(buffer->data, (((asUINT*)buf)+1), length * elementSize); - // For value types we need to call the opAssign for each individual object - for( asUINT n = 0; n < length; n++ ) - { - void *obj = At(n); - asBYTE *srcObj = (asBYTE*)buf; - srcObj += 4 + n*ot->GetSubType()->GetSize(); - engine->AssignScriptObject(obj, srcObj, ot->GetSubType()); - } - } + // For ref types we can do the same as for handles, as they are + // implicitly stored as handles. + memset((((asUINT*)buf)+1), 0, length * elementSize); + } + else + { + // TODO: Optimize by calling the copy constructor of the object instead of + // constructing with the default constructor and then assigning the value + // TODO: With C++11 ideally we should be calling the move constructor, instead + // of the copy constructor as the engine will just discard the objects in the + // buffer afterwards. + CreateBuffer(&buffer, length); - // Notify the GC of the successful creation - if( objType->GetFlags() & asOBJ_GC ) - objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType); + // For value types we need to call the opAssign for each individual object + for( asUINT n = 0; n < length; n++ ) + { + void *obj = At(n); + asBYTE *srcObj = (asBYTE*)buf; + srcObj += 4 + n*ti->GetSubType()->GetSize(); + engine->AssignScriptObject(obj, srcObj, ti->GetSubType()); + } + } + + // Notify the GC of the successful creation + if( objType->GetFlags() & asOBJ_GC ) + objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType); } -CScriptArray::CScriptArray(asUINT length, asIObjectType *ot) +CScriptArray::CScriptArray(asUINT length, asITypeInfo *ti) { - refCount = 1; - gcFlag = false; - objType = ot; - objType->AddRef(); - buffer = 0; + // The object type should be the template instance of the array + assert( ti && string(ti->GetName()) == "array" ); - Precache(); + refCount = 1; + gcFlag = false; + objType = ti; + objType->AddRef(); + buffer = 0; - // Determine element size - if( subTypeId & asTYPEID_MASK_OBJECT ) - elementSize = sizeof(asPWORD); - else - elementSize = objType->GetEngine()->GetSizeOfPrimitiveType(subTypeId); + Precache(); - // Make sure the array size isn't too large for us to handle - if( !CheckMaxSize(length) ) - { - // Don't continue with the initialization - return; - } + // Determine element size + if( subTypeId & asTYPEID_MASK_OBJECT ) + elementSize = sizeof(asPWORD); + else + elementSize = objType->GetEngine()->GetSizeOfPrimitiveType(subTypeId); - CreateBuffer(&buffer, length); + // Make sure the array size isn't too large for us to handle + if( !CheckMaxSize(length) ) + { + // Don't continue with the initialization + return; + } - // Notify the GC of the successful creation - if( objType->GetFlags() & asOBJ_GC ) - objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType); + CreateBuffer(&buffer, length); + + // Notify the GC of the successful creation + if( objType->GetFlags() & asOBJ_GC ) + objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType); } CScriptArray::CScriptArray(const CScriptArray &other) { - refCount = 1; - gcFlag = false; - objType = other.objType; - objType->AddRef(); - buffer = 0; + refCount = 1; + gcFlag = false; + objType = other.objType; + objType->AddRef(); + buffer = 0; - Precache(); + Precache(); - elementSize = other.elementSize; + elementSize = other.elementSize; - if( objType->GetFlags() & asOBJ_GC ) - objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType); + if( objType->GetFlags() & asOBJ_GC ) + objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType); - CreateBuffer(&buffer, 0); + CreateBuffer(&buffer, 0); - // Copy the content - *this = other; + // Copy the content + *this = other; } -CScriptArray::CScriptArray(asUINT length, void *defVal, asIObjectType *ot) +CScriptArray::CScriptArray(asUINT length, void *defVal, asITypeInfo *ti) { - refCount = 1; - gcFlag = false; - objType = ot; - objType->AddRef(); - buffer = 0; + // The object type should be the template instance of the array + assert( ti && string(ti->GetName()) == "array" ); - Precache(); + refCount = 1; + gcFlag = false; + objType = ti; + objType->AddRef(); + buffer = 0; - // Determine element size - if( subTypeId & asTYPEID_MASK_OBJECT ) - elementSize = sizeof(asPWORD); - else - elementSize = objType->GetEngine()->GetSizeOfPrimitiveType(subTypeId); + Precache(); - // Make sure the array size isn't too large for us to handle - if( !CheckMaxSize(length) ) - { - // Don't continue with the initialization - return; - } + // Determine element size + if( subTypeId & asTYPEID_MASK_OBJECT ) + elementSize = sizeof(asPWORD); + else + elementSize = objType->GetEngine()->GetSizeOfPrimitiveType(subTypeId); - CreateBuffer(&buffer, length); + // Make sure the array size isn't too large for us to handle + if( !CheckMaxSize(length) ) + { + // Don't continue with the initialization + return; + } - // Notify the GC of the successful creation - if( objType->GetFlags() & asOBJ_GC ) - objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType); + CreateBuffer(&buffer, length); - // Initialize the elements with the default value - for( asUINT n = 0; n < GetSize(); n++ ) - SetValue(n, defVal); + // Notify the GC of the successful creation + if( objType->GetFlags() & asOBJ_GC ) + objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType); + + // Initialize the elements with the default value + for( asUINT n = 0; n < GetSize(); n++ ) + SetValue(n, defVal); } void CScriptArray::SetValue(asUINT index, void *value) { - // At() will take care of the out-of-bounds checking, though - // if called from the application then nothing will be done - void *ptr = At(index); - if( ptr == 0 ) return; + // At() will take care of the out-of-bounds checking, though + // if called from the application then nothing will be done + void *ptr = At(index); + if( ptr == 0 ) return; - if( (subTypeId & ~asTYPEID_MASK_SEQNBR) && !(subTypeId & asTYPEID_OBJHANDLE) ) - objType->GetEngine()->AssignScriptObject(ptr, value, objType->GetSubType()); - else if( subTypeId & asTYPEID_OBJHANDLE ) - { - void *tmp = *(void**)ptr; - *(void**)ptr = *(void**)value; - objType->GetEngine()->AddRefScriptObject(*(void**)value, objType->GetSubType()); - if( tmp ) - objType->GetEngine()->ReleaseScriptObject(tmp, objType->GetSubType()); - } - else if( subTypeId == asTYPEID_BOOL || - subTypeId == asTYPEID_INT8 || - subTypeId == asTYPEID_UINT8 ) - *(char*)ptr = *(char*)value; - else if( subTypeId == asTYPEID_INT16 || - subTypeId == asTYPEID_UINT16 ) - *(short*)ptr = *(short*)value; - else if( subTypeId == asTYPEID_INT32 || - subTypeId == asTYPEID_UINT32 || - subTypeId == asTYPEID_FLOAT || - subTypeId > asTYPEID_DOUBLE ) // enums have a type id larger than doubles - *(int*)ptr = *(int*)value; - else if( subTypeId == asTYPEID_INT64 || - subTypeId == asTYPEID_UINT64 || - subTypeId == asTYPEID_DOUBLE ) - *(double*)ptr = *(double*)value; + if( (subTypeId & ~asTYPEID_MASK_SEQNBR) && !(subTypeId & asTYPEID_OBJHANDLE) ) + objType->GetEngine()->AssignScriptObject(ptr, value, objType->GetSubType()); + else if( subTypeId & asTYPEID_OBJHANDLE ) + { + void *tmp = *(void**)ptr; + *(void**)ptr = *(void**)value; + objType->GetEngine()->AddRefScriptObject(*(void**)value, objType->GetSubType()); + if( tmp ) + objType->GetEngine()->ReleaseScriptObject(tmp, objType->GetSubType()); + } + else if( subTypeId == asTYPEID_BOOL || + subTypeId == asTYPEID_INT8 || + subTypeId == asTYPEID_UINT8 ) + *(char*)ptr = *(char*)value; + else if( subTypeId == asTYPEID_INT16 || + subTypeId == asTYPEID_UINT16 ) + *(short*)ptr = *(short*)value; + else if( subTypeId == asTYPEID_INT32 || + subTypeId == asTYPEID_UINT32 || + subTypeId == asTYPEID_FLOAT || + subTypeId > asTYPEID_DOUBLE ) // enums have a type id larger than doubles + *(int*)ptr = *(int*)value; + else if( subTypeId == asTYPEID_INT64 || + subTypeId == asTYPEID_UINT64 || + subTypeId == asTYPEID_DOUBLE ) + *(double*)ptr = *(double*)value; } CScriptArray::~CScriptArray() { - if( buffer ) - { - DeleteBuffer(buffer); - buffer = 0; - } - if( objType ) objType->Release(); + if( buffer ) + { + DeleteBuffer(buffer); + buffer = 0; + } + if( objType ) objType->Release(); } asUINT CScriptArray::GetSize() const { - return buffer->numElements; + return buffer->numElements; } bool CScriptArray::IsEmpty() const { - return buffer->numElements == 0; + return buffer->numElements == 0; } void CScriptArray::Reserve(asUINT maxElements) { - if( maxElements <= buffer->maxElements ) - return; + if( maxElements <= buffer->maxElements ) + return; - if( !CheckMaxSize(maxElements) ) - return; + if( !CheckMaxSize(maxElements) ) + return; - // Allocate memory for the buffer - SArrayBuffer *newBuffer = reinterpret_cast(userAlloc(sizeof(SArrayBuffer)-1 + elementSize*maxElements)); - if( newBuffer ) - { - newBuffer->numElements = buffer->numElements; - newBuffer->maxElements = maxElements; - } - else - { - // Out of memory - asIScriptContext *ctx = asGetActiveContext(); - if( ctx ) - ctx->SetException("Out of memory"); - return; - } + // Allocate memory for the buffer + SArrayBuffer *newBuffer = reinterpret_cast(userAlloc(sizeof(SArrayBuffer)-1 + elementSize*maxElements)); + if( newBuffer ) + { + newBuffer->numElements = buffer->numElements; + newBuffer->maxElements = maxElements; + } + else + { + // Out of memory + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Out of memory"); + return; + } - // TODO: memcpy assumes the objects in the array doesn't hold pointers to themselves - // This should really be using the objects copy/move constructor to copy each object - // to the new location. It would most likely be a hit on the performance though. - memcpy(newBuffer->data, buffer->data, buffer->numElements*elementSize); + // As objects in arrays of objects are not stored inline, it is safe to use memcpy here + // since we're just copying the pointers to objects and not the actual objects. + memcpy(newBuffer->data, buffer->data, buffer->numElements*elementSize); - // Release the old buffer - userFree(buffer); + // Release the old buffer + userFree(buffer); - buffer = newBuffer; + buffer = newBuffer; } void CScriptArray::Resize(asUINT numElements) { - if( !CheckMaxSize(numElements) ) - return; + if( !CheckMaxSize(numElements) ) + return; - Resize((int)numElements - (int)buffer->numElements, (asUINT)-1); + Resize((int)numElements - (int)buffer->numElements, (asUINT)-1); +} + +void CScriptArray::RemoveRange(asUINT start, asUINT count) +{ + if (count == 0) + return; + + if( buffer == 0 || start > buffer->numElements ) + { + // If this is called from a script we raise a script exception + asIScriptContext *ctx = asGetActiveContext(); + if (ctx) + ctx->SetException("Index out of bounds"); + return; + } + + // Cap count to the end of the array + if (start + count > buffer->numElements) + count = buffer->numElements - start; + + // Destroy the elements that are being removed + Destruct(buffer, start, start + count); + + // Compact the elements + // As objects in arrays of objects are not stored inline, it is safe to use memmove here + // since we're just copying the pointers to objects and not the actual objects. + memmove(buffer->data + start*elementSize, buffer->data + (start + count)*elementSize, (buffer->numElements - start - count)*elementSize); + buffer->numElements -= count; } // Internal void CScriptArray::Resize(int delta, asUINT at) { - if( delta < 0 ) - { - if( -delta > (int)buffer->numElements ) - delta = -(int)buffer->numElements; - if( at > buffer->numElements + delta ) - at = buffer->numElements + delta; - } - else if( delta > 0 ) - { - // Make sure the array size isn't too large for us to handle - if( delta > 0 && !CheckMaxSize(buffer->numElements + delta) ) - return; + if( delta < 0 ) + { + if( -delta > (int)buffer->numElements ) + delta = -(int)buffer->numElements; + if( at > buffer->numElements + delta ) + at = buffer->numElements + delta; + } + else if( delta > 0 ) + { + // Make sure the array size isn't too large for us to handle + if( delta > 0 && !CheckMaxSize(buffer->numElements + delta) ) + return; - if( at > buffer->numElements ) - at = buffer->numElements; - } + if( at > buffer->numElements ) + at = buffer->numElements; + } - if( delta == 0 ) return; + if( delta == 0 ) return; - if( buffer->maxElements < buffer->numElements + delta ) - { - // Allocate memory for the buffer - SArrayBuffer *newBuffer = reinterpret_cast(userAlloc(sizeof(SArrayBuffer)-1 + elementSize*(buffer->numElements + delta))); - if( newBuffer ) - { - newBuffer->numElements = buffer->numElements + delta; - newBuffer->maxElements = newBuffer->numElements; - } - else - { - // Out of memory - asIScriptContext *ctx = asGetActiveContext(); - if( ctx ) - ctx->SetException("Out of memory"); - return; - } + if( buffer->maxElements < buffer->numElements + delta ) + { + // Allocate memory for the buffer + SArrayBuffer *newBuffer = reinterpret_cast(userAlloc(sizeof(SArrayBuffer)-1 + elementSize*(buffer->numElements + delta))); + if( newBuffer ) + { + newBuffer->numElements = buffer->numElements + delta; + newBuffer->maxElements = newBuffer->numElements; + } + else + { + // Out of memory + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Out of memory"); + return; + } - // TODO: memcpy assumes the objects in the array doesn't hold pointers to themselves - // This should really be using the objects copy/move constructor to copy each object - // to the new location. It would most likely be a hit on the performance though. - memcpy(newBuffer->data, buffer->data, at*elementSize); - if( at < buffer->numElements ) - memcpy(newBuffer->data + (at+delta)*elementSize, buffer->data + at*elementSize, (buffer->numElements-at)*elementSize); + // As objects in arrays of objects are not stored inline, it is safe to use memcpy here + // since we're just copying the pointers to objects and not the actual objects. + memcpy(newBuffer->data, buffer->data, at*elementSize); + if( at < buffer->numElements ) + memcpy(newBuffer->data + (at+delta)*elementSize, buffer->data + at*elementSize, (buffer->numElements-at)*elementSize); - // Initialize the new elements with default values - Construct(newBuffer, at, at+delta); + // Initialize the new elements with default values + Construct(newBuffer, at, at+delta); - // Release the old buffer - userFree(buffer); + // Release the old buffer + userFree(buffer); - buffer = newBuffer; - } - else if( delta < 0 ) - { - Destruct(buffer, at, at-delta); - // TODO: memmove assumes the objects in the array doesn't hold pointers to themselves - // This should really be using the objects copy/move constructor to copy each object - // to the new location. It would most likely be a hit on the performance though. - memmove(buffer->data + at*elementSize, buffer->data + (at-delta)*elementSize, (buffer->numElements - (at-delta))*elementSize); - buffer->numElements += delta; - } - else - { - // TODO: memmove assumes the objects in the array doesn't hold pointers to themselves - // This should really be using the objects copy/move constructor to copy each object - // to the new location. It would most likely be a hit on the performance though. - memmove(buffer->data + (at+delta)*elementSize, buffer->data + at*elementSize, (buffer->numElements - at)*elementSize); - Construct(buffer, at, at+delta); - buffer->numElements += delta; - } + buffer = newBuffer; + } + else if( delta < 0 ) + { + Destruct(buffer, at, at-delta); + // As objects in arrays of objects are not stored inline, it is safe to use memmove here + // since we're just copying the pointers to objects and not the actual objects. + memmove(buffer->data + at*elementSize, buffer->data + (at-delta)*elementSize, (buffer->numElements - (at-delta))*elementSize); + buffer->numElements += delta; + } + else + { + // As objects in arrays of objects are not stored inline, it is safe to use memmove here + // since we're just copying the pointers to objects and not the actual objects. + memmove(buffer->data + (at+delta)*elementSize, buffer->data + at*elementSize, (buffer->numElements - at)*elementSize); + Construct(buffer, at, at+delta); + buffer->numElements += delta; + } } // internal bool CScriptArray::CheckMaxSize(asUINT numElements) { - // This code makes sure the size of the buffer that is allocated - // for the array doesn't overflow and becomes smaller than requested + // This code makes sure the size of the buffer that is allocated + // for the array doesn't overflow and becomes smaller than requested - asUINT maxSize = 0xFFFFFFFFul - sizeof(SArrayBuffer) + 1; - if( elementSize > 0 ) - maxSize /= elementSize; + asUINT maxSize = 0xFFFFFFFFul - sizeof(SArrayBuffer) + 1; + if( elementSize > 0 ) + maxSize /= elementSize; - if( numElements > maxSize ) - { - asIScriptContext *ctx = asGetActiveContext(); - if( ctx ) - ctx->SetException("Too large array size"); + if( numElements > maxSize ) + { + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Too large array size"); - return false; - } + return false; + } - // OK - return true; + // OK + return true; } -asIObjectType *CScriptArray::GetArrayObjectType() const +asITypeInfo *CScriptArray::GetArrayObjectType() const { - return objType; + return objType; } int CScriptArray::GetArrayTypeId() const { - return objType->GetTypeId(); + return objType->GetTypeId(); } int CScriptArray::GetElementTypeId() const { - return subTypeId; + return subTypeId; } void CScriptArray::InsertAt(asUINT index, void *value) { - if( index > buffer->numElements ) - { - // If this is called from a script we raise a script exception - asIScriptContext *ctx = asGetActiveContext(); - if( ctx ) - ctx->SetException("Index out of bounds"); - return; - } + if( index > buffer->numElements ) + { + // If this is called from a script we raise a script exception + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Index out of bounds"); + return; + } - // Make room for the new element - Resize(1, index); + // Make room for the new element + Resize(1, index); - // Set the value of the new element - SetValue(index, value); + // Set the value of the new element + SetValue(index, value); +} + +void CScriptArray::InsertAt(asUINT index, const CScriptArray &arr) +{ + if (index > buffer->numElements) + { + asIScriptContext *ctx = asGetActiveContext(); + if (ctx) + ctx->SetException("Index out of bounds"); + return; + } + + if (objType != arr.objType) + { + // This shouldn't really be possible to happen when + // called from a script, but let's check for it anyway + asIScriptContext *ctx = asGetActiveContext(); + if (ctx) + ctx->SetException("Mismatching array types"); + return; + } + + asUINT elements = arr.GetSize(); + Resize(elements, index); + if (&arr != this) + { + for (asUINT n = 0; n < arr.GetSize(); n++) + { + // This const cast is allowed, since we know the + // value will only be used to make a copy of it + void *value = const_cast(arr.At(n)); + SetValue(index + n, value); + } + } + else + { + // The array that is being inserted is the same as this one. + // So we should iterate over the elements before the index, + // and then the elements after + for (asUINT n = 0; n < index; n++) + { + // This const cast is allowed, since we know the + // value will only be used to make a copy of it + void *value = const_cast(arr.At(n)); + SetValue(index + n, value); + } + + for (asUINT n = index + elements, m = 0; n < arr.GetSize(); n++, m++) + { + // This const cast is allowed, since we know the + // value will only be used to make a copy of it + void *value = const_cast(arr.At(n)); + SetValue(index + index + m, value); + } + } } void CScriptArray::InsertLast(void *value) { - InsertAt(buffer->numElements, value); + InsertAt(buffer->numElements, value); } void CScriptArray::RemoveAt(asUINT index) { - if( index >= buffer->numElements ) - { - // If this is called from a script we raise a script exception - asIScriptContext *ctx = asGetActiveContext(); - if( ctx ) - ctx->SetException("Index out of bounds"); - return; - } + if( index >= buffer->numElements ) + { + // If this is called from a script we raise a script exception + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Index out of bounds"); + return; + } - // Remove the element - Resize(-1, index); + // Remove the element + Resize(-1, index); } void CScriptArray::RemoveLast() { - RemoveAt(buffer->numElements-1); + RemoveAt(buffer->numElements-1); } // Return a pointer to the array element. Returns 0 if the index is out of bounds const void *CScriptArray::At(asUINT index) const { - if( buffer == 0 || index >= buffer->numElements ) - { - // If this is called from a script we raise a script exception - asIScriptContext *ctx = asGetActiveContext(); - if( ctx ) - ctx->SetException("Index out of bounds"); - return 0; - } + if( buffer == 0 || index >= buffer->numElements ) + { + // If this is called from a script we raise a script exception + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Index out of bounds"); + return 0; + } - if( (subTypeId & asTYPEID_MASK_OBJECT) && !(subTypeId & asTYPEID_OBJHANDLE) ) - return *(void**)(buffer->data + elementSize*index); - else - return buffer->data + elementSize*index; + if( (subTypeId & asTYPEID_MASK_OBJECT) && !(subTypeId & asTYPEID_OBJHANDLE) ) + return *(void**)(buffer->data + elementSize*index); + else + return buffer->data + elementSize*index; } void *CScriptArray::At(asUINT index) { - return const_cast(const_cast(this)->At(index)); + return const_cast(const_cast(this)->At(index)); +} + +void *CScriptArray::GetBuffer() +{ + return buffer->data; } // internal void CScriptArray::CreateBuffer(SArrayBuffer **buf, asUINT numElements) { - *buf = reinterpret_cast(userAlloc(sizeof(SArrayBuffer)-1+elementSize*numElements)); + *buf = reinterpret_cast(userAlloc(sizeof(SArrayBuffer)-1+elementSize*numElements)); - if( *buf ) - { - (*buf)->numElements = numElements; - (*buf)->maxElements = numElements; - Construct(*buf, 0, numElements); - } - else - { - // Oops, out of memory - asIScriptContext *ctx = asGetActiveContext(); - if( ctx ) - ctx->SetException("Out of memory"); - } + if( *buf ) + { + (*buf)->numElements = numElements; + (*buf)->maxElements = numElements; + Construct(*buf, 0, numElements); + } + else + { + // Oops, out of memory + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Out of memory"); + } } // internal void CScriptArray::DeleteBuffer(SArrayBuffer *buf) { - Destruct(buf, 0, buf->numElements); + Destruct(buf, 0, buf->numElements); - // Free the buffer - userFree(buf); + // Free the buffer + userFree(buf); } // internal void CScriptArray::Construct(SArrayBuffer *buf, asUINT start, asUINT end) { - if( (subTypeId & asTYPEID_MASK_OBJECT) && !(subTypeId & asTYPEID_OBJHANDLE) ) - { - // Create an object using the default constructor/factory for each element - void **max = (void**)(buf->data + end * sizeof(void*)); - void **d = (void**)(buf->data + start * sizeof(void*)); + if( (subTypeId & asTYPEID_MASK_OBJECT) && !(subTypeId & asTYPEID_OBJHANDLE) ) + { + // Create an object using the default constructor/factory for each element + void **max = (void**)(buf->data + end * sizeof(void*)); + void **d = (void**)(buf->data + start * sizeof(void*)); - asIScriptEngine *engine = objType->GetEngine(); - asIObjectType *subType = objType->GetSubType(); + asIScriptEngine *engine = objType->GetEngine(); + asITypeInfo *subType = objType->GetSubType(); - for( ; d < max; d++ ) - { - *d = (void*)engine->CreateScriptObject(subType); - if( *d == 0 ) - { - // Set the remaining entries to null so the destructor - // won't attempt to destroy invalid objects later - memset(d, 0, sizeof(void*)*(max-d)); + for( ; d < max; d++ ) + { + *d = (void*)engine->CreateScriptObject(subType); + if( *d == 0 ) + { + // Set the remaining entries to null so the destructor + // won't attempt to destroy invalid objects later + memset(d, 0, sizeof(void*)*(max-d)); - // There is no need to set an exception on the context, - // as CreateScriptObject has already done that - return; - } - } - } - else - { - // Set all elements to zero whether they are handles or primitives - void *d = (void*)(buf->data + start * elementSize); - memset(d, 0, (end-start)*elementSize); - } + // There is no need to set an exception on the context, + // as CreateScriptObject has already done that + return; + } + } + } + else + { + // Set all elements to zero whether they are handles or primitives + void *d = (void*)(buf->data + start * elementSize); + memset(d, 0, (end-start)*elementSize); + } } // internal void CScriptArray::Destruct(SArrayBuffer *buf, asUINT start, asUINT end) { - if( subTypeId & asTYPEID_MASK_OBJECT ) - { - asIScriptEngine *engine = objType->GetEngine(); + if( subTypeId & asTYPEID_MASK_OBJECT ) + { + asIScriptEngine *engine = objType->GetEngine(); - void **max = (void**)(buf->data + end * sizeof(void*)); - void **d = (void**)(buf->data + start * sizeof(void*)); + void **max = (void**)(buf->data + end * sizeof(void*)); + void **d = (void**)(buf->data + start * sizeof(void*)); - for( ; d < max; d++ ) - { - if( *d ) - engine->ReleaseScriptObject(*d, objType->GetSubType()); - } - } + for( ; d < max; d++ ) + { + if( *d ) + engine->ReleaseScriptObject(*d, objType->GetSubType()); + } + } } // internal bool CScriptArray::Less(const void *a, const void *b, bool asc, asIScriptContext *ctx, SArrayCache *cache) { - if( !asc ) - { - // Swap items - const void *TEMP = a; - a = b; - b = TEMP; - } + if( !asc ) + { + // Swap items + const void *TEMP = a; + a = b; + b = TEMP; + } - if( !(subTypeId & ~asTYPEID_MASK_SEQNBR) ) - { - // Simple compare of values - switch( subTypeId ) - { - #define COMPARE(T) *((T*)a) < *((T*)b) - case asTYPEID_BOOL: return COMPARE(bool); - case asTYPEID_INT8: return COMPARE(signed char); - case asTYPEID_UINT8: return COMPARE(unsigned char); - case asTYPEID_INT16: return COMPARE(signed short); - case asTYPEID_UINT16: return COMPARE(unsigned short); - case asTYPEID_INT32: return COMPARE(signed int); - case asTYPEID_UINT32: return COMPARE(unsigned int); - case asTYPEID_FLOAT: return COMPARE(float); - case asTYPEID_DOUBLE: return COMPARE(double); - default: return COMPARE(signed int); // All enums fall in this case - #undef COMPARE - } - } - else - { - if( subTypeId & asTYPEID_OBJHANDLE ) - { - // Allow sort to work even if the array contains null handles - if( *(void**)a == 0 ) return true; - if( *(void**)b == 0 ) return false; - } + if( !(subTypeId & ~asTYPEID_MASK_SEQNBR) ) + { + // Simple compare of values + switch( subTypeId ) + { + #define COMPARE(T) *((T*)a) < *((T*)b) + case asTYPEID_BOOL: return COMPARE(bool); + case asTYPEID_INT8: return COMPARE(signed char); + case asTYPEID_UINT8: return COMPARE(unsigned char); + case asTYPEID_INT16: return COMPARE(signed short); + case asTYPEID_UINT16: return COMPARE(unsigned short); + case asTYPEID_INT32: return COMPARE(signed int); + case asTYPEID_UINT32: return COMPARE(unsigned int); + case asTYPEID_FLOAT: return COMPARE(float); + case asTYPEID_DOUBLE: return COMPARE(double); + default: return COMPARE(signed int); // All enums fall in this case + #undef COMPARE + } + } + else + { + int r = 0; - // Execute object opCmp - if( cache && cache->cmpFunc ) - { - // TODO: Add proper error handling - int r = ctx->Prepare(cache->cmpFunc); assert(r >= 0); + if( subTypeId & asTYPEID_OBJHANDLE ) + { + // Allow sort to work even if the array contains null handles + if( *(void**)a == 0 ) return true; + if( *(void**)b == 0 ) return false; + } - if( subTypeId & asTYPEID_OBJHANDLE ) - { - r = ctx->SetObject(*((void**)a)); assert(r >= 0); - r = ctx->SetArgObject(0, *((void**)b)); assert(r >= 0); - } - else - { - r = ctx->SetObject((void*)a); assert(r >= 0); - r = ctx->SetArgObject(0, (void*)b); assert(r >= 0); - } + // Execute object opCmp + if( cache && cache->cmpFunc ) + { + // TODO: Add proper error handling + r = ctx->Prepare(cache->cmpFunc); assert(r >= 0); - r = ctx->Execute(); + if( subTypeId & asTYPEID_OBJHANDLE ) + { + r = ctx->SetObject(*((void**)a)); assert(r >= 0); + r = ctx->SetArgObject(0, *((void**)b)); assert(r >= 0); + } + else + { + r = ctx->SetObject((void*)a); assert(r >= 0); + r = ctx->SetArgObject(0, (void*)b); assert(r >= 0); + } - if( r == asEXECUTION_FINISHED ) - { - return (int)ctx->GetReturnDWord() < 0; - } - } - } + r = ctx->Execute(); - return false; + if( r == asEXECUTION_FINISHED ) + { + return (int)ctx->GetReturnDWord() < 0; + } + } + } + + return false; } void CScriptArray::Reverse() { - asUINT size = GetSize(); + asUINT size = GetSize(); - if( size >= 2 ) - { - asBYTE TEMP[16]; + if( size >= 2 ) + { + asBYTE TEMP[16]; - for( asUINT i = 0; i < size / 2; i++ ) - { - Copy(TEMP, GetArrayItemPointer(i)); - Copy(GetArrayItemPointer(i), GetArrayItemPointer(size - i - 1)); - Copy(GetArrayItemPointer(size - i - 1), TEMP); - } - } + for( asUINT i = 0; i < size / 2; i++ ) + { + Copy(TEMP, GetArrayItemPointer(i)); + Copy(GetArrayItemPointer(i), GetArrayItemPointer(size - i - 1)); + Copy(GetArrayItemPointer(size - i - 1), TEMP); + } + } } bool CScriptArray::operator==(const CScriptArray &other) const { - if( objType != other.objType ) - return false; + if( objType != other.objType ) + return false; - if( GetSize() != other.GetSize() ) - return false; + if( GetSize() != other.GetSize() ) + return false; - asIScriptContext *cmpContext = 0; - bool isNested = false; + asIScriptContext *cmpContext = 0; + bool isNested = false; - if( subTypeId & ~asTYPEID_MASK_SEQNBR ) - { - // Try to reuse the active context - cmpContext = asGetActiveContext(); - if( cmpContext ) - { - if( cmpContext->GetEngine() == objType->GetEngine() && cmpContext->PushState() >= 0 ) - isNested = true; - else - cmpContext = 0; - } - if( cmpContext == 0 ) - { - // TODO: Ideally this context would be retrieved from a pool, so we don't have to - // create a new one everytime. We could keep a context with the array object - // but that would consume a lot of resources as each context is quite heavy. - cmpContext = objType->GetEngine()->CreateContext(); - } - } + if( subTypeId & ~asTYPEID_MASK_SEQNBR ) + { + // Try to reuse the active context + cmpContext = asGetActiveContext(); + if( cmpContext ) + { + if( cmpContext->GetEngine() == objType->GetEngine() && cmpContext->PushState() >= 0 ) + isNested = true; + else + cmpContext = 0; + } + if( cmpContext == 0 ) + { + // TODO: Ideally this context would be retrieved from a pool, so we don't have to + // create a new one everytime. We could keep a context with the array object + // but that would consume a lot of resources as each context is quite heavy. + cmpContext = objType->GetEngine()->CreateContext(); + } + } - // Check if all elements are equal - bool isEqual = true; - SArrayCache *cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); - for( asUINT n = 0; n < GetSize(); n++ ) - if( !Equals(At(n), other.At(n), cmpContext, cache) ) - { - isEqual = false; - break; - } + // Check if all elements are equal + bool isEqual = true; + SArrayCache *cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); + for( asUINT n = 0; n < GetSize(); n++ ) + if( !Equals(At(n), other.At(n), cmpContext, cache) ) + { + isEqual = false; + break; + } - if( cmpContext ) - { - if( isNested ) - { - asEContextState state = cmpContext->GetState(); - cmpContext->PopState(); - if( state == asEXECUTION_ABORTED ) - cmpContext->Abort(); - } - else - cmpContext->Release(); - } + if( cmpContext ) + { + if( isNested ) + { + asEContextState state = cmpContext->GetState(); + cmpContext->PopState(); + if( state == asEXECUTION_ABORTED ) + cmpContext->Abort(); + } + else + cmpContext->Release(); + } - return isEqual; + return isEqual; } // internal bool CScriptArray::Equals(const void *a, const void *b, asIScriptContext *ctx, SArrayCache *cache) const { - if( !(subTypeId & ~asTYPEID_MASK_SEQNBR) ) - { - // Simple compare of values - switch( subTypeId ) - { - #define COMPARE(T) *((T*)a) == *((T*)b) - case asTYPEID_BOOL: return COMPARE(bool); - case asTYPEID_INT8: return COMPARE(signed char); - case asTYPEID_UINT8: return COMPARE(unsigned char); - case asTYPEID_INT16: return COMPARE(signed short); - case asTYPEID_UINT16: return COMPARE(unsigned short); - case asTYPEID_INT32: return COMPARE(signed int); - case asTYPEID_UINT32: return COMPARE(unsigned int); - case asTYPEID_FLOAT: return COMPARE(float); - case asTYPEID_DOUBLE: return COMPARE(double); - default: return COMPARE(signed int); // All enums fall here - #undef COMPARE - } - } - else - { - int r = 0; + if( !(subTypeId & ~asTYPEID_MASK_SEQNBR) ) + { + // Simple compare of values + switch( subTypeId ) + { + #define COMPARE(T) *((T*)a) == *((T*)b) + case asTYPEID_BOOL: return COMPARE(bool); + case asTYPEID_INT8: return COMPARE(signed char); + case asTYPEID_UINT8: return COMPARE(unsigned char); + case asTYPEID_INT16: return COMPARE(signed short); + case asTYPEID_UINT16: return COMPARE(unsigned short); + case asTYPEID_INT32: return COMPARE(signed int); + case asTYPEID_UINT32: return COMPARE(unsigned int); + case asTYPEID_FLOAT: return COMPARE(float); + case asTYPEID_DOUBLE: return COMPARE(double); + default: return COMPARE(signed int); // All enums fall here + #undef COMPARE + } + } + else + { + int r = 0; - if( subTypeId & asTYPEID_OBJHANDLE ) - { - // Allow the find to work even if the array contains null handles - if( *(void**)a == *(void**)b ) return true; - } + if( subTypeId & asTYPEID_OBJHANDLE ) + { + // Allow the find to work even if the array contains null handles + if( *(void**)a == *(void**)b ) return true; + } - // Execute object opEquals if available - if( cache && cache->eqFunc ) - { - // TODO: Add proper error handling - r = ctx->Prepare(cache->eqFunc); assert(r >= 0); + // Execute object opEquals if available + if( cache && cache->eqFunc ) + { + // TODO: Add proper error handling + r = ctx->Prepare(cache->eqFunc); assert(r >= 0); - if( subTypeId & asTYPEID_OBJHANDLE ) - { - r = ctx->SetObject(*((void**)a)); assert(r >= 0); - r = ctx->SetArgObject(0, *((void**)b)); assert(r >= 0); - } - else - { - r = ctx->SetObject((void*)a); assert(r >= 0); - r = ctx->SetArgObject(0, (void*)b); assert(r >= 0); - } + if( subTypeId & asTYPEID_OBJHANDLE ) + { + r = ctx->SetObject(*((void**)a)); assert(r >= 0); + r = ctx->SetArgObject(0, *((void**)b)); assert(r >= 0); + } + else + { + r = ctx->SetObject((void*)a); assert(r >= 0); + r = ctx->SetArgObject(0, (void*)b); assert(r >= 0); + } - r = ctx->Execute(); + r = ctx->Execute(); - if( r == asEXECUTION_FINISHED ) - return ctx->GetReturnByte() != 0; + if( r == asEXECUTION_FINISHED ) + return ctx->GetReturnByte() != 0; - return false; - } + return false; + } - // Execute object opCmp if available - if( cache && cache->cmpFunc ) - { - // TODO: Add proper error handling - r = ctx->Prepare(cache->cmpFunc); assert(r >= 0); + // Execute object opCmp if available + if( cache && cache->cmpFunc ) + { + // TODO: Add proper error handling + r = ctx->Prepare(cache->cmpFunc); assert(r >= 0); - if( subTypeId & asTYPEID_OBJHANDLE ) - { - r = ctx->SetObject(*((void**)a)); assert(r >= 0); - r = ctx->SetArgObject(0, *((void**)b)); assert(r >= 0); - } - else - { - r = ctx->SetObject((void*)a); assert(r >= 0); - r = ctx->SetArgObject(0, (void*)b); assert(r >= 0); - } + if( subTypeId & asTYPEID_OBJHANDLE ) + { + r = ctx->SetObject(*((void**)a)); assert(r >= 0); + r = ctx->SetArgObject(0, *((void**)b)); assert(r >= 0); + } + else + { + r = ctx->SetObject((void*)a); assert(r >= 0); + r = ctx->SetArgObject(0, (void*)b); assert(r >= 0); + } - r = ctx->Execute(); + r = ctx->Execute(); - if( r == asEXECUTION_FINISHED ) - return (int)ctx->GetReturnDWord() == 0; + if( r == asEXECUTION_FINISHED ) + return (int)ctx->GetReturnDWord() == 0; - return false; - } - } + return false; + } + } - return false; + return false; } int CScriptArray::FindByRef(void *ref) const { - return FindByRef(0, ref); + return FindByRef(0, ref); } int CScriptArray::FindByRef(asUINT startAt, void *ref) const { - // Find the matching element by its reference - asUINT size = GetSize(); - if( subTypeId & asTYPEID_OBJHANDLE ) - { - // Dereference the pointer - ref = *(void**)ref; - for( asUINT i = startAt; i < size; i++ ) - { - if( *(void**)At(i) == ref ) - return i; - } - } - else - { - // Compare the reference directly - for( asUINT i = startAt; i < size; i++ ) - { - if( At(i) == ref ) - return i; - } - } + // Find the matching element by its reference + asUINT size = GetSize(); + if( subTypeId & asTYPEID_OBJHANDLE ) + { + // Dereference the pointer + ref = *(void**)ref; + for( asUINT i = startAt; i < size; i++ ) + { + if( *(void**)At(i) == ref ) + return i; + } + } + else + { + // Compare the reference directly + for( asUINT i = startAt; i < size; i++ ) + { + if( At(i) == ref ) + return i; + } + } - return -1; + return -1; } int CScriptArray::Find(void *value) const { - return Find(0, value); + return Find(0, value); } int CScriptArray::Find(asUINT startAt, void *value) const { - // Check if the subtype really supports find() - // TODO: Can't this be done at compile time too by the template callback - SArrayCache *cache = 0; - if( subTypeId & ~asTYPEID_MASK_SEQNBR ) - { - cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); - if( !cache || (cache->cmpFunc == 0 && cache->eqFunc == 0) ) - { - asIScriptContext *ctx = asGetActiveContext(); - asIObjectType* subType = objType->GetEngine()->GetObjectTypeById(subTypeId); + // Check if the subtype really supports find() + // TODO: Can't this be done at compile time too by the template callback + SArrayCache *cache = 0; + if( subTypeId & ~asTYPEID_MASK_SEQNBR ) + { + cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); + if( !cache || (cache->cmpFunc == 0 && cache->eqFunc == 0) ) + { + asIScriptContext *ctx = asGetActiveContext(); + asITypeInfo* subType = objType->GetEngine()->GetTypeInfoById(subTypeId); - // Throw an exception - if( ctx ) - { - char tmp[512]; + // Throw an exception + if( ctx ) + { + char tmp[512]; - if( cache && cache->eqFuncReturnCode == asMULTIPLE_FUNCTIONS ) + if( cache && cache->eqFuncReturnCode == asMULTIPLE_FUNCTIONS ) #if defined(_MSC_VER) && _MSC_VER >= 1500 && !defined(__S3E__) - sprintf_s(tmp, 512, "Type '%s' has multiple matching opEquals or opCmp methods", subType->GetName()); + sprintf_s(tmp, 512, "Type '%s' has multiple matching opEquals or opCmp methods", subType->GetName()); #else - sprintf(tmp, "Type '%s' has multiple matching opEquals or opCmp methods", subType->GetName()); + sprintf(tmp, "Type '%s' has multiple matching opEquals or opCmp methods", subType->GetName()); #endif - else + else #if defined(_MSC_VER) && _MSC_VER >= 1500 && !defined(__S3E__) - sprintf_s(tmp, 512, "Type '%s' does not have a matching opEquals or opCmp method", subType->GetName()); + sprintf_s(tmp, 512, "Type '%s' does not have a matching opEquals or opCmp method", subType->GetName()); #else - sprintf(tmp, "Type '%s' does not have a matching opEquals or opCmp method", subType->GetName()); + sprintf(tmp, "Type '%s' does not have a matching opEquals or opCmp method", subType->GetName()); #endif - ctx->SetException(tmp); - } + ctx->SetException(tmp); + } - return -1; - } - } + return -1; + } + } - asIScriptContext *cmpContext = 0; - bool isNested = false; + asIScriptContext *cmpContext = 0; + bool isNested = false; - if( subTypeId & ~asTYPEID_MASK_SEQNBR ) - { - // Try to reuse the active context - cmpContext = asGetActiveContext(); - if( cmpContext ) - { - if( cmpContext->GetEngine() == objType->GetEngine() && cmpContext->PushState() >= 0 ) - isNested = true; - else - cmpContext = 0; - } - if( cmpContext == 0 ) - { - // TODO: Ideally this context would be retrieved from a pool, so we don't have to - // create a new one everytime. We could keep a context with the array object - // but that would consume a lot of resources as each context is quite heavy. - cmpContext = objType->GetEngine()->CreateContext(); - } - } + if( subTypeId & ~asTYPEID_MASK_SEQNBR ) + { + // Try to reuse the active context + cmpContext = asGetActiveContext(); + if( cmpContext ) + { + if( cmpContext->GetEngine() == objType->GetEngine() && cmpContext->PushState() >= 0 ) + isNested = true; + else + cmpContext = 0; + } + if( cmpContext == 0 ) + { + // TODO: Ideally this context would be retrieved from a pool, so we don't have to + // create a new one everytime. We could keep a context with the array object + // but that would consume a lot of resources as each context is quite heavy. + cmpContext = objType->GetEngine()->CreateContext(); + } + } - // Find the matching element - int ret = -1; - asUINT size = GetSize(); + // Find the matching element + int ret = -1; + asUINT size = GetSize(); - for( asUINT i = startAt; i < size; i++ ) - { - // value passed by reference - if( Equals(At(i), value, cmpContext, cache) ) - { - ret = (int)i; - break; - } - } + for( asUINT i = startAt; i < size; i++ ) + { + // value passed by reference + if( Equals(At(i), value, cmpContext, cache) ) + { + ret = (int)i; + break; + } + } - if( cmpContext ) - { - if( isNested ) - { - asEContextState state = cmpContext->GetState(); - cmpContext->PopState(); - if( state == asEXECUTION_ABORTED ) - cmpContext->Abort(); - } - else - cmpContext->Release(); - } + if( cmpContext ) + { + if( isNested ) + { + asEContextState state = cmpContext->GetState(); + cmpContext->PopState(); + if( state == asEXECUTION_ABORTED ) + cmpContext->Abort(); + } + else + cmpContext->Release(); + } - return ret; + return ret; } // internal // Copy object handle or primitive value +// Even in arrays of objects the objects are allocated on +// the heap and the array stores the pointers to the objects void CScriptArray::Copy(void *dst, void *src) { - memcpy(dst, src, elementSize); + memcpy(dst, src, elementSize); } @@ -1312,397 +1395,475 @@ void CScriptArray::Copy(void *dst, void *src) // Return pointer to array item (object handle or primitive value) void *CScriptArray::GetArrayItemPointer(int index) { - return buffer->data + index * elementSize; + return buffer->data + index * elementSize; } // internal // Return pointer to data in buffer (object or primitive) -void *CScriptArray::GetDataPointer(void *buffer) +void *CScriptArray::GetDataPointer(void *buf) { - if ((subTypeId & asTYPEID_MASK_OBJECT) && !(subTypeId & asTYPEID_OBJHANDLE) ) - { - // Real address of object - return reinterpret_cast(*(size_t*)buffer); - } - else - { - // Primitive is just a raw data - return buffer; - } + if ((subTypeId & asTYPEID_MASK_OBJECT) && !(subTypeId & asTYPEID_OBJHANDLE) ) + { + // Real address of object + return reinterpret_cast(*(size_t*)buf); + } + else + { + // Primitive is just a raw data + return buf; + } } // Sort ascending void CScriptArray::SortAsc() { - Sort(0, GetSize(), true); + Sort(0, GetSize(), true); } // Sort ascending void CScriptArray::SortAsc(asUINT startAt, asUINT count) { - Sort(startAt, count, true); + Sort(startAt, count, true); } // Sort descending void CScriptArray::SortDesc() { - Sort(0, GetSize(), false); + Sort(0, GetSize(), false); } // Sort descending void CScriptArray::SortDesc(asUINT startAt, asUINT count) { - Sort(startAt, count, false); + Sort(startAt, count, false); } // internal void CScriptArray::Sort(asUINT startAt, asUINT count, bool asc) { - // Subtype isn't primitive and doesn't have opCmp - SArrayCache *cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); - if( subTypeId & ~asTYPEID_MASK_SEQNBR ) - { - if( !cache || cache->cmpFunc == 0 ) - { - asIScriptContext *ctx = asGetActiveContext(); - asIObjectType* subType = objType->GetEngine()->GetObjectTypeById(subTypeId); + // Subtype isn't primitive and doesn't have opCmp + SArrayCache *cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); + if( subTypeId & ~asTYPEID_MASK_SEQNBR ) + { + if( !cache || cache->cmpFunc == 0 ) + { + asIScriptContext *ctx = asGetActiveContext(); + asITypeInfo* subType = objType->GetEngine()->GetTypeInfoById(subTypeId); - // Throw an exception - if( ctx ) - { - char tmp[512]; + // Throw an exception + if( ctx ) + { + char tmp[512]; - if( cache && cache->cmpFuncReturnCode == asMULTIPLE_FUNCTIONS ) + if( cache && cache->cmpFuncReturnCode == asMULTIPLE_FUNCTIONS ) #if defined(_MSC_VER) && _MSC_VER >= 1500 && !defined(__S3E__) - sprintf_s(tmp, 512, "Type '%s' has multiple matching opCmp methods", subType->GetName()); + sprintf_s(tmp, 512, "Type '%s' has multiple matching opCmp methods", subType->GetName()); #else - sprintf(tmp, "Type '%s' has multiple matching opCmp methods", subType->GetName()); + sprintf(tmp, "Type '%s' has multiple matching opCmp methods", subType->GetName()); #endif - else + else #if defined(_MSC_VER) && _MSC_VER >= 1500 && !defined(__S3E__) - sprintf_s(tmp, 512, "Type '%s' does not have a matching opCmp method", subType->GetName()); + sprintf_s(tmp, 512, "Type '%s' does not have a matching opCmp method", subType->GetName()); #else - sprintf(tmp, "Type '%s' does not have a matching opCmp method", subType->GetName()); + sprintf(tmp, "Type '%s' does not have a matching opCmp method", subType->GetName()); #endif - ctx->SetException(tmp); - } + ctx->SetException(tmp); + } - return; - } - } + return; + } + } - // No need to sort - if( count < 2 ) - { - return; - } + // No need to sort + if( count < 2 ) + { + return; + } - int start = startAt; - int end = startAt + count; + int start = startAt; + int end = startAt + count; - // Check if we could access invalid item while sorting - if( start >= (int)buffer->numElements || end > (int)buffer->numElements ) - { - asIScriptContext *ctx = asGetActiveContext(); + // Check if we could access invalid item while sorting + if( start >= (int)buffer->numElements || end > (int)buffer->numElements ) + { + asIScriptContext *ctx = asGetActiveContext(); - // Throw an exception - if( ctx ) - { - ctx->SetException("Index out of bounds"); - } + // Throw an exception + if( ctx ) + { + ctx->SetException("Index out of bounds"); + } - return; - } + return; + } - asBYTE tmp[16]; - asIScriptContext *cmpContext = 0; - bool isNested = false; + asBYTE tmp[16]; + asIScriptContext *cmpContext = 0; + bool isNested = false; - if( subTypeId & ~asTYPEID_MASK_SEQNBR ) - { - // Try to reuse the active context - cmpContext = asGetActiveContext(); - if( cmpContext ) - { - if( cmpContext->GetEngine() == objType->GetEngine() && cmpContext->PushState() >= 0 ) - isNested = true; - else - cmpContext = 0; - } - if( cmpContext == 0 ) - { - // TODO: Ideally this context would be retrieved from a pool, so we don't have to - // create a new one everytime. We could keep a context with the array object - // but that would consume a lot of resources as each context is quite heavy. - cmpContext = objType->GetEngine()->CreateContext(); - } - } + if( subTypeId & ~asTYPEID_MASK_SEQNBR ) + { + // Try to reuse the active context + cmpContext = asGetActiveContext(); + if( cmpContext ) + { + if( cmpContext->GetEngine() == objType->GetEngine() && cmpContext->PushState() >= 0 ) + isNested = true; + else + cmpContext = 0; + } + if( cmpContext == 0 ) + { + cmpContext = objType->GetEngine()->RequestContext(); + } + } - // Insertion sort - for( int i = start + 1; i < end; i++ ) - { - Copy(tmp, GetArrayItemPointer(i)); + // Insertion sort + for( int i = start + 1; i < end; i++ ) + { + Copy(tmp, GetArrayItemPointer(i)); - int j = i - 1; + int j = i - 1; - while( j >= start && Less(GetDataPointer(tmp), At(j), asc, cmpContext, cache) ) - { - Copy(GetArrayItemPointer(j + 1), GetArrayItemPointer(j)); - j--; - } + while( j >= start && Less(GetDataPointer(tmp), At(j), asc, cmpContext, cache) ) + { + Copy(GetArrayItemPointer(j + 1), GetArrayItemPointer(j)); + j--; + } - Copy(GetArrayItemPointer(j + 1), tmp); - } + Copy(GetArrayItemPointer(j + 1), tmp); + } - if( cmpContext ) - { - if( isNested ) - { - asEContextState state = cmpContext->GetState(); - cmpContext->PopState(); - if( state == asEXECUTION_ABORTED ) - cmpContext->Abort(); - } - else - cmpContext->Release(); - } + if( cmpContext ) + { + if( isNested ) + { + asEContextState state = cmpContext->GetState(); + cmpContext->PopState(); + if( state == asEXECUTION_ABORTED ) + cmpContext->Abort(); + } + else + objType->GetEngine()->ReturnContext(cmpContext); + } +} + +// Sort with script callback for comparing elements +void CScriptArray::Sort(asIScriptFunction *func, asUINT startAt, asUINT count) +{ + // No need to sort + if (count < 2) + return; + + // Check if we could access invalid item while sorting + asUINT start = startAt; + asUINT end = asQWORD(startAt) + asQWORD(count) >= (asQWORD(1)<<32) ? 0xFFFFFFFF : startAt + count; + if (end > buffer->numElements) + end = buffer->numElements; + + if (start >= buffer->numElements) + { + asIScriptContext *ctx = asGetActiveContext(); + + // Throw an exception + if (ctx) + ctx->SetException("Index out of bounds"); + + return; + } + + asBYTE tmp[16]; + asIScriptContext *cmpContext = 0; + bool isNested = false; + + // Try to reuse the active context + cmpContext = asGetActiveContext(); + if (cmpContext) + { + if (cmpContext->GetEngine() == objType->GetEngine() && cmpContext->PushState() >= 0) + isNested = true; + else + cmpContext = 0; + } + if (cmpContext == 0) + cmpContext = objType->GetEngine()->RequestContext(); + + // Insertion sort + for (asUINT i = start + 1; i < end; i++) + { + Copy(tmp, GetArrayItemPointer(i)); + + asUINT j = i - 1; + + while (j != 0xFFFFFFFF && j >= start ) + { + cmpContext->Prepare(func); + cmpContext->SetArgAddress(0, GetDataPointer(tmp)); + cmpContext->SetArgAddress(1, At(j)); + int r = cmpContext->Execute(); + if (r != asEXECUTION_FINISHED) + break; + if (*(bool*)(cmpContext->GetAddressOfReturnValue())) + { + Copy(GetArrayItemPointer(j + 1), GetArrayItemPointer(j)); + j--; + } + else + break; + } + + Copy(GetArrayItemPointer(j + 1), tmp); + } + + if (cmpContext) + { + if (isNested) + { + asEContextState state = cmpContext->GetState(); + cmpContext->PopState(); + if (state == asEXECUTION_ABORTED) + cmpContext->Abort(); + } + else + objType->GetEngine()->ReturnContext(cmpContext); + } } // internal void CScriptArray::CopyBuffer(SArrayBuffer *dst, SArrayBuffer *src) { - asIScriptEngine *engine = objType->GetEngine(); - if( subTypeId & asTYPEID_OBJHANDLE ) - { - // Copy the references and increase the reference counters - if( dst->numElements > 0 && src->numElements > 0 ) - { - int count = dst->numElements > src->numElements ? src->numElements : dst->numElements; + asIScriptEngine *engine = objType->GetEngine(); + if( subTypeId & asTYPEID_OBJHANDLE ) + { + // Copy the references and increase the reference counters + if( dst->numElements > 0 && src->numElements > 0 ) + { + int count = dst->numElements > src->numElements ? src->numElements : dst->numElements; - void **max = (void**)(dst->data + count * sizeof(void*)); - void **d = (void**)dst->data; - void **s = (void**)src->data; + void **max = (void**)(dst->data + count * sizeof(void*)); + void **d = (void**)dst->data; + void **s = (void**)src->data; - for( ; d < max; d++, s++ ) - { - void *tmp = *d; - *d = *s; - if( *d ) - engine->AddRefScriptObject(*d, objType->GetSubType()); - // Release the old ref after incrementing the new to avoid problem incase it is the same ref - if( tmp ) - engine->ReleaseScriptObject(tmp, objType->GetSubType()); - } - } - } - else - { - if( dst->numElements > 0 && src->numElements > 0 ) - { - int count = dst->numElements > src->numElements ? src->numElements : dst->numElements; - if( subTypeId & asTYPEID_MASK_OBJECT ) - { - // Call the assignment operator on all of the objects - void **max = (void**)(dst->data + count * sizeof(void*)); - void **d = (void**)dst->data; - void **s = (void**)src->data; + for( ; d < max; d++, s++ ) + { + void *tmp = *d; + *d = *s; + if( *d ) + engine->AddRefScriptObject(*d, objType->GetSubType()); + // Release the old ref after incrementing the new to avoid problem incase it is the same ref + if( tmp ) + engine->ReleaseScriptObject(tmp, objType->GetSubType()); + } + } + } + else + { + if( dst->numElements > 0 && src->numElements > 0 ) + { + int count = dst->numElements > src->numElements ? src->numElements : dst->numElements; + if( subTypeId & asTYPEID_MASK_OBJECT ) + { + // Call the assignment operator on all of the objects + void **max = (void**)(dst->data + count * sizeof(void*)); + void **d = (void**)dst->data; + void **s = (void**)src->data; - asIObjectType *subType = objType->GetSubType(); - for( ; d < max; d++, s++ ) - engine->AssignScriptObject(*d, *s, subType); - } - else - { - // Primitives are copied byte for byte - memcpy(dst->data, src->data, count*elementSize); - } - } - } + asITypeInfo *subType = objType->GetSubType(); + for( ; d < max; d++, s++ ) + engine->AssignScriptObject(*d, *s, subType); + } + else + { + // Primitives are copied byte for byte + memcpy(dst->data, src->data, count*elementSize); + } + } + } } // internal // Precache some info void CScriptArray::Precache() { - subTypeId = objType->GetSubTypeId(); + subTypeId = objType->GetSubTypeId(); - // Check if it is an array of objects. Only for these do we need to cache anything - // Type ids for primitives and enums only has the sequence number part - if( !(subTypeId & ~asTYPEID_MASK_SEQNBR) ) - return; + // Check if it is an array of objects. Only for these do we need to cache anything + // Type ids for primitives and enums only has the sequence number part + if( !(subTypeId & ~asTYPEID_MASK_SEQNBR) ) + return; - // The opCmp and opEquals methods are cached because the searching for the - // methods is quite time consuming if a lot of array objects are created. + // The opCmp and opEquals methods are cached because the searching for the + // methods is quite time consuming if a lot of array objects are created. - // First check if a cache already exists for this array type - SArrayCache *cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); - if( cache ) return; + // First check if a cache already exists for this array type + SArrayCache *cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); + if( cache ) return; - // We need to make sure the cache is created only once, even - // if multiple threads reach the same point at the same time - asAcquireExclusiveLock(); + // We need to make sure the cache is created only once, even + // if multiple threads reach the same point at the same time + asAcquireExclusiveLock(); - // Now that we got the lock, we need to check again to make sure the - // cache wasn't created while we were waiting for the lock - cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); - if( cache ) - { - asReleaseExclusiveLock(); - return; - } + // Now that we got the lock, we need to check again to make sure the + // cache wasn't created while we were waiting for the lock + cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); + if( cache ) + { + asReleaseExclusiveLock(); + return; + } - // Create the cache - cache = reinterpret_cast(userAlloc(sizeof(SArrayCache))); - memset(cache, 0, sizeof(SArrayCache)); + // Create the cache + cache = reinterpret_cast(userAlloc(sizeof(SArrayCache))); + memset(cache, 0, sizeof(SArrayCache)); - // If the sub type is a handle to const, then the methods must be const too - bool mustBeConst = (subTypeId & asTYPEID_HANDLETOCONST) ? true : false; + // If the sub type is a handle to const, then the methods must be const too + bool mustBeConst = (subTypeId & asTYPEID_HANDLETOCONST) ? true : false; - asIObjectType *subType = objType->GetEngine()->GetObjectTypeById(subTypeId); - if( subType ) - { - for( asUINT i = 0; i < subType->GetMethodCount(); i++ ) - { - asIScriptFunction *func = subType->GetMethodByIndex(i); + asITypeInfo *subType = objType->GetEngine()->GetTypeInfoById(subTypeId); + if( subType ) + { + for( asUINT i = 0; i < subType->GetMethodCount(); i++ ) + { + asIScriptFunction *func = subType->GetMethodByIndex(i); - if( func->GetParamCount() == 1 && (!mustBeConst || func->IsReadOnly()) ) - { - asDWORD flags = 0; - int returnTypeId = func->GetReturnTypeId(&flags); + if( func->GetParamCount() == 1 && (!mustBeConst || func->IsReadOnly()) ) + { + asDWORD flags = 0; + int returnTypeId = func->GetReturnTypeId(&flags); - // The method must not return a reference - if( flags != asTM_NONE ) - continue; + // The method must not return a reference + if( flags != asTM_NONE ) + continue; - // opCmp returns an int and opEquals returns a bool - bool isCmp = false, isEq = false; - if( returnTypeId == asTYPEID_INT32 && strcmp(func->GetName(), "opCmp") == 0 ) - isCmp = true; - if( returnTypeId == asTYPEID_BOOL && strcmp(func->GetName(), "opEquals") == 0 ) - isEq = true; + // opCmp returns an int and opEquals returns a bool + bool isCmp = false, isEq = false; + if( returnTypeId == asTYPEID_INT32 && strcmp(func->GetName(), "opCmp") == 0 ) + isCmp = true; + if( returnTypeId == asTYPEID_BOOL && strcmp(func->GetName(), "opEquals") == 0 ) + isEq = true; - if( !isCmp && !isEq ) - continue; + if( !isCmp && !isEq ) + continue; - // The parameter must either be a reference to the subtype or a handle to the subtype - int paramTypeId; - func->GetParam(0, ¶mTypeId, &flags); + // The parameter must either be a reference to the subtype or a handle to the subtype + int paramTypeId; + func->GetParam(0, ¶mTypeId, &flags); - if( (paramTypeId & ~(asTYPEID_OBJHANDLE|asTYPEID_HANDLETOCONST)) != (subTypeId & ~(asTYPEID_OBJHANDLE|asTYPEID_HANDLETOCONST)) ) - continue; + if( (paramTypeId & ~(asTYPEID_OBJHANDLE|asTYPEID_HANDLETOCONST)) != (subTypeId & ~(asTYPEID_OBJHANDLE|asTYPEID_HANDLETOCONST)) ) + continue; - if( (flags & asTM_INREF) ) - { - if( (paramTypeId & asTYPEID_OBJHANDLE) || (mustBeConst && !(flags & asTM_CONST)) ) - continue; - } - else if( paramTypeId & asTYPEID_OBJHANDLE ) - { - if( mustBeConst && !(paramTypeId & asTYPEID_HANDLETOCONST) ) - continue; - } - else - continue; + if( (flags & asTM_INREF) ) + { + if( (paramTypeId & asTYPEID_OBJHANDLE) || (mustBeConst && !(flags & asTM_CONST)) ) + continue; + } + else if( paramTypeId & asTYPEID_OBJHANDLE ) + { + if( mustBeConst && !(paramTypeId & asTYPEID_HANDLETOCONST) ) + continue; + } + else + continue; - if( isCmp ) - { - if( cache->cmpFunc || cache->cmpFuncReturnCode ) - { - cache->cmpFunc = 0; - cache->cmpFuncReturnCode = asMULTIPLE_FUNCTIONS; - } - else - cache->cmpFunc = func; - } - else if( isEq ) - { - if( cache->eqFunc || cache->eqFuncReturnCode ) - { - cache->eqFunc = 0; - cache->eqFuncReturnCode = asMULTIPLE_FUNCTIONS; - } - else - cache->eqFunc = func; - } - } - } - } + if( isCmp ) + { + if( cache->cmpFunc || cache->cmpFuncReturnCode ) + { + cache->cmpFunc = 0; + cache->cmpFuncReturnCode = asMULTIPLE_FUNCTIONS; + } + else + cache->cmpFunc = func; + } + else if( isEq ) + { + if( cache->eqFunc || cache->eqFuncReturnCode ) + { + cache->eqFunc = 0; + cache->eqFuncReturnCode = asMULTIPLE_FUNCTIONS; + } + else + cache->eqFunc = func; + } + } + } + } - if( cache->eqFunc == 0 && cache->eqFuncReturnCode == 0 ) - cache->eqFuncReturnCode = asNO_FUNCTION; - if( cache->cmpFunc == 0 && cache->cmpFuncReturnCode == 0 ) - cache->cmpFuncReturnCode = asNO_FUNCTION; + if( cache->eqFunc == 0 && cache->eqFuncReturnCode == 0 ) + cache->eqFuncReturnCode = asNO_FUNCTION; + if( cache->cmpFunc == 0 && cache->cmpFuncReturnCode == 0 ) + cache->cmpFuncReturnCode = asNO_FUNCTION; - // Set the user data only at the end so others that retrieve it will know it is complete - objType->SetUserData(cache, ARRAY_CACHE); + // Set the user data only at the end so others that retrieve it will know it is complete + objType->SetUserData(cache, ARRAY_CACHE); - asReleaseExclusiveLock(); + asReleaseExclusiveLock(); } // GC behaviour void CScriptArray::EnumReferences(asIScriptEngine *engine) { - // TODO: If garbage collection can be done from a separate thread, then this method must be - // protected so that it doesn't get lost during the iteration if the array is modified + // TODO: If garbage collection can be done from a separate thread, then this method must be + // protected so that it doesn't get lost during the iteration if the array is modified - // If the array is holding handles, then we need to notify the GC of them - if( subTypeId & asTYPEID_MASK_OBJECT ) - { - void **d = (void**)buffer->data; - for( asUINT n = 0; n < buffer->numElements; n++ ) - { - if( d[n] ) - engine->GCEnumCallback(d[n]); - } - } + // If the array is holding handles, then we need to notify the GC of them + if( subTypeId & asTYPEID_MASK_OBJECT ) + { + void **d = (void**)buffer->data; + for( asUINT n = 0; n < buffer->numElements; n++ ) + { + if( d[n] ) + engine->GCEnumCallback(d[n]); + } + } } // GC behaviour void CScriptArray::ReleaseAllHandles(asIScriptEngine *) { - // Resizing to zero will release everything - Resize(0); + // Resizing to zero will release everything + Resize(0); } void CScriptArray::AddRef() const { - // Clear the GC flag then increase the counter - gcFlag = false; - asAtomicInc(refCount); + // Clear the GC flag then increase the counter + gcFlag = false; + asAtomicInc(refCount); } void CScriptArray::Release() const { - // Clearing the GC flag then descrease the counter - gcFlag = false; - if( asAtomicDec(refCount) == 0 ) - { - // When reaching 0 no more references to this instance - // exists and the object should be destroyed - this->~CScriptArray(); - userFree(const_cast(this)); - } + // Clearing the GC flag then descrease the counter + gcFlag = false; + if( asAtomicDec(refCount) == 0 ) + { + // When reaching 0 no more references to this instance + // exists and the object should be destroyed + this->~CScriptArray(); + userFree(const_cast(this)); + } } // GC behaviour int CScriptArray::GetRefCount() { - return refCount; + return refCount; } // GC behaviour void CScriptArray::SetFlag() { - gcFlag = true; + gcFlag = true; } // GC behaviour bool CScriptArray::GetFlag() { - return gcFlag; + return gcFlag; } //-------------------------------------------- @@ -1710,275 +1871,304 @@ bool CScriptArray::GetFlag() static void ScriptArrayFactory_Generic(asIScriptGeneric *gen) { - asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0); + asITypeInfo *ti = *(asITypeInfo**)gen->GetAddressOfArg(0); - *reinterpret_cast(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ot); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ti); } static void ScriptArrayFactory2_Generic(asIScriptGeneric *gen) { - asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0); - asUINT length = gen->GetArgDWord(1); + asITypeInfo *ti = *(asITypeInfo**)gen->GetAddressOfArg(0); + asUINT length = gen->GetArgDWord(1); - *reinterpret_cast(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ot, length); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ti, length); } static void ScriptArrayListFactory_Generic(asIScriptGeneric *gen) { - asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0); - void *buf = gen->GetArgAddress(1); + asITypeInfo *ti = *(asITypeInfo**)gen->GetAddressOfArg(0); + void *buf = gen->GetArgAddress(1); - *reinterpret_cast(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ot, buf); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ti, buf); } static void ScriptArrayFactoryDefVal_Generic(asIScriptGeneric *gen) { - asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0); - asUINT length = gen->GetArgDWord(1); - void *defVal = gen->GetArgAddress(2); + asITypeInfo *ti = *(asITypeInfo**)gen->GetAddressOfArg(0); + asUINT length = gen->GetArgDWord(1); + void *defVal = gen->GetArgAddress(2); - *reinterpret_cast(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ot, length, defVal); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ti, length, defVal); } static void ScriptArrayTemplateCallback_Generic(asIScriptGeneric *gen) { - asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0); - bool *dontGarbageCollect = *(bool**)gen->GetAddressOfArg(1); - *reinterpret_cast(gen->GetAddressOfReturnLocation()) = ScriptArrayTemplateCallback(ot, *dontGarbageCollect); + asITypeInfo *ti = *(asITypeInfo**)gen->GetAddressOfArg(0); + bool *dontGarbageCollect = *(bool**)gen->GetAddressOfArg(1); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = ScriptArrayTemplateCallback(ti, *dontGarbageCollect); } static void ScriptArrayAssignment_Generic(asIScriptGeneric *gen) { - CScriptArray *other = (CScriptArray*)gen->GetArgObject(0); - CScriptArray *self = (CScriptArray*)gen->GetObject(); - *self = *other; - gen->SetReturnObject(self); + CScriptArray *other = (CScriptArray*)gen->GetArgObject(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + *self = *other; + gen->SetReturnObject(self); } static void ScriptArrayEquals_Generic(asIScriptGeneric *gen) { - CScriptArray *other = (CScriptArray*)gen->GetArgObject(0); - CScriptArray *self = (CScriptArray*)gen->GetObject(); - gen->SetReturnByte(self->operator==(*other)); + CScriptArray *other = (CScriptArray*)gen->GetArgObject(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + gen->SetReturnByte(self->operator==(*other)); } static void ScriptArrayFind_Generic(asIScriptGeneric *gen) { - void *value = gen->GetArgAddress(0); - CScriptArray *self = (CScriptArray*)gen->GetObject(); - gen->SetReturnDWord(self->Find(value)); + void *value = gen->GetArgAddress(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + gen->SetReturnDWord(self->Find(value)); } static void ScriptArrayFind2_Generic(asIScriptGeneric *gen) { - asUINT index = gen->GetArgDWord(0); - void *value = gen->GetArgAddress(1); - CScriptArray *self = (CScriptArray*)gen->GetObject(); - gen->SetReturnDWord(self->Find(index, value)); + asUINT index = gen->GetArgDWord(0); + void *value = gen->GetArgAddress(1); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + gen->SetReturnDWord(self->Find(index, value)); } static void ScriptArrayFindByRef_Generic(asIScriptGeneric *gen) { - void *value = gen->GetArgAddress(0); - CScriptArray *self = (CScriptArray*)gen->GetObject(); - gen->SetReturnDWord(self->FindByRef(value)); + void *value = gen->GetArgAddress(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + gen->SetReturnDWord(self->FindByRef(value)); } static void ScriptArrayFindByRef2_Generic(asIScriptGeneric *gen) { - asUINT index = gen->GetArgDWord(0); - void *value = gen->GetArgAddress(1); - CScriptArray *self = (CScriptArray*)gen->GetObject(); - gen->SetReturnDWord(self->FindByRef(index, value)); + asUINT index = gen->GetArgDWord(0); + void *value = gen->GetArgAddress(1); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + gen->SetReturnDWord(self->FindByRef(index, value)); } static void ScriptArrayAt_Generic(asIScriptGeneric *gen) { - asUINT index = gen->GetArgDWord(0); - CScriptArray *self = (CScriptArray*)gen->GetObject(); + asUINT index = gen->GetArgDWord(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); - gen->SetReturnAddress(self->At(index)); + gen->SetReturnAddress(self->At(index)); } static void ScriptArrayInsertAt_Generic(asIScriptGeneric *gen) { - asUINT index = gen->GetArgDWord(0); - void *value = gen->GetArgAddress(1); - CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->InsertAt(index, value); + asUINT index = gen->GetArgDWord(0); + void *value = gen->GetArgAddress(1); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->InsertAt(index, value); +} + +static void ScriptArrayInsertAtArray_Generic(asIScriptGeneric *gen) +{ + asUINT index = gen->GetArgDWord(0); + CScriptArray *array = (CScriptArray*)gen->GetArgAddress(1); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->InsertAt(index, *array); } static void ScriptArrayRemoveAt_Generic(asIScriptGeneric *gen) { - asUINT index = gen->GetArgDWord(0); - CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->RemoveAt(index); + asUINT index = gen->GetArgDWord(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->RemoveAt(index); +} + +static void ScriptArrayRemoveRange_Generic(asIScriptGeneric *gen) +{ + asUINT start = gen->GetArgDWord(0); + asUINT count = gen->GetArgDWord(1); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->RemoveRange(start, count); } static void ScriptArrayInsertLast_Generic(asIScriptGeneric *gen) { - void *value = gen->GetArgAddress(0); - CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->InsertLast(value); + void *value = gen->GetArgAddress(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->InsertLast(value); } static void ScriptArrayRemoveLast_Generic(asIScriptGeneric *gen) { - CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->RemoveLast(); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->RemoveLast(); } static void ScriptArrayLength_Generic(asIScriptGeneric *gen) { - CScriptArray *self = (CScriptArray*)gen->GetObject(); + CScriptArray *self = (CScriptArray*)gen->GetObject(); - gen->SetReturnDWord(self->GetSize()); + gen->SetReturnDWord(self->GetSize()); } static void ScriptArrayResize_Generic(asIScriptGeneric *gen) { - asUINT size = gen->GetArgDWord(0); - CScriptArray *self = (CScriptArray*)gen->GetObject(); + asUINT size = gen->GetArgDWord(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->Resize(size); + self->Resize(size); } static void ScriptArrayReserve_Generic(asIScriptGeneric *gen) { - asUINT size = gen->GetArgDWord(0); - CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->Reserve(size); + asUINT size = gen->GetArgDWord(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->Reserve(size); } static void ScriptArraySortAsc_Generic(asIScriptGeneric *gen) { - CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->SortAsc(); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->SortAsc(); } static void ScriptArrayReverse_Generic(asIScriptGeneric *gen) { - CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->Reverse(); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->Reverse(); } static void ScriptArrayIsEmpty_Generic(asIScriptGeneric *gen) { - CScriptArray *self = (CScriptArray*)gen->GetObject(); - *reinterpret_cast(gen->GetAddressOfReturnLocation()) = self->IsEmpty(); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = self->IsEmpty(); } static void ScriptArraySortAsc2_Generic(asIScriptGeneric *gen) { - asUINT index = gen->GetArgDWord(0); - asUINT count = gen->GetArgDWord(1); - CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->SortAsc(index, count); + asUINT index = gen->GetArgDWord(0); + asUINT count = gen->GetArgDWord(1); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->SortAsc(index, count); } static void ScriptArraySortDesc_Generic(asIScriptGeneric *gen) { - CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->SortDesc(); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->SortDesc(); } static void ScriptArraySortDesc2_Generic(asIScriptGeneric *gen) { - asUINT index = gen->GetArgDWord(0); - asUINT count = gen->GetArgDWord(1); - CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->SortDesc(index, count); + asUINT index = gen->GetArgDWord(0); + asUINT count = gen->GetArgDWord(1); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->SortDesc(index, count); +} + +static void ScriptArraySortCallback_Generic(asIScriptGeneric *gen) +{ + asIScriptFunction *callback = (asIScriptFunction*)gen->GetArgAddress(0); + asUINT startAt = gen->GetArgDWord(1); + asUINT count = gen->GetArgDWord(2); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->Sort(callback, startAt, count); } static void ScriptArrayAddRef_Generic(asIScriptGeneric *gen) { - CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->AddRef(); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->AddRef(); } static void ScriptArrayRelease_Generic(asIScriptGeneric *gen) { - CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->Release(); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->Release(); } static void ScriptArrayGetRefCount_Generic(asIScriptGeneric *gen) { - CScriptArray *self = (CScriptArray*)gen->GetObject(); - *reinterpret_cast(gen->GetAddressOfReturnLocation()) = self->GetRefCount(); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = self->GetRefCount(); } static void ScriptArraySetFlag_Generic(asIScriptGeneric *gen) { - CScriptArray *self = (CScriptArray*)gen->GetObject(); - self->SetFlag(); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->SetFlag(); } static void ScriptArrayGetFlag_Generic(asIScriptGeneric *gen) { - CScriptArray *self = (CScriptArray*)gen->GetObject(); - *reinterpret_cast(gen->GetAddressOfReturnLocation()) = self->GetFlag(); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = self->GetFlag(); } static void ScriptArrayEnumReferences_Generic(asIScriptGeneric *gen) { - CScriptArray *self = (CScriptArray*)gen->GetObject(); - asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0); - self->EnumReferences(engine); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0); + self->EnumReferences(engine); } static void ScriptArrayReleaseAllHandles_Generic(asIScriptGeneric *gen) { - CScriptArray *self = (CScriptArray*)gen->GetObject(); - asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0); - self->ReleaseAllHandles(engine); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0); + self->ReleaseAllHandles(engine); } static void RegisterScriptArray_Generic(asIScriptEngine *engine) { - int r = 0; - UNUSED_VAR(r); + int r = 0; + UNUSED_VAR(r); - engine->SetObjectTypeUserDataCleanupCallback(CleanupObjectTypeArrayCache, ARRAY_CACHE); + engine->SetTypeInfoUserDataCleanupCallback(CleanupTypeInfoArrayCache, ARRAY_CACHE); - r = engine->RegisterObjectType("array", 0, asOBJ_REF | asOBJ_GC | asOBJ_TEMPLATE); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in, bool&out)", asFUNCTION(ScriptArrayTemplateCallback_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectType("array", 0, asOBJ_REF | asOBJ_GC | asOBJ_TEMPLATE); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in, bool&out)", asFUNCTION(ScriptArrayTemplateCallback_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in)", asFUNCTION(ScriptArrayFactory_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in, uint)", asFUNCTION(ScriptArrayFactory2_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in, uint, const T &in)", asFUNCTION(ScriptArrayFactoryDefVal_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_LIST_FACTORY, "array@ f(int&in, int&in) {repeat T}", asFUNCTION(ScriptArrayListFactory_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptArrayAddRef_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptArrayRelease_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "T &opIndex(uint)", asFUNCTION(ScriptArrayAt_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "const T &opIndex(uint) const", asFUNCTION(ScriptArrayAt_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "array &opAssign(const array&in)", asFUNCTION(ScriptArrayAssignment_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in)", asFUNCTION(ScriptArrayFactory_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in, uint length)", asFUNCTION(ScriptArrayFactory2_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in, uint length, const T &in value)", asFUNCTION(ScriptArrayFactoryDefVal_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_LIST_FACTORY, "array@ f(int&in, int&in) {repeat T}", asFUNCTION(ScriptArrayListFactory_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptArrayAddRef_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptArrayRelease_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "T &opIndex(uint index)", asFUNCTION(ScriptArrayAt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "const T &opIndex(uint index) const", asFUNCTION(ScriptArrayAt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "array &opAssign(const array&in)", asFUNCTION(ScriptArrayAssignment_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void insertAt(uint, const T&in)", asFUNCTION(ScriptArrayInsertAt_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void removeAt(uint)", asFUNCTION(ScriptArrayRemoveAt_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void insertLast(const T&in)", asFUNCTION(ScriptArrayInsertLast_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void removeLast()", asFUNCTION(ScriptArrayRemoveLast_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "uint length() const", asFUNCTION(ScriptArrayLength_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void reserve(uint)", asFUNCTION(ScriptArrayReserve_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void resize(uint)", asFUNCTION(ScriptArrayResize_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void sortAsc()", asFUNCTION(ScriptArraySortAsc_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void sortAsc(uint, uint)", asFUNCTION(ScriptArraySortAsc2_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void sortDesc()", asFUNCTION(ScriptArraySortDesc_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void sortDesc(uint, uint)", asFUNCTION(ScriptArraySortDesc2_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void reverse()", asFUNCTION(ScriptArrayReverse_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "int find(const T&in) const", asFUNCTION(ScriptArrayFind_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "int find(uint, const T&in) const", asFUNCTION(ScriptArrayFind2_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "int findByRef(const T&in) const", asFUNCTION(ScriptArrayFindByRef_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "int findByRef(uint, const T&in) const", asFUNCTION(ScriptArrayFindByRef2_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "bool opEquals(const array&in) const", asFUNCTION(ScriptArrayEquals_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "bool isEmpty() const", asFUNCTION(ScriptArrayIsEmpty_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "uint get_length() const", asFUNCTION(ScriptArrayLength_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("array", "void set_length(uint)", asFUNCTION(ScriptArrayResize_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptArrayGetRefCount_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ScriptArraySetFlag_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ScriptArrayGetFlag_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ScriptArrayEnumReferences_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("array", asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ScriptArrayReleaseAllHandles_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void insertAt(uint index, const T&in value)", asFUNCTION(ScriptArrayInsertAt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void insertAt(uint index, const array& arr)", asFUNCTION(ScriptArrayInsertAtArray_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("array", "void insertLast(const T&in value)", asFUNCTION(ScriptArrayInsertLast_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("array", "void removeAt(uint index)", asFUNCTION(ScriptArrayRemoveAt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void removeLast()", asFUNCTION(ScriptArrayRemoveLast_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void removeRange(uint start, uint count)", asFUNCTION(ScriptArrayRemoveRange_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("array", "uint length() const", asFUNCTION(ScriptArrayLength_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void reserve(uint length)", asFUNCTION(ScriptArrayReserve_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void resize(uint length)", asFUNCTION(ScriptArrayResize_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortAsc()", asFUNCTION(ScriptArraySortAsc_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortAsc(uint startAt, uint count)", asFUNCTION(ScriptArraySortAsc2_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortDesc()", asFUNCTION(ScriptArraySortDesc_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortDesc(uint startAt, uint count)", asFUNCTION(ScriptArraySortDesc2_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void reverse()", asFUNCTION(ScriptArrayReverse_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "int find(const T&in if_handle_then_const value) const", asFUNCTION(ScriptArrayFind_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "int find(uint startAt, const T&in if_handle_then_const value) const", asFUNCTION(ScriptArrayFind2_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "int findByRef(const T&in if_handle_then_const value) const", asFUNCTION(ScriptArrayFindByRef_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "int findByRef(uint startAt, const T&in if_handle_then_const value) const", asFUNCTION(ScriptArrayFindByRef2_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "bool opEquals(const array&in) const", asFUNCTION(ScriptArrayEquals_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "bool isEmpty() const", asFUNCTION(ScriptArrayIsEmpty_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterFuncdef("bool array::less(const T&in a, const T&in b)"); + r = engine->RegisterObjectMethod("array", "void sort(const less &in, uint startAt = 0, uint count = uint(-1))", asFUNCTION(ScriptArraySortCallback_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("array", "uint get_length() const", asFUNCTION(ScriptArrayLength_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void set_length(uint)", asFUNCTION(ScriptArrayResize_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptArrayGetRefCount_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ScriptArraySetFlag_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ScriptArrayGetFlag_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ScriptArrayEnumReferences_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ScriptArrayReleaseAllHandles_Generic), asCALL_GENERIC); assert( r >= 0 ); } END_AS_NAMESPACE diff --git a/src/scriptengine/scriptarray.hpp b/src/scriptengine/scriptarray.hpp index a1c0a0a1d..9d8c22ed8 100644 --- a/src/scriptengine/scriptarray.hpp +++ b/src/scriptengine/scriptarray.hpp @@ -1,3 +1,33 @@ +/* + AngelCode Scripting Library + Copyright (c) 2003-2017 Andreas Jonsson + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + The original version of this library can be located at: + http://www.angelcode.com/angelscript/ + + Andreas Jonsson + andreas@angelcode.com +*/ + #ifndef SCRIPTARRAY_H #define SCRIPTARRAY_H @@ -25,103 +55,109 @@ struct SArrayCache; class CScriptArray { public: - // Set the memory functions that should be used by all CScriptArrays - static void SetMemoryFunctions(asALLOCFUNC_t allocFunc, asFREEFUNC_t freeFunc); + // Set the memory functions that should be used by all CScriptArrays + static void SetMemoryFunctions(asALLOCFUNC_t allocFunc, asFREEFUNC_t freeFunc); - // Factory functions - static CScriptArray *Create(asIObjectType *ot); - static CScriptArray *Create(asIObjectType *ot, asUINT length); - static CScriptArray *Create(asIObjectType *ot, asUINT length, void *defaultValue); - static CScriptArray *Create(asIObjectType *ot, void *listBuffer); + // Factory functions + static CScriptArray *Create(asITypeInfo *ot); + static CScriptArray *Create(asITypeInfo *ot, asUINT length); + static CScriptArray *Create(asITypeInfo *ot, asUINT length, void *defaultValue); + static CScriptArray *Create(asITypeInfo *ot, void *listBuffer); - // Memory management - void AddRef() const; - void Release() const; + // Memory management + void AddRef() const; + void Release() const; - // Type information - asIObjectType *GetArrayObjectType() const; - int GetArrayTypeId() const; - int GetElementTypeId() const; + // Type information + asITypeInfo *GetArrayObjectType() const; + int GetArrayTypeId() const; + int GetElementTypeId() const; - // Get the current size - asUINT GetSize() const; + // Get the current size + asUINT GetSize() const; - // Returns true if the array is empty - bool IsEmpty() const; + // Returns true if the array is empty + bool IsEmpty() const; - // Pre-allocates memory for elements - void Reserve(asUINT maxElements); + // Pre-allocates memory for elements + void Reserve(asUINT maxElements); - // Resize the array - void Resize(asUINT numElements); + // Resize the array + void Resize(asUINT numElements); - // Get a pointer to an element. Returns 0 if out of bounds - void *At(asUINT index); - const void *At(asUINT index) const; + // Get a pointer to an element. Returns 0 if out of bounds + void *At(asUINT index); + const void *At(asUINT index) const; - // Set value of an element. - // The value arg should be a pointer to the value that will be copied to the element. - // Remember, if the array holds handles the value parameter should be the - // address of the handle. The refCount of the object will also be incremented - void SetValue(asUINT index, void *value); + // Set value of an element. + // The value arg should be a pointer to the value that will be copied to the element. + // Remember, if the array holds handles the value parameter should be the + // address of the handle. The refCount of the object will also be incremented + void SetValue(asUINT index, void *value); - // Copy the contents of one array to another (only if the types are the same) - CScriptArray &operator=(const CScriptArray&); + // Copy the contents of one array to another (only if the types are the same) + CScriptArray &operator=(const CScriptArray&); - // Compare two arrays - bool operator==(const CScriptArray &) const; + // Compare two arrays + bool operator==(const CScriptArray &) const; - // Array manipulation - void InsertAt(asUINT index, void *value); - void RemoveAt(asUINT index); - void InsertLast(void *value); - void RemoveLast(); - void SortAsc(); - void SortDesc(); - void SortAsc(asUINT startAt, asUINT count); - void SortDesc(asUINT startAt, asUINT count); - void Sort(asUINT startAt, asUINT count, bool asc); - void Reverse(); - int Find(void *value) const; - int Find(asUINT startAt, void *value) const; - int FindByRef(void *ref) const; - int FindByRef(asUINT startAt, void *ref) const; + // Array manipulation + void InsertAt(asUINT index, void *value); + void InsertAt(asUINT index, const CScriptArray &arr); + void InsertLast(void *value); + void RemoveAt(asUINT index); + void RemoveLast(); + void RemoveRange(asUINT start, asUINT count); + void SortAsc(); + void SortDesc(); + void SortAsc(asUINT startAt, asUINT count); + void SortDesc(asUINT startAt, asUINT count); + void Sort(asUINT startAt, asUINT count, bool asc); + void Sort(asIScriptFunction *less, asUINT startAt, asUINT count); + void Reverse(); + int Find(void *value) const; + int Find(asUINT startAt, void *value) const; + int FindByRef(void *ref) const; + int FindByRef(asUINT startAt, void *ref) const; - // GC methods - int GetRefCount(); - void SetFlag(); - bool GetFlag(); - void EnumReferences(asIScriptEngine *engine); - void ReleaseAllHandles(asIScriptEngine *engine); + // Return the address of internal buffer for direct manipulation of elements + void *GetBuffer(); + + // GC methods + int GetRefCount(); + void SetFlag(); + bool GetFlag(); + void EnumReferences(asIScriptEngine *engine); + void ReleaseAllHandles(asIScriptEngine *engine); protected: - mutable int refCount; - mutable bool gcFlag; - asIObjectType *objType; - SArrayBuffer *buffer; - int elementSize; - int subTypeId; + mutable int refCount; + mutable bool gcFlag; + asITypeInfo *objType; + SArrayBuffer *buffer; + int elementSize; + int subTypeId; - // Constructors - CScriptArray(asIObjectType *ot, void *initBuf); // Called from script when initialized with list - CScriptArray(asUINT length, asIObjectType *ot); - CScriptArray(asUINT length, void *defVal, asIObjectType *ot); - CScriptArray(const CScriptArray &other); - virtual ~CScriptArray(); + // Constructors + CScriptArray(asITypeInfo *ot, void *initBuf); // Called from script when initialized with list + CScriptArray(asUINT length, asITypeInfo *ot); + CScriptArray(asUINT length, void *defVal, asITypeInfo *ot); + CScriptArray(const CScriptArray &other); + virtual ~CScriptArray(); - bool Less(const void *a, const void *b, bool asc, asIScriptContext *ctx, SArrayCache *cache); - void *GetArrayItemPointer(int index); - void *GetDataPointer(void *buffer); - void Copy(void *dst, void *src); - void Precache(); - bool CheckMaxSize(asUINT numElements); - void Resize(int delta, asUINT at); - void CreateBuffer(SArrayBuffer **buf, asUINT numElements); - void DeleteBuffer(SArrayBuffer *buf); - void CopyBuffer(SArrayBuffer *dst, SArrayBuffer *src); - void Construct(SArrayBuffer *buf, asUINT start, asUINT end); - void Destruct(SArrayBuffer *buf, asUINT start, asUINT end); - bool Equals(const void *a, const void *b, asIScriptContext *ctx, SArrayCache *cache) const; + bool Less(const void *a, const void *b, bool asc, asIScriptContext *ctx, SArrayCache *cache); + void *GetArrayItemPointer(int index); + void *GetDataPointer(void *buffer); + void Copy(void *dst, void *src); + void Precache(); + bool CheckMaxSize(asUINT numElements); + void Resize(int delta, asUINT at); + void CreateBuffer(SArrayBuffer **buf, asUINT numElements); + void DeleteBuffer(SArrayBuffer *buf); + void CopyBuffer(SArrayBuffer *dst, SArrayBuffer *src); + void Construct(SArrayBuffer *buf, asUINT start, asUINT end); + void Destruct(SArrayBuffer *buf, asUINT start, asUINT end); + bool Equals(const void *a, const void *b, asIScriptContext *ctx, SArrayCache *cache) const; }; void RegisterScriptArray(asIScriptEngine *engine, bool defaultArray); diff --git a/src/scriptengine/scriptstdstring.cpp b/src/scriptengine/scriptstdstring.cpp index 381a78cc1..b46cc3d21 100644 --- a/src/scriptengine/scriptstdstring.cpp +++ b/src/scriptengine/scriptstdstring.cpp @@ -1,365 +1,331 @@ /* -AngelCode Scripting Library -Copyright (c) 2003-2015 Andreas Jonsson + AngelCode Scripting Library + Copyright (c) 2003-2017 Andreas Jonsson -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: -1. The origin of this software must not be misrepresented; you -must not claim that you wrote the original software. If you use -this software in a product, an acknowledgment in the product -documentation would be appreciated but is not required. + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source -distribution. + 3. This notice may not be removed or altered from any source + distribution. -The original version of this library can be located at: -http://www.angelcode.com/angelscript/ + The original version of this library can be located at: + http://www.angelcode.com/angelscript/ -Andreas Jonsson -andreas@angelcode.com + Andreas Jonsson + andreas@angelcode.com */ #include "scriptstdstring.hpp" #include // assert() #include // std::stringstream #include // strstr() -#include // sprintf() +#include // sprintf() #include // strtod() #ifndef __psp2__ - #include // setlocale() + #include // setlocale() #endif -#include // std::map using namespace std; -BEGIN_AS_NAMESPACE - // This macro is used to avoid warnings about unused variables. // Usually where the variables are only used in debug mode. #define UNUSED_VAR(x) (void)(x) -#if AS_USE_STRINGPOOL == 1 - -// By keeping the literal strings in a pool the application -// performance is improved as there are less string copies created. - -// The string pool will be kept as user data in the engine. We'll -// need a specific type to identify the string pool user data. -// We just define a number here that we assume nobody else is using for -// object type user data. The add-ons have reserved the numbers 1000 -// through 1999 for this purpose, so we should be fine. -const asPWORD STRING_POOL = 1001; - -// This global static variable is placed here rather than locally within the -// StringFactory, due to memory leak detectors that don't see the deallocation -// of global variables. By placing the variable globally it will be initialized -// before the memory leak detector starts, thus it won't report the missing -// deallocation. An example of this the Marmalade leak detector initialized with -// IwGxInit() and finished with IwGxTerminate(). -static const string emptyString; - -static const string &StringFactory(asUINT length, const char *s) -{ - // Each engine instance has its own string pool - asIScriptContext *ctx = asGetActiveContext(); - if( ctx == 0 ) - { - // The string factory can only be called from a script - assert( ctx ); - return emptyString; - } - asIScriptEngine *engine = ctx->GetEngine(); - - // TODO: runtime optimize: Use unordered_map if C++11 is supported, i.e. MSVC10+, gcc 4.?+ - map *pool = reinterpret_cast< map* >(engine->GetUserData(STRING_POOL)); - - if( !pool ) - { - // The string pool hasn't been created yet, so we'll create it now - asAcquireExclusiveLock(); - - // Make sure the string pool wasn't created while we were waiting for the lock - pool = reinterpret_cast< map* >(engine->GetUserData(STRING_POOL)); - if( !pool ) - { - #if defined(__S3E__) - pool = new map; - #else - pool = new (nothrow) map; - #endif - if( pool == 0 ) - { - ctx->SetException("Out of memory"); - asReleaseExclusiveLock(); - return emptyString; - } - engine->SetUserData(pool, STRING_POOL); - } - - asReleaseExclusiveLock(); - } - - // We can't let other threads modify the pool while we query it - asAcquireSharedLock(); - - // First check if a string object hasn't been created already - map::iterator it; - it = pool->find(s); - if( it != pool->end() ) - { - asReleaseSharedLock(); - return it->second; - } - - asReleaseSharedLock(); - - // Acquire an exclusive lock so we can add the new string to the pool - asAcquireExclusiveLock(); - - // Make sure the string wasn't created while we were waiting for the exclusive lock - it = pool->find(s); - if( it == pool->end() ) - { - // Create a new string object - it = pool->insert(map::value_type(s, string(s, length))).first; - } - - asReleaseExclusiveLock(); - return it->second; -} - -static void CleanupEngineStringPool(asIScriptEngine *engine) -{ - map *pool = reinterpret_cast< map* >(engine->GetUserData(STRING_POOL)); - if( pool ) - delete pool; -} - +#ifdef AS_CAN_USE_CPP11 +// The string factory doesn't need to keep a specific order in the +// cache, so the unordered_map is faster than the ordinary map +#include // std::unordered_map +BEGIN_AS_NAMESPACE +typedef unordered_map map_t; +END_AS_NAMESPACE #else -static string StringFactory(asUINT length, const char *s) -{ - return string(s, length); -} +#include // std::map +BEGIN_AS_NAMESPACE +typedef map map_t; +END_AS_NAMESPACE #endif +class CStdStringFactory : public asIStringFactory +{ +public: + CStdStringFactory() {} + ~CStdStringFactory() + { + // The script engine must release each string + // constant that it has requested + assert(stringCache.size() == 0); + } + + const void *GetStringConstant(const char *data, asUINT length) + { + string str(data, length); + map_t::iterator it = stringCache.find(str); + if (it != stringCache.end()) + it->second++; + else + it = stringCache.insert(map_t::value_type(str, 1)).first; + + return reinterpret_cast(&it->first); + } + + int ReleaseStringConstant(const void *str) + { + if (str == 0) + return asERROR; + + map_t::iterator it = stringCache.find(*reinterpret_cast(str)); + if (it == stringCache.end()) + return asERROR; + + it->second--; + if (it->second == 0) + stringCache.erase(it); + return asSUCCESS; + } + + int GetRawStringData(const void *str, char *data, asUINT *length) const + { + if (str == 0) + return asERROR; + + if (length) + *length = (asUINT)reinterpret_cast(str)->length(); + + if (data) + memcpy(data, reinterpret_cast(str)->c_str(), reinterpret_cast(str)->length()); + + return asSUCCESS; + } + + // TODO: Make sure the access to the string cache is thread safe + map_t stringCache; +}; + +static CStdStringFactory stringFactory; + + static void ConstructString(string *thisPointer) { - new(thisPointer) string(); + new(thisPointer) string(); } static void CopyConstructString(const string &other, string *thisPointer) { - new(thisPointer) string(other); + new(thisPointer) string(other); } static void DestructString(string *thisPointer) { - thisPointer->~string(); + thisPointer->~string(); } static string &AddAssignStringToString(const string &str, string &dest) { - // We don't register the method directly because some compilers - // and standard libraries inline the definition, resulting in the - // linker being unable to find the declaration. - // Example: CLang/LLVM with XCode 4.3 on OSX 10.7 - dest += str; - return dest; + // We don't register the method directly because some compilers + // and standard libraries inline the definition, resulting in the + // linker being unable to find the declaration. + // Example: CLang/LLVM with XCode 4.3 on OSX 10.7 + dest += str; + return dest; } // bool string::isEmpty() // bool string::empty() // if AS_USE_STLNAMES == 1 static bool StringIsEmpty(const string &str) { - // We don't register the method directly because some compilers - // and standard libraries inline the definition, resulting in the - // linker being unable to find the declaration - // Example: CLang/LLVM with XCode 4.3 on OSX 10.7 - return str.empty(); + // We don't register the method directly because some compilers + // and standard libraries inline the definition, resulting in the + // linker being unable to find the declaration + // Example: CLang/LLVM with XCode 4.3 on OSX 10.7 + return str.empty(); } static string &AssignUInt64ToString(asQWORD i, string &dest) { - ostringstream stream; - stream << i; - dest = stream.str(); - return dest; + ostringstream stream; + stream << i; + dest = stream.str(); + return dest; } static string &AddAssignUInt64ToString(asQWORD i, string &dest) { - ostringstream stream; - stream << i; - dest += stream.str(); - return dest; + ostringstream stream; + stream << i; + dest += stream.str(); + return dest; } static string AddStringUInt64(const string &str, asQWORD i) { - ostringstream stream; - stream << i; - return str + stream.str(); + ostringstream stream; + stream << i; + return str + stream.str(); } static string AddInt64String(asINT64 i, const string &str) { - ostringstream stream; - stream << i; - return stream.str() + str; + ostringstream stream; + stream << i; + return stream.str() + str; } static string &AssignInt64ToString(asINT64 i, string &dest) { - ostringstream stream; - stream << i; - dest = stream.str(); - return dest; + ostringstream stream; + stream << i; + dest = stream.str(); + return dest; } static string &AddAssignInt64ToString(asINT64 i, string &dest) { - ostringstream stream; - stream << i; - dest += stream.str(); - return dest; + ostringstream stream; + stream << i; + dest += stream.str(); + return dest; } static string AddStringInt64(const string &str, asINT64 i) { - ostringstream stream; - stream << i; - return str + stream.str(); + ostringstream stream; + stream << i; + return str + stream.str(); } static string AddUInt64String(asQWORD i, const string &str) { - ostringstream stream; - stream << i; - return stream.str() + str; + ostringstream stream; + stream << i; + return stream.str() + str; } static string &AssignDoubleToString(double f, string &dest) { - ostringstream stream; - stream << f; - dest = stream.str(); - return dest; + ostringstream stream; + stream << f; + dest = stream.str(); + return dest; } static string &AddAssignDoubleToString(double f, string &dest) { - ostringstream stream; - stream << f; - dest += stream.str(); - return dest; + ostringstream stream; + stream << f; + dest += stream.str(); + return dest; } static string &AssignFloatToString(float f, string &dest) { - ostringstream stream; - stream << f; - dest = stream.str(); - return dest; + ostringstream stream; + stream << f; + dest = stream.str(); + return dest; } static string &AddAssignFloatToString(float f, string &dest) { - ostringstream stream; - stream << f; - dest += stream.str(); - return dest; + ostringstream stream; + stream << f; + dest += stream.str(); + return dest; } static string &AssignBoolToString(bool b, string &dest) { - ostringstream stream; - stream << (b ? "true" : "false"); - dest = stream.str(); - return dest; + ostringstream stream; + stream << (b ? "true" : "false"); + dest = stream.str(); + return dest; } static string &AddAssignBoolToString(bool b, string &dest) { - ostringstream stream; - stream << (b ? "true" : "false"); - dest += stream.str(); - return dest; + ostringstream stream; + stream << (b ? "true" : "false"); + dest += stream.str(); + return dest; } static string AddStringDouble(const string &str, double f) { - ostringstream stream; - stream << f; - return str + stream.str(); + ostringstream stream; + stream << f; + return str + stream.str(); } static string AddDoubleString(double f, const string &str) { - ostringstream stream; - stream << f; - return stream.str() + str; + ostringstream stream; + stream << f; + return stream.str() + str; } static string AddStringFloat(const string &str, float f) { - ostringstream stream; - stream << f; - return str + stream.str(); + ostringstream stream; + stream << f; + return str + stream.str(); } static string AddFloatString(float f, const string &str) { - ostringstream stream; - stream << f; - return stream.str() + str; + ostringstream stream; + stream << f; + return stream.str() + str; } static string AddStringBool(const string &str, bool b) { - ostringstream stream; - stream << (b ? "true" : "false"); - return str + stream.str(); + ostringstream stream; + stream << (b ? "true" : "false"); + return str + stream.str(); } static string AddBoolString(bool b, const string &str) { - ostringstream stream; - stream << (b ? "true" : "false"); - return stream.str() + str; + ostringstream stream; + stream << (b ? "true" : "false"); + return stream.str() + str; } static char *StringCharAt(unsigned int i, string &str) { - if( i >= str.size() ) - { - // Set a script exception - asIScriptContext *ctx = asGetActiveContext(); - ctx->SetException("Out of range"); + if( i >= str.size() ) + { + // Set a script exception + asIScriptContext *ctx = asGetActiveContext(); + ctx->SetException("Out of range"); - // Return a null pointer - return 0; - } + // Return a null pointer + return 0; + } - return &str[i]; + return &str[i]; } // AngelScript signature: // int string::opCmp(const string &in) const static int StringCmp(const string &a, const string &b) { - int cmp = 0; - if( a < b ) cmp = -1; - else if( a > b ) cmp = 1; - return cmp; + int cmp = 0; + if( a < b ) cmp = -1; + else if( a > b ) cmp = 1; + return cmp; } // This function returns the index of the first position where the substring @@ -370,8 +336,54 @@ static int StringCmp(const string &a, const string &b) // int string::findFirst(const string &in sub, uint start = 0) const static int StringFindFirst(const string &sub, asUINT start, const string &str) { - // We don't register the method directly because the argument types change between 32bit and 64bit platforms - return (int)str.find(sub, start); + // We don't register the method directly because the argument types change between 32bit and 64bit platforms + return (int)str.find(sub, (size_t)(start < 0 ? string::npos : start)); +} + +// This function returns the index of the first position where the one of the bytes in substring +// exists in the input string. If the characters in the substring doesn't exist in the input +// string -1 is returned. +// +// AngelScript signature: +// int string::findFirstOf(const string &in sub, uint start = 0) const +static int StringFindFirstOf(const string &sub, asUINT start, const string &str) +{ + // We don't register the method directly because the argument types change between 32bit and 64bit platforms + return (int)str.find_first_of(sub, (size_t)(start < 0 ? string::npos : start)); +} + +// This function returns the index of the last position where the one of the bytes in substring +// exists in the input string. If the characters in the substring doesn't exist in the input +// string -1 is returned. +// +// AngelScript signature: +// int string::findLastOf(const string &in sub, uint start = -1) const +static int StringFindLastOf(const string &sub, asUINT start, const string &str) +{ + // We don't register the method directly because the argument types change between 32bit and 64bit platforms + return (int)str.find_last_of(sub, (size_t)(start < 0 ? string::npos : start)); +} + +// This function returns the index of the first position where a byte other than those in substring +// exists in the input string. If none is found -1 is returned. +// +// AngelScript signature: +// int string::findFirstNotOf(const string &in sub, uint start = 0) const +static int StringFindFirstNotOf(const string &sub, asUINT start, const string &str) +{ + // We don't register the method directly because the argument types change between 32bit and 64bit platforms + return (int)str.find_first_not_of(sub, (size_t)(start < 0 ? string::npos : start)); +} + +// This function returns the index of the last position where a byte other than those in substring +// exists in the input string. If none is found -1 is returned. +// +// AngelScript signature: +// int string::findLastNotOf(const string &in sub, uint start = -1) const +static int StringFindLastNotOf(const string &sub, asUINT start, const string &str) +{ + // We don't register the method directly because the argument types change between 32bit and 64bit platforms + return (int)str.find_last_of(sub, (size_t)(start < 0 ? string::npos : start)); } // This function returns the index of the last position where the substring @@ -382,16 +394,33 @@ static int StringFindFirst(const string &sub, asUINT start, const string &str) // int string::findLast(const string &in sub, int start = -1) const static int StringFindLast(const string &sub, int start, const string &str) { - // We don't register the method directly because the argument types change between 32bit and 64bit platforms - return (int)str.rfind(sub, (size_t)start); + // We don't register the method directly because the argument types change between 32bit and 64bit platforms + return (int)str.rfind(sub, (size_t)(start < 0 ? string::npos : start)); } +// AngelScript signature: +// void string::insert(uint pos, const string &in other) +static void StringInsert(unsigned int pos, const string &other, string &str) +{ + // We don't register the method directly because the argument types change between 32bit and 64bit platforms + str.insert(pos, other); +} + +// AngelScript signature: +// void string::erase(uint pos, int count = -1) +static void StringErase(unsigned int pos, int count, string &str) +{ + // We don't register the method directly because the argument types change between 32bit and 64bit platforms + str.erase(pos, (size_t)(count < 0 ? string::npos : count)); +} + + // AngelScript signature: // uint string::length() const static asUINT StringLength(const string &str) { - // We don't register the method directly because the return type changes between 32bit and 64bit platforms - return (asUINT)str.length(); + // We don't register the method directly because the return type changes between 32bit and 64bit platforms + return (asUINT)str.length(); } @@ -399,173 +428,261 @@ static asUINT StringLength(const string &str) // void string::resize(uint l) static void StringResize(asUINT l, string &str) { - // We don't register the method directly because the argument types change between 32bit and 64bit platforms - str.resize(l); + // We don't register the method directly because the argument types change between 32bit and 64bit platforms + str.resize(l); } // AngelScript signature: // string formatInt(int64 val, const string &in options, uint width) static string formatInt(asINT64 value, const string &options, asUINT width) { - bool leftJustify = options.find("l") != string::npos; - bool padWithZero = options.find("0") != string::npos; - bool alwaysSign = options.find("+") != string::npos; - bool spaceOnSign = options.find(" ") != string::npos; - bool hexSmall = options.find("h") != string::npos; - bool hexLarge = options.find("H") != string::npos; + bool leftJustify = options.find("l") != string::npos; + bool padWithZero = options.find("0") != string::npos; + bool alwaysSign = options.find("+") != string::npos; + bool spaceOnSign = options.find(" ") != string::npos; + bool hexSmall = options.find("h") != string::npos; + bool hexLarge = options.find("H") != string::npos; - string fmt = "%"; - if( leftJustify ) fmt += "-"; - if( alwaysSign ) fmt += "+"; - if( spaceOnSign ) fmt += " "; - if( padWithZero ) fmt += "0"; + string fmt = "%"; + if( leftJustify ) fmt += "-"; + if( alwaysSign ) fmt += "+"; + if( spaceOnSign ) fmt += " "; + if( padWithZero ) fmt += "0"; #ifdef _WIN32 - fmt += "*I64"; + fmt += "*I64"; #else #ifdef _LP64 - fmt += "*l"; + fmt += "*l"; #else - fmt += "*ll"; + fmt += "*ll"; #endif #endif - if( hexSmall ) fmt += "x"; - else if( hexLarge ) fmt += "X"; - else fmt += "d"; + if( hexSmall ) fmt += "x"; + else if( hexLarge ) fmt += "X"; + else fmt += "d"; - string buf; - buf.resize(width+30); + string buf; + buf.resize(width+30); #if _MSC_VER >= 1400 && !defined(__S3E__) - // MSVC 8.0 / 2005 or newer - sprintf_s(&buf[0], buf.size(), fmt.c_str(), width, value); + // MSVC 8.0 / 2005 or newer + sprintf_s(&buf[0], buf.size(), fmt.c_str(), width, value); #else - sprintf(&buf[0], fmt.c_str(), width, value); + sprintf(&buf[0], fmt.c_str(), width, value); #endif - buf.resize(strlen(&buf[0])); + buf.resize(strlen(&buf[0])); - return buf; + return buf; +} + +// AngelScript signature: +// string formatUInt(uint64 val, const string &in options, uint width) +static string formatUInt(asQWORD value, const string &options, asUINT width) +{ + bool leftJustify = options.find("l") != string::npos; + bool padWithZero = options.find("0") != string::npos; + bool alwaysSign = options.find("+") != string::npos; + bool spaceOnSign = options.find(" ") != string::npos; + bool hexSmall = options.find("h") != string::npos; + bool hexLarge = options.find("H") != string::npos; + + string fmt = "%"; + if( leftJustify ) fmt += "-"; + if( alwaysSign ) fmt += "+"; + if( spaceOnSign ) fmt += " "; + if( padWithZero ) fmt += "0"; + +#ifdef _WIN32 + fmt += "*I64"; +#else +#ifdef _LP64 + fmt += "*l"; +#else + fmt += "*ll"; +#endif +#endif + + if( hexSmall ) fmt += "x"; + else if( hexLarge ) fmt += "X"; + else fmt += "u"; + + string buf; + buf.resize(width+30); +#if _MSC_VER >= 1400 && !defined(__S3E__) + // MSVC 8.0 / 2005 or newer + sprintf_s(&buf[0], buf.size(), fmt.c_str(), width, value); +#else + sprintf(&buf[0], fmt.c_str(), width, value); +#endif + buf.resize(strlen(&buf[0])); + + return buf; } // AngelScript signature: // string formatFloat(double val, const string &in options, uint width, uint precision) static string formatFloat(double value, const string &options, asUINT width, asUINT precision) { - bool leftJustify = options.find("l") != string::npos; - bool padWithZero = options.find("0") != string::npos; - bool alwaysSign = options.find("+") != string::npos; - bool spaceOnSign = options.find(" ") != string::npos; - bool expSmall = options.find("e") != string::npos; - bool expLarge = options.find("E") != string::npos; + bool leftJustify = options.find("l") != string::npos; + bool padWithZero = options.find("0") != string::npos; + bool alwaysSign = options.find("+") != string::npos; + bool spaceOnSign = options.find(" ") != string::npos; + bool expSmall = options.find("e") != string::npos; + bool expLarge = options.find("E") != string::npos; - string fmt = "%"; - if( leftJustify ) fmt += "-"; - if( alwaysSign ) fmt += "+"; - if( spaceOnSign ) fmt += " "; - if( padWithZero ) fmt += "0"; + string fmt = "%"; + if( leftJustify ) fmt += "-"; + if( alwaysSign ) fmt += "+"; + if( spaceOnSign ) fmt += " "; + if( padWithZero ) fmt += "0"; - fmt += "*.*"; + fmt += "*.*"; - if( expSmall ) fmt += "e"; - else if( expLarge ) fmt += "E"; - else fmt += "f"; + if( expSmall ) fmt += "e"; + else if( expLarge ) fmt += "E"; + else fmt += "f"; - string buf; - buf.resize(width+precision+50); + string buf; + buf.resize(width+precision+50); #if _MSC_VER >= 1400 && !defined(__S3E__) - // MSVC 8.0 / 2005 or newer - sprintf_s(&buf[0], buf.size(), fmt.c_str(), width, precision, value); + // MSVC 8.0 / 2005 or newer + sprintf_s(&buf[0], buf.size(), fmt.c_str(), width, precision, value); #else - sprintf(&buf[0], fmt.c_str(), width, precision, value); + sprintf(&buf[0], fmt.c_str(), width, precision, value); #endif - buf.resize(strlen(&buf[0])); + buf.resize(strlen(&buf[0])); - return buf; + return buf; } // AngelScript signature: // int64 parseInt(const string &in val, uint base = 10, uint &out byteCount = 0) static asINT64 parseInt(const string &val, asUINT base, asUINT *byteCount) { - // Only accept base 10 and 16 - if( base != 10 && base != 16 ) - { - if( byteCount ) *byteCount = 0; - return 0; - } + // Only accept base 10 and 16 + if( base != 10 && base != 16 ) + { + if( byteCount ) *byteCount = 0; + return 0; + } - const char *end = &val[0]; + const char *end = &val[0]; - // Determine the sign - bool sign = false; - if( *end == '-' ) - { - sign = true; - end++; - } - else if( *end == '+' ) - end++; + // Determine the sign + bool sign = false; + if( *end == '-' ) + { + sign = true; + end++; + } + else if( *end == '+' ) + end++; - asINT64 res = 0; - if( base == 10 ) - { - while( *end >= '0' && *end <= '9' ) - { - res *= 10; - res += *end++ - '0'; - } - } - else if( base == 16 ) - { - while( (*end >= '0' && *end <= '9') || - (*end >= 'a' && *end <= 'f') || - (*end >= 'A' && *end <= 'F') ) - { - res *= 16; - if( *end >= '0' && *end <= '9' ) - res += *end++ - '0'; - else if( *end >= 'a' && *end <= 'f' ) - res += *end++ - 'a' + 10; - else if( *end >= 'A' && *end <= 'F' ) - res += *end++ - 'A' + 10; - } - } + asINT64 res = 0; + if( base == 10 ) + { + while( *end >= '0' && *end <= '9' ) + { + res *= 10; + res += *end++ - '0'; + } + } + else if( base == 16 ) + { + while( (*end >= '0' && *end <= '9') || + (*end >= 'a' && *end <= 'f') || + (*end >= 'A' && *end <= 'F') ) + { + res *= 16; + if( *end >= '0' && *end <= '9' ) + res += *end++ - '0'; + else if( *end >= 'a' && *end <= 'f' ) + res += *end++ - 'a' + 10; + else if( *end >= 'A' && *end <= 'F' ) + res += *end++ - 'A' + 10; + } + } - if( byteCount ) - *byteCount = asUINT(size_t(end - val.c_str())); + if( byteCount ) + *byteCount = asUINT(size_t(end - val.c_str())); - if( sign ) - res = -res; + if( sign ) + res = -res; - return res; + return res; +} + +// AngelScript signature: +// uint64 parseUInt(const string &in val, uint base = 10, uint &out byteCount = 0) +static asQWORD parseUInt(const string &val, asUINT base, asUINT *byteCount) +{ + // Only accept base 10 and 16 + if (base != 10 && base != 16) + { + if (byteCount) *byteCount = 0; + return 0; + } + + const char *end = &val[0]; + + asQWORD res = 0; + if (base == 10) + { + while (*end >= '0' && *end <= '9') + { + res *= 10; + res += *end++ - '0'; + } + } + else if (base == 16) + { + while ((*end >= '0' && *end <= '9') || + (*end >= 'a' && *end <= 'f') || + (*end >= 'A' && *end <= 'F')) + { + res *= 16; + if (*end >= '0' && *end <= '9') + res += *end++ - '0'; + else if (*end >= 'a' && *end <= 'f') + res += *end++ - 'a' + 10; + else if (*end >= 'A' && *end <= 'F') + res += *end++ - 'A' + 10; + } + } + + if (byteCount) + *byteCount = asUINT(size_t(end - val.c_str())); + + return res; } // AngelScript signature: // double parseFloat(const string &in val, uint &out byteCount = 0) double parseFloat(const string &val, asUINT *byteCount) { - char *end; + char *end; // WinCE doesn't have setlocale. Some quick testing on my current platform // still manages to parse the numbers such as "3.14" even if the decimal for the // locale is ",". #if !defined(_WIN32_WCE) && !defined(ANDROID) && !defined(__psp2__) - // Set the locale to C so that we are guaranteed to parse the float value correctly - char *orig = setlocale(LC_NUMERIC, 0); - setlocale(LC_NUMERIC, "C"); + // Set the locale to C so that we are guaranteed to parse the float value correctly + char *orig = setlocale(LC_NUMERIC, 0); + setlocale(LC_NUMERIC, "C"); #endif - double res = strtod(val.c_str(), &end); + double res = strtod(val.c_str(), &end); #if !defined(_WIN32_WCE) && !defined(ANDROID) && !defined(__psp2__) - // Restore the locale - setlocale(LC_NUMERIC, orig); + // Restore the locale + setlocale(LC_NUMERIC, orig); #endif - if( byteCount ) - *byteCount = asUINT(size_t(end - val.c_str())); + if( byteCount ) + *byteCount = asUINT(size_t(end - val.c_str())); - return res; + return res; } // This function returns a string containing the substring of the input string @@ -575,12 +692,12 @@ double parseFloat(const string &val, asUINT *byteCount) // string string::substr(uint start = 0, int count = -1) const static string StringSubString(asUINT start, int count, const string &str) { - // Check for out-of-bounds - string ret; - if( start < str.length() && count != 0 ) - ret = str.substr(start, count); + // Check for out-of-bounds + string ret; + if( start < str.length() && count != 0 ) + ret = str.substr(start, (size_t)(count < 0 ? string::npos : count)); - return ret; + return ret; } // String equality comparison. @@ -596,477 +713,516 @@ static bool StringEquals(const std::string& lhs, const std::string& rhs) void RegisterStdString_Native(asIScriptEngine *engine) { - int r = 0; - UNUSED_VAR(r); + int r = 0; + UNUSED_VAR(r); - // Register the string type + // Register the string type #if AS_CAN_USE_CPP11 - // With C++11 it is possible to use asGetTypeTraits to automatically determine the correct flags to use - r = engine->RegisterObjectType("string", sizeof(string), asOBJ_VALUE | asGetTypeTraits()); assert( r >= 0 ); + // With C++11 it is possible to use asGetTypeTraits to automatically determine the correct flags to use + r = engine->RegisterObjectType("string", sizeof(string), asOBJ_VALUE | asGetTypeTraits()); assert( r >= 0 ); #else - r = engine->RegisterObjectType("string", sizeof(string), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert( r >= 0 ); + r = engine->RegisterObjectType("string", sizeof(string), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert( r >= 0 ); #endif -#if AS_USE_STRINGPOOL == 1 - // Register the string factory - r = engine->RegisterStringFactory("const string &", asFUNCTION(StringFactory), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterStringFactory("string", &stringFactory); - // Register the cleanup callback for the string pool - engine->SetEngineUserDataCleanupCallback(CleanupEngineStringPool, STRING_POOL); -#else - // Register the string factory - r = engine->RegisterStringFactory("string", asFUNCTION(StringFactory), asCALL_CDECL); assert( r >= 0 ); -#endif + // Register the object operator overloads + r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f(const string &in)", asFUNCTION(CopyConstructString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAssign(const string &in)", asMETHODPR(string, operator =, (const string&), string&), asCALL_THISCALL); assert( r >= 0 ); + // Need to use a wrapper on Mac OS X 10.7/XCode 4.3 and CLang/LLVM, otherwise the linker fails + r = engine->RegisterObjectMethod("string", "string &opAddAssign(const string &in)", asFUNCTION(AddAssignStringToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); +// r = engine->RegisterObjectMethod("string", "string &opAddAssign(const string &in)", asMETHODPR(string, operator+=, (const string&), string&), asCALL_THISCALL); assert( r >= 0 ); - // Register the object operator overloads - r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f(const string &in)", asFUNCTION(CopyConstructString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAssign(const string &in)", asMETHODPR(string, operator =, (const string&), string&), asCALL_THISCALL); assert( r >= 0 ); - // Need to use a wrapper on Mac OS X 10.7/XCode 4.3 and CLang/LLVM, otherwise the linker fails - r = engine->RegisterObjectMethod("string", "string &opAddAssign(const string &in)", asFUNCTION(AddAssignStringToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); -// r = engine->RegisterObjectMethod("string", "string &opAddAssign(const string &in)", asMETHODPR(string, operator+=, (const string&), string&), asCALL_THISCALL); assert( r >= 0 ); + // Need to use a wrapper for operator== otherwise gcc 4.7 fails to compile + r = engine->RegisterObjectMethod("string", "bool opEquals(const string &in) const", asFUNCTIONPR(StringEquals, (const string &, const string &), bool), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "int opCmp(const string &in) const", asFUNCTION(StringCmp), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(const string &in) const", asFUNCTIONPR(operator +, (const string &, const string &), string), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); - // Need to use a wrapper for operator== otherwise gcc 4.7 fails to compile - r = engine->RegisterObjectMethod("string", "bool opEquals(const string &in) const", asFUNCTIONPR(StringEquals, (const string &, const string &), bool), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "int opCmp(const string &in) const", asFUNCTION(StringCmp), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd(const string &in) const", asFUNCTIONPR(operator +, (const string &, const string &), string), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + // The string length can be accessed through methods or through virtual property + r = engine->RegisterObjectMethod("string", "uint length() const", asFUNCTION(StringLength), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "void resize(uint)", asFUNCTION(StringResize), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "uint get_length() const", asFUNCTION(StringLength), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "void set_length(uint)", asFUNCTION(StringResize), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + // Need to use a wrapper on Mac OS X 10.7/XCode 4.3 and CLang/LLVM, otherwise the linker fails +// r = engine->RegisterObjectMethod("string", "bool isEmpty() const", asMETHOD(string, empty), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "bool isEmpty() const", asFUNCTION(StringIsEmpty), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - // The string length can be accessed through methods or through virtual property - r = engine->RegisterObjectMethod("string", "uint length() const", asFUNCTION(StringLength), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "void resize(uint)", asFUNCTION(StringResize), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "uint get_length() const", asFUNCTION(StringLength), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "void set_length(uint)", asFUNCTION(StringResize), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - // Need to use a wrapper on Mac OS X 10.7/XCode 4.3 and CLang/LLVM, otherwise the linker fails -// r = engine->RegisterObjectMethod("string", "bool isEmpty() const", asMETHOD(string, empty), asCALL_THISCALL); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "bool isEmpty() const", asFUNCTION(StringIsEmpty), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + // Register the index operator, both as a mutator and as an inspector + // Note that we don't register the operator[] directly, as it doesn't do bounds checking + r = engine->RegisterObjectMethod("string", "uint8 &opIndex(uint)", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "const uint8 &opIndex(uint) const", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - // Register the index operator, both as a mutator and as an inspector - // Note that we don't register the operator[] directly, as it doesn't do bounds checking - r = engine->RegisterObjectMethod("string", "uint8 &opIndex(uint)", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "const uint8 &opIndex(uint) const", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + // Automatic conversion from values + r = engine->RegisterObjectMethod("string", "string &opAssign(double)", asFUNCTION(AssignDoubleToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(double)", asFUNCTION(AddAssignDoubleToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(double) const", asFUNCTION(AddStringDouble), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(double) const", asFUNCTION(AddDoubleString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - // Automatic conversion from values - r = engine->RegisterObjectMethod("string", "string &opAssign(double)", asFUNCTION(AssignDoubleToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAddAssign(double)", asFUNCTION(AddAssignDoubleToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd(double) const", asFUNCTION(AddStringDouble), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd_r(double) const", asFUNCTION(AddDoubleString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAssign(float)", asFUNCTION(AssignFloatToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(float)", asFUNCTION(AddAssignFloatToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(float) const", asFUNCTION(AddStringFloat), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(float) const", asFUNCTION(AddFloatString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAssign(float)", asFUNCTION(AssignFloatToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAddAssign(float)", asFUNCTION(AddAssignFloatToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd(float) const", asFUNCTION(AddStringFloat), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd_r(float) const", asFUNCTION(AddFloatString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAssign(int64)", asFUNCTION(AssignInt64ToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(int64)", asFUNCTION(AddAssignInt64ToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(int64) const", asFUNCTION(AddStringInt64), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(int64) const", asFUNCTION(AddInt64String), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAssign(int64)", asFUNCTION(AssignInt64ToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAddAssign(int64)", asFUNCTION(AddAssignInt64ToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd(int64) const", asFUNCTION(AddStringInt64), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd_r(int64) const", asFUNCTION(AddInt64String), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAssign(uint64)", asFUNCTION(AssignUInt64ToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(uint64)", asFUNCTION(AddAssignUInt64ToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(uint64) const", asFUNCTION(AddStringUInt64), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(uint64) const", asFUNCTION(AddUInt64String), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAssign(uint64)", asFUNCTION(AssignUInt64ToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAddAssign(uint64)", asFUNCTION(AddAssignUInt64ToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd(uint64) const", asFUNCTION(AddStringUInt64), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd_r(uint64) const", asFUNCTION(AddUInt64String), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAssign(bool)", asFUNCTION(AssignBoolToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(bool)", asFUNCTION(AddAssignBoolToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(bool) const", asFUNCTION(AddStringBool), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(bool) const", asFUNCTION(AddBoolString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAssign(bool)", asFUNCTION(AssignBoolToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAddAssign(bool)", asFUNCTION(AddAssignBoolToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd(bool) const", asFUNCTION(AddStringBool), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd_r(bool) const", asFUNCTION(AddBoolString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + // Utilities + r = engine->RegisterObjectMethod("string", "string substr(uint start = 0, int count = -1) const", asFUNCTION(StringSubString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "int findFirst(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "int findFirstOf(const string &in, uint start = 0) const", asFUNCTION(StringFindFirstOf), asCALL_CDECL_OBJLAST); assert(r >= 0); + r = engine->RegisterObjectMethod("string", "int findFirstNotOf(const string &in, uint start = 0) const", asFUNCTION(StringFindFirstNotOf), asCALL_CDECL_OBJLAST); assert(r >= 0); + r = engine->RegisterObjectMethod("string", "int findLast(const string &in, int start = -1) const", asFUNCTION(StringFindLast), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "int findLastOf(const string &in, int start = -1) const", asFUNCTION(StringFindLastOf), asCALL_CDECL_OBJLAST); assert(r >= 0); + r = engine->RegisterObjectMethod("string", "int findLastNotOf(const string &in, int start = -1) const", asFUNCTION(StringFindLastNotOf), asCALL_CDECL_OBJLAST); assert(r >= 0); + r = engine->RegisterObjectMethod("string", "void insert(uint pos, const string &in other)", asFUNCTION(StringInsert), asCALL_CDECL_OBJLAST); assert(r >= 0); + r = engine->RegisterObjectMethod("string", "void erase(uint pos, int count = -1)", asFUNCTION(StringErase), asCALL_CDECL_OBJLAST); assert(r >= 0); - // Utilities - r = engine->RegisterObjectMethod("string", "string substr(uint start = 0, int count = -1) const", asFUNCTION(StringSubString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "int findFirst(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "int findLast(const string &in, int start = -1) const", asFUNCTION(StringFindLast), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - r = engine->RegisterGlobalFunction("string formatInt(int64 val, const string &in options, uint width = 0)", asFUNCTION(formatInt), asCALL_CDECL); assert(r >= 0); - r = engine->RegisterGlobalFunction("string formatFloat(double val, const string &in options, uint width = 0, uint precision = 0)", asFUNCTION(formatFloat), asCALL_CDECL); assert(r >= 0); - r = engine->RegisterGlobalFunction("int64 parseInt(const string &in, uint base = 10, uint &out byteCount = 0)", asFUNCTION(parseInt), asCALL_CDECL); assert(r >= 0); - r = engine->RegisterGlobalFunction("double parseFloat(const string &in, uint &out byteCount = 0)", asFUNCTION(parseFloat), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("string formatInt(int64 val, const string &in options = \"\", uint width = 0)", asFUNCTION(formatInt), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("string formatUInt(uint64 val, const string &in options = \"\", uint width = 0)", asFUNCTION(formatUInt), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("string formatFloat(double val, const string &in options = \"\", uint width = 0, uint precision = 0)", asFUNCTION(formatFloat), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("int64 parseInt(const string &in, uint base = 10, uint &out byteCount = 0)", asFUNCTION(parseInt), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("uint64 parseUInt(const string &in, uint base = 10, uint &out byteCount = 0)", asFUNCTION(parseUInt), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("double parseFloat(const string &in, uint &out byteCount = 0)", asFUNCTION(parseFloat), asCALL_CDECL); assert(r >= 0); #if AS_USE_STLNAMES == 1 - // Same as length - r = engine->RegisterObjectMethod("string", "uint size() const", asFUNCTION(StringLength), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - // Same as isEmpty - r = engine->RegisterObjectMethod("string", "bool empty() const", asFUNCTION(StringIsEmpty), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - // Same as findFirst - r = engine->RegisterObjectMethod("string", "int find(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst), asCALL_CDECL_OBJLAST); assert( r >= 0 ); - // Same as findLast - r = engine->RegisterObjectMethod("string", "int rfind(const string &in, int start = -1) const", asFUNCTION(StringFindLast), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + // Same as length + r = engine->RegisterObjectMethod("string", "uint size() const", asFUNCTION(StringLength), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + // Same as isEmpty + r = engine->RegisterObjectMethod("string", "bool empty() const", asFUNCTION(StringIsEmpty), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + // Same as findFirst + r = engine->RegisterObjectMethod("string", "int find(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + // Same as findLast + r = engine->RegisterObjectMethod("string", "int rfind(const string &in, int start = -1) const", asFUNCTION(StringFindLast), asCALL_CDECL_OBJLAST); assert( r >= 0 ); #endif - // TODO: Implement the following - // findFirstOf - // findLastOf - // findFirstNotOf - // findLastNotOf - // findAndReplace - replaces a text found in the string - // replaceRange - replaces a range of bytes in the string - // trim/trimLeft/trimRight - // multiply/times/opMul/opMul_r - takes the string and multiplies it n times, e.g. "-".multiply(5) returns "-----" + // TODO: Implement the following + // findAndReplace - replaces a text found in the string + // replaceRange - replaces a range of bytes in the string + // multiply/times/opMul/opMul_r - takes the string and multiplies it n times, e.g. "-".multiply(5) returns "-----" } -#if AS_USE_STRINGPOOL == 1 -static void StringFactoryGeneric(asIScriptGeneric *gen) -{ - asUINT length = gen->GetArgDWord(0); - const char *s = (const char*)gen->GetArgAddress(1); - - // Return a reference to a string - gen->SetReturnAddress(const_cast(&StringFactory(length, s))); -} -#else -static void StringFactoryGeneric(asIScriptGeneric *gen) -{ - asUINT length = gen->GetArgDWord(0); - const char *s = (const char*)gen->GetArgAddress(1); - - // Return a string value - new (gen->GetAddressOfReturnLocation()) string(StringFactory(length, s)); -} -#endif - static void ConstructStringGeneric(asIScriptGeneric * gen) { - new (gen->GetObject()) string(); + new (gen->GetObject()) string(); } static void CopyConstructStringGeneric(asIScriptGeneric * gen) { - string * a = static_cast(gen->GetArgObject(0)); - new (gen->GetObject()) string(*a); + string * a = static_cast(gen->GetArgObject(0)); + new (gen->GetObject()) string(*a); } static void DestructStringGeneric(asIScriptGeneric * gen) { - string * ptr = static_cast(gen->GetObject()); - ptr->~string(); + string * ptr = static_cast(gen->GetObject()); + ptr->~string(); } static void AssignStringGeneric(asIScriptGeneric *gen) { - string * a = static_cast(gen->GetArgObject(0)); - string * self = static_cast(gen->GetObject()); - *self = *a; - gen->SetReturnAddress(self); + string * a = static_cast(gen->GetArgObject(0)); + string * self = static_cast(gen->GetObject()); + *self = *a; + gen->SetReturnAddress(self); } static void AddAssignStringGeneric(asIScriptGeneric *gen) { - string * a = static_cast(gen->GetArgObject(0)); - string * self = static_cast(gen->GetObject()); - *self += *a; - gen->SetReturnAddress(self); + string * a = static_cast(gen->GetArgObject(0)); + string * self = static_cast(gen->GetObject()); + *self += *a; + gen->SetReturnAddress(self); } static void StringEqualsGeneric(asIScriptGeneric * gen) { - string * a = static_cast(gen->GetObject()); - string * b = static_cast(gen->GetArgAddress(0)); - *(bool*)gen->GetAddressOfReturnLocation() = (*a == *b); + string * a = static_cast(gen->GetObject()); + string * b = static_cast(gen->GetArgAddress(0)); + *(bool*)gen->GetAddressOfReturnLocation() = (*a == *b); } static void StringCmpGeneric(asIScriptGeneric * gen) { - string * a = static_cast(gen->GetObject()); - string * b = static_cast(gen->GetArgAddress(0)); + string * a = static_cast(gen->GetObject()); + string * b = static_cast(gen->GetArgAddress(0)); - int cmp = 0; - if( *a < *b ) cmp = -1; - else if( *a > *b ) cmp = 1; + int cmp = 0; + if( *a < *b ) cmp = -1; + else if( *a > *b ) cmp = 1; - *(int*)gen->GetAddressOfReturnLocation() = cmp; + *(int*)gen->GetAddressOfReturnLocation() = cmp; } static void StringAddGeneric(asIScriptGeneric * gen) { - string * a = static_cast(gen->GetObject()); - string * b = static_cast(gen->GetArgAddress(0)); - string ret_val = *a + *b; - gen->SetReturnObject(&ret_val); + string * a = static_cast(gen->GetObject()); + string * b = static_cast(gen->GetArgAddress(0)); + string ret_val = *a + *b; + gen->SetReturnObject(&ret_val); } static void StringLengthGeneric(asIScriptGeneric * gen) { - string * self = static_cast(gen->GetObject()); - *static_cast(gen->GetAddressOfReturnLocation()) = (asUINT)self->length(); + string * self = static_cast(gen->GetObject()); + *static_cast(gen->GetAddressOfReturnLocation()) = (asUINT)self->length(); } static void StringIsEmptyGeneric(asIScriptGeneric * gen) { - string * self = reinterpret_cast(gen->GetObject()); - *reinterpret_cast(gen->GetAddressOfReturnLocation()) = StringIsEmpty(*self); + string * self = reinterpret_cast(gen->GetObject()); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = StringIsEmpty(*self); } static void StringResizeGeneric(asIScriptGeneric * gen) { - string * self = static_cast(gen->GetObject()); - self->resize(*static_cast(gen->GetAddressOfArg(0))); + string * self = static_cast(gen->GetObject()); + self->resize(*static_cast(gen->GetAddressOfArg(0))); +} + +static void StringInsert_Generic(asIScriptGeneric *gen) +{ + string * self = static_cast(gen->GetObject()); + asUINT pos = gen->GetArgDWord(0); + string *other = reinterpret_cast(gen->GetArgAddress(1)); + StringInsert(pos, *other, *self); +} + +static void StringErase_Generic(asIScriptGeneric *gen) +{ + string * self = static_cast(gen->GetObject()); + asUINT pos = gen->GetArgDWord(0); + int count = int(gen->GetArgDWord(1)); + StringErase(pos, count, *self); } static void StringFindFirst_Generic(asIScriptGeneric * gen) { - string *find = reinterpret_cast(gen->GetArgAddress(0)); - asUINT start = gen->GetArgDWord(1); - string *self = reinterpret_cast(gen->GetObject()); - *reinterpret_cast(gen->GetAddressOfReturnLocation()) = StringFindFirst(*find, start, *self); + string *find = reinterpret_cast(gen->GetArgAddress(0)); + asUINT start = gen->GetArgDWord(1); + string *self = reinterpret_cast(gen->GetObject()); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = StringFindFirst(*find, start, *self); } static void StringFindLast_Generic(asIScriptGeneric * gen) { - string *find = reinterpret_cast(gen->GetArgAddress(0)); - asUINT start = gen->GetArgDWord(1); - string *self = reinterpret_cast(gen->GetObject()); - *reinterpret_cast(gen->GetAddressOfReturnLocation()) = StringFindLast(*find, start, *self); + string *find = reinterpret_cast(gen->GetArgAddress(0)); + asUINT start = gen->GetArgDWord(1); + string *self = reinterpret_cast(gen->GetObject()); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = StringFindLast(*find, start, *self); +} + +static void StringFindFirstOf_Generic(asIScriptGeneric * gen) +{ + string *find = reinterpret_cast(gen->GetArgAddress(0)); + asUINT start = gen->GetArgDWord(1); + string *self = reinterpret_cast(gen->GetObject()); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = StringFindFirstOf(*find, start, *self); +} + +static void StringFindLastOf_Generic(asIScriptGeneric * gen) +{ + string *find = reinterpret_cast(gen->GetArgAddress(0)); + asUINT start = gen->GetArgDWord(1); + string *self = reinterpret_cast(gen->GetObject()); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = StringFindLastOf(*find, start, *self); +} + +static void StringFindFirstNotOf_Generic(asIScriptGeneric * gen) +{ + string *find = reinterpret_cast(gen->GetArgAddress(0)); + asUINT start = gen->GetArgDWord(1); + string *self = reinterpret_cast(gen->GetObject()); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = StringFindFirstNotOf(*find, start, *self); +} + +static void StringFindLastNotOf_Generic(asIScriptGeneric * gen) +{ + string *find = reinterpret_cast(gen->GetArgAddress(0)); + asUINT start = gen->GetArgDWord(1); + string *self = reinterpret_cast(gen->GetObject()); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = StringFindLastNotOf(*find, start, *self); } static void formatInt_Generic(asIScriptGeneric * gen) { - asINT64 val = gen->GetArgQWord(0); - string *options = reinterpret_cast(gen->GetArgAddress(1)); - asUINT width = gen->GetArgDWord(2); - new(gen->GetAddressOfReturnLocation()) string(formatInt(val, *options, width)); + asINT64 val = gen->GetArgQWord(0); + string *options = reinterpret_cast(gen->GetArgAddress(1)); + asUINT width = gen->GetArgDWord(2); + new(gen->GetAddressOfReturnLocation()) string(formatInt(val, *options, width)); +} + +static void formatUInt_Generic(asIScriptGeneric * gen) +{ + asQWORD val = gen->GetArgQWord(0); + string *options = reinterpret_cast(gen->GetArgAddress(1)); + asUINT width = gen->GetArgDWord(2); + new(gen->GetAddressOfReturnLocation()) string(formatUInt(val, *options, width)); } static void formatFloat_Generic(asIScriptGeneric *gen) { - double val = gen->GetArgDouble(0); - string *options = reinterpret_cast(gen->GetArgAddress(1)); - asUINT width = gen->GetArgDWord(2); - asUINT precision = gen->GetArgDWord(3); - new(gen->GetAddressOfReturnLocation()) string(formatFloat(val, *options, width, precision)); + double val = gen->GetArgDouble(0); + string *options = reinterpret_cast(gen->GetArgAddress(1)); + asUINT width = gen->GetArgDWord(2); + asUINT precision = gen->GetArgDWord(3); + new(gen->GetAddressOfReturnLocation()) string(formatFloat(val, *options, width, precision)); } static void parseInt_Generic(asIScriptGeneric *gen) { - string *str = reinterpret_cast(gen->GetArgAddress(0)); - asUINT base = gen->GetArgDWord(1); - asUINT *byteCount = reinterpret_cast(gen->GetArgAddress(2)); - gen->SetReturnQWord(parseInt(*str,base,byteCount)); + string *str = reinterpret_cast(gen->GetArgAddress(0)); + asUINT base = gen->GetArgDWord(1); + asUINT *byteCount = reinterpret_cast(gen->GetArgAddress(2)); + gen->SetReturnQWord(parseInt(*str,base,byteCount)); +} + +static void parseUInt_Generic(asIScriptGeneric *gen) +{ + string *str = reinterpret_cast(gen->GetArgAddress(0)); + asUINT base = gen->GetArgDWord(1); + asUINT *byteCount = reinterpret_cast(gen->GetArgAddress(2)); + gen->SetReturnQWord(parseUInt(*str, base, byteCount)); } static void parseFloat_Generic(asIScriptGeneric *gen) { - string *str = reinterpret_cast(gen->GetArgAddress(0)); - asUINT *byteCount = reinterpret_cast(gen->GetArgAddress(1)); - gen->SetReturnDouble(parseFloat(*str,byteCount)); + string *str = reinterpret_cast(gen->GetArgAddress(0)); + asUINT *byteCount = reinterpret_cast(gen->GetArgAddress(1)); + gen->SetReturnDouble(parseFloat(*str,byteCount)); } static void StringCharAtGeneric(asIScriptGeneric * gen) { - unsigned int index = gen->GetArgDWord(0); - string * self = static_cast(gen->GetObject()); + unsigned int index = gen->GetArgDWord(0); + string * self = static_cast(gen->GetObject()); - if (index >= self->size()) - { - // Set a script exception - asIScriptContext *ctx = asGetActiveContext(); - ctx->SetException("Out of range"); + if (index >= self->size()) + { + // Set a script exception + asIScriptContext *ctx = asGetActiveContext(); + ctx->SetException("Out of range"); - gen->SetReturnAddress(0); - } - else - { - gen->SetReturnAddress(&(self->operator [](index))); - } + gen->SetReturnAddress(0); + } + else + { + gen->SetReturnAddress(&(self->operator [](index))); + } } static void AssignInt2StringGeneric(asIScriptGeneric *gen) { - asINT64 *a = static_cast(gen->GetAddressOfArg(0)); - string *self = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << *a; - *self = sstr.str(); - gen->SetReturnAddress(self); + asINT64 *a = static_cast(gen->GetAddressOfArg(0)); + string *self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self = sstr.str(); + gen->SetReturnAddress(self); } static void AssignUInt2StringGeneric(asIScriptGeneric *gen) { - asQWORD *a = static_cast(gen->GetAddressOfArg(0)); - string *self = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << *a; - *self = sstr.str(); - gen->SetReturnAddress(self); + asQWORD *a = static_cast(gen->GetAddressOfArg(0)); + string *self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self = sstr.str(); + gen->SetReturnAddress(self); } static void AssignDouble2StringGeneric(asIScriptGeneric *gen) { - double *a = static_cast(gen->GetAddressOfArg(0)); - string *self = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << *a; - *self = sstr.str(); - gen->SetReturnAddress(self); + double *a = static_cast(gen->GetAddressOfArg(0)); + string *self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self = sstr.str(); + gen->SetReturnAddress(self); } static void AssignFloat2StringGeneric(asIScriptGeneric *gen) { - float *a = static_cast(gen->GetAddressOfArg(0)); - string *self = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << *a; - *self = sstr.str(); - gen->SetReturnAddress(self); + float *a = static_cast(gen->GetAddressOfArg(0)); + string *self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self = sstr.str(); + gen->SetReturnAddress(self); } static void AssignBool2StringGeneric(asIScriptGeneric *gen) { - bool *a = static_cast(gen->GetAddressOfArg(0)); - string *self = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << (*a ? "true" : "false"); - *self = sstr.str(); - gen->SetReturnAddress(self); + bool *a = static_cast(gen->GetAddressOfArg(0)); + string *self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << (*a ? "true" : "false"); + *self = sstr.str(); + gen->SetReturnAddress(self); } static void AddAssignDouble2StringGeneric(asIScriptGeneric * gen) { - double * a = static_cast(gen->GetAddressOfArg(0)); - string * self = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << *a; - *self += sstr.str(); - gen->SetReturnAddress(self); + double * a = static_cast(gen->GetAddressOfArg(0)); + string * self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self += sstr.str(); + gen->SetReturnAddress(self); } static void AddAssignFloat2StringGeneric(asIScriptGeneric * gen) { - float * a = static_cast(gen->GetAddressOfArg(0)); - string * self = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << *a; - *self += sstr.str(); - gen->SetReturnAddress(self); + float * a = static_cast(gen->GetAddressOfArg(0)); + string * self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self += sstr.str(); + gen->SetReturnAddress(self); } static void AddAssignInt2StringGeneric(asIScriptGeneric * gen) { - asINT64 * a = static_cast(gen->GetAddressOfArg(0)); - string * self = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << *a; - *self += sstr.str(); - gen->SetReturnAddress(self); + asINT64 * a = static_cast(gen->GetAddressOfArg(0)); + string * self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self += sstr.str(); + gen->SetReturnAddress(self); } static void AddAssignUInt2StringGeneric(asIScriptGeneric * gen) { - asQWORD * a = static_cast(gen->GetAddressOfArg(0)); - string * self = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << *a; - *self += sstr.str(); - gen->SetReturnAddress(self); + asQWORD * a = static_cast(gen->GetAddressOfArg(0)); + string * self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self += sstr.str(); + gen->SetReturnAddress(self); } static void AddAssignBool2StringGeneric(asIScriptGeneric * gen) { - bool * a = static_cast(gen->GetAddressOfArg(0)); - string * self = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << (*a ? "true" : "false"); - *self += sstr.str(); - gen->SetReturnAddress(self); + bool * a = static_cast(gen->GetAddressOfArg(0)); + string * self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << (*a ? "true" : "false"); + *self += sstr.str(); + gen->SetReturnAddress(self); } static void AddString2DoubleGeneric(asIScriptGeneric * gen) { - string * a = static_cast(gen->GetObject()); - double * b = static_cast(gen->GetAddressOfArg(0)); - std::stringstream sstr; - sstr << *a << *b; - std::string ret_val = sstr.str(); - gen->SetReturnObject(&ret_val); + string * a = static_cast(gen->GetObject()); + double * b = static_cast(gen->GetAddressOfArg(0)); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); } static void AddString2FloatGeneric(asIScriptGeneric * gen) { - string * a = static_cast(gen->GetObject()); - float * b = static_cast(gen->GetAddressOfArg(0)); - std::stringstream sstr; - sstr << *a << *b; - std::string ret_val = sstr.str(); - gen->SetReturnObject(&ret_val); + string * a = static_cast(gen->GetObject()); + float * b = static_cast(gen->GetAddressOfArg(0)); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); } static void AddString2IntGeneric(asIScriptGeneric * gen) { - string * a = static_cast(gen->GetObject()); - asINT64 * b = static_cast(gen->GetAddressOfArg(0)); - std::stringstream sstr; - sstr << *a << *b; - std::string ret_val = sstr.str(); - gen->SetReturnObject(&ret_val); + string * a = static_cast(gen->GetObject()); + asINT64 * b = static_cast(gen->GetAddressOfArg(0)); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); } static void AddString2UIntGeneric(asIScriptGeneric * gen) { - string * a = static_cast(gen->GetObject()); - asQWORD * b = static_cast(gen->GetAddressOfArg(0)); - std::stringstream sstr; - sstr << *a << *b; - std::string ret_val = sstr.str(); - gen->SetReturnObject(&ret_val); + string * a = static_cast(gen->GetObject()); + asQWORD * b = static_cast(gen->GetAddressOfArg(0)); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); } static void AddString2BoolGeneric(asIScriptGeneric * gen) { - string * a = static_cast(gen->GetObject()); - bool * b = static_cast(gen->GetAddressOfArg(0)); - std::stringstream sstr; - sstr << *a << (*b ? "true" : "false"); - std::string ret_val = sstr.str(); - gen->SetReturnObject(&ret_val); + string * a = static_cast(gen->GetObject()); + bool * b = static_cast(gen->GetAddressOfArg(0)); + std::stringstream sstr; + sstr << *a << (*b ? "true" : "false"); + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); } static void AddDouble2StringGeneric(asIScriptGeneric * gen) { - double* a = static_cast(gen->GetAddressOfArg(0)); - string * b = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << *a << *b; - std::string ret_val = sstr.str(); - gen->SetReturnObject(&ret_val); + double* a = static_cast(gen->GetAddressOfArg(0)); + string * b = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); } static void AddFloat2StringGeneric(asIScriptGeneric * gen) { - float* a = static_cast(gen->GetAddressOfArg(0)); - string * b = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << *a << *b; - std::string ret_val = sstr.str(); - gen->SetReturnObject(&ret_val); + float* a = static_cast(gen->GetAddressOfArg(0)); + string * b = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); } static void AddInt2StringGeneric(asIScriptGeneric * gen) { - asINT64* a = static_cast(gen->GetAddressOfArg(0)); - string * b = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << *a << *b; - std::string ret_val = sstr.str(); - gen->SetReturnObject(&ret_val); + asINT64* a = static_cast(gen->GetAddressOfArg(0)); + string * b = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); } static void AddUInt2StringGeneric(asIScriptGeneric * gen) { - asQWORD* a = static_cast(gen->GetAddressOfArg(0)); - string * b = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << *a << *b; - std::string ret_val = sstr.str(); - gen->SetReturnObject(&ret_val); + asQWORD* a = static_cast(gen->GetAddressOfArg(0)); + string * b = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); } static void AddBool2StringGeneric(asIScriptGeneric * gen) { - bool* a = static_cast(gen->GetAddressOfArg(0)); - string * b = static_cast(gen->GetObject()); - std::stringstream sstr; - sstr << (*a ? "true" : "false") << *b; - std::string ret_val = sstr.str(); - gen->SetReturnObject(&ret_val); + bool* a = static_cast(gen->GetAddressOfArg(0)); + string * b = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << (*a ? "true" : "false") << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); } static void StringSubString_Generic(asIScriptGeneric *gen) @@ -1076,93 +1232,93 @@ static void StringSubString_Generic(asIScriptGeneric *gen) asUINT start = *(int*)gen->GetAddressOfArg(0); int count = *(int*)gen->GetAddressOfArg(1); - // Return the substring + // Return the substring new(gen->GetAddressOfReturnLocation()) string(StringSubString(start, count, *str)); } void RegisterStdString_Generic(asIScriptEngine *engine) { - int r = 0; - UNUSED_VAR(r); + int r = 0; + UNUSED_VAR(r); - // Register the string type - r = engine->RegisterObjectType("string", sizeof(string), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert( r >= 0 ); + // Register the string type + r = engine->RegisterObjectType("string", sizeof(string), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert( r >= 0 ); -#if AS_USE_STRINGPOOL == 1 - // Register the string factory - r = engine->RegisterStringFactory("const string &", asFUNCTION(StringFactoryGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterStringFactory("string", &stringFactory); - // Register the cleanup callback for the string pool - engine->SetEngineUserDataCleanupCallback(CleanupEngineStringPool, STRING_POOL); -#else - // Register the string factory - r = engine->RegisterStringFactory("string", asFUNCTION(StringFactoryGeneric), asCALL_GENERIC); assert( r >= 0 ); -#endif + // Register the object operator overloads + r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructStringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f(const string &in)", asFUNCTION(CopyConstructStringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructStringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAssign(const string &in)", asFUNCTION(AssignStringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(const string &in)", asFUNCTION(AddAssignStringGeneric), asCALL_GENERIC); assert( r >= 0 ); - // Register the object operator overloads - r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructStringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f(const string &in)", asFUNCTION(CopyConstructStringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectBehaviour("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructStringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAssign(const string &in)", asFUNCTION(AssignStringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAddAssign(const string &in)", asFUNCTION(AddAssignStringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "bool opEquals(const string &in) const", asFUNCTION(StringEqualsGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "int opCmp(const string &in) const", asFUNCTION(StringCmpGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(const string &in) const", asFUNCTION(StringAddGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "bool opEquals(const string &in) const", asFUNCTION(StringEqualsGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "int opCmp(const string &in) const", asFUNCTION(StringCmpGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd(const string &in) const", asFUNCTION(StringAddGeneric), asCALL_GENERIC); assert( r >= 0 ); + // Register the object methods + r = engine->RegisterObjectMethod("string", "uint length() const", asFUNCTION(StringLengthGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "void resize(uint)", asFUNCTION(StringResizeGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "uint get_length() const", asFUNCTION(StringLengthGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "void set_length(uint)", asFUNCTION(StringResizeGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "bool isEmpty() const", asFUNCTION(StringIsEmptyGeneric), asCALL_GENERIC); assert( r >= 0 ); - // Register the object methods - r = engine->RegisterObjectMethod("string", "uint length() const", asFUNCTION(StringLengthGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "void resize(uint)", asFUNCTION(StringResizeGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "uint get_length() const", asFUNCTION(StringLengthGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "void set_length(uint)", asFUNCTION(StringResizeGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "bool isEmpty() const", asFUNCTION(StringIsEmptyGeneric), asCALL_GENERIC); assert( r >= 0 ); + // Register the index operator, both as a mutator and as an inspector + r = engine->RegisterObjectMethod("string", "uint8 &opIndex(uint)", asFUNCTION(StringCharAtGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "const uint8 &opIndex(uint) const", asFUNCTION(StringCharAtGeneric), asCALL_GENERIC); assert( r >= 0 ); - // Register the index operator, both as a mutator and as an inspector - r = engine->RegisterObjectMethod("string", "uint8 &opIndex(uint)", asFUNCTION(StringCharAtGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "const uint8 &opIndex(uint) const", asFUNCTION(StringCharAtGeneric), asCALL_GENERIC); assert( r >= 0 ); + // Automatic conversion from values + r = engine->RegisterObjectMethod("string", "string &opAssign(double)", asFUNCTION(AssignDouble2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(double)", asFUNCTION(AddAssignDouble2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(double) const", asFUNCTION(AddString2DoubleGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(double) const", asFUNCTION(AddDouble2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - // Automatic conversion from values - r = engine->RegisterObjectMethod("string", "string &opAssign(double)", asFUNCTION(AssignDouble2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAddAssign(double)", asFUNCTION(AddAssignDouble2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd(double) const", asFUNCTION(AddString2DoubleGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd_r(double) const", asFUNCTION(AddDouble2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAssign(float)", asFUNCTION(AssignFloat2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(float)", asFUNCTION(AddAssignFloat2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(float) const", asFUNCTION(AddString2FloatGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(float) const", asFUNCTION(AddFloat2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAssign(float)", asFUNCTION(AssignFloat2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAddAssign(float)", asFUNCTION(AddAssignFloat2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd(float) const", asFUNCTION(AddString2FloatGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd_r(float) const", asFUNCTION(AddFloat2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAssign(int64)", asFUNCTION(AssignInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(int64)", asFUNCTION(AddAssignInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(int64) const", asFUNCTION(AddString2IntGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(int64) const", asFUNCTION(AddInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAssign(int64)", asFUNCTION(AssignInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAddAssign(int64)", asFUNCTION(AddAssignInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd(int64) const", asFUNCTION(AddString2IntGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd_r(int64) const", asFUNCTION(AddInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAssign(uint64)", asFUNCTION(AssignUInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(uint64)", asFUNCTION(AddAssignUInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(uint64) const", asFUNCTION(AddString2UIntGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(uint64) const", asFUNCTION(AddUInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAssign(uint64)", asFUNCTION(AssignUInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAddAssign(uint64)", asFUNCTION(AddAssignUInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd(uint64) const", asFUNCTION(AddString2UIntGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd_r(uint64) const", asFUNCTION(AddUInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAssign(bool)", asFUNCTION(AssignBool2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(bool)", asFUNCTION(AddAssignBool2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(bool) const", asFUNCTION(AddString2BoolGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(bool) const", asFUNCTION(AddBool2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAssign(bool)", asFUNCTION(AssignBool2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string &opAddAssign(bool)", asFUNCTION(AddAssignBool2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd(bool) const", asFUNCTION(AddString2BoolGeneric), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "string opAdd_r(bool) const", asFUNCTION(AddBool2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string substr(uint start = 0, int count = -1) const", asFUNCTION(StringSubString_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("string", "int findFirst(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("string", "int findFirstOf(const string &in, uint start = 0) const", asFUNCTION(StringFindFirstOf_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("string", "int findFirstNotOf(const string &in, uint start = 0) const", asFUNCTION(StringFindFirstNotOf_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("string", "int findLast(const string &in, int start = -1) const", asFUNCTION(StringFindLast_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("string", "int findLastOf(const string &in, int start = -1) const", asFUNCTION(StringFindLastOf_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("string", "int findLastNotOf(const string &in, int start = -1) const", asFUNCTION(StringFindLastNotOf_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("string", "void insert(uint pos, const string &in other)", asFUNCTION(StringInsert_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("string", "void erase(uint pos, int count = -1)", asFUNCTION(StringErase_Generic), asCALL_GENERIC); assert(r >= 0); - r = engine->RegisterObjectMethod("string", "string substr(uint start = 0, int count = -1) const", asFUNCTION(StringSubString_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "int findFirst(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterObjectMethod("string", "int findLast(const string &in, int start = -1) const", asFUNCTION(StringFindLast_Generic), asCALL_GENERIC); assert( r >= 0 ); - r = engine->RegisterGlobalFunction("string formatInt(int64 val, const string &in options, uint width = 0)", asFUNCTION(formatInt_Generic), asCALL_GENERIC); assert(r >= 0); - r = engine->RegisterGlobalFunction("string formatFloat(double val, const string &in options, uint width = 0, uint precision = 0)", asFUNCTION(formatFloat_Generic), asCALL_GENERIC); assert(r >= 0); - r = engine->RegisterGlobalFunction("int64 parseInt(const string &in, uint base = 10, uint &out byteCount = 0)", asFUNCTION(parseInt_Generic), asCALL_GENERIC); assert(r >= 0); - r = engine->RegisterGlobalFunction("double parseFloat(const string &in, uint &out byteCount = 0)", asFUNCTION(parseFloat_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterGlobalFunction("string formatInt(int64 val, const string &in options = \"\", uint width = 0)", asFUNCTION(formatInt_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterGlobalFunction("string formatUInt(uint64 val, const string &in options = \"\", uint width = 0)", asFUNCTION(formatUInt_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterGlobalFunction("string formatFloat(double val, const string &in options = \"\", uint width = 0, uint precision = 0)", asFUNCTION(formatFloat_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterGlobalFunction("int64 parseInt(const string &in, uint base = 10, uint &out byteCount = 0)", asFUNCTION(parseInt_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterGlobalFunction("uint64 parseUInt(const string &in, uint base = 10, uint &out byteCount = 0)", asFUNCTION(parseUInt_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterGlobalFunction("double parseFloat(const string &in, uint &out byteCount = 0)", asFUNCTION(parseFloat_Generic), asCALL_GENERIC); assert(r >= 0); } void RegisterStdString(asIScriptEngine * engine) { - if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY")) - RegisterStdString_Generic(engine); - else - RegisterStdString_Native(engine); + if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY")) + RegisterStdString_Generic(engine); + else + RegisterStdString_Native(engine); } END_AS_NAMESPACE diff --git a/src/scriptengine/scriptstdstring.hpp b/src/scriptengine/scriptstdstring.hpp index d7e3a49c6..c956f6661 100644 --- a/src/scriptengine/scriptstdstring.hpp +++ b/src/scriptengine/scriptstdstring.hpp @@ -1,3 +1,33 @@ +/* + AngelCode Scripting Library + Copyright (c) 2003-2017 Andreas Jonsson + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + The original version of this library can be located at: + http://www.angelcode.com/angelscript/ + + Andreas Jonsson + andreas@angelcode.com +*/ + // // Script std::string // @@ -11,29 +41,17 @@ #ifndef SCRIPTSTDSTRING_H #define SCRIPTSTDSTRING_H -// String must be included before angelscript.h to avoid some errors during -// compilation with GetObject function -#include - #ifndef ANGELSCRIPT_H // Avoid having to inform include path if header is already include before #include #endif +#include + //--------------------------- // Compilation settings // -// The use of the string pool can improve performance quite drastically -// for scripts that work with a lot of literal string constants. -// -// 1 = on -// 0 = off - -#ifndef AS_USE_STRINGPOOL -#define AS_USE_STRINGPOOL 1 -#endif - // Sometimes it may be desired to use the same method names as used by C++ STL. // This may for example reduce time when converting code from script to C++ or // back. diff --git a/src/scriptengine/scriptstdstring_utils.cpp b/src/scriptengine/scriptstdstring_utils.cpp index d46fea751..ca75d59ba 100644 --- a/src/scriptengine/scriptstdstring_utils.cpp +++ b/src/scriptengine/scriptstdstring_utils.cpp @@ -1,3 +1,33 @@ +/* + AngelCode Scripting Library + Copyright (c) 2003-2017 Andreas Jonsson + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + The original version of this library can be located at: + http://www.angelcode.com/angelscript/ + + Andreas Jonsson + andreas@angelcode.com +*/ + #include #include "scriptstdstring.hpp" #include "scriptarray.hpp" @@ -22,45 +52,45 @@ BEGIN_AS_NAMESPACE // array@ string::split(const string &in delim) const static CScriptArray *StringSplit(const string &delim, const string &str) { - // Obtain a pointer to the engine - asIScriptContext *ctx = asGetActiveContext(); - asIScriptEngine *engine = ctx->GetEngine(); + // Obtain a pointer to the engine + asIScriptContext *ctx = asGetActiveContext(); + asIScriptEngine *engine = ctx->GetEngine(); - // TODO: This should only be done once - // TODO: This assumes that CScriptArray was already registered - asIObjectType *arrayType = engine->GetObjectTypeByDecl("array"); + // TODO: This should only be done once + // TODO: This assumes that CScriptArray was already registered + asITypeInfo *arrayType = engine->GetTypeInfoByDecl("array"); - // Create the array object - CScriptArray *array = CScriptArray::Create(arrayType); + // Create the array object + CScriptArray *array = CScriptArray::Create(arrayType); - // Find the existence of the delimiter in the input string - int pos = 0, prev = 0, count = 0; - while( (pos = (int)str.find(delim, prev)) != (int)string::npos ) - { - // Add the part to the array - array->Resize(array->GetSize()+1); - ((string*)array->At(count))->assign(&str[prev], pos-prev); + // Find the existence of the delimiter in the input string + int pos = 0, prev = 0, count = 0; + while( (pos = (int)str.find(delim, prev)) != (int)string::npos ) + { + // Add the part to the array + array->Resize(array->GetSize()+1); + ((string*)array->At(count))->assign(&str[prev], pos-prev); - // Find the next part - count++; - prev = pos + (int)delim.length(); - } + // Find the next part + count++; + prev = pos + (int)delim.length(); + } - // Add the remaining part - array->Resize(array->GetSize()+1); - ((string*)array->At(count))->assign(&str[prev]); + // Add the remaining part + array->Resize(array->GetSize()+1); + ((string*)array->At(count))->assign(&str[prev]); - return array; + return array; } static void StringSplit_Generic(asIScriptGeneric *gen) { - // Get the arguments - string *str = (string*)gen->GetObject(); - string *delim = *(string**)gen->GetAddressOfArg(0); + // Get the arguments + string *str = (string*)gen->GetObject(); + string *delim = *(string**)gen->GetAddressOfArg(0); - // Return the array by handle - *(CScriptArray**)gen->GetAddressOfReturnLocation() = StringSplit(*delim, *str); + // Return the array by handle + *(CScriptArray**)gen->GetAddressOfReturnLocation() = StringSplit(*delim, *str); } @@ -80,50 +110,50 @@ static void StringSplit_Generic(asIScriptGeneric *gen) // string join(const array &in array, const string &in delim) static string StringJoin(const CScriptArray &array, const string &delim) { - // Create the new string - string str = ""; - if( array.GetSize() ) - { - int n; - for( n = 0; n < (int)array.GetSize() - 1; n++ ) - { - str += *(string*)array.At(n); - str += delim; - } + // Create the new string + string str = ""; + if( array.GetSize() ) + { + int n; + for( n = 0; n < (int)array.GetSize() - 1; n++ ) + { + str += *(string*)array.At(n); + str += delim; + } - // Add the last part - str += *(string*)array.At(n); - } + // Add the last part + str += *(string*)array.At(n); + } - return str; + return str; } static void StringJoin_Generic(asIScriptGeneric *gen) { - // Get the arguments - CScriptArray *array = *(CScriptArray**)gen->GetAddressOfArg(0); - string *delim = *(string**)gen->GetAddressOfArg(1); + // Get the arguments + CScriptArray *array = *(CScriptArray**)gen->GetAddressOfArg(0); + string *delim = *(string**)gen->GetAddressOfArg(1); - // Return the string - new(gen->GetAddressOfReturnLocation()) string(StringJoin(*array, *delim)); + // Return the string + new(gen->GetAddressOfReturnLocation()) string(StringJoin(*array, *delim)); } // This is where the utility functions are registered. // The string type must have been registered first. void RegisterStdStringUtils(asIScriptEngine *engine) { - int r; + int r; - if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) - { - r = engine->RegisterObjectMethod("string", "array@ split(const string &in) const", asFUNCTION(StringSplit_Generic), asCALL_GENERIC); assert(r >= 0); - r = engine->RegisterGlobalFunction("string join(const array &in, const string &in)", asFUNCTION(StringJoin_Generic), asCALL_GENERIC); assert(r >= 0); - } - else - { - r = engine->RegisterObjectMethod("string", "array@ split(const string &in) const", asFUNCTION(StringSplit), asCALL_CDECL_OBJLAST); assert(r >= 0); - r = engine->RegisterGlobalFunction("string join(const array &in, const string &in)", asFUNCTION(StringJoin), asCALL_CDECL); assert(r >= 0); - } + if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) + { + r = engine->RegisterObjectMethod("string", "array@ split(const string &in) const", asFUNCTION(StringSplit_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterGlobalFunction("string join(const array &in, const string &in)", asFUNCTION(StringJoin_Generic), asCALL_GENERIC); assert(r >= 0); + } + else + { + r = engine->RegisterObjectMethod("string", "array@ split(const string &in) const", asFUNCTION(StringSplit), asCALL_CDECL_OBJLAST); assert(r >= 0); + r = engine->RegisterGlobalFunction("string join(const array &in, const string &in)", asFUNCTION(StringJoin), asCALL_CDECL); assert(r >= 0); + } } END_AS_NAMESPACE diff --git a/src/states_screens/options_screen_ui.cpp b/src/states_screens/options_screen_ui.cpp index ee47e2629..eb2479396 100644 --- a/src/states_screens/options_screen_ui.cpp +++ b/src/states_screens/options_screen_ui.cpp @@ -128,6 +128,13 @@ void OptionsScreenUI::init() assert( skinSelector != NULL ); // ---- video modes + CheckBoxWidget* splitscreen_method = getWidget("split_screen_horizontally"); + assert(splitscreen_method != NULL); + splitscreen_method->setState(UserConfigParams::split_screen_horizontally); + + //Forbid changing this setting in game + bool in_game = StateManager::get()->getGameState() == GUIEngine::INGAME_MENU; + splitscreen_method->setActive(!in_game); CheckBoxWidget* fps = getWidget("showfps"); assert( fps != NULL ); @@ -220,6 +227,7 @@ void OptionsScreenUI::init() // Forbid changing language while in-game, since this crashes (changing the language involves // tearing down and rebuilding the menu stack. not good when in-game) list_widget->setActive(StateManager::get()->getGameState() != GUIEngine::INGAME_MENU); + } // init @@ -258,6 +266,13 @@ void OptionsScreenUI::eventCallback(Widget* widget, const std::string& name, con UserConfigParams::m_skin_file = core::stringc(selectedSkin.c_str()).c_str() + std::string(".stkskin"); GUIEngine::reloadSkin(); } + else if (name == "split_screen_horizontally") + { + CheckBoxWidget* split_screen_horizontally = getWidget("split_screen_horizontally"); + assert(split_screen_horizontally != NULL); + UserConfigParams::split_screen_horizontally = split_screen_horizontally->getState(); + + } else if (name == "showfps") { CheckBoxWidget* fps = getWidget("showfps"); diff --git a/src/states_screens/race_gui.cpp b/src/states_screens/race_gui.cpp index 49c6488b5..4334052f7 100644 --- a/src/states_screens/race_gui.cpp +++ b/src/states_screens/race_gui.cpp @@ -121,7 +121,7 @@ RaceGUI::RaceGUI() // special case : when 3 players play, use available 4th space for such things - if (race_manager->getNumLocalPlayers() == 3) + if (race_manager->getIfEmptyScreenSpaceExists()) { m_map_left = irr_driver->getActualScreenSize().Width - m_map_width; } @@ -190,15 +190,13 @@ void RaceGUI::renderGlobal(float dt) // Special case : when 3 players play, use 4th window to display such // stuff (but we must clear it) - if (race_manager->getNumLocalPlayers() == 3 && + if (race_manager->getIfEmptyScreenSpaceExists() && !GUIEngine::ModalDialog::isADialogActive()) { static video::SColor black = video::SColor(255,0,0,0); - GL32_draw2DRectangle(black, - core::rect(irr_driver->getActualScreenSize().Width/2, - irr_driver->getActualScreenSize().Height/2, - irr_driver->getActualScreenSize().Width, - irr_driver->getActualScreenSize().Height)); + + GL32_draw2DRectangle(black, irr_driver->GetSplitscreenWindow( + race_manager->getNumLocalPlayers())); } World *world = World::getWorld(); @@ -255,7 +253,7 @@ void RaceGUI::renderPlayerView(const Camera *camera, float dt) drawPlungerInFace(camera, dt); - scaling *= viewport.getWidth()/800.0f; // scale race GUI along screen size + scaling *= float(viewport.getWidth()) / float(irr_driver->getActualScreenSize().Width); // scale race GUI along screen size drawAllMessages(kart, viewport, scaling); if(!World::getWorld()->isRacePhase()) return; @@ -368,9 +366,10 @@ void RaceGUI::drawGlobalTimer() irr_driver->getActualScreenSize().Width , 50); // special case : when 3 players play, use available 4th space for such things - if (race_manager->getNumLocalPlayers() == 3) + if (race_manager->getIfEmptyScreenSpaceExists()) { - pos += core::vector2d(0, irr_driver->getActualScreenSize().Height/2); + pos -= core::vector2d(0, pos.LowerRightCorner.Y / 2); + pos += core::vector2d(0, irr_driver->getActualScreenSize().Height - irr_driver->GetSplitscreenWindow(0).getHeight()); } gui::ScalableFont* font = (use_digit_font ? GUIEngine::getHighresDigitFont() : GUIEngine::getFont()); @@ -888,14 +887,20 @@ void RaceGUI::drawLap(const AbstractKart* kart, if (lap < 0 ) return; core::recti pos; - pos.UpperLeftCorner.Y = viewport.UpperLeftCorner.Y + m_font_height; + // If the time display in the top right is in this viewport, // move the lap/rank display down a little bit so that it is // displayed under the time. - if (viewport.UpperLeftCorner.Y==0 && - viewport.LowerRightCorner.X==(int)(irr_driver->getActualScreenSize().Width) && - race_manager->getNumPlayers()!=3) - pos.UpperLeftCorner.Y += m_font_height; + if (viewport.UpperLeftCorner.Y == 0 && + viewport.LowerRightCorner.X == (int)(irr_driver->getActualScreenSize().Width) && + !race_manager->getIfEmptyScreenSpaceExists()) + { + pos.UpperLeftCorner.Y += m_font_height; + } + else + { + pos.UpperLeftCorner.Y = viewport.UpperLeftCorner.Y + m_font_height; + } pos.LowerRightCorner.Y = viewport.LowerRightCorner.Y+20; pos.UpperLeftCorner.X = viewport.LowerRightCorner.X - m_lap_width - 10; diff --git a/src/states_screens/race_gui_base.cpp b/src/states_screens/race_gui_base.cpp index 4dd278a89..e9ae58f80 100644 --- a/src/states_screens/race_gui_base.cpp +++ b/src/states_screens/race_gui_base.cpp @@ -206,9 +206,9 @@ void RaceGUIBase::drawAllMessages(const AbstractKart* kart, const core::vector2df &scaling) { int y = viewport.LowerRightCorner.Y - m_small_font_max_height - 10; - - const int x = (viewport.LowerRightCorner.X + viewport.UpperLeftCorner.X)/2; - const int w = (viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X); + + const int x = viewport.getCenter().X; + const int w = viewport.getWidth(); // Draw less important messages first, at the very bottom of the screen // unimportant messages are skipped in multiplayer, they take too much screen space @@ -244,7 +244,7 @@ void RaceGUIBase::drawAllMessages(const AbstractKart* kart, } // First line of text somewhat under the top of the viewport. - y = (int)(viewport.UpperLeftCorner.Y + 164*scaling.Y); + y = (int)(viewport.UpperLeftCorner.Y + 20); gui::ScalableFont* font = GUIEngine::getFont(); gui::ScalableFont* big_font = GUIEngine::getTitleFont(); @@ -665,10 +665,11 @@ void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin) int y_base = 20; unsigned int y_space = irr_driver->getActualScreenSize().Height - bottom_margin - y_base; // Special case : when 3 players play, use 4th window to display such stuff - if (race_manager->getNumLocalPlayers() == 3) + if (race_manager->getIfEmptyScreenSpaceExists()) { - x_base = irr_driver->getActualScreenSize().Width/2 + x_base; - y_base = irr_driver->getActualScreenSize().Height/2 + y_base; + irr::core::recti Last_Space = irr_driver->GetSplitscreenWindow(race_manager->getNumLocalPlayers()); + x_base = Last_Space.UpperLeftCorner.X; + y_base = Last_Space.UpperLeftCorner.Y; y_space = irr_driver->getActualScreenSize().Height - y_base; } @@ -729,7 +730,7 @@ void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin) //where is the limit to hide last icons int y_icons_limit = irr_driver->getActualScreenSize().Height - bottom_margin - ICON_PLAYER_WIDTH; - if (race_manager->getNumLocalPlayers() == 3) + if (race_manager->getIfEmptyScreenSpaceExists()) { y_icons_limit = irr_driver->getActualScreenSize().Height - ICON_WIDTH; } diff --git a/src/states_screens/race_gui_overworld.cpp b/src/states_screens/race_gui_overworld.cpp index 625a3eec7..1c236802e 100644 --- a/src/states_screens/race_gui_overworld.cpp +++ b/src/states_screens/race_gui_overworld.cpp @@ -122,7 +122,7 @@ RaceGUIOverworld::RaceGUIOverworld() // special case : when 3 players play, use available 4th space for such things - if (race_manager->getNumLocalPlayers() == 3) + if (race_manager->getIfEmptyScreenSpaceExists()) { m_map_left = irr_driver->getActualScreenSize().Width - m_map_width; } @@ -179,15 +179,15 @@ void RaceGUIOverworld::renderGlobal(float dt) // Special case : when 3 players play, use 4th window to display such // stuff (but we must clear it) - if (race_manager->getNumLocalPlayers() == 3 && + if (race_manager->getIfEmptyScreenSpaceExists() && !GUIEngine::ModalDialog::isADialogActive()) { + const float Sqrt = sqrt(race_manager->getNumLocalPlayers()); + const int rows = ceil(Sqrt); + const int cols = round(Sqrt); static video::SColor black = video::SColor(255,0,0,0); - GL32_draw2DRectangle(black, - core::rect(irr_driver->getActualScreenSize().Width/2, - irr_driver->getActualScreenSize().Height/2, - irr_driver->getActualScreenSize().Width, - irr_driver->getActualScreenSize().Height)); + GL32_draw2DRectangle(black, irr_driver->GetSplitscreenWindow( + race_manager->getNumLocalPlayers())); } World *world = World::getWorld(); diff --git a/src/tracks/graph.cpp b/src/tracks/graph.cpp index a566bbd8c..5ef0876dc 100644 --- a/src/tracks/graph.cpp +++ b/src/tracks/graph.cpp @@ -350,7 +350,7 @@ void Graph::createMeshSP(bool show_invisible, bool enable_transparency, spmb->recalculateBoundingBox(); std::string shader_name = enable_transparency ? "alphablend" : "unlit"; #ifndef SERVER_ONLY - if (!CVS->isDefferedEnabled()) + if (!CVS->isDeferredEnabled()) { shader_name = "solid"; } diff --git a/src/tracks/track_object.cpp b/src/tracks/track_object.cpp index 15445e09a..650fe4521 100644 --- a/src/tracks/track_object.cpp +++ b/src/tracks/track_object.cpp @@ -349,6 +349,16 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent, } } + bool is_in_shadowpass = true; + if (xml_node.get("shadow-pass", &is_in_shadowpass) && glownode) + { + SP::SPMeshNode* spmn = dynamic_cast(glownode); + if (spmn) + { + spmn->setInShadowPass(is_in_shadowpass); + } + } + bool forcedbloom = false; if (xml_node.get("forcedbloom", &forcedbloom) && forcedbloom && glownode) { diff --git a/src/utils/constants.hpp b/src/utils/constants.hpp index 58d58a961..e433430c6 100644 --- a/src/utils/constants.hpp +++ b/src/utils/constants.hpp @@ -47,7 +47,7 @@ #define DEGREE_TO_RAD (M_PI/180.0f) #define RAD_TO_DEGREE (180.0f/M_PI) -const unsigned int MAX_PLAYER_COUNT = 4; +const unsigned int MAX_PLAYER_COUNT = 8; extern const bool IS_LITTLE_ENDIAN; diff --git a/src/utils/debug.cpp b/src/utils/debug.cpp index bf68128d4..8dd406204 100644 --- a/src/utils/debug.cpp +++ b/src/utils/debug.cpp @@ -31,7 +31,9 @@ #include "graphics/shader.hpp" #include "graphics/sp/sp_base.hpp" #include "graphics/sp/sp_shader_manager.hpp" +#include "graphics/sp/sp_shader.hpp" #include "graphics/sp/sp_texture_manager.hpp" +#include "graphics/sp/sp_uniform_assigner.hpp" #include "guiengine/widgets/label_widget.hpp" #include "guiengine/widgets/text_box_widget.hpp" #include "items/powerup_manager.hpp" @@ -76,24 +78,23 @@ enum DebugMenuCommand //! graphics commands DEBUG_GRAPHICS_RELOAD_SHADERS, DEBUG_GRAPHICS_RESET, - DEBUG_GRAPHICS_WIREFRAME, - DEBUG_GRAPHICS_MIPMAP_VIZ, - DEBUG_GRAPHICS_NORMALS_VIZ, DEBUG_GRAPHICS_SSAO_VIZ, - DEBUG_GRAPHICS_RSM_VIZ, - DEBUG_GRAPHICS_RH_VIZ, - DEBUG_GRAPHICS_GI_VIZ, DEBUG_GRAPHICS_SHADOW_VIZ, - DEBUG_GRAPHICS_LIGHT_VIZ, - DEBUG_GRAPHICS_DISTORT_VIZ, + DEBUG_GRAPHICS_BOUNDING_BOXES_VIZ, DEBUG_GRAPHICS_BULLET_1, DEBUG_GRAPHICS_BULLET_2, - DEBUG_GRAPHICS_BOUNDING_BOXES_VIZ, - DEBUG_GRAPHICS_TOGGLE_CULLING, DEBUG_PROFILER, DEBUG_PROFILER_WRITE_REPORT, DEBUG_FONT_DUMP_GLYPH_PAGE, DEBUG_FONT_RELOAD, + DEBUG_SP_RESET, + DEBUG_SP_TOGGLE_CULLING, + DEBUG_SP_WN_VIZ, + DEBUG_SP_NORMALS_VIZ, + DEBUG_SP_TANGENTS_VIZ, + DEBUG_SP_BITANGENTS_VIZ, + DEBUG_SP_WIREFRAME_VIZ, + DEBUG_SP_TN_VIZ, DEBUG_FPS, DEBUG_SAVE_REPLAY, DEBUG_SAVE_HISTORY, @@ -244,6 +245,14 @@ bool handleContextMenuAction(s32 cmd_id) World *world = World::getWorld(); Physics *physics = Physics::getInstance(); + SP::SPShader* nv = NULL; +#ifndef SERVER_ONLY + if (SP::getNormalVisualizer()) + { + nv = SP::getNormalVisualizer(); + } +#endif + switch(cmd_id) { case DEBUG_GRAPHICS_RELOAD_SHADERS: @@ -261,27 +270,6 @@ bool handleContextMenuAction(s32 cmd_id) irr_driver->resetDebugModes(); break; - case DEBUG_GRAPHICS_WIREFRAME: - if (physics) - physics->setDebugMode(IrrDebugDrawer::DM_NONE); - - irr_driver->resetDebugModes(); - irr_driver->toggleWireframe(); - break; - case DEBUG_GRAPHICS_MIPMAP_VIZ: - if (physics) - physics->setDebugMode(IrrDebugDrawer::DM_NONE); - - irr_driver->resetDebugModes(); - irr_driver->toggleMipVisualization(); - break; - case DEBUG_GRAPHICS_NORMALS_VIZ: - if (physics) - physics->setDebugMode(IrrDebugDrawer::DM_NONE); - - irr_driver->resetDebugModes(); - irr_driver->toggleNormals(); - break; case DEBUG_GRAPHICS_SSAO_VIZ: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); @@ -289,27 +277,6 @@ bool handleContextMenuAction(s32 cmd_id) irr_driver->resetDebugModes(); irr_driver->toggleSSAOViz(); break; - case DEBUG_GRAPHICS_RSM_VIZ: - if (physics) - physics->setDebugMode(IrrDebugDrawer::DM_NONE); - - irr_driver->resetDebugModes(); - irr_driver->toggleRSM(); - break; - case DEBUG_GRAPHICS_RH_VIZ: - if (physics) - physics->setDebugMode(IrrDebugDrawer::DM_NONE); - - irr_driver->resetDebugModes(); - irr_driver->toggleRH(); - break; - case DEBUG_GRAPHICS_GI_VIZ: - if (physics) - physics->setDebugMode(IrrDebugDrawer::DM_NONE); - - irr_driver->resetDebugModes(); - irr_driver->toggleGI(); - break; case DEBUG_GRAPHICS_SHADOW_VIZ: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); @@ -317,19 +284,12 @@ bool handleContextMenuAction(s32 cmd_id) irr_driver->resetDebugModes(); irr_driver->toggleShadowViz(); break; - case DEBUG_GRAPHICS_LIGHT_VIZ: + case DEBUG_GRAPHICS_BOUNDING_BOXES_VIZ: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); irr_driver->resetDebugModes(); - irr_driver->toggleLightViz(); - break; - case DEBUG_GRAPHICS_DISTORT_VIZ: - if (physics) - physics->setDebugMode(IrrDebugDrawer::DM_NONE); - - irr_driver->resetDebugModes(); - irr_driver->toggleDistortViz(); + irr_driver->toggleBoundingBoxesViz(); break; case DEBUG_GRAPHICS_BULLET_1: irr_driver->resetDebugModes(); @@ -346,15 +306,142 @@ bool handleContextMenuAction(s32 cmd_id) physics->setDebugMode(IrrDebugDrawer::DM_NO_KARTS_GRAPHICS); break; } - case DEBUG_GRAPHICS_BOUNDING_BOXES_VIZ: + case DEBUG_SP_RESET: irr_driver->resetDebugModes(); - irr_driver->toggleBoundingBoxesViz(); + if (physics) + physics->setDebugMode(IrrDebugDrawer::DM_NONE); +#ifndef SERVER_ONLY + SP::sp_culling = true; +#endif break; - case DEBUG_GRAPHICS_TOGGLE_CULLING: + case DEBUG_SP_TOGGLE_CULLING: #ifndef SERVER_ONLY SP::sp_culling = !SP::sp_culling; #endif break; + case DEBUG_SP_WN_VIZ: + irr_driver->resetDebugModes(); + if (physics) + physics->setDebugMode(IrrDebugDrawer::DM_NONE); +#ifndef SERVER_ONLY + SP::sp_debug_view = true; +#endif + break; + case DEBUG_SP_NORMALS_VIZ: + { + irr_driver->resetDebugModes(); + if (physics) + physics->setDebugMode(IrrDebugDrawer::DM_NONE); +#ifndef SERVER_ONLY + SP::sp_debug_view = true; + int normal = 0; + if (nv) + { + SP::SPUniformAssigner* ua = nv->getUniformAssigner("enable_normals"); + if (ua) + { + ua->getValue(nv->getShaderProgram(SP::RP_1ST), normal); + normal = normal == 0 ? 1 : 0; + nv->use(); + ua->setValue(normal); + glUseProgram(0); + } + } +#endif + break; + } + case DEBUG_SP_TANGENTS_VIZ: + { + irr_driver->resetDebugModes(); + if (physics) + physics->setDebugMode(IrrDebugDrawer::DM_NONE); +#ifndef SERVER_ONLY + SP::sp_debug_view = true; + int tangents = 0; + if (nv) + { + SP::SPUniformAssigner* ua = nv->getUniformAssigner("enable_tangents"); + if (ua) + { + ua->getValue(nv->getShaderProgram(SP::RP_1ST), tangents); + tangents = tangents == 0 ? 1 : 0; + nv->use(); + ua->setValue(tangents); + glUseProgram(0); + } + } +#endif + break; + } + case DEBUG_SP_BITANGENTS_VIZ: + { + irr_driver->resetDebugModes(); + if (physics) + physics->setDebugMode(IrrDebugDrawer::DM_NONE); +#ifndef SERVER_ONLY + SP::sp_debug_view = true; + int bitangents = 0; + if (nv) + { + SP::SPUniformAssigner* ua = nv->getUniformAssigner("enable_bitangents"); + if (ua) + { + ua->getValue(nv->getShaderProgram(SP::RP_1ST), bitangents); + bitangents = bitangents == 0 ? 1 : 0; + nv->use(); + ua->setValue(bitangents); + glUseProgram(0); + } + } +#endif + break; + } + case DEBUG_SP_WIREFRAME_VIZ: + { + irr_driver->resetDebugModes(); + if (physics) + physics->setDebugMode(IrrDebugDrawer::DM_NONE); +#ifndef SERVER_ONLY + SP::sp_debug_view = true; + int wireframe = 0; + if (nv) + { + SP::SPUniformAssigner* ua = nv->getUniformAssigner("enable_wireframe"); + if (ua) + { + ua->getValue(nv->getShaderProgram(SP::RP_1ST), wireframe); + wireframe = wireframe == 0 ? 1 : 0; + nv->use(); + ua->setValue(wireframe); + glUseProgram(0); + } + } +#endif + break; + } + case DEBUG_SP_TN_VIZ: + { + irr_driver->resetDebugModes(); + if (physics) + physics->setDebugMode(IrrDebugDrawer::DM_NONE); +#ifndef SERVER_ONLY + SP::sp_debug_view = true; + int triangle_normals = 0; + if (nv) + { + SP::SPUniformAssigner* ua = nv->getUniformAssigner("enable_triangle_normals"); + if (ua) + { + ua->getValue(nv->getShaderProgram(SP::RP_1ST), triangle_normals); + triangle_normals = triangle_normals == 0 ? 1 : 0; + nv->use(); + ua->setValue(triangle_normals); + glUseProgram(0); + } + } +#endif + break; + } case DEBUG_PROFILER: profiler.toggleStatus(); break; @@ -756,22 +843,13 @@ bool onEvent(const SEvent &event) // graphics menu IGUIContextMenu* sub = mnu->getSubMenu(graphicsMenuIndex); - sub->addItem(L"Reload shaders", DEBUG_GRAPHICS_RELOAD_SHADERS ); - sub->addItem(L"Wireframe", DEBUG_GRAPHICS_WIREFRAME ); - sub->addItem(L"Mipmap viz", DEBUG_GRAPHICS_MIPMAP_VIZ ); - sub->addItem(L"Normals viz", DEBUG_GRAPHICS_NORMALS_VIZ ); - sub->addItem(L"SSAO viz", DEBUG_GRAPHICS_SSAO_VIZ ); - sub->addItem(L"RSM viz", DEBUG_GRAPHICS_RSM_VIZ); - sub->addItem(L"RH viz", DEBUG_GRAPHICS_RH_VIZ); - sub->addItem(L"GI viz", DEBUG_GRAPHICS_GI_VIZ); - sub->addItem(L"Shadow viz", DEBUG_GRAPHICS_SHADOW_VIZ ); - sub->addItem(L"Light viz", DEBUG_GRAPHICS_LIGHT_VIZ ); - sub->addItem(L"Distort viz", DEBUG_GRAPHICS_DISTORT_VIZ ); + sub->addItem(L"Reload shaders", DEBUG_GRAPHICS_RELOAD_SHADERS); + sub->addItem(L"SSAO viz", DEBUG_GRAPHICS_SSAO_VIZ); + sub->addItem(L"Shadow viz", DEBUG_GRAPHICS_SHADOW_VIZ); + sub->addItem(L"Bounding Boxes viz", DEBUG_GRAPHICS_BOUNDING_BOXES_VIZ); sub->addItem(L"Physics debug", DEBUG_GRAPHICS_BULLET_1); sub->addItem(L"Physics debug (no kart)", DEBUG_GRAPHICS_BULLET_2); - sub->addItem(L"Bounding Boxes viz", DEBUG_GRAPHICS_BOUNDING_BOXES_VIZ); - sub->addItem(L"Toggle Culling", DEBUG_GRAPHICS_TOGGLE_CULLING); - sub->addItem(L"Reset debug views", DEBUG_GRAPHICS_RESET ); + sub->addItem(L"Reset debug views", DEBUG_GRAPHICS_RESET); mnu->addItem(L"Items >",-1,true,true); sub = mnu->getSubMenu(1); @@ -827,6 +905,17 @@ bool onEvent(const SEvent &event) sub->addItem(L"Dump glyph pages of fonts", DEBUG_FONT_DUMP_GLYPH_PAGE); sub->addItem(L"Reload all fonts", DEBUG_FONT_RELOAD); + mnu->addItem(L"SP debug >",-1,true, true); + sub = mnu->getSubMenu(7); + sub->addItem(L"Reset SP debug", DEBUG_SP_RESET); + sub->addItem(L"Toggle culling", DEBUG_SP_TOGGLE_CULLING); + sub->addItem(L"Draw world normal in texture", DEBUG_SP_WN_VIZ); + sub->addItem(L"Toggle normals visualization", DEBUG_SP_NORMALS_VIZ); + sub->addItem(L"Toggle tangents visualization", DEBUG_SP_TANGENTS_VIZ); + sub->addItem(L"Toggle bitangents visualization", DEBUG_SP_BITANGENTS_VIZ); + sub->addItem(L"Toggle wireframe visualization", DEBUG_SP_WIREFRAME_VIZ); + sub->addItem(L"Toggle triangle normals visualization", DEBUG_SP_TN_VIZ); + mnu->addItem(L"Adjust values", DEBUG_VISUAL_VALUES); mnu->addItem(L"Profiler", DEBUG_PROFILER); diff --git a/src/utils/log.cpp b/src/utils/log.cpp index b349bb9e7..8a84db47b 100644 --- a/src/utils/log.cpp +++ b/src/utils/log.cpp @@ -189,8 +189,9 @@ void Log::writeLine(const char *line, int level) { // If we don't have a console file, write to stdout and hope for the best - if (!m_file_stdout || level >= LL_WARN || - UserConfigParams::m_log_errors_to_console) // log to console & file + if ( m_buffer_size <= 1 && + (!m_file_stdout || level >= LL_WARN || + UserConfigParams::m_log_errors_to_console) ) // log to console { setTerminalColor((LogLevel)level); #ifdef ANDROID @@ -218,7 +219,7 @@ void Log::writeLine(const char *line, int level) } #if defined(_MSC_FULL_VER) && defined(_DEBUG) - OutputDebugString(line); + if (m_buffer_size <= 1) OutputDebugString(line); #endif if (m_file_stdout) fprintf(m_file_stdout, "%s", line); diff --git a/src/utils/profiler.cpp b/src/utils/profiler.cpp index 00d6951ba..dbec2b986 100644 --- a/src/utils/profiler.cpp +++ b/src/utils/profiler.cpp @@ -41,22 +41,17 @@ static const char* GPU_Phase[Q_LAST] = "Shadows Cascade 1", "Shadows Cascade 2", "Shadows Cascade 3", - "Shadows Postprocess", - "Solid Pass 1", - "RSM", - "RH", - "GI", + "Solid Pass", "Env Map", "SunLight", "PointLights", "SSAO", - "Solid Pass 2", - "Fog", - "Skybox", + "Light Scatter", "Glow", + "Combine Diffuse Color", + "Skybox", "Transparent", "Particles", - "Displacement", "Depth of Field", "Godrays", "Bloom", diff --git a/src/utils/profiler.hpp b/src/utils/profiler.hpp index 8eabe312c..38bfbf37b 100644 --- a/src/utils/profiler.hpp +++ b/src/utils/profiler.hpp @@ -39,22 +39,17 @@ enum QueryPerf Q_SHADOWS_CASCADE1, Q_SHADOWS_CASCADE2, Q_SHADOWS_CASCADE3, - Q_SHADOW_POSTPROCESS, - Q_SOLID_PASS1, - Q_RSM, - Q_RH, - Q_GI, + Q_SOLID_PASS, Q_ENVMAP, Q_SUN, Q_POINTLIGHTS, Q_SSAO, - Q_SOLID_PASS2, - Q_FOG, - Q_SKYBOX, + Q_LIGHTSCATTER, Q_GLOW, + Q_COMBINE_DIFFUSE_COLOR, + Q_SKYBOX, Q_TRANSPARENT, Q_PARTICLES, - Q_DISPLACEMENT, Q_DOF, Q_GODRAYS, Q_BLOOM,