[SCM] GNU Shockwave Flash (SWF) player branch, upstream, updated. upstream/0.8.11_git20120629-2-g0af75cb
Gabriele Giacone
gg0-guest at alioth.debian.org
Tue Sep 3 21:27:50 UTC 2013
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Shockwave Flash (SWF) player".
The branch, upstream has been updated
via 0af75cb171859bfaea434f84e5641f4b9f09a99b (commit)
via a2556ad91722976a282bf5a4aaf4dcbb560dfb02 (commit)
from 8642e06630dfcb7775374b49fd9ea149bf8b269d (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
-----------------------------------------------------------------------
Summary of changes:
Makefile.am | 21 +-
NEWS | 8 +
configure.ac | 248 +-
cygnal/Makefile.am | 9 +-
cygnal/cgi-bin/oflaDemo/oflaDemo.cpp | 2 +-
cygnal/handler.cpp | 2 +-
cygnal/libamf/sol.cpp | 64 +-
cygnal/libnet/diskstream.cpp | 4 +-
cygnal/libnet/network.cpp | 4 +-
cygnal/libnet/rtmp_msg.cpp | 2 +-
cygnal/proc.cpp | 10 +-
doc/C/Makefile.am | 10 +-
doc/C/refmanual/feature_configuration.xml | 80 +-
extensions/fileio/fileio.cpp | 2 +-
gui/Makefile.am | 15 +-
gui/Player.cpp | 7 +-
gui/Player.h | 19 +-
gui/dump/dump.am | 1 +
gui/dump/dump.cpp | 1 +
gui/dump/dump.h | 7 +-
gui/fb/fb.am | 19 +-
gui/fb/fb.cpp | 64 +-
gui/fb/fb_glue_agg.cpp | 6 +-
gui/fb/fb_glue_gles1.cpp | 36 +-
gui/fb/fb_glue_gles1.h | 14 +
gui/fb/fb_glue_ovg.cpp | 10 +-
gui/fb/fbsup.h | 2 +
gui/gnash.cpp | 5 +-
gui/gtk/gtk.am | 5 +-
gui/gtk/gtk.cpp | 8 +-
gui/gtk/gtk_canvas.h | 3 +-
gui/gui.cpp | 13 +-
gui/gui.h | 9 +-
gui/pythonmod/gnash-view.cpp | 1 +
gui/qt/Qt4Gui.cpp | 5 +-
gui/qt/Qt4Gui.h | 3 +
gui/qt/qt4.am | 1 +
gui/sdl/sdl.am | 5 +-
gui/sdl/sdl_agg_glue.cpp | 13 +-
libbase/BitsReader.h | 2 +-
libbase/GnashImage.cpp | 25 +-
libbase/GnashImageGif.cpp | 10 +
libbase/GnashImageJpeg.cpp | 5 +-
libbase/GnashNumeric.h | 23 +-
libbase/GnashScopedPtr.h | 85 +
libbase/IOChannel.cpp | 2 +-
libbase/IOChannel.h | 1 -
libbase/Makefile.am | 29 +-
libbase/RTMP.cpp | 2 -
libbase/Range2d.h | 2 +-
libbase/SharedMem.cpp | 116 +-
libbase/SharedMem.h | 4 +
libbase/Socket.cpp | 182 +-
libbase/Socket.h | 7 -
libbase/URL.cpp | 1 -
libbase/URLAccessManager.cpp | 7 +-
libbase/dsodefs.h | 6 +
libbase/extension.cpp | 6 +-
libbase/jemalloc.c | 6577 --------------------
libbase/jemalloc.h | 76 -
libbase/jemalloc_gnash.c | 66 +
libbase/jemalloc_gnash.h | 105 -
libbase/jemalloc_rb.h | 982 ---
libbase/jemalloc_types.h | 84 -
libbase/log.cpp | 52 +-
libbase/log.h | 7 +-
libbase/rc.cpp | 5 +-
libbase/sharedlib.cpp | 2 +-
libbase/utf8.cpp | 4 +-
libbase/utf8.h | 11 +
libbase/zlib_adapter.cpp | 2 -
libcore/Bitmap.cpp | 4 +-
libcore/Bitmap.h | 2 +-
libcore/Button.cpp | 5 +-
libcore/Button.h | 3 +-
libcore/ClassHierarchy.h | 1 -
libcore/DisplayList.h | 15 +-
libcore/DisplayObject.cpp | 15 +-
libcore/DisplayObject.h | 2 +-
libcore/DynamicShape.cpp | 47 +-
libcore/DynamicShape.h | 8 +-
libcore/ExternalInterface.h | 1 -
libcore/FreetypeGlyphsProvider.cpp | 12 +-
libcore/Geometry.cpp | 11 -
libcore/Geometry.h | 32 +-
libcore/InteractiveObject.h | 6 +-
libcore/LoadVariablesThread.cpp | 1 +
libcore/LoadVariablesThread.h | 6 +-
libcore/Makefile.am | 14 +-
libcore/MorphShape.cpp | 3 +-
libcore/MovieClip.h | 3 +-
libcore/MovieLoader.h | 1 -
libcore/Property.h | 3 +-
libcore/PropertyList.h | 11 +-
libcore/RGBA.h | 7 +-
libcore/Relay.h | 5 +-
libcore/SWFMatrix.cpp | 29 +-
libcore/SWFMatrix.h | 2 +-
libcore/SWFMovie.h | 9 +-
libcore/SWFStream.cpp | 6 +-
libcore/TextField.cpp | 2 +
libcore/TextField.h | 14 +-
libcore/Timers.h | 1 -
libcore/as_environment.h | 5 +-
libcore/as_object.h | 15 +-
libcore/as_value.h | 29 +-
libcore/asobj/Array_as.cpp | 108 +-
libcore/asobj/AsBroadcaster.cpp | 2 +-
libcore/asobj/Global_as.h | 3 +-
libcore/asobj/MovieClipLoader.h | 2 +-
libcore/asobj/NetStream_as.cpp | 75 +-
libcore/asobj/NetStream_as.h | 18 +-
libcore/asobj/Sound_as.cpp | 43 +-
libcore/asobj/String_as.cpp | 6 +-
libcore/asobj/System_as.h | 4 -
libcore/asobj/TextFormat_as.cpp | 105 +-
libcore/asobj/TextFormat_as.h | 6 +-
libcore/asobj/TextSnapshot_as.cpp | 4 +-
libcore/asobj/XMLNode_as.cpp | 14 +-
libcore/asobj/XML_as.cpp | 1 -
libcore/asobj/flash/display/BitmapData_as.cpp | 4 +
.../asobj/flash/external/ExternalInterface_as.cpp | 4 +-
libcore/event_id.h | 2 +-
libcore/movie_root.cpp | 8 +-
libcore/movie_root.h | 4 +-
libcore/parser/Makefile.am | 5 +-
libcore/parser/SWFMovieDefinition.h | 38 +-
libcore/parser/action_buffer.cpp | 2 +-
libcore/parser/action_buffer.h | 4 +-
libcore/swf/DefineBitsTag.cpp | 3 +-
libcore/swf/DefineFontAlignZonesTag.cpp | 2 -
libcore/swf/DefineFontAlignZonesTag.h | 7 +-
libcore/swf/DefineFontTag.cpp | 2 +-
libcore/swf/DefineMorphShapeTag.cpp | 21 +-
libcore/swf/DefineShapeTag.cpp | 2 +-
libcore/swf/DefinitionTag.h | 3 +-
libcore/swf/PlaceObject2Tag.cpp | 8 +
libcore/swf/ShapeRecord.cpp | 288 +-
libcore/swf/ShapeRecord.h | 138 +-
libcore/swf/SoundInfoRecord.h | 2 +-
libcore/swf/SoundStreamHeadTag.cpp | 3 +
libcore/swf/StartSoundTag.cpp | 2 +
libcore/swf/StartSoundTag.h | 1 -
libcore/swf/StreamSoundBlockTag.cpp | 2 +
libcore/swf/VideoFrameTag.h | 9 +-
libcore/swf/tag_loaders.cpp | 2 +
libcore/vm/ASHandlers.cpp | 25 +-
libcore/vm/ASHandlers.h | 1 -
libcore/vm/Makefile.am | 5 +-
libcore/vm/VM.cpp | 9 +-
libcore/vm/VM.h | 25 +-
libcore/vm/fn_call.h | 1 +
libdevice/Makefile.am | 18 +-
libdevice/directfb/DirectFBDevice.cpp | 2 +-
libdevice/directfb/directfb.am | 12 +-
libdevice/egl/egl.am | 17 -
libdevice/egl/eglDevice.cpp | 4 +
libdevice/events/EventDevice.cpp | 2 +-
libdevice/events/InputDevice.h | 2 +
libdevice/events/events.am | 14 +-
libdevice/rawfb/RawFBDevice.cpp | 41 +-
libdevice/rawfb/RawFBDevice.h | 3 +-
libdevice/rawfb/rawfb.am | 14 -
libdevice/vaapi/VaapiImage.cpp | 4 +-
libdevice/vaapi/VaapiSubpicture.cpp | 2 +-
libdevice/vaapi/VaapiSurface.cpp | 2 +-
libdevice/vaapi/VaapiSurfaceGLX.cpp | 6 +-
libdevice/vaapi/VaapiSurfaceProxy.cpp | 4 +-
libdevice/vaapi/vaapi.am | 10 -
libmedia/FLVParser.cpp | 2 +-
libmedia/FLVParser.h | 2 -
libmedia/Makefile.am | 8 +-
libmedia/MediaHandler.h | 3 +-
libmedia/MediaParser.cpp | 4 +-
libmedia/MediaParser.h | 3 +
libmedia/SoundInfo.h | 3 -
libmedia/ffmpeg/AudioDecoderFfmpeg.cpp | 166 +-
libmedia/ffmpeg/AudioResamplerFfmpeg.cpp | 90 +-
libmedia/ffmpeg/AudioResamplerFfmpeg.h | 22 +-
libmedia/ffmpeg/MediaHandlerFfmpeg.cpp | 2 +-
libmedia/ffmpeg/MediaParserFfmpeg.cpp | 52 +-
libmedia/ffmpeg/MediaParserFfmpeg.h | 10 +-
libmedia/ffmpeg/VideoConverterFfmpeg.cpp | 3 +-
libmedia/ffmpeg/VideoDecoderFfmpeg.cpp | 47 +-
libmedia/ffmpeg/VideoDecoderFfmpeg.h | 5 +-
libmedia/ffmpeg/VideoDecoderFfmpegVaapi.cpp | 6 +-
libmedia/ffmpeg/VideoDecoderFfmpegVaapi.h | 10 +-
libmedia/ffmpeg/ffmpegHeaders.h | 64 +
libmedia/gst/AudioInputGst.cpp | 2 +
libmedia/gst/GlibDeprecated.h | 30 +
libmedia/gst/MediaParserGst.cpp | 46 +-
libmedia/gst/MediaParserGst.h | 4 -
libmedia/gst/VideoDecoderGst.cpp | 2 +-
libmedia/gst/VideoInputGst.cpp | 7 +-
libmedia/gst/swfdec_codec_gst.c | 8 +-
librender/GnashTexture.cpp | 20 +-
librender/Makefile.am | 10 +-
librender/agg/Renderer_agg.cpp | 110 +-
librender/agg/Renderer_agg.h | 11 +-
librender/agg/Renderer_agg_style.h | 4 +-
librender/cairo/Renderer_cairo.cpp | 70 +-
librender/opengl/Renderer_ogl.cpp | 94 +-
libsound/EmbedSound.cpp | 2 +-
libsound/EmbedSound.h | 3 +-
libsound/EmbedSoundInst.h | 6 +-
libsound/LiveSound.h | 2 +-
libsound/Makefile.am | 5 +-
libsound/StreamingSound.h | 3 -
libsound/StreamingSoundData.h | 4 +-
libsound/sdl/sound_handler_sdl.h | 1 -
libsound/sound_handler.cpp | 1 +
libsound/sound_handler.h | 4 +-
macros/boost.m4 | 49 +-
macros/ffmpeg.m4 | 139 +-
macros/gnashpkgtool.m4 | 16 +-
macros/haxe.m4 | 2 +-
macros/openvg.m4 | 6 +-
macros/python.m4 | 2 +-
macros/qt4.m4 | 2 +-
missing | 454 +-
packaging/debian/control | 4 +-
packaging/redhat/gnash.spec | 1 +
plugin/klash/klash_part.cpp | 3 +-
plugin/klash4/klash_part.cpp | 3 +-
plugin/klash4/klash_part.h | 2 +-
plugin/npapi/Makefile.am | 2 +-
plugin/npapi/mozilla-sdk/npn_gate.cpp | 4 +-
plugin/npapi/plugin.cpp | 31 +-
plugin/npapi/plugin.h | 2 +-
plugin/npapi/pluginScriptObject.cpp | 4 +-
revno.h | 4 +-
testsuite/FuzzyPixel.h | 1 +
testsuite/Makefile.am | 22 +-
testsuite/MovieTester.cpp | 19 +-
testsuite/MovieTester.h | 2 +-
testsuite/XmlSocketServer.pl | 10 +-
testsuite/actionscript.all/BitmapData.as | 35 +-
testsuite/actionscript.all/Makefile.am | 1 +
testsuite/actionscript.all/NetStream.as | 81 +-
testsuite/actionscript.all/Sound.as | 20 +-
testsuite/actionscript.all/TextFormat.as | 137 +-
testsuite/actionscript.all/XMLNode.as | 8 +
testsuite/actionscript.all/array.as | 36 +-
testsuite/libbase.all/CurlStreamTest.cpp | 2 +-
testsuite/libbase.all/Makefile.am | 23 +-
testsuite/libbase.all/memtest.cpp | 4 +-
testsuite/libcore.all/ClassSizes.cpp | 1 +
testsuite/libcore.all/Makefile.am | 52 +-
.../{libbase.all => libdevice.all}/Makefile.am | 118 +-
.../libdevice.all}/test_dfb.cpp | 0
.../egl => testsuite/libdevice.all}/test_egl.cpp | 11 +-
.../libdevice.all}/test_events.cpp | 0
.../libdevice.all}/test_rawfb.cpp | 7 +
.../libdevice.all}/test_vaapi.cpp | 0
.../x11 => testsuite/libdevice.all}/test_x11.cpp | 0
testsuite/libmedia.all/Makefile.am | 5 +
testsuite/media/Makefile.am | 1 +
testsuite/media/silence.mp3 | Bin 0 -> 69940 bytes
.../misc-haxe.all/classes.all/net/NetStream_as.hx | 398 +-
testsuite/misc-ming.all/Makefile.am | 28 +-
testsuite/misc-ming.all/NetStream-SquareTest.c | 2 +-
testsuite/misc-ming.all/TODO | 1 -
testsuite/misc-ming.all/Video-EmbedSquareTest.c | 5 +-
testsuite/misc-ming.all/XMLSocketTest.as | 83 +-
...ndler_scope_test.c => empty_clip_action_test.c} | 105 +-
.../misc-ming.all/loading/loadMovieTestRunner.cpp | 2 +-
.../sound/EmbeddedSoundTest-Runner.cpp | 1 -
.../misc-ming.all/sound/eventSoundTest1-Runner.cpp | 1 -
testsuite/movies.all/Makefile.am | 6 +
testsuite/samples/Makefile.am | 16 +
utilities/Makefile.am | 16 +-
utilities/findmicrophones.cpp | 2 +
utilities/findwebcams.cpp | 2 +
utilities/processor.cpp | 14 +-
274 files changed, 3533 insertions(+), 10162 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index ce78d68..f8bcf34 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,6 +24,9 @@ AUTOMAKE_OPTIONS = 1.6.0 -Wno-portability
ACLOCAL_AMFLAGS = -I macros -I cygnal
noinst_SCRIPT = autogen.sh
+CXXFLAGS += $(CROSS_CXXFLAGS)
+LDFLAGS += $(CROSS_LDFLAGS)
+
##
## Any custom ./configure switch we want to be
## given at 'make distcheck' time should go here
@@ -43,7 +46,6 @@ DISTCHECK_CONFIGURE_FLAGS = \
--with-plugins-install=prefix \
--enable-extensions=all \
--enable-gui=all \
- --enable-device=all \
--enable-renderer=all \
--enable-python \
--enable-cygnal
@@ -52,6 +54,8 @@ DISTCHECK_CONFIGURE_FLAGS = \
# primarily a Linux only thing.
if LINUX
DISTCHECK_CONFIGURE_FLAGS += --enable-device=all
+else
+DISTCHECK_CONFIGURE_FLAGS += --disable-jemalloc
endif
if CYGNAL
@@ -70,12 +74,20 @@ if BUILD_EXTENSIONS
EXT_DIR = extensions
endif
+if BUILD_LIBSOUND
+SOUND_DIR = libsound
+endif
+
+if BUILD_LIBMEDIA
+MEDIA_DIR = libmedia
+endif
+
SUBDIRS = \
desktop \
$(DEVICES_DIR) \
libbase \
- libmedia \
- libsound \
+ $(MEDIA_DIR) \
+ $(SOUND_DIR) \
libcore \
librender \
gui \
@@ -218,6 +230,7 @@ dumpconfig:
@uname -a
$(CXX) -v
@echo "CXXFLAGS: $(CXXFLAGS)"
+ @echo "LDFLAGS: $(LDFLAGS)"
@echo ""
@echo "Image decoding support..."
@echo " JPEG_CFLAGS is $(JPEG_CFLAGS)"
@@ -520,6 +533,6 @@ package:
packageclean:
-test -z "$(CLEANFILES)" || rm -rf $(CLEANFILES)
-
+
# these files are created when building packages
CLEANFILES += *.deb *.dsc *.gz *.bz2 *.changes deb-copy-stamp gnash*git* gnash-* rpmbuild gnash.spec .rpmmacros
diff --git a/NEWS b/NEWS
index 1f2015e..fbc6d1c 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,14 @@ YYYY/MM/DD
Improvements since 0.8.10 release are:
* Fix opening of external URL with Gnash Standalone (#31833)
+ * Stability fixes in image handling, (CVE-2012-1175, #39388, #37629).
+ * Stability fixes in parsing (#34686) and ActionScript handling (#39385, #39404).
+ * NPAPI Plugin stability fix (#36002).
+ * Improved NetStream ActionScript class support.
+ * Add support for IPv6 [TODO: affects Socket/XML, and what else?].
+ * Fix build against recent Boost and FFMPEG.
+ * Fix support for GIFLIB-5.0 (#39482)
+ * Fix regression in dynamic sound loading (#33760).
Gnash 0.8.10
2012/02/04
diff --git a/configure.ac b/configure.ac
index 0f999be..2d9b3b0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -67,6 +67,10 @@ case "${host}" in
DEFAULT_FLASH_PLATFORM_ID="BSD"
DEFAULT_FLASH_SYSTEM_OS="NetBSD"
;;
+ *-android*)
+ DEFAULT_FLASH_PLATFORM_ID="AND"
+ DEFAULT_FLASH_SYSTEM_OS="Linux"
+ ;;
*-linux-gnu)
DEFAULT_FLASH_PLATFORM_ID="LNX"
DEFAULT_FLASH_SYSTEM_OS="GNU/Linux"
@@ -165,6 +169,10 @@ case "${host}" in
solaris=yes
AC_DEFINE([SOLARIS_HOST], [1], [this is a Solaris platform])
;;
+ *-android*)
+ android=yes
+ AC_DEFINE([ANDROID_HOST], [1], [this is an Android platform])
+ ;;
*-*linux*)
linux=yes
AC_DEFINE([LINUX_HOST], [1], [this is a Linux platform])
@@ -198,10 +206,6 @@ case "${host}" in
AC_DEFINE([WINCE_HOST], [1], [this is a WINCE platform])
AC_DEFINE([WINCE6_HOST], [1], [this is a WINCE6 platform])
;;
- *-android*)
- android=yes
- AC_DEFINE([ANDROID_HOST], [1], [this is an Android platform])
- ;;
esac
@@ -239,11 +243,24 @@ dnl like pentium->geode, which can use the same compiler, but have
dnl different development libraries.
AC_ARG_WITH(sysroot,
- AC_HELP_STRING([--with-sysroot],
- [system root directory for cross compiling]),
- with_top_level=${withval} ;
+ AC_HELP_STRING([--with-sysroot], [system root directory for cross compiling]),
+ with_top_level=${withval};
cross_compiling=yes)
+if test x"${cross_compiling}" != x; then
+ dnl Check if /usr isn't part of the specified path
+ if test -d ${with_top_level}/usr; then
+ with_top_level=${withval}/usr
+ else
+ dnl Check if the specified path supplies /usr
+ if test -d ${with_top_level}/include; then
+ with_top_level=${withval}
+ else
+ AC_MSG_ERROR([Specified sysroot \"${with_top_level}/include\" doesn't exist!])
+ fi
+ fi
+fi
+
dnl Android is a little different when using a standard cross toolchain,
dnl so we have to configure especially for it for now. Usually it's
dnl something like this:
@@ -261,24 +278,27 @@ AC_ARG_WITH([android],
android_ndk=${withval}
if test x"${withval}" != x; then
android_ndk=${withval}
- else
- android_ndk=/opt/android-ndk-r3/build/platforms/android-5/arch-arm
fi
)
CROSS_CXXFLAGS=
-if test x"${android_ndk}" != xno; then
- CROSS_CXXFLAGS=-mandroid -fexceptions
+if test x"${android}" = xyes; then
+ CROSS_CXXFLAGS='-fexceptions -frtti -I${prefix}/include'
+ CROSS_LDFLAGS='-all-static -L${prefix}/lib'
if test x"${with_top_level}" = x; then
with_top_level=/usr/local/android-arm/sysroot/usr
cross_compiling=yes
fi
ANDROID_NDK=${android_ndk}
AC_DEFINE(ANDROID, [1], [This is an Android build])
+ CXXFLAGS="${CXXFLAGS} ${CROSS_CXXFLAGS}"
else
+ CROSS_CXXFLAGS=
ANDROID_NDK=
fi
AC_SUBST(ANDROID_NDK)
-AM_CONDITIONAL(ANDROID, [ test x"${android_ndk}" != xno ])
+AM_CONDITIONAL(ANDROID, [ test x"${android}" = xyes ])
+AC_SUBST(CROSS_LDFLAGS)
+AC_SUBST(CROSS_CXXFLAGS)
AC_C_BIGENDIAN
AC_C_CONST
@@ -729,6 +749,11 @@ AC_ARG_ENABLE(sound,
fi]
)
+AM_CONDITIONAL(BUILD_LIBSOUND, test x${build_sound_none} != xyes)
+if test x${build_sound_none} != xyes; then
+ AC_DEFINE(USE_SOUND, [1], [Build any sound code])
+fi
+
dnl --------------------------------------------------------
dnl Media handler selection
dnl --------------------------------------------------------
@@ -737,7 +762,7 @@ build_media_ffmpeg=auto
build_media_none=no
AC_ARG_ENABLE(media,
AC_HELP_STRING([--enable-media=handler],
- [Enable media handling support using the specified handler: gst, ffmpeg or none (no sound) [[gst]] ]),
+ [Enable media handling support using the specified handlers: ffmpeg gst none(no sound) (default=auto) ]),
if test -n ${enableval}; then
enableval=`echo ${enableval} | tr '\054' ' ' `
@@ -781,6 +806,11 @@ AC_ARG_ENABLE(media,
fi]
)
+AM_CONDITIONAL(BUILD_LIBMEDIA, test x${build_media_none} != xyes)
+if test x${build_media_none} != xyes; then
+ AC_DEFINE(USE_MEDIA, [1], [Build any media code])
+fi
+
dnl If no render is selected, and media handling isn't disabled, them enable gst
if test x${build_media_none} = xno -a x${build_media_gst} = xno -a x${build_media_ffmpeg} = xno; then
build_media_gst=yes
@@ -1017,7 +1047,12 @@ dnl GMA500 but you currently will have to build the AGG renderer
dnl instead of the OGL (OpenGL) one.
build_vaapi_device=no
build_openmax_device=no
-build_egl_device=no
+dnl These renders always require EGL support
+if test x${build_gles1} = xyes -o x${build_ovg} = xyes; then
+ build_egl_device=yes
+else
+ build_egl_device=no
+fi
build_x11_device=no
build_directfb_device=no
if test x"${build_fb}" = xyes -o x"${build_fb}" = xauto; then
@@ -1160,12 +1195,26 @@ if test x"${build_egl_device}" = xyes; then
if test xyes = x"${has_EGL}"; then
AC_DEFINE(BUILD_EGL_DEVICE, [ 1 ],
[Build the EGL device for OpenVG, OpenGLES1&2, and X11/Mesa])
- device_list="${device_list} EGL"
- ndevice=$((ndevice+1))
else
AC_MSG_WARN(["EGL requested but development package not found!"])
build_egl_device=no
fi
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Wall -Werror"
+ native_window_type=none
+ AC_MSG_CHECKING([For EGLNativeWindowType type])
+ AC_TRY_COMPILE([#include <EGL/eglplatform.h>], [
+ EGLNativeWindowType foo = 1;
+ int bar = foo;
+ bar++; ],
+ native_window_type=int,
+ native_window_type=void
+ )
+ CFLAGS="$save_CFLAGS"
+ AC_MSG_RESULT([${native_window_type}])
+ if test x"${native_window_type}" = x"int"; then
+ AC_DEFINE([EGL_NATIVE_WINDOW_INT], [1], [EGLNativeWindowType type])
+ fi
fi
if test ${ndevice} -eq 0; then
@@ -1313,7 +1362,7 @@ extensions_support=yes
nextensions=0
AC_ARG_ENABLE(extensions,
AC_HELP_STRING([--enable-extensions=], [Specify which extensions to build (default: none)])
- AC_HELP_STRING([--disable-extensions], [Disable support for extensions entirely]),
+AC_HELP_STRING([--disable-extensions], [Disable support for extensions entirely]),
if test -n ${enableval}; then
if test "x${enableval}" != "xno"; then
extlist="${enableval}"
@@ -1506,40 +1555,14 @@ fi
# This seems like a good idea, as both the other player and
# Mozilla/Firefox both recently switched to using jemalloc.
AC_ARG_ENABLE(jemalloc,
- AC_HELP_STRING([--enable-jemalloc],[Enable jemalloc instead of system malloc]),
+ AC_HELP_STRING([--enable-jemalloc],[Enable jemalloc instead of system malloc])
+AC_HELP_STRING([--disable-jemalloc],[Disable jemalloc]),
[case "${enableval}" in
yes) jemalloc=yes ;;
no) jemalloc=no ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-jemalloc option]) ;;
esac],jemalloc=yes)
-AC_CHECK_SIZEOF([void *], [4])
-
-if test "x${ac_cv_sizeof_void_p}" != x4 -a x"${ac_cv_sizeof_void_p}" != x8; then
- dnl jemalloc doesn't support unusual pointer sizes
- jemalloc=no
-fi
-
-dnl There is some weird stuff going on with NetBSD and jemalloc, so don't
-dnl build it for now.
-if test x"${netbsd}" = x"yes" -o x"${windows}" = x"yes" -o x"${freebsd}" = x"yes" -o x"${haiku}" = x"yes" -o x"${gnu}" = x"yes"; then
- jemalloc=no
-fi
-dnl If the compiler doesn't have local thread storage enabled, don't try to
-dnl use jemalloc.
-if test x"${jemalloc}" = x"yes"; then
- AC_TRY_COMPILE([], [
- extern __thread int global_i; ],
- has_local_thread_storage=yes
- )
- if test x"${has_local_thread_storage}" = x"yes"; then
- AC_DEFINE([HAVE_LOCAL_THREAD_STORAGE], [1], [Has __thread (local thread storage) support])
- AC_DEFINE([USE_JEMALLOC], [], [Use jemalloc instead of system malloc])
- else
- jemalloc=no
- fi
-fi
-
dnl We can search libs for mallinfo to decide whether we have it or not.
dnl This is added to the linker flags when it's found. Usually it's -lc, but
dnl on OpenSolaris it's -lmalloc, so this fixes the build.
@@ -1549,12 +1572,14 @@ AC_SEARCH_LIBS([mallinfo], [c malloc],
)
AM_CONDITIONAL([HAVE_MALLINFO], test x$mallinfo = xyes)
-AM_CONDITIONAL(JEMALLOC, test x$jemalloc = xyes)
+
+if test x"${jemalloc}" = x"yes"; then
+ GNASH_PKG_FIND(jemalloc, [jemalloc.h], [jemalloc memory management], mallctl)
+fi
-AC_SEARCH_LIBS([getaddrinfo], [c],
- AC_DEFINE(HAVE_IPV6, [1], [Has IPV6 support])
- ipv6=yes
- )
+AM_CONDITIONAL(JEMALLOC, test x"${has_jemalloc}" = xyes)
+
+AC_SEARCH_LIBS([getaddrinfo], [c])
AC_ARG_ENABLE(fps-debug,
AC_HELP_STRING([--enable-fps-debug],[Enable FPS debugging code]),
@@ -1848,14 +1873,14 @@ fi
dnl Check possibility to build FB gui, if requested
dnl FB dependency is a linux system (linux/fb.h)
if test x"${build_fb}" != xno; then
- if test x"${linux}" = xyes; then
+ if test x"${linux}" = xyes -o x"${android}" = xyes; then
build_fb=yes
else
if test x"${build_fb}" = xyes; then
dnl SHOULD we just check at the end of file instead ?
- AC_MSG_ERROR(fb GUI cannot be built on non-linux platforms);
+ AC_MSG_ERROR(framebuffer GUI cannot be built on non-linux platforms);
fi
- AC_MSG_NOTICE([fb GUI won't be built (non-linux platform)])
+ AC_MSG_NOTICE([framebuffer GUI won't be built (non-linux platform)])
build_fb=no
fi
fi
@@ -2076,9 +2101,12 @@ AC_CHECK_HEADERS(sys/utsname.h)
AC_CHECK_HEADERS(signal.h)
AC_CHECK_HEADERS(unistd.h)
AC_CHECK_HEADERS(sys/time.h)
+AC_CHECK_HEADERS(linux/uinput.h, [uinput=yes], [uinput=no])
AC_CHECK_LIB(bz2, BZ2_bzopen, [AC_SUBST(BZ2_LIBS, -lbz2)])
AC_CHECK_LIB(c, getpwnam, AC_DEFINE(HAVE_GETPWNAM, 1, [Has getpwnam] ))
+AM_CONDITIONAL(HAS_UINPUT, [test x$uinput = xyes])
+
dnl X11 is needed for fltk (at least),
dnl and probably for many other guis too ...
dnl if ! test x$build_fb = xyes; then # <--- this is wrong as build_x is non-exclusive
@@ -2086,8 +2114,6 @@ dnl AC_PATH_XTRA
dnl AC_CHECK_LIB(Xmu, XmuCvtStringToOrientation)
dnl AC_CHECK_LIB(gmp, _gmp_get_memory_functions)
GNASH_PATH_X11
-AC_CHECK_LIB(Xi, XInput_find_display)
-AC_CHECK_LIB(X11, XDisableAccessControl)
dnl fi
AM_CONDITIONAL(HAVE_X11, [test x${has_x11} = xyes])
if test x${build_x11_device} = xyes -a x${has_x11} = xyes; then
@@ -2482,7 +2508,7 @@ if test x"${build_gles1}"; then
fi
dnl only Linux supports /dev/fb0
-if test x"${build_rawfb_device}" = xyes -a x"${linux}" = xyes; then
+if test x"${build_rawfb_device}" = xyes; then
AC_DEFINE([BUILD_RAWFB_DEVICE], [1], [Use raw Framebuffer device support])
fi
@@ -2726,7 +2752,6 @@ if test x"$GCC" = x"yes"; then
$CROSS_CXXFLAGS \
-W \
-Wall \
- -Wcast-align \
-Wcast-qual \
-Wpointer-arith \
-Wreturn-type \
@@ -2784,8 +2809,10 @@ AC_DEFUN([CHECK_VISIBILITY_GCC_BUG],
[
AC_CACHE_CHECK([if -fvisibility-inlines-hidden is broken], ac_cv_gcc_visibility_bug, [
AC_LANG_PUSH(C++)
+ save_CFLAGS=$CFLAGS
save_CXXFLAGS=$CXXFLAGS
save_LDFLAGS=$LDFLAGS
+ CFLAGS="-fPIC -O0"
CXXFLAGS="-fPIC -fvisibility-inlines-hidden -O0"
LDFLAGS="$LDFLAGS -shared -fPIC"
@@ -2809,6 +2836,7 @@ AC_DEFUN([CHECK_VISIBILITY_GCC_BUG],
], [],
ac_cv_gcc_visibility_bug=no, ac_cv_gcc_visibility_bug=yes)
+ CFLAGS=$save_CFLAGS
CXXFLAGS=$save_CXXFLAGS
LDFLAGS=$save_LDFLAGS
AC_LANG_POP(C++)
@@ -2843,6 +2871,23 @@ if test x"$ac_cv_gcc_visibility" = xyes -a x"$enable_visibility" != xno; then
CXXFLAGS="$CXXFLAGS -fvisibility=hidden"
fi
+AC_ARG_ENABLE([harden],
+ AC_HELP_STRING([--disable-harden],[Disable hardening]),
+ [case "${enableval}" in
+ yes) harden=yes ;;
+ no) harden=no ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-harden option]) ;;
+ esac],
+ [harden=yes]
+)
+
+if test x"$harden" = x"yes" -a x"${host_cpu}" != mips -a x"${android}" != xyes; then
+ CPPFLAGS="${CPPFLAGS} -D_FORTIFY_SOURCE=2"
+ CFLAGS="${CFLAGS} -fPIE -fstack-protector --param ssp-buffer-size=4 -Wformat -Werror=format-security"
+ CXXFLAGS="${CXXFLAGS} -fPIE -fstack-protector --param ssp-buffer-size=4 -Wformat -Werror=format-security"
+ LDFLAGS="${LDFLAGS} -fPIE -pie -Wl,-z,relro -Wl,-z,now"
+fi
+
dnl Define convenience constants so Gnash can print out the
dnl default configuration of the build.
RENDERER_CONFIG="${renderer_list}"
@@ -3137,8 +3182,14 @@ AC_DEFUN([PKG_ALTERNATIVE],
echo "Configurable options are:"
+if test x"${jemalloc}" = x"yes"; then
+ echo " JEMALLOC Memory management enabled (default)."
+else
+ echo " JEMALLOC Memory management disabled."
+fi
+
if test x"${pthreads}" = x"yes"; then
- echo " POSIX Threads support enabled (default)"
+ echo " POSIX Threads support enabled (default)."
else
if test x"${build_haiku}" = x"yes"; then
echo " POSIX Thread support built into C library."
@@ -3181,6 +3232,20 @@ fi
echo ""
echo "Configured paths for ${build} are:"
+if test x"${jemalloc}" = x"yes"; then
+ if test x"${has_jemalloc}" = xyes; then
+ echo " JEMALLOC flags are: ${JEMALLOC_CFLAGS}"
+ echo " JEMALLOC libs are: ${JEMALLOC_LIBS}"
+ else
+ PKG_ERR([No jemalloc development package installed!])
+ PKG_SUGGEST([Install a jemalloc development environment from
+ http://www.canonware.com/jemalloc/])
+ DEB_INSTALL([libjemalloc-dev])
+ RPM_INSTALL([jemalloc-devel])
+ PKG_ALTERNATIVE([or specify --disable-jemalloc])
+ fi
+fi
+
dnl Dump QT3 options is the user specified a QTOPIA3 or KDE3 GUI
if test x"${build_kde3}" = xyes -o x"${build_qtopia3}" = xyes; then
if test x"${has_qt3}" = xyes; then
@@ -3506,6 +3571,23 @@ if test x"${build_media_ffmpeg}" = x"yes"; then
DEB_INSTALL([libswscale-dev])
PKG_ALTERNATIVE(or reconfigure with --enable-media=gst)
fi
+
+ if test x"${have_ffmpeg_libavutil}" = "xno"; then
+ PKG_ERR([No libavutil development package installed!])
+ PKG_SUGGEST([You can install libavutil from http://ffmpeg.org])
+ DEB_INSTALL([libavutil-dev])
+ PKG_ALTERNATIVE(or reconfigure with --enable-media=gst)
+ fi
+
+ if test x"${ffmpeg_aac_float_planar}" = "xyes" -a \
+ x"${have_ffmpeg_swresample}" = "xno" -a \
+ x"${have_libav_avresample}" = "xno"; then
+ PKG_REC([Please install libswresample/libavresample development package. If you don't, Gnash will be unable to resample some formats (e.g. AAC on youtube)])
+ PKG_SUGGEST([You can install libavresample from http://libav.org])
+ PKG_SUGGEST([You can install libswresample from http://ffmpeg.org])
+ DEB_INSTALL([libavresample-dev])
+ PKG_ALTERNATIVE(or reconfigure with --enable-media=gst)
+ fi
fi
if test x$build_cairo = xyes; then
@@ -3959,8 +4041,8 @@ if test x"$npapi" = xyes; then
else
PKG_ERR([No xulrunner development package is installed!])
PKG_SUGGEST([Install it from http://releases.mozilla.org/pub/mozilla.org/xulrunner])
- DEB_INSTALL([xulrunner-dev]) or
- DEB_INSTALL([firefox-dev])
+ DEB_INSTALL([xulrunner-dev])
+ DEB_ALTERNATIVE([firefox-dev])
RPM_INSTALL([xulrunner-devel])
fi
else
@@ -4159,30 +4241,32 @@ yast_err="`cat $yast_err`"
yast_war="`cat $yast_war`"
yast_rec="`cat $yast_rec`"
-# Pipe stderr to /dev/null since Fedora complains when target isn't there.
-if test x`which apt-get 2>/dev/null` != x; then
- if test x"$deb_err" != x -o x"$deb_war" != x -o x"$deb_rec" != x; then
- echo "#!/bin/sh" > deb-attempt-install-dependencies.sh
- echo "packages=\"$deb_err $deb_war $deb_rec\"" >> deb-attempt-install-dependencies.sh
- echo "PKGCOMMAND=\"apt-get install -y -q\"" >> deb-attempt-install-dependencies.sh
- cat ${srcdir}/base-attempter.sh >> deb-attempt-install-dependencies.sh
- chmod +x deb-attempt-install-dependencies.sh
- echo ""
- echo ".deb users might be able to install most dependencies by executing:"
- echo "sudo ./deb-attempt-install-dependencies.sh"
+if test x"${android}" != xyes; then
+ # Pipe stderr to /dev/null since Fedora complains when target isn't there.
+ if test x`which apt-get 2>/dev/null` != x; then
+ if test x"$deb_err" != x -o x"$deb_war" != x -o x"$deb_rec" != x; then
+ echo "#!/bin/sh" > deb-attempt-install-dependencies.sh
+ echo "packages=\"$deb_err $deb_war $deb_rec\"" >> deb-attempt-install-dependencies.sh
+ echo "PKGCOMMAND=\"apt-get install -y -q\"" >> deb-attempt-install-dependencies.sh
+ cat ${srcdir}/base-attempter.sh >> deb-attempt-install-dependencies.sh
+ chmod +x deb-attempt-install-dependencies.sh
+ echo ""
+ echo ".deb users might be able to install most dependencies by executing:"
+ echo "sudo ./deb-attempt-install-dependencies.sh"
+ fi
fi
-fi
-if test x`which yum 2>/dev/null` != x; then
- if test x"$rpm_err" != x -o x"$rpm_war" != x -o x"$deb_rec" != x; then
- echo "#!/bin/sh" > rpm-attempt-install-dependencies.sh
- echo "packages=\"$rpm_err $rpm_war $rpm_rec\"" >> rpm-attempt-install-dependencies.sh
- echo "PKGCOMMAND=\"yum install -y \"" >> rpm-attempt-install-dependencies.sh
- cat ${srcdir}/base-attempter.sh >> rpm-attempt-install-dependencies.sh
- chmod +x rpm-attempt-install-dependencies.sh
- echo ""
- echo ".rpm users might be able to install most dependencies by executing:"
- echo "sudo ./rpm-attempt-install-dependencies.sh"
+ if test x`which yum 2>/dev/null` != x; then
+ if test x"$rpm_err" != x -o x"$rpm_war" != x -o x"$deb_rec" != x; then
+ echo "#!/bin/sh" > rpm-attempt-install-dependencies.sh
+ echo "packages=\"$rpm_err $rpm_war $rpm_rec\"" >> rpm-attempt-install-dependencies.sh
+ echo "PKGCOMMAND=\"yum install -y \"" >> rpm-attempt-install-dependencies.sh
+ cat ${srcdir}/base-attempter.sh >> rpm-attempt-install-dependencies.sh
+ chmod +x rpm-attempt-install-dependencies.sh
+ echo ""
+ echo ".rpm users might be able to install most dependencies by executing:"
+ echo "sudo ./rpm-attempt-install-dependencies.sh"
+ fi
fi
fi
diff --git a/cygnal/Makefile.am b/cygnal/Makefile.am
index defc16a..30fbba6 100644
--- a/cygnal/Makefile.am
+++ b/cygnal/Makefile.am
@@ -51,8 +51,6 @@ AM_LDFLAGS = \
libamf/libgnashamf.la \
$(top_builddir)/libbase/libgnashbase.la \
$(top_builddir)/libcore/libgnashcore.la \
- $(top_builddir)/libmedia/libgnashmedia.la \
- $(top_builddir)/libsound/libgnashsound.la \
$(top_builddir)/librender/libgnashrender.la \
$(GLIB_LIBS) \
$(LIBINTL) \
@@ -61,6 +59,13 @@ AM_LDFLAGS = \
$(BOOST_CYGNAL_LIBS) \
$(NULL)
+if BUILD_LIBMEDIA
+AM_LDFLAGS += $(top_builddir)/libmedia/libgnashmedia.la
+endif
+if BUILD_LIBSOUND
+AM_LDFLAGS += $(top_builddir)/libsound/libgnashsound.la
+endif
+
localedir = $(datadir)/locale
INCLUDES = -I.. \
diff --git a/cygnal/cgi-bin/oflaDemo/oflaDemo.cpp b/cygnal/cgi-bin/oflaDemo/oflaDemo.cpp
index 4f84803..d4f0a40 100644
--- a/cygnal/cgi-bin/oflaDemo/oflaDemo.cpp
+++ b/cygnal/cgi-bin/oflaDemo/oflaDemo.cpp
@@ -235,7 +235,7 @@ main(int argc, char *argv[])
}
OflaDemoTest net;
- int netfd;
+ int netfd = 0;
if (infile.empty()) {
if (netdebug) {
diff --git a/cygnal/handler.cpp b/cygnal/handler.cpp
index ee8cbb5..4ec0a27 100644
--- a/cygnal/handler.cpp
+++ b/cygnal/handler.cpp
@@ -403,7 +403,7 @@ Handler::findStream(const std::string &filespec)
{
// GNASH_REPORT_FUNCTION;
- for (int i; i < _streams; i++) {
+ for (int i = 0; i < _streams; i++) {
if (_diskstreams[i]->getFilespec() == filespec) {
return _diskstreams[i];
}
diff --git a/cygnal/libamf/sol.cpp b/cygnal/libamf/sol.cpp
index 43a9b4c..0963dcd 100644
--- a/cygnal/libamf/sol.cpp
+++ b/cygnal/libamf/sol.cpp
@@ -51,10 +51,10 @@ using gnash::log_error;
// Object Name - variable (the name of the object as an AMF encoded string)
// Padding - 4 bytes
// After this is a series of AMF objects
-const short SOL_MAGIC = 0x00bf; // is in big-endian format, this is the first
+const boost::uint16_t SOL_MAGIC = 0x00bf; // is in big-endian format, this is the first
// two bytes. of the .sol file.
//char *SOL_FILETYPE = "TCSO";
-const short SOL_BLOCK_MARK = 0x0004;
+const boost::uint16_t SOL_BLOCK_MARK = 0x0004;
/// \define ENSUREBYTES
///
@@ -149,6 +149,15 @@ SOL::formatHeader(const std::string &name)
return formatHeader(name, _filesize);
}
+template <typename T>
+void
+appendSwapped(std::vector<boost::uint8_t>& container, T val)
+{
+ boost::uint8_t *ptr =
+ static_cast<boost::uint8_t*>(swapBytes(&val, sizeof(val)));
+ container.insert(container.end(), ptr, ptr+sizeof(val));
+}
+
/// \brief Create the file header.
///
/// @param name The name of the SharedObject for this file.
@@ -160,67 +169,40 @@ bool
SOL::formatHeader(const std::string &name, int filesize)
{
// GNASH_REPORT_FUNCTION;
- boost::uint32_t i;
// First we add the magic number. All SOL data is in big-endian format,
// so we swap it first.
- boost::uint16_t swapped = SOL_MAGIC;
- swapped = htons(swapped);
- boost::uint8_t *ptr = reinterpret_cast<boost::uint8_t *>(&swapped);
- for (i=0; i<sizeof(boost::uint16_t); i++) {
- _header.push_back(ptr[i]);
- }
+ appendSwapped(_header, SOL_MAGIC);
// Next is the file size to be created. We adjust it as the filesize
// includes the padding in the header, the mystery bytes, and the
// padding, plus the length of the name itself.
filesize += name.size() + 16;
boost::uint32_t len = filesize;
- len = htonl(len);
- ptr = reinterpret_cast<boost::uint8_t *>(&len);
- for (i=0; i<sizeof(boost::uint32_t); i++) {
- _header.push_back(ptr[i]);
- }
+ appendSwapped(_header, len);
// Then the mystery block, but as the value never seems to every change,
// we just built it the same way it always is.
// first is the TCSO, we have no idea what this stands for.
-// ptr = reinterpret_cast<uint8_t *>(const_cast<uint8_t *>("TCSO");
- ptr = (boost::uint8_t *)"TCSO";
- for (i=0; i<sizeof(boost::uint32_t); i++) {
- _header.push_back(ptr[i]);
- }
+ const char magic[] = "TCSO";
+ _header.insert(_header.end(), boost::begin(magic), boost::end(magic));
+
// then the 0x0004 bytes, also a mystery
- swapped = SOL_BLOCK_MARK;
- swapped = htons(swapped);
- ptr = reinterpret_cast<boost::uint8_t *>(&swapped);
- for (i=0; i<sizeof(boost::uint16_t); i++) {
- _header.push_back(ptr[i]);
- }
+ appendSwapped(_header, SOL_BLOCK_MARK);
// finally a bunch of zeros to pad things for this field
- for (i=0; i<sizeof(boost::uint32_t); i++) {
- _header.push_back('\0');
- }
+ _header.insert(_header.end(), '\0', sizeof(boost::uint32_t));
// Encode the name. This is not a string object, which has a type field
// one byte field precedding the length as a file type of AMF::STRING.
// First the length in two bytes
- swapped = name.size();
- swapped = htons(swapped);
- ptr = reinterpret_cast<boost::uint8_t *>(&swapped);
- for (i=0; i<sizeof(boost::uint16_t); i++) {
- _header.push_back(ptr[i]);
- }
+ boost::uint16_t size = name.size();
+ appendSwapped(_header, size);
+
// then the string itself
- ptr = (boost::uint8_t *)name.c_str();
- for (i=0; i<name.size(); i++) {
- _header.push_back(ptr[i]);
- }
+ _header.insert(_header.end(), name.begin(), name.end());
// finally a bunch of zeros to pad things at the end of the header
- for (i=0; i<sizeof(boost::uint32_t); i++) {
- _header.push_back('\0');
- }
+ _header.insert(_header.end(), '\0', sizeof(boost::uint32_t));
#if 0
unsigned char *hexint;
diff --git a/cygnal/libnet/diskstream.cpp b/cygnal/libnet/diskstream.cpp
index b9d4a01..4a5e515 100644
--- a/cygnal/libnet/diskstream.cpp
+++ b/cygnal/libnet/diskstream.cpp
@@ -584,7 +584,9 @@ DiskStream::writeToDisk(const std::string &filespec, boost::uint8_t *data, size_
log_error(strerror(errno));
}
log_debug(_("Writing data (%d bytes) to disk: \"%s\""), size, filespec);
- ::write(fd, data, size);
+ if(::write(fd, data, size) < 0) {
+ log_error(strerror(errno));
+ };
::close(fd);
return true;
diff --git a/cygnal/libnet/network.cpp b/cygnal/libnet/network.cpp
index aecb341..0c1fc49 100644
--- a/cygnal/libnet/network.cpp
+++ b/cygnal/libnet/network.cpp
@@ -84,7 +84,6 @@ using std::vector;
/// This is the main namespace for Gnash and it's libraries.
namespace gnash {
-static const char *DEFAULTPROTO = "tcp";
static const short DEFAULTPORT = RTMP_PORT;
#ifndef INADDR_NONE
@@ -159,7 +158,7 @@ Network::createServer(std::string hostname, short port)
{
// GNASH_REPORT_FUNCTION;
- int on, type;
+ int on;
int retries = 0;
if (_listenfd >= 2) {
@@ -562,7 +561,6 @@ Network::createClient(const string &hostname, short port)
struct timeval tval;
int ret;
int retries;
- struct protoent *proto;
// assert( ! connected() );
if (connected()) {
diff --git a/cygnal/libnet/rtmp_msg.cpp b/cygnal/libnet/rtmp_msg.cpp
index 47371c0..a606137 100644
--- a/cygnal/libnet/rtmp_msg.cpp
+++ b/cygnal/libnet/rtmp_msg.cpp
@@ -169,7 +169,7 @@ boost::shared_ptr<cygnal::Element>
RTMPMsg::operator[](size_t index)
{
// GNASH_REPORT_FUNCTION;
- if (index <= _amfobjs.size()) {
+ if (index < _amfobjs.size()) {
return _amfobjs[index];
}
diff --git a/cygnal/proc.cpp b/cygnal/proc.cpp
index f221c11..f36fa43 100644
--- a/cygnal/proc.cpp
+++ b/cygnal/proc.cpp
@@ -122,23 +122,23 @@ Proc::startCGI(const string &filespec, bool outflag, boost::uint16_t port)
}
// setup a command line. By default, argv[0] is the name of the process
- cmd_line[0] = new char(filespec.size()+1);
+ cmd_line[0] = new char[filespec.size()+1];
strcpy(cmd_line[0], filespec.c_str());
// If the parent has verbosity on, chances are the child should too.
// if (dbglogfile.getVerbosity() > 0) {
- cmd_line[1] = new char(3);
+ cmd_line[1] = new char[3];
strcpy(cmd_line[1], "-n");
- cmd_line[2] = new char(4);
+ cmd_line[2] = new char[4];
strcpy(cmd_line[2], "-vv");
cmd_line[3] = 0;
// }
// When running multiple cgis, we prefer to specify the port it's using.
if (port > 0) {
- cmd_line[3] = new char(3);
+ cmd_line[3] = new char[3];
strcpy(cmd_line[3], "-p");
- cmd_line[4] = new char(10);
+ cmd_line[4] = new char[10];
sprintf(cmd_line[4], "%d", port);
cmd_line[5] = 0;
}
diff --git a/doc/C/Makefile.am b/doc/C/Makefile.am
index 04dc073..91d6709 100644
--- a/doc/C/Makefile.am
+++ b/doc/C/Makefile.am
@@ -230,8 +230,8 @@ endif
if ENABLE_TEXI
-if test x$(DB2X_TEXI) != x; then \
out=`echo $* | sed -e 's:gnash:gnash_:'`; \
- $(DB2X_TEXI) --encoding=us-ascii//TRANSLIT --string-param directory-description="Gnash" --string-param output-file=$${out} $<; \
- $(MAKEINFO) --force $${out}.texi; \
+ $(DB2X_TEXI) --info --encoding=us-ascii//TRANSLIT --string-param \
+directory-description="Gnash" --string-param output-file=$${out} $<; \
else \
basefile="$*"; \
$(DB2X_XSLTPROC) -s texi $< --output $${basefile}.txml; \
@@ -241,11 +241,7 @@ if ENABLE_TEXI
endif
.texi.info:
-if ENABLE_TEXI
- -$(MAKEINFO) --force $<
-else
- touch $@;
-endif
+ touch $@
.man-xml.1:
if ENABLE_MAN
diff --git a/doc/C/refmanual/feature_configuration.xml b/doc/C/refmanual/feature_configuration.xml
index 63cdeb5..5acefbd 100644
--- a/doc/C/refmanual/feature_configuration.xml
+++ b/doc/C/refmanual/feature_configuration.xml
@@ -23,7 +23,7 @@
<listitem>
<para>
<option>--enable-media</option> permits a media handler to be
- selected. The default is Gstreamer.
+ selected. The default is auto.
</para>
</listitem>
</itemizedlist>
@@ -79,8 +79,23 @@
</row>
<row>
- <entry><option>--enable-gui=gtk|sdl|kde|fltk|fb|hildon|alp</option></entry>
- <entry><para>Select the Graphic User Interface to use (choose one).</para>
+ <entry>
+ <programlisting>
+--enable-gui=<gui>[,<gui>]...
+
+ gui can be: aos4
+ aqua
+ dump
+ fb
+ fltk
+ gtk
+ haiku
+ qt3
+ qt4
+ sdl
+ </programlisting>
+ </entry>
+ <entry><para>Select the Graphic User Interface to build.</para>
<variablelist>
<varlistentry>
<term>GTK</term>
@@ -92,23 +107,6 @@
</listitem>
</varlistentry>
<varlistentry>
- <term>Hildon</term>
- <listitem>
- <para>
- The Hildon toolkist is based on GTK+, and is use by
- some mobile devices.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>ALP</term>
- <listitem>
- <para>
- The ALP "Hiker" GUI is used for the Access Linux platform.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
<term>SDL</term>
<listitem>
<para>
@@ -119,7 +117,7 @@
</listitem>
</varlistentry>
<varlistentry>
- <term>KDE</term>
+ <term>QT</term>
<listitem>
<para>
An interface adapted to the KDE Desktop Environment.
@@ -153,21 +151,32 @@
</entry>
</row>
<row>
- <entry><option>--enable-media=ffmpeg|gst|none</option>
+ <entry>
+ <programlisting>
+--enable-media=<handler>[,<handler>]...
+
+ handler can be: ffmpeg
+ gst
+ none
+ </programlisting>
</entry>
- <entry> <para>
- Select the specified media decoder and sound engine.
- FFmpeg uses the SDL sound engine; GST uses its own.
- <option>GST</option> is the default decoder.
+ <entry>
+ <para>
+ Select the specified media decoders.
+ Both ffmpeg and gst use SDL sound engine.
</para>
<para>
- You should only select one media decoder.
+ If option is not given and required dependencies are
+ present, it will build both ffmpeg and gst media
+ handlers. Runtime default will be the first in
+ alphabetical order i.e. ffmpeg.
+ See <option>MediaHandler</option> gnashrc option.
</para></entry>
</row>
<row>
<entry>
- <option>--disable-nsapi</option>
- <option>--enable-nsapi</option>
+ <para><option>--disable-npapi</option></para>
+ <para><option>--enable-npapi</option></para>
</entry>
<entry>Force disable/enable building the NPAPI plugin.
By default the Mozilla plugin is built if the GTK gui
@@ -178,8 +187,8 @@
</row>
<row>
<entry>
- <option>--disable-kparts</option>
- <option>--enable-kparts</option>
+ <para><option>--disable-kparts</option></para>
+ <para><option>--enable-kparts</option></para>
</entry>
<entry>Force disable/enable building the KPARTS plugin. By default the
KDE plugin is built if the kde gui is selected.
@@ -197,7 +206,14 @@
<entry>Disable build of both kparts and npapi plugins</entry>
</row>
<row>
- <entry><option>--enable-renderer=opengl|cairo|agg</option>
+ <entry>
+ <programlisting>
+--enable-renderer=<renderer>[,<renderer>]...
+
+ renderer can be: agg
+ cairo
+ opengl
+ </programlisting>
</entry>
<entry>Enable support for a graphics backend. Currently
only <option>opengl</option> and
diff --git a/extensions/fileio/fileio.cpp b/extensions/fileio/fileio.cpp
index 0854123..cf1cadd 100644
--- a/extensions/fileio/fileio.cpp
+++ b/extensions/fileio/fileio.cpp
@@ -438,7 +438,7 @@ fileio_gets(const fn_call& fn)
assert(ptr);
char buf[BUFSIZE];
memset(buf, 0, BUFSIZE);
- string str = ::gets(buf);
+ string str = ::fgets(buf, BUFSIZE, stdin);
return as_value(buf);
}
diff --git a/gui/Makefile.am b/gui/Makefile.am
index f6a1b63..a3933c3 100644
--- a/gui/Makefile.am
+++ b/gui/Makefile.am
@@ -106,20 +106,21 @@ GTK_LIBS = \
# The following will be filled up later
GUI_CPPFLAGS =
-AM_LDFLAGS = \
- $(INTLLIBS) \
- $(BOOST_LIBS) \
- $(NULL)
-
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
GNASH_LIBS = \
$(top_builddir)/libcore/libgnashcore.la \
$(top_builddir)/libdevice/libgnashdevice.la \
$(top_builddir)/librender/libgnashrender.la \
- $(top_builddir)/libsound/libgnashsound.la \
- $(top_builddir)/libmedia/libgnashmedia.la \
$(top_builddir)/libbase/libgnashbase.la
+if BUILD_LIBMEDIA
+GNASH_LIBS += $(top_builddir)/libmedia/libgnashmedia.la
+endif
+if BUILD_LIBSOUND
+GNASH_LIBS += $(top_builddir)/libsound/libgnashsound.la
+endif
+
if HAVE_VAAPI
GNASH_LIBS += \
$(top_builddir)/libdevice/libgnashvaapi.la \
diff --git a/gui/Player.cpp b/gui/Player.cpp
index 84b9e7d..38d445f 100644
--- a/gui/Player.cpp
+++ b/gui/Player.cpp
@@ -56,6 +56,7 @@
#include "GnashSystemIOHeaders.h" // for write()
#include "log.h"
#include "HostInterface.h"
+#include "RunResources.h"
using namespace gnash;
@@ -427,8 +428,10 @@ Player::run(int argc, char* argv[], const std::string& infile,
// Set the Renderer resource, opengl, openvg, agg, or cairo
_runResources->setRenderBackend(_renderer);
+#ifdef USE_MEDIA
_mediaHandler.reset(media::MediaFactory::instance().get(_media));
-
+#endif
+
if (!_media.empty() && !_mediaHandler.get()) {
boost::format fmt =
boost::format(_("Non-existent media handler %1% specified"))
@@ -542,7 +545,7 @@ Player::run(int argc, char* argv[], const std::string& infile,
if (! _delay) {
float fps = _movieDef->get_frame_rate();
- log_debug(_("Movie Frame Rate is %d, adjusting delay"), fps);
+ // log_debug("Movie Frame Rate is %g, adjusting delay", fps);
// FIXME: this value is arbitrary, and will make any movie with
// less than 12 frames eat up more of the cpu. It should probably
// be a much lower value, like 2.
diff --git a/gui/Player.h b/gui/Player.h
index 039a8b8..d11f0f1 100644
--- a/gui/Player.h
+++ b/gui/Player.h
@@ -24,22 +24,27 @@
#include "gnashconfig.h"
#endif
+#include "HostInterface.h" // for HostInterface, FsCallback, etc
+#include "StringPredicates.h" // for StringNoCaseLessThan
+#include "movie_definition.h"
+
#include <boost/intrusive_ptr.hpp>
#include <string>
#include <boost/shared_ptr.hpp>
#include <map>
#include <memory>
-#include "sound_handler.h"
-#include "MediaHandler.h"
-#include "gui.h"
-#include "movie_definition.h"
-#include "movie_root.h"
-#include "RunResources.h"
-
// Forward declarations
namespace gnash {
class MovieClip;
+ class RunResources;
+ class Gui;
+ namespace media {
+ class MediaHandler;
+ }
+ namespace sound {
+ class sound_handler;
+ }
}
namespace gnash {
diff --git a/gui/dump/dump.am b/gui/dump/dump.am
index 73b1a5e..2c16e73 100644
--- a/gui/dump/dump.am
+++ b/gui/dump/dump.am
@@ -33,4 +33,5 @@ dump_gnash_LDADD = \
$(GNASH_LIBS) \
$(top_builddir)/libdevice/libgnashdevice.la \
$(AGG_LIBS) \
+ $(BOOST_LIBS) \
$(NULL)
diff --git a/gui/dump/dump.cpp b/gui/dump/dump.cpp
index 24b3e29..729f8df 100644
--- a/gui/dump/dump.cpp
+++ b/gui/dump/dump.cpp
@@ -61,6 +61,7 @@
#include "NullSoundHandler.h"
#include "as_environment.h"
#include "as_value.h"
+#include "Movie.h"
namespace gnash {
diff --git a/gui/dump/dump.h b/gui/dump/dump.h
index be0795f..29abea9 100644
--- a/gui/dump/dump.h
+++ b/gui/dump/dump.h
@@ -25,7 +25,6 @@
#include "dsodefs.h" // for DSOEXPORT
#include "gui.h" // for inheritance
-#include "sound_handler.h" // for dtor visibility
#include "ManualClock.h"
#include <string>
@@ -34,6 +33,12 @@
#include <boost/shared_ptr.hpp>
namespace gnash {
+ namespace sound {
+ class sound_handler;
+ }
+}
+
+namespace gnash {
class Renderer_agg_base;
diff --git a/gui/fb/fb.am b/gui/fb/fb.am
index ff43fd3..2182f1b 100644
--- a/gui/fb/fb.am
+++ b/gui/fb/fb.am
@@ -29,11 +29,13 @@ fb_gnash_CPPFLAGS = \
-DGUI_CONFIG=\"FB\" \
-DFAKEFB=\"$(FAKEFB)\" \
$(AM_CPPFLAGS)
-fb_gnash_LDFLAGS = $(LIBLTDL) -export-dynamic $(AM_LDFLAGS)
+fb_gnash_LDFLAGS = $(LIBLTDL) -export-dynamic
fb_gnash_LDADD = \
+ $(INTLLIBS) \
$(GNASH_LIBS) \
$(TS_LIBS) \
- $(BOOST_LIBS)
+ $(BOOST_LIBS) \
+ $(NULL)
# Build support for AntiGrain.
if BUILD_AGG_RENDERER
@@ -51,6 +53,19 @@ fb_gnash_CPPFLAGS += \
fb_gnash_LDADD += $(OPENVG_LIBS) $(EGL_LIBS)
endif # BUILD_OVG_RENDERER
+# Build support for OpenGLES1.
+if BUILD_GLES1_RENDERER
+fb_gnash_SOURCES += fb/fb_glue_gles1.cpp fb/fb_glue_gles1.h
+fb_gnash_CPPFLAGS += \
+ $(GLES1_CFLAGS) \
+ $(EGL_CFLAGS)
+fb_gnash_LDADD += $(GLES1_LIBS) $(EGL_LIBS)
+endif # BUILD_OVG_RENDERER
+
+if ANDROID
+fb_gnash_LDADD += -lui -llog
+endif # ANDROID
+
# # This supports only OpenGLES 1.1 with EGL support.
# if BUILD_GLES1_RENDERER
# fb_gnash_SOURCES += fb/fb_glue_gles1.cpp fb/fb_glue_gles1.h
diff --git a/gui/fb/fb.cpp b/gui/fb/fb.cpp
index f5020da..41153d8 100644
--- a/gui/fb/fb.cpp
+++ b/gui/fb/fb.cpp
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software
// Foundation, Inc
//
// This program is free software; you can redistribute it and/or modify
@@ -126,8 +126,12 @@
#ifdef RENDERER_GLES1
# include "fb_glue_gles1.h"
+# include "opengles1/Renderer_gles1.h"
#endif
+// We need to declare the std::, as the boost header files want to use ptrdiff_t.
+using namespace std;
+
namespace gnash {
namespace gui {
@@ -171,7 +175,7 @@ FBGui::~FBGui()
// GNASH_REPORT_FUNCTION;
if (_fd > 0) {
- enable_terminal();
+ disable_terminal();
// log_debug("Closing framebuffer device");
close(_fd);
}
@@ -193,7 +197,9 @@ FBGui::init(int argc, char *** argv)
renderer = "openvg";
_glue.reset(new FBOvgGlue(0));
// Initialize the glue layer between the renderer and the gui toolkit
- _glue->init(argc, argv);
+ if (!_glue->init(argc, argv)) {
+ return false;
+ }
FBOvgGlue *ovg = reinterpret_cast<FBOvgGlue *>(_glue.get());
// Set "window" size
@@ -207,6 +213,28 @@ FBGui::init(int argc, char *** argv)
}
#endif
+#ifdef RENDERER_GLES1
+ if ((renderer == "opengles1") || (renderer == "gles1")) {
+ renderer = "opengles1";
+ _glue.reset(new FBgles1Glue(0));
+ // Initialize the glue layer between the renderer and the gui toolkit
+ if (!_glue->init(argc, argv)) {
+ return false;
+ }
+
+ FBgles1Glue *gles1 = reinterpret_cast<FBgles1Glue *>(_glue.get());
+ // Set "window" size
+ _width = gles1->getWidth();
+ _height = gles1->getHeight();
+ log_debug("Width:%d, Height:%d", _width, _height);
+ //_renderer.reset(create_render_handler_gles1(true, _glue));
+ _renderer.reset(renderer::gles1::create_handler(""));
+ // renderer::openvg::Renderer_gles1 *rend = reinterpret_cast
+ // <renderer::openvg::Renderer_ovg *>(_renderer.get());
+ // rend->init(_width, _height);
+ }
+#endif
+
// map framebuffer into memory
// Create a new Glue layer
#ifdef RENDERER_AGG
@@ -230,7 +258,8 @@ FBGui::init(int argc, char *** argv)
}
disable_terminal();
-
+
+#ifdef HAVE_LINUX_UINPUT_H
// Look for the User Mode Input (Uinput) device, which is used to
// control the movement and coordinates of the mouse cursor.
if (_uinput.scanForDevice()) {
@@ -239,7 +268,8 @@ FBGui::init(int argc, char *** argv)
} else {
log_error(_("Found no accessible User mode input event device"));
}
-
+#endif
+
// Initialize all the input devices
// Look for Mice that use the PS/2 mouse protocol
@@ -291,7 +321,7 @@ FBGui::init(int argc, char *** argv)
}
// Let -j -k override "window" size
- optind = 0; opterr = 0; char c;
+ optind = 0; opterr = 0; int c;
while ((c = getopt (argc, *argv, "j:k:X:Y:")) != -1) {
switch (c) {
case 'j':
@@ -314,11 +344,11 @@ FBGui::init(int argc, char *** argv)
// should be able to support this, but right now it just gets in
// the way of debugging.
- if ( _xpos < 0 ) _xpos += _var_screeninfo.xres - _width;
- _xpos = clamp<int>(_xpos, 0, _var_screeninfo.xres-_width);
+ if ( _xpos < 0 ) _xpos += _varinfo.xres - _width;
+ _xpos = clamp<int>(_xpos, 0, _varinfo.xres-_width);
- if ( _ypos < 0 ) _ypos += _var_screeninfo.yres - _height;
- _ypos = clamp<int>(_ypos, 0, _var_screeninfo.yres-_height);
+ if ( _ypos < 0 ) _ypos += _varinfo.yres - _height;
+ _ypos = clamp<int>(_ypos, 0, _varinfo.yres-_height);
log_debug("X:%d, Y:%d", _xpos, _ypos);
#endif
@@ -345,7 +375,7 @@ FBGui::run()
// GNASH_REPORT_FUNCTION;
#ifdef USE_TSLIB
- int ts_loop_count;
+ int ts_loop_count = 0;
#endif
VirtualClock& timer = getClock();
@@ -365,8 +395,8 @@ FBGui::run()
// 10ms per heart beat
delay = 10000;
}
- log_debug(_("Movie Frame Rate is %d, adjusting delay to %dms"), fps,
- _interval * delay);
+ // log_debug(_("Movie Frame Rate is %d, adjusting delay to %dms"), fps,
+ // _interval * delay);
// This loops endlessly at the frame rate
while (!terminate_request) {
@@ -500,7 +530,7 @@ FBGui::find_accessible_tty(int no)
fn = find_accessible_tty("/dev/tty%x", no); if (fn) return fn;
fn = find_accessible_tty("/dev/tty%02d", no); if (fn) return fn;
- if (no==0) {
+ if (no == 0) {
fn = find_accessible_tty("/dev/tty", no); // just "/dev/tty"
if (fn) return fn;
}
@@ -532,6 +562,8 @@ FBGui::disable_terminal()
// Find the TTY device name
char* tty = find_accessible_tty(0);
+
+ log_debug("Disabling terminal %s", tty);
int fd;
@@ -661,6 +693,8 @@ FBGui::enable_terminal()
// log_debug("Restoring terminal...");
char* tty = find_accessible_tty(_own_vt);
+ log_debug("Enabling terminal %s", tty);
+
if (!tty) {
log_error(_("Could not find device for VT number %d"), _own_vt);
return false;
@@ -724,11 +758,13 @@ FBGui::checkForData()
InputDevice::convertAbsCoords(ie->x, ie->y,
getStage()->getStageWidth(),
getStage()->getStageHeight());
+#ifdef HAVE_LINUX_UINPUT_H
// The mouse was moved
_uinput.moveTo(coords[0], coords[1]);
if (coords) {
notifyMouseMove(coords[0], coords[1]);
}
+#endif
// See if a mouse button was clicked
if (ie->pressed) {
diff --git a/gui/fb/fb_glue_agg.cpp b/gui/fb/fb_glue_agg.cpp
index 9eaa8f2..6fb60fd 100644
--- a/gui/fb/fb_glue_agg.cpp
+++ b/gui/fb/fb_glue_agg.cpp
@@ -180,7 +180,7 @@ FBAggGlue::createRenderHandler()
agg_handler = create_Renderer_agg(pixelformat);
} else {
log_error(_("The pixel format of your framebuffer could not be detected."));
- return false;
+ return 0;
}
assert(agg_handler != NULL);
@@ -196,12 +196,12 @@ FBAggGlue::createRenderHandler()
}
// This attaches the memory from the device to the AGG renderer
- agg_handler->init_buffer((unsigned char *)mem, rawfb->getFBMemSize(),
+ agg_handler->init_buffer(mem, rawfb->getFBMemSize(),
width, height, rawfb->getStride());
_renderer.reset(agg_handler);
- return (Renderer *)agg_handler;
+ return agg_handler;
}
void
diff --git a/gui/fb/fb_glue_gles1.cpp b/gui/fb/fb_glue_gles1.cpp
index 16ea2f1..28e183d 100644
--- a/gui/fb/fb_glue_gles1.cpp
+++ b/gui/fb/fb_glue_gles1.cpp
@@ -100,34 +100,42 @@ FBgles1Glue::init(int /*argc*/, char *** /*argv*/)
result = eglInitialize(_display, &majorVersion, &minorVersion);
if (result == EGL_FALSE) {
return false;
+ } else {
+ log_trace(_("EGL: initialize ok"));
}
- log_trace(_("EGL: initialize ok"));
result = eglChooseConfig(_display, main_attrib_list, &_config, 1,
&numOfConfigs);
if (result == EGL_FALSE || numOfConfigs != 1) {
return false;
+ } else {
+ log_trace(_("EGL: config ok"));
}
- log_trace(_("EGL: config ok"));
_surface = eglCreateWindowSurface(_display, _config, (NativeWindowType)0,
NULL);
if (eglGetError () != EGL_SUCCESS) {
- return false;
+ log_error("FIXME: eglCreateWindowSurface failed! %d", eglGetError());
+ // return false;
+ } else {
+ log_trace(_("EGL: surface ok"));
}
- log_trace(_("EGL: surface ok"));
_context = eglCreateContext(_display, _config, NULL, NULL);
if (eglGetError () != EGL_SUCCESS) {
- return false;
+ log_error("FIXME: eglCreateContext failed! %d", eglGetError());
+ // return false;
+ } else {
+ log_trace(_("EGL: context ok"));
}
- log_trace(_("EGL: context ok"));
eglMakeCurrent(_display, _surface, _surface, _context);
if (eglGetError () != EGL_SUCCESS) {
- return false;
+ log_error("FIXME: eglMakeCurrent failed! %d", eglGetError());
+ // return false;
+ } else {
+ log_trace(_("EGL: current ok"));
}
- log_trace(_("EGL: current ok"));
const EGLint pbuffer_config_list[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
@@ -158,8 +166,9 @@ FBgles1Glue::init(int /*argc*/, char *** /*argv*/)
pbuffer_attrib_list);
if (eglGetError () != EGL_SUCCESS) {
return false;
+ } else {
+ log_trace("EGL: pbuffer surface ok");
}
- log_trace("EGL: pbuffer surface ok");
return true;
}
@@ -203,6 +212,15 @@ FBgles1Glue::render_to_display () {
eglMakeCurrent(_display, _surface, _surface, _context);
}
+void
+FBgles1Glue::prepDrawingArea(void * /*drawing_area */)
+{
+ // GNASH_REPORT_FUNCTION;
+
+ // _device->attachWindow(reinterpret_cast
+ // <renderer::GnashDevice::native_window_t>(drawing_area));
+}
+
} // end of namespace gui
} // namespace gnash
diff --git a/gui/fb/fb_glue_gles1.h b/gui/fb/fb_glue_gles1.h
index b984703..b7e7daa 100644
--- a/gui/fb/fb_glue_gles1.h
+++ b/gui/fb/fb_glue_gles1.h
@@ -43,6 +43,13 @@
#endif
#endif
+#include "fbsup.h"
+#include "fb_glue.h"
+
+#ifdef BUILD_EGL_DEVICE
+# include "egl/eglDevice.h"
+#endif
+
#include <boost/scoped_ptr.hpp>
#include "fbsup.h"
@@ -70,6 +77,13 @@ public:
void render_to_pbuffer ();
void prepare_copy_from_pbuffer ();
void render_to_display ();
+ /// \brief
+ /// Hand off a handle to the native drawing area to the renderer
+ void prepDrawingArea(void *drawing_area);
+
+ void initBuffer(int width, int height);
+ void resize(int width, int height);
+ // void render(geometry::Range2d<int>& bounds);
protected:
int _fd;
diff --git a/gui/fb/fb_glue_ovg.cpp b/gui/fb/fb_glue_ovg.cpp
index f723476..13e2175 100644
--- a/gui/fb/fb_glue_ovg.cpp
+++ b/gui/fb/fb_glue_ovg.cpp
@@ -109,14 +109,15 @@ FBOvgGlue::init(int argc, char **argv[])
_device.reset(new renderer::EGLDevice(argc, *argv));
// Initialize the display device
- // EGL still reqires us to open the framebuffer
+ // EGL still reqires us to open the framebuffer, except on Android
_device->bindClient(renderer::GnashDevice::OPENVG);
-
+
+#ifndef __ANDROID__
_display.initDevice(0, 0);
_width = getWidth();
_height = getHeight();
-
+
// Some linux distros like ltib have more information available
// about the framebuffer
int fd = ::open("/sys/class/graphics/fb0/stride", O_RDONLY);
@@ -136,6 +137,9 @@ FBOvgGlue::init(int argc, char **argv[])
// framebuffer when creating a window. Under X11, this is
// actually the XID of the created window.
return _device->attachWindow(_display.getHandle());
+#else
+ return _device->attachWindow(0);
+#endif
}
Renderer*
diff --git a/gui/fb/fbsup.h b/gui/fb/fbsup.h
index f505403..eeb5e8d 100644
--- a/gui/fb/fbsup.h
+++ b/gui/fb/fbsup.h
@@ -202,7 +202,9 @@ private:
std::vector<boost::shared_ptr<InputDevice> > _inputs;
boost::shared_ptr<Renderer> _renderer;
+#ifdef HAVE_LINUX_UINPUT_H
UinputDevice _uinput;
+#endif
};
} // end of namespace gui
diff --git a/gui/gnash.cpp b/gui/gnash.cpp
index b1e05f4..f99ce50 100644
--- a/gui/gnash.cpp
+++ b/gui/gnash.cpp
@@ -311,8 +311,9 @@ getSupportedOptions(gnash::Player& p)
using gnash::RcInitFile;
std::vector<std::string> handlers;
+#ifdef USE_MEDIA
gnash::media::MediaFactory::instance().listKeys(back_inserter(handlers));
-
+#endif
std::vector<std::string> renderers;
boost::split(renderers, RENDERER_CONFIG,
boost::is_any_of(" "), boost::token_compress_on);
@@ -518,7 +519,7 @@ version_and_copyright(std::ostream& os)
<< VERSION " ("
<< BRANCH_NICK << "-" << BRANCH_REVNO << "-" << COMMIT_ID
<< ")" << endl << endl
- << _("Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 "
+ << _("Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 "
"Free Software Foundation, Inc.\n"
"Gnash comes with NO WARRANTY, to the extent permitted "
"by law.\nYou may redistribute copies of Gnash under the "
diff --git a/gui/gtk/gtk.am b/gui/gtk/gtk.am
index b4e3604..7f3e3a1 100644
--- a/gui/gtk/gtk.am
+++ b/gui/gtk/gtk.am
@@ -28,12 +28,13 @@ gtk_gnash_SOURCES = $(GUI_SRCS) $(GTK_CANVAS) \
gtk/gtk.cpp gtk/gtksup.h gtk/gtk_glue.h gtk/gui_gtk.cpp
gtk_gnash_CPPFLAGS = -DGUI_GTK -DGUI_CONFIG=\"GTK\" \
$(AM_CPPFLAGS) $(GTK_CFLAGS) $(X11_CFLAGS)
-gtk_gnash_LDFLAGS = -export-dynamic $(AM_LDFLAGS)
+gtk_gnash_LDFLAGS = -export-dynamic
gtk_gnash_LDADD = \
$(top_builddir)/librender/libgnashrender.la \
$(GNASH_LIBS) \
$(GTK_LIBS) \
- $(BZ2_LIBS) \
+ $(INTLLIBS) \
+ $(BOOST_LIBS) \
$(NULL)
#gtk_gnash_DEPENDENCIES = .configline
diff --git a/gui/gtk/gtk.cpp b/gui/gtk/gtk.cpp
index da45af7..0db93c0 100644
--- a/gui/gtk/gtk.cpp
+++ b/gui/gtk/gtk.cpp
@@ -597,7 +597,7 @@ GtkGui::startAdvanceTimer()
(GSourceFunc)advance_movie, this, NULL);
log_debug(_("Advance interval timer set to %d ms (~ %d FPS)"),
- _interval, 1000/_interval);
+ _interval, _interval ? 1000/_interval : 1000);
}
/*private*/
@@ -1875,7 +1875,7 @@ GtkGui::showAboutDialog()
gtk_about_dialog_set_version(about, version.c_str());
gtk_about_dialog_set_copyright(about, "Copyright (C) 2005, 2006, 2007, "
- "2008, 2009, 2010, 2011 The Free Software Foundation");
+ "2008, 2009, 2010, 2011, 2012, 2013 The Free Software Foundation");
gtk_about_dialog_set_comments (about, comments.c_str());
gtk_about_dialog_set_authors(about, authors);
gtk_about_dialog_set_documenters(about, documentors);
@@ -1891,7 +1891,7 @@ GtkGui::showAboutDialog()
gtk_widget_show (aboutWidget);
- if (logo_pixbuf) gdk_pixbuf_unref(logo_pixbuf);
+ if (logo_pixbuf) g_object_unref(logo_pixbuf);
}
///////////////////////////////////////////////////////////////////////////////
@@ -2241,7 +2241,7 @@ addGnashIcon(GtkWindow* window)
GdkPixbuf *window_icon_pixbuf = createPixbuf ("GnashG.png");
if (window_icon_pixbuf) {
gtk_window_set_icon (GTK_WINDOW (window), window_icon_pixbuf);
- gdk_pixbuf_unref (window_icon_pixbuf);
+ g_object_unref (window_icon_pixbuf);
}
}
diff --git a/gui/gtk/gtk_canvas.h b/gui/gtk/gtk_canvas.h
index c461b37..13d5bc9 100644
--- a/gui/gtk/gtk_canvas.h
+++ b/gui/gtk/gtk_canvas.h
@@ -57,10 +57,11 @@ void gnash_canvas_setup (GnashCanvas *canvas, std::string &hwaccel,
void gnash_canvas_before_rendering (GnashCanvas *canvas, gnash::movie_root* stage);
+G_END_DECLS
+
/// Get the Renderer for this canvas
boost::shared_ptr<gnash::Renderer> gnash_canvas_get_renderer(GnashCanvas *canvas);
-G_END_DECLS
#endif
diff --git a/gui/gui.cpp b/gui/gui.cpp
index 73f78cc..2f25fb6 100644
--- a/gui/gui.cpp
+++ b/gui/gui.cpp
@@ -38,6 +38,7 @@
#include "RunResources.h"
#include "StreamProvider.h"
#include "ScreenShotter.h"
+#include "Movie.h"
#ifdef GNASH_FPS_DEBUG
#include "ClockTime.h"
@@ -455,15 +456,16 @@ Gui::toggleSound()
assert (_stage);
// @todo since we registered the sound handler, shouldn't we know
// already what it is ?!
+#ifdef USE_SOUND
sound::sound_handler* s = _stage->runResources().soundHandler();
-
+
if (!s) return;
if (s->is_muted()) s->unmute();
else s->mute();
+#endif // USE_SOUND
}
-
void
Gui::notifyMouseMove(int ux, int uy)
{
@@ -834,11 +836,12 @@ Gui::play()
start();
} else {
assert (_stage);
+#ifdef USE_SOUND
// @todo since we registered the sound handler, shouldn't we know
// already what it is ?!
sound::sound_handler* s = _stage->runResources().soundHandler();
if ( s ) s->unpause();
-
+#endif // USE_SOUND
// log_debug("Starting virtual clock");
_virtualClock.resume();
}
@@ -912,6 +915,7 @@ Gui::start()
// @todo since we registered the sound handler, shouldn't we know
// already what it is ?!
+#ifdef USE_SOUND
sound::sound_handler* s = _stage->runResources().soundHandler();
if ( s ) {
if ( ! _audioDump.empty() ) {
@@ -919,8 +923,9 @@ Gui::start()
}
s->unpause();
}
+#endif // USE_SOUND
_started = true;
-
+
// log_debug("Starting virtual clock");
_virtualClock.resume();
diff --git a/gui/gui.h b/gui/gui.h
index 2c2c54c..69ec79e 100644
--- a/gui/gui.h
+++ b/gui/gui.h
@@ -25,16 +25,12 @@
#include <boost/intrusive_ptr.hpp>
#include <boost/scoped_ptr.hpp>
-#include <boost/function.hpp>
#include <string>
#include <map>
#include <utility>
-#include "SWFRect.h" // for composition
#include "snappingrange.h" // for InvalidatedRanges
-#include "ScreenShotter.h"
#include "GnashKey.h"
-#include "Renderer.h"
#include "VirtualClock.h"
#include "SystemClock.h"
#include "GnashEnums.h"
@@ -71,6 +67,11 @@ namespace gnash {
class RunResources;
class movie_root;
class movie_definition;
+ class Renderer;
+ class SWFRect;
+}
+namespace boost {
+ template <typename Signature> class function;
}
namespace gnash {
diff --git a/gui/pythonmod/gnash-view.cpp b/gui/pythonmod/gnash-view.cpp
index fd7cbb6..02dde2a 100644
--- a/gui/pythonmod/gnash-view.cpp
+++ b/gui/pythonmod/gnash-view.cpp
@@ -37,6 +37,7 @@
#include "VirtualClock.h"
#include "SystemClock.h"
#include "DisplayObject.h"
+#include "Movie.h"
#include "Global_as.h"
#include "NamingPolicy.h"
#include "StreamProvider.h"
diff --git a/gui/qt/Qt4Gui.cpp b/gui/qt/Qt4Gui.cpp
index b3375f6..7b7af5e 100644
--- a/gui/qt/Qt4Gui.cpp
+++ b/gui/qt/Qt4Gui.cpp
@@ -67,6 +67,7 @@
#include "Qt4Gui.moc"
#include "Renderer.h"
#include "RunResources.h"
+#include "GnashException.h"
// Macro for using gettext strings where Qt expects QStrings
#define _q(Str) QString::fromUtf8(_(Str))
@@ -81,6 +82,7 @@ namespace gnash
Qt4Gui::Qt4Gui(unsigned long xid, float scale, bool loop, RunResources& r)
:
Gui(xid, scale, loop, r),
+ _numArgs(0),
_interval(0),
_advanceTimer(0)
{
@@ -103,9 +105,8 @@ bool
Qt4Gui::init(int /*argc*/, char ** /*argv*/[])
{
char** r = NULL;
- int* i = new int(0);
- _application.reset(new QApplication(*i, r));
+ _application.reset(new QApplication(_numArgs, r));
_window.reset(new QMainWindow());
_embedWidget = new EmbedWidget(*this);
_drawingWidget = _embedWidget->drawingWidget();
diff --git a/gui/qt/Qt4Gui.h b/gui/qt/Qt4Gui.h
index deba84f..6d18017 100644
--- a/gui/qt/Qt4Gui.h
+++ b/gui/qt/Qt4Gui.h
@@ -136,6 +136,9 @@ private:
void playHook();
DrawBounds _drawbounds;
+
+ /// argc provided to QApplication.
+ int _numArgs;
/// The main application, which should destroy everything
/// left on closing.
diff --git a/gui/qt/qt4.am b/gui/qt/qt4.am
index 5366a8e..d6793bd 100644
--- a/gui/qt/qt4.am
+++ b/gui/qt/qt4.am
@@ -54,6 +54,7 @@ qt4_gnash_LDFLAGS = -export-dynamic
qt4_gnash_LDADD = \
$(GNASH_LIBS) \
$(AM_LDFLAGS) \
+ $(BOOST_LIBS) \
$(X11_LIBS) \
$(NULL)
diff --git a/gui/sdl/sdl.am b/gui/sdl/sdl.am
index 9c256ff..5f94b07 100644
--- a/gui/sdl/sdl.am
+++ b/gui/sdl/sdl.am
@@ -33,7 +33,10 @@ sdl_gnash_LDFLAGS = -export-dynamic
sdl_gnash_LDADD = \
$(GNASH_LIBS) \
$(AM_LDFLAGS) \
- $(SDL_LIBS)
+ $(SDL_LIBS) \
+ $(INTLLIBS) \
+ $(BOOST_LIBS) \
+ $(NULL)
if BUILD_OGL_RENDERER
sdl_gnash_CPPFLAGS += $(OPENGL_CFLAGS)
diff --git a/gui/sdl/sdl_agg_glue.cpp b/gui/sdl/sdl_agg_glue.cpp
index 3ae8073..df37caa 100644
--- a/gui/sdl/sdl_agg_glue.cpp
+++ b/gui/sdl/sdl_agg_glue.cpp
@@ -185,11 +185,14 @@ SdlAggGlue::render()
void
SdlAggGlue::render(int minx, int miny, int maxx, int maxy)
{
- // Update only the invalidated rectangle
- SDL_Rect clip = { minx, miny, maxx - minx, maxy - miny };
- SDL_SetClipRect(_screen, &clip);
- SDL_BlitSurface(_sdl_surface, 0, _screen, 0);
- SDL_UpdateRect(_screen, clip.x, clip.y, clip.w, clip.h);
+ // Update only the invalidated rectangle
+ SDL_Rect clip = { static_cast<Sint16>(minx),
+ static_cast<Sint16>(miny),
+ static_cast<Uint16>(maxx - minx),
+ static_cast<Uint16>(maxy - miny)};
+ SDL_SetClipRect(_screen, &clip);
+ SDL_BlitSurface(_sdl_surface, 0, _screen, 0);
+ SDL_UpdateRect(_screen, clip.x, clip.y, clip.w, clip.h);
}
} // namespace gnash
diff --git a/libbase/BitsReader.h b/libbase/BitsReader.h
index 180a5c8..83c3391 100644
--- a/libbase/BitsReader.h
+++ b/libbase/BitsReader.h
@@ -155,7 +155,7 @@ public:
}
/// Checks if the stream contains X bits
- bool gotBits(boost::uint32_t nbits)
+ bool gotBits(boost::uint32_t nbits) const
{
boost::uint32_t gotbits = 8-usedBits +8*(end-ptr-1);
if (gotbits > nbits) return true;
diff --git a/libbase/GnashImage.cpp b/libbase/GnashImage.cpp
index 03a6939..e08071c 100644
--- a/libbase/GnashImage.cpp
+++ b/libbase/GnashImage.cpp
@@ -301,18 +301,25 @@ Input::readSWFJpeg3(boost::shared_ptr<IOChannel> in)
im.reset(new ImageRGBA(width, height));
- boost::scoped_array<GnashImage::value_type> line(
+ if (j_in->imageType() == TYPE_RGBA) {
+
+ for (size_t y = 0; y < height; ++y) {
+ j_in->readScanline(scanline(*im, y));
+ }
+ } else {
+ boost::scoped_array<GnashImage::value_type> line(
new GnashImage::value_type[3 * width]);
- for (size_t y = 0; y < height; ++y) {
- j_in->readScanline(line.get());
+ for (size_t y = 0; y < height; ++y) {
+ j_in->readScanline(line.get());
- GnashImage::iterator data = scanline(*im, y);
- for (size_t x = 0; x < width; ++x) {
- data[4*x+0] = line[3*x+0];
- data[4*x+1] = line[3*x+1];
- data[4*x+2] = line[3*x+2];
- data[4*x+3] = 255;
+ GnashImage::iterator data = scanline(*im, y);
+ for (size_t x = 0; x < width; ++x) {
+ data[4*x+0] = line[3*x+0];
+ data[4*x+1] = line[3*x+1];
+ data[4*x+2] = line[3*x+2];
+ data[4*x+3] = 255;
+ }
}
}
diff --git a/libbase/GnashImageGif.cpp b/libbase/GnashImageGif.cpp
index eeba4b7..26865c1 100644
--- a/libbase/GnashImageGif.cpp
+++ b/libbase/GnashImageGif.cpp
@@ -269,7 +269,17 @@ GifInput::processRecord(GifRecordType record)
void
GifInput::read()
{
+#if GIFLIB_MAJOR >= 5
+ int errorCode;
+ _gif = DGifOpen(_inStream.get(), &readData, &errorCode);
+#else
_gif = DGifOpen(_inStream.get(), &readData);
+#endif
+
+ if ( ! _gif ) {
+ // TODO: decode errorCode if available
+ throw ParserException("Could not open input GIF stream");
+ }
GifRecordType record;
diff --git a/libbase/GnashImageJpeg.cpp b/libbase/GnashImageJpeg.cpp
index 3ac4e24..8a6c0f3 100644
--- a/libbase/GnashImageJpeg.cpp
+++ b/libbase/GnashImageJpeg.cpp
@@ -83,7 +83,6 @@ public:
// Constructor.
explicit rw_source_IOChannel(boost::shared_ptr<IOChannel> in)
:
- _ownSourceStream(false),
m_in_stream(in),
m_start_of_file(true)
{
@@ -203,8 +202,6 @@ private:
m_pub.next_input_byte = NULL;
}
- const bool _ownSourceStream;
-
// Source stream
boost::shared_ptr<IOChannel> m_in_stream;
bool m_start_of_file;
@@ -352,7 +349,7 @@ JpegInput::read()
// Until this point the type should be GNASH_IMAGE_INVALID.
// It's possible to create transparent JPEG data by merging an
// alpha channel, but that is handled explicitly elsewhere.
- _type = TYPE_RGB;
+ _type = getComponents() == 4 ? TYPE_RGBA : TYPE_RGB;
}
diff --git a/libbase/GnashNumeric.h b/libbase/GnashNumeric.h
index f172789..c92a2bd 100644
--- a/libbase/GnashNumeric.h
+++ b/libbase/GnashNumeric.h
@@ -35,6 +35,7 @@
#include <boost/cstdint.hpp>
#include <limits>
#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
namespace gnash {
@@ -56,6 +57,14 @@ isFinite(double d)
#endif
}
+template <typename T>
+inline
+typename boost::enable_if<boost::is_floating_point<T>, bool>::type
+isNaN(const T& num)
+{
+ return num != num;
+}
+
inline double
infinite_to_zero(double x)
{
@@ -66,8 +75,8 @@ template <typename T>
inline T
clamp(T i, T min, T max)
{
- assert(min <= max);
- return std::max<T>(min, std::min<T>(i, max));
+ assert(min <= max);
+ return std::max<T>(min, std::min<T>(i, max));
}
template<typename T>
@@ -86,13 +95,19 @@ frnd(float f)
inline double
twipsToPixels(int i)
{
- return static_cast<double>(i / 20.0);
+ return i / 20.0;
}
template<size_t Factor>
boost::int32_t
truncateWithFactor(double a)
-{
+{
+ // If a is NaN, then this function would return -NAN, which when cast to
+ // int32, converts to zero on x86*, but converts to -1 on ARM. The
+ // behaviour is undefined according to ISO-IEC 14882:2003 4.9.1.
+ if (isNaN(a)) {
+ return 0;
+ }
const double factor = static_cast<double>(Factor);
diff --git a/libbase/GnashScopedPtr.h b/libbase/GnashScopedPtr.h
new file mode 100644
index 0000000..f5fc813
--- /dev/null
+++ b/libbase/GnashScopedPtr.h
@@ -0,0 +1,85 @@
+// GnashSmartPtr.h: scoped pointer supporting deleters.
+//
+// Copyright (C) 2013
+// 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifndef GNASH_SCOPED_PTR_H
+#define GNASH_SCOPED_PTR_H
+
+#include <boost/utility.hpp> // noncopyable
+#include <boost/function.hpp>
+
+namespace gnash {
+
+/// ScopedPtr is very similar to scoped_ptr, but includes the Deleter
+/// functionality from shared_ptr. ScopedPtr can be used to implement the RAII
+/// pattern for C APIs, which frequently have their own deallocation strategy,
+/// when shared_ptr semantics are not desirable.
+//
+/// ScopedPtr is similar to C++11's unique_ptr, but the deleter is not part of
+/// the type.
+template <typename T>
+class ScopedPtr : private boost::noncopyable
+{
+private:
+ typedef boost::function<void(T* x)> DeleterT;
+public:
+
+ /// Construct a ScopedPtr and provide a deleter.
+ ///
+ /// @ptr the pointer to exclusively manage.
+ /// @deleter the deleter to call when this object goes out of scope.
+ /// The expression d(ptr) must be well-formed.
+ explicit ScopedPtr(T* ptr, DeleterT d)
+ : _ptr(ptr),
+ _deleter(d)
+ {}
+
+ /// Dereferences the managed pointer and returns a reference.
+ T& operator*() const
+ {
+ return *_ptr;
+ }
+
+ /// Dereference the contained pointer.
+ T* operator->() const
+ {
+ return _ptr;
+ }
+
+ /// Obtain the contained pointer.
+ T* get() const
+ {
+ return _ptr;
+ }
+
+ ~ScopedPtr()
+ {
+ if (_ptr) {
+ _deleter(_ptr);
+ }
+ }
+private:
+
+ T* _ptr;
+ DeleterT _deleter;
+};
+
+} // namespace gnash
+
+#endif
diff --git a/libbase/IOChannel.cpp b/libbase/IOChannel.cpp
index 0e02298..1cf6278 100644
--- a/libbase/IOChannel.cpp
+++ b/libbase/IOChannel.cpp
@@ -69,7 +69,7 @@ IOChannel::read_float32()
boost::uint32_t i;
} u;
- BOOST_STATIC_ASSERT(sizeof(u) == sizeof(u.i));
+ BOOST_STATIC_ASSERT(sizeof(u) == sizeof(u.i)) __attribute__((unused));
u.i = read_le32();
return u.f;
diff --git a/libbase/IOChannel.h b/libbase/IOChannel.h
index c9fa353..50a76cd 100644
--- a/libbase/IOChannel.h
+++ b/libbase/IOChannel.h
@@ -23,7 +23,6 @@
#include <string>
#include <boost/cstdint.hpp> // for boost int types
-#include <iosfwd>
#include "dsodefs.h" // DSOEXPORT
#include "GnashException.h" // for IOException inheritance
diff --git a/libbase/Makefile.am b/libbase/Makefile.am
index ae1b505..12b6a4c 100644
--- a/libbase/Makefile.am
+++ b/libbase/Makefile.am
@@ -46,6 +46,7 @@ libgnashbase_la_SOURCES = \
GnashImageJpeg.cpp \
GnashImageJpeg.h \
GnashNumeric.h \
+ GnashScopedPtr.h \
GnashSleep.h \
GnashSystemFDHeaders.h \
GnashSystemIOHeaders.h \
@@ -93,11 +94,7 @@ libgnashbase_la_SOURCES = \
if JEMALLOC
libgnashbase_la_SOURCES += \
- jemalloc.c \
- jemalloc.h \
- jemalloc_gnash.h \
- jemalloc_rb.h \
- jemalloc_types.h \
+ jemalloc_gnash.c \
$(NULL)
endif
@@ -164,13 +161,10 @@ libgnashbase_la_CPPFLAGS = -DPLUGINSDIR=\"$(pluginsdir)\" \
$(BOOST_CFLAGS) \
$(OPENGL_CFLAGS) \
$(LTDL_CFLAGS) \
+ $(JEMALLOC_CFLAGS) \
-I$(top_srcdir)/librender \
$(NULL)
-if ANDROID
-libgnashbase_la_CPPFLAGS += $(ANDROID_NDK)/usr/include
-endif
-
libgnashbase_la_LIBADD = \
$(JPEG_LIBS) \
$(PNG_LIBS) \
@@ -180,10 +174,17 @@ libgnashbase_la_LIBADD = \
$(LIBINTL) \
$(BOOST_LIBS) \
$(OPENGL_LIBS) \
+ $(OPENVG_LIBS) \
+ $(EGL_LIBS) \
$(PTHREAD_LIBS) \
$(LTDL_LIBS) \
+ $(JEMALLOC_LIBS) \
$(NULL)
+if ANDROID
+libgnashbase_la_LIBADD += -lui -llog
+endif # ANDROID
+
if HAIKU
libgnashbase_la_LIBADD += $(HAIKU_LIBS)
endif
@@ -192,10 +193,6 @@ inst_HEADERS = \
accumulator.h \
SimpleBuffer.h \
GnashNumeric.h \
- jemalloc_gnash.h \
- jemalloc_types.h \
- jemalloc_rb.h \
- jemalloc.h \
GnashSleep.h \
gmemory.h \
SharedMem.h \
@@ -203,6 +200,7 @@ inst_HEADERS = \
tu_file.h \
IOChannel.h \
Socket.h \
+ GnashScopedPtr.h \
GnashSystemFDHeaders.h \
GnashSystemNetHeaders.h \
GnashSystemIOHeaders.h \
@@ -278,8 +276,11 @@ if WIN32
libgnashbase_la_LIBADD += -lws2_32 -lwinmm
endif
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
+AM_LDFLAGS = $(CROSS_LDFLAGS)
+
if ENABLE_PCH
-AM_CXXFLAGS = $(PCH_FLAGS)
+AM_CXXFLAGS += $(PCH_FLAGS)
endif
edit = sed \
diff --git a/libbase/RTMP.cpp b/libbase/RTMP.cpp
index f02c91c..cc5046f 100644
--- a/libbase/RTMP.cpp
+++ b/libbase/RTMP.cpp
@@ -382,8 +382,6 @@ RTMP::readSocket(boost::uint8_t* buffer, int n)
sendBytesReceived(this);
log_debug("Sent bytes received");
}
-
- buffer += bytesRead;
return bytesRead;
}
diff --git a/libbase/Range2d.h b/libbase/Range2d.h
index ed81b3f..c1cac0b 100644
--- a/libbase/Range2d.h
+++ b/libbase/Range2d.h
@@ -809,7 +809,7 @@ Range2d<int>::roundMax(float max) const
template<> inline unsigned int
Range2d<unsigned int>::roundMax(float max) const
{
- return static_cast<unsigned int>(std::ceil(static_cast<float>(max)));
+ return static_cast<unsigned int>(std::ceil(max));
}
/// Specialization of area value for int type.
diff --git a/libbase/SharedMem.cpp b/libbase/SharedMem.cpp
index 303dc63..8ad78af 100644
--- a/libbase/SharedMem.cpp
+++ b/libbase/SharedMem.cpp
@@ -35,6 +35,7 @@
#endif
#include "log.h"
+#include "GnashSleep.h"
#if (defined(HAVE_SHMGET))
# define ENABLE_SHARED_MEM 1
@@ -105,69 +106,104 @@ SharedMem::unlock() const
}
bool
-SharedMem::attach()
+SharedMem::getSemaphore()
{
-#if !ENABLE_SHARED_MEM
-# error "You need SYSV Shared memory support to use this option"
-#endif
-
- // Don't try to attach twice.
- if (_addr) return true;
-
- _shmkey = rcfile.getLCShmKey();
-
- // Check rcfile for key; if there isn't one, use the Adobe key.
- if (_shmkey == 0) {
- log_debug("No shared memory key specified in rcfile. Using default for communication with other players");
- _shmkey = 0xdd3adabd;
- }
-
- log_debug("Using shared memory key %s",
- boost::io::group(std::hex, std::showbase, _shmkey));
-
- // First get semaphore.
-
- // Check if it exists already.
- _semid = ::semget(_shmkey, 1, 0600);
-
#ifndef __amigaos4__
// Struct for semctl
union semun {
int val;
- struct semi_ds* buf;
+ struct semid_ds* buf;
unsigned short* array;
};
#endif
semun s;
- // If it does not exist, create it and set its value to 1.
- if (_semid < 0) {
-
- _semid = ::semget(_shmkey, 1, IPC_CREAT | 0600);
+ // We employ the textbook solution to the race condition during creation
+ // and initialization of the semaphore: Create the semaphore with IPC_EXCL
+ // so that for the first process, creation will succeed, but for any
+ // concurrent process it will fail with EEXIST. Then, once the first
+ // process is finished initializing the semaphore, semop is called (in our
+ // case by calling lock()) which modifies semid_ds::otime, and the
+ // concurrent process knows it can proceed with using the semaphore
+ // (provided it obtains a lock.)
+ _semid = ::semget(_shmkey, 1, IPC_CREAT | IPC_EXCL | 0600);
+ if (_semid >= 0) {
+ // Initialize semval.
+ s.val = 1;
+ int ret = ::semctl(_semid, 0, SETVAL, s);
+ if (ret < 0) {
+ log_error(_("Failed to set semaphore value: %1%"), strerror(errno));
+ return false;
+ }
+ // The first semop is executed immediately after this function returns.
+ } else if (errno == EEXIST) {
+ _semid = semget(_shmkey, 1, 0600);
if (_semid < 0) {
- log_error(_("Failed to get semaphore for shared memory!"));
+ log_error(_("Failed to obtain nonexclusive semaphore for shared "
+ "memory: %1%"), strerror(errno));
return false;
- }
+ }
- s.val = 1;
- const int ret = ::semctl(_semid, 0, SETVAL, s);
- if (ret < 0) {
- log_error(_("Failed to set semaphore value"));
+ // Wait until semid_ds::sem_otime changes.
+ semid_ds buf = semid_ds();
+ s.buf = &buf;
+ const int maxRetries = 10;
+ time_t uSecondsWait = 100; // 0.1ms
+ bool ok = false;
+
+ for(int i = 0; i < maxRetries; i++) {
+ semctl(_semid, 0, IPC_STAT, s);
+ if (buf.sem_otime != 0) {
+ ok = true;
+ break;
+ } else {
+ gnashSleep(uSecondsWait);
+ }
+ }
+
+ if (!ok) {
+ log_error(_("Timed out waiting for semaphore initialization."));
return false;
}
+ } else {
+ log_error(_("Failed creating semaphore: %1%"), strerror(errno));
+ return false;
+ }
+
+ return true;
+}
+
+bool
+SharedMem::attach()
+{
+#if !ENABLE_SHARED_MEM
+# error "You need SYSV Shared memory support to use this option"
+#endif
+
+ // Don't try to attach twice.
+ if (_addr) return true;
+
+ _shmkey = rcfile.getLCShmKey();
+
+ // Check rcfile for key; if there isn't one, use the Adobe key.
+ if (_shmkey == 0) {
+ log_debug("No shared memory key specified in rcfile. Using default for communication with other players");
+ _shmkey = 0xdd3adabd;
}
- // The 4th argument is neither necessary nor used, but we pass it
- // anyway for fun.
- const int semval = ::semctl(_semid, 0, GETVAL, s);
+ log_debug("Using shared memory key %s",
+ boost::io::group(std::hex, std::showbase, _shmkey));
- if (semval != 1) {
- log_error(_("Need semaphore value of 1 for locking. Cannot attach shared memory!"));
+ if (!getSemaphore()) {
return false;
}
+ // Note that at this point semval is of indeterminate value: for the
+ // process that created the semaphore, the value is 1, but for another
+ // process the value would depend on whether there is an existing lock.
+
Lock lock(*this);
// Then attach shared memory. See if it exists.
diff --git a/libbase/SharedMem.h b/libbase/SharedMem.h
index c177f53..94672d9 100644
--- a/libbase/SharedMem.h
+++ b/libbase/SharedMem.h
@@ -105,6 +105,10 @@ private:
/// @return true if successful, false if not.
DSOEXPORT bool unlock() const;
+ /// Obtain a semaphore.
+ /// @return true on success; false otherwise.
+ bool getSemaphore();
+
iterator _addr;
const size_t _size;
diff --git a/libbase/Socket.cpp b/libbase/Socket.cpp
index 2bb3484..b23240a 100644
--- a/libbase/Socket.cpp
+++ b/libbase/Socket.cpp
@@ -24,23 +24,18 @@
#include "Socket.h"
-#include <cstring>
#include <cerrno>
#include <csignal>
#include <boost/lexical_cast.hpp>
#include <boost/cstdint.hpp>
-#include <boost/shared_ptr.hpp>
-
+
#include "GnashSystemNetHeaders.h"
#include "GnashSystemFDHeaders.h"
-#include "URL.h"
#include "log.h"
#include "utility.h"
#include "GnashAlgorithm.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
+#include "GnashSystemNetHeaders.h"
+#include "GnashScopedPtr.h"
namespace gnash {
@@ -128,6 +123,28 @@ Socket::close()
_error = false;
}
+namespace {
+
+addrinfo* getAddrInfo(const std::string& hostname, boost::uint16_t port)
+{
+ addrinfo req = addrinfo(), *ans = 0;
+
+ req.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
+ req.ai_socktype = SOCK_STREAM;
+
+ std::string portNo = boost::lexical_cast<std::string>(port);
+ int code = getaddrinfo(hostname.c_str(), portNo.c_str(), &req, &ans);
+ if (code != 0) {
+ log_error(_("getaddrinfo() failed with code: #%d - %s"),
+ code, gai_strerror(code));
+ return 0;
+ }
+
+ return ans;
+}
+
+}
+
bool
Socket::connect(const std::string& hostname, boost::uint16_t port)
{
@@ -147,72 +164,31 @@ Socket::connect(const std::string& hostname, boost::uint16_t port)
}
// This is used for ::connect()
- struct sockaddr *saddr = 0;
-
-#ifdef HAVE_IPV6
- int code = 0;
- struct addrinfo req, *ans;
- std::memset(&req, 0, sizeof(struct addrinfo));
- req.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
- req.ai_socktype = SOCK_STREAM;
-
- // getaddrinfo() is sensitive to how localhost is defined in
- // /etc/hosts. Whatever hostname is, needs to match the entry in
- // the hosts file. Localhost is usually only used for debug and
- // and testing, all other hostnames are fully qualified. Anyway,
- // this causes our XMLSocketTester test case to fail since not
- // all build slaves have the same entry for localhost in their
- // hosts file.
- code = getaddrinfo(hostname.c_str(), 0, &req, &ans);
- if (code != 0) {
- if (code == EAI_NONAME) {
- std::string localhost;
- if (hostname == "localhost") {
- localhost = "localhost.localdomain";
- } else if (hostname == "localhost.localdomain") {
- localhost = "localhost";
- }
- if ((code = getaddrinfo(localhost.c_str(), 0, &req, &ans)) != 0) {
- log_error(_("getaddrinfo() failed again with code: #%d - %s\n"),
- code, gai_strerror(code));
- return false;
- }
- log_error(_("getaddrinfo() needed to change localhost, check your /etc/hosts file!"));
- } else {
- log_error(_("getaddrinfo() failed with code: #%d - %s\n"),
- code, gai_strerror(code));
- return false;
- }
+ ScopedPtr<addrinfo> ans(getAddrInfo(hostname, port), freeaddrinfo);
+ if (!ans.get()) {
+ return false;
}
// display all the IP numbers
- struct addrinfo *ot = ans;
- while (ot) {
- char clienthost [NI_MAXHOST];
- std::memset(&clienthost, 0, NI_MAXHOST);
- char clientservice[NI_MAXSERV];
- std::memset(&clientservice, 0, NI_MAXSERV);
- getnameinfo(ot->ai_addr, ot->ai_addrlen,
- clienthost, sizeof(clienthost),
- clientservice, sizeof(clientservice),
- NI_NUMERICHOST);
-
- boost::shared_ptr<char> straddr = getIPString(ot);
-
- if (ot->ai_family == AF_INET6) {
- log_debug("%s has IPV6 address of: %s", hostname, straddr.get());
- } else if (ot->ai_family == AF_INET) {
- log_debug("%s has IPV4 address of: %s", hostname, straddr.get());
- } else {
- log_error("%s has no IP address!", hostname);
+ if (LogFile::getDefaultInstance().getVerbosity() != 0) {
+ for(const addrinfo* ot = ans.get(); ot; ot = ot->ai_next) {
+
+ char clienthost [INET6_ADDRSTRLEN] = {};
+ int code = getnameinfo(ot->ai_addr, ot->ai_addrlen,
+ clienthost, sizeof(clienthost),
+ NULL, 0, NI_NUMERICHOST);
+
+ if (code != 0) {
+ log_error(_("getnameinfo() failed: %1%"), gai_strerror(code));
+ } else {
+ log_debug("%s has address of: %s", hostname, clienthost);
+ }
}
-
- ot = ot->ai_next;
}
// Multiple IPV$ and IPV6 numbers may be returned, so we try them all if
// required
- struct addrinfo *it = ans;
+ const addrinfo *it = ans.get();
while (it) {
_socket = ::socket(it->ai_family, it->ai_socktype, it->ai_protocol);
if (_socket < 0) {
@@ -226,40 +202,10 @@ Socket::connect(const std::string& hostname, boost::uint16_t port)
}
}
- // cache the data we need later
- struct sockaddr_in6 *addr6 = reinterpret_cast<struct sockaddr_in6 *>(it->ai_addr);
- // When NULL is passed to getaddrinfo(), the port isn't set in
- // the returned data, so we do it here.
- addr6->sin6_port = htons(port);
- saddr = it->ai_addr;
- const int addrlen = it->ai_addrlen;
-
- freeaddrinfo(ans); // free the response data
-#else
- struct sockaddr_in addr;
- std::memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = ::inet_addr(hostname.c_str());
- if (addr.sin_addr.s_addr == INADDR_NONE) {
- struct hostent* host = ::gethostbyname(hostname.c_str());
- if (!host || !host->h_addr) {
- return false;
- }
- addr.sin_addr = *reinterpret_cast<in_addr*>(host->h_addr);
- _socket = ::socket(addr.sin_family, SOCK_STREAM, IPPROTO_TCP);
-
- if (_socket < 0) {
- const int err = errno;
- log_error(_("Socket creation failed: %s"), std::strerror(err));
- _socket = 0;
- return false;
- }
+ if (!it) {
+ log_error(_("Socket creation attempt(s) failed: giving up."));
+ return false;
}
- // cache the data we need later
- const int addrlen = sizeof(struct sockaddr);
- saddr = reinterpret_cast<struct sockaddr *>(&addr);
-#endif
#ifndef _WIN32
// Set non-blocking.
@@ -268,7 +214,8 @@ Socket::connect(const std::string& hostname, boost::uint16_t port)
#endif
// Attempt connection
- if (::connect(_socket, saddr, addrlen) < 0) {
+ int ret = ::connect(_socket, it->ai_addr, it->ai_addrlen);
+ if (ret < 0) {
const int err = errno;
#ifndef _WIN32
if (err != EINPROGRESS) {
@@ -302,44 +249,13 @@ Socket::connect(const std::string& hostname, boost::uint16_t port)
return true;
}
-// Return the string representation of the IPV4 or IPV6 number
-boost::shared_ptr<char>
-Socket::getIPString(struct addrinfo *ai)
-{
- boost::shared_ptr<char> straddr(new char[INET6_ADDRSTRLEN]);
- std::memset(straddr.get(), 0, INET6_ADDRSTRLEN);
- if (ai->ai_family == AF_INET6) {
- struct sockaddr_in6 *sock6 = reinterpret_cast<struct sockaddr_in6 *>(ai->ai_addr);
- struct in6_addr sin6_addr = sock6->sin6_addr;
- ::inet_ntop(AF_INET6, &sin6_addr, straddr.get(), INET6_ADDRSTRLEN);
-// log_debug("IPV6 address: %s", straddr.get());
- } else if (ai->ai_family == AF_INET) {
- struct sockaddr_in *sock = reinterpret_cast<struct sockaddr_in *>(ai->ai_addr);
- struct in_addr sin_addr = sock->sin_addr;
- ::inet_ntop(AF_INET, &sin_addr, straddr.get(), INET_ADDRSTRLEN);
-// log_debug("IPV4 address: %s", straddr);
- } else {
- log_error("no IP address in addrinfo!");
- }
-
- return straddr;
-}
-
void
Socket::fillCache()
{
-
// Read position is always _pos + _size wrapped.
const size_t cacheSize = arraySize(_cache);
size_t start = (_pos + _size) % cacheSize;
- // Try to fill the whole remaining buffer.
- const size_t completeRead = cacheSize - _size;
-
- // End is start + read size, wrapped.
- size_t end = (start + completeRead) % cacheSize;
- if (end == 0) end = cacheSize;
-
char* startpos = _cache + start;
while (1) {
@@ -439,8 +355,6 @@ std::streamsize
Socket::write(const void* src, std::streamsize num)
{
if (bad()) return 0;
-
- int bytesSent = 0;
int toWrite = num;
const char* buf = static_cast<const char*>(src);
@@ -462,7 +376,7 @@ Socket::write(const void* src, std::streamsize num)
// a return of -1 from ::send.
while (toWrite > 0) {
- bytesSent = ::send(_socket, buf, toWrite, 0);
+ int bytesSent = ::send(_socket, buf, toWrite, 0);
if (bytesSent < 0) {
const int err = errno;
log_error(_("Socket send error %s"), std::strerror(err));
diff --git a/libbase/Socket.h b/libbase/Socket.h
index 6bef010..c2d3121 100644
--- a/libbase/Socket.h
+++ b/libbase/Socket.h
@@ -23,11 +23,7 @@
#include "dsodefs.h"
#include <boost/cstdint.hpp>
-#include <boost/shared_ptr.hpp>
#include "IOChannel.h"
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
namespace gnash {
class URL;
@@ -123,9 +119,6 @@ public:
private:
- // Return the string representation of the IPV4 or IPV6 number
- boost::shared_ptr<char> getIPString(struct addrinfo *ai);
-
/// Fill the cache.
void fillCache();
diff --git a/libbase/URL.cpp b/libbase/URL.cpp
index 5ffdb70..9455215 100644
--- a/libbase/URL.cpp
+++ b/libbase/URL.cpp
@@ -86,7 +86,6 @@ URL::normalize_path(std::string& path)
i!=e; ++i) {
path += "/" + *i;
}
-
}
void
diff --git a/libbase/URLAccessManager.cpp b/libbase/URLAccessManager.cpp
index 227da42..43b58f1 100644
--- a/libbase/URLAccessManager.cpp
+++ b/libbase/URLAccessManager.cpp
@@ -32,6 +32,11 @@
#include <vector>
#include <cassert>
+// Android fails to define this constant
+#ifndef MAXHOSTNAMELEN
+# define MAXHOSTNAMELEN 256
+#endif
+
namespace gnash {
namespace URLAccessManager {
@@ -204,7 +209,7 @@ host_check(const std::string& host)
// Get hostname
//
- #define MAXHOSTNAMELEN 200
+// #define MAXHOSTNAMELEN 200
char name[MAXHOSTNAMELEN];
if (::gethostname(name, MAXHOSTNAMELEN) == -1)
{
diff --git a/libbase/dsodefs.h b/libbase/dsodefs.h
index c3bc470..7bc4182 100644
--- a/libbase/dsodefs.h
+++ b/libbase/dsodefs.h
@@ -57,4 +57,10 @@
#endif
#endif
+#ifdef USE_TESTSUITE
+# define DSOTEXPORT DSOEXPORT
+#else
+# define DSOTEXPORT
+#endif
+
#endif // DSODEFS_H
diff --git a/libbase/extension.cpp b/libbase/extension.cpp
index ad5541e..45fab1d 100644
--- a/libbase/extension.cpp
+++ b/libbase/extension.cpp
@@ -152,7 +152,7 @@ bool
Extension::initModuleWithFunc(const std::string& module,
const std::string& func, as_object &obj)
{
- GNASH_REPORT_FUNCTION;
+// GNASH_REPORT_FUNCTION;
SharedLib *sl;
@@ -188,7 +188,7 @@ Extension::scanDir()
bool
Extension::scanDir(const std::string& dirlist)
{
- GNASH_REPORT_FUNCTION;
+// GNASH_REPORT_FUNCTION;
Tok t(dirlist, Sep(":"));
for (Tok::iterator i = t.begin(), e = t.end(); i != e; ++i) {
@@ -241,7 +241,7 @@ Extension::scanDir(const std::string& dirlist)
void
Extension::dumpModules()
{
- GNASH_REPORT_FUNCTION;
+// GNASH_REPORT_FUNCTION;
std::cerr << _modules.size() << " plugin(s) for Gnash installed" << std::endl;
std::vector<std::string>::iterator it;
diff --git a/libbase/jemalloc.c b/libbase/jemalloc.c
deleted file mode 100644
index 077dead..0000000
--- a/libbase/jemalloc.c
+++ /dev/null
@@ -1,6577 +0,0 @@
-/* -*- Mode: C; tab-width: 8; c-basic-offset: 8; indent-tabs-mode: t -*- */
-/* vim:set softtabstop=8 shiftwidth=8: */
-/*-
- * Copyright (C) 2006-2008 Jason Evans <jasone at FreeBSD.org>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice(s), this list of conditions and the following disclaimer as
- * the first lines of this file unmodified other than the possible
- * addition of one or more copyright notices.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice(s), this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *******************************************************************************
- *
- * This allocator implementation is designed to provide scalable performance
- * for multi-threaded programs on multi-processor systems. The following
- * features are included for this purpose:
- *
- * + Multiple arenas are used if there are multiple CPUs, which reduces lock
- * contention and cache sloshing.
- *
- * + Cache line sharing between arenas is avoided for internal data
- * structures.
- *
- * + Memory is managed in chunks and runs (chunks can be split into runs),
- * rather than as individual pages. This provides a constant-time
- * mechanism for associating allocations with particular arenas.
- *
- * Allocation requests are rounded up to the nearest size class, and no record
- * of the original request size is maintained. Allocations are broken into
- * categories according to size class. Assuming runtime defaults, 4 kB pages
- * and a 16 byte quantum on a 32-bit system, the size classes in each category
- * are as follows:
- *
- * |=====================================|
- * | Category | Subcategory | Size |
- * |=====================================|
- * | Small | Tiny | 2 |
- * | | | 4 |
- * | | | 8 |
- * | |----------------+---------|
- * | | Quantum-spaced | 16 |
- * | | | 32 |
- * | | | 48 |
- * | | | ... |
- * | | | 480 |
- * | | | 496 |
- * | | | 512 |
- * | |----------------+---------|
- * | | Sub-page | 1 kB |
- * | | | 2 kB |
- * |=====================================|
- * | Large | 4 kB |
- * | | 8 kB |
- * | | 12 kB |
- * | | ... |
- * | | 1012 kB |
- * | | 1016 kB |
- * | | 1020 kB |
- * |=====================================|
- * | Huge | 1 MB |
- * | | 2 MB |
- * | | 3 MB |
- * | | ... |
- * |=====================================|
- *
- * A different mechanism is used for each category:
- *
- * Small : Each size class is segregated into its own set of runs. Each run
- * maintains a bitmap of which regions are free/allocated.
- *
- * Large : Each allocation is backed by a dedicated run. Metadata are stored
- * in the associated arena chunk header maps.
- *
- * Huge : Each allocation is backed by a dedicated contiguous set of chunks.
- * Metadata are stored in a separate red-black tree.
- *
- *******************************************************************************
- */
-#include "jemalloc_gnash.h"
-
-#ifdef MOZ_MEMORY_ANDROID
-#define NO_TLS
-#define _pthread_self() pthread_self()
-#endif
-
-/*
- * MALLOC_PRODUCTION disables assertions and statistics gathering. It also
- * defaults the A and J runtime options to off. These settings are appropriate
- * for production systems.
- */
-#ifndef MOZ_MEMORY_DEBUG
-# define MALLOC_PRODUCTION
-#endif
-
-/*
- * Use only one arena by default. Mozilla does not currently make extensive
- * use of concurrent allocation, so the increased fragmentation associated with
- * multiple arenas is not warranted.
- */
-#define MOZ_MEMORY_NARENAS_DEFAULT_ONE
-
-#ifndef MALLOC_PRODUCTION
- /*
- * MALLOC_DEBUG enables assertions and other sanity checks, and disables
- * inline functions.
- */
-# define MALLOC_DEBUG
-
- /*
- * MALLOC_STATS enables statistics calculation, and is required for
- * jemalloc_stats().
- */
-# define MALLOC_STATS
-
- /* Memory filling (junk/zero). */
-# define MALLOC_FILL
-
- /* Allocation tracing. */
-# ifndef MOZ_MEMORY_WINDOWS
-# define MALLOC_UTRACE
-# endif
-
- /* Support optional abort() on OOM. */
-# define MALLOC_XMALLOC
-
- /* Support SYSV semantics. */
-# define MALLOC_SYSV
-#endif
-
-/*
- * MALLOC_VALIDATE causes malloc_usable_size() to perform some pointer
- * validation. There are many possible errors that validation does not even
- * attempt to detect.
- */
-#define MALLOC_VALIDATE
-
-/* Embed no-op macros that support memory allocation tracking via valgrind. */
-#ifdef MOZ_VALGRIND
-# define MALLOC_VALGRIND
-#endif
-#ifdef MALLOC_VALGRIND
-# include <valgrind/valgrind.h>
-#else
-# define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)
-# define VALGRIND_FREELIKE_BLOCK(addr, rzB)
-#endif
-
-/*
- * MALLOC_BALANCE enables monitoring of arena lock contention and dynamically
- * re-balances arena load if exponentially averaged contention exceeds a
- * certain threshold.
- */
-/* #define MALLOC_BALANCE */
-
-#if (!defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN))
- /*
- * MALLOC_PAGEFILE causes all mmap()ed memory to be backed by temporary
- * files, so that if a chunk is mapped, it is guaranteed to be swappable.
- * This avoids asynchronous OOM failures that are due to VM over-commit.
- *
- * XXX OS X over-commits, so we should probably use mmap() instead of
- * vm_allocate(), so that MALLOC_PAGEFILE works.
- */
-#define MALLOC_PAGEFILE
-#endif
-
-#ifdef MALLOC_PAGEFILE
-/* Write size when initializing a page file. */
-# define MALLOC_PAGEFILE_WRITE_SIZE 512
-#endif
-
-#if defined(MOZ_MEMORY_LINUX) && !defined(MOZ_MEMORY_ANDROID)
-#define _GNU_SOURCE /* For mremap(2). */
-#define issetugid() 0
-#if 0 /* Enable in order to test decommit code on Linux. */
-# define MALLOC_DECOMMIT
-#endif
-#endif
-
-#ifndef MOZ_MEMORY_WINCE
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stdlib.h>
-#endif
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#ifdef MOZ_MEMORY_WINDOWS
-#ifndef MOZ_MEMORY_WINCE
-#include <cruntime.h>
-#include <internal.h>
-#include <io.h>
-#else
-#include <cmnintrin.h>
-#include <crtdefs.h>
-#define SIZE_MAX UINT_MAX
-#endif
-#include <windows.h>
-
-#pragma warning( disable: 4267 4996 4146 )
-
-#define bool BOOL
-#define false FALSE
-#define true TRUE
-#define inline __inline
-#define SIZE_T_MAX SIZE_MAX
-#define STDERR_FILENO 2
-#define PATH_MAX MAX_PATH
-#define vsnprintf _vsnprintf
-
-#ifndef NO_TLS
-static unsigned long tlsIndex = 0xffffffff;
-#endif
-
-#define __thread
-#ifdef MOZ_MEMORY_WINCE
-#define _pthread_self() GetCurrentThreadId()
-#else
-#define _pthread_self() __threadid()
-#endif
-#define issetugid() 0
-
-#ifndef MOZ_MEMORY_WINCE
-/* use MSVC intrinsics */
-#pragma intrinsic(_BitScanForward)
-static __forceinline int
-ffs(int x)
-{
- unsigned long i;
-
- if (_BitScanForward(&i, x) != 0)
- return (i + 1);
-
- return (0);
-}
-
-/* Implement getenv without using malloc */
-static char mozillaMallocOptionsBuf[64];
-
-#define getenv xgetenv
-static char *
-getenv(const char *name)
-{
-
- if (GetEnvironmentVariableA(name, (LPSTR)&mozillaMallocOptionsBuf,
- sizeof(mozillaMallocOptionsBuf)) > 0)
- return (mozillaMallocOptionsBuf);
-
- return (NULL);
-}
-
-#else /* WIN CE */
-
-#define ENOMEM 12
-#define EINVAL 22
-
-static __forceinline int
-ffs(int x)
-{
-
- return 32 - _CountLeadingZeros((-x) & x);
-}
-#endif
-
-typedef unsigned char uint8_t;
-typedef unsigned uint32_t;
-typedef unsigned long long uint64_t;
-typedef unsigned long long uintmax_t;
-#if defined(MOZ_MEMORY_SIZEOF_PTR_2POW) && (MOZ_MEMORY_SIZEOF_PTR_2POW == 3)
-typedef long long ssize_t;
-#else
-typedef long ssize_t;
-#endif
-
-#define MALLOC_DECOMMIT
-#endif
-
-#ifndef MOZ_MEMORY_WINDOWS
-#ifndef MOZ_MEMORY_SOLARIS
-#include <sys/cdefs.h>
-#endif
-#ifndef __DECONST
-# define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
-#endif
-#ifndef MOZ_MEMORY
-__FBSDID("$FreeBSD: head/lib/libc/stdlib/malloc.c 180599 2008-07-18 19:35:44Z jasone $");
-#include "libc_private.h"
-#ifdef MALLOC_DEBUG
-# define _LOCK_DEBUG
-#endif
-#include "spinlock.h"
-#include "namespace.h"
-#endif
-#include <sys/mman.h>
-#ifndef MADV_FREE
-# define MADV_FREE MADV_DONTNEED
-#endif
-#ifndef MAP_NOSYNC
-# define MAP_NOSYNC 0
-#endif
-#include <sys/param.h>
-#ifndef MOZ_MEMORY
-#include <sys/stddef.h>
-#endif
-#include <sys/time.h>
-#include <sys/types.h>
-#if !defined(MOZ_MEMORY_SOLARIS) && !defined(MOZ_MEMORY_ANDROID)
-#include <sys/sysctl.h>
-#endif
-#include <sys/uio.h>
-#ifndef MOZ_MEMORY
-#include <sys/ktrace.h> /* Must come after several other sys/ includes. */
-
-#include <machine/atomic.h>
-#include <machine/cpufunc.h>
-#include <machine/vmparam.h>
-#endif
-
-#include <errno.h>
-#include <limits.h>
-#ifndef SIZE_T_MAX
-# define SIZE_T_MAX SIZE_MAX
-#endif
-#include <pthread.h>
-#ifdef MOZ_MEMORY_DARWIN
-#define _pthread_self pthread_self
-#define _pthread_mutex_init pthread_mutex_init
-#define _pthread_mutex_trylock pthread_mutex_trylock
-#define _pthread_mutex_lock pthread_mutex_lock
-#define _pthread_mutex_unlock pthread_mutex_unlock
-#endif
-#include <sched.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef MOZ_MEMORY_DARWIN
-#include <strings.h>
-#endif
-#include <unistd.h>
-
-#ifdef MOZ_MEMORY_DARWIN
-#include <libkern/OSAtomic.h>
-#include <mach/mach_error.h>
-#include <mach/mach_init.h>
-#include <mach/vm_map.h>
-#include <malloc/malloc.h>
-#endif
-
-#ifndef MOZ_MEMORY
-#include "un-namespace.h"
-#endif
-
-#endif
-
-
-/* Some tools, such as /dev/dsp wrappers, LD_PRELOAD libraries that
- * happen to override mmap() and call dlsym() from their overridden
- * mmap(). The problem is that dlsym() calls malloc(), and this ends
- * up in a dead lock in jemalloc.
- * On these systems, we prefer to directly use the system call.
- * We do that for Linux systems and kfreebsd with GNU userland.
- * Note sanity checks are not done (alignment of offset, ...) because
- * the uses of mmap are pretty limited, in jemalloc.
- *
- * On Alpha, glibc has a bug that prevents syscall() to work for system
- * calls with 6 arguments
- */
-#if (defined(MOZ_MEMORY_LINUX) && !defined(__alpha__)) || \
- (defined(MOZ_MEMORY_BSD) && defined(__GLIBC__))
-#include <sys/syscall.h>
-#if defined(SYS_mmap) || defined(SYS_mmap2)
-static inline
-void *_mmap(void *addr, size_t length, int prot, int flags,
- int fd, off_t offset)
-{
-/* S390 only passes one argument to the mmap system call, which is a
- * pointer to a structure containing the arguments */
-#ifdef __s390__
- struct {
- void *addr;
- size_t length;
- int prot;
- int flags;
- int fd;
- off_t offset;
- } args = { addr, length, prot, flags, fd, offset };
- return (void *) syscall(SYS_mmap, &args);
-#else
-#ifdef SYS_mmap2
- return (void *) syscall(SYS_mmap2, addr, length, prot, flags,
- fd, offset >> 12);
-#else
- return (void *) syscall(SYS_mmap, addr, length, prot, flags,
- fd, offset);
-#endif
-#endif
-}
-#define mmap _mmap
-#define munmap(a, l) syscall(SYS_munmap, a, l)
-#endif
-#endif
-
-#ifdef MOZ_MEMORY_DARWIN
-static const bool __isthreaded = true;
-#endif
-
-#if defined(MOZ_MEMORY_SOLARIS) && defined(MAP_ALIGN) && !defined(JEMALLOC_NEVER_USES_MAP_ALIGN) || defined(MOZ_MEMORY_LINUX)
-#define JEMALLOC_USES_MAP_ALIGN /* Required on Solaris 10. Might improve performance elsewhere. */
-#endif
-
-#if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6)
-#define JEMALLOC_USES_MAP_ALIGN /* Required for Windows CE < 6 */
-#endif
-
-#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
-
-#ifdef MOZ_MEMORY_WINDOWS
- /* MSVC++ does not support C99 variable-length arrays. */
-# define RB_NO_C99_VARARRAYS
-#endif
-#include "jemalloc_rb.h"
-
-#ifdef MALLOC_DEBUG
- /* Disable inlining to make debugging easier. */
-#ifdef inline
-#undef inline
-#endif
-
-# define inline
-#endif
-
-/* Size of stack-allocated buffer passed to strerror_r(). */
-#define STRERROR_BUF 64
-
-/* Minimum alignment of allocations is 2^QUANTUM_2POW_MIN bytes. */
-# define QUANTUM_2POW_MIN 4
-#ifdef MOZ_MEMORY_SIZEOF_PTR_2POW
-# define SIZEOF_PTR_2POW MOZ_MEMORY_SIZEOF_PTR_2POW
-#else
-# define SIZEOF_PTR_2POW 2
-#endif
-#ifndef PIC
-# define PIC
-#endif
-#ifndef MOZ_MEMORY_DARWIN
-static const bool __isthreaded = true;
-#else
-# define NO_TLS
-#endif
-#if 0
-#ifdef __i386__
-# define QUANTUM_2POW_MIN 4
-# define SIZEOF_PTR_2POW 2
-# define CPU_SPINWAIT __asm__ volatile("pause")
-#endif
-#ifdef __ia64__
-# define QUANTUM_2POW_MIN 4
-# define SIZEOF_PTR_2POW 3
-#endif
-#ifdef __alpha__
-# define QUANTUM_2POW_MIN 4
-# define SIZEOF_PTR_2POW 3
-# define NO_TLS
-#endif
-#ifdef __sparc64__
-# define QUANTUM_2POW_MIN 4
-# define SIZEOF_PTR_2POW 3
-# define NO_TLS
-#endif
-#ifdef __amd64__
-# define QUANTUM_2POW_MIN 4
-# define SIZEOF_PTR_2POW 3
-# define CPU_SPINWAIT __asm__ volatile("pause")
-#endif
-#ifdef __arm__
-# define QUANTUM_2POW_MIN 3
-# define SIZEOF_PTR_2POW 2
-# define NO_TLS
-#endif
-#ifdef __mips__
-# define QUANTUM_2POW_MIN 3
-# define SIZEOF_PTR_2POW 2
-# define NO_TLS
-#endif
-#ifdef __powerpc__
-# define QUANTUM_2POW_MIN 4
-# define SIZEOF_PTR_2POW 2
-#endif
-#endif
-
-#define SIZEOF_PTR (1U << SIZEOF_PTR_2POW)
-
-/* sizeof(int) == (1U << SIZEOF_INT_2POW). */
-#ifndef SIZEOF_INT_2POW
-# define SIZEOF_INT_2POW 2
-#endif
-
-/* We can't use TLS in non-PIC programs, since TLS relies on loader magic. */
-#if (!defined(PIC) && !defined(NO_TLS))
-# define NO_TLS
-#endif
-
-#ifdef NO_TLS
- /* MALLOC_BALANCE requires TLS. */
-# ifdef MALLOC_BALANCE
-# undef MALLOC_BALANCE
-# endif
-#endif
-
-/*
- * Size and alignment of memory chunks that are allocated by the OS's virtual
- * memory system.
- */
-#if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6)
-#define CHUNK_2POW_DEFAULT 21
-#else
-#define CHUNK_2POW_DEFAULT 20
-#endif
-/* Maximum number of dirty pages per arena. */
-#define DIRTY_MAX_DEFAULT (1U << 10)
-
-/*
- * Maximum size of L1 cache line. This is used to avoid cache line aliasing,
- * so over-estimates are okay (up to a point), but under-estimates will
- * negatively affect performance.
- */
-#define CACHELINE_2POW 6
-#define CACHELINE ((size_t)(1U << CACHELINE_2POW))
-
-/* Smallest size class to support. */
-#define TINY_MIN_2POW 1
-
-/*
- * Maximum size class that is a multiple of the quantum, but not (necessarily)
- * a power of 2. Above this size, allocations are rounded up to the nearest
- * power of 2.
- */
-#define SMALL_MAX_2POW_DEFAULT 9
-#define SMALL_MAX_DEFAULT (1U << SMALL_MAX_2POW_DEFAULT)
-
-/*
- * RUN_MAX_OVRHD indicates maximum desired run header overhead. Runs are sized
- * as small as possible such that this setting is still honored, without
- * violating other constraints. The goal is to make runs as small as possible
- * without exceeding a per run external fragmentation threshold.
- *
- * We use binary fixed point math for overhead computations, where the binary
- * point is implicitly RUN_BFP bits to the left.
- *
- * Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be
- * honored for some/all object sizes, since there is one bit of header overhead
- * per object (plus a constant). This constraint is relaxed (ignored) for runs
- * that are so small that the per-region overhead is greater than:
- *
- * (RUN_MAX_OVRHD / (reg_size << (3+RUN_BFP))
- */
-#define RUN_BFP 12
-/* \/ Implicit binary fixed point. */
-#define RUN_MAX_OVRHD 0x0000003dU
-#define RUN_MAX_OVRHD_RELAX 0x00001800U
-
-/* Put a cap on small object run size. This overrides RUN_MAX_OVRHD. */
-#define RUN_MAX_SMALL_2POW 15
-#define RUN_MAX_SMALL (1U << RUN_MAX_SMALL_2POW)
-
-/*
- * Hyper-threaded CPUs may need a special instruction inside spin loops in
- * order to yield to another virtual CPU. If no such instruction is defined
- * above, make CPU_SPINWAIT a no-op.
- */
-#ifndef CPU_SPINWAIT
-# define CPU_SPINWAIT
-#endif
-
-/*
- * Adaptive spinning must eventually switch to blocking, in order to avoid the
- * potential for priority inversion deadlock. Backing off past a certain point
- * can actually waste time.
- */
-#define SPIN_LIMIT_2POW 11
-
-/*
- * Conversion from spinning to blocking is expensive; we use (1U <<
- * BLOCK_COST_2POW) to estimate how many more times costly blocking is than
- * worst-case spinning.
- */
-#define BLOCK_COST_2POW 4
-
-#ifdef MALLOC_BALANCE
- /*
- * We use an exponential moving average to track recent lock contention,
- * where the size of the history window is N, and alpha=2/(N+1).
- *
- * Due to integer math rounding, very small values here can cause
- * substantial degradation in accuracy, thus making the moving average decay
- * faster than it would with precise calculation.
- */
-# define BALANCE_ALPHA_INV_2POW 9
-
- /*
- * Threshold value for the exponential moving contention average at which to
- * re-assign a thread.
- */
-# define BALANCE_THRESHOLD_DEFAULT (1U << (SPIN_LIMIT_2POW-4))
-#endif
-
-/******************************************************************************/
-
-/*
- * Mutexes based on spinlocks. We can't use normal pthread spinlocks in all
- * places, because they require malloc()ed memory, which causes bootstrapping
- * issues in some cases.
- */
-#if defined(MOZ_MEMORY_WINDOWS)
-#define malloc_mutex_t CRITICAL_SECTION
-#define malloc_spinlock_t CRITICAL_SECTION
-#elif defined(MOZ_MEMORY_DARWIN)
-typedef struct {
- OSSpinLock lock;
-} malloc_mutex_t;
-typedef struct {
- OSSpinLock lock;
-} malloc_spinlock_t;
-#elif defined(MOZ_MEMORY)
-typedef pthread_mutex_t malloc_mutex_t;
-typedef pthread_mutex_t malloc_spinlock_t;
-#else
-/* XXX these should #ifdef these for freebsd (and linux?) only */
-typedef struct {
- spinlock_t lock;
-} malloc_mutex_t;
-typedef malloc_spinlock_t malloc_mutex_t;
-#endif
-
-/* Set to true once the allocator has been initialized. */
-static bool malloc_initialized = false;
-
-#if defined(MOZ_MEMORY_WINDOWS)
-/* No init lock for Windows. */
-#elif defined(MOZ_MEMORY_DARWIN)
-static malloc_mutex_t init_lock = {OS_SPINLOCK_INIT};
-#elif defined(MOZ_MEMORY_LINUX) && !defined(MOZ_MEMORY_ANDROID)
-static malloc_mutex_t init_lock = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
-#elif defined(MOZ_MEMORY)
-static malloc_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;
-#else
-static malloc_mutex_t init_lock = {_SPINLOCK_INITIALIZER};
-#endif
-
-/******************************************************************************/
-/*
- * Statistics data structures.
- */
-
-#ifdef MALLOC_STATS
-
-typedef struct malloc_bin_stats_s malloc_bin_stats_t;
-struct malloc_bin_stats_s {
- /*
- * Number of allocation requests that corresponded to the size of this
- * bin.
- */
- uint64_t nrequests;
-
- /* Total number of runs created for this bin's size class. */
- uint64_t nruns;
-
- /*
- * Total number of runs reused by extracting them from the runs tree for
- * this bin's size class.
- */
- uint64_t reruns;
-
- /* High-water mark for this bin. */
- unsigned long highruns;
-
- /* Current number of runs in this bin. */
- unsigned long curruns;
-};
-
-typedef struct arena_stats_s arena_stats_t;
-struct arena_stats_s {
- /* Number of bytes currently mapped. */
- size_t mapped;
-
- /*
- * Total number of purge sweeps, total number of madvise calls made,
- * and total pages purged in order to keep dirty unused memory under
- * control.
- */
- uint64_t npurge;
- uint64_t nmadvise;
- uint64_t purged;
-#ifdef MALLOC_DECOMMIT
- /*
- * Total number of decommit/commit operations, and total number of
- * pages decommitted.
- */
- uint64_t ndecommit;
- uint64_t ncommit;
- uint64_t decommitted;
-
- /* Current number of committed pages. */
- size_t committed;
-#endif
-
- /* Per-size-category statistics. */
- size_t allocated_small;
- uint64_t nmalloc_small;
- uint64_t ndalloc_small;
-
- size_t allocated_large;
- uint64_t nmalloc_large;
- uint64_t ndalloc_large;
-
-#ifdef MALLOC_BALANCE
- /* Number of times this arena reassigned a thread due to contention. */
- uint64_t nbalance;
-#endif
-};
-
-typedef struct chunk_stats_s chunk_stats_t;
-struct chunk_stats_s {
- /* Number of chunks that were allocated. */
- uint64_t nchunks;
-
- /* High-water mark for number of chunks allocated. */
- unsigned long highchunks;
-
- /*
- * Current number of chunks allocated. This value isn't maintained for
- * any other purpose, so keep track of it in order to be able to set
- * highchunks.
- */
- unsigned long curchunks;
-};
-
-#endif /* #ifdef MALLOC_STATS */
-
-/******************************************************************************/
-/*
- * Extent data structures.
- */
-
-/* Tree of extents. */
-typedef struct extent_node_s extent_node_t;
-struct extent_node_s {
- /* Linkage for the size/address-ordered tree. */
- rb_node(extent_node_t) link_szad;
-
- /* Linkage for the address-ordered tree. */
- rb_node(extent_node_t) link_ad;
-
- /* Pointer to the extent that this tree node is responsible for. */
- void *addr;
-
- /* Total region size. */
- size_t size;
-};
-typedef rb_tree(extent_node_t) extent_tree_t;
-
-/******************************************************************************/
-/*
- * Radix tree data structures.
- */
-
-#ifdef MALLOC_VALIDATE
- /*
- * Size of each radix tree node (must be a power of 2). This impacts tree
- * depth.
- */
-# if (SIZEOF_PTR == 4)
-# define MALLOC_RTREE_NODESIZE (1U << 14)
-# else
-# define MALLOC_RTREE_NODESIZE CACHELINE
-# endif
-
-typedef struct malloc_rtree_s malloc_rtree_t;
-struct malloc_rtree_s {
- malloc_spinlock_t lock;
- void **root;
- unsigned height;
- unsigned level2bits[1]; /* Dynamically sized. */
-};
-#endif
-
-/******************************************************************************/
-/*
- * Arena data structures.
- */
-
-typedef struct arena_s arena_t;
-typedef struct arena_bin_s arena_bin_t;
-
-/* Each element of the chunk map corresponds to one page within the chunk. */
-typedef struct arena_chunk_map_s arena_chunk_map_t;
-struct arena_chunk_map_s {
- /*
- * Linkage for run trees. There are two disjoint uses:
- *
- * 1) arena_t's runs_avail tree.
- * 2) arena_run_t conceptually uses this linkage for in-use non-full
- * runs, rather than directly embedding linkage.
- */
- rb_node(arena_chunk_map_t) link;
-
- /*
- * Run address (or size) and various flags are stored together. The bit
- * layout looks like (assuming 32-bit system):
- *
- * ???????? ???????? ????---- --ckdzla
- *
- * ? : Unallocated: Run address for first/last pages, unset for internal
- * pages.
- * Small: Run address.
- * Large: Run size for first page, unset for trailing pages.
- * - : Unused.
- * c : decommitted?
- * k : key?
- * d : dirty?
- * z : zeroed?
- * l : large?
- * a : allocated?
- *
- * Following are example bit patterns for the three types of runs.
- *
- * r : run address
- * s : run size
- * x : don't care
- * - : 0
- * [cdzla] : bit set
- *
- * Unallocated:
- * ssssssss ssssssss ssss---- --c-----
- * xxxxxxxx xxxxxxxx xxxx---- ----d---
- * ssssssss ssssssss ssss---- -----z--
- *
- * Small:
- * rrrrrrrr rrrrrrrr rrrr---- -------a
- * rrrrrrrr rrrrrrrr rrrr---- -------a
- * rrrrrrrr rrrrrrrr rrrr---- -------a
- *
- * Large:
- * ssssssss ssssssss ssss---- ------la
- * -------- -------- -------- ------la
- * -------- -------- -------- ------la
- */
- size_t bits;
-#ifdef MALLOC_DECOMMIT
-#define CHUNK_MAP_DECOMMITTED ((size_t)0x20U)
-#endif
-#define CHUNK_MAP_KEY ((size_t)0x10U)
-#define CHUNK_MAP_DIRTY ((size_t)0x08U)
-#define CHUNK_MAP_ZEROED ((size_t)0x04U)
-#define CHUNK_MAP_LARGE ((size_t)0x02U)
-#define CHUNK_MAP_ALLOCATED ((size_t)0x01U)
-};
-typedef rb_tree(arena_chunk_map_t) arena_avail_tree_t;
-typedef rb_tree(arena_chunk_map_t) arena_run_tree_t;
-
-/* Arena chunk header. */
-typedef struct arena_chunk_s arena_chunk_t;
-struct arena_chunk_s {
- /* Arena that owns the chunk. */
- arena_t *arena;
-
- /* Linkage for the arena's chunks_dirty tree. */
- rb_node(arena_chunk_t) link_dirty;
-
- /* Number of dirty pages. */
- size_t ndirty;
-
- /* Map of pages within chunk that keeps track of free/large/small. */
- arena_chunk_map_t map[1]; /* Dynamically sized. */
-};
-typedef rb_tree(arena_chunk_t) arena_chunk_tree_t;
-
-typedef struct arena_run_s arena_run_t;
-struct arena_run_s {
-#ifdef MALLOC_DEBUG
- uint32_t magic;
-# define ARENA_RUN_MAGIC 0x384adf93
-#endif
-
- /* Bin this run is associated with. */
- arena_bin_t *bin;
-
- /* Index of first element that might have a free region. */
- unsigned regs_minelm;
-
- /* Number of free regions in run. */
- unsigned nfree;
-
- /* Bitmask of in-use regions (0: in use, 1: free). */
- unsigned regs_mask[1]; /* Dynamically sized. */
-};
-
-struct arena_bin_s {
- /*
- * Current run being used to service allocations of this bin's size
- * class.
- */
- arena_run_t *runcur;
-
- /*
- * Tree of non-full runs. This tree is used when looking for an
- * existing run when runcur is no longer usable. We choose the
- * non-full run that is lowest in memory; this policy tends to keep
- * objects packed well, and it can also help reduce the number of
- * almost-empty chunks.
- */
- arena_run_tree_t runs;
-
- /* Size of regions in a run for this bin's size class. */
- size_t reg_size;
-
- /* Total size of a run for this bin's size class. */
- size_t run_size;
-
- /* Total number of regions in a run for this bin's size class. */
- uint32_t nregs;
-
- /* Number of elements in a run's regs_mask for this bin's size class. */
- uint32_t regs_mask_nelms;
-
- /* Offset of first region in a run for this bin's size class. */
- uint32_t reg0_offset;
-
-#ifdef MALLOC_STATS
- /* Bin statistics. */
- malloc_bin_stats_t stats;
-#endif
-};
-
-struct arena_s {
-#ifdef MALLOC_DEBUG
- uint32_t magic;
-# define ARENA_MAGIC 0x947d3d24
-#endif
-
- /* All operations on this arena require that lock be locked. */
-#ifdef MOZ_MEMORY
- malloc_spinlock_t lock;
-#else
- pthread_mutex_t lock;
-#endif
-
-#ifdef MALLOC_STATS
- arena_stats_t stats;
-#endif
-
- /* Tree of dirty-page-containing chunks this arena manages. */
- arena_chunk_tree_t chunks_dirty;
-
- /*
- * In order to avoid rapid chunk allocation/deallocation when an arena
- * oscillates right on the cusp of needing a new chunk, cache the most
- * recently freed chunk. The spare is left in the arena's chunk trees
- * until it is deleted.
- *
- * There is one spare chunk per arena, rather than one spare total, in
- * order to avoid interactions between multiple threads that could make
- * a single spare inadequate.
- */
- arena_chunk_t *spare;
-
- /*
- * Current count of pages within unused runs that are potentially
- * dirty, and for which madvise(... MADV_FREE) has not been called. By
- * tracking this, we can institute a limit on how much dirty unused
- * memory is mapped for each arena.
- */
- size_t ndirty;
-
- /*
- * Size/address-ordered tree of this arena's available runs. This tree
- * is used for first-best-fit run allocation.
- */
- arena_avail_tree_t runs_avail;
-
-#ifdef MALLOC_BALANCE
- /*
- * The arena load balancing machinery needs to keep track of how much
- * lock contention there is. This value is exponentially averaged.
- */
- uint32_t contention;
-#endif
-
- /*
- * bins is used to store rings of free regions of the following sizes,
- * assuming a 16-byte quantum, 4kB pagesize, and default MALLOC_OPTIONS.
- *
- * bins[i] | size |
- * --------+------+
- * 0 | 2 |
- * 1 | 4 |
- * 2 | 8 |
- * --------+------+
- * 3 | 16 |
- * 4 | 32 |
- * 5 | 48 |
- * 6 | 64 |
- * : :
- * : :
- * 33 | 496 |
- * 34 | 512 |
- * --------+------+
- * 35 | 1024 |
- * 36 | 2048 |
- * --------+------+
- */
- arena_bin_t bins[1]; /* Dynamically sized. */
-};
-
-/******************************************************************************/
-/*
- * Data.
- */
-
-#ifndef MOZ_MEMORY_NARENAS_DEFAULT_ONE
-/* Number of CPUs. */
-static unsigned ncpus;
-#endif
-
-/* VM page size. */
-static size_t pagesize;
-static size_t pagesize_mask;
-static size_t pagesize_2pow;
-
-/* Various bin-related settings. */
-static size_t bin_maxclass; /* Max size class for bins. */
-static unsigned ntbins; /* Number of (2^n)-spaced tiny bins. */
-static unsigned nqbins; /* Number of quantum-spaced bins. */
-static unsigned nsbins; /* Number of (2^n)-spaced sub-page bins. */
-static size_t small_min;
-static size_t small_max;
-
-/* Various quantum-related settings. */
-static size_t quantum;
-static size_t quantum_mask; /* (quantum - 1). */
-
-/* Various chunk-related settings. */
-static size_t chunksize;
-static size_t chunksize_mask; /* (chunksize - 1). */
-static size_t chunk_npages;
-static size_t arena_chunk_header_npages;
-static size_t arena_maxclass; /* Max size class for arenas. */
-
-/********/
-/*
- * Chunks.
- */
-
-#ifdef MALLOC_VALIDATE
-static malloc_rtree_t *chunk_rtree;
-#endif
-
-/* Protects chunk-related data structures. */
-static malloc_mutex_t huge_mtx;
-
-/* Tree of chunks that are stand-alone huge allocations. */
-static extent_tree_t huge;
-
-#ifdef MALLOC_STATS
-/* Huge allocation statistics. */
-static uint64_t huge_nmalloc;
-static uint64_t huge_ndalloc;
-static size_t huge_allocated;
-#endif
-
-#ifdef MALLOC_PAGEFILE
-static char pagefile_templ[PATH_MAX];
-#endif
-
-/****************************/
-/*
- * base (internal allocation).
- */
-
-/*
- * Current pages that are being used for internal memory allocations. These
- * pages are carved up in cacheline-size quanta, so that there is no chance of
- * false cache line sharing.
- */
-static void *base_pages;
-static void *base_next_addr;
-#ifdef MALLOC_DECOMMIT
-static void *base_next_decommitted;
-#endif
-static void *base_past_addr; /* Addr immediately past base_pages. */
-static extent_node_t *base_nodes;
-static malloc_mutex_t base_mtx;
-#ifdef MALLOC_STATS
-static size_t base_mapped;
-# ifdef MALLOC_DECOMMIT
-static size_t base_committed;
-# endif
-#endif
-
-/********/
-/*
- * Arenas.
- */
-
-/*
- * Arenas that are used to service external requests. Not all elements of the
- * arenas array are necessarily used; arenas are created lazily as needed.
- */
-static arena_t **arenas;
-static unsigned narenas;
-#ifndef NO_TLS
-# ifdef MALLOC_BALANCE
-static unsigned narenas_2pow;
-# else
-static unsigned next_arena;
-# endif
-#endif
-#ifdef MOZ_MEMORY
-static malloc_spinlock_t arenas_lock; /* Protects arenas initialization. */
-#else
-static pthread_mutex_t arenas_lock; /* Protects arenas initialization. */
-#endif
-
-#ifndef NO_TLS
-/*
- * Map of pthread_self() --> arenas[???], used for selecting an arena to use
- * for allocations.
- */
-#ifndef MOZ_MEMORY_WINDOWS
-static __thread arena_t *arenas_map;
-#endif
-#endif
-
-#ifdef MALLOC_STATS
-/* Chunk statistics. */
-static chunk_stats_t stats_chunks;
-#endif
-
-/*******************************/
-/*
- * Runtime configuration options.
- */
-const char *_malloc_options;
-
-#ifndef MALLOC_PRODUCTION
-static bool opt_abort = true;
-#ifdef MALLOC_FILL
-static bool opt_junk = true;
-#endif
-#else
-static bool opt_abort = false;
-#ifdef MALLOC_FILL
-static bool opt_junk = false;
-#endif
-#endif
-static size_t opt_dirty_max = DIRTY_MAX_DEFAULT;
-#ifdef MALLOC_BALANCE
-static uint64_t opt_balance_threshold = BALANCE_THRESHOLD_DEFAULT;
-#endif
-static bool opt_print_stats = false;
-static size_t opt_quantum_2pow = QUANTUM_2POW_MIN;
-static size_t opt_small_max_2pow = SMALL_MAX_2POW_DEFAULT;
-static size_t opt_chunk_2pow = CHUNK_2POW_DEFAULT;
-#ifdef MALLOC_PAGEFILE
-static bool opt_pagefile = false;
-#endif
-#ifdef MALLOC_UTRACE
-static bool opt_utrace = false;
-#endif
-#ifdef MALLOC_SYSV
-static bool opt_sysv = false;
-#endif
-#ifdef MALLOC_XMALLOC
-static bool opt_xmalloc = false;
-#endif
-#ifdef MALLOC_FILL
-static bool opt_zero = false;
-#endif
-static int opt_narenas_lshift = 0;
-
-#ifdef MALLOC_UTRACE
-typedef struct {
- void *p;
- size_t s;
- void *r;
-} malloc_utrace_t;
-
-#define UTRACE(a, b, c) \
- if (opt_utrace) { \
- malloc_utrace_t ut; \
- ut.p = (a); \
- ut.s = (b); \
- ut.r = (c); \
- utrace(&ut, sizeof(ut)); \
- }
-#else
-#define UTRACE(a, b, c)
-#endif
-
-/******************************************************************************/
-/*
- * Begin function prototypes for non-inline static functions.
- */
-
-static char *umax2s(uintmax_t x, char *s);
-static bool malloc_mutex_init(malloc_mutex_t *mutex);
-static bool malloc_spin_init(malloc_spinlock_t *lock);
-static void wrtmessage(const char *p1, const char *p2, const char *p3,
- const char *p4);
-#ifdef MALLOC_STATS
-#ifdef MOZ_MEMORY_DARWIN
-/* Avoid namespace collision with OS X's malloc APIs. */
-#define malloc_printf moz_malloc_printf
-#endif
-static void malloc_printf(const char *format, ...);
-#endif
-static bool base_pages_alloc_mmap(size_t minsize);
-static bool base_pages_alloc(size_t minsize);
-static void *base_alloc(size_t size);
-static void *base_calloc(size_t number, size_t size);
-static extent_node_t *base_node_alloc(void);
-static void base_node_dealloc(extent_node_t *node);
-#ifdef MALLOC_STATS
-static void stats_print(arena_t *arena);
-#endif
-static void *pages_map(void *addr, size_t size, int pfd);
-static void pages_unmap(void *addr, size_t size);
-static void *chunk_alloc_mmap(size_t size, bool pagefile);
-#ifdef MALLOC_PAGEFILE
-static int pagefile_init(size_t size);
-static void pagefile_close(int pfd);
-#endif
-static void *chunk_alloc(size_t size, bool zero, bool pagefile);
-static void chunk_dealloc_mmap(void *chunk, size_t size);
-static void chunk_dealloc(void *chunk, size_t size);
-#ifndef NO_TLS
-static arena_t *choose_arena_hard(void);
-#endif
-static void arena_run_split(arena_t *arena, arena_run_t *run, size_t size,
- bool large, bool zero);
-static void arena_chunk_init(arena_t *arena, arena_chunk_t *chunk);
-static void arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk);
-static arena_run_t *arena_run_alloc(arena_t *arena, arena_bin_t *bin,
- size_t size, bool large, bool zero);
-static void arena_purge(arena_t *arena);
-static void arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty);
-static void arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk,
- arena_run_t *run, size_t oldsize, size_t newsize);
-static void arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk,
- arena_run_t *run, size_t oldsize, size_t newsize, bool dirty);
-static arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin);
-static void *arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin);
-static size_t arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size);
-#ifdef MALLOC_BALANCE
-static void arena_lock_balance_hard(arena_t *arena);
-#endif
-static void *arena_malloc_large(arena_t *arena, size_t size, bool zero);
-static void *arena_palloc(arena_t *arena, size_t alignment, size_t size,
- size_t alloc_size);
-static size_t arena_salloc(const void *ptr);
-static void arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk,
- void *ptr);
-static void arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk,
- void *ptr, size_t size, size_t oldsize);
-static bool arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk,
- void *ptr, size_t size, size_t oldsize);
-static bool arena_ralloc_large(void *ptr, size_t size, size_t oldsize);
-static void *arena_ralloc(void *ptr, size_t size, size_t oldsize);
-static bool arena_new(arena_t *arena);
-static arena_t *arenas_extend(unsigned ind);
-static void *huge_malloc(size_t size, bool zero);
-static void *huge_palloc(size_t alignment, size_t size);
-static void *huge_ralloc(void *ptr, size_t size, size_t oldsize);
-static void huge_dalloc(void *ptr);
-static void malloc_print_stats(void);
-#ifndef MOZ_MEMORY_WINDOWS
-static
-#endif
-bool malloc_init_hard(void);
-
-void _malloc_prefork(void);
-void _malloc_postfork(void);
-
-/*
- * End function prototypes.
- */
-/******************************************************************************/
-
-/*
- * umax2s() provides minimal integer printing functionality, which is
- * especially useful for situations where allocation in vsnprintf() calls would
- * potentially cause deadlock.
- */
-#define UMAX2S_BUFSIZE 21
-static char *
-umax2s(uintmax_t x, char *s)
-{
- unsigned i;
-
- i = UMAX2S_BUFSIZE - 1;
- s[i] = '\0';
- do {
- i--;
- s[i] = "0123456789"[x % 10];
- x /= 10;
- } while (x > 0);
-
- return (&s[i]);
-}
-
-static void
-wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4)
-{
-#ifdef MOZ_MEMORY_WINCE
- wchar_t buf[1024];
-#define WRT_PRINT(s) \
- MultiByteToWideChar(CP_ACP, 0, s, -1, buf, 1024); \
- OutputDebugStringW(buf)
-
- WRT_PRINT(p1);
- WRT_PRINT(p2);
- WRT_PRINT(p3);
- WRT_PRINT(p4);
-#else
-#if defined(MOZ_MEMORY) && !defined(MOZ_MEMORY_WINDOWS)
-#define _write write
-#endif
- _write(STDERR_FILENO, p1, (unsigned int) strlen(p1));
- _write(STDERR_FILENO, p2, (unsigned int) strlen(p2));
- _write(STDERR_FILENO, p3, (unsigned int) strlen(p3));
- _write(STDERR_FILENO, p4, (unsigned int) strlen(p4));
-#endif
-
-}
-
-#define _malloc_message malloc_message
-
-void (*_malloc_message)(const char *p1, const char *p2, const char *p3,
- const char *p4) = wrtmessage;
-
-#ifdef MALLOC_DEBUG
-# define assert(e) do { \
- if (!(e)) { \
- char line_buf[UMAX2S_BUFSIZE]; \
- _malloc_message(__FILE__, ":", umax2s(__LINE__, \
- line_buf), ": Failed assertion: "); \
- _malloc_message("\"", #e, "\"\n", ""); \
- abort(); \
- } \
-} while (0)
-#else
-#define assert(e)
-#endif
-
-/******************************************************************************/
-/*
- * Begin mutex. We can't use normal pthread mutexes in all places, because
- * they require malloc()ed memory, which causes bootstrapping issues in some
- * cases.
- */
-
-static bool
-malloc_mutex_init(malloc_mutex_t *mutex)
-{
-#if defined(MOZ_MEMORY_WINCE)
- InitializeCriticalSection(mutex);
-#elif defined(MOZ_MEMORY_WINDOWS)
- if (__isthreaded)
- if (! __crtInitCritSecAndSpinCount(mutex, _CRT_SPINCOUNT))
- return (true);
-#elif defined(MOZ_MEMORY_DARWIN)
- mutex->lock = OS_SPINLOCK_INIT;
-#elif defined(MOZ_MEMORY_LINUX) && !defined(MOZ_MEMORY_ANDROID)
- pthread_mutexattr_t attr;
- if (pthread_mutexattr_init(&attr) != 0)
- return (true);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
- if (pthread_mutex_init(mutex, &attr) != 0) {
- pthread_mutexattr_destroy(&attr);
- return (true);
- }
- pthread_mutexattr_destroy(&attr);
-#elif defined(MOZ_MEMORY)
- if (pthread_mutex_init(mutex, NULL) != 0)
- return (true);
-#else
- static const spinlock_t lock = _SPINLOCK_INITIALIZER;
-
- mutex->lock = lock;
-#endif
- return (false);
-}
-
-static inline void
-malloc_mutex_lock(malloc_mutex_t *mutex)
-{
-
-#if defined(MOZ_MEMORY_WINDOWS)
- EnterCriticalSection(mutex);
-#elif defined(MOZ_MEMORY_DARWIN)
- OSSpinLockLock(&mutex->lock);
-#elif defined(MOZ_MEMORY)
- pthread_mutex_lock(mutex);
-#else
- if (__isthreaded)
- _SPINLOCK(&mutex->lock);
-#endif
-}
-
-static inline void
-malloc_mutex_unlock(malloc_mutex_t *mutex)
-{
-
-#if defined(MOZ_MEMORY_WINDOWS)
- LeaveCriticalSection(mutex);
-#elif defined(MOZ_MEMORY_DARWIN)
- OSSpinLockUnlock(&mutex->lock);
-#elif defined(MOZ_MEMORY)
- pthread_mutex_unlock(mutex);
-#else
- if (__isthreaded)
- _SPINUNLOCK(&mutex->lock);
-#endif
-}
-
-static bool
-malloc_spin_init(malloc_spinlock_t *lock)
-{
-#if defined(MOZ_MEMORY_WINCE)
- InitializeCriticalSection(lock);
-#elif defined(MOZ_MEMORY_WINDOWS)
- if (__isthreaded)
- if (! __crtInitCritSecAndSpinCount(lock, _CRT_SPINCOUNT))
- return (true);
-#elif defined(MOZ_MEMORY_DARWIN)
- lock->lock = OS_SPINLOCK_INIT;
-#elif defined(MOZ_MEMORY_LINUX) && !defined(MOZ_MEMORY_ANDROID)
- pthread_mutexattr_t attr;
- if (pthread_mutexattr_init(&attr) != 0)
- return (true);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
- if (pthread_mutex_init(lock, &attr) != 0) {
- pthread_mutexattr_destroy(&attr);
- return (true);
- }
- pthread_mutexattr_destroy(&attr);
-#elif defined(MOZ_MEMORY)
- if (pthread_mutex_init(lock, NULL) != 0)
- return (true);
-#else
- lock->lock = _SPINLOCK_INITIALIZER;
-#endif
- return (false);
-}
-
-static inline void
-malloc_spin_lock(malloc_spinlock_t *lock)
-{
-
-#if defined(MOZ_MEMORY_WINDOWS)
- EnterCriticalSection(lock);
-#elif defined(MOZ_MEMORY_DARWIN)
- OSSpinLockLock(&lock->lock);
-#elif defined(MOZ_MEMORY)
- pthread_mutex_lock(lock);
-#else
- if (__isthreaded)
- _SPINLOCK(&lock->lock);
-#endif
-}
-
-static inline void
-malloc_spin_unlock(malloc_spinlock_t *lock)
-{
-#if defined(MOZ_MEMORY_WINDOWS)
- LeaveCriticalSection(lock);
-#elif defined(MOZ_MEMORY_DARWIN)
- OSSpinLockUnlock(&lock->lock);
-#elif defined(MOZ_MEMORY)
- pthread_mutex_unlock(lock);
-#else
- if (__isthreaded)
- _SPINUNLOCK(&lock->lock);
-#endif
-}
-
-/*
- * End mutex.
- */
-/******************************************************************************/
-/*
- * Begin spin lock. Spin locks here are actually adaptive mutexes that block
- * after a period of spinning, because unbounded spinning would allow for
- * priority inversion.
- */
-
-#if defined(MOZ_MEMORY) && !defined(MOZ_MEMORY_DARWIN)
-# define malloc_spin_init malloc_mutex_init
-# define malloc_spin_lock malloc_mutex_lock
-# define malloc_spin_unlock malloc_mutex_unlock
-#endif
-
-#ifndef MOZ_MEMORY
-/*
- * We use an unpublished interface to initialize pthread mutexes with an
- * allocation callback, in order to avoid infinite recursion.
- */
-int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex,
- void *(calloc_cb)(size_t, size_t));
-
-__weak_reference(_pthread_mutex_init_calloc_cb_stub,
- _pthread_mutex_init_calloc_cb);
-
-int
-_pthread_mutex_init_calloc_cb_stub(pthread_mutex_t *mutex,
- void *(calloc_cb)(size_t, size_t))
-{
-
- return (0);
-}
-
-static bool
-malloc_spin_init(pthread_mutex_t *lock)
-{
-
- if (_pthread_mutex_init_calloc_cb(lock, base_calloc) != 0)
- return (true);
-
- return (false);
-}
-
-static inline unsigned
-malloc_spin_lock(pthread_mutex_t *lock)
-{
- unsigned ret = 0;
-
- if (__isthreaded) {
- if (_pthread_mutex_trylock(lock) != 0) {
- unsigned i;
- volatile unsigned j;
-
- /* Exponentially back off. */
- for (i = 1; i <= SPIN_LIMIT_2POW; i++) {
- for (j = 0; j < (1U << i); j++)
- ret++;
-
- CPU_SPINWAIT;
- if (_pthread_mutex_trylock(lock) == 0)
- return (ret);
- }
-
- /*
- * Spinning failed. Block until the lock becomes
- * available, in order to avoid indefinite priority
- * inversion.
- */
- _pthread_mutex_lock(lock);
- assert((ret << BLOCK_COST_2POW) != 0);
- return (ret << BLOCK_COST_2POW);
- }
- }
-
- return (ret);
-}
-
-static inline void
-malloc_spin_unlock(pthread_mutex_t *lock)
-{
-
- if (__isthreaded)
- _pthread_mutex_unlock(lock);
-}
-#endif
-
-/*
- * End spin lock.
- */
-/******************************************************************************/
-/*
- * Begin Utility functions/macros.
- */
-
-/* Return the chunk address for allocation address a. */
-#define CHUNK_ADDR2BASE(a) \
- ((void *)((uintptr_t)(a) & ~chunksize_mask))
-
-/* Return the chunk offset of address a. */
-#define CHUNK_ADDR2OFFSET(a) \
- ((size_t)((uintptr_t)(a) & chunksize_mask))
-
-/* Return the smallest chunk multiple that is >= s. */
-#define CHUNK_CEILING(s) \
- (((s) + chunksize_mask) & ~chunksize_mask)
-
-/* Return the smallest cacheline multiple that is >= s. */
-#define CACHELINE_CEILING(s) \
- (((s) + (CACHELINE - 1)) & ~(CACHELINE - 1))
-
-/* Return the smallest quantum multiple that is >= a. */
-#define QUANTUM_CEILING(a) \
- (((a) + quantum_mask) & ~quantum_mask)
-
-/* Return the smallest pagesize multiple that is >= s. */
-#define PAGE_CEILING(s) \
- (((s) + pagesize_mask) & ~pagesize_mask)
-
-/* Compute the smallest power of 2 that is >= x. */
-static inline size_t
-pow2_ceil(size_t x)
-{
-
- x--;
- x |= x >> 1;
- x |= x >> 2;
- x |= x >> 4;
- x |= x >> 8;
- x |= x >> 16;
-#if (SIZEOF_PTR == 8)
- x |= x >> 32;
-#endif
- x++;
- return (x);
-}
-
-#ifdef MALLOC_BALANCE
-/*
- * Use a simple linear congruential pseudo-random number generator:
- *
- * prn(y) = (a*x + c) % m
- *
- * where the following constants ensure maximal period:
- *
- * a == Odd number (relatively prime to 2^n), and (a-1) is a multiple of 4.
- * c == Odd number (relatively prime to 2^n).
- * m == 2^32
- *
- * See Knuth's TAOCP 3rd Ed., Vol. 2, pg. 17 for details on these constraints.
- *
- * This choice of m has the disadvantage that the quality of the bits is
- * proportional to bit position. For example. the lowest bit has a cycle of 2,
- * the next has a cycle of 4, etc. For this reason, we prefer to use the upper
- * bits.
- */
-# define PRN_DEFINE(suffix, var, a, c) \
-static inline void \
-sprn_##suffix(uint32_t seed) \
-{ \
- var = seed; \
-} \
- \
-static inline uint32_t \
-prn_##suffix(uint32_t lg_range) \
-{ \
- uint32_t ret, x; \
- \
- assert(lg_range > 0); \
- assert(lg_range <= 32); \
- \
- x = (var * (a)) + (c); \
- var = x; \
- ret = x >> (32 - lg_range); \
- \
- return (ret); \
-}
-# define SPRN(suffix, seed) sprn_##suffix(seed)
-# define PRN(suffix, lg_range) prn_##suffix(lg_range)
-#endif
-
-#ifdef MALLOC_BALANCE
-/* Define the PRNG used for arena assignment. */
-static __thread uint32_t balance_x;
-PRN_DEFINE(balance, balance_x, 1297, 1301)
-#endif
-
-#ifdef MALLOC_UTRACE
-static int
-utrace(const void *addr, size_t len)
-{
- malloc_utrace_t *ut = (malloc_utrace_t *)addr;
-
- assert(len == sizeof(malloc_utrace_t));
-
- if (ut->p == NULL && ut->s == 0 && ut->r == NULL)
- malloc_printf("%d x USER malloc_init()\n", getpid());
- else if (ut->p == NULL && ut->r != NULL) {
- malloc_printf("%d x USER %p = malloc(%zu)\n", getpid(), ut->r,
- ut->s);
- } else if (ut->p != NULL && ut->r != NULL) {
- malloc_printf("%d x USER %p = realloc(%p, %zu)\n", getpid(),
- ut->r, ut->p, ut->s);
- } else
- malloc_printf("%d x USER free(%p)\n", getpid(), ut->p);
-
- return (0);
-}
-#endif
-
-static inline const char *
-_getprogname(void)
-{
-
- return ("<jemalloc>");
-}
-
-#ifdef MALLOC_STATS
-/*
- * Print to stderr in such a way as to (hopefully) avoid memory allocation.
- */
-static void
-malloc_printf(const char *format, ...)
-{
-#ifndef WINCE
- char buf[4096];
- va_list ap;
-
- va_start(ap, format);
- vsnprintf(buf, sizeof(buf), format, ap);
- va_end(ap);
- _malloc_message(buf, "", "", "");
-#endif
-}
-#endif
-
-/******************************************************************************/
-
-#ifdef MALLOC_DECOMMIT
-static inline void
-pages_decommit(void *addr, size_t size)
-{
-
-#ifdef MOZ_MEMORY_WINDOWS
- VirtualFree(addr, size, MEM_DECOMMIT);
-#else
- if (mmap(addr, size, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1,
- 0) == MAP_FAILED)
- abort();
-#endif
-}
-
-static inline void
-pages_commit(void *addr, size_t size)
-{
-
-# ifdef MOZ_MEMORY_WINDOWS
- VirtualAlloc(addr, size, MEM_COMMIT, PAGE_READWRITE);
-# else
- if (mmap(addr, size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE |
- MAP_ANON, -1, 0) == MAP_FAILED)
- abort();
-# endif
-}
-#endif
-
-static bool
-base_pages_alloc_mmap(size_t minsize)
-{
- bool ret;
- size_t csize;
-#ifdef MALLOC_DECOMMIT
- size_t pminsize;
-#endif
- int pfd;
-
- assert(minsize != 0);
- csize = CHUNK_CEILING(minsize);
-#ifdef MALLOC_PAGEFILE
- if (opt_pagefile) {
- pfd = pagefile_init(csize);
- if (pfd == -1)
- return (true);
- } else
-#endif
- pfd = -1;
- base_pages = pages_map(NULL, csize, pfd);
- if (base_pages == NULL) {
- ret = true;
- goto RETURN;
- }
- base_next_addr = base_pages;
- base_past_addr = (void *)((uintptr_t)base_pages + csize);
-#ifdef MALLOC_DECOMMIT
- /*
- * Leave enough pages for minsize committed, since otherwise they would
- * have to be immediately recommitted.
- */
- pminsize = PAGE_CEILING(minsize);
- base_next_decommitted = (void *)((uintptr_t)base_pages + pminsize);
- if (pminsize < csize)
- pages_decommit(base_next_decommitted, csize - pminsize);
-#endif
-#ifdef MALLOC_STATS
- base_mapped += csize;
-# ifdef MALLOC_DECOMMIT
- base_committed += pminsize;
-# endif
-#endif
-
- ret = false;
-RETURN:
-#ifdef MALLOC_PAGEFILE
- if (pfd != -1)
- pagefile_close(pfd);
-#endif
- return (false);
-}
-
-static bool
-base_pages_alloc(size_t minsize)
-{
-
- if (base_pages_alloc_mmap(minsize) == false)
- return (false);
-
- return (true);
-}
-
-static void *
-base_alloc(size_t size)
-{
- void *ret;
- size_t csize;
-
- /* Round size up to nearest multiple of the cacheline size. */
- csize = CACHELINE_CEILING(size);
-
- malloc_mutex_lock(&base_mtx);
- /* Make sure there's enough space for the allocation. */
- if ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) {
- if (base_pages_alloc(csize)) {
- malloc_mutex_unlock(&base_mtx);
- return (NULL);
- }
- }
- /* Allocate. */
- ret = base_next_addr;
- base_next_addr = (void *)((uintptr_t)base_next_addr + csize);
-#ifdef MALLOC_DECOMMIT
- /* Make sure enough pages are committed for the new allocation. */
- if ((uintptr_t)base_next_addr > (uintptr_t)base_next_decommitted) {
- void *pbase_next_addr =
- (void *)(PAGE_CEILING((uintptr_t)base_next_addr));
-
- pages_commit(base_next_decommitted, (uintptr_t)pbase_next_addr -
- (uintptr_t)base_next_decommitted);
- base_next_decommitted = pbase_next_addr;
-# ifdef MALLOC_STATS
- base_committed += (uintptr_t)pbase_next_addr -
- (uintptr_t)base_next_decommitted;
-# endif
- }
-#endif
- malloc_mutex_unlock(&base_mtx);
- VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, false);
-
- return (ret);
-}
-
-static void *
-base_calloc(size_t number, size_t size)
-{
- void *ret;
-
- ret = base_alloc(number * size);
-#ifdef MALLOC_VALGRIND
- if (ret != NULL) {
- VALGRIND_FREELIKE_BLOCK(ret, 0);
- VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, true);
- }
-#endif
- memset(ret, 0, number * size);
-
- return (ret);
-}
-
-static extent_node_t *
-base_node_alloc(void)
-{
- extent_node_t *ret;
-
- malloc_mutex_lock(&base_mtx);
- if (base_nodes != NULL) {
- ret = base_nodes;
- base_nodes = *(extent_node_t **)ret;
- VALGRIND_FREELIKE_BLOCK(ret, 0);
- VALGRIND_MALLOCLIKE_BLOCK(ret, sizeof(extent_node_t), 0, false);
- malloc_mutex_unlock(&base_mtx);
- } else {
- malloc_mutex_unlock(&base_mtx);
- ret = (extent_node_t *)base_alloc(sizeof(extent_node_t));
- }
-
- return (ret);
-}
-
-static void
-base_node_dealloc(extent_node_t *node)
-{
-
- malloc_mutex_lock(&base_mtx);
- VALGRIND_FREELIKE_BLOCK(node, 0);
- VALGRIND_MALLOCLIKE_BLOCK(node, sizeof(extent_node_t *), 0, false);
- *(extent_node_t **)node = base_nodes;
- base_nodes = node;
- malloc_mutex_unlock(&base_mtx);
-}
-
-/******************************************************************************/
-
-#ifdef MALLOC_STATS
-static void
-stats_print(arena_t *arena)
-{
- unsigned i, gap_start;
-
-#ifdef MOZ_MEMORY_WINDOWS
- malloc_printf("dirty: %Iu page%s dirty, %I64u sweep%s,"
- " %I64u madvise%s, %I64u page%s purged\n",
- arena->ndirty, arena->ndirty == 1 ? "" : "s",
- arena->stats.npurge, arena->stats.npurge == 1 ? "" : "s",
- arena->stats.nmadvise, arena->stats.nmadvise == 1 ? "" : "s",
- arena->stats.purged, arena->stats.purged == 1 ? "" : "s");
-# ifdef MALLOC_DECOMMIT
- malloc_printf("decommit: %I64u decommit%s, %I64u commit%s,"
- " %I64u page%s decommitted\n",
- arena->stats.ndecommit, (arena->stats.ndecommit == 1) ? "" : "s",
- arena->stats.ncommit, (arena->stats.ncommit == 1) ? "" : "s",
- arena->stats.decommitted,
- (arena->stats.decommitted == 1) ? "" : "s");
-# endif
-
- malloc_printf(" allocated nmalloc ndalloc\n");
- malloc_printf("small: %12Iu %12I64u %12I64u\n",
- arena->stats.allocated_small, arena->stats.nmalloc_small,
- arena->stats.ndalloc_small);
- malloc_printf("large: %12Iu %12I64u %12I64u\n",
- arena->stats.allocated_large, arena->stats.nmalloc_large,
- arena->stats.ndalloc_large);
- malloc_printf("total: %12Iu %12I64u %12I64u\n",
- arena->stats.allocated_small + arena->stats.allocated_large,
- arena->stats.nmalloc_small + arena->stats.nmalloc_large,
- arena->stats.ndalloc_small + arena->stats.ndalloc_large);
- malloc_printf("mapped: %12Iu\n", arena->stats.mapped);
-#else
- malloc_printf("dirty: %zu page%s dirty, %llu sweep%s,"
- " %llu madvise%s, %llu page%s purged\n",
- arena->ndirty, arena->ndirty == 1 ? "" : "s",
- arena->stats.npurge, arena->stats.npurge == 1 ? "" : "s",
- arena->stats.nmadvise, arena->stats.nmadvise == 1 ? "" : "s",
- arena->stats.purged, arena->stats.purged == 1 ? "" : "s");
-# ifdef MALLOC_DECOMMIT
- malloc_printf("decommit: %llu decommit%s, %llu commit%s,"
- " %llu page%s decommitted\n",
- arena->stats.ndecommit, (arena->stats.ndecommit == 1) ? "" : "s",
- arena->stats.ncommit, (arena->stats.ncommit == 1) ? "" : "s",
- arena->stats.decommitted,
- (arena->stats.decommitted == 1) ? "" : "s");
-# endif
-
- malloc_printf(" allocated nmalloc ndalloc\n");
- malloc_printf("small: %12zu %12llu %12llu\n",
- arena->stats.allocated_small, arena->stats.nmalloc_small,
- arena->stats.ndalloc_small);
- malloc_printf("large: %12zu %12llu %12llu\n",
- arena->stats.allocated_large, arena->stats.nmalloc_large,
- arena->stats.ndalloc_large);
- malloc_printf("total: %12zu %12llu %12llu\n",
- arena->stats.allocated_small + arena->stats.allocated_large,
- arena->stats.nmalloc_small + arena->stats.nmalloc_large,
- arena->stats.ndalloc_small + arena->stats.ndalloc_large);
- malloc_printf("mapped: %12zu\n", arena->stats.mapped);
-#endif
- malloc_printf("bins: bin size regs pgs requests newruns"
- " reruns maxruns curruns\n");
- for (i = 0, gap_start = UINT_MAX; i < ntbins + nqbins + nsbins; i++) {
- if (arena->bins[i].stats.nrequests == 0) {
- if (gap_start == UINT_MAX)
- gap_start = i;
- } else {
- if (gap_start != UINT_MAX) {
- if (i > gap_start + 1) {
- /* Gap of more than one size class. */
- malloc_printf("[%u..%u]\n",
- gap_start, i - 1);
- } else {
- /* Gap of one size class. */
- malloc_printf("[%u]\n", gap_start);
- }
- gap_start = UINT_MAX;
- }
- malloc_printf(
-#if defined(MOZ_MEMORY_WINDOWS)
- "%13u %1s %4u %4u %3u %9I64u %9I64u"
- " %9I64u %7u %7u\n",
-#else
- "%13u %1s %4u %4u %3u %9llu %9llu"
- " %9llu %7lu %7lu\n",
-#endif
- i,
- i < ntbins ? "T" : i < ntbins + nqbins ? "Q" : "S",
- arena->bins[i].reg_size,
- arena->bins[i].nregs,
- arena->bins[i].run_size >> pagesize_2pow,
- arena->bins[i].stats.nrequests,
- arena->bins[i].stats.nruns,
- arena->bins[i].stats.reruns,
- arena->bins[i].stats.highruns,
- arena->bins[i].stats.curruns);
- }
- }
- if (gap_start != UINT_MAX) {
- if (i > gap_start + 1) {
- /* Gap of more than one size class. */
- malloc_printf("[%u..%u]\n", gap_start, i - 1);
- } else {
- /* Gap of one size class. */
- malloc_printf("[%u]\n", gap_start);
- }
- }
-}
-#endif
-
-/*
- * End Utility functions/macros.
- */
-/******************************************************************************/
-/*
- * Begin extent tree code.
- */
-
-static inline int
-extent_szad_comp(extent_node_t *a, extent_node_t *b)
-{
- int ret;
- size_t a_size = a->size;
- size_t b_size = b->size;
-
- ret = (a_size > b_size) - (a_size < b_size);
- if (ret == 0) {
- uintptr_t a_addr = (uintptr_t)a->addr;
- uintptr_t b_addr = (uintptr_t)b->addr;
-
- ret = (a_addr > b_addr) - (a_addr < b_addr);
- }
-
- return (ret);
-}
-
-/* Wrap red-black tree macros in functions. */
-rb_wrap(static, extent_tree_szad_, extent_tree_t, extent_node_t,
- link_szad, extent_szad_comp)
-
-static inline int
-extent_ad_comp(extent_node_t *a, extent_node_t *b)
-{
- uintptr_t a_addr = (uintptr_t)a->addr;
- uintptr_t b_addr = (uintptr_t)b->addr;
-
- return ((a_addr > b_addr) - (a_addr < b_addr));
-}
-
-/* Wrap red-black tree macros in functions. */
-rb_wrap(static, extent_tree_ad_, extent_tree_t, extent_node_t, link_ad,
- extent_ad_comp)
-
-/*
- * End extent tree code.
- */
-/******************************************************************************/
-/*
- * Begin chunk management functions.
- */
-
-#ifdef MOZ_MEMORY_WINDOWS
-#ifdef MOZ_MEMORY_WINCE
-#define ALIGN_ADDR2OFFSET(al, ad) \
- ((uintptr_t)ad & (al - 1))
-static void *
-pages_map_align(size_t size, int pfd, size_t alignment)
-{
-
- void *ret;
- int offset;
- if (size % alignment)
- size += (alignment - (size % alignment));
- assert(size >= alignment);
- ret = pages_map(NULL, size, pfd);
- offset = ALIGN_ADDR2OFFSET(alignment, ret);
- if (offset) {
- /* try to over allocate by the ammount we're offset */
- void *tmp;
- pages_unmap(ret, size);
- tmp = VirtualAlloc(NULL, size + alignment - offset,
- MEM_RESERVE, PAGE_NOACCESS);
- if (offset == ALIGN_ADDR2OFFSET(alignment, tmp))
- ret = VirtualAlloc((void*)((intptr_t)tmp + alignment
- - offset), size, MEM_COMMIT,
- PAGE_READWRITE);
- else
- VirtualFree(tmp, 0, MEM_RELEASE);
- offset = ALIGN_ADDR2OFFSET(alignment, ret);
-
-
- if (offset) {
- /* over allocate to ensure we have an aligned region */
- ret = VirtualAlloc(NULL, size + alignment, MEM_RESERVE,
- PAGE_NOACCESS);
- offset = ALIGN_ADDR2OFFSET(alignment, ret);
- ret = VirtualAlloc((void*)((intptr_t)ret +
- alignment - offset),
- size, MEM_COMMIT, PAGE_READWRITE);
- }
- }
- return (ret);
-}
-#endif
-
-static void *
-pages_map(void *addr, size_t size, int pfd)
-{
- void *ret = NULL;
-#if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6)
- void *va_ret;
- assert(addr == NULL);
- va_ret = VirtualAlloc(addr, size, MEM_RESERVE, PAGE_NOACCESS);
- if (va_ret)
- ret = VirtualAlloc(va_ret, size, MEM_COMMIT, PAGE_READWRITE);
- assert(va_ret == ret);
-#else
- ret = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE,
- PAGE_READWRITE);
-#endif
- return (ret);
-}
-
-static void
-pages_unmap(void *addr, size_t size)
-{
- if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
-#if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6)
- if (GetLastError() == ERROR_INVALID_PARAMETER) {
- MEMORY_BASIC_INFORMATION info;
- VirtualQuery(addr, &info, sizeof(info));
- if (VirtualFree(info.AllocationBase, 0, MEM_RELEASE))
- return;
- }
-#endif
- _malloc_message(_getprogname(),
- ": (malloc) Error in VirtualFree()\n", "", "");
- if (opt_abort)
- abort();
- }
-}
-#elif (defined(MOZ_MEMORY_DARWIN))
-static void *
-pages_map(void *addr, size_t size, int pfd)
-{
- void *ret;
- kern_return_t err;
- int flags;
-
- if (addr != NULL) {
- ret = addr;
- flags = 0;
- } else
- flags = VM_FLAGS_ANYWHERE;
-
- err = vm_allocate((vm_map_t)mach_task_self(), (vm_address_t *)&ret,
- (vm_size_t)size, flags);
- if (err != KERN_SUCCESS)
- ret = NULL;
-
- assert(ret == NULL || (addr == NULL && ret != addr)
- || (addr != NULL && ret == addr));
- return (ret);
-}
-
-static void
-pages_unmap(void *addr, size_t size)
-{
- kern_return_t err;
-
- err = vm_deallocate((vm_map_t)mach_task_self(), (vm_address_t)addr,
- (vm_size_t)size);
- if (err != KERN_SUCCESS) {
- malloc_message(_getprogname(),
- ": (malloc) Error in vm_deallocate(): ",
- mach_error_string(err), "\n");
- if (opt_abort)
- abort();
- }
-}
-
-#define VM_COPY_MIN (pagesize << 5)
-static inline void
-pages_copy(void *dest, const void *src, size_t n)
-{
-
- assert((void *)((uintptr_t)dest & ~pagesize_mask) == dest);
- assert(n >= VM_COPY_MIN);
- assert((void *)((uintptr_t)src & ~pagesize_mask) == src);
-
- vm_copy(mach_task_self(), (vm_address_t)src, (vm_size_t)n,
- (vm_address_t)dest);
-}
-#else /* MOZ_MEMORY_DARWIN */
-#ifdef JEMALLOC_USES_MAP_ALIGN
-static void *
-pages_map_align(size_t size, int pfd, size_t alignment)
-{
- void *ret;
-
- /*
- * We don't use MAP_FIXED here, because it can cause the *replacement*
- * of existing mappings, and we only want to create new mappings.
- */
-#ifdef MOZ_MEMORY_SOLARIS
-#ifdef MALLOC_PAGEFILE
- if (pfd != -1) {
- ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
- MAP_NOSYNC | MAP_ALIGN, pfd, 0);
- } else
-#endif
- {
- ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
- MAP_NOSYNC | MAP_ALIGN | MAP_ANON, -1, 0);
- }
- assert(ret != NULL);
-
- if (ret == MAP_FAILED)
- ret = NULL;
-#else /* !MOZ_MEMORY_SOLARIS */
-#ifdef MALLOC_PAGEFILE
- if (pfd != -1) {
- ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
- MAP_NOSYNC, pfd, 0);
- } else
-#endif
- {
- ret = mmap(NULL, size + alignment, PROT_READ | PROT_WRITE, MAP_PRIVATE |
- MAP_NOSYNC | MAP_ANON, -1, 0);
- }
- assert(ret != NULL);
-
- if (ret == MAP_FAILED)
- return NULL;
-
- uintptr_t aligned_ret;
- size_t extra_size;
- aligned_ret = (uintptr_t)ret + alignment - 1;
- aligned_ret &= ~(alignment - 1);
- extra_size = aligned_ret - (uintptr_t)ret;
- munmap(ret, extra_size);
- munmap(ret + extra_size + size, alignment - extra_size);
- ret = (void*)aligned_ret;
-#endif /* ifdef MOZ_MEMORY_SOLARIS*/
- return (ret);
-}
-#endif
-
-static void *
-pages_map(void *addr, size_t size, int pfd)
-{
- void *ret;
-
- /*
- * We don't use MAP_FIXED here, because it can cause the *replacement*
- * of existing mappings, and we only want to create new mappings.
- */
-#ifdef MALLOC_PAGEFILE
- if (pfd != -1) {
- ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
- MAP_NOSYNC, pfd, 0);
- } else
-#endif
- {
- ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
- MAP_ANON, -1, 0);
- }
- assert(ret != NULL);
-
- if (ret == MAP_FAILED)
- ret = NULL;
- else if (addr != NULL && ret != addr) {
- /*
- * We succeeded in mapping memory, but not in the right place.
- */
- if (munmap(ret, size) == -1) {
- char buf[STRERROR_BUF];
-
- strerror_r(errno, buf, sizeof(buf));
- _malloc_message(_getprogname(),
- ": (malloc) Error in munmap(): ", buf, "\n");
- if (opt_abort)
- abort();
- }
- ret = NULL;
- }
-
- assert(ret == NULL || (addr == NULL && ret != addr)
- || (addr != NULL && ret == addr));
- return (ret);
-}
-
-static void
-pages_unmap(void *addr, size_t size)
-{
-
- if (munmap(addr, size) == -1) {
- char buf[STRERROR_BUF];
-
- strerror_r(errno, buf, sizeof(buf));
- _malloc_message(_getprogname(),
- ": (malloc) Error in munmap(): ", buf, "\n");
- if (opt_abort)
- abort();
- }
-}
-#endif
-
-#ifdef MALLOC_VALIDATE
-static inline malloc_rtree_t *
-malloc_rtree_new(unsigned bits)
-{
- malloc_rtree_t *ret;
- unsigned bits_per_level, height, i;
-
- bits_per_level = ffs(pow2_ceil((MALLOC_RTREE_NODESIZE /
- sizeof(void *)))) - 1;
- height = bits / bits_per_level;
- if (height * bits_per_level != bits)
- height++;
- assert(height * bits_per_level >= bits);
-
- ret = (malloc_rtree_t*)base_calloc(1, sizeof(malloc_rtree_t) + (sizeof(unsigned) *
- (height - 1)));
- if (ret == NULL)
- return (NULL);
-
- malloc_spin_init(&ret->lock);
- ret->height = height;
- if (bits_per_level * height > bits)
- ret->level2bits[0] = bits % bits_per_level;
- else
- ret->level2bits[0] = bits_per_level;
- for (i = 1; i < height; i++)
- ret->level2bits[i] = bits_per_level;
-
- ret->root = (void**)base_calloc(1, sizeof(void *) << ret->level2bits[0]);
- if (ret->root == NULL) {
- /*
- * We leak the rtree here, since there's no generic base
- * deallocation.
- */
- return (NULL);
- }
-
- return (ret);
-}
-
-/* The least significant bits of the key are ignored. */
-static inline void *
-malloc_rtree_get(malloc_rtree_t *rtree, uintptr_t key)
-{
- void *ret;
- uintptr_t subkey;
- unsigned i, lshift, height, bits;
- void **node, **child;
-
- malloc_spin_lock(&rtree->lock);
- for (i = lshift = 0, height = rtree->height, node = rtree->root;
- i < height - 1;
- i++, lshift += bits, node = child) {
- bits = rtree->level2bits[i];
- subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
- child = (void**)node[subkey];
- if (child == NULL) {
- malloc_spin_unlock(&rtree->lock);
- return (NULL);
- }
- }
-
- /* node is a leaf, so it contains values rather than node pointers. */
- bits = rtree->level2bits[i];
- subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
- ret = node[subkey];
- malloc_spin_unlock(&rtree->lock);
-
- return (ret);
-}
-
-static inline bool
-malloc_rtree_set(malloc_rtree_t *rtree, uintptr_t key, void *val)
-{
- uintptr_t subkey;
- unsigned i, lshift, height, bits;
- void **node, **child;
-
- malloc_spin_lock(&rtree->lock);
- for (i = lshift = 0, height = rtree->height, node = rtree->root;
- i < height - 1;
- i++, lshift += bits, node = child) {
- bits = rtree->level2bits[i];
- subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
- child = (void**)node[subkey];
- if (child == NULL) {
- child = (void**)base_calloc(1, sizeof(void *) <<
- rtree->level2bits[i+1]);
- if (child == NULL) {
- malloc_spin_unlock(&rtree->lock);
- return (true);
- }
- node[subkey] = child;
- }
- }
-
- /* node is a leaf, so it contains values rather than node pointers. */
- bits = rtree->level2bits[i];
- subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
- node[subkey] = val;
- malloc_spin_unlock(&rtree->lock);
-
- return (false);
-}
-#endif
-
-static void *
-chunk_alloc_mmap(size_t size, bool pagefile)
-{
- void *ret;
-#ifndef JEMALLOC_USES_MAP_ALIGN
- size_t offset;
-#endif
- int pfd;
-
-#ifdef MALLOC_PAGEFILE
- if (opt_pagefile && pagefile) {
- pfd = pagefile_init(size);
- if (pfd == -1)
- return (NULL);
- } else
-#endif
- pfd = -1;
-
- /*
- * Windows requires that there be a 1:1 mapping between VM
- * allocation/deallocation operations. Therefore, take care here to
- * acquire the final result via one mapping operation. This means
- * unmapping any preliminary result that is not correctly aligned.
- *
- * The MALLOC_PAGEFILE code also benefits from this mapping algorithm,
- * since it reduces the number of page files.
- */
-
-#ifdef JEMALLOC_USES_MAP_ALIGN
- ret = pages_map_align(size, pfd, chunksize);
-#else
- ret = pages_map(NULL, size, pfd);
- if (ret == NULL)
- goto RETURN;
-
- offset = CHUNK_ADDR2OFFSET(ret);
- if (offset != 0) {
- /* Deallocate, then try to allocate at (ret + size - offset). */
- pages_unmap(ret, size);
- ret = pages_map((void *)((uintptr_t)ret + size - offset), size,
- pfd);
- while (ret == NULL) {
- /*
- * Over-allocate in order to map a memory region that
- * is definitely large enough.
- */
- ret = pages_map(NULL, size + chunksize, -1);
- if (ret == NULL)
- goto RETURN;
- /*
- * Deallocate, then allocate the correct size, within
- * the over-sized mapping.
- */
- offset = CHUNK_ADDR2OFFSET(ret);
- pages_unmap(ret, size + chunksize);
- if (offset == 0)
- ret = pages_map(ret, size, pfd);
- else {
- ret = pages_map((void *)((uintptr_t)ret +
- chunksize - offset), size, pfd);
- }
- /*
- * Failure here indicates a race with another thread, so
- * try again.
- */
- }
- }
-RETURN:
-#endif
-#ifdef MALLOC_PAGEFILE
- if (pfd != -1)
- pagefile_close(pfd);
-#endif
-#ifdef MALLOC_STATS
- if (ret != NULL)
- stats_chunks.nchunks += (size / chunksize);
-#endif
- return (ret);
-}
-
-#ifdef MALLOC_PAGEFILE
-static int
-pagefile_init(size_t size)
-{
- int ret;
- size_t i;
- char pagefile_path[PATH_MAX];
- char zbuf[MALLOC_PAGEFILE_WRITE_SIZE];
-
- /*
- * Create a temporary file, then immediately unlink it so that it will
- * not persist.
- */
- strcpy(pagefile_path, pagefile_templ);
- ret = mkstemp(pagefile_path);
- if (ret == -1)
- return (ret);
- if (unlink(pagefile_path)) {
- char buf[STRERROR_BUF];
-
- strerror_r(errno, buf, sizeof(buf));
- _malloc_message(_getprogname(), ": (malloc) Error in unlink(\"",
- pagefile_path, "\"):");
- _malloc_message(buf, "\n", "", "");
- if (opt_abort)
- abort();
- }
-
- /*
- * Write sequential zeroes to the file in order to assure that disk
- * space is committed, with minimal fragmentation. It would be
- * sufficient to write one zero per disk block, but that potentially
- * results in more system calls, for no real gain.
- */
- memset(zbuf, 0, sizeof(zbuf));
- for (i = 0; i < size; i += sizeof(zbuf)) {
- if (write(ret, zbuf, sizeof(zbuf)) != sizeof(zbuf)) {
- if (errno != ENOSPC) {
- char buf[STRERROR_BUF];
-
- strerror_r(errno, buf, sizeof(buf));
- _malloc_message(_getprogname(),
- ": (malloc) Error in write(): ", buf, "\n");
- if (opt_abort)
- abort();
- }
- pagefile_close(ret);
- return (-1);
- }
- }
-
- return (ret);
-}
-
-static void
-pagefile_close(int pfd)
-{
-
- if (close(pfd)) {
- char buf[STRERROR_BUF];
-
- strerror_r(errno, buf, sizeof(buf));
- _malloc_message(_getprogname(),
- ": (malloc) Error in close(): ", buf, "\n");
- if (opt_abort)
- abort();
- }
-}
-#endif
-
-static void *
-chunk_alloc(size_t size, bool zero, bool pagefile)
-{
- void *ret;
-
- assert(size != 0);
- assert((size & chunksize_mask) == 0);
-
- ret = chunk_alloc_mmap(size, pagefile);
- if (ret != NULL) {
- goto RETURN;
- }
-
- /* All strategies for allocation failed. */
- ret = NULL;
-RETURN:
-#ifdef MALLOC_STATS
- if (ret != NULL)
- stats_chunks.curchunks += (size / chunksize);
- if (stats_chunks.curchunks > stats_chunks.highchunks)
- stats_chunks.highchunks = stats_chunks.curchunks;
-#endif
-
-#ifdef MALLOC_VALIDATE
- if (ret != NULL) {
- if (malloc_rtree_set(chunk_rtree, (uintptr_t)ret, ret)) {
- chunk_dealloc(ret, size);
- return (NULL);
- }
- }
-#endif
-
- assert(CHUNK_ADDR2BASE(ret) == ret);
- return (ret);
-}
-
-static void
-chunk_dealloc_mmap(void *chunk, size_t size)
-{
-
- pages_unmap(chunk, size);
-}
-
-static void
-chunk_dealloc(void *chunk, size_t size)
-{
-
- assert(chunk != NULL);
- assert(CHUNK_ADDR2BASE(chunk) == chunk);
- assert(size != 0);
- assert((size & chunksize_mask) == 0);
-
-#ifdef MALLOC_STATS
- stats_chunks.curchunks -= (size / chunksize);
-#endif
-#ifdef MALLOC_VALIDATE
- malloc_rtree_set(chunk_rtree, (uintptr_t)chunk, NULL);
-#endif
-
- chunk_dealloc_mmap(chunk, size);
-}
-
-/*
- * End chunk management functions.
- */
-/******************************************************************************/
-/*
- * Begin arena.
- */
-
-/*
- * Choose an arena based on a per-thread value (fast-path code, calls slow-path
- * code if necessary).
- */
-static inline arena_t *
-choose_arena(void)
-{
- arena_t *ret;
-
- /*
- * We can only use TLS if this is a PIC library, since for the static
- * library version, libc's malloc is used by TLS allocation, which
- * introduces a bootstrapping issue.
- */
-#ifndef NO_TLS
- if (__isthreaded == false) {
- /* Avoid the overhead of TLS for single-threaded operation. */
- return (arenas[0]);
- }
-
-# ifdef MOZ_MEMORY_WINDOWS
- ret = (arena_t*)TlsGetValue(tlsIndex);
-# else
- ret = arenas_map;
-# endif
-
- if (ret == NULL) {
- ret = choose_arena_hard();
- assert(ret != NULL);
- }
-#else
- if (__isthreaded && narenas > 1) {
- unsigned long ind;
-
- /*
- * Hash _pthread_self() to one of the arenas. There is a prime
- * number of arenas, so this has a reasonable chance of
- * working. Even so, the hashing can be easily thwarted by
- * inconvenient _pthread_self() values. Without specific
- * knowledge of how _pthread_self() calculates values, we can't
- * easily do much better than this.
- */
- ind = (unsigned long) _pthread_self() % narenas;
-
- /*
- * Optimistially assume that arenas[ind] has been initialized.
- * At worst, we find out that some other thread has already
- * done so, after acquiring the lock in preparation. Note that
- * this lazy locking also has the effect of lazily forcing
- * cache coherency; without the lock acquisition, there's no
- * guarantee that modification of arenas[ind] by another thread
- * would be seen on this CPU for an arbitrary amount of time.
- *
- * In general, this approach to modifying a synchronized value
- * isn't a good idea, but in this case we only ever modify the
- * value once, so things work out well.
- */
- ret = arenas[ind];
- if (ret == NULL) {
- /*
- * Avoid races with another thread that may have already
- * initialized arenas[ind].
- */
- malloc_spin_lock(&arenas_lock);
- if (arenas[ind] == NULL)
- ret = arenas_extend((unsigned)ind);
- else
- ret = arenas[ind];
- malloc_spin_unlock(&arenas_lock);
- }
- } else
- ret = arenas[0];
-#endif
-
- assert(ret != NULL);
- return (ret);
-}
-
-#ifndef NO_TLS
-/*
- * Choose an arena based on a per-thread value (slow-path code only, called
- * only by choose_arena()).
- */
-static arena_t *
-choose_arena_hard(void)
-{
- arena_t *ret;
-
- assert(__isthreaded);
-
-#ifdef MALLOC_BALANCE
- /* Seed the PRNG used for arena load balancing. */
- SPRN(balance, (uint32_t)(uintptr_t)(_pthread_self()));
-#endif
-
- if (narenas > 1) {
-#ifdef MALLOC_BALANCE
- unsigned ind;
-
- ind = PRN(balance, narenas_2pow);
- if ((ret = arenas[ind]) == NULL) {
- malloc_spin_lock(&arenas_lock);
- if ((ret = arenas[ind]) == NULL)
- ret = arenas_extend(ind);
- malloc_spin_unlock(&arenas_lock);
- }
-#else
- malloc_spin_lock(&arenas_lock);
- if ((ret = arenas[next_arena]) == NULL)
- ret = arenas_extend(next_arena);
- next_arena = (next_arena + 1) % narenas;
- malloc_spin_unlock(&arenas_lock);
-#endif
- } else
- ret = arenas[0];
-
-#ifdef MOZ_MEMORY_WINDOWS
- TlsSetValue(tlsIndex, ret);
-#else
- arenas_map = ret;
-#endif
-
- return (ret);
-}
-#endif
-
-static inline int
-arena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b)
-{
- uintptr_t a_chunk = (uintptr_t)a;
- uintptr_t b_chunk = (uintptr_t)b;
-
- assert(a != NULL);
- assert(b != NULL);
-
- return ((a_chunk > b_chunk) - (a_chunk < b_chunk));
-}
-
-/* Wrap red-black tree macros in functions. */
-rb_wrap(static, arena_chunk_tree_dirty_, arena_chunk_tree_t,
- arena_chunk_t, link_dirty, arena_chunk_comp)
-
-static inline int
-arena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
-{
- uintptr_t a_mapelm = (uintptr_t)a;
- uintptr_t b_mapelm = (uintptr_t)b;
-
- assert(a != NULL);
- assert(b != NULL);
-
- return ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm));
-}
-
-/* Wrap red-black tree macros in functions. */
-rb_wrap(static, arena_run_tree_, arena_run_tree_t, arena_chunk_map_t, link,
- arena_run_comp)
-
-static inline int
-arena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
-{
- int ret;
- size_t a_size = a->bits & ~pagesize_mask;
- size_t b_size = b->bits & ~pagesize_mask;
-
- ret = (a_size > b_size) - (a_size < b_size);
- if (ret == 0) {
- uintptr_t a_mapelm, b_mapelm;
-
- if ((a->bits & CHUNK_MAP_KEY) == 0)
- a_mapelm = (uintptr_t)a;
- else {
- /*
- * Treat keys as though they are lower than anything
- * else.
- */
- a_mapelm = 0;
- }
- b_mapelm = (uintptr_t)b;
-
- ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm);
- }
-
- return (ret);
-}
-
-/* Wrap red-black tree macros in functions. */
-rb_wrap(static, arena_avail_tree_, arena_avail_tree_t, arena_chunk_map_t, link,
- arena_avail_comp)
-
-static inline void *
-arena_run_reg_alloc(arena_run_t *run, arena_bin_t *bin)
-{
- void *ret;
- unsigned i, mask, bit, regind;
-
- assert(run->magic == ARENA_RUN_MAGIC);
- assert(run->regs_minelm < bin->regs_mask_nelms);
-
- /*
- * Move the first check outside the loop, so that run->regs_minelm can
- * be updated unconditionally, without the possibility of updating it
- * multiple times.
- */
- i = run->regs_minelm;
- mask = run->regs_mask[i];
- if (mask != 0) {
- /* Usable allocation found. */
- bit = ffs((int)mask) - 1;
-
- regind = ((i << (SIZEOF_INT_2POW + 3)) + bit);
- assert(regind < bin->nregs);
- ret = (void *)(((uintptr_t)run) + bin->reg0_offset
- + (bin->reg_size * regind));
-
- /* Clear bit. */
- mask ^= (1U << bit);
- run->regs_mask[i] = mask;
-
- return (ret);
- }
-
- for (i++; i < bin->regs_mask_nelms; i++) {
- mask = run->regs_mask[i];
- if (mask != 0) {
- /* Usable allocation found. */
- bit = ffs((int)mask) - 1;
-
- regind = ((i << (SIZEOF_INT_2POW + 3)) + bit);
- assert(regind < bin->nregs);
- ret = (void *)(((uintptr_t)run) + bin->reg0_offset
- + (bin->reg_size * regind));
-
- /* Clear bit. */
- mask ^= (1U << bit);
- run->regs_mask[i] = mask;
-
- /*
- * Make a note that nothing before this element
- * contains a free region.
- */
- run->regs_minelm = i; /* Low payoff: + (mask == 0); */
-
- return (ret);
- }
- }
- /* Not reached. */
- assert(0);
- return (NULL);
-}
-
-static inline void
-arena_run_reg_dalloc(arena_run_t *run, arena_bin_t *bin, void *ptr, size_t size)
-{
- /*
- * To divide by a number D that is not a power of two we multiply
- * by (2^21 / D) and then right shift by 21 positions.
- *
- * X / D
- *
- * becomes
- *
- * (X * size_invs[(D >> QUANTUM_2POW_MIN) - 3]) >> SIZE_INV_SHIFT
- */
-#define SIZE_INV_SHIFT 21
-#define SIZE_INV(s) (((1U << SIZE_INV_SHIFT) / (s << QUANTUM_2POW_MIN)) + 1)
- static const unsigned size_invs[] = {
- SIZE_INV(3),
- SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7),
- SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11),
- SIZE_INV(12),SIZE_INV(13), SIZE_INV(14), SIZE_INV(15),
- SIZE_INV(16),SIZE_INV(17), SIZE_INV(18), SIZE_INV(19),
- SIZE_INV(20),SIZE_INV(21), SIZE_INV(22), SIZE_INV(23),
- SIZE_INV(24),SIZE_INV(25), SIZE_INV(26), SIZE_INV(27),
- SIZE_INV(28),SIZE_INV(29), SIZE_INV(30), SIZE_INV(31)
-#if (QUANTUM_2POW_MIN < 4)
- ,
- SIZE_INV(32), SIZE_INV(33), SIZE_INV(34), SIZE_INV(35),
- SIZE_INV(36), SIZE_INV(37), SIZE_INV(38), SIZE_INV(39),
- SIZE_INV(40), SIZE_INV(41), SIZE_INV(42), SIZE_INV(43),
- SIZE_INV(44), SIZE_INV(45), SIZE_INV(46), SIZE_INV(47),
- SIZE_INV(48), SIZE_INV(49), SIZE_INV(50), SIZE_INV(51),
- SIZE_INV(52), SIZE_INV(53), SIZE_INV(54), SIZE_INV(55),
- SIZE_INV(56), SIZE_INV(57), SIZE_INV(58), SIZE_INV(59),
- SIZE_INV(60), SIZE_INV(61), SIZE_INV(62), SIZE_INV(63)
-#endif
- };
- unsigned diff, regind, elm, bit;
-
- assert(run->magic == ARENA_RUN_MAGIC);
- assert(((sizeof(size_invs)) / sizeof(unsigned)) + 3
- >= (SMALL_MAX_DEFAULT >> QUANTUM_2POW_MIN));
-
- /*
- * Avoid doing division with a variable divisor if possible. Using
- * actual division here can reduce allocator throughput by over 20%!
- */
- diff = (unsigned)((uintptr_t)ptr - (uintptr_t)run - bin->reg0_offset);
- if ((size & (size - 1)) == 0) {
- /*
- * log2_table allows fast division of a power of two in the
- * [1..128] range.
- *
- * (x / divisor) becomes (x >> log2_table[divisor - 1]).
- */
- static const unsigned char log2_table[] = {
- 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7
- };
-
- if (size <= 128)
- regind = (diff >> log2_table[size - 1]);
- else if (size <= 32768)
- regind = diff >> (8 + log2_table[(size >> 8) - 1]);
- else {
- /*
- * The run size is too large for us to use the lookup
- * table. Use real division.
- */
- regind = diff / size;
- }
- } else if (size <= ((sizeof(size_invs) / sizeof(unsigned))
- << QUANTUM_2POW_MIN) + 2) {
- regind = size_invs[(size >> QUANTUM_2POW_MIN) - 3] * diff;
- regind >>= SIZE_INV_SHIFT;
- } else {
- /*
- * size_invs isn't large enough to handle this size class, so
- * calculate regind using actual division. This only happens
- * if the user increases small_max via the 'S' runtime
- * configuration option.
- */
- regind = diff / size;
- };
- assert(diff == regind * size);
- assert(regind < bin->nregs);
-
- elm = regind >> (SIZEOF_INT_2POW + 3);
- if (elm < run->regs_minelm)
- run->regs_minelm = elm;
- bit = regind - (elm << (SIZEOF_INT_2POW + 3));
- assert((run->regs_mask[elm] & (1U << bit)) == 0);
- run->regs_mask[elm] |= (1U << bit);
-#undef SIZE_INV
-#undef SIZE_INV_SHIFT
-}
-
-static void
-arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large,
- bool zero)
-{
- arena_chunk_t *chunk;
- size_t old_ndirty, run_ind, total_pages, need_pages, rem_pages, i;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
- old_ndirty = chunk->ndirty;
- run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk)
- >> pagesize_2pow);
- total_pages = (chunk->map[run_ind].bits & ~pagesize_mask) >>
- pagesize_2pow;
- need_pages = (size >> pagesize_2pow);
- assert(need_pages > 0);
- assert(need_pages <= total_pages);
- rem_pages = total_pages - need_pages;
-
- arena_avail_tree_remove(&arena->runs_avail, &chunk->map[run_ind]);
-
- /* Keep track of trailing unused pages for later use. */
- if (rem_pages > 0) {
- chunk->map[run_ind+need_pages].bits = (rem_pages <<
- pagesize_2pow) | (chunk->map[run_ind+need_pages].bits &
- pagesize_mask);
- chunk->map[run_ind+total_pages-1].bits = (rem_pages <<
- pagesize_2pow) | (chunk->map[run_ind+total_pages-1].bits &
- pagesize_mask);
- arena_avail_tree_insert(&arena->runs_avail,
- &chunk->map[run_ind+need_pages]);
- }
-
- for (i = 0; i < need_pages; i++) {
-#ifdef MALLOC_DECOMMIT
- /*
- * Commit decommitted pages if necessary. If a decommitted
- * page is encountered, commit all needed adjacent decommitted
- * pages in one operation, in order to reduce system call
- * overhead.
- */
- if (chunk->map[run_ind + i].bits & CHUNK_MAP_DECOMMITTED) {
- size_t j;
-
- /*
- * Advance i+j to just past the index of the last page
- * to commit. Clear CHUNK_MAP_DECOMMITTED along the
- * way.
- */
- for (j = 0; i + j < need_pages && (chunk->map[run_ind +
- i + j].bits & CHUNK_MAP_DECOMMITTED); j++) {
- chunk->map[run_ind + i + j].bits ^=
- CHUNK_MAP_DECOMMITTED;
- }
-
- pages_commit((void *)((uintptr_t)chunk + ((run_ind + i)
- << pagesize_2pow)), (j << pagesize_2pow));
-# ifdef MALLOC_STATS
- arena->stats.ncommit++;
- arena->stats.committed += j;
-# endif
- } else /* No need to zero since commit zeros. */
-#endif
-
- /* Zero if necessary. */
- if (zero) {
- if ((chunk->map[run_ind + i].bits & CHUNK_MAP_ZEROED)
- == 0) {
- VALGRIND_MALLOCLIKE_BLOCK((void *)((uintptr_t)
- chunk + ((run_ind + i) << pagesize_2pow)),
- pagesize, 0, false);
- memset((void *)((uintptr_t)chunk + ((run_ind
- + i) << pagesize_2pow)), 0, pagesize);
- VALGRIND_FREELIKE_BLOCK((void *)((uintptr_t)
- chunk + ((run_ind + i) << pagesize_2pow)),
- 0);
- /* CHUNK_MAP_ZEROED is cleared below. */
- }
- }
-
- /* Update dirty page accounting. */
- if (chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY) {
- chunk->ndirty--;
- arena->ndirty--;
- /* CHUNK_MAP_DIRTY is cleared below. */
- }
-
- /* Initialize the chunk map. */
- if (large) {
- chunk->map[run_ind + i].bits = CHUNK_MAP_LARGE
- | CHUNK_MAP_ALLOCATED;
- } else {
- chunk->map[run_ind + i].bits = (size_t)run
- | CHUNK_MAP_ALLOCATED;
- }
- }
-
- /*
- * Set the run size only in the first element for large runs. This is
- * primarily a debugging aid, since the lack of size info for trailing
- * pages only matters if the application tries to operate on an
- * interior pointer.
- */
- if (large)
- chunk->map[run_ind].bits |= size;
-
- if (chunk->ndirty == 0 && old_ndirty > 0)
- arena_chunk_tree_dirty_remove(&arena->chunks_dirty, chunk);
-}
-
-static void
-arena_chunk_init(arena_t *arena, arena_chunk_t *chunk)
-{
- arena_run_t *run;
- size_t i;
-
- VALGRIND_MALLOCLIKE_BLOCK(chunk, (arena_chunk_header_npages <<
- pagesize_2pow), 0, false);
-#ifdef MALLOC_STATS
- arena->stats.mapped += chunksize;
-#endif
-
- chunk->arena = arena;
-
- /*
- * Claim that no pages are in use, since the header is merely overhead.
- */
- chunk->ndirty = 0;
-
- /* Initialize the map to contain one maximal free untouched run. */
- run = (arena_run_t *)((uintptr_t)chunk + (arena_chunk_header_npages <<
- pagesize_2pow));
- for (i = 0; i < arena_chunk_header_npages; i++)
- chunk->map[i].bits = 0;
- chunk->map[i].bits = arena_maxclass
-#ifdef MALLOC_DECOMMIT
- | CHUNK_MAP_DECOMMITTED
-#endif
- | CHUNK_MAP_ZEROED;
- for (i++; i < chunk_npages-1; i++) {
- chunk->map[i].bits =
-#ifdef MALLOC_DECOMMIT
- CHUNK_MAP_DECOMMITTED |
-#endif
- CHUNK_MAP_ZEROED;
- }
- chunk->map[chunk_npages-1].bits = arena_maxclass
-#ifdef MALLOC_DECOMMIT
- | CHUNK_MAP_DECOMMITTED
-#endif
- | CHUNK_MAP_ZEROED;
-
-#ifdef MALLOC_DECOMMIT
- /*
- * Start out decommitted, in order to force a closer correspondence
- * between dirty pages and committed untouched pages.
- */
- pages_decommit(run, arena_maxclass);
-# ifdef MALLOC_STATS
- arena->stats.ndecommit++;
- arena->stats.decommitted += (chunk_npages - arena_chunk_header_npages);
- arena->stats.committed += arena_chunk_header_npages;
-# endif
-#endif
-
- /* Insert the run into the runs_avail tree. */
- arena_avail_tree_insert(&arena->runs_avail,
- &chunk->map[arena_chunk_header_npages]);
-}
-
-static void
-arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk)
-{
-
- if (arena->spare != NULL) {
- if (arena->spare->ndirty > 0) {
- arena_chunk_tree_dirty_remove(
- &chunk->arena->chunks_dirty, arena->spare);
- arena->ndirty -= arena->spare->ndirty;
-#if (defined(MALLOC_STATS) && defined(MALLOC_DECOMMIT))
- arena->stats.committed -= arena->spare->ndirty;
-#endif
- }
- VALGRIND_FREELIKE_BLOCK(arena->spare, 0);
- chunk_dealloc((void *)arena->spare, chunksize);
-#ifdef MALLOC_STATS
- arena->stats.mapped -= chunksize;
-# ifdef MALLOC_DECOMMIT
- arena->stats.committed -= arena_chunk_header_npages;
-# endif
-#endif
- }
-
- /*
- * Remove run from runs_avail, so that the arena does not use it.
- * Dirty page flushing only uses the chunks_dirty tree, so leaving this
- * chunk in the chunks_* trees is sufficient for that purpose.
- */
- arena_avail_tree_remove(&arena->runs_avail,
- &chunk->map[arena_chunk_header_npages]);
-
- arena->spare = chunk;
-}
-
-static arena_run_t *
-arena_run_alloc(arena_t *arena, arena_bin_t *bin, size_t size, bool large,
- bool zero)
-{
- arena_chunk_t *chunk;
- arena_run_t *run;
- arena_chunk_map_t *mapelm, key;
-
- assert(size <= arena_maxclass);
- assert((size & pagesize_mask) == 0);
-
- chunk = NULL;
- while (true) {
- /* Search the arena's chunks for the lowest best fit. */
- key.bits = size | CHUNK_MAP_KEY;
- mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key);
- if (mapelm != NULL) {
- arena_chunk_t *run_chunk =
- (arena_chunk_t*)CHUNK_ADDR2BASE(mapelm);
- size_t pageind = ((uintptr_t)mapelm -
- (uintptr_t)run_chunk->map) /
- sizeof(arena_chunk_map_t);
-
- if (chunk != NULL)
- chunk_dealloc(chunk, chunksize);
- run = (arena_run_t *)((uintptr_t)run_chunk + (pageind
- << pagesize_2pow));
- arena_run_split(arena, run, size, large, zero);
- return (run);
- }
-
- if (arena->spare != NULL) {
- /* Use the spare. */
- chunk = arena->spare;
- arena->spare = NULL;
- run = (arena_run_t *)((uintptr_t)chunk +
- (arena_chunk_header_npages << pagesize_2pow));
- /* Insert the run into the runs_avail tree. */
- arena_avail_tree_insert(&arena->runs_avail,
- &chunk->map[arena_chunk_header_npages]);
- arena_run_split(arena, run, size, large, zero);
- return (run);
- }
-
- /*
- * No usable runs. Create a new chunk from which to allocate
- * the run.
- */
- if (chunk == NULL) {
- chunk = (arena_chunk_t *)chunk_alloc(chunksize, true,
- true);
- if (chunk == NULL)
- return (NULL);
- }
-
- arena_chunk_init(arena, chunk);
- run = (arena_run_t *)((uintptr_t)chunk +
- (arena_chunk_header_npages << pagesize_2pow));
- /* Update page map. */
- arena_run_split(arena, run, size, large, zero);
- return (run);
- }
-}
-
-static void
-arena_purge(arena_t *arena)
-{
- arena_chunk_t *chunk;
- size_t i, npages;
-#ifdef MALLOC_DEBUG
- size_t ndirty = 0;
- rb_foreach_begin(arena_chunk_t, link_dirty, &arena->chunks_dirty,
- chunk) {
- ndirty += chunk->ndirty;
- } rb_foreach_end(arena_chunk_t, link_dirty, &arena->chunks_dirty, chunk)
- assert(ndirty == arena->ndirty);
-#endif
- assert(arena->ndirty > opt_dirty_max);
-
-#ifdef MALLOC_STATS
- arena->stats.npurge++;
-#endif
-
- /*
- * Iterate downward through chunks until enough dirty memory has been
- * purged. Terminate as soon as possible in order to minimize the
- * number of system calls, even if a chunk has only been partially
- * purged.
- */
- while (arena->ndirty > (opt_dirty_max >> 1)) {
- chunk = arena_chunk_tree_dirty_last(&arena->chunks_dirty);
- assert(chunk != NULL);
-
- for (i = chunk_npages - 1; chunk->ndirty > 0; i--) {
- assert(i >= arena_chunk_header_npages);
-
- if (chunk->map[i].bits & CHUNK_MAP_DIRTY) {
-#ifdef MALLOC_DECOMMIT
- assert((chunk->map[i].bits &
- CHUNK_MAP_DECOMMITTED) == 0);
-#endif
- chunk->map[i].bits ^=
-#ifdef MALLOC_DECOMMIT
- CHUNK_MAP_DECOMMITTED |
-#endif
- CHUNK_MAP_DIRTY;
- /* Find adjacent dirty run(s). */
- for (npages = 1; i > arena_chunk_header_npages
- && (chunk->map[i - 1].bits &
- CHUNK_MAP_DIRTY); npages++) {
- i--;
-#ifdef MALLOC_DECOMMIT
- assert((chunk->map[i].bits &
- CHUNK_MAP_DECOMMITTED) == 0);
-#endif
- chunk->map[i].bits ^=
-#ifdef MALLOC_DECOMMIT
- CHUNK_MAP_DECOMMITTED |
-#endif
- CHUNK_MAP_DIRTY;
- }
- chunk->ndirty -= npages;
- arena->ndirty -= npages;
-
-#ifdef MALLOC_DECOMMIT
- pages_decommit((void *)((uintptr_t)
- chunk + (i << pagesize_2pow)),
- (npages << pagesize_2pow));
-# ifdef MALLOC_STATS
- arena->stats.ndecommit++;
- arena->stats.decommitted += npages;
- arena->stats.committed -= npages;
-# endif
-#else
- madvise((void *)((uintptr_t)chunk + (i <<
- pagesize_2pow)), (npages << pagesize_2pow),
- MADV_FREE);
-#endif
-#ifdef MALLOC_STATS
- arena->stats.nmadvise++;
- arena->stats.purged += npages;
-#endif
- if (arena->ndirty <= (opt_dirty_max >> 1))
- break;
- }
- }
-
- if (chunk->ndirty == 0) {
- arena_chunk_tree_dirty_remove(&arena->chunks_dirty,
- chunk);
- }
- }
-}
-
-static void
-arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty)
-{
- arena_chunk_t *chunk;
- size_t size, run_ind, run_pages;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
- run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk)
- >> pagesize_2pow);
- assert(run_ind >= arena_chunk_header_npages);
- assert(run_ind < chunk_npages);
- if ((chunk->map[run_ind].bits & CHUNK_MAP_LARGE) != 0)
- size = chunk->map[run_ind].bits & ~pagesize_mask;
- else
- size = run->bin->run_size;
- run_pages = (size >> pagesize_2pow);
-
- /* Mark pages as unallocated in the chunk map. */
- if (dirty) {
- size_t i;
-
- for (i = 0; i < run_pages; i++) {
- assert((chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY)
- == 0);
- chunk->map[run_ind + i].bits = CHUNK_MAP_DIRTY;
- }
-
- if (chunk->ndirty == 0) {
- arena_chunk_tree_dirty_insert(&arena->chunks_dirty,
- chunk);
- }
- chunk->ndirty += run_pages;
- arena->ndirty += run_pages;
- } else {
- size_t i;
-
- for (i = 0; i < run_pages; i++) {
- chunk->map[run_ind + i].bits &= ~(CHUNK_MAP_LARGE |
- CHUNK_MAP_ALLOCATED);
- }
- }
- chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
- pagesize_mask);
- chunk->map[run_ind+run_pages-1].bits = size |
- (chunk->map[run_ind+run_pages-1].bits & pagesize_mask);
-
- /* Try to coalesce forward. */
- if (run_ind + run_pages < chunk_npages &&
- (chunk->map[run_ind+run_pages].bits & CHUNK_MAP_ALLOCATED) == 0) {
- size_t nrun_size = chunk->map[run_ind+run_pages].bits &
- ~pagesize_mask;
-
- /*
- * Remove successor from runs_avail; the coalesced run is
- * inserted later.
- */
- arena_avail_tree_remove(&arena->runs_avail,
- &chunk->map[run_ind+run_pages]);
-
- size += nrun_size;
- run_pages = size >> pagesize_2pow;
-
- assert((chunk->map[run_ind+run_pages-1].bits & ~pagesize_mask)
- == nrun_size);
- chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
- pagesize_mask);
- chunk->map[run_ind+run_pages-1].bits = size |
- (chunk->map[run_ind+run_pages-1].bits & pagesize_mask);
- }
-
- /* Try to coalesce backward. */
- if (run_ind > arena_chunk_header_npages && (chunk->map[run_ind-1].bits &
- CHUNK_MAP_ALLOCATED) == 0) {
- size_t prun_size = chunk->map[run_ind-1].bits & ~pagesize_mask;
-
- run_ind -= prun_size >> pagesize_2pow;
-
- /*
- * Remove predecessor from runs_avail; the coalesced run is
- * inserted later.
- */
- arena_avail_tree_remove(&arena->runs_avail,
- &chunk->map[run_ind]);
-
- size += prun_size;
- run_pages = size >> pagesize_2pow;
-
- assert((chunk->map[run_ind].bits & ~pagesize_mask) ==
- prun_size);
- chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
- pagesize_mask);
- chunk->map[run_ind+run_pages-1].bits = size |
- (chunk->map[run_ind+run_pages-1].bits & pagesize_mask);
- }
-
- /* Insert into runs_avail, now that coalescing is complete. */
- arena_avail_tree_insert(&arena->runs_avail, &chunk->map[run_ind]);
-
- /* Deallocate chunk if it is now completely unused. */
- if ((chunk->map[arena_chunk_header_npages].bits & (~pagesize_mask |
- CHUNK_MAP_ALLOCATED)) == arena_maxclass)
- arena_chunk_dealloc(arena, chunk);
-
- /* Enforce opt_dirty_max. */
- if (arena->ndirty > opt_dirty_max)
- arena_purge(arena);
-}
-
-static void
-arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
- size_t oldsize, size_t newsize)
-{
- size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> pagesize_2pow;
- size_t head_npages = (oldsize - newsize) >> pagesize_2pow;
-
- assert(oldsize > newsize);
-
- /*
- * Update the chunk map so that arena_run_dalloc() can treat the
- * leading run as separately allocated.
- */
- chunk->map[pageind].bits = (oldsize - newsize) | CHUNK_MAP_LARGE |
- CHUNK_MAP_ALLOCATED;
- chunk->map[pageind+head_npages].bits = newsize | CHUNK_MAP_LARGE |
- CHUNK_MAP_ALLOCATED;
-
- arena_run_dalloc(arena, run, false);
-}
-
-static void
-arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
- size_t oldsize, size_t newsize, bool dirty)
-{
- size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> pagesize_2pow;
- size_t npages = newsize >> pagesize_2pow;
-
- assert(oldsize > newsize);
-
- /*
- * Update the chunk map so that arena_run_dalloc() can treat the
- * trailing run as separately allocated.
- */
- chunk->map[pageind].bits = newsize | CHUNK_MAP_LARGE |
- CHUNK_MAP_ALLOCATED;
- chunk->map[pageind+npages].bits = (oldsize - newsize) | CHUNK_MAP_LARGE
- | CHUNK_MAP_ALLOCATED;
-
- arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize),
- dirty);
-}
-
-static arena_run_t *
-arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin)
-{
- arena_chunk_map_t *mapelm;
- arena_run_t *run;
- unsigned i, remainder;
-
- /* Look for a usable run. */
- mapelm = arena_run_tree_first(&bin->runs);
- if (mapelm != NULL) {
- /* run is guaranteed to have available space. */
- arena_run_tree_remove(&bin->runs, mapelm);
- run = (arena_run_t *)(mapelm->bits & ~pagesize_mask);
-#ifdef MALLOC_STATS
- bin->stats.reruns++;
-#endif
- return (run);
- }
- /* No existing runs have any space available. */
-
- /* Allocate a new run. */
- run = arena_run_alloc(arena, bin, bin->run_size, false, false);
- if (run == NULL)
- return (NULL);
- /*
- * Don't initialize if a race in arena_run_alloc() allowed an existing
- * run to become usable.
- */
- if (run == bin->runcur)
- return (run);
-
- VALGRIND_MALLOCLIKE_BLOCK(run, sizeof(arena_run_t) + (sizeof(unsigned) *
- (bin->regs_mask_nelms - 1)), 0, false);
-
- /* Initialize run internals. */
- run->bin = bin;
-
- for (i = 0; i < bin->regs_mask_nelms - 1; i++)
- run->regs_mask[i] = UINT_MAX;
- remainder = bin->nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1);
- if (remainder == 0)
- run->regs_mask[i] = UINT_MAX;
- else {
- /* The last element has spare bits that need to be unset. */
- run->regs_mask[i] = (UINT_MAX >> ((1U << (SIZEOF_INT_2POW + 3))
- - remainder));
- }
-
- run->regs_minelm = 0;
-
- run->nfree = bin->nregs;
-#ifdef MALLOC_DEBUG
- run->magic = ARENA_RUN_MAGIC;
-#endif
-
-#ifdef MALLOC_STATS
- bin->stats.nruns++;
- bin->stats.curruns++;
- if (bin->stats.curruns > bin->stats.highruns)
- bin->stats.highruns = bin->stats.curruns;
-#endif
- return (run);
-}
-
-/* bin->runcur must have space available before this function is called. */
-static inline void *
-arena_bin_malloc_easy(arena_t *arena, arena_bin_t *bin, arena_run_t *run)
-{
- void *ret;
-
- assert(run->magic == ARENA_RUN_MAGIC);
- assert(run->nfree > 0);
-
- ret = arena_run_reg_alloc(run, bin);
- assert(ret != NULL);
- run->nfree--;
-
- return (ret);
-}
-
-/* Re-fill bin->runcur, then call arena_bin_malloc_easy(). */
-static void *
-arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)
-{
-
- bin->runcur = arena_bin_nonfull_run_get(arena, bin);
- if (bin->runcur == NULL)
- return (NULL);
- assert(bin->runcur->magic == ARENA_RUN_MAGIC);
- assert(bin->runcur->nfree > 0);
-
- return (arena_bin_malloc_easy(arena, bin, bin->runcur));
-}
-
-/*
- * Calculate bin->run_size such that it meets the following constraints:
- *
- * *) bin->run_size >= min_run_size
- * *) bin->run_size <= arena_maxclass
- * *) bin->run_size <= RUN_MAX_SMALL
- * *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed).
- *
- * bin->nregs, bin->regs_mask_nelms, and bin->reg0_offset are
- * also calculated here, since these settings are all interdependent.
- */
-static size_t
-arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size)
-{
- size_t try_run_size, good_run_size;
- unsigned good_nregs, good_mask_nelms, good_reg0_offset;
- unsigned try_nregs, try_mask_nelms, try_reg0_offset;
-
- assert(min_run_size >= pagesize);
- assert(min_run_size <= arena_maxclass);
- assert(min_run_size <= RUN_MAX_SMALL);
-
- /*
- * Calculate known-valid settings before entering the run_size
- * expansion loop, so that the first part of the loop always copies
- * valid settings.
- *
- * The do..while loop iteratively reduces the number of regions until
- * the run header and the regions no longer overlap. A closed formula
- * would be quite messy, since there is an interdependency between the
- * header's mask length and the number of regions.
- */
- try_run_size = min_run_size;
- try_nregs = ((try_run_size - sizeof(arena_run_t)) / bin->reg_size)
- + 1; /* Counter-act try_nregs-- in loop. */
- do {
- try_nregs--;
- try_mask_nelms = (try_nregs >> (SIZEOF_INT_2POW + 3)) +
- ((try_nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1)) ? 1 : 0);
- try_reg0_offset = try_run_size - (try_nregs * bin->reg_size);
- } while (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1))
- > try_reg0_offset);
-
- /* run_size expansion loop. */
- do {
- /*
- * Copy valid settings before trying more aggressive settings.
- */
- good_run_size = try_run_size;
- good_nregs = try_nregs;
- good_mask_nelms = try_mask_nelms;
- good_reg0_offset = try_reg0_offset;
-
- /* Try more aggressive settings. */
- try_run_size += pagesize;
- try_nregs = ((try_run_size - sizeof(arena_run_t)) /
- bin->reg_size) + 1; /* Counter-act try_nregs-- in loop. */
- do {
- try_nregs--;
- try_mask_nelms = (try_nregs >> (SIZEOF_INT_2POW + 3)) +
- ((try_nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1)) ?
- 1 : 0);
- try_reg0_offset = try_run_size - (try_nregs *
- bin->reg_size);
- } while (sizeof(arena_run_t) + (sizeof(unsigned) *
- (try_mask_nelms - 1)) > try_reg0_offset);
- } while (try_run_size <= arena_maxclass && try_run_size <= RUN_MAX_SMALL
- && RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX
- && (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size);
-
- assert(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1))
- <= good_reg0_offset);
- assert((good_mask_nelms << (SIZEOF_INT_2POW + 3)) >= good_nregs);
-
- /* Copy final settings. */
- bin->run_size = good_run_size;
- bin->nregs = good_nregs;
- bin->regs_mask_nelms = good_mask_nelms;
- bin->reg0_offset = good_reg0_offset;
-
- return (good_run_size);
-}
-
-#ifdef MALLOC_BALANCE
-static inline void
-arena_lock_balance(arena_t *arena)
-{
- unsigned contention;
-
- contention = malloc_spin_lock(&arena->lock);
- if (narenas > 1) {
- /*
- * Calculate the exponentially averaged contention for this
- * arena. Due to integer math always rounding down, this value
- * decays somewhat faster then normal.
- */
- arena->contention = (((uint64_t)arena->contention
- * (uint64_t)((1U << BALANCE_ALPHA_INV_2POW)-1))
- + (uint64_t)contention) >> BALANCE_ALPHA_INV_2POW;
- if (arena->contention >= opt_balance_threshold)
- arena_lock_balance_hard(arena);
- }
-}
-
-static void
-arena_lock_balance_hard(arena_t *arena)
-{
- uint32_t ind;
-
- arena->contention = 0;
-#ifdef MALLOC_STATS
- arena->stats.nbalance++;
-#endif
- ind = PRN(balance, narenas_2pow);
- if (arenas[ind] != NULL) {
-#ifdef MOZ_MEMORY_WINDOWS
- TlsSetValue(tlsIndex, arenas[ind]);
-#else
- arenas_map = arenas[ind];
-#endif
- } else {
- malloc_spin_lock(&arenas_lock);
- if (arenas[ind] != NULL) {
-#ifdef MOZ_MEMORY_WINDOWS
- TlsSetValue(tlsIndex, arenas[ind]);
-#else
- arenas_map = arenas[ind];
-#endif
- } else {
-#ifdef MOZ_MEMORY_WINDOWS
- TlsSetValue(tlsIndex, arenas_extend(ind));
-#else
- arenas_map = arenas_extend(ind);
-#endif
- }
- malloc_spin_unlock(&arenas_lock);
- }
-}
-#endif
-
-static inline void *
-arena_malloc_small(arena_t *arena, size_t size, bool zero)
-{
- void *ret;
- arena_bin_t *bin;
- arena_run_t *run;
-
- if (size < small_min) {
- /* Tiny. */
- size = pow2_ceil(size);
- bin = &arena->bins[ffs((int)(size >> (TINY_MIN_2POW +
- 1)))];
-#if (!defined(NDEBUG) || defined(MALLOC_STATS))
- /*
- * Bin calculation is always correct, but we may need
- * to fix size for the purposes of assertions and/or
- * stats accuracy.
- */
- if (size < (1U << TINY_MIN_2POW))
- size = (1U << TINY_MIN_2POW);
-#endif
- } else if (size <= small_max) {
- /* Quantum-spaced. */
- size = QUANTUM_CEILING(size);
- bin = &arena->bins[ntbins + (size >> opt_quantum_2pow)
- - 1];
- } else {
- /* Sub-page. */
- size = pow2_ceil(size);
- bin = &arena->bins[ntbins + nqbins
- + (ffs((int)(size >> opt_small_max_2pow)) - 2)];
- }
- assert(size == bin->reg_size);
-
-#ifdef MALLOC_BALANCE
- arena_lock_balance(arena);
-#else
- malloc_spin_lock(&arena->lock);
-#endif
- if ((run = bin->runcur) != NULL && run->nfree > 0)
- ret = arena_bin_malloc_easy(arena, bin, run);
- else
- ret = arena_bin_malloc_hard(arena, bin);
-
- if (ret == NULL) {
- malloc_spin_unlock(&arena->lock);
- return (NULL);
- }
-
-#ifdef MALLOC_STATS
- bin->stats.nrequests++;
- arena->stats.nmalloc_small++;
- arena->stats.allocated_small += size;
-#endif
- malloc_spin_unlock(&arena->lock);
-
- VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, zero);
- if (zero == false) {
-#ifdef MALLOC_FILL
- if (opt_junk)
- memset(ret, 0xa5, size);
- else if (opt_zero)
- memset(ret, 0, size);
-#endif
- } else
- memset(ret, 0, size);
-
- return (ret);
-}
-
-static void *
-arena_malloc_large(arena_t *arena, size_t size, bool zero)
-{
- void *ret;
-
- /* Large allocation. */
- size = PAGE_CEILING(size);
-#ifdef MALLOC_BALANCE
- arena_lock_balance(arena);
-#else
- malloc_spin_lock(&arena->lock);
-#endif
- ret = (void *)arena_run_alloc(arena, NULL, size, true, zero);
- if (ret == NULL) {
- malloc_spin_unlock(&arena->lock);
- return (NULL);
- }
-#ifdef MALLOC_STATS
- arena->stats.nmalloc_large++;
- arena->stats.allocated_large += size;
-#endif
- malloc_spin_unlock(&arena->lock);
-
- VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, zero);
- if (zero == false) {
-#ifdef MALLOC_FILL
- if (opt_junk)
- memset(ret, 0xa5, size);
- else if (opt_zero)
- memset(ret, 0, size);
-#endif
- }
-
- return (ret);
-}
-
-static inline void *
-arena_malloc(arena_t *arena, size_t size, bool zero)
-{
-
- assert(arena != NULL);
- assert(arena->magic == ARENA_MAGIC);
- assert(size != 0);
- assert(QUANTUM_CEILING(size) <= arena_maxclass);
-
- if (size <= bin_maxclass) {
- return (arena_malloc_small(arena, size, zero));
- } else
- return (arena_malloc_large(arena, size, zero));
-}
-
-static inline void *
-imalloc(size_t size)
-{
-
- assert(size != 0);
-
- if (size <= arena_maxclass)
- return (arena_malloc(choose_arena(), size, false));
- else
- return (huge_malloc(size, false));
-}
-
-static inline void *
-icalloc(size_t size)
-{
-
- if (size <= arena_maxclass)
- return (arena_malloc(choose_arena(), size, true));
- else
- return (huge_malloc(size, true));
-}
-
-/* Only handles large allocations that require more than page alignment. */
-static void *
-arena_palloc(arena_t *arena, size_t alignment, size_t size, size_t alloc_size)
-{
- void *ret;
- size_t offset;
- arena_chunk_t *chunk;
-
- assert((size & pagesize_mask) == 0);
- assert((alignment & pagesize_mask) == 0);
-
-#ifdef MALLOC_BALANCE
- arena_lock_balance(arena);
-#else
- malloc_spin_lock(&arena->lock);
-#endif
- ret = (void *)arena_run_alloc(arena, NULL, alloc_size, true, false);
- if (ret == NULL) {
- malloc_spin_unlock(&arena->lock);
- return (NULL);
- }
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ret);
-
- offset = (uintptr_t)ret & (alignment - 1);
- assert((offset & pagesize_mask) == 0);
- assert(offset < alloc_size);
- if (offset == 0)
- arena_run_trim_tail(arena, chunk, (arena_run_t*)ret, alloc_size, size, false);
- else {
- size_t leadsize, trailsize;
-
- leadsize = alignment - offset;
- if (leadsize > 0) {
- arena_run_trim_head(arena, chunk, (arena_run_t*)ret, alloc_size,
- alloc_size - leadsize);
- ret = (void *)((uintptr_t)ret + leadsize);
- }
-
- trailsize = alloc_size - leadsize - size;
- if (trailsize != 0) {
- /* Trim trailing space. */
- assert(trailsize < alloc_size);
- arena_run_trim_tail(arena, chunk, (arena_run_t*)ret, size + trailsize,
- size, false);
- }
- }
-
-#ifdef MALLOC_STATS
- arena->stats.nmalloc_large++;
- arena->stats.allocated_large += size;
-#endif
- malloc_spin_unlock(&arena->lock);
-
- VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, false);
-#ifdef MALLOC_FILL
- if (opt_junk)
- memset(ret, 0xa5, size);
- else if (opt_zero)
- memset(ret, 0, size);
-#endif
- return (ret);
-}
-
-static inline void *
-ipalloc(size_t alignment, size_t size)
-{
- void *ret;
- size_t ceil_size;
-
- /*
- * Round size up to the nearest multiple of alignment.
- *
- * This done, we can take advantage of the fact that for each small
- * size class, every object is aligned at the smallest power of two
- * that is non-zero in the base two representation of the size. For
- * example:
- *
- * Size | Base 2 | Minimum alignment
- * -----+----------+------------------
- * 96 | 1100000 | 32
- * 144 | 10100000 | 32
- * 192 | 11000000 | 64
- *
- * Depending on runtime settings, it is possible that arena_malloc()
- * will further round up to a power of two, but that never causes
- * correctness issues.
- */
- ceil_size = (size + (alignment - 1)) & (-alignment);
- /*
- * (ceil_size < size) protects against the combination of maximal
- * alignment and size greater than maximal alignment.
- */
- if (ceil_size < size) {
- /* size_t overflow. */
- return (NULL);
- }
-
- if (ceil_size <= pagesize || (alignment <= pagesize
- && ceil_size <= arena_maxclass))
- ret = arena_malloc(choose_arena(), ceil_size, false);
- else {
- size_t run_size;
-
- /*
- * We can't achieve sub-page alignment, so round up alignment
- * permanently; it makes later calculations simpler.
- */
- alignment = PAGE_CEILING(alignment);
- ceil_size = PAGE_CEILING(size);
- /*
- * (ceil_size < size) protects against very large sizes within
- * pagesize of SIZE_T_MAX.
- *
- * (ceil_size + alignment < ceil_size) protects against the
- * combination of maximal alignment and ceil_size large enough
- * to cause overflow. This is similar to the first overflow
- * check above, but it needs to be repeated due to the new
- * ceil_size value, which may now be *equal* to maximal
- * alignment, whereas before we only detected overflow if the
- * original size was *greater* than maximal alignment.
- */
- if (ceil_size < size || ceil_size + alignment < ceil_size) {
- /* size_t overflow. */
- return (NULL);
- }
-
- /*
- * Calculate the size of the over-size run that arena_palloc()
- * would need to allocate in order to guarantee the alignment.
- */
- if (ceil_size >= alignment)
- run_size = ceil_size + alignment - pagesize;
- else {
- /*
- * It is possible that (alignment << 1) will cause
- * overflow, but it doesn't matter because we also
- * subtract pagesize, which in the case of overflow
- * leaves us with a very large run_size. That causes
- * the first conditional below to fail, which means
- * that the bogus run_size value never gets used for
- * anything important.
- */
- run_size = (alignment << 1) - pagesize;
- }
-
- if (run_size <= arena_maxclass) {
- ret = arena_palloc(choose_arena(), alignment, ceil_size,
- run_size);
- } else if (alignment <= chunksize)
- ret = huge_malloc(ceil_size, false);
- else
- ret = huge_palloc(alignment, ceil_size);
- }
-
- assert(((uintptr_t)ret & (alignment - 1)) == 0);
- return (ret);
-}
-
-/* Return the size of the allocation pointed to by ptr. */
-static size_t
-arena_salloc(const void *ptr)
-{
- size_t ret;
- arena_chunk_t *chunk;
- size_t pageind, mapbits;
-
- assert(ptr != NULL);
- assert(CHUNK_ADDR2BASE(ptr) != ptr);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> pagesize_2pow);
- mapbits = chunk->map[pageind].bits;
- assert((mapbits & CHUNK_MAP_ALLOCATED) != 0);
- if ((mapbits & CHUNK_MAP_LARGE) == 0) {
- arena_run_t *run = (arena_run_t *)(mapbits & ~pagesize_mask);
- assert(run->magic == ARENA_RUN_MAGIC);
- ret = run->bin->reg_size;
- } else {
- ret = mapbits & ~pagesize_mask;
- assert(ret != 0);
- }
-
- return (ret);
-}
-
-#if (defined(MALLOC_VALIDATE) || defined(MOZ_MEMORY_DARWIN))
-/*
- * Validate ptr before assuming that it points to an allocation. Currently,
- * the following validation is performed:
- *
- * + Check that ptr is not NULL.
- *
- * + Check that ptr lies within a mapped chunk.
- */
-static inline size_t
-isalloc_validate(const void *ptr)
-{
- arena_chunk_t *chunk;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- if (chunk == NULL)
- return (0);
-
- if (malloc_rtree_get(chunk_rtree, (uintptr_t)chunk) == NULL)
- return (0);
-
- if (chunk != ptr) {
- assert(chunk->arena->magic == ARENA_MAGIC);
- return (arena_salloc(ptr));
- } else {
- size_t ret;
- extent_node_t *node;
- extent_node_t key;
-
- /* Chunk. */
- key.addr = (void *)chunk;
- malloc_mutex_lock(&huge_mtx);
- node = extent_tree_ad_search(&huge, &key);
- if (node != NULL)
- ret = node->size;
- else
- ret = 0;
- malloc_mutex_unlock(&huge_mtx);
- return (ret);
- }
-}
-#endif
-
-static inline size_t
-isalloc(const void *ptr)
-{
- size_t ret;
- arena_chunk_t *chunk;
-
- assert(ptr != NULL);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- if (chunk != ptr) {
- /* Region. */
- assert(chunk->arena->magic == ARENA_MAGIC);
-
- ret = arena_salloc(ptr);
- } else {
- extent_node_t *node, key;
-
- /* Chunk (huge allocation). */
-
- malloc_mutex_lock(&huge_mtx);
-
- /* Extract from tree of huge allocations. */
- key.addr = __DECONST(void *, ptr);
- node = extent_tree_ad_search(&huge, &key);
- assert(node != NULL);
-
- ret = node->size;
-
- malloc_mutex_unlock(&huge_mtx);
- }
-
- return (ret);
-}
-
-static inline void
-arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- arena_chunk_map_t *mapelm)
-{
- arena_run_t *run;
- arena_bin_t *bin;
- size_t size;
-
- run = (arena_run_t *)(mapelm->bits & ~pagesize_mask);
- assert(run->magic == ARENA_RUN_MAGIC);
- bin = run->bin;
- size = bin->reg_size;
-
-#ifdef MALLOC_FILL
- if (opt_junk)
- memset(ptr, 0x5a, size);
-#endif
-
- arena_run_reg_dalloc(run, bin, ptr, size);
- run->nfree++;
-
- if (run->nfree == bin->nregs) {
- /* Deallocate run. */
- if (run == bin->runcur)
- bin->runcur = NULL;
- else if (bin->nregs != 1) {
- size_t run_pageind = (((uintptr_t)run -
- (uintptr_t)chunk)) >> pagesize_2pow;
- arena_chunk_map_t *run_mapelm =
- &chunk->map[run_pageind];
- /*
- * This block's conditional is necessary because if the
- * run only contains one region, then it never gets
- * inserted into the non-full runs tree.
- */
- assert(arena_run_tree_search(&bin->runs, run_mapelm) ==
- run_mapelm);
- arena_run_tree_remove(&bin->runs, run_mapelm);
- }
-#ifdef MALLOC_DEBUG
- run->magic = 0;
-#endif
- VALGRIND_FREELIKE_BLOCK(run, 0);
- arena_run_dalloc(arena, run, true);
-#ifdef MALLOC_STATS
- bin->stats.curruns--;
-#endif
- } else if (run->nfree == 1 && run != bin->runcur) {
- /*
- * Make sure that bin->runcur always refers to the lowest
- * non-full run, if one exists.
- */
- if (bin->runcur == NULL)
- bin->runcur = run;
- else if ((uintptr_t)run < (uintptr_t)bin->runcur) {
- /* Switch runcur. */
- if (bin->runcur->nfree > 0) {
- arena_chunk_t *runcur_chunk =
- (arena_chunk_t*)CHUNK_ADDR2BASE(bin->runcur);
- size_t runcur_pageind =
- (((uintptr_t)bin->runcur -
- (uintptr_t)runcur_chunk)) >> pagesize_2pow;
- arena_chunk_map_t *runcur_mapelm =
- &runcur_chunk->map[runcur_pageind];
-
- /* Insert runcur. */
- assert(arena_run_tree_search(&bin->runs,
- runcur_mapelm) == NULL);
- arena_run_tree_insert(&bin->runs,
- runcur_mapelm);
- }
- bin->runcur = run;
- } else {
- size_t run_pageind = (((uintptr_t)run -
- (uintptr_t)chunk)) >> pagesize_2pow;
- arena_chunk_map_t *run_mapelm =
- &chunk->map[run_pageind];
-
- assert(arena_run_tree_search(&bin->runs, run_mapelm) ==
- NULL);
- arena_run_tree_insert(&bin->runs, run_mapelm);
- }
- }
-#ifdef MALLOC_STATS
- arena->stats.allocated_small -= size;
- arena->stats.ndalloc_small++;
-#endif
-}
-
-static void
-arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)
-{
- /* Large allocation. */
- malloc_spin_lock(&arena->lock);
-
-#ifdef MALLOC_FILL
-#ifndef MALLOC_STATS
- if (opt_junk)
-#endif
-#endif
- {
- size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >>
- pagesize_2pow;
- size_t size = chunk->map[pageind].bits & ~pagesize_mask;
-
-#ifdef MALLOC_FILL
-#ifdef MALLOC_STATS
- if (opt_junk)
-#endif
- memset(ptr, 0x5a, size);
-#endif
-#ifdef MALLOC_STATS
- arena->stats.allocated_large -= size;
-#endif
- }
-#ifdef MALLOC_STATS
- arena->stats.ndalloc_large++;
-#endif
-
- arena_run_dalloc(arena, (arena_run_t *)ptr, true);
- malloc_spin_unlock(&arena->lock);
-}
-
-static inline void
-arena_dalloc(void *ptr, size_t offset)
-{
- arena_chunk_t *chunk;
- arena_t *arena;
- size_t pageind;
- arena_chunk_map_t *mapelm;
-
- assert(ptr != NULL);
- assert(offset != 0);
- assert(CHUNK_ADDR2OFFSET(ptr) == offset);
-
- chunk = (arena_chunk_t *) ((uintptr_t)ptr - offset);
- arena = chunk->arena;
- assert(arena != NULL);
- assert(arena->magic == ARENA_MAGIC);
-
- pageind = offset >> pagesize_2pow;
- mapelm = &chunk->map[pageind];
- assert((mapelm->bits & CHUNK_MAP_ALLOCATED) != 0);
- if ((mapelm->bits & CHUNK_MAP_LARGE) == 0) {
- /* Small allocation. */
- malloc_spin_lock(&arena->lock);
- arena_dalloc_small(arena, chunk, ptr, mapelm);
- malloc_spin_unlock(&arena->lock);
- } else
- arena_dalloc_large(arena, chunk, ptr);
- VALGRIND_FREELIKE_BLOCK(ptr, 0);
-}
-
-static inline void
-idalloc(void *ptr)
-{
- size_t offset;
-
- assert(ptr != NULL);
-
- offset = CHUNK_ADDR2OFFSET(ptr);
- if (offset != 0)
- arena_dalloc(ptr, offset);
- else
- huge_dalloc(ptr);
-}
-
-static void
-arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- size_t size, size_t oldsize)
-{
-
- assert(size < oldsize);
-
- /*
- * Shrink the run, and make trailing pages available for other
- * allocations.
- */
-#ifdef MALLOC_BALANCE
- arena_lock_balance(arena);
-#else
- malloc_spin_lock(&arena->lock);
-#endif
- arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size,
- true);
-#ifdef MALLOC_STATS
- arena->stats.allocated_large -= oldsize - size;
-#endif
- malloc_spin_unlock(&arena->lock);
-}
-
-static bool
-arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- size_t size, size_t oldsize)
-{
- size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> pagesize_2pow;
- size_t npages = oldsize >> pagesize_2pow;
-
- assert(oldsize == (chunk->map[pageind].bits & ~pagesize_mask));
-
- /* Try to extend the run. */
- assert(size > oldsize);
-#ifdef MALLOC_BALANCE
- arena_lock_balance(arena);
-#else
- malloc_spin_lock(&arena->lock);
-#endif
- if (pageind + npages < chunk_npages && (chunk->map[pageind+npages].bits
- & CHUNK_MAP_ALLOCATED) == 0 && (chunk->map[pageind+npages].bits &
- ~pagesize_mask) >= size - oldsize) {
- /*
- * The next run is available and sufficiently large. Split the
- * following run, then merge the first part with the existing
- * allocation.
- */
- arena_run_split(arena, (arena_run_t *)((uintptr_t)chunk +
- ((pageind+npages) << pagesize_2pow)), size - oldsize, true,
- false);
-
- chunk->map[pageind].bits = size | CHUNK_MAP_LARGE |
- CHUNK_MAP_ALLOCATED;
- chunk->map[pageind+npages].bits = CHUNK_MAP_LARGE |
- CHUNK_MAP_ALLOCATED;
-
-#ifdef MALLOC_STATS
- arena->stats.allocated_large += size - oldsize;
-#endif
- malloc_spin_unlock(&arena->lock);
- return (false);
- }
- malloc_spin_unlock(&arena->lock);
-
- return (true);
-}
-
-/*
- * Try to resize a large allocation, in order to avoid copying. This will
- * always fail if growing an object, and the following run is already in use.
- */
-static bool
-arena_ralloc_large(void *ptr, size_t size, size_t oldsize)
-{
- size_t psize;
-
- psize = PAGE_CEILING(size);
- if (psize == oldsize) {
- /* Same size class. */
-#ifdef MALLOC_FILL
- if (opt_junk && size < oldsize) {
- memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize -
- size);
- }
-#endif
- return (false);
- } else {
- arena_chunk_t *chunk;
- arena_t *arena;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- arena = chunk->arena;
- assert(arena->magic == ARENA_MAGIC);
-
- if (psize < oldsize) {
-#ifdef MALLOC_FILL
- /* Fill before shrinking in order avoid a race. */
- if (opt_junk) {
- memset((void *)((uintptr_t)ptr + size), 0x5a,
- oldsize - size);
- }
-#endif
- arena_ralloc_large_shrink(arena, chunk, ptr, psize,
- oldsize);
- return (false);
- } else {
- bool ret = arena_ralloc_large_grow(arena, chunk, ptr,
- psize, oldsize);
-#ifdef MALLOC_FILL
- if (ret == false && opt_zero) {
- memset((void *)((uintptr_t)ptr + oldsize), 0,
- size - oldsize);
- }
-#endif
- return (ret);
- }
- }
-}
-
-static void *
-arena_ralloc(void *ptr, size_t size, size_t oldsize)
-{
- void *ret;
- size_t copysize;
-
- /* Try to avoid moving the allocation. */
- if (size < small_min) {
- if (oldsize < small_min &&
- ffs((int)(pow2_ceil(size) >> (TINY_MIN_2POW + 1)))
- == ffs((int)(pow2_ceil(oldsize) >> (TINY_MIN_2POW + 1))))
- goto IN_PLACE; /* Same size class. */
- } else if (size <= small_max) {
- if (oldsize >= small_min && oldsize <= small_max &&
- (QUANTUM_CEILING(size) >> opt_quantum_2pow)
- == (QUANTUM_CEILING(oldsize) >> opt_quantum_2pow))
- goto IN_PLACE; /* Same size class. */
- } else if (size <= bin_maxclass) {
- if (oldsize > small_max && oldsize <= bin_maxclass &&
- pow2_ceil(size) == pow2_ceil(oldsize))
- goto IN_PLACE; /* Same size class. */
- } else if (oldsize > bin_maxclass && oldsize <= arena_maxclass) {
- assert(size > bin_maxclass);
- if (arena_ralloc_large(ptr, size, oldsize) == false)
- return (ptr);
- }
-
- /*
- * If we get here, then size and oldsize are different enough that we
- * need to move the object. In that case, fall back to allocating new
- * space and copying.
- */
- ret = arena_malloc(choose_arena(), size, false);
- if (ret == NULL)
- return (NULL);
-
- /* Junk/zero-filling were already done by arena_malloc(). */
- copysize = (size < oldsize) ? size : oldsize;
-#ifdef VM_COPY_MIN
- if (copysize >= VM_COPY_MIN)
- pages_copy(ret, ptr, copysize);
- else
-#endif
- memcpy(ret, ptr, copysize);
- idalloc(ptr);
- return (ret);
-IN_PLACE:
-#ifdef MALLOC_FILL
- if (opt_junk && size < oldsize)
- memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size);
- else if (opt_zero && size > oldsize)
- memset((void *)((uintptr_t)ptr + oldsize), 0, size - oldsize);
-#endif
- return (ptr);
-}
-
-static inline void *
-iralloc(void *ptr, size_t size)
-{
- size_t oldsize;
-
- assert(ptr != NULL);
- assert(size != 0);
-
- oldsize = isalloc(ptr);
-
-#ifndef MALLOC_VALGRIND
- if (size <= arena_maxclass)
- return (arena_ralloc(ptr, size, oldsize));
- else
- return (huge_ralloc(ptr, size, oldsize));
-#else
- /*
- * Valgrind does not provide a public interface for modifying an
- * existing allocation, so use malloc/memcpy/free instead.
- */
- {
- void *ret = imalloc(size);
- if (ret != NULL) {
- if (oldsize < size)
- memcpy(ret, ptr, oldsize);
- else
- memcpy(ret, ptr, size);
- idalloc(ptr);
- }
- return (ret);
- }
-#endif
-}
-
-static bool
-arena_new(arena_t *arena)
-{
- unsigned i;
- arena_bin_t *bin;
- size_t pow2_size, prev_run_size;
-
- if (malloc_spin_init(&arena->lock))
- return (true);
-
-#ifdef MALLOC_STATS
- memset(&arena->stats, 0, sizeof(arena_stats_t));
-#endif
-
- /* Initialize chunks. */
- arena_chunk_tree_dirty_new(&arena->chunks_dirty);
- arena->spare = NULL;
-
- arena->ndirty = 0;
-
- arena_avail_tree_new(&arena->runs_avail);
-
-#ifdef MALLOC_BALANCE
- arena->contention = 0;
-#endif
-
- /* Initialize bins. */
- prev_run_size = pagesize;
-
- /* (2^n)-spaced tiny bins. */
- for (i = 0; i < ntbins; i++) {
- bin = &arena->bins[i];
- bin->runcur = NULL;
- arena_run_tree_new(&bin->runs);
-
- bin->reg_size = (1U << (TINY_MIN_2POW + i));
-
- prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
-
-#ifdef MALLOC_STATS
- memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
-#endif
- }
-
- /* Quantum-spaced bins. */
- for (; i < ntbins + nqbins; i++) {
- bin = &arena->bins[i];
- bin->runcur = NULL;
- arena_run_tree_new(&bin->runs);
-
- bin->reg_size = quantum * (i - ntbins + 1);
-
- pow2_size = pow2_ceil(quantum * (i - ntbins + 1));
- prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
-
-#ifdef MALLOC_STATS
- memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
-#endif
- }
-
- /* (2^n)-spaced sub-page bins. */
- for (; i < ntbins + nqbins + nsbins; i++) {
- bin = &arena->bins[i];
- bin->runcur = NULL;
- arena_run_tree_new(&bin->runs);
-
- bin->reg_size = (small_max << (i - (ntbins + nqbins) + 1));
-
- prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
-
-#ifdef MALLOC_STATS
- memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
-#endif
- }
-
-#ifdef MALLOC_DEBUG
- arena->magic = ARENA_MAGIC;
-#endif
-
- return (false);
-}
-
-/* Create a new arena and insert it into the arenas array at index ind. */
-static arena_t *
-arenas_extend(unsigned ind)
-{
- arena_t *ret;
-
- /* Allocate enough space for trailing bins. */
- ret = (arena_t *)base_alloc(sizeof(arena_t)
- + (sizeof(arena_bin_t) * (ntbins + nqbins + nsbins - 1)));
- if (ret != NULL && arena_new(ret) == false) {
- arenas[ind] = ret;
- return (ret);
- }
- /* Only reached if there is an OOM error. */
-
- /*
- * OOM here is quite inconvenient to propagate, since dealing with it
- * would require a check for failure in the fast path. Instead, punt
- * by using arenas[0]. In practice, this is an extremely unlikely
- * failure.
- */
- _malloc_message(_getprogname(),
- ": (malloc) Error initializing arena\n", "", "");
- if (opt_abort)
- abort();
-
- return (arenas[0]);
-}
-
-/*
- * End arena.
- */
-/******************************************************************************/
-/*
- * Begin general internal functions.
- */
-
-static void *
-huge_malloc(size_t size, bool zero)
-{
- void *ret;
- size_t csize;
-#ifdef MALLOC_DECOMMIT
- size_t psize;
-#endif
- extent_node_t *node;
-
- /* Allocate one or more contiguous chunks for this request. */
-
- csize = CHUNK_CEILING(size);
- if (csize == 0) {
- /* size is large enough to cause size_t wrap-around. */
- return (NULL);
- }
-
- /* Allocate an extent node with which to track the chunk. */
- node = base_node_alloc();
- if (node == NULL)
- return (NULL);
-
- ret = chunk_alloc(csize, zero, true);
- if (ret == NULL) {
- base_node_dealloc(node);
- return (NULL);
- }
-
- /* Insert node into huge. */
- node->addr = ret;
-#ifdef MALLOC_DECOMMIT
- psize = PAGE_CEILING(size);
- node->size = psize;
-#else
- node->size = csize;
-#endif
-
- malloc_mutex_lock(&huge_mtx);
- extent_tree_ad_insert(&huge, node);
-#ifdef MALLOC_STATS
- huge_nmalloc++;
-# ifdef MALLOC_DECOMMIT
- huge_allocated += psize;
-# else
- huge_allocated += csize;
-# endif
-#endif
- malloc_mutex_unlock(&huge_mtx);
-
-#ifdef MALLOC_DECOMMIT
- if (csize - psize > 0)
- pages_decommit((void *)((uintptr_t)ret + psize), csize - psize);
-#endif
-
-#ifdef MALLOC_DECOMMIT
- VALGRIND_MALLOCLIKE_BLOCK(ret, psize, 0, zero);
-#else
- VALGRIND_MALLOCLIKE_BLOCK(ret, csize, 0, zero);
-#endif
-
-#ifdef MALLOC_FILL
- if (zero == false) {
- if (opt_junk)
-# ifdef MALLOC_DECOMMIT
- memset(ret, 0xa5, psize);
-# else
- memset(ret, 0xa5, csize);
-# endif
- else if (opt_zero)
-# ifdef MALLOC_DECOMMIT
- memset(ret, 0, psize);
-# else
- memset(ret, 0, csize);
-# endif
- }
-#endif
-
- return (ret);
-}
-
-/* Only handles large allocations that require more than chunk alignment. */
-static void *
-huge_palloc(size_t alignment, size_t size)
-{
- void *ret;
- size_t alloc_size, chunk_size, offset;
-#ifdef MALLOC_DECOMMIT
- size_t psize;
-#endif
- extent_node_t *node;
- int pfd;
-
- /*
- * This allocation requires alignment that is even larger than chunk
- * alignment. This means that huge_malloc() isn't good enough.
- *
- * Allocate almost twice as many chunks as are demanded by the size or
- * alignment, in order to assure the alignment can be achieved, then
- * unmap leading and trailing chunks.
- */
- assert(alignment >= chunksize);
-
- chunk_size = CHUNK_CEILING(size);
-
- if (size >= alignment)
- alloc_size = chunk_size + alignment - chunksize;
- else
- alloc_size = (alignment << 1) - chunksize;
-
- /* Allocate an extent node with which to track the chunk. */
- node = base_node_alloc();
- if (node == NULL)
- return (NULL);
-
- /*
- * Windows requires that there be a 1:1 mapping between VM
- * allocation/deallocation operations. Therefore, take care here to
- * acquire the final result via one mapping operation.
- *
- * The MALLOC_PAGEFILE code also benefits from this mapping algorithm,
- * since it reduces the number of page files.
- */
-#ifdef MALLOC_PAGEFILE
- if (opt_pagefile) {
- pfd = pagefile_init(size);
- if (pfd == -1)
- return (NULL);
- } else
-#endif
- pfd = -1;
-#ifdef JEMALLOC_USES_MAP_ALIGN
- ret = pages_map_align(chunk_size, pfd, alignment);
-#else
- do {
- void *over;
-
- over = chunk_alloc(alloc_size, false, false);
- if (over == NULL) {
- base_node_dealloc(node);
- ret = NULL;
- goto RETURN;
- }
-
- offset = (uintptr_t)over & (alignment - 1);
- assert((offset & chunksize_mask) == 0);
- assert(offset < alloc_size);
- ret = (void *)((uintptr_t)over + offset);
- chunk_dealloc(over, alloc_size);
- ret = pages_map(ret, chunk_size, pfd);
- /*
- * Failure here indicates a race with another thread, so try
- * again.
- */
- } while (ret == NULL);
-#endif
- /* Insert node into huge. */
- node->addr = ret;
-#ifdef MALLOC_DECOMMIT
- psize = PAGE_CEILING(size);
- node->size = psize;
-#else
- node->size = chunk_size;
-#endif
-
- malloc_mutex_lock(&huge_mtx);
- extent_tree_ad_insert(&huge, node);
-#ifdef MALLOC_STATS
- huge_nmalloc++;
-# ifdef MALLOC_DECOMMIT
- huge_allocated += psize;
-# else
- huge_allocated += chunk_size;
-# endif
-#endif
- malloc_mutex_unlock(&huge_mtx);
-
-#ifdef MALLOC_DECOMMIT
- if (chunk_size - psize > 0) {
- pages_decommit((void *)((uintptr_t)ret + psize),
- chunk_size - psize);
- }
-#endif
-
-#ifdef MALLOC_DECOMMIT
- VALGRIND_MALLOCLIKE_BLOCK(ret, psize, 0, false);
-#else
- VALGRIND_MALLOCLIKE_BLOCK(ret, chunk_size, 0, false);
-#endif
-
-#ifdef MALLOC_FILL
- if (opt_junk)
-# ifdef MALLOC_DECOMMIT
- memset(ret, 0xa5, psize);
-# else
- memset(ret, 0xa5, chunk_size);
-# endif
- else if (opt_zero)
-# ifdef MALLOC_DECOMMIT
- memset(ret, 0, psize);
-# else
- memset(ret, 0, chunk_size);
-# endif
-#endif
-
-RETURN:
-#ifdef MALLOC_PAGEFILE
- if (pfd != -1)
- pagefile_close(pfd);
-#endif
- return (ret);
-}
-
-static void *
-huge_ralloc(void *ptr, size_t size, size_t oldsize)
-{
- void *ret;
- size_t copysize;
-
- /* Avoid moving the allocation if the size class would not change. */
-
- if (oldsize > arena_maxclass &&
- CHUNK_CEILING(size) == CHUNK_CEILING(oldsize)) {
-#ifdef MALLOC_DECOMMIT
- size_t psize = PAGE_CEILING(size);
-#endif
-#ifdef MALLOC_FILL
- if (opt_junk && size < oldsize) {
- memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize
- - size);
- }
-#endif
-#ifdef MALLOC_DECOMMIT
- if (psize < oldsize) {
- extent_node_t *node, key;
-
- pages_decommit((void *)((uintptr_t)ptr + psize),
- oldsize - psize);
-
- /* Update recorded size. */
- malloc_mutex_lock(&huge_mtx);
- key.addr = __DECONST(void *, ptr);
- node = extent_tree_ad_search(&huge, &key);
- assert(node != NULL);
- assert(node->size == oldsize);
-# ifdef MALLOC_STATS
- huge_allocated -= oldsize - psize;
-# endif
- node->size = psize;
- malloc_mutex_unlock(&huge_mtx);
- } else if (psize > oldsize) {
- extent_node_t *node, key;
-
- pages_commit((void *)((uintptr_t)ptr + oldsize),
- psize - oldsize);
-
- /* Update recorded size. */
- malloc_mutex_lock(&huge_mtx);
- key.addr = __DECONST(void *, ptr);
- node = extent_tree_ad_search(&huge, &key);
- assert(node != NULL);
- assert(node->size == oldsize);
-# ifdef MALLOC_STATS
- huge_allocated += psize - oldsize;
-# endif
- node->size = psize;
- malloc_mutex_unlock(&huge_mtx);
- }
-#endif
-#ifdef MALLOC_FILL
- if (opt_zero && size > oldsize) {
- memset((void *)((uintptr_t)ptr + oldsize), 0, size
- - oldsize);
- }
-#endif
- return (ptr);
- }
-
- /*
- * If we get here, then size and oldsize are different enough that we
- * need to use a different size class. In that case, fall back to
- * allocating new space and copying.
- */
- ret = huge_malloc(size, false);
- if (ret == NULL)
- return (NULL);
-
- copysize = (size < oldsize) ? size : oldsize;
-#ifdef VM_COPY_MIN
- if (copysize >= VM_COPY_MIN)
- pages_copy(ret, ptr, copysize);
- else
-#endif
- memcpy(ret, ptr, copysize);
- idalloc(ptr);
- return (ret);
-}
-
-static void
-huge_dalloc(void *ptr)
-{
- extent_node_t *node, key;
-
- malloc_mutex_lock(&huge_mtx);
-
- /* Extract from tree of huge allocations. */
- key.addr = ptr;
- node = extent_tree_ad_search(&huge, &key);
- assert(node != NULL);
- assert(node->addr == ptr);
- extent_tree_ad_remove(&huge, node);
-
-#ifdef MALLOC_STATS
- huge_ndalloc++;
- huge_allocated -= node->size;
-#endif
-
- malloc_mutex_unlock(&huge_mtx);
-
- /* Unmap chunk. */
-#ifdef MALLOC_FILL
- if (opt_junk)
- memset(node->addr, 0x5a, node->size);
-#endif
-#ifdef MALLOC_DECOMMIT
- chunk_dealloc(node->addr, CHUNK_CEILING(node->size));
-#else
- chunk_dealloc(node->addr, node->size);
-#endif
- VALGRIND_FREELIKE_BLOCK(node->addr, 0);
-
- base_node_dealloc(node);
-}
-
-#ifndef MOZ_MEMORY_NARENAS_DEFAULT_ONE
-#ifdef MOZ_MEMORY_BSD
-static inline unsigned
-malloc_ncpus(void)
-{
- unsigned ret;
- int mib[2];
- size_t len;
-
- mib[0] = CTL_HW;
- mib[1] = HW_NCPU;
- len = sizeof(ret);
- if (sysctl(mib, 2, &ret, &len, (void *) 0, 0) == -1) {
- /* Error. */
- return (1);
- }
-
- return (ret);
-}
-#elif (defined(MOZ_MEMORY_LINUX))
-#include <fcntl.h>
-
-static inline unsigned
-malloc_ncpus(void)
-{
- unsigned ret;
- int fd, nread, column;
- char buf[1024];
- static const char matchstr[] = "processor\t:";
- int i;
-
- /*
- * sysconf(3) would be the preferred method for determining the number
- * of CPUs, but it uses malloc internally, which causes untennable
- * recursion during malloc initialization.
- */
- fd = open("/proc/cpuinfo", O_RDONLY);
- if (fd == -1)
- return (1); /* Error. */
- /*
- * Count the number of occurrences of matchstr at the beginnings of
- * lines. This treats hyperthreaded CPUs as multiple processors.
- */
- column = 0;
- ret = 0;
- while (true) {
- nread = read(fd, &buf, sizeof(buf));
- if (nread <= 0)
- break; /* EOF or error. */
- for (i = 0;i < nread;i++) {
- char c = buf[i];
- if (c == '\n')
- column = 0;
- else if (column != -1) {
- if (c == matchstr[column]) {
- column++;
- if (column == sizeof(matchstr) - 1) {
- column = -1;
- ret++;
- }
- } else
- column = -1;
- }
- }
- }
-
- if (ret == 0)
- ret = 1; /* Something went wrong in the parser. */
- close(fd);
-
- return (ret);
-}
-#elif (defined(MOZ_MEMORY_DARWIN))
-#include <mach/mach_init.h>
-#include <mach/mach_host.h>
-
-static inline unsigned
-malloc_ncpus(void)
-{
- kern_return_t error;
- natural_t n;
- processor_info_array_t pinfo;
- mach_msg_type_number_t pinfocnt;
-
- error = host_processor_info(mach_host_self(), PROCESSOR_BASIC_INFO,
- &n, &pinfo, &pinfocnt);
- if (error != KERN_SUCCESS)
- return (1); /* Error. */
- else
- return (n);
-}
-#elif (defined(MOZ_MEMORY_SOLARIS))
-
-static inline unsigned
-malloc_ncpus(void)
-{
- return sysconf(_SC_NPROCESSORS_ONLN);
-}
-#else
-static inline unsigned
-malloc_ncpus(void)
-{
-
- /*
- * We lack a way to determine the number of CPUs on this platform, so
- * assume 1 CPU.
- */
- return (1);
-}
-#endif
-#endif
-
-static void
-malloc_print_stats(void)
-{
-
- if (opt_print_stats) {
- char s[UMAX2S_BUFSIZE];
- _malloc_message("___ Begin malloc statistics ___\n", "", "",
- "");
- _malloc_message("Assertions ",
-#ifdef NDEBUG
- "disabled",
-#else
- "enabled",
-#endif
- "\n", "");
- _malloc_message("Boolean MALLOC_OPTIONS: ",
- opt_abort ? "A" : "a", "", "");
-#ifdef MALLOC_FILL
- _malloc_message(opt_junk ? "J" : "j", "", "", "");
-#endif
-#ifdef MALLOC_PAGEFILE
- _malloc_message(opt_pagefile ? "o" : "O", "", "", "");
-#endif
- _malloc_message("P", "", "", "");
-#ifdef MALLOC_UTRACE
- _malloc_message(opt_utrace ? "U" : "u", "", "", "");
-#endif
-#ifdef MALLOC_SYSV
- _malloc_message(opt_sysv ? "V" : "v", "", "", "");
-#endif
-#ifdef MALLOC_XMALLOC
- _malloc_message(opt_xmalloc ? "X" : "x", "", "", "");
-#endif
-#ifdef MALLOC_FILL
- _malloc_message(opt_zero ? "Z" : "z", "", "", "");
-#endif
- _malloc_message("\n", "", "", "");
-
-#ifndef MOZ_MEMORY_NARENAS_DEFAULT_ONE
- _malloc_message("CPUs: ", umax2s(ncpus, s), "\n", "");
-#endif
- _malloc_message("Max arenas: ", umax2s(narenas, s), "\n", "");
-#ifdef MALLOC_BALANCE
- _malloc_message("Arena balance threshold: ",
- umax2s(opt_balance_threshold, s), "\n", "");
-#endif
- _malloc_message("Pointer size: ", umax2s(sizeof(void *), s),
- "\n", "");
- _malloc_message("Quantum size: ", umax2s(quantum, s), "\n", "");
- _malloc_message("Max small size: ", umax2s(small_max, s), "\n",
- "");
- _malloc_message("Max dirty pages per arena: ",
- umax2s(opt_dirty_max, s), "\n", "");
-
- _malloc_message("Chunk size: ", umax2s(chunksize, s), "", "");
- _malloc_message(" (2^", umax2s(opt_chunk_2pow, s), ")\n", "");
-
-#ifdef MALLOC_STATS
- {
- size_t allocated, mapped;
-#ifdef MALLOC_BALANCE
- uint64_t nbalance = 0;
-#endif
- unsigned i;
- arena_t *arena;
-
- /* Calculate and print allocated/mapped stats. */
-
- /* arenas. */
- for (i = 0, allocated = 0; i < narenas; i++) {
- if (arenas[i] != NULL) {
- malloc_spin_lock(&arenas[i]->lock);
- allocated +=
- arenas[i]->stats.allocated_small;
- allocated +=
- arenas[i]->stats.allocated_large;
-#ifdef MALLOC_BALANCE
- nbalance += arenas[i]->stats.nbalance;
-#endif
- malloc_spin_unlock(&arenas[i]->lock);
- }
- }
-
- /* huge/base. */
- malloc_mutex_lock(&huge_mtx);
- allocated += huge_allocated;
- mapped = stats_chunks.curchunks * chunksize;
- malloc_mutex_unlock(&huge_mtx);
-
- malloc_mutex_lock(&base_mtx);
- mapped += base_mapped;
- malloc_mutex_unlock(&base_mtx);
-
-#ifdef MOZ_MEMORY_WINDOWS
- malloc_printf("Allocated: %lu, mapped: %lu\n",
- allocated, mapped);
-#else
- malloc_printf("Allocated: %zu, mapped: %zu\n",
- allocated, mapped);
-#endif
-
-#ifdef MALLOC_BALANCE
- malloc_printf("Arena balance reassignments: %llu\n",
- nbalance);
-#endif
-
- /* Print chunk stats. */
- {
- chunk_stats_t chunks_stats;
-
- malloc_mutex_lock(&huge_mtx);
- chunks_stats = stats_chunks;
- malloc_mutex_unlock(&huge_mtx);
-
- malloc_printf("chunks: nchunks "
- "highchunks curchunks\n");
- malloc_printf(" %13llu%13lu%13lu\n",
- chunks_stats.nchunks,
- chunks_stats.highchunks,
- chunks_stats.curchunks);
- }
-
- /* Print chunk stats. */
- malloc_printf(
- "huge: nmalloc ndalloc allocated\n");
-#ifdef MOZ_MEMORY_WINDOWS
- malloc_printf(" %12llu %12llu %12lu\n",
- huge_nmalloc, huge_ndalloc, huge_allocated);
-#else
- malloc_printf(" %12llu %12llu %12zu\n",
- huge_nmalloc, huge_ndalloc, huge_allocated);
-#endif
- /* Print stats for each arena. */
- for (i = 0; i < narenas; i++) {
- arena = arenas[i];
- if (arena != NULL) {
- malloc_printf(
- "\narenas[%u]:\n", i);
- malloc_spin_lock(&arena->lock);
- stats_print(arena);
- malloc_spin_unlock(&arena->lock);
- }
- }
- }
-#endif /* #ifdef MALLOC_STATS */
- _malloc_message("--- End malloc statistics ---\n", "", "", "");
- }
-}
-
-/*
- * FreeBSD's pthreads implementation calls malloc(3), so the malloc
- * implementation has to take pains to avoid infinite recursion during
- * initialization.
- */
-#if (defined(MOZ_MEMORY_WINDOWS) || defined(MOZ_MEMORY_DARWIN)) && !defined(MOZ_MEMORY_WINCE)
-#define malloc_init() false
-#else
-static inline bool
-malloc_init(void)
-{
-
- if (malloc_initialized == false)
- return (malloc_init_hard());
-
- return (false);
-}
-#endif
-
-#if !defined(MOZ_MEMORY_WINDOWS) || defined(MOZ_MEMORY_WINCE)
-static
-#endif
-bool
-malloc_init_hard(void)
-{
- unsigned i;
- char buf[PATH_MAX + 1];
- const char *opts;
- long result;
-#ifndef MOZ_MEMORY_WINDOWS
- int linklen;
-#endif
-
-#ifndef MOZ_MEMORY_WINDOWS
- malloc_mutex_lock(&init_lock);
-#endif
-
- if (malloc_initialized) {
- /*
- * Another thread initialized the allocator before this one
- * acquired init_lock.
- */
-#ifndef MOZ_MEMORY_WINDOWS
- malloc_mutex_unlock(&init_lock);
-#endif
- return (false);
- }
-
-#ifdef MOZ_MEMORY_WINDOWS
- /* get a thread local storage index */
- tlsIndex = TlsAlloc();
-#endif
-
- /* Get page size and number of CPUs */
-#ifdef MOZ_MEMORY_WINDOWS
- {
- SYSTEM_INFO info;
-
- GetSystemInfo(&info);
- result = info.dwPageSize;
-
- pagesize = (unsigned) result;
-
-#ifndef MOZ_MEMORY_NARENAS_DEFAULT_ONE
- ncpus = info.dwNumberOfProcessors;
-#endif
- }
-#else
-#ifndef MOZ_MEMORY_NARENAS_DEFAULT_ONE
- ncpus = malloc_ncpus();
-#endif
-
- result = sysconf(_SC_PAGESIZE);
- assert(result != -1);
-
- pagesize = (unsigned) result;
-#endif
-
- /*
- * We assume that pagesize is a power of 2 when calculating
- * pagesize_mask and pagesize_2pow.
- */
- assert(((result - 1) & result) == 0);
- pagesize_mask = result - 1;
- pagesize_2pow = ffs((int)result) - 1;
-
-#ifdef MALLOC_PAGEFILE
- /*
- * Determine where to create page files. It is insufficient to
- * unconditionally use P_tmpdir (typically "/tmp"), since for some
- * operating systems /tmp is a separate filesystem that is rather small.
- * Therefore prefer, in order, the following locations:
- *
- * 1) MALLOC_TMPDIR
- * 2) TMPDIR
- * 3) P_tmpdir
- */
- {
- char *s;
- size_t slen;
- static const char suffix[] = "/jemalloc.XXXXXX";
-
- if ((s = getenv("MALLOC_TMPDIR")) == NULL && (s =
- getenv("TMPDIR")) == NULL)
- s = P_tmpdir;
- slen = strlen(s);
- if (slen + sizeof(suffix) > sizeof(pagefile_templ)) {
- _malloc_message(_getprogname(),
- ": (malloc) Page file path too long\n",
- "", "");
- abort();
- }
- memcpy(pagefile_templ, s, slen);
- memcpy(&pagefile_templ[slen], suffix, sizeof(suffix));
- }
-#endif
-
- for (i = 0; i < 3; i++) {
- unsigned j;
-
- /* Get runtime configuration. */
- switch (i) {
- case 0:
-#ifndef MOZ_MEMORY_WINDOWS
- if ((linklen = readlink("/etc/malloc.conf", buf,
- sizeof(buf) - 1)) != -1) {
- /*
- * Use the contents of the "/etc/malloc.conf"
- * symbolic link's name.
- */
- buf[linklen] = '\0';
- opts = buf;
- } else
-#endif
- {
- /* No configuration specified. */
- buf[0] = '\0';
- opts = buf;
- }
- break;
- case 1:
- if (issetugid() == 0 && (opts =
- getenv("MALLOC_OPTIONS")) != NULL) {
- /*
- * Do nothing; opts is already initialized to
- * the value of the MALLOC_OPTIONS environment
- * variable.
- */
- } else {
- /* No configuration specified. */
- buf[0] = '\0';
- opts = buf;
- }
- break;
- case 2:
- if (_malloc_options != NULL) {
- /*
- * Use options that were compiled into the
- * program.
- */
- opts = _malloc_options;
- } else {
- /* No configuration specified. */
- buf[0] = '\0';
- opts = buf;
- }
- break;
- default:
- /* NOTREACHED */
- buf[0] = '\0';
- opts = buf;
- assert(false);
- }
-
- for (j = 0; opts[j] != '\0'; j++) {
- unsigned k, nreps;
- bool nseen;
-
- /* Parse repetition count, if any. */
- for (nreps = 0, nseen = false;; j++, nseen = true) {
- switch (opts[j]) {
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- case '8': case '9':
- nreps *= 10;
- nreps += opts[j] - '0';
- break;
- default:
- goto MALLOC_OUT;
- }
- }
-MALLOC_OUT:
- if (nseen == false)
- nreps = 1;
-
- for (k = 0; k < nreps; k++) {
- switch (opts[j]) {
- case 'a':
- opt_abort = false;
- break;
- case 'A':
- opt_abort = true;
- break;
- case 'b':
-#ifdef MALLOC_BALANCE
- opt_balance_threshold >>= 1;
-#endif
- break;
- case 'B':
-#ifdef MALLOC_BALANCE
- if (opt_balance_threshold == 0)
- opt_balance_threshold = 1;
- else if ((opt_balance_threshold << 1)
- > opt_balance_threshold)
- opt_balance_threshold <<= 1;
-#endif
- break;
- case 'f':
- opt_dirty_max >>= 1;
- break;
- case 'F':
- if (opt_dirty_max == 0)
- opt_dirty_max = 1;
- else if ((opt_dirty_max << 1) != 0)
- opt_dirty_max <<= 1;
- break;
-#ifdef MALLOC_FILL
- case 'j':
- opt_junk = false;
- break;
- case 'J':
- opt_junk = true;
- break;
-#endif
- case 'k':
- /*
- * Chunks always require at least one
- * header page, so chunks can never be
- * smaller than two pages.
- */
- if (opt_chunk_2pow > pagesize_2pow + 1)
- opt_chunk_2pow--;
- break;
- case 'K':
- if (opt_chunk_2pow + 1 <
- (sizeof(size_t) << 3))
- opt_chunk_2pow++;
- break;
- case 'n':
- opt_narenas_lshift--;
- break;
- case 'N':
- opt_narenas_lshift++;
- break;
-#ifdef MALLOC_PAGEFILE
- case 'o':
- /* Do not over-commit. */
- opt_pagefile = true;
- break;
- case 'O':
- /* Allow over-commit. */
- opt_pagefile = false;
- break;
-#endif
- case 'p':
- opt_print_stats = false;
- break;
- case 'P':
- opt_print_stats = true;
- break;
- case 'q':
- if (opt_quantum_2pow > QUANTUM_2POW_MIN)
- opt_quantum_2pow--;
- break;
- case 'Q':
- if (opt_quantum_2pow < pagesize_2pow -
- 1)
- opt_quantum_2pow++;
- break;
- case 's':
- if (opt_small_max_2pow >
- QUANTUM_2POW_MIN)
- opt_small_max_2pow--;
- break;
- case 'S':
- if (opt_small_max_2pow < pagesize_2pow
- - 1)
- opt_small_max_2pow++;
- break;
-#ifdef MALLOC_UTRACE
- case 'u':
- opt_utrace = false;
- break;
- case 'U':
- opt_utrace = true;
- break;
-#endif
-#ifdef MALLOC_SYSV
- case 'v':
- opt_sysv = false;
- break;
- case 'V':
- opt_sysv = true;
- break;
-#endif
-#ifdef MALLOC_XMALLOC
- case 'x':
- opt_xmalloc = false;
- break;
- case 'X':
- opt_xmalloc = true;
- break;
-#endif
-#ifdef MALLOC_FILL
- case 'z':
- opt_zero = false;
- break;
- case 'Z':
- opt_zero = true;
- break;
-#endif
- default: {
- char cbuf[2];
-
- cbuf[0] = opts[j];
- cbuf[1] = '\0';
- _malloc_message(_getprogname(),
- ": (malloc) Unsupported character "
- "in malloc options: '", cbuf,
- "'\n");
- }
- }
- }
- }
- }
-
- /* Take care to call atexit() only once. */
- if (opt_print_stats) {
-#ifndef MOZ_MEMORY_WINDOWS
- /* Print statistics at exit. */
- atexit(malloc_print_stats);
-#endif
- }
-
-#if (!defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN) && !defined(MOZ_MEMORY_ANDROID))
- /* Prevent potential deadlock on malloc locks after fork. */
- pthread_atfork(_malloc_prefork, _malloc_postfork, _malloc_postfork);
-#endif
-
- /* Set variables according to the value of opt_small_max_2pow. */
- if (opt_small_max_2pow < opt_quantum_2pow)
- opt_small_max_2pow = opt_quantum_2pow;
- small_max = (1U << opt_small_max_2pow);
-
- /* Set bin-related variables. */
- bin_maxclass = (pagesize >> 1);
- assert(opt_quantum_2pow >= TINY_MIN_2POW);
- ntbins = opt_quantum_2pow - TINY_MIN_2POW;
- assert(ntbins <= opt_quantum_2pow);
- nqbins = (small_max >> opt_quantum_2pow);
- nsbins = pagesize_2pow - opt_small_max_2pow - 1;
-
- /* Set variables according to the value of opt_quantum_2pow. */
- quantum = (1U << opt_quantum_2pow);
- quantum_mask = quantum - 1;
- if (ntbins > 0)
- small_min = (quantum >> 1) + 1;
- else
- small_min = 1;
- assert(small_min <= quantum);
-
- /* Set variables according to the value of opt_chunk_2pow. */
- chunksize = (1LU << opt_chunk_2pow);
- chunksize_mask = chunksize - 1;
- chunk_npages = (chunksize >> pagesize_2pow);
- {
- size_t header_size;
-
- /*
- * Compute the header size such that it is large
- * enough to contain the page map and enough nodes for the
- * worst case: one node per non-header page plus one extra for
- * situations where we briefly have one more node allocated
- * than we will need.
- */
- header_size = sizeof(arena_chunk_t) +
- (sizeof(arena_chunk_map_t) * (chunk_npages - 1));
- arena_chunk_header_npages = (header_size >> pagesize_2pow) +
- ((header_size & pagesize_mask) != 0);
- }
- arena_maxclass = chunksize - (arena_chunk_header_npages <<
- pagesize_2pow);
-
-#ifdef JEMALLOC_USES_MAP_ALIGN
- /*
- * When using MAP_ALIGN, the alignment parameter must be a power of two
- * multiple of the system pagesize, or mmap will fail.
- */
- assert((chunksize % pagesize) == 0);
- assert((1 << (ffs(chunksize / pagesize) - 1)) == (chunksize/pagesize));
-#endif
-
- UTRACE(0, 0, 0);
-
-#ifdef MALLOC_STATS
- memset(&stats_chunks, 0, sizeof(chunk_stats_t));
-#endif
-
- /* Various sanity checks that regard configuration. */
- assert(quantum >= sizeof(void *));
- assert(quantum <= pagesize);
- assert(chunksize >= pagesize);
- assert(quantum * 4 <= chunksize);
-
- /* Initialize chunks data. */
- malloc_mutex_init(&huge_mtx);
- extent_tree_ad_new(&huge);
-#ifdef MALLOC_STATS
- huge_nmalloc = 0;
- huge_ndalloc = 0;
- huge_allocated = 0;
-#endif
-
- /* Initialize base allocation data structures. */
-#ifdef MALLOC_STATS
- base_mapped = 0;
-# ifdef MALLOC_DECOMMIT
- base_committed = 0;
-# endif
-#endif
- base_nodes = NULL;
- malloc_mutex_init(&base_mtx);
-
-#ifdef MOZ_MEMORY_NARENAS_DEFAULT_ONE
- narenas = 1;
-#else
- if (ncpus > 1) {
- /*
- * For SMP systems, create four times as many arenas as there
- * are CPUs by default.
- */
- opt_narenas_lshift += 2;
- }
-
- /* Determine how many arenas to use. */
- narenas = ncpus;
-#endif
- if (opt_narenas_lshift > 0) {
- if ((narenas << opt_narenas_lshift) > narenas)
- narenas <<= opt_narenas_lshift;
- /*
- * Make sure not to exceed the limits of what base_alloc() can
- * handle.
- */
- if (narenas * sizeof(arena_t *) > chunksize)
- narenas = chunksize / sizeof(arena_t *);
- } else if (opt_narenas_lshift < 0) {
- if ((narenas >> -opt_narenas_lshift) < narenas)
- narenas >>= -opt_narenas_lshift;
- /* Make sure there is at least one arena. */
- if (narenas == 0)
- narenas = 1;
- }
-#ifdef MALLOC_BALANCE
- assert(narenas != 0);
- for (narenas_2pow = 0;
- (narenas >> (narenas_2pow + 1)) != 0;
- narenas_2pow++);
-#endif
-
-#ifdef NO_TLS
- if (narenas > 1) {
- static const unsigned primes[] = {1, 3, 5, 7, 11, 13, 17, 19,
- 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83,
- 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
- 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211,
- 223, 227, 229, 233, 239, 241, 251, 257, 263};
- unsigned nprimes, parenas;
-
- /*
- * Pick a prime number of hash arenas that is more than narenas
- * so that direct hashing of pthread_self() pointers tends to
- * spread allocations evenly among the arenas.
- */
- assert((narenas & 1) == 0); /* narenas must be even. */
- nprimes = (sizeof(primes) >> SIZEOF_INT_2POW);
- parenas = primes[nprimes - 1]; /* In case not enough primes. */
- for (i = 1; i < nprimes; i++) {
- if (primes[i] > narenas) {
- parenas = primes[i];
- break;
- }
- }
- narenas = parenas;
- }
-#endif
-
-#ifndef NO_TLS
-# ifndef MALLOC_BALANCE
- next_arena = 0;
-# endif
-#endif
-
- /* Allocate and initialize arenas. */
- arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas);
- if (arenas == NULL) {
-#ifndef MOZ_MEMORY_WINDOWS
- malloc_mutex_unlock(&init_lock);
-#endif
- return (true);
- }
- /*
- * Zero the array. In practice, this should always be pre-zeroed,
- * since it was just mmap()ed, but let's be sure.
- */
- memset(arenas, 0, sizeof(arena_t *) * narenas);
-
- /*
- * Initialize one arena here. The rest are lazily created in
- * choose_arena_hard().
- */
- arenas_extend(0);
- if (arenas[0] == NULL) {
-#ifndef MOZ_MEMORY_WINDOWS
- malloc_mutex_unlock(&init_lock);
-#endif
- return (true);
- }
-#ifndef NO_TLS
- /*
- * Assign the initial arena to the initial thread, in order to avoid
- * spurious creation of an extra arena if the application switches to
- * threaded mode.
- */
-#ifdef MOZ_MEMORY_WINDOWS
- TlsSetValue(tlsIndex, arenas[0]);
-#else
- arenas_map = arenas[0];
-#endif
-#endif
-
- /*
- * Seed here for the initial thread, since choose_arena_hard() is only
- * called for other threads. The seed value doesn't really matter.
- */
-#ifdef MALLOC_BALANCE
- SPRN(balance, 42);
-#endif
-
- malloc_spin_init(&arenas_lock);
-
-#ifdef MALLOC_VALIDATE
- chunk_rtree = malloc_rtree_new((SIZEOF_PTR << 3) - opt_chunk_2pow);
- if (chunk_rtree == NULL)
- return (true);
-#endif
-
- malloc_initialized = true;
-#ifndef MOZ_MEMORY_WINDOWS
- malloc_mutex_unlock(&init_lock);
-#endif
- return (false);
-}
-
-/* XXX Why not just expose malloc_print_stats()? */
-#ifdef MOZ_MEMORY_WINDOWS
-void
-malloc_shutdown()
-{
-
- malloc_print_stats();
-}
-#endif
-
-/*
- * End general internal functions.
- */
-/******************************************************************************/
-/*
- * Begin malloc(3)-compatible functions.
- */
-
-/*
- * Inline the standard malloc functions if they are being subsumed by Darwin's
- * zone infrastructure.
- */
-#ifdef MOZ_MEMORY_DARWIN
-# define ZONE_INLINE inline
-#else
-# define ZONE_INLINE
-#endif
-
-/* Mangle standard interfaces on Darwin and Android,
- in order to avoid linking problems. */
-#if defined(MOZ_MEMORY_DARWIN)
-#define malloc(a) moz_malloc(a)
-#define valloc(a) moz_valloc(a)
-#define calloc(a, b) moz_calloc(a, b)
-#define realloc(a, b) moz_realloc(a, b)
-#define free(a) moz_free(a)
-#endif
-
-#if defined(MOZ_MEMORY_ANDROID) || defined(WRAP_MALLOC)
-inline void sys_free(void* ptr) {return free(ptr);}
-#define malloc(a) je_malloc(a)
-#define valloc(a) je_valloc(a)
-#define calloc(a, b) je_calloc(a, b)
-#define realloc(a, b) je_realloc(a, b)
-#define free(a) je_free(a)
-#define posix_memalign(a, b, c) je_posix_memalign(a, b, c)
-
-char *je_strndup(const char *src, size_t len) {
- char* dst = (char*)je_malloc(len + 1);
- if(dst)
- strncpy(dst, src, len + 1);
- return dst;
-}
-char *je_strdup(const char *src) {
- size_t len = strlen(src);
- return je_strndup(src, len );
-}
-#endif
-
-ZONE_INLINE
-void *
-malloc(size_t size)
-{
- void *ret;
-
- if (malloc_init()) {
- ret = NULL;
- goto RETURN;
- }
-
- if (size == 0) {
-#ifdef MALLOC_SYSV
- if (opt_sysv == false)
-#endif
- size = 1;
-#ifdef MALLOC_SYSV
- else {
- ret = NULL;
- goto RETURN;
- }
-#endif
- }
-
- ret = imalloc(size);
-
-RETURN:
- if (ret == NULL) {
-#ifdef MALLOC_XMALLOC
- if (opt_xmalloc) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in malloc(): out of memory\n", "",
- "");
- abort();
- }
-#endif
- errno = ENOMEM;
- }
-
- UTRACE(0, size, ret);
- return (ret);
-}
-
-#ifdef MOZ_MEMORY_SOLARIS
-# ifdef __SUNPRO_C
-void *
-memalign(size_t alignment, size_t size);
-#pragma no_inline(memalign)
-# elif (defined(__GNU_C__))
-__attribute__((noinline))
-# endif
-#else
-inline
-#endif
-void *
-memalign(size_t alignment, size_t size)
-{
- void *ret;
-
- assert(((alignment - 1) & alignment) == 0);
-
- if (malloc_init()) {
- ret = NULL;
- goto RETURN;
- }
-
- if (size == 0) {
-#ifdef MALLOC_SYSV
- if (opt_sysv == false)
-#endif
- size = 1;
-#ifdef MALLOC_SYSV
- else {
- ret = NULL;
- goto RETURN;
- }
-#endif
- }
-
- alignment = alignment < sizeof(void*) ? sizeof(void*) : alignment;
- ret = ipalloc(alignment, size);
-
-RETURN:
-#ifdef MALLOC_XMALLOC
- if (opt_xmalloc && ret == NULL) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in memalign(): out of memory\n", "", "");
- abort();
- }
-#endif
- UTRACE(0, size, ret);
- return (ret);
-}
-
-ZONE_INLINE
-int
-posix_memalign(void **memptr, size_t alignment, size_t size)
-{
- void *result;
-
- /* Make sure that alignment is a large enough power of 2. */
- if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void *)) {
-#ifdef MALLOC_XMALLOC
- if (opt_xmalloc) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in posix_memalign(): "
- "invalid alignment\n", "", "");
- abort();
- }
-#endif
- return (EINVAL);
- }
-
- /* The 0-->1 size promotion is done in the memalign() call below */
-
-#ifdef MOZ_MEMORY_DARWIN
- result = moz_memalign(alignment, size);
-#else
- result = memalign(alignment, size);
-#endif
- if (result == NULL)
- return (ENOMEM);
-
- *memptr = result;
- return (0);
-}
-
-ZONE_INLINE
-void *
-valloc(size_t size)
-{
-#ifdef MOZ_MEMORY_DARWIN
- return (moz_memalign(pagesize, size));
-#else
- return (memalign(pagesize, size));
-#endif
-}
-
-ZONE_INLINE
-void *
-calloc(size_t num, size_t size)
-{
- void *ret;
- size_t num_size;
-
- if (malloc_init()) {
- num_size = 0;
- ret = NULL;
- goto RETURN;
- }
-
- num_size = num * size;
- if (num_size == 0) {
-#ifdef MALLOC_SYSV
- if ((opt_sysv == false) && ((num == 0) || (size == 0)))
-#endif
- num_size = 1;
-#ifdef MALLOC_SYSV
- else {
- ret = NULL;
- goto RETURN;
- }
-#endif
- /*
- * Try to avoid division here. We know that it isn't possible to
- * overflow during multiplication if neither operand uses any of the
- * most significant half of the bits in a size_t.
- */
- } else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2)))
- && (num_size / size != num)) {
- /* size_t overflow. */
- ret = NULL;
- goto RETURN;
- }
-
- ret = icalloc(num_size);
-
-RETURN:
- if (ret == NULL) {
-#ifdef MALLOC_XMALLOC
- if (opt_xmalloc) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in calloc(): out of memory\n", "",
- "");
- abort();
- }
-#endif
- errno = ENOMEM;
- }
-
- UTRACE(0, num_size, ret);
- return (ret);
-}
-
-ZONE_INLINE
-void *
-realloc(void *ptr, size_t size)
-{
- void *ret;
-
- if (size == 0) {
-#ifdef MALLOC_SYSV
- if (opt_sysv == false)
-#endif
- size = 1;
-#ifdef MALLOC_SYSV
- else {
- if (ptr != NULL)
- idalloc(ptr);
- ret = NULL;
- goto RETURN;
- }
-#endif
- }
-
- if (ptr != NULL) {
- assert(malloc_initialized);
-
- ret = iralloc(ptr, size);
-
- if (ret == NULL) {
-#ifdef MALLOC_XMALLOC
- if (opt_xmalloc) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in realloc(): out of "
- "memory\n", "", "");
- abort();
- }
-#endif
- errno = ENOMEM;
- }
- } else {
- if (malloc_init())
- ret = NULL;
- else
- ret = imalloc(size);
-
- if (ret == NULL) {
-#ifdef MALLOC_XMALLOC
- if (opt_xmalloc) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in realloc(): out of "
- "memory\n", "", "");
- abort();
- }
-#endif
- errno = ENOMEM;
- }
- }
-
-#ifdef MALLOC_SYSV
-RETURN:
-#endif
- UTRACE(ptr, size, ret);
- return (ret);
-}
-
-ZONE_INLINE
-void
-free(void *ptr)
-{
- size_t offset;
-
- UTRACE(ptr, 0, 0);
-
- /*
- * A version of idalloc that checks for NULL pointer but only for
- * huge allocations assuming that CHUNK_ADDR2OFFSET(NULL) == 0.
- */
- assert(CHUNK_ADDR2OFFSET(NULL) == 0);
- offset = CHUNK_ADDR2OFFSET(ptr);
- if (offset != 0)
- arena_dalloc(ptr, offset);
- else if (ptr != NULL)
- huge_dalloc(ptr);
-}
-
-/*
- * End malloc(3)-compatible functions.
- */
-/******************************************************************************/
-/*
- * Begin non-standard functions.
- */
-#ifdef MOZ_MEMORY_ANDROID
-size_t
-malloc_usable_size(void *ptr)
-#else
-size_t
-malloc_usable_size(const void *ptr)
-#endif
-{
-
-#ifdef MALLOC_VALIDATE
- return (isalloc_validate(ptr));
-#else
- assert(ptr != NULL);
-
- return (isalloc(ptr));
-#endif
-}
-
-#ifdef MALLOC_STATS
-void
-jemalloc_stats(jemalloc_stats_t *stats)
-{
- size_t i;
-
- assert(stats != NULL);
-
- /*
- * Gather runtime settings.
- */
- stats->opt_abort = opt_abort;
- stats->opt_junk =
-#ifdef MALLOC_FILL
- opt_junk ? true :
-#endif
- false;
- stats->opt_utrace =
-#ifdef MALLOC_UTRACE
- opt_utrace ? true :
-#endif
- false;
- stats->opt_sysv =
-#ifdef MALLOC_SYSV
- opt_sysv ? true :
-#endif
- false;
- stats->opt_xmalloc =
-#ifdef MALLOC_XMALLOC
- opt_xmalloc ? true :
-#endif
- false;
- stats->opt_zero =
-#ifdef MALLOC_FILL
- opt_zero ? true :
-#endif
- false;
- stats->narenas = narenas;
- stats->balance_threshold =
-#ifdef MALLOC_BALANCE
- opt_balance_threshold
-#else
- SIZE_T_MAX
-#endif
- ;
- stats->quantum = quantum;
- stats->small_max = small_max;
- stats->large_max = arena_maxclass;
- stats->chunksize = chunksize;
- stats->dirty_max = opt_dirty_max;
-
- /*
- * Gather current memory usage statistics.
- */
- stats->mapped = 0;
- stats->committed = 0;
- stats->allocated = 0;
- stats->dirty = 0;
-
- /* Get huge mapped/allocated. */
- malloc_mutex_lock(&huge_mtx);
- stats->mapped += stats_chunks.curchunks * chunksize;
-#ifdef MALLOC_DECOMMIT
- stats->committed += huge_allocated;
-#endif
- stats->allocated += huge_allocated;
- malloc_mutex_unlock(&huge_mtx);
-
- /* Get base mapped. */
- malloc_mutex_lock(&base_mtx);
- stats->mapped += base_mapped;
-#ifdef MALLOC_DECOMMIT
- assert(base_committed <= base_mapped);
- stats->committed += base_committed;
-#endif
- malloc_mutex_unlock(&base_mtx);
-
- /* Iterate over arenas and their chunks. */
- for (i = 0; i < narenas; i++) {
- arena_t *arena = arenas[i];
- if (arena != NULL) {
- arena_chunk_t *chunk;
-
- malloc_spin_lock(&arena->lock);
- stats->allocated += arena->stats.allocated_small;
- stats->allocated += arena->stats.allocated_large;
-#ifdef MALLOC_DECOMMIT
- stats->committed += (arena->stats.committed <<
- pagesize_2pow);
-#endif
- stats->dirty += (arena->ndirty << pagesize_2pow);
- malloc_spin_unlock(&arena->lock);
- }
- }
-
-#ifndef MALLOC_DECOMMIT
- stats->committed = stats->mapped;
-#endif
- assert(stats->mapped >= stats->committed);
- assert(stats->committed >= stats->allocated);
-}
-#endif /* MALLOC_STATS */
-
-#ifdef MOZ_MEMORY_WINDOWS
-void*
-_recalloc(void *ptr, size_t count, size_t size)
-{
- size_t oldsize = (ptr != NULL) ? isalloc(ptr) : 0;
- size_t newsize = count * size;
-
- /*
- * In order for all trailing bytes to be zeroed, the caller needs to
- * use calloc(), followed by recalloc(). However, the current calloc()
- * implementation only zeros the bytes requested, so if recalloc() is
- * to work 100% correctly, calloc() will need to change to zero
- * trailing bytes.
- */
-
- ptr = realloc(ptr, newsize);
- if (ptr != NULL && oldsize < newsize) {
- memset((void *)((uintptr_t)ptr + oldsize), 0, newsize -
- oldsize);
- }
-
- return ptr;
-}
-
-/*
- * This impl of _expand doesn't ever actually expand or shrink blocks: it
- * simply replies that you may continue using a shrunk block.
- */
-void*
-_expand(void *ptr, size_t newsize)
-{
- if (isalloc(ptr) >= newsize)
- return ptr;
-
- return NULL;
-}
-
-size_t
-_msize(const void *ptr)
-{
-
- return malloc_usable_size(ptr);
-}
-#endif
-
-/*
- * End non-standard functions.
- */
-/******************************************************************************/
-/*
- * Begin library-private functions, used by threading libraries for protection
- * of malloc during fork(). These functions are only called if the program is
- * running in threaded mode, so there is no need to check whether the program
- * is threaded here.
- */
-
-void
-_malloc_prefork(void)
-{
- unsigned i;
-
- /* Acquire all mutexes in a safe order. */
-
- malloc_spin_lock(&arenas_lock);
- for (i = 0; i < narenas; i++) {
- if (arenas[i] != NULL)
- malloc_spin_lock(&arenas[i]->lock);
- }
-
- malloc_mutex_lock(&base_mtx);
-
- malloc_mutex_lock(&huge_mtx);
-}
-
-void
-_malloc_postfork(void)
-{
- unsigned i;
-
- /* Release all mutexes, now that fork() has completed. */
-
- malloc_mutex_unlock(&huge_mtx);
-
- malloc_mutex_unlock(&base_mtx);
-
- for (i = 0; i < narenas; i++) {
- if (arenas[i] != NULL)
- malloc_spin_unlock(&arenas[i]->lock);
- }
- malloc_spin_unlock(&arenas_lock);
-}
-
-/*
- * End library-private functions.
- */
-/******************************************************************************/
-
-#ifdef HAVE_DLOPEN
-# include <dlfcn.h>
-#endif
-
-#ifdef MOZ_MEMORY_DARWIN
-static malloc_zone_t zone;
-static struct malloc_introspection_t zone_introspect;
-
-static size_t
-zone_size(malloc_zone_t *zone, void *ptr)
-{
-
- /*
- * There appear to be places within Darwin (such as setenv(3)) that
- * cause calls to this function with pointers that *no* zone owns. If
- * we knew that all pointers were owned by *some* zone, we could split
- * our zone into two parts, and use one as the default allocator and
- * the other as the default deallocator/reallocator. Since that will
- * not work in practice, we must check all pointers to assure that they
- * reside within a mapped chunk before determining size.
- */
- return (isalloc_validate(ptr));
-}
-
-static void *
-zone_malloc(malloc_zone_t *zone, size_t size)
-{
-
- return (malloc(size));
-}
-
-static void *
-zone_calloc(malloc_zone_t *zone, size_t num, size_t size)
-{
-
- return (calloc(num, size));
-}
-
-static void *
-zone_valloc(malloc_zone_t *zone, size_t size)
-{
- void *ret = NULL; /* Assignment avoids useless compiler warning. */
-
- posix_memalign(&ret, pagesize, size);
-
- return (ret);
-}
-
-static void
-zone_free(malloc_zone_t *zone, void *ptr)
-{
-
- free(ptr);
-}
-
-static void *
-zone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
-{
-
- return (realloc(ptr, size));
-}
-
-static void *
-zone_destroy(malloc_zone_t *zone)
-{
-
- /* This function should never be called. */
- assert(false);
- return (NULL);
-}
-
-static size_t
-zone_good_size(malloc_zone_t *zone, size_t size)
-{
- size_t ret;
- void *p;
-
- /*
- * Actually create an object of the appropriate size, then find out
- * how large it could have been without moving up to the next size
- * class.
- */
- p = malloc(size);
- if (p != NULL) {
- ret = isalloc(p);
- free(p);
- } else
- ret = size;
-
- return (ret);
-}
-
-static void
-zone_force_lock(malloc_zone_t *zone)
-{
-
- _malloc_prefork();
-}
-
-static void
-zone_force_unlock(malloc_zone_t *zone)
-{
-
- _malloc_postfork();
-}
-
-static malloc_zone_t *
-create_zone(void)
-{
-
- assert(malloc_initialized);
-
- zone.size = (void *)zone_size;
- zone.malloc = (void *)zone_malloc;
- zone.calloc = (void *)zone_calloc;
- zone.valloc = (void *)zone_valloc;
- zone.free = (void *)zone_free;
- zone.realloc = (void *)zone_realloc;
- zone.destroy = (void *)zone_destroy;
- zone.zone_name = "jemalloc_zone";
- zone.batch_malloc = NULL;
- zone.batch_free = NULL;
- zone.introspect = &zone_introspect;
-
- zone_introspect.enumerator = NULL;
- zone_introspect.good_size = (void *)zone_good_size;
- zone_introspect.check = NULL;
- zone_introspect.print = NULL;
- zone_introspect.log = NULL;
- zone_introspect.force_lock = (void *)zone_force_lock;
- zone_introspect.force_unlock = (void *)zone_force_unlock;
- zone_introspect.statistics = NULL;
-
- return (&zone);
-}
-
-__attribute__((constructor))
-void
-jemalloc_darwin_init(void)
-{
- extern unsigned malloc_num_zones;
- extern malloc_zone_t **malloc_zones;
-
- if (malloc_init_hard())
- abort();
-
- /*
- * The following code is *not* thread-safe, so it's critical that
- * initialization be manually triggered.
- */
-
- /* Register the custom zones. */
- malloc_zone_register(create_zone());
- assert(malloc_zones[malloc_num_zones - 1] == &zone);
-
- /*
- * Shift malloc_zones around so that zone is first, which makes it the
- * default zone.
- */
- assert(malloc_num_zones > 1);
- memmove(&malloc_zones[1], &malloc_zones[0],
- sizeof(malloc_zone_t *) * (malloc_num_zones - 1));
- malloc_zones[0] = &zone;
-}
-
-#elif defined(__GLIBC__) && !defined(__UCLIBC__)
-/*
- * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible
- * to inconsistently reference libc's malloc(3)-compatible functions
- * (bug 493541).
- *
- * These definitions interpose hooks in glibc. The functions are actually
- * passed an extra argument for the caller return address, which will be
- * ignored.
- */
-#ifndef WRAP_MALLOC
-void (*__free_hook)(void *ptr) = free;
-void *(*__malloc_hook)(size_t size) = malloc;
-void *(*__realloc_hook)(void *ptr, size_t size) = realloc;
-void *(*__memalign_hook)(size_t alignment, size_t size) = memalign;
-#endif
-
-#elif defined(RTLD_DEEPBIND)
-/*
- * XXX On systems that support RTLD_GROUP or DF_1_GROUP, do their
- * implementations permit similar inconsistencies? Should STV_SINGLETON
- * visibility be used for interposition where available?
- */
-# error "Interposing malloc is unsafe on this system without libc malloc hooks."
-#endif
diff --git a/libbase/jemalloc.h b/libbase/jemalloc.h
deleted file mode 100644
index 03e0559..0000000
--- a/libbase/jemalloc.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*- Mode: C; tab-width: 8; c-basic-offset: 8 -*- */
-/* vim:set softtabstop=8 shiftwidth=8: */
-/*-
- * Copyright (C) 2006-2008 Jason Evans <jasone at FreeBSD.org>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice(s), this list of conditions and the following disclaimer as
- * the first lines of this file unmodified other than the possible
- * addition of one or more copyright notices.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice(s), this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _JEMALLOC_H_
-#define _JEMALLOC_H_
-
-#include "jemalloc_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern const char *_malloc_options;
-
-/* Darwin and Linux already have memory allocation functions */
-#if (!defined(MOZ_MEMORY_DARWIN) && !defined(MOZ_MEMORY_LINUX))
-void *malloc(size_t size);
-void *valloc(size_t size);
-void *calloc(size_t num, size_t size);
-void *realloc(void *ptr, size_t size);
-void free(void *ptr);
-int posix_memalign(void **memptr, size_t alignment, size_t size);
-#endif /* MOZ_MEMORY_DARWIN, MOZ_MEMORY_LINUX */
-
-#if defined(MOZ_MEMORY_ANDROID) || defined(WRAP_MALLOC)
-void *je_malloc(size_t size);
-void *je_valloc(size_t size);
-void *je_calloc(size_t num, size_t size);
-void *je_realloc(void *ptr, size_t size);
-void je_free(void *ptr);
-int je_posix_memalign(void **memptr, size_t alignment, size_t size);
-char *je_strndup(const char *src, size_t len);
-char *je_strdup(const char *src);
-#endif
-
-/* Linux has memalign and malloc_usable_size */
-#if !defined(MOZ_MEMORY_LINUX)
-void *memalign(size_t alignment, size_t size);
-size_t malloc_usable_size(const void *ptr);
-#endif /* MOZ_MEMORY_LINUX */
-
-void jemalloc_stats(jemalloc_stats_t *stats);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* _JEMALLOC_H_ */
diff --git a/libbase/jemalloc_gnash.c b/libbase/jemalloc_gnash.c
new file mode 100644
index 0000000..a702688
--- /dev/null
+++ b/libbase/jemalloc_gnash.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2013 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stddef.h>
+#include <jemalloc.h>
+
+#ifdef HAVE_CONFIG_H
+# include "gnashconfig.h"
+#endif
+
+#ifdef USE_STATS_MEMORY
+
+/* Borrowed from malloc.h, as this is Linux specific. This has been
+ * added to jemalloc so the existing memory profiling in Gnash will
+ * continue to work. Most of these fields aren't used by the Gnash
+ * memory profiling, but we leave them here for a semblance of
+ * portability. The only fields Gnash uses are arena, uordblks. and
+ * fordblks.
+ */
+struct mallinfo {
+ int arena; /* non-mmapped space allocated from system */
+ int ordblks; /* number of free chunks UNUSED */
+ int smblks; /* number of fastbin blocks UNUSED */
+ int hblks; /* number of mmapped regions UNUSED */
+ int hblkhd; /* space in mmapped regions UNUSED */
+ int usmblks; /* maximum total allocated space UNUSED */
+ int fsmblks; /* space available in freed fastbin blocks UNUSED */
+ int uordblks; /* total allocated space */
+ int fordblks; /* total free space */
+ int keepcost; /* top-most, releasable space UNUSED */
+};
+
+struct mallinfo mallinfo (void);
+
+struct mallinfo
+mallinfo(void)
+{
+ struct mallinfo mi = {0,};
+
+ size_t len = sizeof(mi.arena);
+ mallctl("stats.mapped", &mi.arena, &len, NULL, 0);
+ len = sizeof(mi.uordblks);
+ mallctl("stats.allocated", &mi.uordblks, &len, NULL, 0);
+
+ mi.fordblks = mi.arena - mi.uordblks;
+
+ return mi;
+}
+
+#endif /* USE_STATS_MEMORY */
diff --git a/libbase/jemalloc_gnash.h b/libbase/jemalloc_gnash.h
deleted file mode 100644
index 3818cb1..0000000
--- a/libbase/jemalloc_gnash.h
+++ /dev/null
@@ -1,105 +0,0 @@
-#ifndef GNASH_JEMALLOC_H
-#define GNASH_JEMALLOC_H
-
-#ifdef HAVE_CONFIG_H
-# include "gnashconfig.h"
-#endif
-
-/* Compiling for user mode application, not operating system */
-#define MOZ_MEMORY
-
-#ifdef LINUX_HOST
-#define MOZ_MEMORY_LINUX
-#endif
-
-#ifdef WIN32_HOST
-#define MOZ_MEMORY_WINDOWS
-#endif
-
-/* OpenBSD and others are excluded here to mimic what Mozilla does. */
-#if defined(FREEBSD_HOST) || defined(NETBSD_HOST)
-#define MOZ_MEMORY_BSD
-#endif
-
-#ifdef DARWIN_HOST
-#define MOZ_MEMORY_DARWIN
-#endif
-
-#ifdef SOLARIS_HOST
-#define MOZ_MEMORY_SOLARIS
-#endif
-
-#ifdef WINCE_HOST
-#define MOZ_MEMORY_WINCE
-#endif
-
-#ifdef WINCE6_HOST
-#define MOZ_MEMORY_WINCE6
-#endif
-
-#ifdef ANDROID_HOST
-#define MOZ_MEMORY_ANDROID
-#endif
-
-#if SIZEOF_VOID_P == 4
-# define MOZ_MEMORY_SIZEOF_PTR_2POW 2
-#elif SIZEOF_VOID_P == 8
-# define MOZ_MEMORY_SIZEOF_PTR_2POW 3
-#endif
-
-#if 0
-/* Unfortunately, even though jemalloc has valgrind hooks, it still produces
- * false positives. See https://bugzilla.mozilla.org/show_bug.cgi?id=503249
- */
-#define MOZ_VALGRIND
-#endif
-
-#include "jemalloc.h"
-
-#ifdef USE_STATS_MEMORY
-
-/* Enable statistics tracking plus API in jemalloc. */
-#define MALLOC_STATS
-
-/* Borrowed from malloc.h, as this is Linux specific. This has been
- * added to jemalloc so the existing memory profiling in Gnash will
- * continue to work. Most of these fields aren't used by the Gnash
- * memory profiling, but we leave them here for a semblance of
- * portability. The only fields Gnash uses are arena, uordblks. and
- * fordblks.
- */
-struct mallinfo {
- int arena; /* non-mmapped space allocated from system */
- int ordblks; /* number of free chunks UNUSED */
- int smblks; /* number of fastbin blocks UNUSED */
- int hblks; /* number of mmapped regions UNUSED */
- int hblkhd; /* space in mmapped regions UNUSED */
- int usmblks; /* maximum total allocated space UNUSED */
- int fsmblks; /* space available in freed fastbin blocks UNUSED */
- int uordblks; /* total allocated space */
- int fordblks; /* total free space */
- int keepcost; /* top-most, releasable space UNUSED */
-};
-
-struct mallinfo
-mallinfo(void)
-{
- struct mallinfo mi;
- jemalloc_stats_t stats;
-
- jemalloc_stats(&stats);
-
- /* clear unused fields */
- mi.keepcost = mi.ordblks = mi.smblks = mi.usmblks = mi.fsmblks =
- mi.hblks = mi.hblkhd = 0;
-
- mi.arena = stats.mapped;
- mi.uordblks = stats.allocated;
- mi.fordblks = stats.mapped - mi.uordblks;
-
- return mi;
-}
-
-#endif /* USE_STATS_MEMORY */
-
-#endif /* GNASH_JEMALLOC_H */
diff --git a/libbase/jemalloc_rb.h b/libbase/jemalloc_rb.h
deleted file mode 100644
index 43d8569..0000000
--- a/libbase/jemalloc_rb.h
+++ /dev/null
@@ -1,982 +0,0 @@
-/******************************************************************************
- *
- * Copyright (C) 2008 Jason Evans <jasone at FreeBSD.org>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice(s), this list of conditions and the following disclaimer
- * unmodified other than the allowable addition of one or more
- * copyright notices.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice(s), this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- *
- * cpp macro implementation of left-leaning red-black trees.
- *
- * Usage:
- *
- * (Optional.)
- * #define SIZEOF_PTR ...
- * #define SIZEOF_PTR_2POW ...
- * #define RB_NO_C99_VARARRAYS
- *
- * (Optional, see assert(3).)
- * #define NDEBUG
- *
- * (Required.)
- * #include <assert.h>
- * #include <rb.h>
- * ...
- *
- * All operations are done non-recursively. Parent pointers are not used, and
- * color bits are stored in the least significant bit of right-child pointers,
- * thus making node linkage as compact as is possible for red-black trees.
- *
- * Some macros use a comparison function pointer, which is expected to have the
- * following prototype:
- *
- * int (a_cmp *)(a_type *a_node, a_type *a_other);
- * ^^^^^^
- * or a_key
- *
- * Interpretation of comparision function return values:
- *
- * -1 : a_node < a_other
- * 0 : a_node == a_other
- * 1 : a_node > a_other
- *
- * In all cases, the a_node or a_key macro argument is the first argument to the
- * comparison function, which makes it possible to write comparison functions
- * that treat the first argument specially.
- *
- ******************************************************************************/
-
-#ifndef RB_H_
-#define RB_H_
-
-#if 0
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/libc/stdlib/rb.h 178995 2008-05-14 18:33:13Z jasone $");
-#endif
-
-/* Node structure. */
-#define rb_node(a_type) \
-struct { \
- a_type *rbn_left; \
- a_type *rbn_right_red; \
-}
-
-/* Root structure. */
-#define rb_tree(a_type) \
-struct { \
- a_type *rbt_root; \
- a_type rbt_nil; \
-}
-
-/* Left accessors. */
-#define rbp_left_get(a_type, a_field, a_node) \
- ((a_node)->a_field.rbn_left)
-#define rbp_left_set(a_type, a_field, a_node, a_left) do { \
- (a_node)->a_field.rbn_left = a_left; \
-} while (0)
-
-/* Right accessors. */
-#define rbp_right_get(a_type, a_field, a_node) \
- ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red) \
- & ((ssize_t)-2)))
-#define rbp_right_set(a_type, a_field, a_node, a_right) do { \
- (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right) \
- | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1))); \
-} while (0)
-
-/* Color accessors. */
-#define rbp_red_get(a_type, a_field, a_node) \
- ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red) \
- & ((size_t)1)))
-#define rbp_color_set(a_type, a_field, a_node, a_red) do { \
- (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t) \
- (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)) \
- | ((ssize_t)a_red)); \
-} while (0)
-#define rbp_red_set(a_type, a_field, a_node) do { \
- (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) \
- (a_node)->a_field.rbn_right_red) | ((size_t)1)); \
-} while (0)
-#define rbp_black_set(a_type, a_field, a_node) do { \
- (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t) \
- (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)); \
-} while (0)
-
-/* Node initializer. */
-#define rbp_node_new(a_type, a_field, a_tree, a_node) do { \
- rbp_left_set(a_type, a_field, (a_node), &(a_tree)->rbt_nil); \
- rbp_right_set(a_type, a_field, (a_node), &(a_tree)->rbt_nil); \
- rbp_red_set(a_type, a_field, (a_node)); \
-} while (0)
-
-/* Tree initializer. */
-#define rb_new(a_type, a_field, a_tree) do { \
- (a_tree)->rbt_root = &(a_tree)->rbt_nil; \
- rbp_node_new(a_type, a_field, a_tree, &(a_tree)->rbt_nil); \
- rbp_black_set(a_type, a_field, &(a_tree)->rbt_nil); \
-} while (0)
-
-/* Tree operations. */
-#define rbp_black_height(a_type, a_field, a_tree, r_height) do { \
- a_type *rbp_bh_t; \
- for (rbp_bh_t = (a_tree)->rbt_root, (r_height) = 0; \
- rbp_bh_t != &(a_tree)->rbt_nil; \
- rbp_bh_t = rbp_left_get(a_type, a_field, rbp_bh_t)) { \
- if (rbp_red_get(a_type, a_field, rbp_bh_t) == false) { \
- (r_height)++; \
- } \
- } \
-} while (0)
-
-#define rbp_first(a_type, a_field, a_tree, a_root, r_node) do { \
- for ((r_node) = (a_root); \
- rbp_left_get(a_type, a_field, (r_node)) != &(a_tree)->rbt_nil; \
- (r_node) = rbp_left_get(a_type, a_field, (r_node))) { \
- } \
-} while (0)
-
-#define rbp_last(a_type, a_field, a_tree, a_root, r_node) do { \
- for ((r_node) = (a_root); \
- rbp_right_get(a_type, a_field, (r_node)) != &(a_tree)->rbt_nil; \
- (r_node) = rbp_right_get(a_type, a_field, (r_node))) { \
- } \
-} while (0)
-
-#define rbp_next(a_type, a_field, a_cmp, a_tree, a_node, r_node) do { \
- if (rbp_right_get(a_type, a_field, (a_node)) \
- != &(a_tree)->rbt_nil) { \
- rbp_first(a_type, a_field, a_tree, rbp_right_get(a_type, \
- a_field, (a_node)), (r_node)); \
- } else { \
- a_type *rbp_n_t = (a_tree)->rbt_root; \
- assert(rbp_n_t != &(a_tree)->rbt_nil); \
- (r_node) = &(a_tree)->rbt_nil; \
- while (true) { \
- int rbp_n_cmp = (a_cmp)((a_node), rbp_n_t); \
- if (rbp_n_cmp < 0) { \
- (r_node) = rbp_n_t; \
- rbp_n_t = rbp_left_get(a_type, a_field, rbp_n_t); \
- } else if (rbp_n_cmp > 0) { \
- rbp_n_t = rbp_right_get(a_type, a_field, rbp_n_t); \
- } else { \
- break; \
- } \
- assert(rbp_n_t != &(a_tree)->rbt_nil); \
- } \
- } \
-} while (0)
-
-#define rbp_prev(a_type, a_field, a_cmp, a_tree, a_node, r_node) do { \
- if (rbp_left_get(a_type, a_field, (a_node)) != &(a_tree)->rbt_nil) {\
- rbp_last(a_type, a_field, a_tree, rbp_left_get(a_type, \
- a_field, (a_node)), (r_node)); \
- } else { \
- a_type *rbp_p_t = (a_tree)->rbt_root; \
- assert(rbp_p_t != &(a_tree)->rbt_nil); \
- (r_node) = &(a_tree)->rbt_nil; \
- while (true) { \
- int rbp_p_cmp = (a_cmp)((a_node), rbp_p_t); \
- if (rbp_p_cmp < 0) { \
- rbp_p_t = rbp_left_get(a_type, a_field, rbp_p_t); \
- } else if (rbp_p_cmp > 0) { \
- (r_node) = rbp_p_t; \
- rbp_p_t = rbp_right_get(a_type, a_field, rbp_p_t); \
- } else { \
- break; \
- } \
- assert(rbp_p_t != &(a_tree)->rbt_nil); \
- } \
- } \
-} while (0)
-
-#define rb_first(a_type, a_field, a_tree, r_node) do { \
- rbp_first(a_type, a_field, a_tree, (a_tree)->rbt_root, (r_node)); \
- if ((r_node) == &(a_tree)->rbt_nil) { \
- (r_node) = NULL; \
- } \
-} while (0)
-
-#define rb_last(a_type, a_field, a_tree, r_node) do { \
- rbp_last(a_type, a_field, a_tree, (a_tree)->rbt_root, r_node); \
- if ((r_node) == &(a_tree)->rbt_nil) { \
- (r_node) = NULL; \
- } \
-} while (0)
-
-#define rb_next(a_type, a_field, a_cmp, a_tree, a_node, r_node) do { \
- rbp_next(a_type, a_field, a_cmp, a_tree, (a_node), (r_node)); \
- if ((r_node) == &(a_tree)->rbt_nil) { \
- (r_node) = NULL; \
- } \
-} while (0)
-
-#define rb_prev(a_type, a_field, a_cmp, a_tree, a_node, r_node) do { \
- rbp_prev(a_type, a_field, a_cmp, a_tree, (a_node), (r_node)); \
- if ((r_node) == &(a_tree)->rbt_nil) { \
- (r_node) = NULL; \
- } \
-} while (0)
-
-#define rb_search(a_type, a_field, a_cmp, a_tree, a_key, r_node) do { \
- int rbp_se_cmp; \
- (r_node) = (a_tree)->rbt_root; \
- while ((r_node) != &(a_tree)->rbt_nil \
- && (rbp_se_cmp = (a_cmp)((a_key), (r_node))) != 0) { \
- if (rbp_se_cmp < 0) { \
- (r_node) = rbp_left_get(a_type, a_field, (r_node)); \
- } else { \
- (r_node) = rbp_right_get(a_type, a_field, (r_node)); \
- } \
- } \
- if ((r_node) == &(a_tree)->rbt_nil) { \
- (r_node) = NULL; \
- } \
-} while (0)
-
-/*
- * Find a match if it exists. Otherwise, find the next greater node, if one
- * exists.
- */
-#define rb_nsearch(a_type, a_field, a_cmp, a_tree, a_key, r_node) do { \
- a_type *rbp_ns_t = (a_tree)->rbt_root; \
- (r_node) = NULL; \
- while (rbp_ns_t != &(a_tree)->rbt_nil) { \
- int rbp_ns_cmp = (a_cmp)((a_key), rbp_ns_t); \
- if (rbp_ns_cmp < 0) { \
- (r_node) = rbp_ns_t; \
- rbp_ns_t = rbp_left_get(a_type, a_field, rbp_ns_t); \
- } else if (rbp_ns_cmp > 0) { \
- rbp_ns_t = rbp_right_get(a_type, a_field, rbp_ns_t); \
- } else { \
- (r_node) = rbp_ns_t; \
- break; \
- } \
- } \
-} while (0)
-
-/*
- * Find a match if it exists. Otherwise, find the previous lesser node, if one
- * exists.
- */
-#define rb_psearch(a_type, a_field, a_cmp, a_tree, a_key, r_node) do { \
- a_type *rbp_ps_t = (a_tree)->rbt_root; \
- (r_node) = NULL; \
- while (rbp_ps_t != &(a_tree)->rbt_nil) { \
- int rbp_ps_cmp = (a_cmp)((a_key), rbp_ps_t); \
- if (rbp_ps_cmp < 0) { \
- rbp_ps_t = rbp_left_get(a_type, a_field, rbp_ps_t); \
- } else if (rbp_ps_cmp > 0) { \
- (r_node) = rbp_ps_t; \
- rbp_ps_t = rbp_right_get(a_type, a_field, rbp_ps_t); \
- } else { \
- (r_node) = rbp_ps_t; \
- break; \
- } \
- } \
-} while (0)
-
-#define rbp_rotate_left(a_type, a_field, a_node, r_node) do { \
- (r_node) = rbp_right_get(a_type, a_field, (a_node)); \
- rbp_right_set(a_type, a_field, (a_node), \
- rbp_left_get(a_type, a_field, (r_node))); \
- rbp_left_set(a_type, a_field, (r_node), (a_node)); \
-} while (0)
-
-#define rbp_rotate_right(a_type, a_field, a_node, r_node) do { \
- (r_node) = rbp_left_get(a_type, a_field, (a_node)); \
- rbp_left_set(a_type, a_field, (a_node), \
- rbp_right_get(a_type, a_field, (r_node))); \
- rbp_right_set(a_type, a_field, (r_node), (a_node)); \
-} while (0)
-
-#define rbp_lean_left(a_type, a_field, a_node, r_node) do { \
- bool rbp_ll_red; \
- rbp_rotate_left(a_type, a_field, (a_node), (r_node)); \
- rbp_ll_red = rbp_red_get(a_type, a_field, (a_node)); \
- rbp_color_set(a_type, a_field, (r_node), rbp_ll_red); \
- rbp_red_set(a_type, a_field, (a_node)); \
-} while (0)
-
-#define rbp_lean_right(a_type, a_field, a_node, r_node) do { \
- bool rbp_lr_red; \
- rbp_rotate_right(a_type, a_field, (a_node), (r_node)); \
- rbp_lr_red = rbp_red_get(a_type, a_field, (a_node)); \
- rbp_color_set(a_type, a_field, (r_node), rbp_lr_red); \
- rbp_red_set(a_type, a_field, (a_node)); \
-} while (0)
-
-#define rbp_move_red_left(a_type, a_field, a_node, r_node) do { \
- a_type *rbp_mrl_t, *rbp_mrl_u; \
- rbp_mrl_t = rbp_left_get(a_type, a_field, (a_node)); \
- rbp_red_set(a_type, a_field, rbp_mrl_t); \
- rbp_mrl_t = rbp_right_get(a_type, a_field, (a_node)); \
- rbp_mrl_u = rbp_left_get(a_type, a_field, rbp_mrl_t); \
- if (rbp_red_get(a_type, a_field, rbp_mrl_u)) { \
- rbp_rotate_right(a_type, a_field, rbp_mrl_t, rbp_mrl_u); \
- rbp_right_set(a_type, a_field, (a_node), rbp_mrl_u); \
- rbp_rotate_left(a_type, a_field, (a_node), (r_node)); \
- rbp_mrl_t = rbp_right_get(a_type, a_field, (a_node)); \
- if (rbp_red_get(a_type, a_field, rbp_mrl_t)) { \
- rbp_black_set(a_type, a_field, rbp_mrl_t); \
- rbp_red_set(a_type, a_field, (a_node)); \
- rbp_rotate_left(a_type, a_field, (a_node), rbp_mrl_t); \
- rbp_left_set(a_type, a_field, (r_node), rbp_mrl_t); \
- } else { \
- rbp_black_set(a_type, a_field, (a_node)); \
- } \
- } else { \
- rbp_red_set(a_type, a_field, (a_node)); \
- rbp_rotate_left(a_type, a_field, (a_node), (r_node)); \
- } \
-} while (0)
-
-#define rbp_move_red_right(a_type, a_field, a_node, r_node) do { \
- a_type *rbp_mrr_t; \
- rbp_mrr_t = rbp_left_get(a_type, a_field, (a_node)); \
- if (rbp_red_get(a_type, a_field, rbp_mrr_t)) { \
- a_type *rbp_mrr_u, *rbp_mrr_v; \
- rbp_mrr_u = rbp_right_get(a_type, a_field, rbp_mrr_t); \
- rbp_mrr_v = rbp_left_get(a_type, a_field, rbp_mrr_u); \
- if (rbp_red_get(a_type, a_field, rbp_mrr_v)) { \
- rbp_color_set(a_type, a_field, rbp_mrr_u, \
- rbp_red_get(a_type, a_field, (a_node))); \
- rbp_black_set(a_type, a_field, rbp_mrr_v); \
- rbp_rotate_left(a_type, a_field, rbp_mrr_t, rbp_mrr_u); \
- rbp_left_set(a_type, a_field, (a_node), rbp_mrr_u); \
- rbp_rotate_right(a_type, a_field, (a_node), (r_node)); \
- rbp_rotate_left(a_type, a_field, (a_node), rbp_mrr_t); \
- rbp_right_set(a_type, a_field, (r_node), rbp_mrr_t); \
- } else { \
- rbp_color_set(a_type, a_field, rbp_mrr_t, \
- rbp_red_get(a_type, a_field, (a_node))); \
- rbp_red_set(a_type, a_field, rbp_mrr_u); \
- rbp_rotate_right(a_type, a_field, (a_node), (r_node)); \
- rbp_rotate_left(a_type, a_field, (a_node), rbp_mrr_t); \
- rbp_right_set(a_type, a_field, (r_node), rbp_mrr_t); \
- } \
- rbp_red_set(a_type, a_field, (a_node)); \
- } else { \
- rbp_red_set(a_type, a_field, rbp_mrr_t); \
- rbp_mrr_t = rbp_left_get(a_type, a_field, rbp_mrr_t); \
- if (rbp_red_get(a_type, a_field, rbp_mrr_t)) { \
- rbp_black_set(a_type, a_field, rbp_mrr_t); \
- rbp_rotate_right(a_type, a_field, (a_node), (r_node)); \
- rbp_rotate_left(a_type, a_field, (a_node), rbp_mrr_t); \
- rbp_right_set(a_type, a_field, (r_node), rbp_mrr_t); \
- } else { \
- rbp_rotate_left(a_type, a_field, (a_node), (r_node)); \
- } \
- } \
-} while (0)
-
-#define rb_insert(a_type, a_field, a_cmp, a_tree, a_node) do { \
- a_type rbp_i_s; \
- a_type *rbp_i_g, *rbp_i_p, *rbp_i_c, *rbp_i_t, *rbp_i_u; \
- int rbp_i_cmp = 0; \
- rbp_i_g = &(a_tree)->rbt_nil; \
- rbp_left_set(a_type, a_field, &rbp_i_s, (a_tree)->rbt_root); \
- rbp_right_set(a_type, a_field, &rbp_i_s, &(a_tree)->rbt_nil); \
- rbp_black_set(a_type, a_field, &rbp_i_s); \
- rbp_i_p = &rbp_i_s; \
- rbp_i_c = (a_tree)->rbt_root; \
- /* Iteratively search down the tree for the insertion point, */\
- /* splitting 4-nodes as they are encountered. At the end of each */\
- /* iteration, rbp_i_g->rbp_i_p->rbp_i_c is a 3-level path down */\
- /* the tree, assuming a sufficiently deep tree. */\
- while (rbp_i_c != &(a_tree)->rbt_nil) { \
- rbp_i_t = rbp_left_get(a_type, a_field, rbp_i_c); \
- rbp_i_u = rbp_left_get(a_type, a_field, rbp_i_t); \
- if (rbp_red_get(a_type, a_field, rbp_i_t) \
- && rbp_red_get(a_type, a_field, rbp_i_u)) { \
- /* rbp_i_c is the top of a logical 4-node, so split it. */\
- /* This iteration does not move down the tree, due to the */\
- /* disruptiveness of node splitting. */\
- /* */\
- /* Rotate right. */\
- rbp_rotate_right(a_type, a_field, rbp_i_c, rbp_i_t); \
- /* Pass red links up one level. */\
- rbp_i_u = rbp_left_get(a_type, a_field, rbp_i_t); \
- rbp_black_set(a_type, a_field, rbp_i_u); \
- if (rbp_left_get(a_type, a_field, rbp_i_p) == rbp_i_c) { \
- rbp_left_set(a_type, a_field, rbp_i_p, rbp_i_t); \
- rbp_i_c = rbp_i_t; \
- } else { \
- /* rbp_i_c was the right child of rbp_i_p, so rotate */\
- /* left in order to maintain the left-leaning */\
- /* invariant. */\
- assert(rbp_right_get(a_type, a_field, rbp_i_p) \
- == rbp_i_c); \
- rbp_right_set(a_type, a_field, rbp_i_p, rbp_i_t); \
- rbp_lean_left(a_type, a_field, rbp_i_p, rbp_i_u); \
- if (rbp_left_get(a_type, a_field, rbp_i_g) == rbp_i_p) {\
- rbp_left_set(a_type, a_field, rbp_i_g, rbp_i_u); \
- } else { \
- assert(rbp_right_get(a_type, a_field, rbp_i_g) \
- == rbp_i_p); \
- rbp_right_set(a_type, a_field, rbp_i_g, rbp_i_u); \
- } \
- rbp_i_p = rbp_i_u; \
- rbp_i_cmp = (a_cmp)((a_node), rbp_i_p); \
- if (rbp_i_cmp < 0) { \
- rbp_i_c = rbp_left_get(a_type, a_field, rbp_i_p); \
- } else { \
- assert(rbp_i_cmp > 0); \
- rbp_i_c = rbp_right_get(a_type, a_field, rbp_i_p); \
- } \
- continue; \
- } \
- } \
- rbp_i_g = rbp_i_p; \
- rbp_i_p = rbp_i_c; \
- rbp_i_cmp = (a_cmp)((a_node), rbp_i_c); \
- if (rbp_i_cmp < 0) { \
- rbp_i_c = rbp_left_get(a_type, a_field, rbp_i_c); \
- } else { \
- assert(rbp_i_cmp > 0); \
- rbp_i_c = rbp_right_get(a_type, a_field, rbp_i_c); \
- } \
- } \
- /* rbp_i_p now refers to the node under which to insert. */\
- rbp_node_new(a_type, a_field, a_tree, (a_node)); \
- if (rbp_i_cmp > 0) { \
- rbp_right_set(a_type, a_field, rbp_i_p, (a_node)); \
- rbp_lean_left(a_type, a_field, rbp_i_p, rbp_i_t); \
- if (rbp_left_get(a_type, a_field, rbp_i_g) == rbp_i_p) { \
- rbp_left_set(a_type, a_field, rbp_i_g, rbp_i_t); \
- } else if (rbp_right_get(a_type, a_field, rbp_i_g) == rbp_i_p) {\
- rbp_right_set(a_type, a_field, rbp_i_g, rbp_i_t); \
- } \
- } else { \
- rbp_left_set(a_type, a_field, rbp_i_p, (a_node)); \
- } \
- /* Update the root and make sure that it is black. */\
- (a_tree)->rbt_root = rbp_left_get(a_type, a_field, &rbp_i_s); \
- rbp_black_set(a_type, a_field, (a_tree)->rbt_root); \
-} while (0)
-
-#define rb_remove(a_type, a_field, a_cmp, a_tree, a_node) do { \
- a_type rbp_r_s; \
- a_type *rbp_r_p, *rbp_r_c, *rbp_r_xp, *rbp_r_t, *rbp_r_u; \
- int rbp_r_cmp; \
- rbp_left_set(a_type, a_field, &rbp_r_s, (a_tree)->rbt_root); \
- rbp_right_set(a_type, a_field, &rbp_r_s, &(a_tree)->rbt_nil); \
- rbp_black_set(a_type, a_field, &rbp_r_s); \
- rbp_r_p = &rbp_r_s; \
- rbp_r_c = (a_tree)->rbt_root; \
- rbp_r_xp = &(a_tree)->rbt_nil; \
- /* Iterate down the tree, but always transform 2-nodes to 3- or */\
- /* 4-nodes in order to maintain the invariant that the current */\
- /* node is not a 2-node. This allows simple deletion once a leaf */\
- /* is reached. Handle the root specially though, since there may */\
- /* be no way to convert it from a 2-node to a 3-node. */\
- rbp_r_cmp = (a_cmp)((a_node), rbp_r_c); \
- if (rbp_r_cmp < 0) { \
- rbp_r_t = rbp_left_get(a_type, a_field, rbp_r_c); \
- rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t); \
- if (rbp_red_get(a_type, a_field, rbp_r_t) == false \
- && rbp_red_get(a_type, a_field, rbp_r_u) == false) { \
- /* Apply standard transform to prepare for left move. */\
- rbp_move_red_left(a_type, a_field, rbp_r_c, rbp_r_t); \
- rbp_black_set(a_type, a_field, rbp_r_t); \
- rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t); \
- rbp_r_c = rbp_r_t; \
- } else { \
- /* Move left. */\
- rbp_r_p = rbp_r_c; \
- rbp_r_c = rbp_left_get(a_type, a_field, rbp_r_c); \
- } \
- } else { \
- if (rbp_r_cmp == 0) { \
- assert((a_node) == rbp_r_c); \
- if (rbp_right_get(a_type, a_field, rbp_r_c) \
- == &(a_tree)->rbt_nil) { \
- /* Delete root node (which is also a leaf node). */\
- if (rbp_left_get(a_type, a_field, rbp_r_c) \
- != &(a_tree)->rbt_nil) { \
- rbp_lean_right(a_type, a_field, rbp_r_c, rbp_r_t); \
- rbp_right_set(a_type, a_field, rbp_r_t, \
- &(a_tree)->rbt_nil); \
- } else { \
- rbp_r_t = &(a_tree)->rbt_nil; \
- } \
- rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t); \
- } else { \
- /* This is the node we want to delete, but we will */\
- /* instead swap it with its successor and delete the */\
- /* successor. Record enough information to do the */\
- /* swap later. rbp_r_xp is the a_node's parent. */\
- rbp_r_xp = rbp_r_p; \
- rbp_r_cmp = 1; /* Note that deletion is incomplete. */\
- } \
- } \
- if (rbp_r_cmp == 1) { \
- if (rbp_red_get(a_type, a_field, rbp_left_get(a_type, \
- a_field, rbp_right_get(a_type, a_field, rbp_r_c))) \
- == false) { \
- rbp_r_t = rbp_left_get(a_type, a_field, rbp_r_c); \
- if (rbp_red_get(a_type, a_field, rbp_r_t)) { \
- /* Standard transform. */\
- rbp_move_red_right(a_type, a_field, rbp_r_c, \
- rbp_r_t); \
- } else { \
- /* Root-specific transform. */\
- rbp_red_set(a_type, a_field, rbp_r_c); \
- rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t); \
- if (rbp_red_get(a_type, a_field, rbp_r_u)) { \
- rbp_black_set(a_type, a_field, rbp_r_u); \
- rbp_rotate_right(a_type, a_field, rbp_r_c, \
- rbp_r_t); \
- rbp_rotate_left(a_type, a_field, rbp_r_c, \
- rbp_r_u); \
- rbp_right_set(a_type, a_field, rbp_r_t, \
- rbp_r_u); \
- } else { \
- rbp_red_set(a_type, a_field, rbp_r_t); \
- rbp_rotate_left(a_type, a_field, rbp_r_c, \
- rbp_r_t); \
- } \
- } \
- rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t); \
- rbp_r_c = rbp_r_t; \
- } else { \
- /* Move right. */\
- rbp_r_p = rbp_r_c; \
- rbp_r_c = rbp_right_get(a_type, a_field, rbp_r_c); \
- } \
- } \
- } \
- if (rbp_r_cmp != 0) { \
- while (true) { \
- assert(rbp_r_p != &(a_tree)->rbt_nil); \
- rbp_r_cmp = (a_cmp)((a_node), rbp_r_c); \
- if (rbp_r_cmp < 0) { \
- rbp_r_t = rbp_left_get(a_type, a_field, rbp_r_c); \
- if (rbp_r_t == &(a_tree)->rbt_nil) { \
- /* rbp_r_c now refers to the successor node to */\
- /* relocate, and rbp_r_xp/a_node refer to the */\
- /* context for the relocation. */\
- if (rbp_left_get(a_type, a_field, rbp_r_xp) \
- == (a_node)) { \
- rbp_left_set(a_type, a_field, rbp_r_xp, \
- rbp_r_c); \
- } else { \
- assert(rbp_right_get(a_type, a_field, \
- rbp_r_xp) == (a_node)); \
- rbp_right_set(a_type, a_field, rbp_r_xp, \
- rbp_r_c); \
- } \
- rbp_left_set(a_type, a_field, rbp_r_c, \
- rbp_left_get(a_type, a_field, (a_node))); \
- rbp_right_set(a_type, a_field, rbp_r_c, \
- rbp_right_get(a_type, a_field, (a_node))); \
- rbp_color_set(a_type, a_field, rbp_r_c, \
- rbp_red_get(a_type, a_field, (a_node))); \
- if (rbp_left_get(a_type, a_field, rbp_r_p) \
- == rbp_r_c) { \
- rbp_left_set(a_type, a_field, rbp_r_p, \
- &(a_tree)->rbt_nil); \
- } else { \
- assert(rbp_right_get(a_type, a_field, rbp_r_p) \
- == rbp_r_c); \
- rbp_right_set(a_type, a_field, rbp_r_p, \
- &(a_tree)->rbt_nil); \
- } \
- break; \
- } \
- rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t); \
- if (rbp_red_get(a_type, a_field, rbp_r_t) == false \
- && rbp_red_get(a_type, a_field, rbp_r_u) == false) { \
- rbp_move_red_left(a_type, a_field, rbp_r_c, \
- rbp_r_t); \
- if (rbp_left_get(a_type, a_field, rbp_r_p) \
- == rbp_r_c) { \
- rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);\
- } else { \
- rbp_right_set(a_type, a_field, rbp_r_p, \
- rbp_r_t); \
- } \
- rbp_r_c = rbp_r_t; \
- } else { \
- rbp_r_p = rbp_r_c; \
- rbp_r_c = rbp_left_get(a_type, a_field, rbp_r_c); \
- } \
- } else { \
- /* Check whether to delete this node (it has to be */\
- /* the correct node and a leaf node). */\
- if (rbp_r_cmp == 0) { \
- assert((a_node) == rbp_r_c); \
- if (rbp_right_get(a_type, a_field, rbp_r_c) \
- == &(a_tree)->rbt_nil) { \
- /* Delete leaf node. */\
- if (rbp_left_get(a_type, a_field, rbp_r_c) \
- != &(a_tree)->rbt_nil) { \
- rbp_lean_right(a_type, a_field, rbp_r_c, \
- rbp_r_t); \
- rbp_right_set(a_type, a_field, rbp_r_t, \
- &(a_tree)->rbt_nil); \
- } else { \
- rbp_r_t = &(a_tree)->rbt_nil; \
- } \
- if (rbp_left_get(a_type, a_field, rbp_r_p) \
- == rbp_r_c) { \
- rbp_left_set(a_type, a_field, rbp_r_p, \
- rbp_r_t); \
- } else { \
- rbp_right_set(a_type, a_field, rbp_r_p, \
- rbp_r_t); \
- } \
- break; \
- } else { \
- /* This is the node we want to delete, but we */\
- /* will instead swap it with its successor */\
- /* and delete the successor. Record enough */\
- /* information to do the swap later. */\
- /* rbp_r_xp is a_node's parent. */\
- rbp_r_xp = rbp_r_p; \
- } \
- } \
- rbp_r_t = rbp_right_get(a_type, a_field, rbp_r_c); \
- rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t); \
- if (rbp_red_get(a_type, a_field, rbp_r_u) == false) { \
- rbp_move_red_right(a_type, a_field, rbp_r_c, \
- rbp_r_t); \
- if (rbp_left_get(a_type, a_field, rbp_r_p) \
- == rbp_r_c) { \
- rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);\
- } else { \
- rbp_right_set(a_type, a_field, rbp_r_p, \
- rbp_r_t); \
- } \
- rbp_r_c = rbp_r_t; \
- } else { \
- rbp_r_p = rbp_r_c; \
- rbp_r_c = rbp_right_get(a_type, a_field, rbp_r_c); \
- } \
- } \
- } \
- } \
- /* Update root. */\
- (a_tree)->rbt_root = rbp_left_get(a_type, a_field, &rbp_r_s); \
-} while (0)
-
-/*
- * The rb_wrap() macro provides a convenient way to wrap functions around the
- * cpp macros. The main benefits of wrapping are that 1) repeated macro
- * expansion can cause code bloat, especially for rb_{insert,remove)(), and
- * 2) type, linkage, comparison functions, etc. need not be specified at every
- * call point.
- */
-
-#define rb_wrap(a_attr, a_prefix, a_tree_type, a_type, a_field, a_cmp) \
-a_attr void \
-a_prefix##new(a_tree_type *tree) { \
- rb_new(a_type, a_field, tree); \
-} \
-a_attr a_type * \
-a_prefix##first(a_tree_type *tree) { \
- a_type *ret; \
- rb_first(a_type, a_field, tree, ret); \
- return (ret); \
-} \
-a_attr a_type * \
-a_prefix##last(a_tree_type *tree) { \
- a_type *ret; \
- rb_last(a_type, a_field, tree, ret); \
- return (ret); \
-} \
-a_attr a_type * \
-a_prefix##next(a_tree_type *tree, a_type *node) { \
- a_type *ret; \
- rb_next(a_type, a_field, a_cmp, tree, node, ret); \
- return (ret); \
-} \
-a_attr a_type * \
-a_prefix##prev(a_tree_type *tree, a_type *node) { \
- a_type *ret; \
- rb_prev(a_type, a_field, a_cmp, tree, node, ret); \
- return (ret); \
-} \
-a_attr a_type * \
-a_prefix##search(a_tree_type *tree, a_type *key) { \
- a_type *ret; \
- rb_search(a_type, a_field, a_cmp, tree, key, ret); \
- return (ret); \
-} \
-a_attr a_type * \
-a_prefix##nsearch(a_tree_type *tree, a_type *key) { \
- a_type *ret; \
- rb_nsearch(a_type, a_field, a_cmp, tree, key, ret); \
- return (ret); \
-} \
-a_attr a_type * \
-a_prefix##psearch(a_tree_type *tree, a_type *key) { \
- a_type *ret; \
- rb_psearch(a_type, a_field, a_cmp, tree, key, ret); \
- return (ret); \
-} \
-a_attr void \
-a_prefix##insert(a_tree_type *tree, a_type *node) { \
- rb_insert(a_type, a_field, a_cmp, tree, node); \
-} \
-a_attr void \
-a_prefix##remove(a_tree_type *tree, a_type *node) { \
- rb_remove(a_type, a_field, a_cmp, tree, node); \
-}
-
-/*
- * The iterators simulate recursion via an array of pointers that store the
- * current path. This is critical to performance, since a series of calls to
- * rb_{next,prev}() would require time proportional to (n lg n), whereas this
- * implementation only requires time proportional to (n).
- *
- * Since the iterators cache a path down the tree, any tree modification may
- * cause the cached path to become invalid. In order to continue iteration,
- * use something like the following sequence:
- *
- * {
- * a_type *node, *tnode;
- *
- * rb_foreach_begin(a_type, a_field, a_tree, node) {
- * ...
- * rb_next(a_type, a_field, a_cmp, a_tree, node, tnode);
- * rb_remove(a_type, a_field, a_cmp, a_tree, node);
- * rb_foreach_next(a_type, a_field, a_cmp, a_tree, tnode);
- * ...
- * } rb_foreach_end(a_type, a_field, a_tree, node)
- * }
- *
- * Note that this idiom is not advised if every iteration modifies the tree,
- * since in that case there is no algorithmic complexity improvement over a
- * series of rb_{next,prev}() calls, thus making the setup overhead wasted
- * effort.
- */
-
-#ifdef RB_NO_C99_VARARRAYS
- /*
- * Avoid using variable-length arrays, at the cost of using more stack space.
- * Size the path arrays such that they are always large enough, even if a
- * tree consumes all of memory. Since each node must contain a minimum of
- * two pointers, there can never be more nodes than:
- *
- * 1 << ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1))
- *
- * Since the depth of a tree is limited to 3*lg(#nodes), the maximum depth
- * is:
- *
- * (3 * ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1)))
- *
- * This works out to a maximum depth of 87 and 180 for 32- and 64-bit
- * systems, respectively (approximatly 348 and 1440 bytes, respectively).
- */
-# define rbp_compute_f_height(a_type, a_field, a_tree)
-# define rbp_f_height (3 * ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1)))
-# define rbp_compute_fr_height(a_type, a_field, a_tree)
-# define rbp_fr_height (3 * ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1)))
-#else
-# define rbp_compute_f_height(a_type, a_field, a_tree) \
- /* Compute the maximum possible tree depth (3X the black height). */\
- unsigned rbp_f_height; \
- rbp_black_height(a_type, a_field, a_tree, rbp_f_height); \
- rbp_f_height *= 3;
-# define rbp_compute_fr_height(a_type, a_field, a_tree) \
- /* Compute the maximum possible tree depth (3X the black height). */\
- unsigned rbp_fr_height; \
- rbp_black_height(a_type, a_field, a_tree, rbp_fr_height); \
- rbp_fr_height *= 3;
-#endif
-
-#define rb_foreach_begin(a_type, a_field, a_tree, a_var) { \
- rbp_compute_f_height(a_type, a_field, a_tree) \
- { \
- /* Initialize the path to contain the left spine. */\
- a_type *rbp_f_path[rbp_f_height]; \
- a_type *rbp_f_node; \
- bool rbp_f_synced = false; \
- unsigned rbp_f_depth = 0; \
- if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) { \
- rbp_f_path[rbp_f_depth] = (a_tree)->rbt_root; \
- rbp_f_depth++; \
- while ((rbp_f_node = rbp_left_get(a_type, a_field, \
- rbp_f_path[rbp_f_depth-1])) != &(a_tree)->rbt_nil) { \
- rbp_f_path[rbp_f_depth] = rbp_f_node; \
- rbp_f_depth++; \
- } \
- } \
- /* While the path is non-empty, iterate. */\
- while (rbp_f_depth > 0) { \
- (a_var) = rbp_f_path[rbp_f_depth-1];
-
-/* Only use if modifying the tree during iteration. */
-#define rb_foreach_next(a_type, a_field, a_cmp, a_tree, a_node) \
- /* Re-initialize the path to contain the path to a_node. */\
- rbp_f_depth = 0; \
- if (a_node != NULL) { \
- if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) { \
- rbp_f_path[rbp_f_depth] = (a_tree)->rbt_root; \
- rbp_f_depth++; \
- rbp_f_node = rbp_f_path[0]; \
- while (true) { \
- int rbp_f_cmp = (a_cmp)((a_node), \
- rbp_f_path[rbp_f_depth-1]); \
- if (rbp_f_cmp < 0) { \
- rbp_f_node = rbp_left_get(a_type, a_field, \
- rbp_f_path[rbp_f_depth-1]); \
- } else if (rbp_f_cmp > 0) { \
- rbp_f_node = rbp_right_get(a_type, a_field, \
- rbp_f_path[rbp_f_depth-1]); \
- } else { \
- break; \
- } \
- assert(rbp_f_node != &(a_tree)->rbt_nil); \
- rbp_f_path[rbp_f_depth] = rbp_f_node; \
- rbp_f_depth++; \
- } \
- } \
- } \
- rbp_f_synced = true;
-
-#define rb_foreach_end(a_type, a_field, a_tree, a_var) \
- if (rbp_f_synced) { \
- rbp_f_synced = false; \
- continue; \
- } \
- /* Find the successor. */\
- if ((rbp_f_node = rbp_right_get(a_type, a_field, \
- rbp_f_path[rbp_f_depth-1])) != &(a_tree)->rbt_nil) { \
- /* The successor is the left-most node in the right */\
- /* subtree. */\
- rbp_f_path[rbp_f_depth] = rbp_f_node; \
- rbp_f_depth++; \
- while ((rbp_f_node = rbp_left_get(a_type, a_field, \
- rbp_f_path[rbp_f_depth-1])) != &(a_tree)->rbt_nil) { \
- rbp_f_path[rbp_f_depth] = rbp_f_node; \
- rbp_f_depth++; \
- } \
- } else { \
- /* The successor is above the current node. Unwind */\
- /* until a left-leaning edge is removed from the */\
- /* path, or the path is empty. */\
- for (rbp_f_depth--; rbp_f_depth > 0; rbp_f_depth--) { \
- if (rbp_left_get(a_type, a_field, \
- rbp_f_path[rbp_f_depth-1]) \
- == rbp_f_path[rbp_f_depth]) { \
- break; \
- } \
- } \
- } \
- } \
- } \
-}
-
-#define rb_foreach_reverse_begin(a_type, a_field, a_tree, a_var) { \
- rbp_compute_fr_height(a_type, a_field, a_tree) \
- { \
- /* Initialize the path to contain the right spine. */\
- a_type *rbp_fr_path[rbp_fr_height]; \
- a_type *rbp_fr_node; \
- bool rbp_fr_synced = false; \
- unsigned rbp_fr_depth = 0; \
- if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) { \
- rbp_fr_path[rbp_fr_depth] = (a_tree)->rbt_root; \
- rbp_fr_depth++; \
- while ((rbp_fr_node = rbp_right_get(a_type, a_field, \
- rbp_fr_path[rbp_fr_depth-1])) != &(a_tree)->rbt_nil) { \
- rbp_fr_path[rbp_fr_depth] = rbp_fr_node; \
- rbp_fr_depth++; \
- } \
- } \
- /* While the path is non-empty, iterate. */\
- while (rbp_fr_depth > 0) { \
- (a_var) = rbp_fr_path[rbp_fr_depth-1];
-
-/* Only use if modifying the tree during iteration. */
-#define rb_foreach_reverse_prev(a_type, a_field, a_cmp, a_tree, a_node) \
- /* Re-initialize the path to contain the path to a_node. */\
- rbp_fr_depth = 0; \
- if (a_node != NULL) { \
- if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) { \
- rbp_fr_path[rbp_fr_depth] = (a_tree)->rbt_root; \
- rbp_fr_depth++; \
- rbp_fr_node = rbp_fr_path[0]; \
- while (true) { \
- int rbp_fr_cmp = (a_cmp)((a_node), \
- rbp_fr_path[rbp_fr_depth-1]); \
- if (rbp_fr_cmp < 0) { \
- rbp_fr_node = rbp_left_get(a_type, a_field, \
- rbp_fr_path[rbp_fr_depth-1]); \
- } else if (rbp_fr_cmp > 0) { \
- rbp_fr_node = rbp_right_get(a_type, a_field,\
- rbp_fr_path[rbp_fr_depth-1]); \
- } else { \
- break; \
- } \
- assert(rbp_fr_node != &(a_tree)->rbt_nil); \
- rbp_fr_path[rbp_fr_depth] = rbp_fr_node; \
- rbp_fr_depth++; \
- } \
- } \
- } \
- rbp_fr_synced = true;
-
-#define rb_foreach_reverse_end(a_type, a_field, a_tree, a_var) \
- if (rbp_fr_synced) { \
- rbp_fr_synced = false; \
- continue; \
- } \
- if (rbp_fr_depth == 0) { \
- /* rb_foreach_reverse_sync() was called with a NULL */\
- /* a_node. */\
- break; \
- } \
- /* Find the predecessor. */\
- if ((rbp_fr_node = rbp_left_get(a_type, a_field, \
- rbp_fr_path[rbp_fr_depth-1])) != &(a_tree)->rbt_nil) { \
- /* The predecessor is the right-most node in the left */\
- /* subtree. */\
- rbp_fr_path[rbp_fr_depth] = rbp_fr_node; \
- rbp_fr_depth++; \
- while ((rbp_fr_node = rbp_right_get(a_type, a_field, \
- rbp_fr_path[rbp_fr_depth-1])) != &(a_tree)->rbt_nil) {\
- rbp_fr_path[rbp_fr_depth] = rbp_fr_node; \
- rbp_fr_depth++; \
- } \
- } else { \
- /* The predecessor is above the current node. Unwind */\
- /* until a right-leaning edge is removed from the */\
- /* path, or the path is empty. */\
- for (rbp_fr_depth--; rbp_fr_depth > 0; rbp_fr_depth--) {\
- if (rbp_right_get(a_type, a_field, \
- rbp_fr_path[rbp_fr_depth-1]) \
- == rbp_fr_path[rbp_fr_depth]) { \
- break; \
- } \
- } \
- } \
- } \
- } \
-}
-
-#endif /* RB_H_ */
diff --git a/libbase/jemalloc_types.h b/libbase/jemalloc_types.h
deleted file mode 100644
index 7b18f6c..0000000
--- a/libbase/jemalloc_types.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*- Mode: C; tab-width: 8; c-basic-offset: 8 -*- */
-/* vim:set softtabstop=8 shiftwidth=8: */
-/*-
- * Copyright (C) 2006-2008 Jason Evans <jasone at FreeBSD.org>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice(s), this list of conditions and the following disclaimer as
- * the first lines of this file unmodified other than the possible
- * addition of one or more copyright notices.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice(s), this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _JEMALLOC_TYPES_H_
-#define _JEMALLOC_TYPES_H_
-
-/* grab size_t */
-#ifdef _MSC_VER
-#include <crtdefs.h>
-#else
-#include <stddef.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef unsigned char jemalloc_bool;
-
-/*
- * jemalloc_stats() is not a stable interface. When using jemalloc_stats_t, be
- * sure that the compiled results of jemalloc.c are in sync with this header
- * file.
- */
-typedef struct {
- /*
- * Run-time configuration settings.
- */
- jemalloc_bool opt_abort; /* abort(3) on error? */
- jemalloc_bool opt_junk; /* Fill allocated/free memory with 0xa5/0x5a? */
- jemalloc_bool opt_utrace; /* Trace all allocation events? */
- jemalloc_bool opt_sysv; /* SysV semantics? */
- jemalloc_bool opt_xmalloc; /* abort(3) on OOM? */
- jemalloc_bool opt_zero; /* Fill allocated memory with 0x0? */
- size_t narenas; /* Number of arenas. */
- size_t balance_threshold; /* Arena contention rebalance threshold. */
- size_t quantum; /* Allocation quantum. */
- size_t small_max; /* Max quantum-spaced allocation size. */
- size_t large_max; /* Max sub-chunksize allocation size. */
- size_t chunksize; /* Size of each virtual memory mapping. */
- size_t dirty_max; /* Max dirty pages per arena. */
-
- /*
- * Current memory usage statistics.
- */
- size_t mapped; /* Bytes mapped (not necessarily committed). */
- size_t committed; /* Bytes committed (readable/writable). */
- size_t allocated; /* Bytes allocted (in use by application). */
- size_t dirty; /* Bytes dirty (committed unused pages). */
-} jemalloc_stats_t;
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* _JEMALLOC_TYPES_H_ */
diff --git a/libbase/log.cpp b/libbase/log.cpp
index 14ef03c..2920bdd 100644
--- a/libbase/log.cpp
+++ b/libbase/log.cpp
@@ -123,6 +123,11 @@ void
processLog_trace(const boost::format& fmt)
{
dbglogfile.log(N_("TRACE"), fmt.str());
+ // Print messages to the Android log, where they can be retrieved with
+ // logcat.
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_INFO, "Gnash", fmt.str().c_str());
+#endif
}
void
@@ -130,6 +135,11 @@ processLog_debug(const boost::format& fmt)
{
if (dbglogfile.getVerbosity() < LogFile::LOG_DEBUG) return;
dbglogfile.log(N_("DEBUG"), fmt.str());
+ // Print messages to the Android log, where they can be retrieved with
+ // logcat.
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_DEBUG, "Gnash", fmt.str().c_str());
+#endif
}
void
@@ -137,48 +147,88 @@ processLog_abc(const boost::format& fmt)
{
if (dbglogfile.getVerbosity() < LogFile::LOG_EXTRA) return;
dbglogfile.log(N_("ABC"), fmt.str());
+ // Print messages to the Android log, where they can be retrieved with
+ // logcat.
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_VERBOSE, "Gnash", fmt.str().c_str());
+#endif
}
void
processLog_parse(const boost::format& fmt)
{
dbglogfile.log(fmt.str());
+ // Print messages to the Android log, where they can be retrieved with
+ // logcat.
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_VERBOSE, "Gnash", fmt.str().c_str());
+#endif
}
void
processLog_network(const boost::format& fmt)
{
dbglogfile.log(N_("NETWORK"), fmt.str());
+ // Print messages to the Android log, where they can be retrieved with
+ // logcat.
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_DEBUG, "Gnash", fmt.str().c_str());
+#endif
}
void
processLog_error(const boost::format& fmt)
{
dbglogfile.log(N_("ERROR"), fmt.str());
+ // Print messages to the Android log, where they can be retrieved with
+ // logcat.
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_ERROR, "Gnash", fmt.str().c_str());
+#endif
}
void
processLog_unimpl(const boost::format& fmt)
{
dbglogfile.log(N_("UNIMPLEMENTED"), fmt.str());
+ // Print messages to the Android log, where they can be retrieved with
+ // logcat.
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_WARN, "Gnash", fmt.str().c_str());
+#endif
}
void
processLog_security(const boost::format& fmt)
{
dbglogfile.log(N_("SECURITY"), fmt.str());
+ // Print messages to the Android log, where they can be retrieved with
+ // logcat.
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_WARN, "Gnash", fmt.str().c_str());
+#endif
}
void
processLog_swferror(const boost::format& fmt)
{
dbglogfile.log(N_("MALFORMED SWF"), fmt.str());
+ // Print messages to the Android log, where they can be retrieved with
+ // logcat.
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_WARN, "Gnash", fmt.str().c_str());
+#endif
}
void
processLog_aserror(const boost::format& fmt)
{
dbglogfile.log(N_("ACTIONSCRIPT ERROR"), fmt.str());
+ // Print messages to the Android log, where they can be retrieved with
+ // logcat.
+#ifdef __ANDROID__
+ __android_log_print(ANDROID_LOG_WARN, "Gnash", fmt.str().c_str());
+#endif
}
void
@@ -374,6 +424,6 @@ inline unsigned long int /* pthread_t */ get_thread_id(void)
// Local Variables:
// mode: C++
-// indent-tabs-mode: t
+// indent-tabs-mode: nil
// End:
diff --git a/libbase/log.h b/libbase/log.h
index 5a6a041..962d5bf 100644
--- a/libbase/log.h
+++ b/libbase/log.h
@@ -30,6 +30,12 @@
#include <boost/thread/mutex.hpp>
#include <boost/format.hpp>
+// This is needed so we can print to the Android log file, which can
+// be retrieved with logcat.
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
// the default name for the debug log
#define DEFAULT_LOGFILE "gnash-dbg.log"
@@ -438,7 +444,6 @@ private:
}
-
#endif // GNASH_LOG_H
diff --git a/libbase/rc.cpp b/libbase/rc.cpp
index ef79d6e..5192792 100644
--- a/libbase/rc.cpp
+++ b/libbase/rc.cpp
@@ -83,7 +83,7 @@ RcInitFile::RcInitFile()
DEFAULT_FLASH_REV_NUMBER ",0"),
// An empty string leaves detection to VM.cpp:
_flashSystemOS(""),
- _flashSystemManufacturer("Gnash "DEFAULT_FLASH_SYSTEM_OS),
+ _flashSystemManufacturer("Gnash " DEFAULT_FLASH_SYSTEM_OS),
_actionDump(false),
_parserDump(false),
_verboseASCodingErrors(false),
@@ -777,8 +777,7 @@ RcInitFile::updateFile(const std::string& filespec)
cmd << "SOLSafeDir " << _solsandbox << endl <<
cmd << "localConnection " << _lcdisabled << endl <<
cmd << "LCTrace " << _lctrace << endl <<
- cmd << "LCShmkey " << std::hex << (boost::uint32_t) _lcshmkey
- << std::dec << endl <<
+ cmd << "LCShmkey " << std::hex << _lcshmkey << std::dec << endl <<
cmd << "ignoreFSCommand " << _ignoreFSCommand << endl <<
cmd << "ignoreShowMenu " << _ignoreShowMenu << endl <<
cmd << "saveStreamingMedia " << _saveStreamingMedia << endl <<
diff --git a/libbase/sharedlib.cpp b/libbase/sharedlib.cpp
index 8528818..918bf69 100644
--- a/libbase/sharedlib.cpp
+++ b/libbase/sharedlib.cpp
@@ -101,7 +101,7 @@ SharedLib::openLib (const std::string& filespec)
_dlhandle = lt_dlopenext (filespec.c_str());
if (_dlhandle == NULL) {
- log_error("%s", lt_dlerror());
+ log_error("lt_dlopenext(\"%s\") failed: %s", filespec.c_str(), lt_dlerror());
return false;
}
diff --git a/libbase/utf8.cpp b/libbase/utf8.cpp
index bcf3d9f..31f3c8e 100644
--- a/libbase/utf8.cpp
+++ b/libbase/utf8.cpp
@@ -344,8 +344,8 @@ guessEncoding(const std::string &str, int &length, std::vector<int>& offsets)
was_even = !was_odd;
}
- it++;
- index++;
+ ++it;
+ ++index;
}
offsets.push_back(index); // [length - 1] = index;
diff --git a/libbase/utf8.h b/libbase/utf8.h
index 6b28d57..2be2711 100644
--- a/libbase/utf8.h
+++ b/libbase/utf8.h
@@ -27,6 +27,17 @@
#include "dsodefs.h" // For DSOEXPORT
+// Android doesn't have any support for wide characters at all.
+#ifdef __ANDROID__
+namespace std {
+typedef basic_string
+ <wchar_t
+ ,std::char_traits<wchar_t>
+ ,std::allocator<wchar_t> >
+wstring;
+}
+#endif
+
namespace gnash {
/// Utilities to convert between std::string and std::wstring.
diff --git a/libbase/zlib_adapter.cpp b/libbase/zlib_adapter.cpp
index f40ff11..1ef03d5 100644
--- a/libbase/zlib_adapter.cpp
+++ b/libbase/zlib_adapter.cpp
@@ -324,7 +324,5 @@ std::auto_ptr<IOChannel> make_inflater(std::auto_ptr<IOChannel> in)
// Local Variables:
// mode: C++
-// c-basic-offset: 8
-// tab-width: 8
// indent-tabs-mode: nil
// End:
diff --git a/libcore/Bitmap.cpp b/libcore/Bitmap.cpp
index dc93441..cad8767 100644
--- a/libcore/Bitmap.cpp
+++ b/libcore/Bitmap.cpp
@@ -28,6 +28,7 @@
#include "movie_root.h"
#include "RunResources.h"
#include "Transform.h"
+#include "BitmapMovieDefinition.h"
namespace gnash {
@@ -90,13 +91,14 @@ Bitmap::construct(as_object* /*init*/)
const size_t fillLeft = _shape.addFillStyle(fill);
- Path bmpath(w, h, fillLeft, 0, 0, false);
+ Path bmpath(w, h, fillLeft, 0, 0);
bmpath.drawLineTo(w, 0);
bmpath.drawLineTo(0, 0);
bmpath.drawLineTo(0, h);
bmpath.drawLineTo(w, h);
_shape.add_path(bmpath);
+ _shape.setBounds(SWFRect(0, 0, w, h));
_shape.finalize();
set_invalidated();
diff --git a/libcore/Bitmap.h b/libcore/Bitmap.h
index 5c00701..b0f4628 100644
--- a/libcore/Bitmap.h
+++ b/libcore/Bitmap.h
@@ -23,11 +23,11 @@
#include <boost/intrusive_ptr.hpp>
#include "DisplayObject.h"
#include "flash/display/BitmapData_as.h"
-#include "BitmapMovieDefinition.h"
#include "DynamicShape.h"
namespace gnash {
class CachedBitmap;
+ class BitmapMovieDefinition;
}
diff --git a/libcore/Button.cpp b/libcore/Button.cpp
index 761a0ea..94cdd7c 100644
--- a/libcore/Button.cpp
+++ b/libcore/Button.cpp
@@ -512,7 +512,7 @@ Button::mouseEvent(const event_id& event)
// no sound for this transition
if (bi < 0) break;
-
+#ifdef USE_SOUND
const SWF::DefineButtonSoundTag::ButtonSound& bs =
_def->buttonSound(bi);
@@ -539,7 +539,8 @@ Button::mouseEvent(const event_id& event)
sinfo.outPoint
);
}
-
+#endif // USE_SOUND
+
} while(0);
// From: "ActionScript - The Definitive Guide" by Colin Moock
diff --git a/libcore/Button.h b/libcore/Button.h
index 843e250..1414564 100644
--- a/libcore/Button.h
+++ b/libcore/Button.h
@@ -29,6 +29,7 @@
#include "InteractiveObject.h"
#include "GnashKey.h"
+#include "dsodefs.h"
// Forward declarations.
namespace gnash {
@@ -40,7 +41,7 @@ namespace gnash {
namespace gnash {
/// Button implements Flash buttons.
-class Button : public InteractiveObject
+class DSOTEXPORT Button : public InteractiveObject
{
public:
diff --git a/libcore/ClassHierarchy.h b/libcore/ClassHierarchy.h
index 161afd9..c372c57 100644
--- a/libcore/ClassHierarchy.h
+++ b/libcore/ClassHierarchy.h
@@ -26,7 +26,6 @@
#include <string>
#include <vector>
-#include <iosfwd>
#include "ObjectURI.h"
diff --git a/libcore/DisplayList.h b/libcore/DisplayList.h
index a316e19..14aedf0 100644
--- a/libcore/DisplayList.h
+++ b/libcore/DisplayList.h
@@ -20,9 +20,6 @@
#ifndef GNASH_DLIST_H
#define GNASH_DLIST_H
-#include "snappingrange.h"
-
-#include <string>
#include <list>
#include <iosfwd>
#if GNASH_PARANOIA_LEVEL > 1 && !defined(NDEBUG)
@@ -32,6 +29,10 @@
#include "log.h"
#endif
+#include "snappingrange.h"
+#include "dsodefs.h" // for DSOTEXPORT
+
+
// GNASH_PARANOIA_LEVEL:
// 0 : (not unimplemented)
// 1 : quick assertions
@@ -93,7 +94,7 @@ public:
///
/// @param depth
/// depth at which the new DisplayObject is placed.
- void placeDisplayObject(DisplayObject* ch, int depth);
+ DSOTEXPORT void placeDisplayObject(DisplayObject* ch, int depth);
/// \brief
/// Replace the old DisplayObject at the specified depth with
@@ -219,7 +220,7 @@ public:
void omit_display();
/// May return NULL.
- DisplayObject* getDisplayObjectAtDepth(int depth) const;
+ DSOTEXPORT DisplayObject* getDisplayObjectAtDepth(int depth) const;
/// If there are multiples, returns the *first* match only!
//
@@ -232,7 +233,7 @@ public:
/// @param caseless
/// Wheter comparison must be case-insensitive.
///
- DisplayObject* getDisplayObjectByName(string_table& st,
+ DSOTEXPORT DisplayObject* getDisplayObjectByName(string_table& st,
const ObjectURI& uri, bool caseless) const;
/// \brief
@@ -389,7 +390,7 @@ DisplayList::visitAll(V& visitor) const
}
}
-std::ostream& operator<< (std::ostream&, const DisplayList&);
+DSOTEXPORT std::ostream& operator<< (std::ostream&, const DisplayList&);
} // namespace gnash
diff --git a/libcore/DisplayObject.cpp b/libcore/DisplayObject.cpp
index 9923cc5..254c4bd 100644
--- a/libcore/DisplayObject.cpp
+++ b/libcore/DisplayObject.cpp
@@ -31,6 +31,9 @@
#include "movie_root.h"
#include "MovieClip.h"
+#include "Movie.h"
+#include "DisplayObject.h"
+#include "Object.h"
#include "VM.h"
#include "fn_call.h"
#include "GnashException.h"
@@ -354,7 +357,7 @@ as_value
getHeight(DisplayObject& o)
{
SWFRect bounds = o.getBounds();
- const SWFMatrix m = getMatrix(o);
+ const SWFMatrix& m = getMatrix(o);
m.transform(bounds);
return twipsToPixels(bounds.height());
}
@@ -1109,7 +1112,7 @@ setY(DisplayObject& o, const as_value& val)
as_value
getY(DisplayObject& o)
{
- const SWFMatrix m = getMatrix(o);
+ const SWFMatrix& m = getMatrix(o);
return twipsToPixels(m.get_y_translation());
}
@@ -1140,7 +1143,7 @@ setX(DisplayObject& o, const as_value& val)
as_value
getX(DisplayObject& o)
{
- const SWFMatrix m = getMatrix(o);
+ const SWFMatrix& m = getMatrix(o);
return twipsToPixels(m.get_x_translation());
}
@@ -1389,7 +1392,7 @@ getFocusRect(DisplayObject& o)
if (boost::indeterminate(fr)) {
as_value null;
null.set_null();
- return as_value(null);
+ return null;
}
const bool ret = static_cast<bool>(fr);
if (getSWFVersion(*getObject(&o)) == 5) {
@@ -1548,12 +1551,12 @@ doSet(const ObjectURI& uri, DisplayObject& o, const as_value& val)
{
string_table& st = getStringTable(*getObject(&o));
- const GetterSetter gs = getGetterSetterByURI(uri, st);
+ const GetterSetter& gs = getGetterSetterByURI(uri, st);
// not found (all props have getters)
if (!gs.first) return false;
- const Setter s = gs.second;
+ const Setter& s = gs.second;
// read-only (TODO: aserror ?)
if (!s) return true;
diff --git a/libcore/DisplayObject.h b/libcore/DisplayObject.h
index 0dc0630..bde7359 100644
--- a/libcore/DisplayObject.h
+++ b/libcore/DisplayObject.h
@@ -165,7 +165,7 @@ SWFCxForm getWorldCxForm(const DisplayObject& d);
/// dynamic DisplayObjects, but tags are not always stored. They are not
/// stored in most InteractiveObjects because most properties can be
/// overridden during SWF execution.
-class DisplayObject : public GcResource, boost::noncopyable
+class DSOTEXPORT DisplayObject : public GcResource, boost::noncopyable
{
public:
diff --git a/libcore/DynamicShape.cpp b/libcore/DynamicShape.cpp
index 4b5e1fc..10bc3cb 100644
--- a/libcore/DynamicShape.cpp
+++ b/libcore/DynamicShape.cpp
@@ -41,6 +41,7 @@ DynamicShape::clear()
_shape.clear();
_currpath = 0;
_currfill = _currline = 0;
+ _currsubshape.clear();
// TODO: worth setting _changed=true ?
}
@@ -53,8 +54,9 @@ DynamicShape::display(Renderer& renderer, const Transform& xform) const
void
DynamicShape::add_path(const Path& pth)
{
- _shape.addPath(pth);
- _currpath = &_shape.currentPath();
+ _currsubshape.addPath(pth);
+ _currpath = &_currsubshape.currentPath();
+ _changed = true;
}
void
@@ -80,6 +82,11 @@ DynamicShape::endFill()
_y = _currpath->ap.y;
}
+ if (_currline) {
+ _shape.addSubshape(_currsubshape);
+ _currsubshape.paths().clear(); // Retain style info
+ }
+
// Remove reference to the "current" path, as
// next drawing will happen on a different one
_currpath = 0;
@@ -93,12 +100,13 @@ DynamicShape::beginFill(const FillStyle& f)
// End previous fill
endFill();
+
_currfill = addFillStyle(f);
// TODO: how to know wheter the fill should be set
// as *left* or *right* fill ?
// A quick test shows that *left* always work fine !
- Path newPath(_x, _y, _currfill, 0, _currline, true);
+ Path newPath(_x, _y, _currfill, 0, _currline);
add_path(newPath);
}
@@ -112,12 +120,18 @@ DynamicShape::startNewPath(bool newShape)
_currpath->close();
}
+ if (newShape) {
+ _shape.addSubshape(_currsubshape);
+ _currsubshape.paths().clear(); // Retain style info
+ }
+
+
// The DrawingApiTest.swf file shows we should not
// end the current fill when starting a new path.
// A quick test shows that *left* always work fine !
// More than that, using a *right* fill seems to break the tests !
- Path newPath(_x, _y, _currfill, 0, _currline, newShape);
+ Path newPath(_x, _y, _currfill, 0, _currline);
add_path(newPath);
}
@@ -130,11 +144,16 @@ DynamicShape::finalize() const
// Close any pending filled path (_currpath should be last path)
if ( _currpath && _currfill)
{
- assert(!_shape.paths().empty());
- assert(_currpath == &(_shape.paths().back()));
+ assert(!_currsubshape.paths().empty());
+ assert(_currpath == &(_currsubshape.paths().back()));
_currpath->close();
}
+ // This function being const seems to be at odds with its purpose...
+ _shape.addSubshape(_currsubshape);
+
+ _currsubshape.clear();
+
// TODO: check consistency of fills and such !
_changed = false;
@@ -176,7 +195,7 @@ DynamicShape::moveTo(boost::int32_t x, boost::int32_t y)
void
DynamicShape::lineTo(boost::int32_t x, boost::int32_t y, int swfVersion)
{
- if (!_currpath) startNewPath(true);
+ if (!_currpath) startNewPath(false);
assert(_currpath);
_currpath->drawLineTo(x, y);
@@ -185,7 +204,7 @@ DynamicShape::lineTo(boost::int32_t x, boost::int32_t y, int swfVersion)
SWFRect bounds = _shape.getBounds();
unsigned thickness = _currline ?
- _shape.lineStyles().back().getThickness() : 0;
+ _currsubshape.lineStyles().back().getThickness() : 0;
if (_currpath->size() == 1) {
_currpath->expandBounds(bounds, thickness, swfVersion);
@@ -208,7 +227,7 @@ void
DynamicShape::curveTo(boost::int32_t cx, boost::int32_t cy,
boost::int32_t ax, boost::int32_t ay, int swfVersion)
{
- if (!_currpath) startNewPath(true);
+ if (!_currpath) startNewPath(false);
assert(_currpath);
_currpath->drawCurveTo(cx, cy, ax, ay);
@@ -216,7 +235,7 @@ DynamicShape::curveTo(boost::int32_t cx, boost::int32_t cy,
SWFRect bounds = _shape.getBounds();
unsigned thickness = _currline ?
- _shape.lineStyles().back().getThickness() : 0;
+ _currsubshape.lineStyles().back().getThickness() : 0;
if (_currpath->size() == 1) {
_currpath->expandBounds(bounds, thickness, swfVersion);
@@ -241,15 +260,15 @@ DynamicShape::curveTo(boost::int32_t cx, boost::int32_t cy,
size_t
DynamicShape::addFillStyle(const FillStyle& stl)
{
- _shape.addFillStyle(stl);
- return _shape.fillStyles().size();
+ _currsubshape.addFillStyle(stl);
+ return _currsubshape.fillStyles().size();
}
size_t
DynamicShape::add_line_style(const LineStyle& stl)
{
- _shape.addLineStyle(stl);
- return _shape.lineStyles().size();
+ _currsubshape.addLineStyle(stl);
+ return _currsubshape.lineStyles().size();
}
} // end namespace gnash
diff --git a/libcore/DynamicShape.h b/libcore/DynamicShape.h
index 0eb3d20..c082c23 100644
--- a/libcore/DynamicShape.h
+++ b/libcore/DynamicShape.h
@@ -21,7 +21,6 @@
#ifndef GNASH_DYNAMIC_SHAPE_H
#define GNASH_DYNAMIC_SHAPE_H
-#include <vector>
#include "LineStyle.h"
#include "ShapeRecord.h"
@@ -148,8 +147,7 @@ public:
const SWFMatrix& wm) const
{
finalize();
- return geometry::pointTest(_shape.paths(), _shape.lineStyles(), x, y,
- wm);
+ return _shape.pointTest(x, y, wm);
}
const SWF::ShapeRecord& shapeRecord() const {
@@ -182,6 +180,8 @@ private:
/// If newShape is true the new shape will start a new subshape.
void startNewPath(bool newShape);
+
+
Path* _currpath;
size_t _currfill;
@@ -196,6 +196,8 @@ private:
mutable bool _changed;
+ mutable SWF::Subshape _currsubshape;
+
/// The actual SWF::ShapeRecord wrapped by this class.
//
/// Mutable for lazy finalization.
diff --git a/libcore/ExternalInterface.h b/libcore/ExternalInterface.h
index 5d0c635..7ad0047 100644
--- a/libcore/ExternalInterface.h
+++ b/libcore/ExternalInterface.h
@@ -23,7 +23,6 @@
#include <string>
#include <vector>
-#include <map>
#include <set>
#include <boost/shared_ptr.hpp>
diff --git a/libcore/FreetypeGlyphsProvider.cpp b/libcore/FreetypeGlyphsProvider.cpp
index 608019d..273bd10 100644
--- a/libcore/FreetypeGlyphsProvider.cpp
+++ b/libcore/FreetypeGlyphsProvider.cpp
@@ -99,14 +99,15 @@ public:
{
/// A default fill style is solid white.
FillStyle f = SolidFill(rgba());
- _shape.addFillStyle(f);
- _shape.addPath(Path(_x, _y, 1, 0, 0, true));
- _currPath = &_shape.currentPath();
+ _subshape.addFillStyle(f);
+ _subshape.addPath(Path(_x, _y, 1, 0, 0));
+ _currPath = &_subshape.currentPath();
}
void finish()
{
_currPath->close();
+ _shape.addSubshape(_subshape);
}
~OutlineWalker() {}
@@ -158,8 +159,8 @@ private:
_x = static_cast<boost::int32_t>(to->x * _scale);
_y = - static_cast<boost::int32_t>(to->y * _scale);
_currPath->close();
- _shape.addPath(Path(_x, _y, 1, 0, 0, false));
- _currPath = &_shape.currentPath();
+ _subshape.addPath(Path(_x, _y, 1, 0, 0));
+ _currPath = &_subshape.currentPath();
return 0;
}
@@ -227,6 +228,7 @@ private:
_shape.setBounds(bounds);
}
+ SWF::Subshape _subshape;
SWF::ShapeRecord& _shape;
const float _scale;
diff --git a/libcore/Geometry.cpp b/libcore/Geometry.cpp
index 350d249..d8cb7e3 100644
--- a/libcore/Geometry.cpp
+++ b/libcore/Geometry.cpp
@@ -161,17 +161,6 @@ pointTest(const std::vector<Path>& paths,
float next_pen_y = pth.ap.y;
float pen_x, pen_y;
- if (pth.m_new_shape)
- {
- if (( even_odd && (counter % 2) != 0) ||
- (!even_odd && (counter != 0)) )
- {
- // the point is inside the previous subshape, so exit now
- return true;
- }
-
- counter=0;
- }
if (pth.empty()) continue;
// If the path has a line style, check for strokes there
diff --git a/libcore/Geometry.h b/libcore/Geometry.h
index 5836303..5ec7ca6 100644
--- a/libcore/Geometry.h
+++ b/libcore/Geometry.h
@@ -185,16 +185,13 @@ public:
/// All paths with a higher index in the list belong to the same
/// shape unless they have m_new_shape==true on their own.
/// Sub-shapes affect the order in which outlines and shapes are rendered.
- bool m_new_shape;
/// Default constructor
//
/// @param newShape
/// True if this path starts a new subshape
///
- Path(bool newShape = false)
- :
- m_new_shape(newShape)
+ Path()
{
reset(0, 0, 0, 0, 0);
}
@@ -205,8 +202,7 @@ public:
m_fill1(from.m_fill1),
m_line(from.m_line),
ap(from.ap),
- m_edges(from.m_edges),
- m_new_shape(from.m_new_shape)
+ m_edges(from.m_edges)
{
}
@@ -233,10 +229,7 @@ public:
/// @param newShape
/// True if this path starts a new subshape
Path(boost::int32_t ax, boost::int32_t ay,
- unsigned fill0, unsigned fill1, unsigned line,
- bool newShape)
- :
- m_new_shape(newShape)
+ unsigned fill0, unsigned fill1, unsigned line)
{
reset(ax, ay, fill0, fill1, line);
}
@@ -462,18 +455,6 @@ public:
{
(*it).transform(mat);
}
- }
-
- /// Set this path as the start of a new (sub)shape
- void setNewShape()
- {
- m_new_shape=true;
- }
-
- /// Return true if this path starts a new (sub)shape
- bool getNewShape() const
- {
- return m_new_shape;
}
/// Return true if this path contains no edges
@@ -556,13 +537,6 @@ public:
{
return m_edges[n];
}
-
- /// Returns true if this path begins a new subshape. <-- VERIFYME
- bool isNewShape() const
- {
- return m_new_shape;
- }
-
}; // end of class Path
namespace geometry
diff --git a/libcore/InteractiveObject.h b/libcore/InteractiveObject.h
index cb384cc..c9cdfd7 100644
--- a/libcore/InteractiveObject.h
+++ b/libcore/InteractiveObject.h
@@ -19,13 +19,13 @@
#ifndef GNASH_INTERACTIVE_DISPLAY_OBJECT_H
#define GNASH_INTERACTIVE_DISPLAY_OBJECT_H
+#include <vector>
+#include <cassert>
+
#include "DisplayObject.h" // for inheritance
#include "log.h"
#include "as_object.h" // for getRoot()
-#include <vector>
-#include <cassert>
-
namespace gnash {
class StaticText;
namespace SWF {
diff --git a/libcore/LoadVariablesThread.cpp b/libcore/LoadVariablesThread.cpp
index 2f70eda..4229168 100644
--- a/libcore/LoadVariablesThread.cpp
+++ b/libcore/LoadVariablesThread.cpp
@@ -22,6 +22,7 @@
#include "log.h"
#include "GnashException.h"
#include "utf8.h"
+#include "StreamProvider.h"
#include <string>
#include <boost/scoped_array.hpp>
diff --git a/libcore/LoadVariablesThread.h b/libcore/LoadVariablesThread.h
index 35723d2..bd97ff8 100644
--- a/libcore/LoadVariablesThread.h
+++ b/libcore/LoadVariablesThread.h
@@ -28,10 +28,14 @@
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
-#include "StreamProvider.h" // for inlines
#include "URL.h" // for inlines
namespace gnash {
+ class StreamProvider;
+ class IOChannel;
+}
+
+namespace gnash {
// Exception thrown by LoadVariablesThread constructor if unable to connect
// to the stream input.
diff --git a/libcore/Makefile.am b/libcore/Makefile.am
index 43e8449..edce528 100644
--- a/libcore/Makefile.am
+++ b/libcore/Makefile.am
@@ -20,8 +20,11 @@ AUTOMAKE_OPTIONS =
SUBDIRS = parser vm
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
+AM_LDFLAGS = $(CROSS_LDFLAGS)
+
if ENABLE_PCH
-AM_CXXFLAGS = $(PCH_FLAGS)
+AM_CXXFLAGS += $(PCH_FLAGS)
endif
pkglib_LTLIBRARIES = libgnashcore.la
@@ -289,14 +292,19 @@ inst_HEADERS += $(EXTENSIONS_API)
libgnashcore_la_LIBADD = \
$(top_builddir)/libcore/parser/libgnashparser.la \
$(top_builddir)/libcore/vm/libgnashvm.la \
- $(top_builddir)/libmedia/libgnashmedia.la \
- $(top_builddir)/libsound/libgnashsound.la \
$(top_builddir)/libbase/libgnashbase.la \
$(BOOST_LIBS) \
$(FREETYPE2_LIBS) \
$(FONTCONFIG_LIBS) \
$(NULL)
+if BUILD_LIBMEDIA
+libgnashcore_la_LIBADD += $(top_builddir)/libmedia/libgnashmedia.la
+endif
+if BUILD_LIBSOUND
+libgnashcore_la_LIBADD += $(top_builddir)/libsound/libgnashsound.la
+endif
+
libgnashcore_la_LDFLAGS = -release $(VERSION) -export-dynamic
if HAIKU
diff --git a/libcore/MorphShape.cpp b/libcore/MorphShape.cpp
index 98f4914..f1f67ee 100644
--- a/libcore/MorphShape.cpp
+++ b/libcore/MorphShape.cpp
@@ -55,8 +55,7 @@ MorphShape::pointInShape(boost::int32_t x, boost::int32_t y) const
// shape).
if (!_shape.getBounds().point_test(lp.x, lp.y)) return false;
- return geometry::pointTest(_shape.paths(), _shape.lineStyles(),
- lp.x, lp.y, wm);
+ return _shape.pointTest(lp.x, lp.y, wm);
}
void
diff --git a/libcore/MovieClip.h b/libcore/MovieClip.h
index 03800af..4511107 100644
--- a/libcore/MovieClip.h
+++ b/libcore/MovieClip.h
@@ -27,7 +27,6 @@
#endif
#include <vector>
-#include <list>
#include <map>
#include <string>
#include <boost/ptr_container/ptr_list.hpp>
@@ -81,7 +80,7 @@ namespace gnash {
/// (Movie) containing either the definition or the code from
/// which the MovieClip was created. The _url member and SWF version are
/// dependent on the _swf. Exports are also sought in this Movie.
-class MovieClip : public DisplayObjectContainer
+class DSOTEXPORT MovieClip : public DisplayObjectContainer
{
public:
diff --git a/libcore/MovieLoader.h b/libcore/MovieLoader.h
index b20e155..b67719b 100644
--- a/libcore/MovieLoader.h
+++ b/libcore/MovieLoader.h
@@ -20,7 +20,6 @@
#define GNASH_MOVIE_LOADER_H
#include <boost/intrusive_ptr.hpp>
-#include <list>
#include <string>
#include <boost/ptr_container/ptr_list.hpp>
#include <boost/noncopyable.hpp>
diff --git a/libcore/Property.h b/libcore/Property.h
index d1a4b23..0733a6a 100644
--- a/libcore/Property.h
+++ b/libcore/Property.h
@@ -28,6 +28,7 @@
#include "PropFlags.h"
#include "as_value.h"
#include "ObjectURI.h"
+#include "dsodefs.h" // for DSOTEXPORT
namespace gnash {
typedef as_value (*as_c_function_ptr)(const fn_call& fn);
@@ -342,7 +343,7 @@ public:
/// properties.
/// @return the value of this property
///
- as_value getValue(const as_object& this_ptr) const;
+ DSOTEXPORT as_value getValue(const as_object& this_ptr) const;
/// Get internal cached value of this property
//
diff --git a/libcore/PropertyList.h b/libcore/PropertyList.h
index cb82542..23bba9d 100644
--- a/libcore/PropertyList.h
+++ b/libcore/PropertyList.h
@@ -33,6 +33,7 @@
#include <algorithm>
#include "Property.h" // for templated functions
+#include "dsodefs.h" // for DSOTEXPORT
// Forward declaration
namespace gnash {
@@ -129,7 +130,7 @@ public:
/// Construct the PropertyList
//
/// @param obj The as_object to which this PropertyList belongs.
- PropertyList(as_object& obj);
+ DSOTEXPORT PropertyList(as_object& obj);
/// Visit properties
//
@@ -184,7 +185,7 @@ public:
/// Flags to associate to the property if a new one is created.
/// @return true if the value was successfully set, false
/// otherwise (found a read-only property, most likely).
- bool setValue(const ObjectURI& uri, const as_value& value,
+ DSOTEXPORT bool setValue(const ObjectURI& uri, const as_value& value,
const PropFlags& flagsIfMissing = 0);
/// Get a property if it exists.
@@ -193,7 +194,7 @@ public:
/// @return A Property or 0, if no such property exists.
/// All Property objects are owned by this PropertyList. Do
/// not delete them.
- Property* getProperty(const ObjectURI& uri) const;
+ DSOTEXPORT Property* getProperty(const ObjectURI& uri) const;
/// Delete a Property, if existing and not protected from deletion.
//
@@ -206,7 +207,7 @@ public:
/// - (false, false) : property not found
/// - (true, false) : property protected from deletion
/// - (true, true) : property successfully deleted
- std::pair<bool,bool> delProperty(const ObjectURI& uri);
+ DSOTEXPORT std::pair<bool,bool> delProperty(const ObjectURI& uri);
/// Add a getter/setter property, if not already existing
//
@@ -266,7 +267,7 @@ public:
/// @param uri Name of the property.
/// @param setTrue The set of flags to set
/// @param setFalse The set of flags to clear
- void setFlags(const ObjectURI& uri, int setTrue, int setFalse);
+ DSOTEXPORT void setFlags(const ObjectURI& uri, int setTrue, int setFalse);
/// Set the flags of all properties.
//
diff --git a/libcore/RGBA.h b/libcore/RGBA.h
index cfb2c60..06af1af 100644
--- a/libcore/RGBA.h
+++ b/libcore/RGBA.h
@@ -24,8 +24,7 @@
#include <string>
#include <boost/cstdint.hpp>
-#include "dsodefs.h"
-#include "SWF.h"
+#include "dsodefs.h" // for DSOTEXPORT
namespace gnash {
@@ -115,7 +114,7 @@ public:
};
-std::ostream& operator<<(std::ostream& os, const rgba& r);
+DSOTEXPORT std::ostream& operator<<(std::ostream& os, const rgba& r);
/// Create an RGBA value from a hex string (e.g. FF0000)
//
@@ -125,7 +124,7 @@ std::ostream& operator<<(std::ostream& os, const rgba& r);
rgba colorFromHexString(const std::string& color);
/// Used for morphing.
-rgba lerp(const rgba& a, const rgba& b, float f);
+rgba DSOEXPORT lerp(const rgba& a, const rgba& b, float f);
} // namespace gnash
diff --git a/libcore/Relay.h b/libcore/Relay.h
index 4a07924..53d0541 100644
--- a/libcore/Relay.h
+++ b/libcore/Relay.h
@@ -88,7 +88,10 @@ public:
/// Make sure we are removed from the list of callbacks on destruction.
virtual ~ActiveRelay();
- /// ActiveRelay objects must have an advanceState method.
+ /// ActiveRelay objects must have an update() method.
+ //
+ /// The method will be called at the heart-beat frequency.
+ ///
virtual void update() = 0;
/// Mark any other reachable resources, and finally mark our owner
diff --git a/libcore/SWFMatrix.cpp b/libcore/SWFMatrix.cpp
index 46749c6..220c9ef 100644
--- a/libcore/SWFMatrix.cpp
+++ b/libcore/SWFMatrix.cpp
@@ -24,12 +24,31 @@
#include <cmath>
#include <iomanip>
+#include <iostream>
#include "log.h"
#include "GnashNumeric.h"
#include "SWFRect.h"
#include "Point2d.h"
+// The Bionic libm doesn't build sincos for ARM, but older versions
+// of boost want it. It also turns out AGG using this causes a
+// segfault by passing in 0 as an argument for x, so for now we
+// ignore that error so debugging can continue.
+#ifdef __ANDROID__
+void
+sincos(double x, double *psin, double *pcos)
+{
+ if (x > 0) {
+ *psin = sin(x);
+ *pcos = cos(x);
+ } else {
+ std::cerr << "FIXME: sincos(0) will segfault!" << std::endl;
+ // *psin = 0.244287;
+ // *pcos = 0.969703;
+ }
+}
+#endif
// This class intentionally uses overflows, which are not allowed in
// signed types; apart from being UB always, in practice it produces
@@ -206,7 +225,11 @@ void
SWFMatrix::set_scale(double xscale, double yscale)
{
const double rotation = get_rotation();
- set_scale_rotation(xscale, yscale, rotation);
+ if ((xscale == 0.0) || (yscale == 0.0)) {
+ std::cerr << "FIXME: sincos(0) will segfault!" << std::endl;
+ } else {
+ set_scale_rotation(xscale, yscale, rotation);
+ }
}
void
@@ -352,7 +375,5 @@ operator<<(std::ostream& o, const SWFMatrix& m)
// Local Variables:
// mode: C++
-// c-basic-offset: 8
-// tab-width: 8
-// indent-tabs-mode: t
+// indent-tabs-mode: nil
// End:
diff --git a/libcore/SWFMatrix.h b/libcore/SWFMatrix.h
index d1763cd..3747b70 100644
--- a/libcore/SWFMatrix.h
+++ b/libcore/SWFMatrix.h
@@ -238,7 +238,7 @@ operator==(const SWFMatrix& a, const SWFMatrix& b)
a._ty == b._ty;
}
-std::ostream& operator<<(std::ostream& o, const SWFMatrix& m);
+DSOTEXPORT std::ostream& operator<<(std::ostream& o, const SWFMatrix& m);
} // namespace gnash
diff --git a/libcore/SWFMovie.h b/libcore/SWFMovie.h
index 67fd0c1..d7d6ce8 100644
--- a/libcore/SWFMovie.h
+++ b/libcore/SWFMovie.h
@@ -22,13 +22,14 @@
#ifndef GNASH_SWF_MOVIE_H
#define GNASH_SWF_MOVIE_H
-#include "Movie.h" // for inheritance
-#include "SWFMovieDefinition.h" // for dtor visibility by smart ptr
-
#include <boost/intrusive_ptr.hpp>
#include <string>
#include <map>
+#include "Movie.h" // for inheritance
+#include "SWFMovieDefinition.h" // for dtor visibility by smart ptr
+#include "dsodefs.h" // for DSOTEXPORT
+
// Forward declarations
namespace gnash {
class DisplayObject;
@@ -54,7 +55,7 @@ class SWFMovie : public Movie
public:
- SWFMovie(as_object* object, const SWFMovieDefinition* def,
+ DSOTEXPORT SWFMovie(as_object* object, const SWFMovieDefinition* def,
DisplayObject* parent);
virtual ~SWFMovie() {}
diff --git a/libcore/SWFStream.cpp b/libcore/SWFStream.cpp
index ee400ea..2767fe2 100644
--- a/libcore/SWFStream.cpp
+++ b/libcore/SWFStream.cpp
@@ -229,14 +229,14 @@ float SWFStream::read_ufixed()
float SWFStream::read_short_ufixed()
{
// align(); // read_u16 will align
- return static_cast<float> ( read_u16() / 256.0f );
+ return read_u16() / 256.0f;
}
// Read a short fixed value, signed.
float SWFStream::read_short_sfixed()
{
// align(); // read_s16 will align
- return static_cast<float> ( read_s16() / 256.0f );
+ return read_s16() / 256.0f;
}
/// Read a 16bit (1:sign 5:exp 10:mantissa) floating point value
@@ -312,7 +312,7 @@ double SWFStream::read_d64()
const unsigned short dataLength = 8;
double d = 0;
- BOOST_STATIC_ASSERT(sizeof(double) == dataLength);
+ BOOST_STATIC_ASSERT(sizeof(double) == dataLength) __attribute__((unused));
// Should align:
if (read(reinterpret_cast<char*>(&d), dataLength) < dataLength)
diff --git a/libcore/TextField.cpp b/libcore/TextField.cpp
index e943af3..e7ec6cc 100644
--- a/libcore/TextField.cpp
+++ b/libcore/TextField.cpp
@@ -60,6 +60,7 @@
#include "Renderer.h"
#include "Transform.h"
#include "ObjectURI.h"
+#include "Movie.h"
// Text fields have a fixed 2 pixel padding for each side (regardless of border)
#define PADDING_TWIPS 40
@@ -71,6 +72,7 @@
// Define this to get debugging info about text formatting
//#define GNASH_DEBUG_TEXT_FORMATTING 1
+
namespace gnash {
TextField::TextField(as_object* object, DisplayObject* parent,
diff --git a/libcore/TextField.h b/libcore/TextField.h
index 4c19477..78df198 100644
--- a/libcore/TextField.h
+++ b/libcore/TextField.h
@@ -25,10 +25,10 @@
#include <vector>
#include "InteractiveObject.h" // for inheritance
-#include "LineStyle.h" // for LineStyle
#include "snappingrange.h"
#include "SWFRect.h" // for inlines
#include "GnashKey.h"
+#include "RGBA.h" // for rgba
// Forward declarations
namespace gnash {
@@ -40,10 +40,20 @@ namespace gnash {
class Font;
}
+#ifdef __ANDROID__
+namespace std {
+typedef basic_string
+ <wchar_t
+ ,std::char_traits<wchar_t>
+ ,std::allocator<wchar_t> >
+wstring;
+}
+#endif
+
namespace gnash {
/// An instance of a DefineEditTextTag
-class TextField : public InteractiveObject
+class DSOTEXPORT TextField : public InteractiveObject
{
public:
diff --git a/libcore/Timers.h b/libcore/Timers.h
index 44ec571..dac3f52 100644
--- a/libcore/Timers.h
+++ b/libcore/Timers.h
@@ -22,7 +22,6 @@
#include "dsodefs.h"
#include "fn_call.h"
-#include <string>
#include <limits>
// Forward declarations
diff --git a/libcore/as_environment.h b/libcore/as_environment.h
index 9e0a290..2f6b677 100644
--- a/libcore/as_environment.h
+++ b/libcore/as_environment.h
@@ -23,6 +23,7 @@
#include <vector>
#include <algorithm>
+#include "dsodefs.h" // for DSOTEXPORT
#include "as_value.h"
#include "SafeStack.h"
@@ -53,7 +54,7 @@ public:
/// A stack of objects used for variables/members lookup
typedef std::vector<as_object*> ScopeStack;
- as_environment(VM& vm);
+ DSOTEXPORT as_environment(VM& vm);
VM& getVM() const { return _vm; }
@@ -226,7 +227,7 @@ getVM(const as_environment& env)
movie_root& getRoot(const as_environment& env);
string_table& getStringTable(const as_environment& env);
int getSWFVersion(const as_environment& env);
-Global_as& getGlobal(const as_environment &env);
+DSOTEXPORT Global_as& getGlobal(const as_environment &env);
} // namespace gnash
diff --git a/libcore/as_object.h b/libcore/as_object.h
index d962fc9..639b49b 100644
--- a/libcore/as_object.h
+++ b/libcore/as_object.h
@@ -35,6 +35,7 @@
#include "PropFlags.h"
#include "Relay.h"
#include "ObjectURI.h"
+#include "dsodefs.h" // for DSOTEXPORT
// Forward declarations
namespace gnash {
@@ -167,7 +168,7 @@ public:
/// @param global A reference to the Global object the new
/// object ultimately belongs to. The created object
/// uses the resources of the Global object.
- explicit as_object(const Global_as& global);
+ explicit DSOTEXPORT as_object(const Global_as& global);
/// The as_object dtor does nothing special.
virtual ~as_object() {}
@@ -446,7 +447,7 @@ public:
/// - (false, false) : property not found
/// - (true, false) : property protected from deletion
/// - (true, true) : property successfully deleted
- std::pair<bool, bool> delProperty(const ObjectURI& uri);
+ DSOTEXPORT std::pair<bool, bool> delProperty(const ObjectURI& uri);
/// Get this object's own named property, if existing.
//
@@ -855,7 +856,7 @@ hasOwnProperty(as_object& o, const ObjectURI& uri)
return (o.getOwnProperty(uri));
}
-as_object* getObjectWithPrototype(Global_as& gl, const ObjectURI& c);
+DSOTEXPORT as_object* getObjectWithPrototype(Global_as& gl, const ObjectURI& c);
/// Check whether the object is an instance of a known type.
//
@@ -902,13 +903,13 @@ typedef std::vector<std::pair<ObjectURI, as_value> > SortedPropertyList;
SortedPropertyList enumerateProperties(as_object& o);
/// Get the VM from an as_object.
-VM& getVM(const as_object& o);
+DSOTEXPORT VM& getVM(const as_object& o);
/// Get the movie_root from an as_object.
-movie_root& getRoot(const as_object& o);
+DSOTEXPORT movie_root& getRoot(const as_object& o);
/// Get the string_table from an as_object.
-string_table& getStringTable(const as_object& o);
+DSOTEXPORT string_table& getStringTable(const as_object& o);
/// Get the RunResources from an as_object.
const RunResources& getRunResources(const as_object& o);
@@ -917,7 +918,7 @@ const RunResources& getRunResources(const as_object& o);
int getSWFVersion(const as_object& o);
/// Get the Global object from an as_object.
-Global_as& getGlobal(const as_object& o);
+DSOTEXPORT Global_as& getGlobal(const as_object& o);
/// Return whether property matching is caseless
inline bool caseless(const as_object& o) {
diff --git a/libcore/as_value.h b/libcore/as_value.h
index a54efa1..0adc302 100644
--- a/libcore/as_value.h
+++ b/libcore/as_value.h
@@ -19,18 +19,18 @@
#ifndef GNASH_AS_VALUE_H
#define GNASH_AS_VALUE_H
-#include "dsodefs.h"
-#include "CharacterProxy.h"
-
#include <limits>
#include <string>
#include <boost/variant.hpp>
#include <iosfwd> // for inlined output operator
-#include <boost/type_traits/is_floating_point.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/cstdint.hpp>
-#include "utility.h" // UNUSED
+#include "utility.h" // for UNUSED
+#include "dsodefs.h" // for DSOTEXPORT
+#include "CharacterProxy.h"
+#include "GnashNumeric.h" // for isNaN
+
// Forward declarations
namespace gnash {
@@ -52,17 +52,6 @@ namespace gnash {
// NaN constant for use in as_value implementation
static const double NaN = std::numeric_limits<double>::quiet_NaN();
-// The following template works just like its C counterpart, with added
-// type safety (i.e., they will only compile for floating point arguments).
-template <typename T>
-inline bool
-isNaN(const T& num, typename boost::enable_if<boost::is_floating_point<T> >::
- type* dummy = 0)
-{
- UNUSED(dummy);
- return num != num;
-}
-
template <typename T>
inline bool
isInf(const T& num)
@@ -231,7 +220,7 @@ public:
/// for lower versions.
//
/// TODO: drop the default argument.
- std::string to_string(int version = 7) const;
+ DSOTEXPORT std::string to_string(int version = 7) const;
/// Get a number representation for this value
//
@@ -241,7 +230,7 @@ public:
/// Conversion to boolean.
//
/// This function performs conversion if necessary.
- bool to_bool(int version) const;
+ DSOTEXPORT bool to_bool(int version) const;
/// Return value as an object, converting primitive values as needed.
//
@@ -368,7 +357,7 @@ public:
//
/// Strict equality is defined as the two values being of the
/// same type and the same value.
- bool strictly_equals(const as_value& v) const;
+ DSOTEXPORT bool strictly_equals(const as_value& v) const;
/// Return true if this value is abstractly equal to the given one
//
@@ -482,7 +471,7 @@ private:
};
/// Stream operator.
-std::ostream& operator<<(std::ostream& os, const as_value& v);
+DSOTEXPORT std::ostream& operator<<(std::ostream& os, const as_value& v);
/// Convert numeric value to string value, following ECMA-262 specification
//
diff --git a/libcore/asobj/Array_as.cpp b/libcore/asobj/Array_as.cpp
index ffff998..80b3803 100644
--- a/libcore/asobj/Array_as.cpp
+++ b/libcore/asobj/Array_as.cpp
@@ -161,7 +161,103 @@ private:
size_t _i;
};
-
+
+namespace mergesort {
+
+// AS Array.sort() allows the user to pass a scripted comparator.
+//
+// ISO/IEC 14882:2003 states that comparators used in the standard's sorting
+// functions must meet the strict weak ordering model. If this requirement is
+// not met, bad things happen (see #39385).
+//
+// We cannot guarantee that scripted comparators meet any particular ordering
+// model. In fact, some people use Array.sort() to randomize an array. We must
+// therefore have a sort implementation which is safe to use with a
+// nonconforming comparator.
+//
+// The following is an implementation of merge sort. I chose merge sort because
+// it is reasonably fast, efficient, simple and it is used by Spidermonkey for
+// the same purpose as ours. I am using in-place merge, which of course trades
+// memory efficiency for CPU time (just like std::sort). Whether this is a good
+// tradeoff in this case, remains to be seen.
+
+/// 'Safe' version of std::inplace_merge: even with a comparator that does not
+/// adhere to the strict weak ordering model, this implementation is
+/// memory-safe and free from infinite loops.
+//
+/// Merges the two already-sorted ranges (@begin, @middle] and (@middle, @end] into the
+/// sorted range (begin, end]. @compare is used for determining order.
+template<typename IterType, typename ComparatorType>
+void
+inplaceMerge(IterType begin, IterType middle, const IterType& end, ComparatorType compare)
+{
+ typedef typename std::iterator_traits<IterType>::value_type value_type;
+
+ // Let's assume compare is std::less, for example.
+ //
+ // We walk through the first range, looking for an element which is
+ // greater or equal to the first value of the second range, the
+ // next-high value (NHV). If we find one, then we move the range of
+ // the values in the second range which are less than NHV one place to
+ // the left, and we copy NHV into the vacant space immediately to the
+ // right.
+ // +--<--+ -<-+
+ // | | <- <- (2nd it.) | |<-|<-| (3rd it.)
+ // [2, 6, 7 3, 4, 5] -> [2, 3, 7, 4, 5, 6] -> [2,3,4,5,6,7]
+ // | | | | | | |
+ // | middle | middle | middle
+ // +---->------+ +--->----+
+ while(begin != middle ) {
+ if (compare(*middle, *begin)) {
+ value_type next_high = *begin;
+ *begin = *middle;
+
+ // Find the first element that is not less than next_high. Then, shift all
+ // elements before that element one position to the left, and copy
+ // next_high into the vacant spot.
+ IterType it = std::find_if(middle, end, !boost::bind<bool>(compare, _1, next_high));
+ std::copy(boost::next(middle), it, middle);
+ *(--it) = next_high;
+ }
+ ++begin;
+ }
+}
+
+/// Merge-sort the range delineated by (@begin, end] using comparator @compare.
+template<typename IterType, typename ComparatorType>
+void mergeSort(IterType begin, IterType end, ComparatorType compare)
+{
+ typedef typename std::iterator_traits<IterType>::difference_type diff_type;
+
+ diff_type distance = std::distance(begin, end);
+ if(distance < 2) {
+ return;
+ }
+
+ IterType middle = begin;
+ std::advance(middle, distance / 2);
+
+ mergeSort(begin, middle, compare);
+ mergeSort(middle, end, compare);
+ inplaceMerge(begin, middle, end, compare);
+}
+
+
+} // namespace mergesort
+
+template <typename IterType, typename ComparatorType>
+void
+SafeSort(IterType begin, IterType end, ComparatorType compare)
+{
+ std::sort(begin, end, compare);
+}
+
+class as_value_custom;
+
+template <typename IterType>
+void
+SafeSort(IterType begin, IterType end, const as_value_custom& compare);
+
/// \brief
/// Attempt to sort the array using given values comparator, avc.
/// If two or more elements in the array are equal, as determined
@@ -270,7 +366,7 @@ as_value sortIndexed(as_object& array, AVCMP avc, AVEQ ave)
getIndexedElements(array, v);
- std::sort(v.begin(), v.end(), avc);
+ SafeSort(v.begin(), v.end(), avc);
if (std::adjacent_find(v.begin(), v.end(), ave) != v.end()) {
return as_value(0.0);
@@ -294,7 +390,7 @@ sortIndexed(as_object& array, AVCMP avc)
{
std::vector<indexed_as_value> v;
getIndexedElements(array, v);
- std::sort(v.begin(), v.end(), avc);
+ SafeSort(v.begin(), v.end(), avc);
as_object* o = getGlobal(array).createArray();
pushIndices(*o, v);
return o;
@@ -737,6 +833,12 @@ flag_preprocess(boost::uint8_t flgs, bool* douniq, bool* doindex)
return flgs;
}
+template <typename IterType>
+void
+SafeSort(IterType begin, IterType end, const as_value_custom& compare)
+{
+ mergesort::mergeSort(begin, end, compare);
+}
class GetKeys
{
diff --git a/libcore/asobj/AsBroadcaster.cpp b/libcore/asobj/AsBroadcaster.cpp
index ef0ca3e..198f325 100644
--- a/libcore/asobj/AsBroadcaster.cpp
+++ b/libcore/asobj/AsBroadcaster.cpp
@@ -127,7 +127,7 @@ private:
/// Name of the event being broadcasted
/// appropriately cased based on SWF version
/// of the current VM
- const ObjectURI& _eventURI;
+ const ObjectURI _eventURI;
/// Number of event dispatches
size_t _dispatched;
diff --git a/libcore/asobj/Global_as.h b/libcore/asobj/Global_as.h
index b5c1cba..e8cae06 100644
--- a/libcore/asobj/Global_as.h
+++ b/libcore/asobj/Global_as.h
@@ -33,6 +33,7 @@
#include "fn_call.h"
#include "log.h"
#include "ClassHierarchy.h"
+#include "dsodefs.h" // for DSOTEXPORT
// Forward declarations
namespace gnash {
@@ -96,7 +97,7 @@ private:
};
-as_object* createObject(const Global_as& gl);
+DSOTEXPORT as_object* createObject(const Global_as& gl);
/// Register a built-in object
diff --git a/libcore/asobj/MovieClipLoader.h b/libcore/asobj/MovieClipLoader.h
index 15209ee..fcfa04b 100644
--- a/libcore/asobj/MovieClipLoader.h
+++ b/libcore/asobj/MovieClipLoader.h
@@ -24,7 +24,7 @@
namespace gnash {
class as_object;
-class ObjectURI;
+struct ObjectURI;
/// Initialize the global MovieClipLoader class
void moviecliploader_class_init(as_object& global, const ObjectURI& uri);
diff --git a/libcore/asobj/NetStream_as.cpp b/libcore/asobj/NetStream_as.cpp
index 40cb6a8..386a227 100644
--- a/libcore/asobj/NetStream_as.cpp
+++ b/libcore/asobj/NetStream_as.cpp
@@ -18,6 +18,10 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
#include "NetStream_as.h"
#include <functional>
@@ -44,6 +48,8 @@
#include "AMFConverter.h"
#include "AMF.h"
#include "SoundUtils.h"
+#include "VideoDecoder.h"
+#include "AudioDecoder.h"
// Define the following macro to have status notification handling debugged
//#define GNASH_DEBUG_STATUS
@@ -72,8 +78,16 @@ namespace {
as_value netstream_receiveAudio(const fn_call& fn);
as_value netstream_receiveVideo(const fn_call& fn);
as_value netstream_send(const fn_call& fn);
+ as_value netstream_time(const fn_call& fn);
+ as_value netstream_bytesloaded(const fn_call& fn);
+ as_value netstream_bytestotal(const fn_call& fn);
+ as_value netstream_currentFPS(const fn_call& fn);
+ as_value netstream_bufferLength(const fn_call& fn);
+ as_value netstream_bufferTime(const fn_call& fn);
+ as_value netstream_liveDelay(const fn_call& fn);
void attachNetStreamInterface(as_object& o);
+ void attachPrototypeProperties(as_object& proto);
// TODO: see where this can be done more centrally.
void executeTag(const SimpleBuffer& _buffer, as_object& thisPtr);
@@ -118,7 +132,7 @@ netstream_class_init(as_object& where, const ObjectURI& uri)
// NetStream is genuinely a built-in class, but its constructor calls
// several native functions. It also calls NetConnection.call.
registerBuiltinClass(where, netstream_new, attachNetStreamInterface,
- 0, uri);
+ NULL, uri);
}
void
@@ -181,8 +195,10 @@ NetStream_as::setBufferTime(boost::uint32_t time)
long
NetStream_as::bufferLength()
{
+#ifdef USE_MEDIA
if (_parser.get() == NULL) return 0;
return _parser->getBufferLength();
+#endif // USE_MEDIA
}
std::auto_ptr<image::GnashImage>
@@ -535,10 +551,11 @@ NetStream_as::startPlayback()
std::auto_ptr<image::GnashImage>
NetStream_as::getDecodedVideoFrame(boost::uint32_t ts)
{
- assert(_videoDecoder.get());
-
+ assert(_videoDecoder.get());
+
std::auto_ptr<image::GnashImage> video;
+#ifdef USE_MEDIA
assert(_parser.get());
if (!_parser.get()) {
log_error(_("getDecodedVideoFrame: no parser available"));
@@ -548,7 +565,7 @@ NetStream_as::getDecodedVideoFrame(boost::uint32_t ts)
boost::uint64_t nextTimestamp;
bool parsingComplete = _parser->parsingCompleted();
if (!_parser->nextVideoFrameTimestamp(nextTimestamp)) {
-
+
#ifdef GNASH_DEBUG_DECODING
log_debug(_("getDecodedVideoFrame(%d): "
"no more video frames in input "
@@ -609,7 +626,8 @@ NetStream_as::getDecodedVideoFrame(boost::uint32_t ts)
break;
}
}
-
+#endif // USE_MEDIA
+
return video;
}
@@ -618,6 +636,7 @@ NetStream_as::decodeNextVideoFrame()
{
std::auto_ptr<image::GnashImage> video;
+#ifdef USE_MEDIA
if (!_parser.get()) {
log_error(_("decodeNextVideoFrame: no parser available"));
return video;
@@ -644,7 +663,8 @@ NetStream_as::decodeNextVideoFrame()
// TODO: tell more about the failure
log_error(_("Error decoding encoded video frame in NetStream input"));
}
-
+#endif // USE_MEDIA
+
return video;
}
@@ -653,6 +673,11 @@ NetStream_as::decodeNextAudioFrame()
{
assert (_parser.get());
+ // TODO: make the buffer cursored later ?
+ BufferedAudioStreamer::CursoredBuffer* raw =
+ new BufferedAudioStreamer::CursoredBuffer();
+
+#ifdef USE_MEDIA
std::auto_ptr<media::EncodedAudioFrame> frame = _parser->nextAudioFrame();
if (!frame.get()) {
#ifdef GNASH_DEBUG_DECODING
@@ -663,9 +688,6 @@ NetStream_as::decodeNextAudioFrame()
return 0;
}
- // TODO: make the buffer cursored later ?
- BufferedAudioStreamer::CursoredBuffer* raw =
- new BufferedAudioStreamer::CursoredBuffer();
raw->m_data = _audioDecoder->decode(*frame, raw->m_size);
// TODO: let the sound_handler do this .. sounds cleaner
@@ -693,7 +715,8 @@ NetStream_as::decodeNextAudioFrame()
#endif
raw->m_ptr = raw->m_data;
-
+#endif // USE_MEDIA
+
return raw;
}
@@ -764,6 +787,8 @@ NetStream_as::refreshAudioBuffer()
{
assert (_parser.get());
+#ifdef USE_MEDIA
+
#ifdef GNASH_DEBUG_DECODING
// bufferLength() would lock the mutex (which we already hold),
// so this is to avoid that.
@@ -804,13 +829,15 @@ NetStream_as::refreshAudioBuffer()
// timestamp >= curPos and push them into the buffer to be
// consumed by audio_streamer
pushDecodedAudioFrames(curPos);
+#endif // USE_MEDIA
}
void
NetStream_as::pushDecodedAudioFrames(boost::uint32_t ts)
{
assert(_parser.get());
-
+
+#ifdef USE_MEDIA
if (!_audioDecoder.get()) {
// There are 3 possible reasons for _audioDecoder to not be here:
@@ -1028,10 +1055,9 @@ NetStream_as::pushDecodedAudioFrames(boost::uint32_t ts)
_playHead.setAudioConsumed();
}
-
+#endif // USE_MEDIA
}
-
void
NetStream_as::refreshVideoFrame(bool alsoIfPaused)
{
@@ -1125,7 +1151,7 @@ NetStream_as::refreshVideoFrame(bool alsoIfPaused)
#ifdef GNASH_DEBUG_DECODING
log_debug(_("%p.refreshVideoFrame(): "
"no more video frames to decode "
- "(DEC_STOPPED, null from getDecodedVideoFrame)"),
+ "(DEC_STOPPED, null from getDeodedVideoFrame)"),
this);
#endif
}
@@ -1178,6 +1204,8 @@ NetStream_as::videoWidth() const
void
NetStream_as::update()
{
+
+#ifdef USE_MEDIA
// Check if there are any new status messages, and if we should
// pass them to a event handler
processStatusNotifications();
@@ -1341,6 +1369,7 @@ NetStream_as::update()
e = tags.end(); i != e; ++i) {
executeTag(**i, owner());
}
+#endif // USE_MEDIA
}
boost::int32_t
@@ -1560,6 +1589,14 @@ netstream_new(const fn_call& fn)
NetConnection_as* nc;
if (isNativeType(toObject(fn.arg(0), getVM(fn)), nc)) {
ns->setNetCon(nc);
+ if ( nc->isConnected() ) {
+ // TODO: initialize only once ?
+ // Test it (but keep re-entrancy, in case)
+ as_object* proto = obj->get_prototype();
+ if ( proto ) {
+ attachPrototypeProperties(*proto);
+ }
+ }
}
else {
IF_VERBOSE_ASCODING_ERRORS(
@@ -1572,7 +1609,6 @@ netstream_new(const fn_call& fn)
}
obj->setRelay(ns);
-
return as_value();
}
@@ -1830,9 +1866,14 @@ attachNetStreamInterface(as_object& o)
o.init_member("receiveAudio", gl.createFunction(netstream_receiveAudio));
o.init_member("receiveVideo", gl.createFunction(netstream_receiveVideo));
o.init_member("send", vm.getNative(2101, 3));
+}
- // Properties
- // TODO: attach to each instance rather then to the class ? check it ..
+// Function to attach the properties of prototype
+// Attaching to all instances rather than to a class
+//
+void
+attachPrototypeProperties(as_object& o)
+{
o.init_readonly_property("time", &netstream_time);
o.init_readonly_property("bytesLoaded", &netstream_bytesloaded);
diff --git a/libcore/asobj/NetStream_as.h b/libcore/asobj/NetStream_as.h
index 77c636e..d55c611 100644
--- a/libcore/asobj/NetStream_as.h
+++ b/libcore/asobj/NetStream_as.h
@@ -29,24 +29,32 @@
#include <string>
#include <boost/ptr_container/ptr_deque.hpp>
#include <boost/scoped_ptr.hpp>
+#include <boost/thread/mutex.hpp>
-#include "MediaParser.h"
#include "PlayHead.h" // for composition
-#include "VideoDecoder.h" // for visibility of dtor
-#include "AudioDecoder.h" // for visibility of dtor
-#include "VirtualClock.h"
#include "Relay.h" // for ActiveRelay inheritance
+#include <memory>
// Forward declarations
namespace gnash {
+ class InterruptableVirtualClock;
+ class as_object;
class CharacterProxy;
class IOChannel;
class NetConnection_as;
class as_function;
class DisplayObject;
struct ObjectURI;
+ namespace image {
+ class GnashImage;
+ }
namespace media {
class MediaHandler;
+ class AudioDecoder;
+ class AudioInfo;
+ class MediaParser;
+ class VideoDecoder;
+ class VideoInfo;
}
namespace sound {
class sound_handler;
@@ -235,7 +243,7 @@ public:
///
boost::int32_t time();
- /// Called at the SWF heart-beat. Used to process queued status messages
+ /// Called at the heart-beat frequency. Used to process queued status messages
/// and (re)start after a buffering pause. In NetStreamFfmpeg it is also
/// used to find the next video frame to be shown, though this might
/// change.
diff --git a/libcore/asobj/Sound_as.cpp b/libcore/asobj/Sound_as.cpp
index 66e1fc5..1a05109 100644
--- a/libcore/asobj/Sound_as.cpp
+++ b/libcore/asobj/Sound_as.cpp
@@ -17,6 +17,10 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
#include "Sound_as.h"
#include <string>
@@ -29,6 +33,7 @@
#include "RunResources.h"
#include "log.h"
#include "sound_handler.h"
+#include "MediaParser.h"
#include "AudioDecoder.h"
#include "MediaHandler.h"
#include "sound_definition.h"
@@ -349,6 +354,7 @@ Sound_as::update()
void
Sound_as::probeAudio()
{
+#ifdef USE_SOUND
if ( ! externalSound ) {
// Only probe for sound complete
assert(_soundHandler);
@@ -380,7 +386,12 @@ Sound_as::probeAudio()
// TODO: check if this should be called anyway.
if (success) handleId3Data(_mediaParser->getId3Info(), owner());
}
- return;
+
+ // If this is an event sound, we are done. Otherwise, if there is
+ // any data available, we should start playback.
+ if (!isStreaming || _mediaParser->isBufferEmpty()) {
+ return;
+ }
}
if (isAttached()) {
@@ -436,6 +447,7 @@ Sound_as::probeAudio()
assert(_audioDecoder.get());
}
}
+#endif // USE_SOUND
}
void
@@ -597,7 +609,13 @@ Sound_as::loadSound(const std::string& file, bool streaming)
}
// TODO: use global _soundbuftime
- _mediaParser->setBufferTime(60000); // one minute buffer... should be fine
+ if (isStreaming) {
+ _mediaParser->setBufferTime(60000); // one minute buffer... should be fine
+ } else {
+ // If this is an event sound, we must not limit buffering (parsing),
+ // because onLoad will not be called until we have finished doing so.
+ _mediaParser->setBufferTime(std::numeric_limits<boost::uint64_t>::max());
+ }
startProbeTimer();
@@ -677,6 +695,7 @@ Sound_as::start(double secOff, int loops)
return;
}
+#ifdef USE_SOUND
if (externalSound) {
if ( ! _mediaParser ) {
log_error(_("No MediaParser initialized, can't start an external sound"));
@@ -714,7 +733,7 @@ Sound_as::start(double secOff, int loops)
inPoint = (secOff*44100);
}
- log_debug("Sound.start: secOff:%d", secOff);
+ log_debug("Sound.start: secOff:%d loops:%d", secOff, loops);
_soundHandler->startSound(
soundId,
@@ -726,6 +745,7 @@ Sound_as::start(double secOff, int loops)
startProbeTimer(); // to dispatch onSoundComplete
}
+#endif // USE_SOUND
}
void
@@ -736,6 +756,7 @@ Sound_as::stop(int si)
return;
}
+#ifdef USE_SOUND
// stop the sound
if (si < 0) {
if (externalSound) {
@@ -754,6 +775,7 @@ Sound_as::stop(int si)
} else {
_soundHandler->stopEventSound(si);
}
+#endif // USE_SOUND
}
size_t
@@ -789,7 +811,7 @@ Sound_as::getPosition() const
"likely not playing anyway)..."));
return 0;
}
-
+#ifdef USE_SOUND
// If this is a event sound get the info from the soundhandler
if (!externalSound) {
return _soundHandler->tell(soundId);
@@ -801,9 +823,9 @@ Sound_as::getPosition() const
return ts;
}
}
-
+#endif // USE_SOUND
+
return 0;
-
}
@@ -813,6 +835,7 @@ Sound_as::getAudio(boost::int16_t* samples, unsigned int nSamples, bool& atEOF)
boost::uint8_t* stream = reinterpret_cast<boost::uint8_t*>(samples);
int len = nSamples*2;
+#ifdef USE_SOUND
//GNASH_REPORT_FUNCTION;
while (len) {
@@ -884,6 +907,7 @@ Sound_as::getAudio(boost::int16_t* samples, unsigned int nSamples, bool& atEOF)
atEOF=false;
return nSamples-(len/2);
+#endif // USE_SOUND
}
// audio callback is running in sound handler thread
@@ -994,11 +1018,8 @@ sound_start(const fn_call& fn)
secondOffset = toNumber(fn.arg(0), getVM(fn));
if (fn.nargs > 1) {
- loop = (int) toNumber(fn.arg(1), getVM(fn)) - 1;
-
- // -1 means infinite playing of sound
- // sanity check
- loop = loop < 0 ? -1 : loop;
+ // Negative values count as playing once (aka looping 0 times)
+ loop = std::max(0, toInt(fn.arg(1), getVM(fn)) - 1);
}
}
so->start(secondOffset, loop);
diff --git a/libcore/asobj/String_as.cpp b/libcore/asobj/String_as.cpp
index 9f668f3..5a5231c 100644
--- a/libcore/asobj/String_as.cpp
+++ b/libcore/asobj/String_as.cpp
@@ -579,7 +579,7 @@ string_charCodeAt(const fn_call& fn)
}
)
- size_t index = static_cast<size_t>(toNumber(fn.arg(0), getVM(fn)));
+ size_t index = static_cast<size_t>(toInt(fn.arg(0), getVM(fn)));
if (index >= wstr.length()) {
as_value rv;
@@ -634,7 +634,7 @@ string_toUpperCase(const fn_call& fn)
std::wstring wstr = utf8::decodeCanonicalString(str, version);
-#if !defined(__HAIKU__) && !defined(__amigaos4__)
+#if !defined(__HAIKU__) && !defined(__amigaos4__) && !defined(__ANDROID__)
static const std::locale swfLocale((std::locale()), new SWFCtype());
boost::to_upper(wstr, swfLocale);
#else
@@ -660,7 +660,7 @@ string_toLowerCase(const fn_call& fn)
std::wstring wstr = utf8::decodeCanonicalString(str, version);
-#if !defined(__HAIKU__) && !defined(__amigaos4__)
+#if !defined(__HAIKU__) && !defined(__amigaos4__) && !defined(__ANDROID__)
static const std::locale swfLocale((std::locale()), new SWFCtype());
boost::to_lower(wstr, swfLocale);
#else
diff --git a/libcore/asobj/System_as.h b/libcore/asobj/System_as.h
index cec278b..2e4d0bf 100644
--- a/libcore/asobj/System_as.h
+++ b/libcore/asobj/System_as.h
@@ -20,10 +20,6 @@
#ifndef GNASH_ASOBJ3_SYSTEM_H
#define GNASH_ASOBJ3_SYSTEM_H
-#include <string>
-#include <vector>
-
-
namespace gnash {
// Forward declarations
diff --git a/libcore/asobj/TextFormat_as.cpp b/libcore/asobj/TextFormat_as.cpp
index d00a1e7..7d1e60c 100644
--- a/libcore/asobj/TextFormat_as.cpp
+++ b/libcore/asobj/TextFormat_as.cpp
@@ -34,7 +34,9 @@
#include "Array_as.h"
#include "fontlib.h"
#include "Font.h"
-
+#include "movie_definition.h"
+#include "movie_root.h"
+#include "Movie.h"
namespace gnash {
@@ -540,7 +542,6 @@ textformat_align(const fn_call& fn)
return ret;
}
-
/// Return various dimensions of a theoretical run of text
//
/// The TextFormat's format values are used to calculate what the dimensions
@@ -568,26 +569,44 @@ textformat_getTextExtent(const fn_call& fn)
const int version = getSWFVersion(fn);
const std::string& s = fn.arg(0).to_string(version);
- const bool limitWidth = (fn.nargs > 1);
+ bool limitWidth = (fn.nargs > 1);
// Everything must be in twips here.
- const double tfw = limitWidth ?
- pixelsToTwips(toNumber(fn.arg(1), getVM(fn))) : 0;
+ const int tfw = limitWidth ?
+ pixelsToTwips(toNumber(fn.arg(1), getVM(fn)) - 4) : 0;
const bool bold = relay->bold() ? *relay->bold() : false;
const bool italic = relay->italic() ? *relay->italic() : false;
- const double size = relay->size() ? *relay->size() : 240;
+ const int size = relay->size() ? *relay->size() : 240;
// Note: currently leading is never defined for device fonts, and since
// getTextExtent currently only takes account of device fonts we don't
// need it.
- Font* f = relay->font() ?
- fontlib::get_font(*relay->font(), bold, italic) :
- fontlib::get_default_font().get();
-
+ Font* f = 0;
+ if (relay->font()) {
+ const std::string& name = *relay->font();
+ const movie_definition* md = getRoot(fn).getRootMovie().definition();
+
+ // Option 1. Name refers to an imported font ('asset') symbol.
+ boost::uint16_t fontId = md->exportID(name);
+ if (fontId != 0) {
+ f = md->get_font(fontId);
+ }
+
+ if (!f) {
+ // Option 2. Name refers to an embedded font.
+ f = md->get_font(name, bold, italic);
+ if (!f) {
+ // Option 3. Name refers to a device font.
+ f = fontlib::get_font(name, bold, italic);
+ }
+ }
+ } else {
+ f = fontlib::get_default_font().get();
+ }
// Whether to use embedded fonts if required.
- const bool em = false;
+ const bool em = true;
/// Advance, descent, ascent given according to square of 1024.
//
@@ -595,42 +614,72 @@ textformat_getTextExtent(const fn_call& fn)
/// 240 twips for a size 12.
const double scale = size / static_cast<double>(f->unitsPerEM(em));
- // If the text is empty, size is 0. Otherwise we start with the font
- // size.
- double height = s.empty() ? 0 : size;
- double width = 0;
- double curr = 0;
+ int width = 0;
+ int curr = 0;
+
+ const int ascent = f->ascent(em) * scale;
+ const int descent = f->descent(em) * scale;
- const double ascent = f->ascent(em) * scale;
- const double descent = f->descent(em) * scale;
+ // If the text is empty, height is 0. Otherwise we start with the font
+ // size.
+ int height = s.empty() ? 0 : ascent + descent;
+
+ bool limitWidthSet = true;
+ if (version < 8 && limitWidth) {
+ limitWidth = false;
+ limitWidthSet = false;
+ }
for (std::string::const_iterator it = s.begin(), e = s.end();
it != e; ++it) {
const int index = f->get_glyph_index(*it, em);
- const double advance = f->get_advance(index, em) * scale;
- if (limitWidth && (curr + advance > tfw)) {
- curr = 0;
- height += size;
+ int advance = f->get_advance(index, em) * scale;
+ // Snap advance to the nearest pixel boundary.
+ advance = (advance + 19) / 20 * 20;
+
+ if (limitWidth && it != s.begin() ) {
+ bool wrap = version < 8 ? (curr + advance > tfw) : (curr + advance >= tfw);
+ if (wrap) {
+ curr = 0;
+ height += ascent + descent;
+ }
}
curr += advance;
width = std::max(width, curr);
+ if (!limitWidthSet) {
+ // For v7, wrapping is enabled only if the limit param is greater
+ // than or equal to the width of the first two letters (plus the
+ // 4-pixel padding, which has been subtracted from tfw).
+ if (std::distance(s.begin(), it) == 1) {
+ limitWidth = (tfw >= width);
+ limitWidthSet = true;
+ }
+ }
}
Global_as& gl = getGlobal(fn);
as_object* obj = new as_object(gl);
- obj->init_member("textFieldHeight", twipsToPixels(height) + 4);
obj->init_member("textFieldWidth",
- limitWidth ? twipsToPixels(tfw) : twipsToPixels(width) + 4);
+ (fn.nargs > 1) ? twipsToPixels(tfw) + 4 : twipsToPixels(width) + 4);
obj->init_member("width", twipsToPixels(width));
- obj->init_member("height", twipsToPixels(height));
- obj->init_member("ascent", twipsToPixels(ascent));
- obj->init_member("descent", twipsToPixels(descent));
- return as_value(obj);
+ double ascentPixels = twipsToPixels(ascent);
+ double descentPixels = twipsToPixels(descent);
+ double heightPixels = twipsToPixels(height);
+ if (version < 8) {
+ ascentPixels = std::floor(ascentPixels);
+ descentPixels = std::floor(descentPixels);
+ heightPixels = std::floor(heightPixels);
+ }
+ obj->init_member("ascent", ascentPixels);
+ obj->init_member("descent", descentPixels);
+ obj->init_member("height", heightPixels);
+ obj->init_member("textFieldHeight", heightPixels + 4);
+ return as_value(obj);
}
diff --git a/libcore/asobj/TextFormat_as.h b/libcore/asobj/TextFormat_as.h
index f0f7fed..9acbd5d 100644
--- a/libcore/asobj/TextFormat_as.h
+++ b/libcore/asobj/TextFormat_as.h
@@ -186,7 +186,11 @@ private:
/// 0xFF0000 is red, 0x00FF00 is green.
boost::optional<rgba> _color;
- // The name of a font for text as a string.
+ /// a) The name of an imported font asset (not the font's name), or
+ /// b) the name of an embedded font, or
+ /// c) the name of a device font
+ ///
+ /// If no font is set, a default font will be used instead.
boost::optional<std::string> _font;
/// An integer that indicates the indentation from the left
diff --git a/libcore/asobj/TextSnapshot_as.cpp b/libcore/asobj/TextSnapshot_as.cpp
index 26cf85c..e2f83ad 100644
--- a/libcore/asobj/TextSnapshot_as.cpp
+++ b/libcore/asobj/TextSnapshot_as.cpp
@@ -79,7 +79,7 @@ public:
protected:
- virtual void setReachable() const;
+ virtual void setReachable();
private:
@@ -221,7 +221,7 @@ TextSnapshot_as::getSelected(size_t start, size_t end) const
}
void
-TextSnapshot_as::setReachable() const
+TextSnapshot_as::setReachable()
{
std::for_each(_textFields.begin(), _textFields.end(), setTextReachable);
}
diff --git a/libcore/asobj/XMLNode_as.cpp b/libcore/asobj/XMLNode_as.cpp
index 663a8a4..2aee2da 100644
--- a/libcore/asobj/XMLNode_as.cpp
+++ b/libcore/asobj/XMLNode_as.cpp
@@ -110,6 +110,12 @@ XMLNode_as::XMLNode_as(const XMLNode_as& tpl, bool deep)
XMLNode_as::~XMLNode_as()
{
+ // In practice it is quite likely that the child will be garbage-collected
+ // before the parent. See Savannah bug #39404.
+ if (_parent ) {
+ _parent->removeChild(this);
+ }
+
clearChildren();
}
@@ -378,10 +384,14 @@ XMLNode_as::extractPrefix(std::string& prefix) const
void
XMLNode_as::clearChildren()
{
- for (Children::const_iterator it = _children.begin(), e = _children.end();
+ for (Children::iterator it = _children.begin(), e = _children.end();
it != e; ++it) {
- const XMLNode_as* node = *it;
+ XMLNode_as* node = *it;
+
+ node->setParent(0);
if (!node->_object) {
+ // The node is not GC'd because it has no associated object.
+ // See XMLNode_as class docs.
delete node;
}
}
diff --git a/libcore/asobj/XML_as.cpp b/libcore/asobj/XML_as.cpp
index c20432b..a361856 100644
--- a/libcore/asobj/XML_as.cpp
+++ b/libcore/asobj/XML_as.cpp
@@ -506,7 +506,6 @@ XML_as::parseXML(const std::string& xml)
void
XML_as::clear()
{
- // TODO: should set childs's parent to NULL ?
clearChildren();
_docTypeDecl.clear();
_xmlDecl.clear();
diff --git a/libcore/asobj/flash/display/BitmapData_as.cpp b/libcore/asobj/flash/display/BitmapData_as.cpp
index cca2139..273aabc 100644
--- a/libcore/asobj/flash/display/BitmapData_as.cpp
+++ b/libcore/asobj/flash/display/BitmapData_as.cpp
@@ -1099,7 +1099,11 @@ bitmapdata_draw(const fn_call& fn)
}
}
+ SWFMatrix oldM = mc->transform().matrix;
+ mc->setMatrix(t.matrix, true);
ptr->draw(*mc, t);
+ mc->setMatrix(oldM, true);
+
return as_value();
}
diff --git a/libcore/asobj/flash/external/ExternalInterface_as.cpp b/libcore/asobj/flash/external/ExternalInterface_as.cpp
index dfb5769..86530e6 100644
--- a/libcore/asobj/flash/external/ExternalInterface_as.cpp
+++ b/libcore/asobj/flash/external/ExternalInterface_as.cpp
@@ -275,7 +275,7 @@ externalinterface_call(const fn_call& fn)
if (mr.getControlFD() <= 0) {
log_debug("ExternalInterface not accessible on call.");
val.set_null();
- return as_value(val);
+ return val;
}
if (fn.nargs > 1) {
@@ -406,7 +406,7 @@ externalinterface_uArgumentsToXML(const fn_call& fn)
ArgsToXML tx(ret, fn);
size_t size = arrayLength(*obj);
if (size) {
- for (size_t i = 1; i < static_cast<size_t>(size); ++i) {
+ for (size_t i = 1; i < size; ++i) {
tx(getOwnProperty(*obj, arrayKey(vm, i)));
}
}
diff --git a/libcore/event_id.h b/libcore/event_id.h
index 5eb6ab1..6890be5 100644
--- a/libcore/event_id.h
+++ b/libcore/event_id.h
@@ -118,7 +118,7 @@ public:
// As long as we can work out the SWFCode from the
// gnash::key::code it's all right.
int i = 0;
- while (key::codeMap[i][key::SWF] != SWFkey && i < key::KEYCOUNT) i++;
+ while (i < key::KEYCOUNT && key::codeMap[i][key::SWF] != SWFkey) i++;
if (i == key::KEYCOUNT) _keyCode = key::INVALID;
else _keyCode = static_cast<key::code>(i);
diff --git a/libcore/movie_root.cpp b/libcore/movie_root.cpp
index 6c32e9b..1bae796 100644
--- a/libcore/movie_root.cpp
+++ b/libcore/movie_root.cpp
@@ -854,8 +854,9 @@ movie_root::advance()
bool advanced = false;
+#ifdef USE_SOUND
try {
-
+
sound::sound_handler* s = _runResources.soundHandler();
if (s && _timelineSound) {
@@ -948,7 +949,8 @@ movie_root::advance()
log_error(_("Buffer overread during advance: %s"), e.what());
clear(_actionQueue);
}
-
+#endif // USE_SOUND
+
return advanced;
}
@@ -1693,7 +1695,7 @@ movie_root::executeTimers()
// Don't do anything if we have no timers, just return so we don't
// waste cpu cycles.
- if (_intervalTimers.size() == 0) {
+ if (_intervalTimers.empty()) {
return;
}
diff --git a/libcore/movie_root.h b/libcore/movie_root.h
index 3157f02..a89787b 100644
--- a/libcore/movie_root.h
+++ b/libcore/movie_root.h
@@ -81,10 +81,9 @@
#include <boost/optional.hpp>
#include "dsodefs.h" // DSOEXPORT
+#include "DragState.h"
#include "MouseButtonState.h" // for composition
-#include "DragState.h" // for composition
#include "GnashKey.h" // key::code
-#include "Movie.h"
#include "GnashEnums.h"
#include "MovieClip.h"
#include "SimpleBuffer.h" // for LoadCallback
@@ -119,6 +118,7 @@ namespace gnash {
class RunResources;
class Button;
class VM;
+ class Movie;
}
namespace gnash {
diff --git a/libcore/parser/Makefile.am b/libcore/parser/Makefile.am
index 378d331..5eaeeac 100644
--- a/libcore/parser/Makefile.am
+++ b/libcore/parser/Makefile.am
@@ -88,7 +88,10 @@ if WIN32
libgnashparser_la_LDFLAGS += -no-undefined
endif
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
+AM_LDFLAGS = $(CROSS_LDFLAGS)
+
if ENABLE_PCH
-AM_CXXFLAGS = $(PCH_FLAGS)
+AM_CXXFLAGS += $(PCH_FLAGS)
endif
diff --git a/libcore/parser/SWFMovieDefinition.h b/libcore/parser/SWFMovieDefinition.h
index 514b46e..94f85e8 100644
--- a/libcore/parser/SWFMovieDefinition.h
+++ b/libcore/parser/SWFMovieDefinition.h
@@ -27,13 +27,6 @@
#include "gnashconfig.h" // for USE_SWFTREE
#endif
-#include "movie_definition.h" // for inheritance
-#include "DefinitionTag.h" // for boost::intrusive_ptr visibility of dtor
-#include "StringPredicates.h"
-#include "SWFRect.h"
-#include "GnashNumeric.h"
-#include "GnashAlgorithm.h"
-
#include <boost/intrusive_ptr.hpp>
#include <vector>
#include <map>
@@ -45,6 +38,13 @@
#include <boost/thread/barrier.hpp>
#include <boost/scoped_ptr.hpp>
+#include "movie_definition.h" // for inheritance
+#include "DefinitionTag.h" // for boost::intrusive_ptr visibility of dtor
+#include "StringPredicates.h"
+#include "SWFRect.h"
+#include "GnashNumeric.h"
+#include "dsodefs.h" // for DSOTEXPORT
+
// Forward declarations
namespace gnash {
namespace image {
@@ -132,7 +132,7 @@ public:
//
/// replaces any existing DisplayObject with the same id
///
- void addDisplayObject(int id, boost::intrusive_ptr<SWF::DefinitionTag> c);
+ DSOTEXPORT void addDisplayObject(int id, boost::intrusive_ptr<SWF::DefinitionTag> c);
/// Return an iterator to the first dictionary element
CharacterIterator begin() { return _map.begin(); }
@@ -161,7 +161,7 @@ private:
/// It cannot be played directly, and does not hold
/// current state; for that you need to call createMovie()
/// to get a movie instance
-class SWFMovieDefinition : public movie_definition
+class DSOTEXPORT SWFMovieDefinition : public movie_definition
{
public:
@@ -171,7 +171,7 @@ public:
/// parsing.
SWFMovieDefinition(const RunResources& runResources);
- ~SWFMovieDefinition();
+ DSOTEXPORT ~SWFMovieDefinition();
/// Return total number of frames advertised for the SWFMovie.
size_t get_frame_count() const {
@@ -237,28 +237,28 @@ public:
return m_file_length;
}
- virtual void importResources(boost::intrusive_ptr<movie_definition> source,
+ DSOTEXPORT virtual void importResources(boost::intrusive_ptr<movie_definition> source,
const Imports& imports);
virtual void addDisplayObject(boost::uint16_t id, SWF::DefinitionTag* c);
/// Return a DisplayObject from the dictionary
- SWF::DefinitionTag* getDefinitionTag(boost::uint16_t id) const;
+ DSOTEXPORT SWF::DefinitionTag* getDefinitionTag(boost::uint16_t id) const;
// See dox in movie_definition
//
// locks _namedFramesMutex
- bool get_labeled_frame(const std::string& label, size_t& frame_number)
+ DSOTEXPORT bool get_labeled_frame(const std::string& label, size_t& frame_number)
const;
- void add_font(int font_id, boost::intrusive_ptr<Font> f);
+ DSOTEXPORT void add_font(int font_id, boost::intrusive_ptr<Font> f);
- Font* get_font(int font_id) const;
+ DSOTEXPORT Font* get_font(int font_id) const;
Font* get_font(const std::string& name, bool bold, bool italic) const;
// See dox in movie_definition.h
- CachedBitmap* getBitmap(int DisplayObject_id) const;
+ DSOTEXPORT CachedBitmap* getBitmap(int DisplayObject_id) const;
// See dox in movie_definition.h
void addBitmap(int DisplayObject_id, boost::intrusive_ptr<CachedBitmap> im);
@@ -290,11 +290,11 @@ public:
//
// locks _namedFramesMutex and _frames_loaded_mutex
//
- void add_frame_name(const std::string& name);
+ DSOTEXPORT void add_frame_name(const std::string& name);
/// Set an input object for later loading DefineBits
/// images (JPEG images without the table info).
- void set_jpeg_loader(std::auto_ptr<image::JpegInput> j_in);
+ DSOTEXPORT void set_jpeg_loader(std::auto_ptr<image::JpegInput> j_in);
// See dox in movie_definition.h
image::JpegInput* get_jpeg_loader() const {
@@ -507,7 +507,7 @@ private:
/// NOTE: this method locks _frames_loaded_mutex
///
/// @return the new value of _frames_loaded
- virtual void incrementLoadedFrames();
+ DSOTEXPORT virtual void incrementLoadedFrames();
/// Set number of bytes loaded from input stream
//
diff --git a/libcore/parser/action_buffer.cpp b/libcore/parser/action_buffer.cpp
index d6c64b4..23ddab2 100644
--- a/libcore/parser/action_buffer.cpp
+++ b/libcore/parser/action_buffer.cpp
@@ -574,7 +574,7 @@ convert_double_wacky(const void *p)
} c;
} u;
- BOOST_STATIC_ASSERT(sizeof(u) == sizeof(u.i));
+ BOOST_STATIC_ASSERT(sizeof(u) == sizeof(u.i)) __attribute__((unused));
// Detect endianness of doubles by storing a value that is
// exactly representable and that has different values in the
diff --git a/libcore/parser/action_buffer.h b/libcore/parser/action_buffer.h
index 883d440..4cdd729 100644
--- a/libcore/parser/action_buffer.h
+++ b/libcore/parser/action_buffer.h
@@ -94,8 +94,8 @@ public:
/// Get a pointer to the current instruction within the code
const unsigned char* getFramePointer(size_t pc) const
{
- assert (pc < m_buffer.size());
- return reinterpret_cast<const unsigned char*>(&m_buffer.at(pc));
+ assert (pc < m_buffer.size());
+ return &m_buffer.at(pc);
}
/// Get a signed integer value from given offset
diff --git a/libcore/swf/DefineBitsTag.cpp b/libcore/swf/DefineBitsTag.cpp
index 0b5e417..b7cff44 100644
--- a/libcore/swf/DefineBitsTag.cpp
+++ b/libcore/swf/DefineBitsTag.cpp
@@ -622,7 +622,8 @@ inflateWrapper(SWFStream& in, void* buffer, size_t buffer_bytes)
chunkSize = availableBytes;
}
- BOOST_STATIC_ASSERT(sizeof(char) == sizeof(boost::uint8_t));
+ BOOST_STATIC_ASSERT(sizeof(char) == sizeof(boost::uint8_t))
+ __attribute__((unused));
// Fill the buffer
in.read(reinterpret_cast<char*>(buf), chunkSize);
diff --git a/libcore/swf/DefineFontAlignZonesTag.cpp b/libcore/swf/DefineFontAlignZonesTag.cpp
index 8346c04..5c27fbd 100644
--- a/libcore/swf/DefineFontAlignZonesTag.cpp
+++ b/libcore/swf/DefineFontAlignZonesTag.cpp
@@ -33,8 +33,6 @@ namespace SWF {
DefineFontAlignZonesTag::DefineFontAlignZonesTag(movie_definition& /*m*/,
SWFStream& /*in*/)
- :
- _csm_table_int(2)
{
}
diff --git a/libcore/swf/DefineFontAlignZonesTag.h b/libcore/swf/DefineFontAlignZonesTag.h
index 4509fb0..54053eb 100644
--- a/libcore/swf/DefineFontAlignZonesTag.h
+++ b/libcore/swf/DefineFontAlignZonesTag.h
@@ -51,12 +51,7 @@ private:
/// Construct a DefineFoneAlignZonesTag
//
/// This should only be called from the loader() function.
- DefineFontAlignZonesTag(movie_definition& m, SWFStream& in);
-
- unsigned short _font2_id_ref;
-
- unsigned _csm_table_int;
-
+ DefineFontAlignZonesTag(movie_definition& m, SWFStream& in);
};
} // namespace gnash::SWF
diff --git a/libcore/swf/DefineFontTag.cpp b/libcore/swf/DefineFontTag.cpp
index 0fa31e7..4ad7954 100644
--- a/libcore/swf/DefineFontTag.cpp
+++ b/libcore/swf/DefineFontTag.cpp
@@ -285,7 +285,7 @@ DefineFontTag::readDefineFont2Or3(SWFStream& in, movie_definition& m,
in.ensureBytes(nGlyphs*2);
for (size_t i = 0; i < nGlyphs; i++) {
- // This is documented to be unsigned, but then we get negative
+ // This is documented to be signed, but then we get negative
// advances for subpixel fonts because the advance overflows
// int16_t.
_glyphTable[i].advance = static_cast<float>(in.read_u16());
diff --git a/libcore/swf/DefineMorphShapeTag.cpp b/libcore/swf/DefineMorphShapeTag.cpp
index 1315b85..4be974a 100644
--- a/libcore/swf/DefineMorphShapeTag.cpp
+++ b/libcore/swf/DefineMorphShapeTag.cpp
@@ -106,26 +106,32 @@ DefineMorphShapeTag::read(SWFStream& in, TagType tag, movie_definition& md,
}
in.ensureBytes(4);
- // Offset. What is this for?
+ // Spec: Indicates offset to the second Shape.
static_cast<void>(in.read_u32());
// Next line will throw ParserException on malformed SWF
const boost::uint16_t fillCount = in.read_variable_count();
+ SWF::Subshape subshape1;
+ SWF::Subshape subshape2;
+
for (size_t i = 0; i < fillCount; ++i) {
OptionalFillPair fp = readFills(in, tag, md, true);
- _shape1.addFillStyle(fp.first);
- _shape2.addFillStyle(*fp.second);
+ subshape1.addFillStyle(fp.first);
+ subshape2.addFillStyle(*fp.second);
}
const boost::uint16_t lineCount = in.read_variable_count();
LineStyle ls1, ls2;
for (size_t i = 0; i < lineCount; ++i) {
ls1.read_morph(in, tag, md, r, &ls2);
- _shape1.addLineStyle(ls1);
- _shape2.addLineStyle(ls2);
+ subshape1.addLineStyle(ls1);
+ subshape2.addLineStyle(ls2);
}
+ _shape1.addSubshape(subshape1);
+ _shape2.addSubshape(subshape2);
+
_shape1.read(in, tag, md, r);
in.align();
_shape2.read(in, tag, md, r);
@@ -139,9 +145,8 @@ DefineMorphShapeTag::read(SWFStream& in, TagType tag, movie_definition& md,
// Starting bounds are the same as shape1
_bounds = bounds1;
- assert(_shape1.fillStyles().size() == _shape2.fillStyles().size());
- assert(_shape1.lineStyles().size() == _shape2.lineStyles().size());
-
+ assert((_shape1.subshapes().size() == _shape2.subshapes().size()) &&
+ (_shape2.subshapes().size() == 1));
}
} // namespace SWF
diff --git a/libcore/swf/DefineShapeTag.cpp b/libcore/swf/DefineShapeTag.cpp
index 49ab8b5..faa279a 100644
--- a/libcore/swf/DefineShapeTag.cpp
+++ b/libcore/swf/DefineShapeTag.cpp
@@ -73,7 +73,7 @@ bool
DefineShapeTag::pointTestLocal(boost::int32_t x, boost::int32_t y,
const SWFMatrix& wm) const
{
- return geometry::pointTest(_shape.paths(), _shape.lineStyles(), x, y, wm);
+ return _shape.pointTest(x, y, wm);
}
diff --git a/libcore/swf/DefinitionTag.h b/libcore/swf/DefinitionTag.h
index b3825b0..7d3db70 100644
--- a/libcore/swf/DefinitionTag.h
+++ b/libcore/swf/DefinitionTag.h
@@ -24,6 +24,7 @@
#include <boost/cstdint.hpp>
#include "ControlTag.h"
+#include "dsodefs.h" // for DSOTEXPORT
// Forward declarations
@@ -68,7 +69,7 @@ public:
//
/// The process is different for imported DefinitionTags, which are added
/// with a new id.
- virtual void executeState(MovieClip* m, DisplayList& /*dlist*/) const;
+ DSOTEXPORT virtual void executeState(MovieClip* m, DisplayList& /*dlist*/) const;
/// The immutable id of the DefinitionTag.
//
diff --git a/libcore/swf/PlaceObject2Tag.cpp b/libcore/swf/PlaceObject2Tag.cpp
index 46cfbc5..cb63557 100644
--- a/libcore/swf/PlaceObject2Tag.cpp
+++ b/libcore/swf/PlaceObject2Tag.cpp
@@ -163,6 +163,14 @@ PlaceObject2Tag::readPlaceActions(SWFStream& in)
);
break;
}
+
+ if ( event_length == 0 ) {
+ IF_VERBOSE_MALFORMED_SWF(
+ log_swferror(_("swf_event::read(), "
+ "event_length = 0 (empty). Skipping."));
+ );
+ continue;
+ }
key::code ch = key::INVALID;
diff --git a/libcore/swf/ShapeRecord.cpp b/libcore/swf/ShapeRecord.cpp
index 5b74e85..23d8b0a 100644
--- a/libcore/swf/ShapeRecord.cpp
+++ b/libcore/swf/ShapeRecord.cpp
@@ -40,8 +40,6 @@ namespace {
SWF::TagType tag, movie_definition& md, const RunResources& /*r*/);
void readLineStyles(ShapeRecord::LineStyles& styles, SWFStream& in,
SWF::TagType tag, movie_definition& md, const RunResources& /*r*/);
- void computeBounds(SWFRect& bounds, const ShapeRecord::Paths& paths,
- const ShapeRecord::LineStyles& lineStyles, int swfVersion);
}
// Functors for path and style manipulation.
@@ -138,7 +136,6 @@ private:
} // anonymous namespace
-
ShapeRecord::ShapeRecord(SWFStream& in, SWF::TagType tag, movie_definition& m,
const RunResources& r)
{
@@ -153,60 +150,73 @@ ShapeRecord::~ShapeRecord()
{
}
-ShapeRecord::ShapeRecord(const ShapeRecord& other)
- :
- _fillStyles(other._fillStyles),
- _lineStyles(other._lineStyles),
- _paths(other._paths),
- _bounds(other._bounds)
-{
-}
-
-ShapeRecord&
-ShapeRecord::operator=(const ShapeRecord& other)
-{
- _fillStyles = other._fillStyles;
- _lineStyles = other._lineStyles;
- _paths = other._paths;
- _bounds = other._bounds;
- return *this;
-}
-
void
ShapeRecord::clear()
{
- _fillStyles.clear();
- _lineStyles.clear();
- _paths.clear();
_bounds.set_null();
+ _subshapes.clear();
}
void
-ShapeRecord::addFillStyle(const FillStyle& fs)
+Subshape::addFillStyle(const FillStyle& fs)
{
_fillStyles.push_back(fs);
}
+
+/// Find the bounds of this subhape, and return them in a rectangle.
+SWFRect
+Subshape::computeBounds(int swfVersion) const
+{
+ SWFRect bounds;
+
+ for (unsigned int i = 0; i < _paths.size(); i++) {
+ const Path& p = _paths[i];
+
+ unsigned thickness = 0;
+ if ( p.m_line ) {
+ // For glyph shapes m_line is allowed to be 1
+ // while no defined line styles are allowed.
+ if (lineStyles().empty()) {
+ // This is either a Glyph, for which m_line==1 is valid
+ // or a bug in the parser, which we have no way to
+ // check at this time
+ assert(p.m_line == 1);
+ }
+ else
+ {
+ thickness = lineStyles()[p.m_line-1].getThickness();
+ }
+ }
+ p.expandBounds(bounds, thickness, swfVersion);
+ }
+
+ return bounds;
+}
+
void
-ShapeRecord::setLerp(const ShapeRecord& a, const ShapeRecord& b,
+ShapeRecord::setLerp(const ShapeRecord& aa, const ShapeRecord& bb,
const double ratio)
{
+ assert(_subshapes.size() == 1);
// Update current bounds.
- _bounds.set_lerp(a.getBounds(), b.getBounds(), ratio);
+ _bounds.set_lerp(aa.getBounds(), bb.getBounds(), ratio);
+ const Subshape& a = aa.subshapes().front();
+ const Subshape& b = bb.subshapes().front();
// fill styles
const FillStyles::const_iterator fs1 = a.fillStyles().begin();
const FillStyles::const_iterator fs2 = b.fillStyles().begin();
- std::for_each(_fillStyles.begin(), _fillStyles.end(),
+ std::for_each(_subshapes.front().fillStyles().begin(), _subshapes.front().fillStyles().end(),
Lerp<FillStyles>(fs1, fs2, ratio));
// line styles
const LineStyles::const_iterator ls1 = a.lineStyles().begin();
const LineStyles::const_iterator ls2 = b.lineStyles().begin();
- std::for_each(_lineStyles.begin(), _lineStyles.end(),
+ std::for_each(_subshapes.front().lineStyles().begin(), _subshapes.front().lineStyles().end(),
Lerp<LineStyles>(ls1, ls2, ratio));
// This is used for cases in which number
@@ -218,8 +228,8 @@ ShapeRecord::setLerp(const ShapeRecord& a, const ShapeRecord& b,
// shape
const Paths& paths1 = a.paths();
const Paths& paths2 = b.paths();
- for (size_t i = 0, k = 0, n = 0; i < _paths.size(); i++) {
- Path& p = _paths[i];
+ for (size_t i = 0, k = 0, n = 0; i < _subshapes.front().paths().size(); i++) {
+ Path& p = _subshapes.front().paths()[i];
const Path& p1 = i < paths1.size() ? paths1[i] : empty_path;
const Path& p2 = n < paths2.size() ? paths2[n] : empty_path;
@@ -251,7 +261,28 @@ ShapeRecord::setLerp(const ShapeRecord& a, const ShapeRecord& b,
}
}
}
+}
+
+unsigned
+ShapeRecord::readStyleChange(SWFStream& in, size_t num_style_bits, size_t numStyles)
+{
+ if (!num_style_bits) {
+ return 0;
+ }
+ in.ensureBits(num_style_bits);
+ unsigned style = in.read_uint(num_style_bits);
+
+ if ( style > numStyles ) {
+ IF_VERBOSE_MALFORMED_SWF(
+ log_swferror(_("Invalid fill style %1% in "
+ "style change record - %2% defined. "
+ "Set to 0."), style, numStyles);
+ );
+ style = 0;
+ }
+
+ return style;
}
void
@@ -266,6 +297,14 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
tag == SWF::DEFINESHAPE4 ||
tag == SWF::DEFINESHAPE4_);
+ Subshape subshape;
+ if (!_subshapes.empty()) {
+ // This is a little naughty. In case we're reading DEFINEMORPH, we'll
+ // have been provided with styles, which are now copied....
+ subshape = _subshapes.front();
+ _subshapes.clear();
+ }
+
if (styleInfo) {
_bounds = readRect(in);
@@ -283,8 +322,8 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
LOG_ONCE(log_unimpl("DEFINESHAPE4 edge boundaries and scales"));
}
- readFillStyles(_fillStyles, in, tag, m, r);
- readLineStyles(_lineStyles, in, tag, m, r);
+ readFillStyles(subshape.fillStyles(), in, tag, m, r);
+ readLineStyles(subshape.lineStyles(), in, tag, m, r);
}
if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2 ) {
@@ -332,8 +371,6 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
// At the moment we just store each edge with
// the full necessary info to render it, which
// is simple but not optimally efficient.
- int fill_base = 0;
- int line_base = 0;
int x = 0, y = 0;
Path current_path;
@@ -350,15 +387,17 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
if (flags == SHAPE_END) {
// Store the current path if any.
if (! current_path.empty()) {
- _paths.push_back(current_path);
+ subshape.paths().push_back(current_path);
current_path.m_edges.resize(0);
+ _subshapes.push_back(subshape);
+ subshape.clear();
}
break;
}
if (flags & SHAPE_MOVE) {
// Store the current path if any, and prepare a fresh one.
if (! current_path.empty()) {
- _paths.push_back(current_path);
+ subshape.paths().push_back(current_path);
current_path.m_edges.resize(0);
}
in.ensureBits(5);
@@ -383,38 +422,15 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
if ((flags & SHAPE_FILLSTYLE0_CHANGE) && num_fill_bits > 0) {
// FillStyle_0_change = 1;
if (! current_path.empty()) {
- _paths.push_back(current_path);
+ subshape.paths().push_back(current_path);
current_path.m_edges.resize(0);
current_path.ap.x = x;
current_path.ap.y = y;
}
- in.ensureBits(num_fill_bits);
- unsigned style = in.read_uint(num_fill_bits);
- if (style > 0) {
- style += fill_base;
- }
-
- if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2) {
- if ( style > 1 ) { // 0:hide 1:renderer
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid fill style %d in "
- "fillStyle0Change record for font tag "
- "(0 or 1 valid). Set to 0."), style);
- );
- style = 0;
- }
- } else {
- // 1-based index
- if ( style > _fillStyles.size() ) {
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid fill style %d in "
- "fillStyle0Change record - %d defined. "
- "Set to 0."), style, _fillStyles.size());
- );
- style = 0;
- }
- }
-
+
+ unsigned style = readStyleChange(in, num_fill_bits,
+ (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2) ? 1 : subshape.fillStyles().size());
+
current_path.setLeftFill(style);
#if SHAPE_LOG
IF_VERBOSE_PARSE(
@@ -426,37 +442,14 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
if ((flags & SHAPE_FILLSTYLE1_CHANGE) && num_fill_bits > 0) {
// FillStyle_1_change = 1;
if (! current_path.empty()) {
- _paths.push_back(current_path);
+ subshape.paths().push_back(current_path);
current_path.m_edges.resize(0);
current_path.ap.x = x;
current_path.ap.y = y;
}
- in.ensureBits(num_fill_bits);
- unsigned style = in.read_uint(num_fill_bits);
- if (style > 0) {
- style += fill_base;
- }
-
- if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2) {
- if ( style > 1 ) { // 0:hide 1:renderer
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid fill style %d in "
- "fillStyle1Change record for font tag "
- "(0 or 1 valid). Set to 0."), style);
- );
- style = 0;
- }
- } else {
- // 1-based index
- if ( style > _fillStyles.size() ) {
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid fill style %d in "
- "fillStyle1Change record - %d defined. "
- "Set to 0."), style, _fillStyles.size());
- );
- style = 0;
- }
- }
+ unsigned style = readStyleChange(in, num_fill_bits,
+ (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2) ? 1 : subshape.fillStyles().size());
+
current_path.setRightFill(style);
#if SHAPE_LOG
IF_VERBOSE_PARSE (
@@ -468,36 +461,14 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
if ((flags & SHAPE_LINESTYLE_CHANGE) && num_line_bits > 0) {
// line_style_change = 1;
if (! current_path.empty()) {
- _paths.push_back(current_path);
+ subshape.paths().push_back(current_path);
current_path.m_edges.resize(0);
current_path.ap.x = x;
current_path.ap.y = y;
}
- in.ensureBits(num_line_bits);
- unsigned style = in.read_uint(num_line_bits);
- if (style > 0) {
- style += line_base;
- }
- if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2) {
- if ( style > 1 ) { // 0:hide 1:renderer
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid line style %d in "
- "lineStyleChange record for font tag "
- "(0 or 1 valid). Set to 0."), style);
- );
- style = 0;
- }
- } else {
- // 1-based index
- if (style > _lineStyles.size()) {
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid fill style %d in "
- "lineStyleChange record - %d defined. "
- "Set to 0."), style, _lineStyles.size());
- );
- style = 0;
- }
- }
+ unsigned style = readStyleChange(in, num_line_bits,
+ (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2) ? 1 : subshape.lineStyles().size());
+
current_path.setLineStyle(style);
#if SHAPE_LOG
IF_VERBOSE_PARSE(
@@ -520,20 +491,15 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
// Store the current path if any.
if (! current_path.empty()) {
- _paths.push_back(current_path);
+ subshape.paths().push_back(current_path);
current_path.clear();
}
- // Tack on an empty path signalling a new shape.
- // @@ need better understanding of whether this is correct??!?!!
- // @@ i.e., we should just start a whole new shape here, right?
- _paths.push_back(Path());
- _paths.back().m_new_shape = true;
+ _subshapes.push_back(subshape);
+ subshape.clear();
- fill_base = _fillStyles.size();
- line_base = _lineStyles.size();
- readFillStyles(_fillStyles, in, tag, m, r);
- readLineStyles(_lineStyles, in, tag, m, r);
+ readFillStyles(subshape.fillStyles(), in, tag, m, r);
+ readLineStyles(subshape.lineStyles(), in, tag, m, r);
in.ensureBits(8);
num_fill_bits = in.read_uint(4);
@@ -542,10 +508,11 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
} else {
// EDGERECORD
in.ensureBits(1);
- bool edge_flag = in.read_bit();
- if (edge_flag == 0) {
+ bool straight_edge = in.read_bit();
+ int num_bits = 2 + in.read_uint(4);
+ if (!straight_edge) {
in.ensureBits(4);
- int num_bits = 2 + in.read_uint(4);
+
// curved edge
in.ensureBits(4 * num_bits);
int cx = x + in.read_sint(num_bits);
@@ -559,14 +526,13 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
"%d %d - %d %d - %d %d"), x, y, cx, cy, ax, ay);
);
#endif
- current_path.m_edges.push_back(Edge(cx, cy, ax, ay));
+ current_path.drawCurveTo(cx, cy, ax, ay);
x = ax;
y = ay;
} else {
// straight edge
in.ensureBits(5);
- int num_bits = 2 + in.read_uint(4);
- bool line_flag = in.read_bit();
+ bool line_flag = in.read_bit();
int dx = 0, dy = 0;
if (line_flag)
{
@@ -577,7 +543,7 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
} else {
in.ensureBits(1);
bool vert_flag = in.read_bit();
- if (vert_flag == 0) {
+ if (!vert_flag) {
// Horizontal line.
in.ensureBits(num_bits);
dx = in.read_sint(num_bits);
@@ -594,8 +560,8 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
"%d %d - %d %d"), x, y, x + dx, y + dy);
);
#endif
- current_path.m_edges.push_back(Edge(x + dx, y + dy,
- x + dx, y + dy));
+ current_path.drawLineTo(x + dx, y + dy);
+
x += dx;
y += dy;
}
@@ -605,7 +571,12 @@ ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
if (!styleInfo) {
// TODO: performance would be improved by computing
// the bounds as edges are parsed.
- computeBounds(_bounds, _paths, _lineStyles, m.get_version());
+ _bounds.set_null();
+ for (Subshapes::const_iterator it = _subshapes.begin(),
+ end = _subshapes.end(); it != end; ++it) {
+ SWFRect bounds = it->computeBounds(m.get_version());
+ _bounds.expand_to_rect(bounds);
+ }
}
#ifdef GNASH_DEBUG_SHAPE_BOUNDS
@@ -680,34 +651,6 @@ readLineStyles(ShapeRecord::LineStyles& styles, SWFStream& in,
}
}
-// Find the bounds of this shape, and store them in the given rectangle.
-void
-computeBounds(SWFRect& bounds, const ShapeRecord::Paths& paths,
- const ShapeRecord::LineStyles& lineStyles, int swfVersion)
-{
- bounds.set_null();
-
- for (unsigned int i = 0; i < paths.size(); i++) {
- const Path& p = paths[i];
-
- unsigned thickness = 0;
- if ( p.m_line ) {
- // For glyph shapes m_line is allowed to be 1
- // while no defined line styles are allowed.
- if (lineStyles.empty()) {
- // This is either a Glyph, for which m_line==1 is valid
- // or a bug in the parser, which we have no way to
- // check at this time
- assert(p.m_line == 1);
- }
- else
- {
- thickness = lineStyles[p.m_line-1].getThickness();
- }
- }
- p.expandBounds(bounds, thickness, swfVersion);
- }
-}
} // anonymous namespace
@@ -717,9 +660,14 @@ operator<<(std::ostream& o, const ShapeRecord& sh)
{
o << boost::format("Shape Record: bounds %1%") % sh.getBounds();
- const ShapeRecord::FillStyles& fills = sh.fillStyles();
- std::copy(fills.begin(), fills.end(),
- std::ostream_iterator<FillStyle>(o, ","));
+
+ for (ShapeRecord::Subshapes::const_iterator it = sh.subshapes().begin(),
+ end = sh.subshapes().end(); it != end; ++it) {
+
+ const ShapeRecord::FillStyles& fills = it->fillStyles();
+ std::copy(fills.begin(), fills.end(),
+ std::ostream_iterator<FillStyle>(o, ","));
+ }
return o;
}
diff --git a/libcore/swf/ShapeRecord.h b/libcore/swf/ShapeRecord.h
index b43cb58..2f73612 100644
--- a/libcore/swf/ShapeRecord.h
+++ b/libcore/swf/ShapeRecord.h
@@ -22,6 +22,7 @@
#include "Geometry.h"
#include "LineStyle.h"
+#include "FillStyle.h"
#include "SWFRect.h"
#include <vector>
@@ -30,12 +31,78 @@
namespace gnash {
class movie_definition;
class RunResources;
- class FillStyle;
}
namespace gnash {
namespace SWF {
+
+
+class Subshape {
+
+public:
+ typedef std::vector<FillStyle> FillStyles;
+ typedef std::vector<LineStyle> LineStyles;
+ typedef std::vector<Path> Paths;
+
+ const FillStyles& fillStyles() const {
+ return _fillStyles;
+ }
+
+ FillStyles& fillStyles() {
+ return _fillStyles;
+ }
+
+ const LineStyles& lineStyles() const {
+ return _lineStyles;
+ }
+
+ LineStyles& lineStyles() {
+ return _lineStyles;
+ }
+
+ const Paths& paths() const {
+ return _paths;
+ }
+
+ Paths& paths() {
+ return _paths;
+ }
+
+ /// For DynamicShape
+ //
+ /// TODO: rewrite DynamicShape to push paths when they're
+ /// finished and drop this.
+ Path& currentPath() {
+ return _paths.back();
+ }
+
+ void addFillStyle(const FillStyle& fs);
+
+ void addPath(const Path& path) {
+ _paths.push_back(path);
+ }
+
+ void addLineStyle(const LineStyle& ls) {
+ _lineStyles.push_back(ls);
+ }
+
+ void clear() {
+ _fillStyles.clear();
+ _lineStyles.clear();
+ _paths.clear();
+ }
+
+ SWFRect computeBounds(int swfVersion) const;
+
+private:
+ FillStyles _fillStyles;
+ LineStyles _lineStyles;
+ Paths _paths;
+};
+
+
+
/// Holds information needed to draw a shape.
//
/// This does not correspond exactly to parsed record in a SWF file, but
@@ -49,13 +116,20 @@ namespace SWF {
//
/// ShapeRecord objects are not ref-counted, so they may be stack-allocated
/// or used in smart pointers.
+//
+/// A shape can have sub-shapes. This can happen when there are multiple
+/// layers of the same frame count. Flash combines them to one single shape.
+/// The problem with sub-shapes is, that outlines can be hidden by other
+/// layers so they must be rendered separately. In order to be sure outlines
+/// are show correctly, draw the subshapes contained in the ShapeRecord in
+/// sequence.
class ShapeRecord
{
public:
-
- typedef std::vector<FillStyle> FillStyles;
- typedef std::vector<LineStyle> LineStyles;
- typedef std::vector<Path> Paths;
+ typedef Subshape::FillStyles FillStyles;
+ typedef Subshape::LineStyles LineStyles;
+ typedef Subshape::Paths Paths;
+ typedef std::vector<Subshape> Subshapes;
/// Construct a ShapeRecord.
//
@@ -71,11 +145,6 @@ public:
ShapeRecord(SWFStream& in, SWF::TagType tag, movie_definition& m,
const RunResources& r);
- /// Copy constructor
- ShapeRecord(const ShapeRecord& other);
-
- /// Assignment operator
- ShapeRecord& operator=(const ShapeRecord& other);
~ShapeRecord();
@@ -86,30 +155,18 @@ public:
void read(SWFStream& in, SWF::TagType tag, movie_definition& m,
const RunResources& r);
- const FillStyles& fillStyles() const {
- return _fillStyles;
- }
-
- const LineStyles& lineStyles() const {
- return _lineStyles;
+ const Subshapes& subshapes() const {
+ return _subshapes;
}
- const Paths& paths() const {
- return _paths;
+ void addSubshape(const Subshape& subshape) {
+ _subshapes.push_back(subshape);
}
const SWFRect& getBounds() const {
return _bounds;
}
- /// For DynamicShape
- //
- /// TODO: rewrite DynamicShape to push paths when they're
- /// finished and drop this.
- Path& currentPath() {
- return _paths.back();
- }
-
/// Set to the lerp of two ShapeRecords.
//
/// Used in shape morphing.
@@ -119,22 +176,26 @@ public:
/// Reset all shape data.
void clear();
- void addFillStyle(const FillStyle& fs);
-
- void addPath(const Path& path) {
- _paths.push_back(path);
+ void setBounds(const SWFRect& bounds) {
+ _bounds = bounds;
}
- void addLineStyle(const LineStyle& ls) {
- _lineStyles.push_back(ls);
- }
+ bool pointTest(boost::int32_t x, boost::int32_t y,
+ const SWFMatrix& wm) const {
+ for (SWF::ShapeRecord::Subshapes::const_iterator it = _subshapes.begin(),
+ end = _subshapes.end(); it != end; ++it) {
- void setBounds(const SWFRect& bounds) {
- _bounds = bounds;
+ if (geometry::pointTest(it->paths(), it->lineStyles(), x, y, wm)) {
+ return true;
+ }
+ }
+ return false;
}
private:
+ unsigned readStyleChange(SWFStream& in, size_t num_fill_bits, size_t numStyles);
+
/// Shape record flags for use in parsing.
enum ShapeRecordFlags {
SHAPE_END = 0x00,
@@ -144,12 +205,9 @@ private:
SHAPE_LINESTYLE_CHANGE = 0x08,
SHAPE_HAS_NEW_STYLES = 0x10
};
-
- FillStyles _fillStyles;
- LineStyles _lineStyles;
- Paths _paths;
- SWFRect _bounds;
+ SWFRect _bounds;
+ Subshapes _subshapes;
};
std::ostream& operator<<(std::ostream& o, const ShapeRecord& sh);
diff --git a/libcore/swf/SoundInfoRecord.h b/libcore/swf/SoundInfoRecord.h
index be77892..3165788 100644
--- a/libcore/swf/SoundInfoRecord.h
+++ b/libcore/swf/SoundInfoRecord.h
@@ -21,7 +21,7 @@
#ifndef GNASH_SWF_SOUNDINFO_H
#define GNASH_SWF_SOUNDINFO_H
-#include "sound_handler.h" // sound::SoundEnvelopes
+#include "SoundEnvelope.h" // sound::SoundEnvelopes
#include <limits>
diff --git a/libcore/swf/SoundStreamHeadTag.cpp b/libcore/swf/SoundStreamHeadTag.cpp
index c148716..516393f 100644
--- a/libcore/swf/SoundStreamHeadTag.cpp
+++ b/libcore/swf/SoundStreamHeadTag.cpp
@@ -38,6 +38,8 @@ void
SoundStreamHeadTag::loader(SWFStream& in, TagType tag, movie_definition& m,
const RunResources& r)
{
+#ifdef USE_SOUND
+
// 18 || 45
assert(tag == SWF::SOUNDSTREAMHEAD || tag == SWF::SOUNDSTREAMHEAD2);
@@ -157,6 +159,7 @@ SoundStreamHeadTag::loader(SWFStream& in, TagType tag, movie_definition& m,
const int handler_id = handler->createStreamingSound(sinfo);
m.set_loading_sound_stream_id(handler_id);
+#endif // USE_SOUND
}
} // namespace SWF
diff --git a/libcore/swf/StartSoundTag.cpp b/libcore/swf/StartSoundTag.cpp
index ad5dc5e..b6a9eb2 100644
--- a/libcore/swf/StartSoundTag.cpp
+++ b/libcore/swf/StartSoundTag.cpp
@@ -82,6 +82,7 @@ StartSoundTag::executeActions(MovieClip* m, DisplayList& /* dlist */) const
sound::sound_handler* handler =
getRunResources(*getObject(m)).soundHandler();
+#ifdef USE_SOUND
if (handler) {
if (_soundInfo.stopPlayback) {
//log_debug("Execute StartSoundTag with 'stop playback' flag on");
@@ -101,6 +102,7 @@ StartSoundTag::executeActions(MovieClip* m, DisplayList& /* dlist */) const
);
}
}
+#endif // USE_SOUND
}
void
diff --git a/libcore/swf/StartSoundTag.h b/libcore/swf/StartSoundTag.h
index 0bcb523..6d6dd63 100644
--- a/libcore/swf/StartSoundTag.h
+++ b/libcore/swf/StartSoundTag.h
@@ -20,7 +20,6 @@
#define GNASH_SWF_STARTSOUND_TAG_H
#include "ControlTag.h" // for inheritance
-#include "sound_handler.h" // for sound_envelope (composition)
#include "SWF.h" // for TagType definition
#include "SoundInfoRecord.h"
diff --git a/libcore/swf/StreamSoundBlockTag.cpp b/libcore/swf/StreamSoundBlockTag.cpp
index cb9d59a..ce3510a 100644
--- a/libcore/swf/StreamSoundBlockTag.cpp
+++ b/libcore/swf/StreamSoundBlockTag.cpp
@@ -43,12 +43,14 @@ StreamSoundBlockTag::executeActions(MovieClip* m, DisplayList& /*dlist*/) const
sound::sound_handler* handler =
getRunResources(*getObject(m)).soundHandler();
+#ifdef USE_SOUND
if (handler) {
// This makes it possible to stop only the stream when framejumping.
m->setStreamSoundId(_handler_id);
handler->playStream(_handler_id, _blockId);
getRoot(*getObject(m)).setStreamBlock(_handler_id, _blockId);
}
+#endif // USE_SOUND
}
void
diff --git a/libcore/swf/VideoFrameTag.h b/libcore/swf/VideoFrameTag.h
index b4862e2..02c4575 100644
--- a/libcore/swf/VideoFrameTag.h
+++ b/libcore/swf/VideoFrameTag.h
@@ -19,18 +19,13 @@
#ifndef GNASH_SWF_VIDEOFRAMETAG_H
#define GNASH_SWF_VIDEOFRAMETAG_H
-#include "DefinitionTag.h"
-#include "movie_definition.h"
#include "SWF.h"
-#include "SWFRect.h" // for composition
-#include "ControlTag.h"
-#include "VideoDecoder.h"
-
-#include <memory> // for auto_ptr
namespace gnash {
// Forward declarations
class SWFStream;
+ class RunResources;
+ class movie_definition;
}
namespace gnash {
diff --git a/libcore/swf/tag_loaders.cpp b/libcore/swf/tag_loaders.cpp
index c756e6f..0d2418c 100644
--- a/libcore/swf/tag_loaders.cpp
+++ b/libcore/swf/tag_loaders.cpp
@@ -158,6 +158,7 @@ define_sound_loader(SWFStream& in, TagType tag, movie_definition& m,
const boost::uint16_t id = in.read_u16();
+#ifdef USE_SOUND
media::audioCodecType format = static_cast<media::audioCodecType>(
in.read_uint(4));
@@ -237,6 +238,7 @@ define_sound_loader(SWFStream& in, TagType tag, movie_definition& m,
"so DisplayObject with id %d will not be added to "
"the dictionary"), id);
}
+#endif // USE_SOUND
}
diff --git a/libcore/vm/ASHandlers.cpp b/libcore/vm/ASHandlers.cpp
index 92f9cd9..05121d1 100644
--- a/libcore/vm/ASHandlers.cpp
+++ b/libcore/vm/ASHandlers.cpp
@@ -2994,17 +2994,22 @@ ActionBitwiseXor(ActionExec& thread)
env.drop(1);
}
+inline boost::uint32_t
+saneShiftParam(boost::int32_t value)
+{
+ // NOTE: ISO-IEC 14882:2003 5.8.1: "The behavior is undefined if the right
+ // operand is negative, or greater than or equal to the length in bits of
+ // the promoted left operand."
+ boost::uint32_t rv = value;
+ return rv % 32;
+}
+
void
ActionShiftLeft(ActionExec& thread)
{
as_environment& env = thread.env;
- /// A left shift of more than or equal to the size in
- /// bits of the left operand, or a negative shift, results
- /// in undefined behaviour in C++.
- boost::int32_t amount = toInt(env.top(0), getVM(env)) % 32;
- if (amount < 0) amount += 32;
-
+ boost::uint32_t amount = saneShiftParam(toInt(env.top(0), getVM(env)));
boost::int32_t value = toInt(env.top(1), getVM(env));
value = value << amount;
@@ -3018,8 +3023,7 @@ ActionShiftRight(ActionExec& thread)
{
as_environment& env = thread.env;
- // This is UB.
- boost::uint32_t amount = toInt(env.top(0), getVM(env));
+ boost::uint32_t amount = saneShiftParam(toInt(env.top(0), getVM(env)));
boost::int32_t value = toInt(env.top(1), getVM(env));
value = value >> amount;
@@ -3033,11 +3037,10 @@ ActionShiftRight2(ActionExec& thread)
{
as_environment& env = thread.env;
- // This is UB
- boost::uint32_t amount = toInt(env.top(0), getVM(env));
+ boost::uint32_t amount = saneShiftParam(toInt(env.top(0), getVM(env)));
boost::int32_t value = toInt(env.top(1), getVM(env));
- value = boost::uint32_t(value) >> amount;
+ value = static_cast<boost::uint32_t>(value) >> amount;
env.top(1) = value;
env.drop(1);
diff --git a/libcore/vm/ASHandlers.h b/libcore/vm/ASHandlers.h
index cbe75f3..a739549 100644
--- a/libcore/vm/ASHandlers.h
+++ b/libcore/vm/ASHandlers.h
@@ -19,7 +19,6 @@
#ifndef GNASH_ASHANDLERS_H
#define GNASH_ASHANDLERS_H
-#include <string>
#include <vector>
#include "SWF.h"
diff --git a/libcore/vm/Makefile.am b/libcore/vm/Makefile.am
index b984c06..6497cea 100644
--- a/libcore/vm/Makefile.am
+++ b/libcore/vm/Makefile.am
@@ -88,7 +88,10 @@ if WIN32
libgnashvm_la_LDFLAGS += -no-undefined
endif
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
+AM_LDFLAGS = $(CROSS_LDFLAGS)
+
if ENABLE_PCH
-AM_CXXFLAGS = $(PCH_FLAGS)
+AM_CXXFLAGS += $(PCH_FLAGS)
endif
diff --git a/libcore/vm/VM.cpp b/libcore/vm/VM.cpp
index 627b803..4214097 100644
--- a/libcore/vm/VM.cpp
+++ b/libcore/vm/VM.cpp
@@ -464,7 +464,14 @@ toInt(const as_value& v, const VM& vm)
{
const double d = v.to_number(vm.getSWFVersion());
- if (!isFinite(d)) return 0;
+ if (!isFinite(d) || isNaN(d)) {
+ return 0;
+ }
+
+ typedef std::numeric_limits<boost::int32_t> limit;
+ if (d >= limit::min() && d <= limit::max()) {
+ return d;
+ }
if (d < 0) {
return - static_cast<boost::uint32_t>(std::fmod(-d, 4294967296.0));
diff --git a/libcore/vm/VM.h b/libcore/vm/VM.h
index 4bab9b9..6e2edb0 100644
--- a/libcore/vm/VM.h
+++ b/libcore/vm/VM.h
@@ -25,15 +25,12 @@
#endif
#include <map>
-#include <vector>
#include <memory>
-#include <locale>
+#include <boost/array.hpp>
#include <boost/cstdint.hpp>
-#include <boost/random.hpp>
+#include <boost/random/mersenne_twister.hpp> // for mt11213b
#include <boost/noncopyable.hpp>
-#include <boost/array.hpp>
-#include "GC.h"
#include "string_table.h"
#include "SafeStack.h"
#include "CallStack.h"
@@ -41,18 +38,18 @@
#include "namedStrings.h"
#include "ObjectURI.h"
#include "ConstantPool.h"
+#include "dsodefs.h"
+#include "utility.h" // for UNUSED
// Forward declarations
namespace gnash {
- class Global_as;
- class VM;
- class fn_call;
- class movie_root;
- class NativeFunction;
+ class Global_as;
+ class fn_call;
+ class movie_root;
+ class NativeFunction;
class SharedObjectLibrary;
- class as_value;
- class as_object;
- class VirtualClock;
+ class as_object;
+ class VirtualClock;
class UserFunction;
}
@@ -408,7 +405,7 @@ bool toBool(const as_value& v, const VM& vm);
/// @param val The value to return as a double
/// @param vm The VM to use for the conversion.
/// @return The double value of the passed as_value.
-double toNumber(const as_value& v, const VM& vm);
+DSOTEXPORT double toNumber(const as_value& v, const VM& vm);
/// Convert an as_value to an object
//
diff --git a/libcore/vm/fn_call.h b/libcore/vm/fn_call.h
index e74cf1c..6d234f3 100644
--- a/libcore/vm/fn_call.h
+++ b/libcore/vm/fn_call.h
@@ -25,6 +25,7 @@
#include <ostream>
#include <algorithm>
+#include "utility.h" // for typeName
#include "as_object.h"
#include "as_value.h"
#include "VM.h"
diff --git a/libdevice/Makefile.am b/libdevice/Makefile.am
index 991526e..6cd0c9e 100644
--- a/libdevice/Makefile.am
+++ b/libdevice/Makefile.am
@@ -97,8 +97,11 @@ mudflap:
clean-hook:
-rm -f core.*
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
+# AM_LDFLAGS = $(CROSS_LDFLAGS)
+
if ENABLE_PCH
-AM_CXXFLAGS = $(PCH_FLAGS)
+AM_CXXFLAGS += $(PCH_FLAGS)
endif
bin_PROGRAMS =
@@ -121,19 +124,6 @@ if BUILD_DIRECTFB_DEVICE
include directfb/directfb.am
endif
-if ENABLE_DEVELOPER_TESTS
-if BUILD_X11_DEVICE
-
-check_PROGRAMS += test_x11
-test_x11_SOURCES = x11/test_x11.cpp
-test_x11_CPPFLAGS = $(AM_CPPFLAGS) $(X11_CFLAGS)
-test_x11_LDADD = \
- libgnashdevice.la \
- $(X11_LIBS) \
- $(GNASH_LIBS)
-endif
-endif
-
if BUILD_VAAPI_DEVICE
include vaapi/vaapi.am
endif
diff --git a/libdevice/directfb/DirectFBDevice.cpp b/libdevice/directfb/DirectFBDevice.cpp
index aea118e..b5673db 100644
--- a/libdevice/directfb/DirectFBDevice.cpp
+++ b/libdevice/directfb/DirectFBDevice.cpp
@@ -172,7 +172,7 @@ DirectFBDevice::initDevice(int argc, char *argv[])
}
if ((result == _layer->GetScreen(_layer, &_screen)) == DR_OK) {
- log_error(_("GetScreen(): %s"_, getErrorString(result));
+ log_error(_("GetScreen(): %s"), getErrorString(result));
}
DFBSurfacePixelFormat format;
diff --git a/libdevice/directfb/directfb.am b/libdevice/directfb/directfb.am
index d04827a..7022a16 100644
--- a/libdevice/directfb/directfb.am
+++ b/libdevice/directfb/directfb.am
@@ -1,5 +1,6 @@
#
-# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012,
+# 2013 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
@@ -21,12 +22,3 @@ libgnashdevice_la_SOURCES += \
directfb/DirectFBDevice.cpp \
directfb/DirectFBDevice.h
libgnashdevice_la_LIBADD += $(DIRECTFB_LIBS)
-
-check_PROGRAMS += test_dfb
-test_dfb_SOURCES = directfb/test_dfb.cpp
-test_dfb_CPPFLAGS = $(AM_CPPFLAGS) $(DIRECTFB_CFLAGS)
-test_dfb_LDADD = \
- libgnashdevice.la \
- $(TS_LIBS) \
- $(DIRECTFB_LIBS) \
- $(GNASH_LIBS)
diff --git a/libdevice/egl/egl.am b/libdevice/egl/egl.am
index 145e9d1..7b1ac85 100644
--- a/libdevice/egl/egl.am
+++ b/libdevice/egl/egl.am
@@ -27,23 +27,6 @@ eglinfo_LDADD = \
$(EGL_LIBS) \
$(NULL)
-if ENABLE_DEVELOPER_TESTS
-# this tests the low level EGL interface, used by OpenVG, OpenGLES1, and OpenGLES2.
-bin_PROGRAMS += test_egl
-test_egl_SOURCES = egl/test_egl.cpp
-test_egl_CPPFLAGS = $(AM_CPPFLAGS) $(EGL_CFLAGS)
-test_egl_LDADD = \
- libgnashdevice.la \
- $(EXTRA_EGL_LIBS) \
- $(TS_LIBS) \
- $(CURL_LIBS) \
- $(EGL_LIBS) \
- $(GNASH_LIBS) \
- $(LTDL_LIBS) \
- $(top_builddir)/libbase/libgnashbase.la \
- $(NULL)
-endif
-
libgnashdevice_la_CPPFLAGS += $(EGL_CFLAGS)
libgnashdevice_la_SOURCES += \
egl/eglDevice.cpp \
diff --git a/libdevice/egl/eglDevice.cpp b/libdevice/egl/eglDevice.cpp
index 263361b..5f9894a 100644
--- a/libdevice/egl/eglDevice.cpp
+++ b/libdevice/egl/eglDevice.cpp
@@ -380,7 +380,11 @@ EGLDevice::attachWindow(GnashDevice::native_window_t window)
if (!window) {
throw GnashException("bogus window handle!");
} else {
+#ifdef EGL_NATIVE_WINDOW_INT
_nativeWindow = static_cast<EGLNativeWindowType>(window);
+#else
+ _nativeWindow = reinterpret_cast<EGLNativeWindowType>(window);
+#endif
}
if (_eglSurface != EGL_NO_SURFACE) {
diff --git a/libdevice/events/EventDevice.cpp b/libdevice/events/EventDevice.cpp
index b5b93e4..5351dcf 100644
--- a/libdevice/events/EventDevice.cpp
+++ b/libdevice/events/EventDevice.cpp
@@ -524,7 +524,7 @@ EventDevice::check()
activity = true;
break;
case MSC_MAX:
- case MSC_CNT:
+// case MSC_CNT:
default:
log_unimpl(_("Misc event from Input Event Device"));
}
diff --git a/libdevice/events/InputDevice.h b/libdevice/events/InputDevice.h
index 13595cb..6d36ed0 100644
--- a/libdevice/events/InputDevice.h
+++ b/libdevice/events/InputDevice.h
@@ -30,7 +30,9 @@
#include <vector>
#include <queue>
#include <linux/input.h>
+#ifdef HAVE_LINUX_UINPUT_H
#include <linux/uinput.h>
+#endif
#include "GnashKey.h"
diff --git a/libdevice/events/events.am b/libdevice/events/events.am
index 9eff369..29149d7 100644
--- a/libdevice/events/events.am
+++ b/libdevice/events/events.am
@@ -42,20 +42,12 @@ endif
# The Uinput device is write only, and is used to control the mouse
# movements.
+if HAS_UINPUT
libgnashdevice_la_SOURCES += events/UinputDevice.cpp
+endif
if ENABLE_DEVELOPER_TESTS
-check_PROGRAMS += test_events evtest
-test_events_SOURCES = events/test_events.cpp
-test_events_CPPFLAGS = $(AM_CPPFLAGS)
-test_events_LDADD = \
- libgnashdevice.la \
- $(EXTRA_EVENTS_LIBS) \
- $(TS_LIBS) \
- $(CURL_LIBS) \
- $(EVENTS_LIBS) \
- $(GNASH_LIBS)
-
+check_PROGRAMS += evtest
evtest_SOURCES = events/evtest.c
evtest_CPPFLAGS = $(AM_CPPFLAGS)
evtest_LDADD = \
diff --git a/libdevice/rawfb/RawFBDevice.cpp b/libdevice/rawfb/RawFBDevice.cpp
index 59cbf02..bce2333 100644
--- a/libdevice/rawfb/RawFBDevice.cpp
+++ b/libdevice/rawfb/RawFBDevice.cpp
@@ -77,6 +77,7 @@ void
RawFBDevice::clear()
{
GNASH_REPORT_FUNCTION;
+
if (_fbmem) {
memset(_fbmem, 0, _fixinfo.smem_len);
}
@@ -124,7 +125,11 @@ RawFBDevice::initDevice(int /* argc */, char **/* argv[] */)
// lets us redefine this at runtime.
devname = getenv("FAKE_FRAMEBUFFER");
if (!devname) {
+#ifdef __ANDROID__
+ devname = "/dev/graphics/fb0";
+#else
devname = "/dev/fb0";
+#endif
}
}
_fd = open(devname, O_RDWR);
@@ -144,13 +149,18 @@ RawFBDevice::initDevice(int /* argc */, char **/* argv[] */)
ioctl(_fd, FBIOGET_VSCREENINFO, &_varinfo);
ioctl(_fd, FBIOGET_FSCREENINFO, &_fixinfo);
#endif
- log_debug(_("Framebuffer device uses %d bytes of memory."),
- _fixinfo.smem_len);
- log_debug(_("Video mode: %dx%d with %d bits per pixel."),
+
+ // dump();
+
+ log_debug("Framebuffer device uses %d bytes of memory.",
+ _fixinfo.smem_len);
+ log_debug("Video mode: %dx%d with %d bits per pixel. (Virtual: %dx%d)",
_varinfo.xres, _varinfo.yres,
- _varinfo.bits_per_pixel);
+ _varinfo.bits_per_pixel,
+ _varinfo.xres_virtual, _varinfo.yres_virtual
+ );
- log_debug(_("Framebuffer stride is: %d."), _fixinfo.line_length);
+ log_debug("Framebuffer stride is: %d.", _fixinfo.line_length);
return true;
}
@@ -269,6 +279,27 @@ RawFBDevice::eventLoop(size_t /* passes */)
GNASH_REPORT_FUNCTION;
}
+void
+RawFBDevice::dump()
+{
+ // dump the fb_var_screeninfo data
+ std::cerr << "X res visible = " << _varinfo.xres << std::endl;
+ std::cerr << "Y res visible = " << _varinfo.yres << std::endl;
+ std::cerr << "X res virtual = " << _varinfo.xres_virtual << std::endl;
+ std::cerr << "Y res virtual = " << _varinfo.yres_virtual << std::endl;
+ std::cerr << "X offset = " << _varinfo.xoffset << std::endl;
+ std::cerr << "Y offset = " << _varinfo.yoffset << std::endl;
+ std::cerr << "bits per pixel = " << _varinfo.bits_per_pixel << std::endl;
+
+ // dump the fb_fix_screeninfo data
+ std::cerr << "Screen Memory = " << _fixinfo.smem_len << std::endl;
+ std::cerr << "Screen Type = " << _fixinfo.type << std::endl;
+ std::cerr << "X Pan step = " << _fixinfo.xpanstep << std::endl;
+ std::cerr << "Y Pan step = " << _fixinfo.ypanstep << std::endl;
+ std::cerr << "Y wrap step = " << _fixinfo.ywrapstep << std::endl;
+ std::cerr << "line length = " << _fixinfo.line_length << std::endl;
+}
+
#ifdef ENABLE_FAKE_FRAMEBUFFER
// Simulate the ioctls used to get information from the framebuffer
// driver. Since this is an emulator, we have to set these fields
diff --git a/libdevice/rawfb/RawFBDevice.h b/libdevice/rawfb/RawFBDevice.h
index 69f85a2..3aaf83a 100644
--- a/libdevice/rawfb/RawFBDevice.h
+++ b/libdevice/rawfb/RawFBDevice.h
@@ -138,7 +138,8 @@ class DSOEXPORT RawFBDevice : public GnashDevice
}
bool swapBuffers();
-
+
+ void dump();
protected:
/// Clear the framebuffer memory
void clear();
diff --git a/libdevice/rawfb/rawfb.am b/libdevice/rawfb/rawfb.am
index d3511f2..bbe2998 100644
--- a/libdevice/rawfb/rawfb.am
+++ b/libdevice/rawfb/rawfb.am
@@ -9,18 +9,4 @@ libgnashdevice_la_SOURCES += \
libgnashdevice_la_LIBADD += \
$(TSLIB_LIBS) \
$(EXTRA_EGL_LIBS)
-
-
-if ENABLE_DEVELOPER_TESTS
-check_PROGRAMS += test_rawfb
-
-# this tests the low level EGL interface, used by OpenVG, OpenGLES1,
-# and OpenGLES2.
-test_rawfb_SOURCES = rawfb/test_rawfb.cpp
-test_rawfb_CPPFLAGS = $(AM_CPPFLAGS)
-test_rawfb_LDADD = \
- libgnashdevice.la \
- $(TS_LIBS) \
- $(GNASH_LIBS)
-endif
endif
\ No newline at end of file
diff --git a/libdevice/vaapi/VaapiImage.cpp b/libdevice/vaapi/VaapiImage.cpp
index 5fc6cf2..d4a6a17 100644
--- a/libdevice/vaapi/VaapiImage.cpp
+++ b/libdevice/vaapi/VaapiImage.cpp
@@ -35,7 +35,7 @@ VaapiImage::VaapiImage(unsigned int width,
: _format(format)
, _image_data(NULL)
{
- log_debug(_("VaapiImage::VaapiImage(): format '%s'\n", string_of_FOURCC(format)));
+ log_debug(_("VaapiImage::VaapiImage(): format '%s'\n"), string_of_FOURCC(format));
memset(&_image, 0, sizeof(_image));
_image.image_id = VA_INVALID_ID;
@@ -79,7 +79,7 @@ bool VaapiImage::create(unsigned int width, unsigned int height)
if (!vaapi_check_status(status, "vaCreateImage()"))
return false;
- log_debug(_(" image 0x%08x, format '%s'\n", get(), string_of_FOURCC(_format)));
+ log_debug(_(" image 0x%08x, format '%s'\n"), get(), string_of_FOURCC(_format));
return true;
}
diff --git a/libdevice/vaapi/VaapiSubpicture.cpp b/libdevice/vaapi/VaapiSubpicture.cpp
index e6ea376..227a05a 100644
--- a/libdevice/vaapi/VaapiSubpicture.cpp
+++ b/libdevice/vaapi/VaapiSubpicture.cpp
@@ -32,7 +32,7 @@ VaapiSubpicture::VaapiSubpicture(boost::shared_ptr<VaapiImage> image)
: _image(image)
, _subpicture(VA_INVALID_ID)
{
- log_debug(_("VaapiSubpicture::VaapiSubpicture(): format '%s'\n", string_of_FOURCC(image->format())));
+ log_debug(_("VaapiSubpicture::VaapiSubpicture(): format '%s'\n"), string_of_FOURCC(image->format()));
if (!create()) {
boost::format msg;
diff --git a/libdevice/vaapi/VaapiSurface.cpp b/libdevice/vaapi/VaapiSurface.cpp
index fd09bfa..7a16495 100644
--- a/libdevice/vaapi/VaapiSurface.cpp
+++ b/libdevice/vaapi/VaapiSurface.cpp
@@ -74,7 +74,7 @@ public:
VaapiSurfaceImpl::~VaapiSurfaceImpl()
{
- log_debug(_("VaapiSurface::~VaapiSurface(): surface 0x%08x\n", surface()));
+ log_debug(_("VaapiSurface::~VaapiSurface(): surface 0x%08x\n"), surface());
if (surface() == VA_INVALID_SURFACE) {
return;
diff --git a/libdevice/vaapi/VaapiSurfaceGLX.cpp b/libdevice/vaapi/VaapiSurfaceGLX.cpp
index 1c85af8..91a7cc5 100644
--- a/libdevice/vaapi/VaapiSurfaceGLX.cpp
+++ b/libdevice/vaapi/VaapiSurfaceGLX.cpp
@@ -202,14 +202,14 @@ VaapiSurfaceGLXImpl::VaapiSurfaceGLXImpl(GLenum target, GLuint texture)
reset(reinterpret_cast<uintptr_t>(surface));
- log_debug(_(" -> surface %p\n", this->surface()));
+ log_debug(_(" -> surface %p\n"), this->surface());
}
VaapiSurfaceGLXImpl::~VaapiSurfaceGLXImpl()
{
// GNASH_REPORT_FUNCTION;
- log_debug(_("VaapiSurface::~VaapiSurface(): surface %p\n", surface()));
+ log_debug(_("VaapiSurface::~VaapiSurface(): surface %p\n"), surface());
if (!surface()) {
return;
@@ -263,7 +263,7 @@ VaapiSurfaceGLX::VaapiSurfaceGLX(GLenum target, GLuint texture)
bool VaapiSurfaceGLX::update(boost::shared_ptr<VaapiSurface> surface)
{
- log_debug(_("VaapiSurfaceGLX::update(): from surface 0x%08x\n", surface->get()));
+ log_debug(_("VaapiSurfaceGLX::update(): from surface 0x%08x\n"), surface->get());
return dynamic_cast<VaapiSurfaceGLXImpl *>(_impl.get())->update(surface);
}
diff --git a/libdevice/vaapi/VaapiSurfaceProxy.cpp b/libdevice/vaapi/VaapiSurfaceProxy.cpp
index d51a38b..8972587 100644
--- a/libdevice/vaapi/VaapiSurfaceProxy.cpp
+++ b/libdevice/vaapi/VaapiSurfaceProxy.cpp
@@ -28,12 +28,12 @@ VaapiSurfaceProxy::VaapiSurfaceProxy(boost::shared_ptr<VaapiSurface> surface,
boost::shared_ptr<VaapiContext> context)
: _context(context), _surface(surface)
{
- log_debug(_("VaapiSurfaceProxy::VaapiSurfaceProxy(): surface 0x%08x\n", _surface->get()));
+ log_debug(_("VaapiSurfaceProxy::VaapiSurfaceProxy(): surface 0x%08x\n"), _surface->get());
}
VaapiSurfaceProxy::~VaapiSurfaceProxy()
{
- log_debug(_("VaapiSurfaceProxy::~VaapiSurfaceProxy(): surface 0x%08x\n", _surface->get()));
+ log_debug(_("VaapiSurfaceProxy::~VaapiSurfaceProxy(): surface 0x%08x\n"), _surface->get());
_context->releaseSurface(_surface);
}
diff --git a/libdevice/vaapi/vaapi.am b/libdevice/vaapi/vaapi.am
index 4e9e602..2611c2b 100644
--- a/libdevice/vaapi/vaapi.am
+++ b/libdevice/vaapi/vaapi.am
@@ -91,13 +91,3 @@ libgnashdevice_la_CPPFLAGS += $(VAAPI_CFLAGS)
# vaapi/VaapiDevice.cpp \
# vaapi/VaapiDevice.h
libgnashdevice_la_LIBADD += $(VAAPI_LIBS)
-
-if ENABLE_DEVELOPER_TESTS
-check_PROGRAMS += test_vaapi
-test_vaapi_SOURCES = vaapi/test_vaapi.cpp
-test_vaapi_CPPFLAGS = $(AM_CPPFLAGS) $(VAAPI_CFLAGS)
-test_vaapi_LDADD = \
- libgnashdevice.la \
- $(VAAPI_LIBS) \
- $(GNASH_LIBS)
-endif
\ No newline at end of file
diff --git a/libmedia/FLVParser.cpp b/libmedia/FLVParser.cpp
index 7333dd9..8210e34 100644
--- a/libmedia/FLVParser.cpp
+++ b/libmedia/FLVParser.cpp
@@ -447,7 +447,7 @@ FLVParser::parseNextTag(bool index_only)
}
boost::mutex::scoped_lock lock(_metaTagsMutex);
- _metaTags.insert(std::make_pair(flvtag.timestamp, metaTag.release()));
+ _metaTags.insert(std::make_pair(flvtag.timestamp, MetaTags::mapped_type(metaTag)));
}
else
{
diff --git a/libmedia/FLVParser.h b/libmedia/FLVParser.h
index d302bb1..5a31c14 100644
--- a/libmedia/FLVParser.h
+++ b/libmedia/FLVParser.h
@@ -26,9 +26,7 @@
#include "dsodefs.h"
#include "MediaParser.h" // for inheritance
-#include "SimpleBuffer.h"
-#include <set>
#include <memory>
#include <map>
diff --git a/libmedia/Makefile.am b/libmedia/Makefile.am
index 2d740ad..985e034 100644
--- a/libmedia/Makefile.am
+++ b/libmedia/Makefile.am
@@ -16,7 +16,8 @@
AUTOMAKE_OPTIONS = foreign
-AM_CXXFLAGS = -DREGISTER_MEDIA_HANDLERS
+AM_CXXFLAGS = $(CROSS_CXXFLAGS) -DREGISTER_MEDIA_HANDLERS
+AM_LDFLAGS = $(CROSS_LDFLAGS)
# If we are using an installable libltdl, then it needs to be built
# before libgnash, as libgnash depends on it for extensions.
@@ -46,6 +47,7 @@ libgnashmedia_la_SOURCES += \
gst/AudioDecoderGst.h \
gst/AudioInputGst.cpp \
gst/AudioInputGst.h \
+ gst/GlibDeprecated.h \
gst/GstUtil.cpp \
gst/GstUtil.h \
gst/MediaHandlerGst.cpp \
@@ -128,10 +130,6 @@ libgnashmedia_la_CPPFLAGS = \
$(BOOST_CFLAGS) \
$(NULL)
-if ANDROID
-libgnashmedia_la_CPPFLAGS += $(ANDROID_NDK)/usr/include
-endif
-
if USE_GST_ENGINE
libgnashmedia_la_CPPFLAGS += \
$(GSTREAMER_CFLAGS) \
diff --git a/libmedia/MediaHandler.h b/libmedia/MediaHandler.h
index 4ffd6e0..98f62ce 100644
--- a/libmedia/MediaHandler.h
+++ b/libmedia/MediaHandler.h
@@ -21,14 +21,12 @@
#ifndef GNASH_MEDIAHANDLER_H
#define GNASH_MEDIAHANDLER_H
-#include "MediaParser.h" // for videoCodecType and audioCodecType enums
#include "dsodefs.h" // DSOEXPORT
#include "VideoConverter.h"
#include "GnashFactory.h"
#include <vector>
#include <memory>
-#include <map>
#include <string>
// Forward declarations
@@ -42,6 +40,7 @@ namespace gnash {
class VideoInput;
class AudioInput;
class MediaHandler;
+ class MediaParser;
}
}
diff --git a/libmedia/MediaParser.cpp b/libmedia/MediaParser.cpp
index 77eb5d6..e4de8ca 100644
--- a/libmedia/MediaParser.cpp
+++ b/libmedia/MediaParser.cpp
@@ -424,8 +424,8 @@ bool
MediaParser::bufferFull() const
{
// Callers are expected to hold a lock on _qMutex
- int bl = getBufferLengthNoLock();
- int bt = getBufferTime();
+ boost::uint64_t bl = getBufferLengthNoLock();
+ boost::uint64_t bt = getBufferTime();
#ifdef GNASH_DEBUG_MEDIAPARSER
log_debug("MediaParser::bufferFull: %d/%d", bl, bt);
#endif // GNASH_DEBUG_MEDIAPARSER
diff --git a/libmedia/MediaParser.h b/libmedia/MediaParser.h
index 535dd78..35ed0d0 100644
--- a/libmedia/MediaParser.h
+++ b/libmedia/MediaParser.h
@@ -75,6 +75,9 @@ enum codecType
/// Video codec ids as defined in flash
enum videoCodecType
{
+ /// No video codec
+ NO_VIDEO_CODEC = 0,
+
/// H263/SVQ3 video codec
VIDEO_CODEC_H263 = 2,
diff --git a/libmedia/SoundInfo.h b/libmedia/SoundInfo.h
index 8537dfc..f574e59 100644
--- a/libmedia/SoundInfo.h
+++ b/libmedia/SoundInfo.h
@@ -117,9 +117,6 @@ private:
/// Current format of the sound (MP3, raw, etc).
audioCodecType _format;
- /// The size of the undecoded data
- unsigned long _dataSize;
-
/// Stereo or not
bool _stereo;
diff --git a/libmedia/ffmpeg/AudioDecoderFfmpeg.cpp b/libmedia/ffmpeg/AudioDecoderFfmpeg.cpp
index 067e418..b194f54 100644
--- a/libmedia/ffmpeg/AudioDecoderFfmpeg.cpp
+++ b/libmedia/ffmpeg/AudioDecoderFfmpeg.cpp
@@ -30,12 +30,6 @@
//#define GNASH_DEBUG_AUDIO_DECODING
-#if LIBAVCODEC_VERSION_MAJOR >= 53
-#define AVCODEC_DECODE_AUDIO avcodec_decode_audio3
-#else
-#define AVCODEC_DECODE_AUDIO avcodec_decode_audio2
-#endif
-
namespace gnash {
namespace media {
namespace ffmpeg {
@@ -84,11 +78,13 @@ AudioDecoderFfmpeg::~AudioDecoderFfmpeg()
void AudioDecoderFfmpeg::setup(SoundInfo& info)
{
- // Init the avdecoder-decoder
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52,6,2)
+ // Starting from this version avcodec_register calls avcodec_init
avcodec_init();
+#endif
avcodec_register_all();// change this to only register need codec?
- enum CodecID codec_id;
+ enum CODECID codec_id;
switch(info.getFormat()) {
case AUDIO_CODEC_RAW:
@@ -131,12 +127,20 @@ void AudioDecoderFfmpeg::setup(SoundInfo& info)
}
}
+#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(53,8,0)
+ _audioCodecCtx = avcodec_alloc_context3(_audioCodec);
+#else
_audioCodecCtx = avcodec_alloc_context();
+#endif
if (!_audioCodecCtx) {
throw MediaException(_("libavcodec couldn't allocate context"));
}
+#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(53,8,0)
+ int ret = avcodec_open2(_audioCodecCtx, _audioCodec, NULL);
+#else
int ret = avcodec_open(_audioCodecCtx, _audioCodec);
+#endif
if (ret < 0) {
av_free(_audioCodecCtx);
_audioCodecCtx=0;
@@ -158,14 +162,14 @@ void AudioDecoderFfmpeg::setup(SoundInfo& info)
case CODEC_ID_PCM_U16LE:
_audioCodecCtx->channels = (info.isStereo() ? 2 : 1);
_audioCodecCtx->sample_rate = info.getSampleRate();
- _audioCodecCtx->sample_fmt = SAMPLE_FMT_S16; // ?! arbitrary ?
+ _audioCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16; // ?! arbitrary ?
_audioCodecCtx->frame_size = 1;
break;
default:
_audioCodecCtx->channels = (info.isStereo() ? 2 : 1);
_audioCodecCtx->sample_rate = info.getSampleRate();
- _audioCodecCtx->sample_fmt = SAMPLE_FMT_S16; // ?! arbitrary ?
+ _audioCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16; // ?! arbitrary ?
break;
}
}
@@ -173,14 +177,17 @@ void AudioDecoderFfmpeg::setup(SoundInfo& info)
void AudioDecoderFfmpeg::setup(const AudioInfo& info)
{
// Init the avdecoder-decoder
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52,6,2)
+ // Starting from this version avcodec_register calls avcodec_init
avcodec_init();
+#endif
avcodec_register_all();// change this to only register need codec?
- enum CodecID codec_id = CODEC_ID_NONE;
+ enum CODECID codec_id = CODEC_ID_NONE;
if (info.type == CODEC_TYPE_CUSTOM)
{
- codec_id = static_cast<CodecID>(info.codec);
+ codec_id = static_cast<CODECID>(info.codec);
}
else if (info.type == CODEC_TYPE_FLASH)
{
@@ -254,7 +261,11 @@ void AudioDecoderFfmpeg::setup(const AudioInfo& info)
_needsParsing = (_parser != NULL);
// Create an audioCodecCtx from the ffmpeg parser if exists/possible
+#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(53,8,0)
+ _audioCodecCtx = avcodec_alloc_context3(_audioCodec);
+#else
_audioCodecCtx = avcodec_alloc_context();
+#endif
if (!_audioCodecCtx) {
throw MediaException(_("AudioDecoderFfmpeg: libavcodec couldn't "
"allocate context"));
@@ -297,7 +308,7 @@ void AudioDecoderFfmpeg::setup(const AudioInfo& info)
_audioCodecCtx->channels = (info.stereo ? 2 : 1);
_audioCodecCtx->sample_rate = info.sampleRate;
// was commented out (why?):
- _audioCodecCtx->sample_fmt = SAMPLE_FMT_S16;
+ _audioCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
break;
}
@@ -305,7 +316,11 @@ void AudioDecoderFfmpeg::setup(const AudioInfo& info)
#ifdef GNASH_DEBUG_AUDIO_DECODING
log_debug(" Opening codec");
#endif // GNASH_DEBUG_AUDIO_DECODING
+#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(53,8,0)
+ int ret = avcodec_open2(_audioCodecCtx, _audioCodec, NULL);
+#else
int ret = avcodec_open(_audioCodecCtx, _audioCodec);
+#endif
if (ret < 0) {
//avcodec_close(_audioCodecCtx);
av_free(_audioCodecCtx);
@@ -326,7 +341,7 @@ AudioDecoderFfmpeg::decode(const boost::uint8_t* input,
{
//GNASH_REPORT_FUNCTION;
- size_t retCapacity = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+ size_t retCapacity = MAX_AUDIO_FRAME_SIZE;
boost::uint8_t* retBuf = new boost::uint8_t[retCapacity];
int retBufSize = 0;
@@ -480,66 +495,81 @@ AudioDecoderFfmpeg::decodeFrame(const boost::uint8_t* input,
assert(inputSize);
- const size_t bufsize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+ size_t outSize = MAX_AUDIO_FRAME_SIZE;
// TODO: make this a private member, to reuse (see NetStreamFfmpeg in 0.8.3)
- boost::uint8_t* output;
-
- output = reinterpret_cast<boost::uint8_t*>(av_malloc(bufsize));
- if (!output) {
+ boost::int16_t* outPtr = reinterpret_cast<boost::int16_t*>(av_malloc(outSize));
+ if (!outPtr) {
log_error(_("failed to allocate audio buffer."));
outputSize = 0;
return NULL;
}
- boost::int16_t* outPtr = reinterpret_cast<boost::int16_t*>(output);
-
- // We initialize output size to the full size
- // then decoding will eventually reduce it
- int outSize = bufsize;
-
#ifdef GNASH_DEBUG_AUDIO_DECODING
log_debug("AudioDecoderFfmpeg: about to decode %d bytes; "
- "ctx->channels:%d, avctx->frame_size:%d",
+ "ctx->channels:%d, ctx->frame_size:%d",
inputSize, _audioCodecCtx->channels, _audioCodecCtx->frame_size);
#endif
// older ffmpeg versions didn't accept a const input..
-#if LIBAVCODEC_VERSION_MAJOR >= 53
AVPacket pkt;
+ int got_frm = 0;
av_init_packet(&pkt);
- pkt.data = (uint8_t*) input;
+ pkt.data = const_cast<uint8_t*>(input);
pkt.size = inputSize;
-#endif
- int tmp = AVCODEC_DECODE_AUDIO(_audioCodecCtx, outPtr, &outSize,
-#if LIBAVCODEC_VERSION_MAJOR >= 53
- &pkt);
-#else
- input, inputSize);
-#endif
+ AVFrame *frm = avcodec_alloc_frame();
+ if (!frm) {
+ log_error(_("failed to allocate frame."));
+ return NULL;
+ }
+ int tmp = avcodec_decode_audio4(_audioCodecCtx, frm, &got_frm, &pkt);
#ifdef GNASH_DEBUG_AUDIO_DECODING
- log_debug(" avcodec_decode_audio[2](ctx, bufptr, %d, input, %d) "
- "returned %d; set frame_size=%d",
- bufsize, inputSize, tmp, outSize);
+ const char* fmtname = av_get_sample_fmt_name(_audioCodecCtx->sample_fmt);
+ log_debug(" decodeFrame | frm->nb_samples: %d | &got_frm: %d | "
+ "returned %d | inputSize: %d",
+ frm->nb_samples, got_frm, tmp, inputSize);
#endif
- if (tmp < 0) {
- log_error(_("avcodec_decode_audio returned %d. Upgrading "
- "ffmpeg/libavcodec might fix this issue."), tmp);
- outputSize = 0;
+ int plane_size;
+ if (tmp >= 0 && got_frm) {
+ int data_size = av_samples_get_buffer_size( &plane_size,
+ _audioCodecCtx->channels, frm->nb_samples,
+ _audioCodecCtx->sample_fmt, 1);
+ if (static_cast<int>(outSize) < data_size) {
+ log_error(_("output buffer size is too small for the current frame "
+ "(%d < %d)"), outSize, data_size);
+ return NULL;
+ }
- av_free(output);
- return NULL;
- }
+ memcpy(outPtr, frm->extended_data[0], plane_size);
- if (outSize < 2) {
- log_error(_("outputSize:%d after decoding %d bytes of input audio "
- "data. Upgrading ffmpeg/libavcodec might fix this issue."),
- outputSize, inputSize);
- outputSize = 0;
+#if !(defined(HAVE_SWRESAMPLE_H) || defined(HAVE_AVRESAMPLE_H))
+ int planar = av_sample_fmt_is_planar(_audioCodecCtx->sample_fmt);
+ if (planar && _audioCodecCtx->channels > 1) {
+ uint8_t *out = ((uint8_t *)outPtr) + plane_size;
+ for (int ch = 1; ch < _audioCodecCtx->channels; ch++) {
+ memcpy(out, frm->extended_data[ch], plane_size);
+ out += plane_size;
+ }
+ }
+#endif
- av_free(output);
+ outSize = data_size;
+#ifdef GNASH_DEBUG_AUDIO_DECODING
+ log_debug(" decodeFrame | fmt: %d | fmt_name: %s | planar: %d | "
+ "plane_size: %d | outSize: %d",
+ _audioCodecCtx->sample_fmt, fmtname, planar, plane_size, outSize);
+#endif
+ } else {
+ if (tmp < 0)
+ log_error(_("avcodec_decode_audio returned %d."), tmp);
+ if (outSize < 2)
+ log_error(_("outputSize:%d after decoding %d bytes of input audio "
+ "data."), outputSize, inputSize);
+ log_error(_("Upgrading ffmpeg/libavcodec might fix this issue."));
+ outputSize = 0;
+ av_freep(&frm);
return NULL;
}
@@ -562,26 +592,27 @@ AudioDecoderFfmpeg::decodeFrame(const boost::uint8_t* input,
boost::uint8_t* resampledOutput = new boost::uint8_t[resampledFrameSize];
#ifdef GNASH_DEBUG_AUDIO_DECODING
- log_debug("Calling the resampler; resampleFactor:%d; "
- "ouput to 44100hz, 2channels, %dbytes; "
- "input is %dhz, %dchannels, %dbytes, %dsamples",
- resampleFactor,
- resampledFrameSize, _audioCodecCtx->sample_rate,
- _audioCodecCtx->channels, outSize, inSamples);
+ log_debug(" decodeFrame | Calling the resampler, resampleFactor: %d | "
+ "in %d hz %d ch %d bytes %d samples, %s fmt", resampleFactor,
+ _audioCodecCtx->sample_rate, _audioCodecCtx->channels, outSize,
+ inSamples, fmtname);
+ log_debug(" decodeFrame | out 44100 hz 2 ch %d bytes",
+ resampledFrameSize);
#endif
- int outSamples = _resampler.resample(outPtr, // input
- reinterpret_cast<boost::int16_t*>(resampledOutput), // output
- inSamples); // input..
+ int outSamples = _resampler.resample(frm->extended_data, // input
+ plane_size, // input
+ frm->nb_samples, // input
+ &resampledOutput); // output
+
+ // make sure to set outPtr *after* we use it as input to the resampler
+ outPtr = reinterpret_cast<boost::int16_t*>(resampledOutput);
#ifdef GNASH_DEBUG_AUDIO_DECODING
log_debug("resampler returned %d samples ", outSamples);
#endif
- // make sure to set outPtr *after* we use it as input to the resampler
- outPtr = reinterpret_cast<boost::int16_t*>(resampledOutput);
-
- av_free(output);
+ av_freep(&frm);
if (expectedMaxOutSamples < outSamples) {
log_error(_(" --- Computation of resampled samples (%d) < then the actual returned samples (%d)"),
@@ -608,9 +639,9 @@ AudioDecoderFfmpeg::decodeFrame(const boost::uint8_t* input,
}
else {
boost::uint8_t* newOutput = new boost::uint8_t[outSize];
- std::memcpy(newOutput, output, outSize);
+ std::memcpy(newOutput, outPtr, outSize);
outPtr = reinterpret_cast<boost::int16_t*>(newOutput);
- av_free(output);
+ av_freep(&frm);
}
outputSize = outSize;
@@ -645,7 +676,8 @@ AudioDecoderFfmpeg::parseInput(const boost::uint8_t* input,
// democratic value for a chunk to decode...
// @todo this might be constrained by codec id, check that !
- // NOTE: AVCODEC_MAX_AUDIO_FRAME_SIZE resulted bigger
+ // NOTE: AVCODEC_MAX_AUDIO_FRAME_SIZE (192000, deprecated replaced with
+ // MAX_AUDIO_FRAME_SIZE) resulted bigger
// than avcodec_decode_audio could handle, resulting
// in eventSoundTest1.swf regression.
//static const unsigned int maxFrameSize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
diff --git a/libmedia/ffmpeg/AudioResamplerFfmpeg.cpp b/libmedia/ffmpeg/AudioResamplerFfmpeg.cpp
index 98ac8b5..41673b4 100644
--- a/libmedia/ffmpeg/AudioResamplerFfmpeg.cpp
+++ b/libmedia/ffmpeg/AudioResamplerFfmpeg.cpp
@@ -19,6 +19,7 @@
//
#include "AudioResamplerFfmpeg.h"
+#include "utility.h"
#include "log.h"
#include <cmath>
@@ -33,48 +34,75 @@ AudioResamplerFfmpeg::AudioResamplerFfmpeg()
:_context(NULL)
{
}
-
-AudioResamplerFfmpeg::~AudioResamplerFfmpeg()
-{
- if ( _context ) {
- audio_resample_close( _context );
- }
+AudioResamplerFfmpeg::~AudioResamplerFfmpeg() {
+ if (_context) {
+#ifdef HAVE_SWRESAMPLE_H
+ swr_free(&_context);
+#elif HAVE_AVRESAMPLE_H
+ avresample_close(_context);
+ avresample_free(&_context);
+#else
+ audio_resample_close(_context);
+#endif
+ }
}
bool
-AudioResamplerFfmpeg::init( AVCodecContext* ctx )
-{
- if ( (ctx->sample_rate != 44100) || (ctx->channels != 2) ) {
- if ( ! _context ) {
-#if LIBAVCODEC_VERSION_MAJOR >= 53
- _context = av_audio_resample_init(
- 2, ctx->channels, 44100, ctx->sample_rate,
- AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16,
- 16, 10, 0, 0.8
+AudioResamplerFfmpeg::init(AVCodecContext* ctx) {
+ if ((ctx->sample_rate != 44100) ||
+#if defined(HAVE_SWRESAMPLE_H) || defined(HAVE_AVRESAMPLE_H)
+ (ctx->sample_fmt != AV_SAMPLE_FMT_S16) ||
+#endif
+ (ctx->channels != 2)) {
+ if (! _context) {
+#ifdef HAVE_SWRESAMPLE_H
+ _context = swr_alloc();
+#elif HAVE_AVRESAMPLE_H
+ _context = avresample_alloc_context();
#else
- _context = audio_resample_init(
- 2, ctx->channels, 44100, ctx->sample_rate
+ _context = av_audio_resample_init(2, ctx->channels,
+ 44100, ctx->sample_rate,
+ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16,
+ 16, 10, 0, 0.8);
+#endif
+#if defined(HAVE_SWRESAMPLE_H) || defined(HAVE_AVRESAMPLE_H)
+ av_opt_set_int(_context, "in_channel_layout",
+ av_get_default_channel_layout(ctx->channels), 0);
+ av_opt_set_int(_context, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
+ av_opt_set_int(_context, "in_sample_rate", ctx->sample_rate, 0);
+ av_opt_set_int(_context, "out_sample_rate", 44100, 0);
+ av_opt_set_int(_context, "in_sample_fmt", ctx->sample_fmt, 0);
+ av_opt_set_int(_context, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
#endif
- );
+#ifdef HAVE_SWRESAMPLE_H
+ swr_init(_context);
+#elif HAVE_AVRESAMPLE_H
+ avresample_open(_context);
+#endif
+ }
+ return true;
}
-
- return true;
- }
-
- return false;
+ return false;
}
int
-AudioResamplerFfmpeg::resample(
- boost::int16_t* input,
- boost::int16_t* output,
- int samples
- )
-{
- return audio_resample( _context, output, input, samples );
+AudioResamplerFfmpeg::resample(boost::uint8_t** input, int plane_size,
+ int samples, boost::uint8_t** output) {
+#ifdef HAVE_SWRESAMPLE_H
+ return swr_convert(_context,
+ output, MAX_AUDIO_FRAME_SIZE,
+ const_cast<const uint8_t**>(input), samples);
+#elif HAVE_AVRESAMPLE_H
+ return avresample_convert(_context,
+ output, 0, MAX_AUDIO_FRAME_SIZE,
+ input, plane_size, samples);
+#else
+ UNUSED( plane_size );
+ return audio_resample(_context, reinterpret_cast<short*>(*output),
+ reinterpret_cast<short*>(*input), samples);
+#endif
}
-
} // gnash.media.ffmpeg namespace
} // gnash.media namespace
} // namespace gnash
diff --git a/libmedia/ffmpeg/AudioResamplerFfmpeg.h b/libmedia/ffmpeg/AudioResamplerFfmpeg.h
index e77aec4..3dc2748 100644
--- a/libmedia/ffmpeg/AudioResamplerFfmpeg.h
+++ b/libmedia/ffmpeg/AudioResamplerFfmpeg.h
@@ -56,21 +56,29 @@ public:
/// @param input
/// A pointer to the audio data that needs resampling
///
- /// @param output
- /// A pointer to where the resampled output should be placed
+ /// @param plane_size
+ /// Input plane/line size
///
/// @param samples
/// Number of samples in the audio
///
+ /// @param output
+ /// A pointer to where the resampled output should be placed
+ ///
/// @return the number of samples in the output data.
///
- DSOEXPORT int resample(
- boost::int16_t* input, boost::int16_t* output, int samples
- );
+ DSOEXPORT int resample(boost::uint8_t** input, int plane_size,
+ int samples, boost::uint8_t** output);
private:
- // The container of the resample format information.
- ReSampleContext* _context;
+ // The container of the resample format information.
+#ifdef HAVE_SWRESAMPLE_H
+ SwrContext* _context;
+#elif HAVE_AVRESAMPLE_H
+ AVAudioResampleContext* _context;
+#else
+ ReSampleContext* _context;
+#endif
};
} // gnash.media.ffmpeg namespace
diff --git a/libmedia/ffmpeg/MediaHandlerFfmpeg.cpp b/libmedia/ffmpeg/MediaHandlerFfmpeg.cpp
index f55c3ba..2c13eaf 100644
--- a/libmedia/ffmpeg/MediaHandlerFfmpeg.cpp
+++ b/libmedia/ffmpeg/MediaHandlerFfmpeg.cpp
@@ -44,7 +44,7 @@ MediaHandlerFfmpeg::description() const
std::ostringstream ss;
const boost::uint32_t ver = avcodec_version();
ss << "FFmpeg (avcodec version: " << (ver >> 16) << "."
- << (ver & 0xff00 >> 8) << "."
+ << ((ver & 0xff00) >> 8) << "."
<< (ver & 0xff) << ")";
return ss.str();
}
diff --git a/libmedia/ffmpeg/MediaParserFfmpeg.cpp b/libmedia/ffmpeg/MediaParserFfmpeg.cpp
index d6e6902..f7cdf2e 100644
--- a/libmedia/ffmpeg/MediaParserFfmpeg.cpp
+++ b/libmedia/ffmpeg/MediaParserFfmpeg.cpp
@@ -344,8 +344,10 @@ MediaParserFfmpeg::initializeParser()
{
av_register_all(); // TODO: needs to be invoked only once ?
+#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52,107,0)
_byteIOCxt.buffer = NULL;
-
+#endif
+
_inputFmt = probeStream();
#ifdef GNASH_ALLOW_VCODEC_ENV
@@ -366,7 +368,11 @@ MediaParserFfmpeg::initializeParser()
// which isn't needed.
_byteIOBuffer.reset(new unsigned char[byteIOBufferSize]);
+#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52,107,0)
init_put_byte(&_byteIOCxt,
+#else
+ _avIOCxt = avio_alloc_context(
+#endif
_byteIOBuffer.get(), // buffer
byteIOBufferSize, // buffer size
0, // write flags
@@ -376,7 +382,11 @@ MediaParserFfmpeg::initializeParser()
MediaParserFfmpeg::seekMediaWrapper // seeker callback
);
+#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52,107,0)
_byteIOCxt.is_streamed = 1;
+#else
+ _avIOCxt->seekable = 0;
+#endif
#if !defined(LIBAVCODEC_VERSION_MAJOR) || LIBAVCODEC_VERSION_MAJOR < 52
// Needed for Lenny.
@@ -387,12 +397,19 @@ MediaParserFfmpeg::initializeParser()
assert(_formatCtx);
+#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52,107,0)
// Otherwise av_open_input_stream will reallocate the context.
AVFormatParameters ap;
std::memset(&ap, 0, sizeof ap);
ap.prealloced_context = 1;
if (av_open_input_stream(&_formatCtx, &_byteIOCxt, "", _inputFmt, &ap) < 0)
+#else
+
+ _formatCtx->pb = _avIOCxt;
+
+ if (avformat_open_input(&_formatCtx, "", _inputFmt, NULL) < 0)
+#endif
{
throw IOException("MediaParserFfmpeg couldn't open input stream");
}
@@ -400,10 +417,17 @@ MediaParserFfmpeg::initializeParser()
#if defined(LIBAVCODEC_VERSION_MAJOR) && LIBAVCODEC_VERSION_MAJOR >= 52
// Note: in at least some versions of ffmpeg, av_open_input_stream does
// not parse metadata; not sure why.
+#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51,5,0)
AVMetadata* md = _formatCtx->metadata;
if (md) {
AVMetadataTag* tag = av_metadata_get(md, "album", 0,
AV_METADATA_MATCH_CASE);
+#else
+ AVDictionary* md = _formatCtx->metadata;
+ if (md) {
+ AVDictionaryEntry* tag = av_dict_get(md, "album", 0,
+ AV_DICT_MATCH_CASE);
+#endif
if (tag && tag->value) {
setId3Info(&Id3Info::album, std::string(tag->value),
_id3Object);
@@ -474,7 +498,7 @@ MediaParserFfmpeg::initializeParser()
#else
boost::uint64_t duration = _videoStream->duration;
#endif
- if (duration == AV_NOPTS_VALUE) {
+ if (duration == static_cast<boost::uint64_t>(AV_NOPTS_VALUE)) {
log_error(_("Duration of video stream unknown"));
duration=0; // TODO: guess!
} else {
@@ -503,7 +527,7 @@ MediaParserFfmpeg::initializeParser()
#else
boost::uint64_t duration = _audioStream->duration;
#endif
- if (duration == AV_NOPTS_VALUE) {
+ if (duration == static_cast<boost::uint64_t>(AV_NOPTS_VALUE)) {
log_error(_("Duration of audio stream unknown to ffmpeg"));
duration=0; // TODO: guess!
}
@@ -601,7 +625,7 @@ MediaParserFfmpeg::seekMedia(boost::int64_t offset, int whence)
else if (whence == SEEK_END)
{
// New position is offset + end of file
- log_unimpl("MediaParserFfmpeg seek from end of file");
+ LOG_ONCE(log_unimpl("MediaParserFfmpeg seek from end of file"));
// This is (most likely) a streamed file, so we can't seek to the end!
// Instead we seek to byteIOBufferSize bytes... seems to work fine...
_stream->seek(byteIOBufferSize);
@@ -611,7 +635,7 @@ MediaParserFfmpeg::seekMedia(boost::int64_t offset, int whence)
{
// ffmpeg uses whence=AVSEEK_SIZE and offset=0 to request
// stream size !
- log_unimpl("MediaParserFfmpeg: unsupported whence value %d", whence);
+ LOG_ONCE(log_unimpl("MediaParserFfmpeg: unsupported whence value %d", whence));
return -1;
}
@@ -620,30 +644,34 @@ MediaParserFfmpeg::seekMedia(boost::int64_t offset, int whence)
}
boost::uint16_t
-MediaParserFfmpeg::SampleFormatToSampleSize(SampleFormat fmt)
+MediaParserFfmpeg::SampleFormatToSampleSize(AVSampleFormat fmt)
{
+#if LIBAVUTIL_VERSION_INT > AV_VERSION_INT(51,4,0)
+ return av_get_bytes_per_sample(fmt);
+#else
switch (fmt)
{
- case SAMPLE_FMT_U8: // unsigned 8 bits
+ case AV_SAMPLE_FMT_U8: // unsigned 8 bits
return 1;
- case SAMPLE_FMT_S16: // signed 16 bits
- case SAMPLE_FMT_FLT: // float
+ case AV_SAMPLE_FMT_S16: // signed 16 bits
+ case AV_SAMPLE_FMT_FLT: // float
return 2;
#if !defined (LIBAVCODEC_VERSION_MAJOR) || LIBAVCODEC_VERSION_MAJOR < 52
// Was dropped for version 52.0.0
- case SAMPLE_FMT_S24: // signed 24 bits
+ case AV_SAMPLE_FMT_S24: // signed 24 bits
return 3;
#endif
- case SAMPLE_FMT_S32: // signed 32 bits
+ case AV_SAMPLE_FMT_S32: // signed 32 bits
return 4;
- case SAMPLE_FMT_NONE:
+ case AV_SAMPLE_FMT_NONE:
default:
return 8; // arbitrary value
}
+#endif
}
diff --git a/libmedia/ffmpeg/MediaParserFfmpeg.h b/libmedia/ffmpeg/MediaParserFfmpeg.h
index 4e410d8..a14cfb6 100644
--- a/libmedia/ffmpeg/MediaParserFfmpeg.h
+++ b/libmedia/ffmpeg/MediaParserFfmpeg.h
@@ -154,7 +154,13 @@ private:
AVStream* _audioStream;
/// ?
- ByteIOContext _byteIOCxt;
+#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52,107,0)
+// AVIOContext was introduced a bit earlier but without version bump, so let's
+// be safe
+ ByteIOContext _byteIOCxt;
+#else
+ AVIOContext* _avIOCxt;
+#endif
/// Size of the ByteIO context buffer
//
@@ -172,7 +178,7 @@ private:
//
/// TODO: move somewhere in ffmpeg utils..
///
- boost::uint16_t SampleFormatToSampleSize(SampleFormat fmt);
+ boost::uint16_t SampleFormatToSampleSize(AVSampleFormat fmt);
/// Make an EncodedVideoFrame from an AVPacket and push to buffer
//
diff --git a/libmedia/ffmpeg/VideoConverterFfmpeg.cpp b/libmedia/ffmpeg/VideoConverterFfmpeg.cpp
index 9680524..5247ce3 100644
--- a/libmedia/ffmpeg/VideoConverterFfmpeg.cpp
+++ b/libmedia/ffmpeg/VideoConverterFfmpeg.cpp
@@ -162,7 +162,8 @@ VideoConverterFfmpeg::convert(const ImgBuf& src)
#endif
- AVPicture srcpicture = {{src.data, 0, 0, 0}, {src.stride[0], 0, 0, 0}};
+ AVPicture srcpicture = {{src.data, 0, 0, 0},
+ {static_cast<int>(src.stride[0]), 0, 0, 0}};
int bufsize = avpicture_get_size(dst_pixFmt, width, height);
diff --git a/libmedia/ffmpeg/VideoDecoderFfmpeg.cpp b/libmedia/ffmpeg/VideoDecoderFfmpeg.cpp
index 40a5c80..5c850b8 100644
--- a/libmedia/ffmpeg/VideoDecoderFfmpeg.cpp
+++ b/libmedia/ffmpeg/VideoDecoderFfmpeg.cpp
@@ -53,9 +53,13 @@ namespace {
void clear_vaapi_context(AVCodecContext* avctx);
void reset_context(AVCodecContext* avctx, VaapiContextFfmpeg* vactx = 0);
PixelFormat get_format(AVCodecContext* avctx, const PixelFormat* fmt);
+#if LIBAVCODEC_VERSION_MAJOR >= 55
+ int get_buffer(AVCodecContext* avctx, AVFrame* pic, int flags);
+#else
int get_buffer(AVCodecContext* avctx, AVFrame* pic);
int reget_buffer(AVCodecContext* avctx, AVFrame* pic);
- void release_buffer(AVCodecContext *avctx, AVFrame *pic);
+ void release_buffer(AVCodecContext* avctx, AVFrame* pic);
+#endif
}
#ifdef HAVE_SWSCALE_H
@@ -117,7 +121,7 @@ VideoDecoderFfmpeg::VideoDecoderFfmpeg(videoCodecType format, int width, int hei
_videoCodec(NULL)
{
- CodecID codec_id = flashToFfmpegCodec(format);
+ CODECID codec_id = flashToFfmpegCodec(format);
init(codec_id, width, height);
}
@@ -127,13 +131,13 @@ VideoDecoderFfmpeg::VideoDecoderFfmpeg(const VideoInfo& info)
_videoCodec(NULL)
{
- CodecID codec_id = CODEC_ID_NONE;
+ CODECID codec_id = CODEC_ID_NONE;
if ( info.type == CODEC_TYPE_FLASH )
{
codec_id = flashToFfmpegCodec(static_cast<videoCodecType>(info.codec));
}
- else codec_id = static_cast<CodecID>(info.codec);
+ else codec_id = static_cast<CODECID>(info.codec);
// This would cause nasty segfaults.
if (codec_id == CODEC_ID_NONE)
@@ -167,11 +171,14 @@ VideoDecoderFfmpeg::VideoDecoderFfmpeg(const VideoInfo& info)
}
void
-VideoDecoderFfmpeg::init(enum CodecID codecId, int /*width*/, int /*height*/,
+VideoDecoderFfmpeg::init(enum CODECID codecId, int /*width*/, int /*height*/,
boost::uint8_t* extradata, int extradataSize)
{
// Init the avdecoder-decoder
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52,6,2)
+ // Starting from this version avcodec_register calls avcodec_init
avcodec_init();
+#endif
avcodec_register_all();// change this to only register need codec?
_videoCodec = avcodec_find_decoder(codecId);
@@ -180,7 +187,11 @@ VideoDecoderFfmpeg::init(enum CodecID codecId, int /*width*/, int /*height*/,
throw MediaException(_("libavcodec can't decode this video format"));
}
+#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(53,8,0)
+ _videoCodecCtx.reset(new CodecContextWrapper(avcodec_alloc_context3(_videoCodec)));
+#else
_videoCodecCtx.reset(new CodecContextWrapper(avcodec_alloc_context()));
+#endif
if (!_videoCodecCtx->getContext()) {
throw MediaException(_("libavcodec couldn't allocate context"));
}
@@ -191,9 +202,13 @@ VideoDecoderFfmpeg::init(enum CodecID codecId, int /*width*/, int /*height*/,
ctx->extradata_size = extradataSize;
ctx->get_format = get_format;
+#if LIBAVCODEC_VERSION_MAJOR >= 55
+ ctx->get_buffer2 = get_buffer;
+#else
ctx->get_buffer = get_buffer;
ctx->reget_buffer = reget_buffer;
ctx->release_buffer = release_buffer;
+#endif
#ifdef HAVE_VA_VA_H
if (vaapi_is_enabled()) {
@@ -203,7 +218,11 @@ VideoDecoderFfmpeg::init(enum CodecID codecId, int /*width*/, int /*height*/,
}
#endif
+#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(53,8,0)
+ int ret = avcodec_open2(ctx, _videoCodec, NULL);
+#else
int ret = avcodec_open(ctx, _videoCodec);
+#endif
if (ret < 0) {
boost::format msg = boost::format(_("libavcodec "
"failed to initialize FFMPEG "
@@ -360,7 +379,7 @@ VideoDecoderFfmpeg::decode(const boost::uint8_t* input,
#if LIBAVCODEC_VERSION_MAJOR >= 53
AVPacket pkt;
av_init_packet(&pkt);
- pkt.data = (uint8_t*) input;
+ pkt.data = const_cast<uint8_t*>(input);
pkt.size = input_size;
avcodec_decode_video2(_videoCodecCtx->getContext(), frame, &bytes,
&pkt);
@@ -411,7 +430,7 @@ VideoDecoderFfmpeg::peek()
}
/* public static */
-enum CodecID
+enum CODECID
VideoDecoderFfmpeg::flashToFfmpegCodec(videoCodecType format)
{
// Find the decoder and init the parser
@@ -514,10 +533,18 @@ get_format(AVCodecContext* avctx, const PixelFormat* fmt)
/// AVCodecContext.get_buffer() implementation
int
+#if LIBAVCODEC_VERSION_MAJOR >= 55
+get_buffer(AVCodecContext* avctx, AVFrame* pic, int flags)
+#else
get_buffer(AVCodecContext* avctx, AVFrame* pic)
+#endif
{
VaapiContextFfmpeg* const vactx = get_vaapi_context(avctx);
+#if LIBAVCODEC_VERSION_MAJOR >= 55
+ if (!vactx) return avcodec_default_get_buffer2(avctx, pic, flags);
+#else
if (!vactx) return avcodec_default_get_buffer(avctx, pic);
+#endif
#ifdef HAVE_VA_VA_H
if (!vactx->initDecoder(avctx->width, avctx->height)) return -1;
@@ -529,13 +556,18 @@ get_buffer(AVCodecContext* avctx, AVFrame* pic)
static unsigned int pic_num = 0;
pic->type = FF_BUFFER_TYPE_USER;
+#if LIBAVCODEC_VERSION_MAJOR < 54
+ // This field has been unused for longer but has been removed with
+ // libavcodec 54.
pic->age = ++pic_num - surface->getPicNum();
+#endif
surface->setPicNum(pic_num);
return 0;
#endif
return -1;
}
+#if LIBAVCODEC_VERSION_MAJOR < 55
/// AVCodecContext.reget_buffer() implementation
int
reget_buffer(AVCodecContext* avctx, AVFrame* pic)
@@ -567,6 +599,7 @@ release_buffer(AVCodecContext *avctx, AVFrame *pic)
pic->data[3] = NULL;
#endif
}
+#endif
}
diff --git a/libmedia/ffmpeg/VideoDecoderFfmpeg.h b/libmedia/ffmpeg/VideoDecoderFfmpeg.h
index 2df7754..d471a6d 100644
--- a/libmedia/ffmpeg/VideoDecoderFfmpeg.h
+++ b/libmedia/ffmpeg/VideoDecoderFfmpeg.h
@@ -27,7 +27,6 @@
#include <vector>
#include <memory>
#include "dsodefs.h" //For DSOEXPORT
-#include "log.h"
#include "VideoDecoder.h"
#include "MediaParser.h" // for videoCodecType enum
#include "ffmpegHeaders.h"
@@ -70,7 +69,7 @@ private:
//
/// @return CODEC_ID_NONE for unsupported flash codecs
///
- static CodecID flashToFfmpegCodec(videoCodecType format);
+ static CODECID flashToFfmpegCodec(videoCodecType format);
/// \brief converts an video frame from (almost) any type to RGB24.
///
@@ -84,7 +83,7 @@ private:
std::auto_ptr<image::GnashImage> frameToImage(AVCodecContext* srcCtx,
const AVFrame& srcFrame);
- void init(enum CodecID format, int width, int height,
+ void init(enum CODECID format, int width, int height,
boost::uint8_t* extradata=0, int extradataSize=0);
std::auto_ptr<image::GnashImage> decode(const boost::uint8_t* input,
diff --git a/libmedia/ffmpeg/VideoDecoderFfmpegVaapi.cpp b/libmedia/ffmpeg/VideoDecoderFfmpegVaapi.cpp
index ba2f777..aac3626 100644
--- a/libmedia/ffmpeg/VideoDecoderFfmpegVaapi.cpp
+++ b/libmedia/ffmpeg/VideoDecoderFfmpegVaapi.cpp
@@ -31,7 +31,7 @@ namespace media {
namespace ffmpeg {
/// Translates FFmpeg Codec ID to VAProfile
-static VAProfile get_profile(enum CodecID codec_id)
+static VAProfile get_profile(enum CODECID codec_id)
{
static const int mpeg2_profiles[] =
{ VAProfileMPEG2Main, VAProfileMPEG2Simple, -1 };
@@ -94,7 +94,7 @@ void vaapi_set_surface(AVFrame *pic, VaapiSurfaceFfmpeg *surface)
}
}
-VaapiContextFfmpeg::VaapiContextFfmpeg(enum CodecID codec_id)
+VaapiContextFfmpeg::VaapiContextFfmpeg(enum CODECID codec_id)
: _context(new VaapiContext(get_profile(codec_id), VAEntrypointVLD))
{
// FFmpeg's vaapi_context must be zero-initialized
@@ -115,7 +115,7 @@ bool VaapiContextFfmpeg::initDecoder(unsigned int width, unsigned int height)
return true;
}
-VaapiContextFfmpeg *VaapiContextFfmpeg::create(enum CodecID codec_id)
+VaapiContextFfmpeg *VaapiContextFfmpeg::create(enum CODECID codec_id)
{
if (!vaapi_is_enabled())
return NULL;
diff --git a/libmedia/ffmpeg/VideoDecoderFfmpegVaapi.h b/libmedia/ffmpeg/VideoDecoderFfmpegVaapi.h
index c365171..25e8a95 100644
--- a/libmedia/ffmpeg/VideoDecoderFfmpegVaapi.h
+++ b/libmedia/ffmpeg/VideoDecoderFfmpegVaapi.h
@@ -29,6 +29,12 @@ extern "C" {
#include <libavcodec/vaapi.h>
}
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,18,102)
+#define CODECID AVCodecID
+#else
+#define CODECID CodecID
+#endif
+
namespace gnash {
namespace media {
namespace ffmpeg {
@@ -62,14 +68,14 @@ class VaapiContextFfmpeg : public vaapi_context {
boost::shared_ptr<VaapiContext> _context;
public:
- VaapiContextFfmpeg(enum CodecID codec_id);
+ VaapiContextFfmpeg(enum CODECID codec_id);
bool initDecoder(unsigned int width, unsigned int height);
VaapiSurfaceFfmpeg *getSurface()
{ return new VaapiSurfaceFfmpeg(_context->acquireSurface(), _context); }
- static VaapiContextFfmpeg *create(enum CodecID codec_id);
+ static VaapiContextFfmpeg *create(enum CODECID codec_id);
};
} // gnash.media.ffmpeg namespace
diff --git a/libmedia/ffmpeg/ffmpegHeaders.h b/libmedia/ffmpeg/ffmpegHeaders.h
index 65a8d0c..5cd3785 100644
--- a/libmedia/ffmpeg/ffmpegHeaders.h
+++ b/libmedia/ffmpeg/ffmpegHeaders.h
@@ -38,6 +38,8 @@
#endif
#endif
+#define MAX_AUDIO_FRAME_SIZE 192000
+
#ifdef HAVE_FFMPEG_AVCODEC_H
extern "C" {
# include <ffmpeg/avcodec.h>
@@ -83,5 +85,67 @@ extern "C" {
#define HAVE_SWSCALE_H 1
#endif
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52,94,1)
+#define AV_SAMPLE_FMT_NONE SAMPLE_FMT_NONE
+#define AV_SAMPLE_FMT_U8 SAMPLE_FMT_U8
+#define AV_SAMPLE_FMT_S16 SAMPLE_FMT_S16
+#define AV_SAMPLE_FMT_S32 SAMPLE_FMT_S32
+#define AV_SAMPLE_FMT_FLT SAMPLE_FMT_FLT
+#define AV_SAMPLE_FMT_DBL SAMPLE_FMT_DBL
+
+#define AVSampleFormat SampleFormat
+#endif
+
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55,18,102)
+#define CODECID AVCodecID
+#else
+#define CODECID CodecID
+#endif
+
+#ifdef HAVE_SWRESAMPLE_H
+extern "C" {
+#include <swresample.h>
+}
+#endif
+
+#ifdef HAVE_FFMPEG_SWRESAMPLE_H
+extern "C" {
+#include <ffmpeg/swresample.h>
+}
+#define HAVE_SWRESAMPLE_H 1
+#endif
+
+#ifdef HAVE_LIBSWRESAMPLE_SWRESAMPLE_H
+extern "C" {
+#include <libswresample/swresample.h>
+}
+#define HAVE_SWRESAMPLE_H 1
+#endif
+
+#ifdef HAVE_AVRESAMPLE_H
+extern "C" {
+#include <avresample.h>
+}
+#endif
+
+#ifdef HAVE_LIBAV_AVRESAMPLE_H
+extern "C" {
+#include <libav/avresample.h>
+}
+#define HAVE_AVRESAMPLE_H 1
+#endif
+
+#ifdef HAVE_LIBAVRESAMPLE_AVRESAMPLE_H
+extern "C" {
+#include <libavresample/avresample.h>
+}
+#define HAVE_AVRESAMPLE_H 1
+#endif
+
+#ifdef HAVE_LIBAVUTIL_OPT_H
+extern "C" {
+#include <libavutil/opt.h>
+}
+#endif
#endif // GNASH_MEDIA_FFMPEG_HEADERS_H
diff --git a/libmedia/gst/AudioInputGst.cpp b/libmedia/gst/AudioInputGst.cpp
index 592d12d..7f8887b 100644
--- a/libmedia/gst/AudioInputGst.cpp
+++ b/libmedia/gst/AudioInputGst.cpp
@@ -22,6 +22,8 @@
#include "gnashconfig.h"
#endif
+#include "GlibDeprecated.h"
+
#include "gst/gst.h"
#include "AudioInputGst.h"
#include "log.h"
diff --git a/libmedia/gst/GlibDeprecated.h b/libmedia/gst/GlibDeprecated.h
new file mode 100644
index 0000000..d1b092a
--- /dev/null
+++ b/libmedia/gst/GlibDeprecated.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef GLIB_DEPRECATED_H
+#define GLIB_DEPRECATED_H
+
+// deprecated since 2.32: g_value_array_get_nth, g_value_array_free
+// gstreamer devs keep using GValueArray deprecated in favour of GArray
+// http://lists.freedesktop.org/archives/gstreamer-devel/2012-October/037539.html
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+#include <glib-object.h>
+#undef GLIB_DISABLE_DEPRECATION_WARNINGS
+
+#endif
diff --git a/libmedia/gst/MediaParserGst.cpp b/libmedia/gst/MediaParserGst.cpp
index 71f98c9..be34921 100644
--- a/libmedia/gst/MediaParserGst.cpp
+++ b/libmedia/gst/MediaParserGst.cpp
@@ -30,8 +30,6 @@
#include <fstream>
#define PUSHBUF_SIZE 1024
-//#define MIN_PROBE_SIZE (PUSHBUF_SIZE * 3)
-#define MIN_PROBE_SIZE 0
// #define GNASH_DEBUG_DATAFLOW
@@ -68,29 +66,11 @@ MediaParserGst::MediaParserGst(std::auto_ptr<IOChannel> stream)
_srcpad = swfdec_gst_connect_srcpad (typefind, srccaps);
gst_caps_unref(srccaps);
- if (!gst_element_set_state (_bin, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS) {
+ if (gst_element_set_state (_bin, GST_STATE_PLAYING) != GST_STATE_CHANGE_SUCCESS) {
throw GnashException(_("MediaParserGst could not change element state"));
}
- SimpleTimer timer;
-
- size_t counter = 0;
- while (!probingConditionsMet(timer) && !_stream->eof() && !_stream->bad()) {
-
- if (!pushGstBuffer()) {
- ++counter;
- }
- }
-
- log_debug(_("Needed %d dead iterations to detect audio type."), counter);
-
-#if 0
- if (! (_videoInfo.get() || _audioInfo.get()) ) {
- throw MediaException(_("MediaParserGst failed to detect any stream types."));
- }
-#endif
-
- if (!gst_element_set_state (_bin, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS) {
+ if (gst_element_set_state (_bin, GST_STATE_PLAYING) != GST_STATE_CHANGE_SUCCESS) {
throw MediaException(_("MediaParserGst could not change element state"));
}
@@ -249,22 +229,6 @@ MediaParserGst::rememberVideoFrame(EncodedVideoFrame* frame)
/// demuxer has signaled "no more pads", or when the first video and
/// audio streams have been found.
-bool MediaParserGst::foundAllStreams()
-{
- return _demux_probe_ended || (_videoInfo.get() && _audioInfo.get());
-}
-
-/// The idea here is that probingConditionsMet will return false, unless:
-/// a) all data types in the stream were found.
-/// b) The timer (currently for 1 second) has expired, if and only if we
-/// succeeded in pushing MIN_PROBE_SIZE bytes into the bin. This should
-/// protect low-bandwidth cases from stopping the probe early.
-
-bool MediaParserGst::probingConditionsMet(const SimpleTimer& timer)
-{
- return foundAllStreams() || (timer.expired() && getBytesLoaded() >= MIN_PROBE_SIZE);
-}
-
static void
print_caps(GstCaps* caps)
{
@@ -314,7 +278,7 @@ MediaParserGst::link_to_fakesink(GstPad* pad)
throw MediaException(_("MediaParserGst: couln't link fakesink"));
}
- if (!gst_element_set_state (_bin, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS) {
+ if (gst_element_set_state (_bin, GST_STATE_PLAYING) != GST_STATE_CHANGE_SUCCESS) {
throw GnashException(_("MediaParserGst could not change element state"));
}
}
@@ -370,7 +334,7 @@ MediaParserGst::cb_typefound(GstElement* typefind, guint /*probability*/,
g_signal_connect(demuxer, "no-more-pads",
G_CALLBACK(MediaParserGst::cb_no_more_pads), parser);
- if (!gst_element_set_state(parser->_bin, GST_STATE_PLAYING) ==
+ if (gst_element_set_state(parser->_bin, GST_STATE_PLAYING) !=
GST_STATE_CHANGE_SUCCESS) {
throw GnashException(_("MediaParserGst could not change "
"element state"));
@@ -525,7 +489,7 @@ void MediaParserGst::cb_pad_added(GstElement* /* element */, GstPad* new_pad,
gst_object_unref(GST_OBJECT(final_pad));
}
- if (!gst_element_set_state (parser->_bin, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS) {
+ if (gst_element_set_state (parser->_bin, GST_STATE_PLAYING) != GST_STATE_CHANGE_SUCCESS) {
throw GnashException(_("MediaParserGst could not change element state"));
}
}
diff --git a/libmedia/gst/MediaParserGst.h b/libmedia/gst/MediaParserGst.h
index 601835c..a6e47d5 100644
--- a/libmedia/gst/MediaParserGst.h
+++ b/libmedia/gst/MediaParserGst.h
@@ -128,10 +128,6 @@ public:
void rememberVideoFrame(EncodedVideoFrame* frame);
private:
- bool foundAllStreams();
-
- bool probingConditionsMet(const SimpleTimer& timer);
-
void link_to_fakesink(GstPad* pad);
static void cb_typefound (GstElement *typefind, guint probability,
diff --git a/libmedia/gst/VideoDecoderGst.cpp b/libmedia/gst/VideoDecoderGst.cpp
index 6cd9dd0..6f2bca3 100644
--- a/libmedia/gst/VideoDecoderGst.cpp
+++ b/libmedia/gst/VideoDecoderGst.cpp
@@ -93,7 +93,7 @@ VideoDecoderGst::VideoDecoderGst(videoCodecType codec_type,
caps = gst_caps_new_simple ("video/x-flash-screen",
NULL);
break;
- case 0:
+ case NO_VIDEO_CODEC:
throw MediaException(_("Video codec is zero. Streaming video expected later."));
break;
default:
diff --git a/libmedia/gst/VideoInputGst.cpp b/libmedia/gst/VideoInputGst.cpp
index 8f23c32..113d92a 100644
--- a/libmedia/gst/VideoInputGst.cpp
+++ b/libmedia/gst/VideoInputGst.cpp
@@ -21,6 +21,8 @@
#include "gnashconfig.h"
#endif
+#include "GlibDeprecated.h"
+
#include "VideoInputGst.h"
#include "log.h"
#include "GstUtil.h"
@@ -649,8 +651,6 @@ VideoInputGst::getSelectedCaps(gint dev_select)
GstMessage *message;
GnashWebcam *data_struct = _vidVect[dev_select];
- GstElement *element;
- element = data_struct->getElementPtr();
if (dev_select < 0 ||
static_cast<size_t>(dev_select) >= _vidVect.size()) {
@@ -1540,10 +1540,9 @@ VideoInputGst::play()
GstStateChangeReturn state;
GstBus *bus;
- gint ret;
//setup bus to watch pipeline for messages
bus = gst_pipeline_get_bus (GST_PIPELINE (webcam->_pipeline));
- ret = gst_bus_add_watch (bus, bus_call, webcam);
+ gst_bus_add_watch (bus, bus_call, webcam);
gst_object_unref (bus);
state = gst_element_set_state (webcam->_pipeline, GST_STATE_PLAYING);
diff --git a/libmedia/gst/swfdec_codec_gst.c b/libmedia/gst/swfdec_codec_gst.c
index 50aeff5..8be6067 100644
--- a/libmedia/gst/swfdec_codec_gst.c
+++ b/libmedia/gst/swfdec_codec_gst.c
@@ -112,8 +112,8 @@ swfdec_gst_feature_filter_parser (GstPluginFeature *feature, gpointer caps)
return swfdec_gst_feature_filter (feature, caps, "Parser", FALSE);
}
-
-
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
static int
swfdec_gst_compare_features (gconstpointer a_, gconstpointer b_)
{
@@ -127,6 +127,7 @@ swfdec_gst_compare_features (gconstpointer a_, gconstpointer b_)
return strcmp (gst_plugin_feature_get_name (a), gst_plugin_feature_get_name (b));
}
+#pragma GCC diagnostic pop
static GstElementFactory *
_swfdec_gst_get_factory (GstCaps *caps, GstPluginFeatureFilter filter)
@@ -356,6 +357,8 @@ swfdec_gst_decoder_finish (SwfdecGstDecoder *dec)
}
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
gboolean
swfdec_gst_decoder_push (SwfdecGstDecoder *dec, GstBuffer *buffer)
{
@@ -382,6 +385,7 @@ swfdec_gst_decoder_push (SwfdecGstDecoder *dec, GstBuffer *buffer)
SWFDEC_ERROR ("error %d pushing data", (int) ret);
return FALSE;
}
+#pragma GCC diagnostic pop
void
swfdec_gst_decoder_push_eos (SwfdecGstDecoder *dec)
diff --git a/librender/GnashTexture.cpp b/librender/GnashTexture.cpp
index 0299914..d024296 100644
--- a/librender/GnashTexture.cpp
+++ b/librender/GnashTexture.cpp
@@ -32,14 +32,15 @@
namespace gnash {
+struct gl_errors_t {
+ GLenum val;
+ const char *str;
+};
+
// Returns a string representation of an OpenGL error
static const char *gl_get_error_string(GLenum error)
{
- static const struct {
- GLenum val;
- const char *str;
- }
- gl_errors[] = {
+ gl_errors_t gl_errors[] = {
{ GL_NO_ERROR, "no error" },
{ GL_INVALID_ENUM, "invalid enumerant" },
{ GL_INVALID_VALUE, "invalid value" },
@@ -50,13 +51,12 @@ static const char *gl_get_error_string(GLenum error)
#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
{ GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "invalid framebuffer operation" },
#endif
- { ~0, NULL }
};
- int i;
- for (i = 0; gl_errors[i].str; i++) {
- if (gl_errors[i].val == error)
- return gl_errors[i].str;
+ for (gl_errors_t *it = boost::begin(gl_errors), *end = boost::end(gl_errors);
+ it != end; ++it) {
+ if (it->val == error)
+ return it->str;
}
return "unknown";
}
diff --git a/librender/Makefile.am b/librender/Makefile.am
index 3c86153..970d78d 100644
--- a/librender/Makefile.am
+++ b/librender/Makefile.am
@@ -44,10 +44,13 @@ AM_CPPFLAGS = -I.. \
GNASH_LIBS = \
$(top_builddir)/libcore/libgnashcore.la \
- $(top_builddir)/libmedia/libgnashmedia.la \
$(top_builddir)/libbase/libgnashbase.la \
$(NULL)
+if BUILD_LIBMEDIA
+GNASH_LIBS += $(top_builddir)/libmedia/libgnashmedia.la
+endif
+
instdir = $(includedir)/gnash
noinst_HEADERS = \
@@ -125,8 +128,11 @@ endif
clean-hook:
-rm -f core.*
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
+AM_LDFLAGS = $(CROSS_LDFLAGS)
+
if ENABLE_PCH
-AM_CXXFLAGS = $(PCH_FLAGS)
+AM_CXXFLAGS += $(PCH_FLAGS)
endif
# Remove libtool .la files
diff --git a/librender/agg/Renderer_agg.cpp b/librender/agg/Renderer_agg.cpp
index 0809767..12b4142 100644
--- a/librender/agg/Renderer_agg.cpp
+++ b/librender/agg/Renderer_agg.cpp
@@ -116,6 +116,10 @@ AGG resources
#include <climits>
#include <boost/scoped_array.hpp>
#include <boost/bind.hpp>
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wsign-compare"
#include <agg_rendering_buffer.h>
#include <agg_renderer_base.h>
#include <agg_pixfmt_gray.h>
@@ -138,6 +142,7 @@ AGG resources
#include <agg_renderer_primitives.h>
#include <agg_image_accessors.h>
#include <agg_alpha_mask_u8.h>
+#pragma GCC diagnostic pop
#include "Renderer_agg_style.h"
@@ -1022,6 +1027,8 @@ public:
void drawGlyph(const SWF::ShapeRecord& shape, const rgba& color,
const SWFMatrix& mat)
{
+ if (shape.subshapes().empty()) return;
+ assert(shape.subshapes().size() == 1);
// select relevant clipping bounds
if (shape.getBounds().is_null()) {
@@ -1032,7 +1039,7 @@ public:
if (_clipbounds_selected.empty()) return;
GnashPaths paths;
- apply_matrix_to_path(shape.paths(), paths, mat);
+ apply_matrix_to_path(shape.subshapes().front().paths(), paths, mat);
// If it's a mask, we don't need the rest.
if (m_drawing_mask) {
@@ -1050,7 +1057,7 @@ public:
StyleHandler sh;
build_agg_styles(sh, v, mat, SWFCxForm());
- draw_shape(-1, paths, agg_paths, sh, false);
+ draw_shape(paths, agg_paths, sh, false);
// NOTE: Do not use even-odd filling rule for glyphs!
@@ -1118,18 +1125,22 @@ public:
if (!bounds_in_clipping_area(cur_bounds.getRange()))
{
return; // no need to draw
- }
-
- const SWF::ShapeRecord::FillStyles& fillStyles = shape.fillStyles();
- const SWF::ShapeRecord::LineStyles& lineStyles = shape.lineStyles();
- const SWF::ShapeRecord::Paths& paths = shape.paths();
-
- // select ranges
- select_clipbounds(shape.getBounds(), xform.matrix);
+ }
+
+ for (SWF::ShapeRecord::Subshapes::const_iterator it = shape.subshapes().begin(),
+ end = shape.subshapes().end(); it != end; ++it ) {
- // render the DisplayObject's shape.
- drawShape(fillStyles, lineStyles, paths, xform.matrix,
- xform.colorTransform);
+ const SWF::ShapeRecord::FillStyles& fillStyles = it->fillStyles();
+ const SWF::ShapeRecord::LineStyles& lineStyles = it->lineStyles();
+ const SWF::ShapeRecord::Paths& paths = it->paths();
+
+ // select ranges
+ select_clipbounds(shape.getBounds(), xform.matrix);
+
+ // render the DisplayObject's subshape.
+ drawShape(fillStyles, lineStyles, paths, xform.matrix,
+ xform.colorTransform);
+ }
}
void drawShape(const std::vector<FillStyle>& FillStyles,
@@ -1145,7 +1156,7 @@ public:
if (!have_shape && !have_outline) {
// Early return for invisible character.
return;
- }
+ }
GnashPaths paths;
apply_matrix_to_path(objpaths, paths, mat);
@@ -1185,19 +1196,14 @@ public:
StyleHandler sh;
if (have_shape) build_agg_styles(sh, FillStyles, mat, cx);
- // We need to separate sub-shapes during rendering.
- const unsigned int subshape_count = count_sub_shapes(paths);
- for (unsigned int subshape=0; subshape<subshape_count; ++subshape)
- {
if (have_shape) {
- draw_shape(subshape, paths, agg_paths, sh, true);
+ draw_shape(paths, agg_paths, sh, true);
}
if (have_outline) {
- draw_outlines(subshape, paths, agg_paths_rounded,
+ draw_outlines(paths, agg_paths_rounded,
line_styles, cx, mat);
}
- }
// Clear selected clipbounds to ease debugging
_clipbounds_selected.clear();
@@ -1224,26 +1230,6 @@ public:
boost::bind(&Path::transform, _1, mat));
}
-
- /// A shape can have sub-shapes. This can happen when there are multiple
- /// layers of the same frame count. Flash combines them to one single shape.
- /// The problem with sub-shapes is, that outlines can be hidden by other
- /// layers so they must be rendered separately.
- unsigned int count_sub_shapes(const GnashPaths &path_in)
- {
- unsigned int sscount=1;
- const size_t pcnt = path_in.size();
-
- for (size_t pno=0; pno<pcnt; ++pno) {
- const Path& this_path = path_in[pno];
-
- if (this_path.m_new_shape)
- sscount++;
- }
-
- return sscount;
- }
-
// Version of buildPaths that uses rounded coordinates (pixel hinting)
// for line styles that want it.
// This is used for outlines which are aligned to the pixel grid to avoid
@@ -1431,7 +1417,7 @@ public:
/// @param subshape_id
/// Defines which subshape to draw. -1 means all subshapes.
///
- void draw_shape(int subshape_id, const GnashPaths &paths,
+ void draw_shape(const GnashPaths &paths,
const AggPaths& agg_paths,
StyleHandler& sh, bool even_odd) {
@@ -1443,7 +1429,7 @@ public:
scanline_type sl;
- draw_shape_impl<scanline_type> (subshape_id, paths, agg_paths,
+ draw_shape_impl<scanline_type> (paths, agg_paths,
sh, even_odd, sl);
} else {
@@ -1454,7 +1440,7 @@ public:
scanline_type sl(_alphaMasks.back().getMask());
- draw_shape_impl<scanline_type> (subshape_id, paths, agg_paths,
+ draw_shape_impl<scanline_type> (paths, agg_paths,
sh, even_odd, sl);
}
@@ -1465,7 +1451,7 @@ public:
/// one with and one without an alpha mask. This makes drawing without masks
/// much faster.
template <class scanline_type>
- void draw_shape_impl(int subshape_id, const GnashPaths &paths,
+ void draw_shape_impl(const GnashPaths &paths,
const AggPaths& agg_paths,
StyleHandler& sh, bool even_odd, scanline_type& sl) {
/*
@@ -1507,8 +1493,6 @@ public:
applyClipBox<ras_type> (rasc, *bounds);
- int current_subshape=0;
-
// push paths to AGG
const size_t pcount = paths.size();
@@ -1519,19 +1503,11 @@ public:
const_cast<agg::path_storage&>(agg_paths[pno]);
agg::conv_curve<agg::path_storage> curve(this_path_agg);
-
- if (this_path_gnash.m_new_shape) ++current_subshape;
-
- if ((subshape_id >= 0) && (current_subshape!=subshape_id)) {
- // Skip this path as it is not part of the requested sub-shape.
- continue;
- }
-
+
if ((this_path_gnash.m_fill0==0) && (this_path_gnash.m_fill1==0)) {
// Skip this path as it contains no fill style
continue;
}
-
// Tell the rasterizer which styles the following path will use.
// The good thing is, that it already supports two fill styles out of
@@ -1543,7 +1519,7 @@ public:
rasc.add_path(curve);
}
-
+
agg::render_scanlines_compound_layered(rasc, sl, rbase, alloc, sh);
}
@@ -1651,7 +1627,7 @@ public:
/// Just like draw_shapes() except that it draws an outline.
- void draw_outlines(int subshape_id, const GnashPaths &paths,
+ void draw_outlines(const GnashPaths &paths,
const AggPaths& agg_paths,
const std::vector<LineStyle> &line_styles, const SWFCxForm& cx,
const SWFMatrix& linestyle_matrix) {
@@ -1664,7 +1640,7 @@ public:
scanline_type sl;
- draw_outlines_impl<scanline_type> (subshape_id, paths, agg_paths,
+ draw_outlines_impl<scanline_type> (paths, agg_paths,
line_styles, cx, linestyle_matrix, sl);
} else {
@@ -1675,7 +1651,7 @@ public:
scanline_type sl(_alphaMasks.back().getMask());
- draw_outlines_impl<scanline_type> (subshape_id, paths, agg_paths,
+ draw_outlines_impl<scanline_type> (paths, agg_paths,
line_styles, cx, linestyle_matrix, sl);
}
@@ -1685,7 +1661,7 @@ public:
/// Template for draw_outlines(), see draw_shapes_impl().
template <class scanline_type>
- void draw_outlines_impl(int subshape_id, const GnashPaths &paths,
+ void draw_outlines_impl(const GnashPaths &paths,
const AggPaths& agg_paths,
const std::vector<LineStyle> &line_styles, const SWFCxForm& cx,
const SWFMatrix& linestyle_matrix, scanline_type& sl) {
@@ -1722,8 +1698,6 @@ public:
applyClipBox<ras_type> (ras, *bounds);
- int current_subshape=0;
-
for (size_t pno=0, pcount=paths.size(); pno<pcount; ++pno) {
const Path& this_path_gnash = paths[pno];
@@ -1731,14 +1705,6 @@ public:
agg::path_storage &this_path_agg =
const_cast<agg::path_storage&>(agg_paths[pno]);
- if (this_path_gnash.m_new_shape)
- ++current_subshape;
-
- if ((subshape_id>=0) && (current_subshape!=subshape_id)) {
- // Skip this path as it is not part of the requested sub-shape.
- continue;
- }
-
if (this_path_gnash.m_line==0) {
// Skip this path as it contains no line style
continue;
@@ -1747,7 +1713,7 @@ public:
agg::conv_curve< agg::path_storage > curve(this_path_agg); // to render curves
agg::conv_stroke< agg::conv_curve < agg::path_storage > >
stroke(curve); // to get an outline
-
+
const LineStyle& lstyle = line_styles[this_path_gnash.m_line-1];
int thickness = lstyle.getThickness();
diff --git a/librender/agg/Renderer_agg.h b/librender/agg/Renderer_agg.h
index 0c88c7c..f95c4ad 100644
--- a/librender/agg/Renderer_agg.h
+++ b/librender/agg/Renderer_agg.h
@@ -30,7 +30,7 @@ class Renderer_agg_base : public Renderer
{
private:
- unsigned char *_testBuffer; // buffer used by initTestBuffer() only
+ unsigned char *_testBuffer, *_testBufferTmp; // buffers used by initTestBuffer() only
public:
@@ -50,7 +50,14 @@ public:
virtual bool initTestBuffer(unsigned width, unsigned height) {
int size = width * height * getBytesPerPixel();
- _testBuffer = static_cast<unsigned char *>(realloc(_testBuffer, size));
+ _testBufferTmp = static_cast<unsigned char *>(realloc(_testBuffer, size));
+ if (_testBufferTmp == NULL) {
+ log_error(_("Memory reallocation error"));
+ return false;
+ } else {
+ _testBuffer = _testBufferTmp;
+ }
+
memset(_testBuffer, 0, size);
printf("Renderer Test memory at: %p\n", _testBuffer);
diff --git a/librender/agg/Renderer_agg_style.h b/librender/agg/Renderer_agg_style.h
index 7920f05..64b06d5 100644
--- a/librender/agg/Renderer_agg_style.h
+++ b/librender/agg/Renderer_agg_style.h
@@ -25,6 +25,8 @@
#include <vector>
#include <boost/ptr_container/ptr_vector.hpp>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#include <agg_gradient_lut.h>
#include <agg_color_rgba.h>
#include <agg_color_gray.h>
@@ -37,7 +39,7 @@
#include <agg_span_image_filter_rgba.h>
#include <agg_pixfmt_rgb.h>
#include <agg_pixfmt_rgba.h>
-#include <iostream>
+#pragma GCC diagnostic pop
#include "LinearRGB.h"
#include "Renderer_agg_bitmap.h"
diff --git a/librender/cairo/Renderer_cairo.cpp b/librender/cairo/Renderer_cairo.cpp
index 99c1301..c597dd4 100644
--- a/librender/cairo/Renderer_cairo.cpp
+++ b/librender/cairo/Renderer_cairo.cpp
@@ -950,31 +950,6 @@ Renderer_cairo::draw_subshape(const PathVec& path_vec, const SWFMatrix& mat,
draw_outlines(path_vec, line_styles, cx, mat);
}
-
-std::vector<PathVec::const_iterator>
-Renderer_cairo::find_subshapes(const PathVec& path_vec)
-{
- std::vector<PathVec::const_iterator> subshapes;
-
- PathVec::const_iterator it = path_vec.begin();
- PathVec::const_iterator end = path_vec.end();
-
- subshapes.push_back(it);
- ++it;
-
- for (;it != end; ++it) {
- const Path& cur_path = *it;
-
- if (cur_path.m_new_shape) {
- subshapes.push_back(it);
- }
- }
-
- subshapes.push_back(end);
-
- return subshapes;
-}
-
void
Renderer_cairo::draw_mask(const PathVec& path_vec)
{
@@ -1011,40 +986,23 @@ Renderer_cairo::apply_matrix_to_paths(std::vector<Path>& paths,
void
Renderer_cairo::drawShape(const SWF::ShapeRecord& shape, const Transform& xform)
{
- const PathVec& path_vec = shape.paths();
-
- if (!path_vec.size()) {
- return;
- }
-
cairo_set_fill_rule(_cr, CAIRO_FILL_RULE_EVEN_ODD); // TODO: Move to init
-
- if (_drawing_mask) {
- PathVec scaled_path_vec = path_vec;
-
- apply_matrix_to_paths(scaled_path_vec, xform.matrix);
- draw_mask(scaled_path_vec);
- return;
- }
CairoScopeMatrix mat_transformer(_cr, xform.matrix);
- std::vector<PathVec::const_iterator> subshapes = find_subshapes(path_vec);
-
- const std::vector<FillStyle>& FillStyles = shape.fillStyles();
- const std::vector<LineStyle>& line_styles = shape.lineStyles();
+ for (SWF::ShapeRecord::Subshapes::const_iterator it = shape.subshapes().begin(),
+ end = shape.subshapes().end(); it != end; ++it) {
- for (size_t i = 0; i < subshapes.size()-1; ++i) {
- PathVec subshape_paths;
+ if (_drawing_mask) {
+ PathVec scaled_path_vec = it->paths();
- if (subshapes[i] != subshapes[i+1]) {
- subshape_paths = PathVec(subshapes[i], subshapes[i+1]);
- } else {
- subshape_paths.push_back(*subshapes[i]);
+ apply_matrix_to_paths(scaled_path_vec, xform.matrix);
+ draw_mask(scaled_path_vec);
+ continue;
}
-
- draw_subshape(subshape_paths, xform.matrix, xform.colorTransform,
- FillStyles, line_styles);
+
+ draw_subshape(it->paths(), xform.matrix, xform.colorTransform,
+ it->fillStyles(), it->lineStyles());
}
}
@@ -1052,14 +1010,18 @@ void
Renderer_cairo::drawGlyph(const SWF::ShapeRecord& rec, const rgba& color,
const SWFMatrix& mat)
{
+ if (rec.subshapes().empty() || rec.getBounds().is_null()) {
+ return;
+ }
+
SWFCxForm dummy_cx;
std::vector<FillStyle> glyph_fs;
FillStyle coloring = FillStyle(SolidFill(color));
glyph_fs.push_back(coloring);
-
- const PathVec& path_vec = rec.paths();
+
+ const PathVec& path_vec = rec.subshapes().front().paths();
std::vector<LineStyle> dummy_ls;
diff --git a/librender/opengl/Renderer_ogl.cpp b/librender/opengl/Renderer_ogl.cpp
index a15057c..1d4102e 100644
--- a/librender/opengl/Renderer_ogl.cpp
+++ b/librender/opengl/Renderer_ogl.cpp
@@ -1256,7 +1256,7 @@ public:
float prev_cx = cur_end.cp.x;
float prev_cy = cur_end.cp.y;
- Path newpath(cur_end.ap.x, cur_end.ap.y, cur_path.m_fill1, cur_path.m_fill0, cur_path.m_line, cur_path.m_new_shape);
+ Path newpath(cur_end.ap.x, cur_end.ap.y, cur_path.m_fill1, cur_path.m_fill0, cur_path.m_line);
float prev_ax = cur_end.ap.x;
float prev_ay = cur_end.ap.y;
@@ -1629,32 +1629,6 @@ public:
}
- std::vector<PathVec::const_iterator>
- find_subshapes(const PathVec& path_vec)
- {
- std::vector<PathVec::const_iterator> subshapes;
-
- PathVec::const_iterator it = path_vec.begin(),
- end = path_vec.end();
-
- subshapes.push_back(it);
- ++it;
-
- for (;it != end; ++it) {
- const Path& cur_path = *it;
-
- if (cur_path.m_new_shape) {
- subshapes.push_back(it);
- }
- }
-
- if (subshapes.back() != end) {
- subshapes.push_back(end);
- }
-
- return subshapes;
- }
-
/// Takes a path and translates it using the given SWFMatrix.
void
apply_matrix_to_paths(std::vector<Path>& paths, const SWFMatrix& mat)
@@ -1749,54 +1723,48 @@ public:
virtual void drawShape(const SWF::ShapeRecord& shape, const Transform& xform)
{
-
- const PathVec& path_vec = shape.paths();
-
- if (!path_vec.size()) {
- // No paths. Nothing to draw...
- return;
+ if (shape.subshapes().empty()) {
+ return;
}
- if (_drawing_mask) {
- PathVec scaled_path_vec = path_vec;
-
- apply_matrix_to_paths(scaled_path_vec, xform.matrix);
- draw_mask(scaled_path_vec);
- return;
- }
+ oglScopeMatrix scope_mat(xform.matrix);
+
+ for (SWF::ShapeRecord::Subshapes::const_iterator it = shape.subshapes().begin(),
+ end = shape.subshapes().end(); it != end; ++it) {
+ const PathVec& path_vec = it->paths();
+
+ if (!path_vec.size()) {
+ // No paths. Nothing to draw...
+ return;
+ }
- bool have_shape, have_outline;
+ if (_drawing_mask) {
+ PathVec scaled_path_vec = path_vec;
+
+ apply_matrix_to_paths(scaled_path_vec, xform.matrix);
+ draw_mask(scaled_path_vec);
+ continue;
+ }
- analyze_paths(path_vec, have_shape, have_outline);
+ bool have_shape, have_outline;
- if (!have_shape && !have_outline) {
- return; // invisible character
- }
+ analyze_paths(path_vec, have_shape, have_outline);
- oglScopeMatrix scope_mat(xform.matrix);
+ if (!have_shape && !have_outline) {
+ continue; // invisible character
+ }
- std::vector<PathVec::const_iterator> subshapes = find_subshapes(path_vec);
-
- const std::vector<FillStyle>& FillStyles = shape.fillStyles();
- const std::vector<LineStyle>& line_styles = shape.lineStyles();
-
- for (size_t i = 0; i < subshapes.size()-1; ++i) {
- PathVec subshape_paths;
-
- if (subshapes[i] != subshapes[i+1]) {
- subshape_paths = PathVec(subshapes[i], subshapes[i+1]);
- } else {
- subshape_paths.push_back(*subshapes[i]);
- }
-
- draw_subshape(subshape_paths, xform.matrix, xform.colorTransform,
- FillStyles, line_styles);
+ draw_subshape(it->paths(), xform.matrix, xform.colorTransform,
+ it->fillStyles(), it->lineStyles());
}
}
virtual void drawGlyph(const SWF::ShapeRecord& rec, const rgba& c,
const SWFMatrix& mat)
{
+ if (rec.subshapes().empty()) {
+ return;
+ }
if (_drawing_mask) abort();
SWFCxForm dummy_cx;
std::vector<FillStyle> glyph_fs;
@@ -1809,7 +1777,7 @@ public:
oglScopeMatrix scope_mat(mat);
- draw_subshape(rec.paths(), mat, dummy_cx, glyph_fs, dummy_ls);
+ draw_subshape(rec.subshapes().front().paths(), mat, dummy_cx, glyph_fs, dummy_ls);
}
virtual void set_scale(float xscale, float yscale) {
diff --git a/libsound/EmbedSound.cpp b/libsound/EmbedSound.cpp
index e115ce1..9f18ba0 100644
--- a/libsound/EmbedSound.cpp
+++ b/libsound/EmbedSound.cpp
@@ -59,7 +59,7 @@ EmbedSound::eraseActiveSound(Instances::iterator i)
std::auto_ptr<EmbedSoundInst>
EmbedSound::createInstance(media::MediaHandler& mh, unsigned int inPoint,
unsigned int outPoint, const SoundEnvelopes* envelopes,
- unsigned int loopCount)
+ int loopCount)
{
std::auto_ptr<EmbedSoundInst> ret(
new EmbedSoundInst(*this, mh, inPoint, outPoint, envelopes, loopCount));
diff --git a/libsound/EmbedSound.h b/libsound/EmbedSound.h
index f1a0975..61a0890 100644
--- a/libsound/EmbedSound.h
+++ b/libsound/EmbedSound.h
@@ -22,7 +22,6 @@
#include <vector>
#include <memory> // for auto_ptr (composition)
-#include <set> // for composition (_soundInstances)
#include <cassert>
#include <boost/thread/mutex.hpp>
#include <boost/scoped_ptr.hpp>
@@ -139,7 +138,7 @@ public:
///
std::auto_ptr<EmbedSoundInst> createInstance(media::MediaHandler& mh,
unsigned int inPoint, unsigned int outPoint,
- const SoundEnvelopes* envelopes, unsigned int loopCount);
+ const SoundEnvelopes* envelopes, int loopCount);
/// Drop all active sounds
//
diff --git a/libsound/EmbedSoundInst.h b/libsound/EmbedSoundInst.h
index 91bf854..27ff8cf 100644
--- a/libsound/EmbedSoundInst.h
+++ b/libsound/EmbedSoundInst.h
@@ -20,15 +20,13 @@
#ifndef SOUND_EMBEDSOUNDINST_H
#define SOUND_EMBEDSOUNDINST_H
-#include <memory>
#include <cassert>
#include <boost/cstdint.hpp> // For C99 int types
+#include <limits>
+#include "EmbedSound.h"
#include "LiveSound.h"
-#include "AudioDecoder.h"
#include "SoundEnvelope.h"
-#include "EmbedSound.h"
-#include "sound_handler.h"
// Forward declarations
namespace gnash {
diff --git a/libsound/LiveSound.h b/libsound/LiveSound.h
index 113aa55..8da4719 100644
--- a/libsound/LiveSound.h
+++ b/libsound/LiveSound.h
@@ -27,12 +27,12 @@
#include "InputStream.h"
#include "AudioDecoder.h"
#include "SimpleBuffer.h"
-#include "SoundInfo.h"
// Forward declarations
namespace gnash {
namespace media {
class MediaHandler;
+ class SoundInfo;
}
}
diff --git a/libsound/Makefile.am b/libsound/Makefile.am
index 83474c4..a771188 100644
--- a/libsound/Makefile.am
+++ b/libsound/Makefile.am
@@ -91,8 +91,11 @@ libgnashsound_la_LDFLAGS += -no-undefined
libgnashsound_la_LIBADD += -lintl
endif
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
+AM_LDFLAGS = $(CROSS_LDFLAGS)
+
if ENABLE_PCH
-AM_CXXFLAGS = $(PCH_FLAGS)
+AM_CXXFLAGS += $(PCH_FLAGS)
endif
# Remove libtool .la files
diff --git a/libsound/StreamingSound.h b/libsound/StreamingSound.h
index a8e9938..45cfb40 100644
--- a/libsound/StreamingSound.h
+++ b/libsound/StreamingSound.h
@@ -25,9 +25,6 @@
#include <boost/cstdint.hpp> // For C99 int types
#include "LiveSound.h"
-#include "AudioDecoder.h"
-#include "SoundEnvelope.h"
-#include "SimpleBuffer.h"
#include "StreamingSoundData.h"
#include "sound_handler.h"
diff --git a/libsound/StreamingSoundData.h b/libsound/StreamingSoundData.h
index e6f6186..6da7326 100644
--- a/libsound/StreamingSoundData.h
+++ b/libsound/StreamingSoundData.h
@@ -21,19 +21,17 @@
#define SOUND_STREAMING_SOUND_DATA_H
#include <vector>
-#include <map>
#include <memory>
-#include <set>
#include <cassert>
#include <boost/thread/mutex.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
-#include "SimpleBuffer.h"
#include "SoundInfo.h"
// Forward declarations
namespace gnash {
+ class SimpleBuffer;
namespace sound {
class InputStream;
class StreamingSound;
diff --git a/libsound/sdl/sound_handler_sdl.h b/libsound/sdl/sound_handler_sdl.h
index b9809e8..9d3c830 100644
--- a/libsound/sdl/sound_handler_sdl.h
+++ b/libsound/sdl/sound_handler_sdl.h
@@ -24,7 +24,6 @@
#include "sound_handler.h" // for inheritance
-#include <set> // for composition (InputStreams)
#include <SDL_audio.h>
#include <boost/thread/mutex.hpp>
diff --git a/libsound/sound_handler.cpp b/libsound/sound_handler.cpp
index ed35c1f..3c0ae52 100644
--- a/libsound/sound_handler.cpp
+++ b/libsound/sound_handler.cpp
@@ -31,6 +31,7 @@
#include "StreamingSound.h"
#include "StreamingSoundData.h"
#include "SimpleBuffer.h"
+#include "MediaHandler.h"
// Debug create_sound/delete_sound/playSound/stop_sound, loops
//#define GNASH_DEBUG_SOUNDS_MANAGEMENT
diff --git a/libsound/sound_handler.h b/libsound/sound_handler.h
index 01cd64a..ddc6385 100644
--- a/libsound/sound_handler.h
+++ b/libsound/sound_handler.h
@@ -31,13 +31,13 @@
#include <boost/scoped_ptr.hpp>
#include "dsodefs.h" // for DSOEXPORT
-#include "MediaHandler.h" // for inlined ctor
#include "SoundEnvelope.h" // for SoundEnvelopes typedef
#include "AuxStream.h" // for aux_streamer_ptr typedef
-#include "WAVWriter.h" // for dtor visibility
+#include "WAVWriter.h"
namespace gnash {
namespace media {
+ class MediaHandler;
class SoundInfo;
}
namespace sound {
diff --git a/macros/boost.m4 b/macros/boost.m4
index 845aaae..8ab371d 100644
--- a/macros/boost.m4
+++ b/macros/boost.m4
@@ -1,6 +1,6 @@
dnl
dnl Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
-dnl 2011 Free Software Foundation, Inc.
+dnl 2011, 2012 Free Software Foundation, Inc.
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
@@ -15,9 +15,8 @@ dnl You should have received a copy of the GNU General Public License
dnl along with this program; if not, write to the Free Software
dnl Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
dnl Boost modules are:
-dnl date-time, filesystem. graph. iostreams, program options,
+dnl date-time, filesystem. graph. iostreams, program options, system, chrono
dnl regex, serialization, signals, unit test, thead, and wave.
AC_DEFUN([GNASH_PATH_BOOST],
@@ -28,7 +27,8 @@ AC_DEFUN([GNASH_PATH_BOOST],
gnash_boost_libdir=""
missing_headers=""
missing_libs=""
- cygnal_missing_libs=""
+ missing_plugin_libs=""
+ missing_cygnal_libs=""
gcc_version=""
dirname=""
libname=""
@@ -37,11 +37,13 @@ AC_DEFUN([GNASH_PATH_BOOST],
boost_headers="detail/lightweight_mutex.hpp thread/thread.hpp multi_index_container.hpp multi_index/key_extractors.hpp thread/mutex.hpp program_options/options_description.hpp iostreams/stream.hpp"
dnl this is a list of *required* libraries. If any of these are missing, this
dnl test will return a failure, and Gnash won't build.
- boost_libs="thread program_options iostreams"
+ boost_libs="thread program_options system"
+ boost_plugin_libs="iostreams"
- dnl this is a list of *recommended* libraries. If any of these are missing, this
- dnl test will return a warning, and Gnash will build, but testing won't work.
- cygnal_boost_libs="serialization date_time"
+ dnl this is a list of *recommended* libraries. If any of these are missing,
+ dnl this test will return a warning, and Gnash will build, but testing
+ dnl won't work.
+ boost_cygnal_libs="serialization date_time"
dnl this is the default list for paths to search. This gets
dnl redefined if --with-boost-incl= is specified.
@@ -75,6 +77,7 @@ AC_DEFUN([GNASH_PATH_BOOST],
AC_MSG_CHECKING([for boost header])
for i in $newlist; do
+ gnash_boost_topdir=/usr/include/boost
dirs="`ls -dr $i/boost* 2>/dev/null | xargs`"
for u in ${dirs}; do
if test -n "$u" -a -d "$u" -a x"$u" != x"/usr/include/boost"; then
@@ -82,7 +85,7 @@ AC_DEFUN([GNASH_PATH_BOOST],
gnash_boost_subdir="`dirname ${gnash_boost_topdir}`"
gnash_boost_version="`echo ${gnash_boost_topdir} | sed -e 's:.*boost-::'`"
dnl Fix for packaging systems not adding extra fluff to the path-name.
- for k in ${boost_headers}; do
+ for k in ${boost_headers}; do
if test ! -f ${gnash_boost_topdir}/boost/$k; then
if test ! -f ${gnash_boost_subdir}/boost/$k; then
missing_headers="${missing_headers} $k"
@@ -103,6 +106,14 @@ AC_DEFUN([GNASH_PATH_BOOST],
done
done
+ dnl As of boost 1.47, the chrono library is required. You can get a list of
+ dnl when a Boost library was added at:
+ dnl http://www.boost.org/doc/libs/?sort=boost-version
+
+ gnash_boost_version=`grep "define.*BOOST_VERSION " ${gnash_boost_topdir}/version.hpp | cut -d ' ' -f 3`
+ if test ${gnash_boost_version} -ge 104700; then
+ boost_libs="${boost_libs} chrono"
+ fi
dnl this is the default list for paths to search. This gets
dnl redefined if --with-boost-lib= is specified.
newlist=$libslist
@@ -145,19 +156,28 @@ AC_DEFUN([GNASH_PATH_BOOST],
fi
done
done
- for j in ${cygnal_boost_libs}; do
+ for j in ${boost_plugin_libs}; do
+ dirs="`ls -dr ${dirname}/libboost_${j}*.${shlibext} ${dirname}/libboost_${j}*.a 2>/dev/null`"
+ if test -n "${dirs}"; then
+ libname="`echo ${dirs} | sed -e 's:^.*/lib::' -e "s:\.${shlibext}::" -e "s:\.a::"`"
+ ac_cv_path_boost_plugin_lib="${ac_cv_path_boost_plugin_lib} -l${libname}"
+ else
+ missing_plugin_libs="${missing_plugin_libs} $j"
+ fi
+ done
+ for j in ${boost_cygnal_libs}; do
dirs="`ls -dr ${dirname}/libboost_${j}*.${shlibext} ${dirname}/libboost_${j}*.a 2>/dev/null`"
if test -n "${dirs}"; then
libname="`echo ${dirs} | sed -e 's:^.*/lib::' -e "s:\.${shlibext}::" -e "s:\.a::"`"
ac_cv_path_boost_cygnal_lib="${ac_cv_path_boost_cygnal_lib} -l${libname}"
else
- cygnal_missing_libs="${cygnal_missing_libs} $j"
+ missing_cygnal_libs="${missing_cygnal_libs} $j"
fi
done
fi
if test x"${missing_libs}" != x ; then
- AC_MSG_WARN([Libraries ${missing_libs} ${cygnal_missing_libs} aren't installed ])
+ AC_MSG_WARN([Libraries ${missing_libs} ${missing_plugin_libs} ${missing_cygnal_libs} aren't installed ])
fi
AC_MSG_RESULT(${ac_cv_path_boost_lib})
@@ -169,6 +189,10 @@ AC_DEFUN([GNASH_PATH_BOOST],
BOOST_LIBS="$ac_cv_path_boost_lib"
fi
+ if test x"${ac_cv_path_boost_plugin_lib}" != x; then
+ BOOST_PLUGIN_LIBS="$ac_cv_path_boost_plugin_lib"
+ fi
+
if test x"${ac_cv_path_boost_cygnal_lib}" != x; then
BOOST_CYGNAL_LIBS="$ac_cv_path_boost_cygnal_lib"
fi
@@ -179,6 +203,7 @@ AC_DEFUN([GNASH_PATH_BOOST],
AC_SUBST(BOOST_CFLAGS)
AC_SUBST(BOOST_LIBS)
+ AC_SUBST(BOOST_PLUGIN_LIBS)
AC_SUBST(BOOST_CYGNAL_LIBS)
dnl This isn't right: you don't need boot date-time installed unless u build
diff --git a/macros/ffmpeg.m4 b/macros/ffmpeg.m4
index c645134..c3ef987 100644
--- a/macros/ffmpeg.m4
+++ b/macros/ffmpeg.m4
@@ -43,7 +43,7 @@ AC_DEFUN([GNASH_PATH_FFMPEG],
ffmpeg_top_incl=`dirname ${with_ffmpeg_incl}`
if test -f ${with_ffmpeg_incl}/avcodec.h; then
ac_cv_path_ffmpeg_incl="-I`(cd ${ffmpeg_top_incl}; pwd)`"
- if test -f ${with_ffmpeg_incl}/version.h && $EGREP LIBAVCODEC_VERSION ${with_ffmpeg_incl}/version.h >/dev/null; then
+ if test -f ${with_ffmpeg_incl}/version.h && $EGREP LIBAVCODEC_VERSION ${with_ffmpeg_incl}/version.h 2>&1 >/dev/null; then
avcodec_h=${with_ffmpeg_incl}/version.h
else
avcodec_h=${with_ffmpeg_incl}/avcodec.h
@@ -73,7 +73,7 @@ AC_DEFUN([GNASH_PATH_FFMPEG],
for i in "" ffmpeg libavcodec ffmpeg/libavcodec; do
if test -f ${ffmpeg_top_incl}/${i}/avcodec.h; then
ac_cv_path_ffmpeg_incl="-I`(cd ${ffmpeg_top_incl}; pwd)`"
- if test -f ${ffmpeg_top_incl}/${i}/version.h && $EGREP LIBAVCODEC_VERSION ${ffmpeg_top_incl}/${i}/version.h 2>/dev/null; then
+ if test -f ${ffmpeg_top_incl}/${i}/version.h && $EGREP LIBAVCODEC_VERSION ${ffmpeg_top_incl}/${i}/version.h 2>&1 >/dev/null; then
avcodec_h="${ffmpeg_top_incl}/${i}/version.h"
else
avcodec_h="${ffmpeg_top_incl}/${i}/avcodec.h"
@@ -97,7 +97,7 @@ AC_DEFUN([GNASH_PATH_FFMPEG],
for i in ffmpeg libavcodec ffmpeg/libavcodec; do
if test -f ${ffmpeg_top_incl}/${i}/avcodec.h; then
ac_cv_path_ffmpeg_incl="-I`(cd ${ffmpeg_top_incl}/${i}; pwd)`"
- if test -f ${ffmpeg_top_incl}/${i}/version.h && $EGREP LIBAVCODEC_VERSION ${ffmpeg_top_incl}/${i}/version.h 2>/dev/null; then
+ if test -f ${ffmpeg_top_incl}/${i}/version.h && $EGREP LIBAVCODEC_VERSION ${ffmpeg_top_incl}/${i}/version.h 2>&1 >/dev/null; then
avcodec_h=${ffmpeg_top_incl}/${i}/version.h
else
avcodec_h=${ffmpeg_top_incl}/${i}/avcodec.h
@@ -219,9 +219,9 @@ AC_DEFUN([GNASH_PATH_FFMPEG],
AC_MSG_CHECKING([ffmpeg version])
- ffmpeg_major_version=`$EGREP "define LIBAVCODEC_VERSION_MAJOR " ${versionfile} | sed -e "s%[[^0-9]]%%g"`
- ffmpeg_minor_version=`$EGREP "define LIBAVCODEC_VERSION_MINOR " ${versionfile} | sed -e "s%[[^0-9]]%%g"`
- ffmpeg_micro_version=`$EGREP "define LIBAVCODEC_VERSION_MICRO " ${versionfile} | sed -e "s%[[^0-9]]%%g"`
+ ffmpeg_major_version=`$EGREP "define LIBAVCODEC_VERSION_MAJOR " ${versionfile} 2>&1 | sed -e "s%[[^0-9]]%%g"`
+ ffmpeg_minor_version=`$EGREP "define LIBAVCODEC_VERSION_MINOR " ${versionfile} 2>&1 | sed -e "s%[[^0-9]]%%g"`
+ ffmpeg_micro_version=`$EGREP "define LIBAVCODEC_VERSION_MICRO " ${versionfile} 2>&1 | sed -e "s%[[^0-9]]%%g"`
if test x"${ffmpeg_major_version}" != x ; then
@@ -230,15 +230,15 @@ AC_DEFUN([GNASH_PATH_FFMPEG],
else
dnl #define LIBAVCODEC_VERSION_TRIPLET 51,50,1
- ffmpeg_version=`$EGREP "define LIBAVCODEC_VERSION_TRIPLET " ${versionfile} | awk '{print $'3'}' | sed -e "s%,%.%g"`
+ ffmpeg_version=`$EGREP "define LIBAVCODEC_VERSION_TRIPLET " ${versionfile} 2>&1 | awk '{print $'3'}' | sed -e "s%,%.%g"`
if test x"${ffmpeg_version}" = x ; then
dnl NOTE: the [0-9]*d. pattern discards deb-heads rubbish prefix
- ffmpeg_version=`$EGREP "define LIBAVCODEC_VERSION " ${versionfile} | awk '{print $'3'}' | sed -e "s%^[[0-9]]d\.%%"`
+ ffmpeg_version=`$EGREP "define LIBAVCODEC_VERSION " ${versionfile} | awk '{print $'3'}' 2>&1 | sed -e "s%^[[0-9]]d\.%%"`
if test x"${ffmpeg_version}" = x ; then
- ffmpeg_version=`$EGREP "define LIBAVCODEC_BUILD " ${versionfile} | awk '{print $'3'}'`
+ ffmpeg_version=`$EGREP "define LIBAVCODEC_BUILD " ${versionfile} 2>&1 | awk '{print $'3'}'`
fi
fi
@@ -255,32 +255,34 @@ AC_DEFUN([GNASH_PATH_FFMPEG],
AC_MSG_RESULT($ffmpeg_version ($ffmpeg_num_version))
-dnl AC_EGREP_HEADER(avcodec_decode_audio2, ${avcodec_h}, [avfound=yes], [avfound=no])
-
- if test -z "$ffmpeg_num_version" -o "$ffmpeg_num_version" -lt 512800; then
- AC_MSG_WARN([Wrong ffmpeg/libavcodec version! 51.28.0 or greater required, $ffmpeg_version detected.])
- else
- ffmpeg_version_check=ok
- fi
+dnl minimum supported libavcodec version = Debian stable one = currently Wheezy 7.0 53.35.00
- if test -z "$ffmpeg_num_version" -o "$ffmpeg_num_version" -lt 514900; then
- dnl 51.49.0 or higher required
- AC_MSG_WARN([This version of ffmpeg/libavcodec ($ffmpeg_version) is not able to play VP6A encoded video: 51.49.0 or higher required!])
+ if test -z "$ffmpeg_num_version" -o "$ffmpeg_num_version" -lt 533500; then
+ AC_MSG_WARN([Wrong ffmpeg/libavcodec version! 53.35.0 or greater required, $ffmpeg_version detected.])
else
- AC_DEFINE(FFMPEG_VP6A, 1, [Define if ffmpeg can play VP6A.])
+ ffmpeg_version_check=ok
fi
- if test -z "$ffmpeg_num_version" -o "$ffmpeg_num_version" -lt 514600; then
- dnl 51.46.0 (r10741) or higher required for CODEC_ID_NELLYMOSER
- AC_MSG_WARN([This version of ffmpeg/libavcodec ($ffmpeg_version) is not able to decode NELLYMOSER encoded audio: 51.46.0 (r10741) or higher required!])
- else
- AC_DEFINE(FFMPEG_NELLYMOSER, 1, [Define if ffmpeg can decode NELLYMOSER audio])
- fi
else
AC_MSG_WARN([Could not check ffmpeg version (can't find avcodec.h file)])
# ffmpeg_version_check=ok # this is NOT ok, why would it be ?!
fi
+dnl Check if installed ffmpeg/libav already switched aac decoding from S16 to
+dnl float planar format (FLTP). If recent enough, we'll recommend to install
+dnl a dedicate resampling library to get aac properly decoded.
+dnl Commit in question (3d3cf6745e2a5dc9c377244454c3186d75b177fa) corresponds
+dnl to libavcodec ffmpeg version 54.77.100 / libav version 54.33.0.
+dnl | ffmpeg | 1.0 (54.59.100) S16 | 1.1 (54.86.100) FLTP |
+dnl | libav | 0.8 (53.35.0) S16 | 9 (54.35.0) FLTP |
+
+ if test ${ffmpeg_major_version} -ge 55 -o \
+ \( ${ffmpeg_major_version} -eq 54 -a ${ffmpeg_micro_version} -eq 0 \) -o \
+ \( ${ffmpeg_major_version} -eq 54 -a ${ffmpeg_minor_version} -ge 77 -a \
+ ${ffmpeg_micro_version} -ge 100 \); then
+ ffmpeg_aac_float_planar=yes
+ fi
+
LIBAVCODEC_IDENT=${ffmpeg_version}
FFMPEG_CFLAGS="-D__STDC_CONSTANT_MACROS ${ac_cv_path_ffmpeg_incl}"
@@ -319,6 +321,46 @@ dnl AC_EGREP_HEADER(avcodec_decode_audio2, ${avcodec_h}, [avfound=yes], [avfou
ffmpeg_version_check=
fi
+ AC_MSG_CHECKING([for libavutil/opt.h])
+ have_ffmpeg_libavutil=no
+ if test -f "${ffmpeg_top_incl}/libavutil/opt.h"; then
+ have_ffmpeg_libavutil=yes
+ AC_DEFINE(HAVE_LIBAVUTIL_OPT_H, 1, [Define if libavutil/opt.h is found])
+ fi
+ AC_MSG_RESULT($have_ffmpeg_libavutil)
+
+ AC_MSG_CHECKING([for swresample.h])
+ have_ffmpeg_swresample=no
+ if test -f "${ffmpeg_top_incl}/ffmpeg/swresample.h"; then
+ have_ffmpeg_swresample=yes
+ AC_DEFINE(HAVE_FFMPEG_SWRESAMPLE_H, 1, [Define if swresample.h is found])
+ fi
+ if test -f "${ffmpeg_top_incl}/libswresample/swresample.h"; then
+ have_ffmpeg_swresample=yes
+ AC_DEFINE(HAVE_LIBSWRESAMPLE_SWRESAMPLE_H, 1, [Define if swresample.h is found])
+ fi
+ if test -f "${ffmpeg_top_incl}/swresample.h"; then
+ have_ffmpeg_swresample=yes
+ AC_DEFINE(HAVE_SWRESAMPLE_H, 1, [Define if swresample.h is found])
+ fi
+ AC_MSG_RESULT($have_ffmpeg_swresample)
+
+ AC_MSG_CHECKING([for avresample.h])
+ have_libav_avresample=no
+ if test -f "${ffmpeg_top_incl}/libav/avresample.h"; then
+ have_libav_avresample=yes
+ AC_DEFINE(HAVE_LIBAV_AVRESAMPLE_H, 1, [Define if avresample.h is found])
+ fi
+ if test -f "${ffmpeg_top_incl}/libavresample/avresample.h"; then
+ have_libav_avresample=yes
+ AC_DEFINE(HAVE_LIBAVRESAMPLE_AVRESAMPLE_H, 1, [Define if avresample.h is found])
+ fi
+ if test -f "${ffmpeg_top_incl}/avresample.h"; then
+ have_libav_avresample=yes
+ AC_DEFINE(HAVE_AVRESAMPLE_H, 1, [Define if avresample.h is found])
+ fi
+ AC_MSG_RESULT($have_libav_avresample)
+
AC_MSG_CHECKING([for libavcodec/vaapi.h])
have_ffmpeg_vaapi="no"
if test -f "${ffmpeg_top_incl}/ffmpeg/vaapi.h"; then
@@ -625,6 +667,51 @@ dnl AC_EGREP_HEADER(avcodec_decode_audio2, ${avcodec_h}, [avfound=yes], [avfou
fi
dnl End of SWSCALE library looking }
+ dnl Look for the {SW,AV}RESAMPLE libraries {
+ dnl
+ AC_MSG_CHECKING([for libswresample library])
+ if test x"$PKG_CONFIG" != x -a x${cross_compiling} = xno; then
+ $PKG_CONFIG --exists libswresample && libswresample=`$PKG_CONFIG --libs-only-l libswresample`
+ else
+ libswresample=""
+ fi
+ if test x"${libswresample}" = x; then
+ if test -f ${top_lib_dir}/libswresample.a -o -f ${top_lib_dir}/libswresample.${shlibext}; then
+ ac_cv_path_ffmpeg_lib="${ac_cv_path_ffmpeg_lib} -lswresample"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ if test x${cross_compiling} = xno; then
+ AC_CHECK_LIB(swresample, swresample, [ac_cv_path_ffmpeg_lib="${ac_cv_path_ffmpeg_lib} -lswresample"])
+ fi
+ fi
+ else
+ AC_MSG_RESULT(${libswresample})
+ ac_cv_path_ffmpeg_lib="${ac_cv_path_ffmpeg_lib} ${libswresample}"
+ fi
+
+ AC_MSG_CHECKING([for libavresample library])
+ if test x"$PKG_CONFIG" != x -a x${cross_compiling} = xno; then
+ $PKG_CONFIG --exists libavresample && libavresample=`$PKG_CONFIG --libs-only-l libavresample`
+ else
+ libavresample=""
+ fi
+ if test x"${libavresample}" = x; then
+ if test -f ${top_lib_dir}/libavresample.a -o -f ${top_lib_dir}/libavresample.${shlibext}; then
+ ac_cv_path_ffmpeg_lib="${ac_cv_path_ffmpeg_lib} -lavresample"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ if test x${cross_compiling} = xno; then
+ AC_CHECK_LIB(avresample, avresample, [ac_cv_path_ffmpeg_lib="${ac_cv_path_ffmpeg_lib} -lavresample"])
+ fi
+ fi
+ else
+ AC_MSG_RESULT(${libavresample})
+ ac_cv_path_ffmpeg_lib="${ac_cv_path_ffmpeg_lib} ${libavresample}"
+ fi
+ dnl End of {SW,AV}RESAMPLE libraries looking }
+
fi
dnl End of all optional library tests }
diff --git a/macros/gnashpkgtool.m4 b/macros/gnashpkgtool.m4
index 9998e9a..0840ef2 100644
--- a/macros/gnashpkgtool.m4
+++ b/macros/gnashpkgtool.m4
@@ -167,14 +167,22 @@ if test x"${$1}" = x"yes" -a x"${found_$1_incl}" = "xyes"; then
AC_CACHE_VAL(ac_cv_path_$1_lib,[
if test x"${with_$1_lib}" != x ; then
AC_MSG_CHECKING([for lib$1 library in specified directory])
+ dnl look for the library with the lower case name
if test -f ${with_$1_lib}/lib$name.a -o -f ${with_$1_lib}/lib$name.${shlibext}; then
tmp="`(cd ${with_$1_lib}; pwd)`"
ac_cv_path_$1_lib="-L${tmp} -l$name"
AC_MSG_RESULT([yes])
- else
- AC_MSG_ERROR([${with_$1_lib} directory doesn't contain library $name.])
- AC_MSG_RESULT([no])
- fi
+ else
+ dnl look for the library with the unchanged case name
+ if test x"${ac_cv_path_$1_lib}" = x -a -f ${with_$1_lib}/lib$1.a -o -f ${with_$1_lib}/lib$1.${shlibext}; then
+ tmp="`(cd ${with_$1_lib}; pwd)`"
+ ac_cv_path_$1_lib="-L${tmp} -l$1"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_ERROR([${with_$1_lib} directory doesn't contain library $name.])
+ AC_MSG_RESULT([no])
+ fi
+ fi
fi
])
diff --git a/macros/haxe.m4 b/macros/haxe.m4
index 98c3bb7..881f30f 100644
--- a/macros/haxe.m4
+++ b/macros/haxe.m4
@@ -50,7 +50,7 @@ AC_DEFUN([AC_PATH_HAXE], [
if test x"$HAXE" != "x"; then
AC_MSG_CHECKING([for HAXE version])
- HAXE_VERSION=`$HAXE -help | grep -i ^haxe | awk '{print $'3'}'`
+ HAXE_VERSION=`$HAXE -help 2>&1| grep -i ^haxe | awk '{print $'3'}'`
AC_MSG_RESULT([${HAXE_VERSION}])
major=`echo $HAXE_VERSION | cut -d '.' -f 1`
diff --git a/macros/openvg.m4 b/macros/openvg.m4
index 8bd23bb..93b2823 100644
--- a/macros/openvg.m4
+++ b/macros/openvg.m4
@@ -22,8 +22,8 @@ AC_DEFUN([GNASH_PATH_OPENVG],
AC_ARG_WITH(openvg_includes, AC_HELP_STRING([--with-openvg-includes], [directory where Openvg headers are]), with_openvg_includes=${withval})
AC_CACHE_VAL(ac_cv_path_openvg_includes,[
if test x"${with_openvg_includes}" != x; then
- if test -f ${with_openvg_includes}/openvg.h; then
- ac_cv_path_openvg_includes="`(cd ${with_openvg_includes}; pwd)`"
+ if test -f ${with_openvg_includes}/VG/openvg.h; then
+ ac_cv_path_openvg_includes="-I`(cd ${with_openvg_includes}; pwd)`"
else
AC_MSG_ERROR([${with_openvg_includes} directory doesn't contain VG/openvg.h])
fi
@@ -77,7 +77,7 @@ AC_DEFUN([GNASH_PATH_OPENVG],
fi
])
- if test x"${ac_cv_path_openvg_lib}" -o x"${has_openvg}" = xyes; then
+ if test x"${ac_cv_path_openvg_lib}" = x; then
for i in $libslist; do
if test -f $i/libOpenVG.${shlibext} -o -f $i/libOpenVG.a; then
if test ! x"$i" = x"/usr/lib" -a ! x"$i" = x"/usr/lib64"; then
diff --git a/macros/python.m4 b/macros/python.m4
index 652f5ed..82d16b9 100644
--- a/macros/python.m4
+++ b/macros/python.m4
@@ -54,7 +54,7 @@ AC_DEFUN([GNASH_PATH_PYTHON],
dnl If the path hasn't been specified, go look for it.
if test x"${ac_cv_path_python_incl}" = x; then
if test x"${pythonconfig}" != "x"; then
- ac_cv_path_python_incl="`${pythonconfig} --include`"
+ ac_cv_path_python_incl="`${pythonconfig} --includes`"
else
for i in $incllist; do
for j in `ls -dr $i/python2.* 2>/dev/null`;do
diff --git a/macros/qt4.m4 b/macros/qt4.m4
index c67c727..8798dec 100644
--- a/macros/qt4.m4
+++ b/macros/qt4.m4
@@ -31,7 +31,7 @@ AC_DEFUN([GNASH_PATH_QT4], [
ac_cv_path_qt4_incl="${ac_cv_path_qt4_incl} -I`(cd ${with_qt4_incl}; pwd)`"
for i in ${qt4_include_subdirs}; do
if test -d "${with_qt4_incl}/$i"; then
- ac_cv_path_qt4_incl="${ac_cv_path_qt4_incl} -I`(cd ${with_qt4_incl}\$i; pwd)`"
+ ac_cv_path_qt4_incl="${ac_cv_path_qt4_incl} -I`(cd ${with_qt4_incl}/$i; pwd)`"
fi
done
else
diff --git a/missing b/missing
index dea5679..cdea514 100755
--- a/missing
+++ b/missing
@@ -1,12 +1,10 @@
#! /bin/sh
-# Common stub for a few missing GNU programs while installing.
+# Common wrapper for a few potentially missing GNU programs.
-scriptversion=2005-06-08.21
+scriptversion=2012-06-26.16; # UTC
-# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005,
-# 2006, 2007, 2008, 2009
-# Free Software Foundation, Inc.
-# Originally by Fran,cois Pinard <pinard at iro.umontreal.ca>, 1996.
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+# Originally written by Fran,cois Pinard <pinard at iro.umontreal.ca>, 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
@@ -19,9 +17,7 @@ scriptversion=2005-06-08.21
# 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., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -29,63 +25,40 @@ scriptversion=2005-06-08.21
# 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"
+ echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
-run=:
+case $1 in
-# 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"
+ --is-lightweight)
+ # Used by our autoconf macros to check whether the available missing
+ # script is modern enough.
+ exit 0
+ ;;
-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
- ;;
+ --run)
+ # Back-compat with the calling convention used by older automake.
+ shift
+ ;;
-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.
+Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
+to PROGRAM being missing or too old.
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'
- 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]
+ aclocal autoconf autoheader autom4te automake makeinfo
+ bison yacc flex lex help2man
+
+Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
+'g' are ignored when checking the name.
Send bug reports to <bug-automake at gnu.org>."
exit $?
@@ -97,265 +70,146 @@ Send bug reports to <bug-automake at gnu.org>."
;;
-*)
- echo 1>&2 "$0: Unknown \`$1' option"
- echo 1>&2 "Try \`$0 --help' for more information"
+ echo 1>&2 "$0: unknown '$1' option"
+ echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
-# 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).
-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 "$1" 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 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
- test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
- 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 [ $# -ne 1 ]; then
- eval LASTARG="\${$#}"
- case "$LASTARG" in
- *.y)
- SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
- if [ -f "$SRCFILE" ]; then
- cp "$SRCFILE" y.tab.c
- fi
- SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
- if [ -f "$SRCFILE" ]; then
- cp "$SRCFILE" y.tab.h
- fi
- ;;
- esac
- fi
- if [ ! -f y.tab.h ]; then
- echo >y.tab.h
- fi
- if [ ! -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 [ $# -ne 1 ]; then
- eval LASTARG="\${$#}"
- case "$LASTARG" in
- *.l)
- SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
- if [ -f "$SRCFILE" ]; then
- cp "$SRCFILE" lex.yy.c
- fi
- ;;
- esac
- fi
- if [ ! -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 's/.*-o \([^ ]*\).*/\1/p'`
- if test -z "$file"; then
- file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
- fi
- if [ -f "$file" ]; then
- touch $file
- else
- test -z "$file" || exec >$file
- echo ".ab help2man is required to generate this page"
- exit 1
- 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 's/.*-o \([^ ]*\).*/\1/p'`
- 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
+# Run the given program, remember its exit status.
+"$@"; st=$?
+
+# If it succeeded, we are done.
+test $st -eq 0 && exit 0
+
+# Also exit now if we it failed (or wasn't found), and '--version' was
+# passed; such an option is passed most likely to detect whether the
+# program is present and works.
+case $2 in --version|--help) exit $st;; esac
+
+# Exit code 63 means version mismatch. This often happens when the user
+# tries to use an ancient version of a tool on a file that requires a
+# minimum version.
+if test $st -eq 63; then
+ msg="probably too old"
+elif test $st -eq 127; then
+ # Program was missing.
+ msg="missing on your system"
+else
+ # Program was found and executed, but failed. Give up.
+ exit $st
+fi
-exit 0
+perl_URL=http://www.perl.org/
+flex_URL=http://flex.sourceforge.net/
+gnu_software_URL=http://www.gnu.org/software
+
+program_details ()
+{
+ case $1 in
+ aclocal|automake)
+ echo "The '$1' program is part of the GNU Automake package:"
+ echo "<$gnu_software_URL/automake>"
+ echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
+ echo "<$gnu_software_URL/autoconf>"
+ echo "<$gnu_software_URL/m4/>"
+ echo "<$perl_URL>"
+ ;;
+ autoconf|autom4te|autoheader)
+ echo "The '$1' program is part of the GNU Autoconf package:"
+ echo "<$gnu_software_URL/autoconf/>"
+ echo "It also requires GNU m4 and Perl in order to run:"
+ echo "<$gnu_software_URL/m4/>"
+ echo "<$perl_URL>"
+ ;;
+ esac
+}
+
+give_advice ()
+{
+ # Normalize program name to check for.
+ normalized_program=`echo "$1" | sed '
+ s/^gnu-//; t
+ s/^gnu//; t
+ s/^g//; t'`
+
+ printf '%s\n' "'$1' is $msg."
+
+ configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
+ case $normalized_program in
+ autoconf*)
+ echo "You should only need it if you modified 'configure.ac',"
+ echo "or m4 files included by it."
+ program_details 'autoconf'
+ ;;
+ autoheader*)
+ echo "You should only need it if you modified 'acconfig.h' or"
+ echo "$configure_deps."
+ program_details 'autoheader'
+ ;;
+ automake*)
+ echo "You should only need it if you modified 'Makefile.am' or"
+ echo "$configure_deps."
+ program_details 'automake'
+ ;;
+ aclocal*)
+ echo "You should only need it if you modified 'acinclude.m4' or"
+ echo "$configure_deps."
+ program_details 'aclocal'
+ ;;
+ autom4te*)
+ echo "You might have modified some maintainer files that require"
+ echo "the 'automa4te' program to be rebuilt."
+ program_details 'autom4te'
+ ;;
+ bison*|yacc*)
+ echo "You should only need it if you modified a '.y' file."
+ echo "You may want to install the GNU Bison package:"
+ echo "<$gnu_software_URL/bison/>"
+ ;;
+ lex*|flex*)
+ echo "You should only need it if you modified a '.l' file."
+ echo "You may want to install the Fast Lexical Analyzer package:"
+ echo "<$flex_URL>"
+ ;;
+ help2man*)
+ echo "You should only need it if you modified a dependency" \
+ "of a man page."
+ echo "You may want to install the GNU Help2man package:"
+ echo "<$gnu_software_URL/help2man/>"
+ ;;
+ makeinfo*)
+ echo "You should only need it if you modified a '.texi' file, or"
+ echo "any other file indirectly affecting the aspect of the manual."
+ echo "You might want to install the Texinfo package:"
+ echo "<$gnu_software_URL/texinfo/>"
+ echo "The spurious makeinfo call might also be the consequence of"
+ echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
+ echo "want to install GNU make:"
+ echo "<$gnu_software_URL/make/>"
+ ;;
+ *)
+ echo "You might have modified some files without having the proper"
+ echo "tools for further handling them. Check the 'README' file, it"
+ echo "often tells you about the needed prerequisites for installing"
+ echo "this package. You may also peek at any GNU archive site, in"
+ echo "case some other package contains this missing '$1' program."
+ ;;
+ esac
+}
+
+give_advice "$1" | sed -e '1s/^/WARNING: /' \
+ -e '2,$s/^/ /' >&2
+
+# Propagate the correct exit status (expected to be 127 for a program
+# not found, 63 for a program that failed due to version mismatch).
+exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-end: "$"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
# End:
diff --git a/packaging/debian/control b/packaging/debian/control
index b050050..658f518 100644
--- a/packaging/debian/control
+++ b/packaging/debian/control
@@ -15,6 +15,7 @@ Build-Depends: dpkg-dev (>= 1.13.19),
libboost-program-options-dev,
libboost-thread-dev,
libboost-date-time-dev,
+ libboost-system-dev,
libgtk2.0-dev,
libatk1.0-dev,
kdelibs5-dev | kdelibs-dev,
@@ -35,7 +36,8 @@ Build-Depends: dpkg-dev (>= 1.13.19),
libavutil-dev,
libswscale-dev,
lsb-release,
- xulrunner-dev | firefox-dev
+ xulrunner-dev | firefox-dev,
+ libjemalloc-dev
# OpenGL packages are disabled for now
# libgl1-mesa-dev, libglu1-mesa-dev, libgtkglext1-dev, libqt4-opengl-dev,
Standards-Version: 3.8.4
diff --git a/packaging/redhat/gnash.spec b/packaging/redhat/gnash.spec
index 44d95ce..59a1b1e 100644
--- a/packaging/redhat/gnash.spec
+++ b/packaging/redhat/gnash.spec
@@ -33,6 +33,7 @@ BuildRequires: kdelibs-devel >= 4.0, kdebase-devel >= 4.0, qt-devel >= 4.0
%endif
# these are needed for the various renderers, which now all get built
BuildRequires: libXt-devel agg-devel libstdc++
+BuildRequires: jemalloc-devel
# The default Gnash package only includes the GTK parts, the rest
# is in gnash-common.
diff --git a/plugin/klash/klash_part.cpp b/plugin/klash/klash_part.cpp
index ca53997..a2714a2 100644
--- a/plugin/klash/klash_part.cpp
+++ b/plugin/klash/klash_part.cpp
@@ -98,7 +98,6 @@ KDE_NO_CDTOR_EXPORT KlashPart::KlashPart (QWidget * wparent, const char *wname,
m_fullscreen (false),
m_started_emited (false) {
//kdDebug () << "KlashPart(" << this << ")::KlashPart ()" << endl;
- bool show_fullscreen = false;
setInstance (KlashFactory::instance (), true);
/*KAction *playact =*/ new KAction(i18n("P&lay"), QString ("player_play"), KShortcut (), this, SLOT(play ()), actionCollection (), "play");
/*KAction *pauseact =*/ new KAction(i18n("&Pause"), QString ("player_pause"), KShortcut (), this, SLOT(pause ()), actionCollection (), "pause");
@@ -126,7 +125,7 @@ KDE_NO_CDTOR_EXPORT KlashPart::KlashPart (QWidget * wparent, const char *wname,
} else if (name == QString::fromLatin1("src")) {
m_src_url = value;
} else if (name == QString::fromLatin1 ("fullscreenmode")) {
- show_fullscreen = getBoolValue (value);
+ m_fullscreen = getBoolValue (value);
} else if (name == QString::fromLatin1 ("autostart")) {
bool ok;
m_autostart = value.toInt (&ok);
diff --git a/plugin/klash4/klash_part.cpp b/plugin/klash4/klash_part.cpp
index 3ba0873..801e86d 100644
--- a/plugin/klash4/klash_part.cpp
+++ b/plugin/klash4/klash_part.cpp
@@ -101,7 +101,6 @@ KDE_NO_CDTOR_EXPORT KlashPart::KlashPart (QWidget * wparent,
m_fullscreen (false),
m_started_emited (false) {
//kdDebug () << "KlashPart(" << this << ")::KlashPart ()" << endl;
- bool show_fullscreen = false;
setComponentData (*KlashFactory::instance ());
KAction *playact = new KAction(this);
playact->setText(i18n("P&lay"));
@@ -138,7 +137,7 @@ KDE_NO_CDTOR_EXPORT KlashPart::KlashPart (QWidget * wparent,
} else if (name == QString::fromLatin1("src")) {
m_src_url = value;
} else if (name == QString::fromLatin1 ("fullscreenmode")) {
- show_fullscreen = getBoolValue (value);
+ m_fullscreen = getBoolValue (value);
} else if (name == QString::fromLatin1 ("autostart")) {
bool ok;
m_autostart = value.toInt (&ok);
diff --git a/plugin/klash4/klash_part.h b/plugin/klash4/klash_part.h
index 8c8e3ce..2ae6fb3 100644
--- a/plugin/klash4/klash_part.h
+++ b/plugin/klash4/klash_part.h
@@ -39,7 +39,7 @@ class KAboutData;
class KlashPart;
class KInstance;
class KProcess;
-class JSCommandEntry;
+struct JSCommandEntry;
class KlashView;
/*
diff --git a/plugin/npapi/Makefile.am b/plugin/npapi/Makefile.am
index 2d649c7..e101269 100644
--- a/plugin/npapi/Makefile.am
+++ b/plugin/npapi/Makefile.am
@@ -78,7 +78,7 @@ libgnashplugin_la_SOURCES = plugin.cpp \
libgnashplugin_la_LIBADD = \
$(GLIB_LIBS) \
- -lboost_iostreams \
+ $(BOOST_PLUGIN_LIBS) \
$(NULL)
# Scriptable plugin support
diff --git a/plugin/npapi/mozilla-sdk/npn_gate.cpp b/plugin/npapi/mozilla-sdk/npn_gate.cpp
index 7731aae..ef41572 100644
--- a/plugin/npapi/mozilla-sdk/npn_gate.cpp
+++ b/plugin/npapi/mozilla-sdk/npn_gate.cpp
@@ -364,7 +364,9 @@ NPN_ReleaseVariantValue(NPVariant *variant)
NPNFuncs.releasevariantvalue(variant);
} else {
if (variant->type == NPVariantType_String) {
- NPN_MemFree((void*)gnash::GetNPStringChars(NPVARIANT_TO_STRING(*variant)));
+ NPString& strVar = NPVARIANT_TO_STRING(*variant);
+ NPUTF8* buffer = const_cast<NPUTF8*>(gnash::GetNPStringChars(strVar));
+ NPN_MemFree(buffer);
} else if (variant->type == NPVariantType_Object) {
NPN_ReleaseObject(NPVARIANT_TO_OBJECT(*variant));
}
diff --git a/plugin/npapi/plugin.cpp b/plugin/npapi/plugin.cpp
index dc597f1..0a270f4 100644
--- a/plugin/npapi/plugin.cpp
+++ b/plugin/npapi/plugin.cpp
@@ -50,17 +50,17 @@
// The name must be this value to get flash movies that check the
// plugin version to load.
#define PLUGIN_NAME "Shockwave Flash"
-#define MIME_TYPES_DESCRIPTION MIME_TYPES_HANDLED":swf:"PLUGIN_NAME
+#define MIME_TYPES_DESCRIPTION MIME_TYPES_HANDLED ":swf:" PLUGIN_NAME
// Some javascript plugin detectors use the description
// to decide the flash version to display. They expect the
// form (major version).(minor version) r(revision).
// e.g. "8.0 r99."
-#define FLASH_VERSION DEFAULT_FLASH_MAJOR_VERSION"."\
- DEFAULT_FLASH_MINOR_VERSION" r"DEFAULT_FLASH_REV_NUMBER"."
+#define FLASH_VERSION DEFAULT_FLASH_MAJOR_VERSION "." \
+ DEFAULT_FLASH_MINOR_VERSION " r" DEFAULT_FLASH_REV_NUMBER "."
#define PLUGIN_DESCRIPTION \
- "Shockwave Flash "FLASH_VERSION"<br>Gnash "VERSION", the GNU SWF Player. \
+ "Shockwave Flash " FLASH_VERSION "<br>Gnash " VERSION ", the GNU SWF Player. \
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 \
<a href=\"http://www.fsf.org\">Free \
Software Foundation</a>, Inc. <br> \
@@ -71,7 +71,7 @@
href=\"http://www.gnu.org/software/gnash/\"> \
http://www.gnu.org/software/gnash</a>. \
<br>\
- Compatible Shockwave Flash "FLASH_VERSION
+ Compatible Shockwave Flash " FLASH_VERSION
#include "plugin.h"
#include "GnashSystemIOHeaders.h"
@@ -1203,10 +1203,19 @@ nsPluginInstance::setupProxy(const std::string& url)
// no proxy
}
else if ( parts[0] == "PROXY" ) {
- if (setenv("http_proxy", parts[1].c_str(), 1) < 0) {
- gnash::log_error(
- "Couldn't set environment variable http_proxy to %s",
- nproxy);
+ // authenticated proxies: need to specify proxy credentials through
+ // http_proxy env var set to user:pass at proxy:port. If set, it won't be
+ // overridden. See https://savannah.gnu.org/bugs/?26713
+ char *http_proxy=getenv("http_proxy");
+ if (!http_proxy) {
+ gnash::log_debug("Setting http_proxy to %s", parts[1].c_str());
+ if (setenv("http_proxy", parts[1].c_str(), 1) < 0) {
+ gnash::log_error(
+ "Couldn't set environment variable http_proxy to %s",
+ parts[1].c_str());
+ }
+ } else {
+ gnash::log_debug("http_proxy already set to %s", http_proxy);
}
}
else {
@@ -1318,14 +1327,14 @@ wait_for_gdb()
}
void
-nsPluginInstance::setupIOChannel(int fd, GIOFunc handler, GIOCondition signals) const
+nsPluginInstance::setupIOChannel(int fd, GIOFunc handler, GIOCondition signals)
{
GIOChannel* ichan = g_io_channel_unix_new(fd);
g_io_channel_set_close_on_unref(ichan, true);
gnash::log_debug("New IO Channel for fd #%d",
g_io_channel_unix_get_fd(ichan));
- g_io_add_watch(ichan, signals, handler, (gpointer)this);
+ g_io_add_watch(ichan, signals, handler, this);
g_io_channel_unref(ichan);
}
diff --git a/plugin/npapi/plugin.h b/plugin/npapi/plugin.h
index 4f3acf9..a715c2e 100644
--- a/plugin/npapi/plugin.h
+++ b/plugin/npapi/plugin.h
@@ -107,7 +107,7 @@ private:
/// @param handler the function to invoke
/// @param signals the signals for which to invoke the handler
/// See GIOChannel documentation for more information on the parameters.
- void setupIOChannel(int fd, GIOFunc handler, GIOCondition signals) const;
+ void setupIOChannel(int fd, GIOFunc handler, GIOCondition signals);
/// Process requests from the player.
diff --git a/plugin/npapi/pluginScriptObject.cpp b/plugin/npapi/pluginScriptObject.cpp
index c6b55e4..29d1408 100644
--- a/plugin/npapi/pluginScriptObject.cpp
+++ b/plugin/npapi/pluginScriptObject.cpp
@@ -273,7 +273,9 @@ GnashPluginScriptObject::GnashPluginScriptObject()
// Constructor
GnashPluginScriptObject::GnashPluginScriptObject(NPP npp)
- : _nppinstance (npp)
+ : _nppinstance (npp),
+ _controlfd(-1),
+ _hostfd(-1)
{
// log_debug(__PRETTY_FUNCTION__);
diff --git a/revno.h b/revno.h
index 8406a55..8183638 100644
--- a/revno.h
+++ b/revno.h
@@ -1,3 +1,3 @@
-#define BRANCH_REVNO "21586"
+#define BRANCH_REVNO "2"
#define BRANCH_NICK "master"
-#define COMMIT_ID "6528395"
+#define COMMIT_ID "0a5e717"
diff --git a/testsuite/FuzzyPixel.h b/testsuite/FuzzyPixel.h
index 862eab2..d5f1b68 100644
--- a/testsuite/FuzzyPixel.h
+++ b/testsuite/FuzzyPixel.h
@@ -24,6 +24,7 @@
#include "Range2d.h"
#include "GnashKey.h" // for namespace key
#include "RGBA.h" // for rgba class (composition)
+#include "dsodefs.h" // for DSOTEXPORT
#include <cmath>
#include <ostream>
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 152a103..57b21aa 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -18,6 +18,9 @@
AUTOMAKE_OPTIONS = -Wno-portability
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
+AM_LDFLAGS = $(CROSS_LDFLAGS)
+
DIR_MING=
if ENABLE_MING
@@ -86,10 +89,13 @@ SUBDIRS = \
$(DIR_SWFC) \
movies.all \
libbase.all \
- libmedia.all \
libcore.all \
$(NULL)
+if BUILD_LIBMEDIA
+SUBDIRS += libmedia.all
+endif
+
EXTRA_DIST = check.h \
DummyMovieDefinition.h \
DummyCharacter.h \
@@ -124,13 +130,22 @@ libtestsuite_la_SOURCES = \
$(NULL)
libtestsuite_la_LIBADD = \
$(RENDERER_LIBS) \
- $(top_builddir)/libmedia/libgnashmedia.la \
- $(top_builddir)/libsound/libgnashsound.la \
$(top_builddir)/libcore/libgnashcore.la \
$(top_builddir)/libbase/libgnashbase.la \
$(top_builddir)/librender/libgnashrender.la \
$(NULL)
+if ANDROID
+libtestsuite_la_LIBADD += -lui -llog
+endif # ANDROID
+
+if BUILD_LIBMEDIA
+libtestsuite_la_LIBADD += $(top_builddir)/libmedia/libgnashmedia.la
+endif
+if BUILD_LIBSOUND
+libtestsuite_la_LIBADD += $(top_builddir)/libsound/libgnashsound.la
+endif
+
libtestsuite_la_CXXFLAGS = \
-I$(top_srcdir)/libbase \
-I$(top_srcdir)/libmedia \
@@ -146,6 +161,7 @@ libtestsuite_la_CXXFLAGS = \
-I$(top_srcdir)/libcore/vm \
$(BOOST_CFLAGS) \
$(CAIRO_CFLAGS) \
+ $(CROSS_CXXFLAGS) \
$(NULL)
tmpSharedObject:
diff --git a/testsuite/MovieTester.cpp b/testsuite/MovieTester.cpp
index 8cea0e8..5066983 100644
--- a/testsuite/MovieTester.cpp
+++ b/testsuite/MovieTester.cpp
@@ -38,8 +38,6 @@
#include "swf/TagLoadersTable.h"
#include "swf/DefaultTagLoaders.h"
-#include "MediaHandler.h"
-
#ifdef RENDERER_CAIRO
# include "Renderer_cairo.h"
#endif
@@ -92,15 +90,20 @@ MovieTester::MovieTester(const std::string& url)
_samplesFetched(0)
{
+#ifdef USE_MEDIA
// Initialize the testing media handlers
initTestingMediaHandlers();
+#endif
+ _runResources.reset(new RunResources());
+#ifdef USE_SOUND
// Initialize the sound handler(s)
initTestingSoundHandlers();
-
- _runResources.reset(new RunResources());
_runResources->setSoundHandler(_sound_handler);
+#endif
+#ifdef USE_MEDIA
_runResources->setMediaHandler(_mediaHandler);
+#endif
boost::shared_ptr<SWF::TagLoadersTable> loaders(new SWF::TagLoadersTable());
addDefaultLoaders(*loaders);
@@ -509,14 +512,18 @@ bool
MovieTester::streamingSound() const
{
if (!_sound_handler.get()) return false;
+#ifdef USE_SOUND
return _sound_handler->streamingSound();
+#endif
}
int
MovieTester::soundsStarted()
{
if ( ! _sound_handler.get() ) return 0;
+#ifdef USE_SOUND
return _sound_handler->numSoundsStarted();
+#endif
}
int
@@ -611,6 +618,7 @@ MovieTester::canTestVideo() const
void
MovieTester::initTestingSoundHandlers()
{
+#ifdef USE_SOUND
// Currently, SoundHandler can't be constructed
// w/out a registered MediaHandler .
// Should be fixed though...
@@ -620,13 +628,16 @@ MovieTester::initTestingSoundHandlers()
log_error("No media handler available, "
"could not construct sound handler");
}
+#endif // USE_SOUND
}
void
MovieTester::initTestingMediaHandlers()
{
+#ifdef USE_SOUND
// TODO: allow selection.
_mediaHandler.reset(media::MediaFactory::instance().get(""));
+#endif
}
void
diff --git a/testsuite/MovieTester.h b/testsuite/MovieTester.h
index 0727ece..2584003 100644
--- a/testsuite/MovieTester.h
+++ b/testsuite/MovieTester.h
@@ -154,7 +154,7 @@ public:
/// Return NULL if there's no DisplayObject with that name in
/// the sprite's display list.
///
- const DisplayObject* findDisplayItemByName(const MovieClip& mc,
+ DSOTEXPORT const DisplayObject* findDisplayItemByName(const MovieClip& mc,
const std::string& name);
/// Find a DisplayObject on the stage by full target name.
diff --git a/testsuite/XmlSocketServer.pl b/testsuite/XmlSocketServer.pl
index 3d06aee..f3ff8ac 100644
--- a/testsuite/XmlSocketServer.pl
+++ b/testsuite/XmlSocketServer.pl
@@ -1,11 +1,17 @@
use IO::Socket;
+use IO::Socket::INET6;
use IO::Select;
use Time::HiRes;
$SIG{PIPE}='IGNORE';
-my $m=new IO::Socket::INET(Listen=>1,LocalPort=>2229,Reuse=>1,Proto=>'tcp');
-my $O=new IO::Select($m);
+my $m;
+%socketArgs = (Listen=>1,LocalPort=>2229,Reuse=>1,Proto=>'tcp');
+$m = IO::Socket::INET6->new(%socketArgs)
+ or $m = IO::Socket::INET->new(%socketArgs)
+ or die ("Socket creation failed: $!\n");
+
+my $O = new IO::Select($m) or die ("Select failed: $!\n");
$verbose = ( $ARGV[0] eq '-v' ) ? 1 : 0;
diff --git a/testsuite/actionscript.all/BitmapData.as b/testsuite/actionscript.all/BitmapData.as
index 19f6a4c..f7ca139 100644
--- a/testsuite/actionscript.all/BitmapData.as
+++ b/testsuite/actionscript.all/BitmapData.as
@@ -535,14 +535,12 @@ check(near(bm, 5, 5, 0xffffff));
check(near(bm, 5, 15, 0xffffff));
check(near(bm, 5, 25, 0xffffff));
check(near(bm, 15, 5, 0xffffff));
-xcheck(near(bm, 15, 15, 0x00ff00));
+check(near(bm, 15, 15, 0x00ff00));
check(near(bm, 15, 25, 0xffffff));
check(near(bm, 25, 5, 0xffffff));
check(near(bm, 25, 15, 0xffffff));
check(near(bm, 25, 25, 0xffffff));
-disp.attachBitmap(bm, 400);
-
// Mask with different transform, MovieClip with different transform
mask._x = 10;
bm = new flash.display.BitmapData(50, 50, false);
@@ -556,13 +554,30 @@ check(near(bm, 15, 5, 0xffffff));
check(near(bm, 15, 15, 0xffffff));
check(near(bm, 15, 25, 0xffffff));
check(near(bm, 25, 5, 0xffffff));
-xcheck(near(bm, 25, 15, 0x0000ff));
+check(near(bm, 25, 15, 0x0000ff));
check(near(bm, 25, 25, 0xffffff));
bm = new flash.display.BitmapData(50, 50, false);
bm.draw(mc, new flash.geom.Matrix(1, 0, 0, 1, 5, 5));
-// A bit of the blue and green blue stripe is visible.
+// A bit of the green and blue stripe is visible.
+check(near(bm, 5, 5, 0xffffff));
+check(near(bm, 5, 15, 0xffffff));
+check(near(bm, 5, 25, 0xffffff));
+check(near(bm, 15, 5, 0xffffff));
+check(near(bm, 15, 15, 0xffffff));
+check(near(bm, 15, 25, 0xffffff));
+check(near(bm, 25, 5, 0xffffff));
+check(near(bm, 23, 15, 0x00ff00));
+check(near(bm, 24, 15, 0x00ff00));
+xcheck(near(bm, 25, 15, 0x0000ff)); // gnash: 0x0b0bfe
+check(near(bm, 26, 15, 0x0000ff));
+check(near(bm, 25, 25, 0xffffff));
+
+bm = new flash.display.BitmapData(50, 50, false);
+bm.draw(mc, new flash.geom.Matrix(2, 0, 0, 2, 5, 5));
+
+// A bit of the red and green stripe is visible.
check(near(bm, 5, 5, 0xffffff));
check(near(bm, 5, 15, 0xffffff));
check(near(bm, 5, 25, 0xffffff));
@@ -570,10 +585,14 @@ check(near(bm, 15, 5, 0xffffff));
check(near(bm, 15, 15, 0xffffff));
check(near(bm, 15, 25, 0xffffff));
check(near(bm, 25, 5, 0xffffff));
-xcheck(near(bm, 23, 15, 0x00ff00));
-xcheck(near(bm, 25, 15, 0x0000ff));
+check(near(bm, 23, 15, 0xff0000));
+check(near(bm, 24, 15, 0xff0000));
+xcheck(near(bm, 25, 15, 0x00ff00)); // gnash: 0x0bfe0b
+check(near(bm, 26, 15, 0x00ff00));
check(near(bm, 25, 25, 0xffffff));
+disp.attachBitmap(bm, 400);
+
bm = new flash.display.BitmapData(10, 10, true, 0x5010eeff);
xcheck_equals(bm.getPixel32(5, 5), 0x5010efff);
@@ -1127,6 +1146,6 @@ flash.display.BitmapData.prototype = e;
// END OF TEST
//-------------------------------------------------------------
-totals(392);
+totals(406);
#endif // OUTPUT_VERSION >= 8
diff --git a/testsuite/actionscript.all/Makefile.am b/testsuite/actionscript.all/Makefile.am
index a9205b4..94ef849 100644
--- a/testsuite/actionscript.all/Makefile.am
+++ b/testsuite/actionscript.all/Makefile.am
@@ -268,6 +268,7 @@ $(ASTESTS_OUT) $(ASTESTS_VERSIONED_OUT) $(ONLINETEST_RULES) $(ALLTESTS_VERSIONED
.as.swf:
$(MAKESWF) \
-i$(DEJAGNU_SO_URL):dejagnu \
+ -i$(DEJAGNU_SO_URL):dejafont \
-DUSE_DEJAGNU_MODULE \
-DOUTPUT_VERSION=$(SWFVERSION) -v$(SWFVERSION) \
$(DEF_MAKESWF_FLAGS) \
diff --git a/testsuite/actionscript.all/NetStream.as b/testsuite/actionscript.all/NetStream.as
index 866a390..b6171e4 100644
--- a/testsuite/actionscript.all/NetStream.as
+++ b/testsuite/actionscript.all/NetStream.as
@@ -1,5 +1,6 @@
//
-// Copyright (C) 2005, 2006, 2007, 2009, 2010 Free Software
+// Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011, 2012
+// 2013 Free Software
// Foundation, Inc
//
// This program is free software; you can redistribute it and/or modify
@@ -51,28 +52,37 @@ check_equals ( typeof(netstreamObj), 'object' );
* when the NetStream connection is established. *
* */
-xcheck(! NetStream.prototype.hasOwnProperty('currentFps'));
+check(! NetStream.prototype.hasOwnProperty('currentFps'));
check(! netstreamObj.hasOwnProperty('currentFps'));
-xcheck(! NetStream.prototype.hasOwnProperty('bufferLength'));
+check(! NetStream.prototype.hasOwnProperty('bufferLength'));
check(! netstreamObj.hasOwnProperty('bufferLength'));
-xcheck(! NetStream.prototype.hasOwnProperty('bufferTime'));
+check(! NetStream.prototype.hasOwnProperty('bufferTime'));
check(! netstreamObj.hasOwnProperty('bufferTime'));
-xcheck(! NetStream.prototype.hasOwnProperty('liveDelay'));
+check(! NetStream.prototype.hasOwnProperty('liveDelay'));
check(! netstreamObj.hasOwnProperty('liveDelay'));
-xcheck(! NetStream.prototype.hasOwnProperty('time'));
+check(! NetStream.prototype.hasOwnProperty('time'));
check(! netstreamObj.hasOwnProperty('time'));
/* Added in SWF7 (still apply to SWF6) */
-xcheck(! NetStream.prototype.hasOwnProperty('bytesLoaded'));
+check(! NetStream.prototype.hasOwnProperty('bytesLoaded'));
check(! netstreamObj.hasOwnProperty('bytesLoaded'));
-xcheck(! NetStream.prototype.hasOwnProperty('bytesTotal'));
+check(! NetStream.prototype.hasOwnProperty('bytesTotal'));
check(! netstreamObj.hasOwnProperty('bytesTotal'));
+check( NetStream.prototype.hasOwnProperty('close'));
+check(! netstreamObj.hasOwnProperty('close'));
+
+check( NetStream.prototype.hasOwnProperty('pause'));
+check(! netstreamObj.hasOwnProperty('pause'));
+
+check( NetStream.prototype.hasOwnProperty('play'));
+check(! netstreamObj.hasOwnProperty('play'));
+
/* Subscriber Methods */
@@ -153,41 +163,42 @@ check_equals(typeof(netstreamObj.onMetaData), 'string');
// currentFps (read-only)
check_equals ( typeof(netstreamObj.currentFps), 'undefined' );
netstreamObj.currentFps = 'string';
-xcheck_equals ( typeof(netstreamObj.currentFps), 'string' );
+check_equals ( typeof(netstreamObj.currentFps), 'string' );
netstreamObj.currentFps = false;
-xcheck_equals ( typeof(netstreamObj.currentFps), 'boolean' );
+check_equals ( typeof(netstreamObj.currentFps), 'boolean' );
// bufferLength (read-only)
-xcheck_equals ( typeof(netstreamObj.bufferLength), 'undefined' );
+check_equals ( typeof(netstreamObj.bufferLength), 'undefined' );
netstreamObj.bufferLength = 'string';
-xcheck_equals ( typeof(netstreamObj.bufferLength), 'string' );
+
+check_equals ( typeof(netstreamObj.bufferLength), 'string' );
netstreamObj.bufferLength = false;
-xcheck_equals ( typeof(netstreamObj.bufferLength), 'boolean' );
+check_equals ( typeof(netstreamObj.bufferLength), 'boolean' );
// bufferTime
-xcheck_equals ( typeof(netstreamObj.bufferTime), 'undefined' );
+check_equals ( typeof(netstreamObj.bufferTime), 'undefined' );
netstreamObj.setBufferTime(10);
-xcheck_equals(netstreamObj.bufferTime, NULL);
+check_equals(netstreamObj.bufferTime, NULL);
netstreamObj.bufferTime = 20;
-xcheck_equals(netstreamObj.bufferTime, 20);
+check_equals(netstreamObj.bufferTime, 20);
netstreamObj.setBufferTime = 30;
-xcheck_equals(netstreamObj.bufferTime, 20);
+check_equals(netstreamObj.bufferTime, 20);
netstreamObj.setBufferTime(false);
-xcheck_equals(netstreamObj.bufferTime, 20);
+check_equals(netstreamObj.bufferTime, 20);
netstreamObj.setBufferTime('string');
-xcheck_equals(netstreamObj.bufferTime, 20);
-xnetstreamObj.setBufferTime('5');
-xcheck_equals(netstreamObj.bufferTime, 20);
+check_equals(netstreamObj.bufferTime, 20);
+netstreamObj.setBufferTime('5');
+check_equals(netstreamObj.bufferTime, 20);
// liveDelay (read-only)
check_equals ( typeof(netstreamObj.liveDelay), 'undefined' );
netstreamObj.liveDelay = 'string';
-xcheck_equals ( typeof(netstreamObj.liveDelay), 'string' );
+check_equals ( typeof(netstreamObj.liveDelay), 'string' );
// time (read-only)
-xcheck_equals ( typeof(netstreamObj.time), 'undefined' );
+check_equals ( typeof(netstreamObj.time), 'undefined' );
netstreamObj.time = 'string';
-xcheck_equals ( typeof(netstreamObj.time), 'string' );
+check_equals ( typeof(netstreamObj.time), 'string' );
/* Two properties added in SWF7 */
@@ -197,10 +208,30 @@ check_equals ( typeof(netstreamObj.bytesLoaded), 'undefined' );
// bytesLoaded (read-only)
check_equals ( typeof(netstreamObj.bytesTotal), 'undefined' );
+// See when NetStream object is populated
+check(! NetStream.prototype.hasOwnProperty('currentFps'));
+nc = { isConnected: true };
+netstreamObj = new NetStream(nc);
+check(! NetStream.prototype.hasOwnProperty('currentFps'));
+nc = new NetConnection();
+check(! NetStream.prototype.hasOwnProperty('currentFps'));
+netstreamObj = new NetStream(nc);
+check(! NetStream.prototype.hasOwnProperty('currentFps'));
+nc.connect(null);
+check(! NetStream.prototype.hasOwnProperty('currentFps'));
+netstreamObj = new NetStream(nc); // Here's when !
+check(NetStream.prototype.hasOwnProperty('currentFps'));
+var NetStreamProtoBackup = NetStream.prototype;
+NetStream.prototype = {};
+netstreamObj = new NetStream();
+check(!NetStream.prototype.hasOwnProperty('currentFps'));
+netstreamObj = new NetStream(nc); // And prototype is populated again!
+check(NetStream.prototype.hasOwnProperty('currentFps'));
+
#endif // OUTPUT_VERSION >= 6
#if OUTPUT_VERSION < 6
check_totals(0);
#else
-check_totals(60);
+check_totals(74);
#endif
diff --git a/testsuite/actionscript.all/Sound.as b/testsuite/actionscript.all/Sound.as
index d65ac73..2ac115f 100644
--- a/testsuite/actionscript.all/Sound.as
+++ b/testsuite/actionscript.all/Sound.as
@@ -28,7 +28,7 @@ rcsid="Sound.as";
endOfTest = function()
{
#if OUTPUT_VERSION > 5
- check_totals(111);
+ check_totals(112);
#else
check_totals(94);
#endif
@@ -157,6 +157,7 @@ mp3.onID3 = function() {
};
mp3.loadSound(MEDIA(stereo8.mp3), false);
+
#endif
@@ -300,10 +301,25 @@ s.onSoundComplete = function()
check_equals(typeof(s.onLoadArg), 'boolean');
check_equals(s.onLoadArg, true);
+ // Test for #33760:
+ // Try to load an mp3 sound (without any tags) that is longer than the
+ // (at the time of writing) hard-coded single minute of buffer time.
+ longsilence = new Sound();
+ longsilence.onLoad = function(success) {
+ // Test for #33760, continued: Having this test here is a hack, but the
+ // delay in calling this function will ensure the sound has started.
+ pass("mp3 over one minute long loaded");
+
+ endOfTest();
+ };
+
+ longsilence.loadSound(MEDIA(silence.mp3), true);
+
+ stop();
+
// TODO: test non-streaming sound
// TODO: test loadSound on unexistent sound
- endOfTest();
};
s.onLoad = function(arg)
diff --git a/testsuite/actionscript.all/TextFormat.as b/testsuite/actionscript.all/TextFormat.as
index 9193125..90c2235 100644
--- a/testsuite/actionscript.all/TextFormat.as
+++ b/testsuite/actionscript.all/TextFormat.as
@@ -332,104 +332,153 @@ check(te.hasOwnProperty("textFieldHeight"));
check(te.hasOwnProperty("width"));
check(te.hasOwnProperty("height"));
-xcheck_equals(Math.round(te.textFieldWidth), 37);
-check_equals(Math.round(te.ascent), 11);
+check_equals(te.textFieldWidth, 37);
+check_equals(te.width, 33);
+#if OUTPUT_VERSION > 7
+check_equals(te.ascent, 11.1);
+#else
+check_equals(te.ascent, 11);
+#endif
#if OUTPUT_VERSION > 7
- xcheck_equals(Math.round(te.textFieldHeight), 18);
- check_equals(Math.round(te.descent), 3);
+ check_equals(te.textFieldHeight, 17.9);
+ check_equals(te.descent, 2.8);
#else
- xcheck_equals(Math.round(te.textFieldHeight), 17);
- xcheck_equals(Math.round(te.descent), 2);
+ check_equals(te.textFieldHeight, 17);
+ check_equals(te.descent, 2);
#endif
+te = tf2.getTextExtent("a");
+check_equals(te.width, 8);
+te = tf2.getTextExtent("aa");
+check_equals(te.width, 16);
+te = tf2.getTextExtent("aaa");
+check_equals(te.width, 24);
+
te = tf2.getTextExtent("Hello", 10);
#if OUTPUT_VERSION > 7
- xcheck_equals(Math.round(te.textFieldHeight), 74);
+ check_equals(te.textFieldHeight, 73.5);
#else
- xcheck_equals(Math.round(te.textFieldHeight), 17);
+ check_equals(te.textFieldHeight, 17);
+#endif
+
+#if OUTPUT_VERSION == 7
+ var wrappingPoint = 0;
+ for (var i:Number = 10; i < 30; i++) {
+ if (tf2.getTextExtent("Hello", i).height != 13) {
+ wrappingPoint = i;
+ break;
+ }
+ }
+
+ // Wrapping is enabled only if the wrapping value >= tfw of the first two
+ // letters. Doh.
+ check_equals(wrappingPoint, tf2.getTextExtent("He").textFieldWidth );
+ check_equals(tf2.getTextExtent("Hello", wrappingPoint).height, 27);
#endif
check_equals(te.textFieldWidth, 10);
#if OUTPUT_VERSION > 7
-check_equals(Math.round(te.width), 9);
+check_equals(te.width, 9);
#else
-xcheck_equals(Math.round(te.width), 33);
+check_equals(te.width, 33);
#endif
te = tf2.getTextExtent("Hello", 5);
#if OUTPUT_VERSION < 8
- xcheck_equals(Math.round(te.textFieldHeight), 17);
- xcheck_equals(Math.round(te.descent), 2);
+ check_equals(te.textFieldHeight, 17);
+ check_equals(te.descent, 2);
#else
- xcheck_equals(Math.round(te.textFieldHeight), 74);
- check_equals(Math.round(te.descent), 3);
+ check_equals(te.textFieldHeight, 73.5);
+ check_equals(te.descent, 2.8);
#endif
check_equals(te.textFieldWidth, 5);
-check_equals(Math.round(te.ascent), 11);
+#if OUTPUT_VERSION > 7
+check_equals(te.ascent, 11.1);
+#else
+check_equals(te.ascent, 11);
+#endif
#if OUTPUT_VERSION > 7
-// Width of largest character in version 8?
-check_equals(Math.round(te.width), 9);
+// Text is wrapped in v8; 'advance' of largest character.
+check_equals(te.width, 9);
#else
-xcheck_equals(Math.round(te.width), 33);
+check_equals(te.width, 33);
#endif
te = tf2.getTextExtent("Longer sentence with more words.", 30);
check_equals(te.textFieldWidth, 30);
-xcheck_equals(Math.round(te.width), 25);
+check_equals(te.width, 25);
#if OUTPUT_VERSION > 7
xcheck_equals(te.height, 152.9);
#else
xcheck_equals(te.height, 152);
#endif
+te = tf2.getTextExtent("Longersentencewithoneword", 30);
+check_equals(te.textFieldWidth, 30);
+#if OUTPUT_VERSION > 7
+check_equals(te.height, 125.1);
+check_equals(Math.round(te.width), 25);
+#else
+check_equals(te.width, 26);
+check_equals(te.height, 111);
+#endif
+
te = tf2.getTextExtent("o");
-xcheck_equals(Math.round(te.textFieldWidth), 12);
-check_equals(Math.round(te.ascent), 11);
+check_equals(te.textFieldWidth, 12);
+#if OUTPUT_VERSION > 7
+check_equals(te.ascent, 11.1);
+#else
+check_equals(te.ascent, 11);
+#endif
#if OUTPUT_VERSION < 8
- xcheck_equals(Math.round(te.textFieldHeight), 17);
- xcheck_equals(Math.round(te.descent), 2);
+ check_equals(te.textFieldHeight, 17);
+ check_equals(te.descent, 2);
#else
- xcheck_equals(Math.round(te.textFieldHeight), 18);
- check_equals(Math.round(te.descent), 3);
+ check_equals(te.textFieldHeight, 17.9);
+ check_equals(te.descent, 2.8);
#endif
te = tf2.getTextExtent("oo");
-xcheck_equals(Math.round(te.textFieldWidth), 20);
+check_equals(Math.round(te.textFieldWidth), 20);
check_equals(Math.round(te.ascent), 11);
#if OUTPUT_VERSION < 8
- xcheck_equals(Math.round(te.textFieldHeight), 17);
- xcheck_equals(Math.round(te.descent), 2);
+ check_equals(te.textFieldHeight, 17);
+ check_equals(te.descent, 2);
#else
- xcheck_equals(Math.round(te.textFieldHeight), 18);
- check_equals(Math.round(te.descent), 3);
+ check_equals(te.textFieldHeight, 17.9);
+ check_equals(te.descent, 2.8);
#endif
te = tf2.getTextExtent("ool");
-xcheck_equals(Math.round(te.textFieldWidth), 24);
-check_equals(Math.round(te.ascent), 11);
+check_equals(te.textFieldWidth, 24);
+#if OUTPUT_VERSION > 7
+check_equals(te.ascent, 11.1);
+#else
+check_equals(te.ascent, 11);
+#endif
#if OUTPUT_VERSION < 8
- xcheck_equals(Math.round(te.textFieldHeight), 17);
- xcheck_equals(Math.round(te.descent), 2);
+ check_equals(te.textFieldHeight, 17);
+ check_equals(te.descent, 2);
#else
- xcheck_equals(Math.round(te.textFieldHeight), 18);
- check_equals(Math.round(te.descent), 3);
+ check_equals(te.textFieldHeight, 17.9);
+ check_equals(te.descent, 2.8);
#endif
tf2.size = 20;
te = tf2.getTextExtent("ool");
-xcheck_equals(Math.round(te.textFieldHeight), 27);
-xcheck_equals(Math.round(te.textFieldWidth), 36);
+check_equals(Math.round(te.textFieldHeight), 27);
+check_equals(Math.round(te.textFieldWidth), 36);
#if OUTPUT_VERSION < 8
- xcheck_equals(Math.round(te.ascent), 18);
- xcheck_equals(Math.round(te.descent), 4);
+ check_equals(te.ascent, 18);
+ check_equals(te.descent, 4);
#else
- check_equals(Math.round(te.ascent), 19);
- check_equals(Math.round(te.descent), 5);
+ check_equals(te.ascent, 18.55);
+ check_equals(te.descent, 4.7);
#endif
#endif
@@ -437,7 +486,7 @@ xcheck_equals(Math.round(te.textFieldWidth), 36);
#if OUTPUT_VERSION < 7
check_totals(122);
#elif OUTPUT_VERSION == 7
- check_totals(159);
+ check_totals(168);
#else
- check_totals(159);
+ check_totals(166);
#endif
diff --git a/testsuite/actionscript.all/XMLNode.as b/testsuite/actionscript.all/XMLNode.as
index ae1b054..bcc254b 100644
--- a/testsuite/actionscript.all/XMLNode.as
+++ b/testsuite/actionscript.all/XMLNode.as
@@ -406,5 +406,13 @@ check_equals(xn.toString(), "");
xn = new XMLNode(7, "");
check_equals(xn.toString(), "");
+// Test for https://savannah.gnu.org/bugs/index.php?39404
+// NOTE: you need to run under valgrind to determine
+// if the test was successful or not...
+x = new XML('<t></t>'); x.appendChild(new XML('<t></t>'));
+var x2 = new XML('<t></t>'); x2.appendChild(x); delete x2;
+// many allocations force GC run
+for (var i=0; i<256; ++i) x = {};
+
check_totals(182);
diff --git a/testsuite/actionscript.all/array.as b/testsuite/actionscript.all/array.as
index 70c55a2..0417419 100644
--- a/testsuite/actionscript.all/array.as
+++ b/testsuite/actionscript.all/array.as
@@ -324,6 +324,24 @@ trysortarray.sort( testCmpBogus6 );
check_equals ( trysortarray.length, 4 );
xcheck_equals ( trysortarray.toString(), "2,3,4,1" );
+// This comparator is total nonsense, but there are people using this to
+// randomize their array, and we must oblige by not aborting. (See #39385.)
+function randomComparator(a, b) {
+ return Math.random() < 0.5 ? -1 : 1;
+}
+
+var indexedarray = new Array(10,9,8,3,2,1,0);
+indexedarray = indexedarray.sort(randomComparator, Array.RETURNINDEXEDARRAY);
+
+check_equals ( indexedarray.length, 7 );
+
+var firstRandom = indexedarray.toString();
+indexedarray = indexedarray.sort(randomComparator, Array.RETURNINDEXEDARRAY);
+var secondRandom = indexedarray.toString();
+
+// I suppose it is theoretically possible that these are the same. But it
+// seems very unlikely.
+check(firstRandom != secondRandom);
//-----------------------------------------------------
// Test non-integer and insane indices.
@@ -1680,6 +1698,17 @@ ret = "" + t.sort();
check_equals(rescount, 0);
check_equals(ret, "");
+// Check for correct array prototype inheritance
+// (see http://savannah.gnu.org/bugs/?38084)
+
+function X() { trace('X ctor'); }
+X.prototype = new Array();
+trace("creating new object");
+o = new X();
+o.push("Array data");
+ret = o.pop();
+xcheck_equals(ret, "Array data");
+
#if OUTPUT_VERSION > 5
Empty = function() {};
@@ -1783,13 +1812,12 @@ check_equals(ar.__proto__, "string");
// ASnative(252, 12) - [Array.prototype] sortOn
//
-
#if OUTPUT_VERSION < 6
- check_totals(549);
+ check_totals(552);
#else
# if OUTPUT_VERSION < 7
- check_totals(633);
+ check_totals(636);
# else
- check_totals(643);
+ check_totals(646);
# endif
#endif
diff --git a/testsuite/libbase.all/CurlStreamTest.cpp b/testsuite/libbase.all/CurlStreamTest.cpp
index 8489926..4f15b6a 100644
--- a/testsuite/libbase.all/CurlStreamTest.cpp
+++ b/testsuite/libbase.all/CurlStreamTest.cpp
@@ -96,7 +96,7 @@ dump_file(const char* url, ostream& os)
os << buf[i];
}
}
-
+ fclose(f);
}
int
diff --git a/testsuite/libbase.all/Makefile.am b/testsuite/libbase.all/Makefile.am
index ca5b165..0f0015e 100644
--- a/testsuite/libbase.all/Makefile.am
+++ b/testsuite/libbase.all/Makefile.am
@@ -22,7 +22,18 @@ AUTOMAKE_OPTIONS = dejagnu
LDADD = \
$(top_builddir)/libbase/libgnashbase.la \
$(top_builddir)/librender/libgnashrender.la \
- $(LIBINTL)
+ $(LIBINTL) \
+ $(AGG_LIBS) \
+ $(OPENVG_LIBS) \
+ $(EGL_LIBS) \
+ $(NULL)
+
+if ANDROID
+LDADD += -lui -llog
+endif # ANDROID
+
+AM_LDFLAGS = $(CROSS_LDFLAGS)
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
# AM_CPPFLAGS isn't right here since per-program *_CPPFLAGS override global
# AM_CPPFLAGS
@@ -67,30 +78,40 @@ check_PROGRAMS = \
NoSeekFileTest_SOURCES = NoSeekFileTest.cpp
NoSeekFileTest_CPPFLAGS = $(AM_CPPFLAGS) \
'-DINPUT="$(srcdir)/NoSeekFileTest.cpp"'
+NoSeekFileTest_LDADD = $(LDADD)
URLTest_SOURCES = URLTest.cpp
URLTest_CPPFLAGS = $(AM_CPPFLAGS) \
'-DBUILDDIR="$(abs_builddir)"'
+URLTest_LDADD = $(LDADD)
RcTest_SOURCES = RcTest.cpp
RcTest_CPPFLAGS = $(AM_CPPFLAGS) \
-DSRCDIR="$(srcdir)"
+RcTest_LDADD = $(LDADD)
IntTypesTest_SOURCES = IntTypesTest.cpp
IntTypesTest_CPPFLAGS = $(AM_CPPFLAGS) \
-DSRCDIR="$(srcdir)"
+IntTypesTest_LDADD = $(LDADD)
# Test the Memory class
#memtest_SOURCES = memtest.cpp
Point2dTest_SOURCES = Point2dTest.cpp
+Point2dTest_LDADD = $(LDADD)
+
Range2dTest_SOURCES = Range2dTest.cpp
+Range2dTest_LDADD = $(LDADD)
+
snappingrangetest_SOURCES = snappingrangetest.cpp
+snappingrangetest_LDADD= $(LDADD)
string_tableTest_SOURCES = string_tableTest.cpp
string_tableTest_CPPFLAGS = $(AM_CPPFLAGS) \
-DSRCDIR="$(srcdir)"
string_tableTest_LDFLAGS = $(BOOST_LIBS)
+string_tableTest_LDADD = $(LDADD)
TEST_DRIVERS = ../simple.exp
TEST_CASES = \
diff --git a/testsuite/libbase.all/memtest.cpp b/testsuite/libbase.all/memtest.cpp
index ad5cb2f..4563da4 100644
--- a/testsuite/libbase.all/memtest.cpp
+++ b/testsuite/libbase.all/memtest.cpp
@@ -117,7 +117,7 @@ main (int /*argc*/, char** /*argv*/) {
}
sv.push_back("Aloha");
- delete x;
+ delete[] x;
mem.addStats(__LINE__); // take a sample
diff = mem.diffStats();
// cerr << "Second string allocated: " << diff << endl;
@@ -192,7 +192,7 @@ long *
test_noleak()
{
long *x = test_leak();
- delete x;
+ delete[] x;
return 0;
}
diff --git a/testsuite/libcore.all/ClassSizes.cpp b/testsuite/libcore.all/ClassSizes.cpp
index daab738..f86fe28 100644
--- a/testsuite/libcore.all/ClassSizes.cpp
+++ b/testsuite/libcore.all/ClassSizes.cpp
@@ -25,6 +25,7 @@
#include "Property.h"
#include "PropertyList.h"
#include "MovieClip.h"
+#include "Movie.h"
#include "DisplayObject.h"
#include "RGBA.h"
#include "movie_root.h"
diff --git a/testsuite/libcore.all/Makefile.am b/testsuite/libcore.all/Makefile.am
index 32059f8..537959e 100644
--- a/testsuite/libcore.all/Makefile.am
+++ b/testsuite/libcore.all/Makefile.am
@@ -19,6 +19,8 @@
AUTOMAKE_OPTIONS = dejagnu
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
+
AM_CPPFLAGS = \
-I$(top_srcdir)/testsuite \
-I$(top_srcdir)/librender \
@@ -60,55 +62,69 @@ CLEANFILES = \
gnash-dbg.log \
$(NULL)
-AM_LDFLAGS = \
+LDADD = \
$(top_builddir)/libcore/libgnashcore.la \
$(top_builddir)/libbase/libgnashbase.la \
- $(top_builddir)/libmedia/libgnashmedia.la \
- $(top_builddir)/libsound/libgnashsound.la \
- $(BOOST_LIBS)
+ $(CROSS_LDFLAGS) \
+ $(BOOST_LIBS) \
+ $(AGG_LIBS) \
+ $(OPENVG_LIBS) \
+ $(EGL_LIBS) \
+ $(NULL)
+
+if ANDROID
+LDADD += -lui -llog
+endif # ANDROID
+
+if BUILD_LIBMEDIA
+LDADD += $(top_builddir)/libmedia/libgnashmedia.la
+endif
+if BUILD_LIBSOUND
+LDADD += $(top_builddir)/libsound/libgnashsound.la
+endif
BitsReaderTest_SOURCES = BitsReaderTest.cpp
-BitsReaderTest_LDADD = $(AM_LDFLAGS)
+BitsReaderTest_LDADD = $(LDADD)
StreamTest_SOURCES = StreamTest.cpp
-StreamTest_LDADD = $(AM_LDFLAGS)
+StreamTest_LDADD = $(LDADD)
MatrixTest_SOURCES = MatrixTest.cpp
-MatrixTest_LDADD = $(AM_LDFLAGS)
+MatrixTest_LDADD = $(LDADD)
PointTest_SOURCES = PointTest.cpp
-PointTest_LDADD = $(AM_LDFLAGS)
+PointTest_LDADD = $(LDADD)
EdgeTest_SOURCES = EdgeTest.cpp
-EdgeTest_LDADD = $(AM_LDFLAGS)
+EdgeTest_LDADD = $(LDADD)
PropertyListTest_SOURCES = PropertyListTest.cpp
-PropertyListTest_LDADD = $(AM_LDFLAGS)
+PropertyListTest_LDADD = $(LDADD)
PropFlagsTest_SOURCES = PropFlagsTest.cpp
-PropFlagsTest_LDADD = $(AM_LDFLAGS)
+PropFlagsTest_LDADD = $(LDADD)
DisplayListTest_SOURCES = DisplayListTest.cpp
-DisplayListTest_LDADD = $(AM_LDFLAGS)
+DisplayListTest_LDADD = $(LDADD)
# if CYGNAL
check_PROGRAMS += AsValueTest
AsValueTest_SOURCES = AsValueTest.cpp
-AsValueTest_LDADD = $(AM_LDFLAGS)
+AsValueTest_LDADD = $(LDADD)
# endif
ClassSizes_SOURCES = ClassSizes.cpp
-ClassSizes_LDADD = $(AM_LDFLAGS)
+ClassSizes_LDADD = $(LDADD)
SafeStackTest_SOURCES = SafeStackTest.cpp
-SafeStackTest_LDADD = $(AM_LDFLAGS)
+SafeStackTest_LDADD = $(LDADD)
CxFormTest_SOURCES = CxFormTest.cpp
-CxFormTest_LDADD = $(AM_LDFLAGS)
+CxFormTest_LDADD = $(LDADD)
CodeStreamTest_SOURCES = CodeStreamTest.cpp
-CodeStreamTest_LDADD = $(AM_LDFLAGS)
-CodeStreamTest_DEPENDENCIES = $(AM_LDFLAGS)
+CodeStreamTest_LDADD = $(LDADD)
+CodeStreamTest_DEPENDENCIES = $(LDADD)
TEST_DRIVERS = ../simple.exp
TEST_CASES = $(check_PROGRAMS)
diff --git a/testsuite/libbase.all/Makefile.am b/testsuite/libdevice.all/Makefile.am
similarity index 56%
copy from testsuite/libbase.all/Makefile.am
copy to testsuite/libdevice.all/Makefile.am
index ca5b165..1ac78c1 100644
--- a/testsuite/libbase.all/Makefile.am
+++ b/testsuite/libdevice.all/Makefile.am
@@ -21,18 +21,22 @@ AUTOMAKE_OPTIONS = dejagnu
LDADD = \
$(top_builddir)/libbase/libgnashbase.la \
- $(top_builddir)/librender/libgnashrender.la \
- $(LIBINTL)
+ $(LIBINTL) \
+ $(NULL)
+
+if ANDROID
+LDADD += -lui -llog
+endif # ANDROID
+
+AM_LDFLAGS = $(CROSS_LDFLAGS)
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
# AM_CPPFLAGS isn't right here since per-program *_CPPFLAGS override global
# AM_CPPFLAGS
AM_CPPFLAGS = \
-I$(top_srcdir)/libbase \
- -I$(top_srcdir)/libcore \
+ -I$(top_srcdir)/libdevice \
-I$(top_srcdir)/testsuite \
- $(MING_CFLAGS) \
- $(BOOST_CFLAGS) \
- $(PTHREAD_CFLAGS) \
$(DEJAGNU_CFLAGS) \
$(NULL)
@@ -46,52 +50,70 @@ CLEANFILES = \
NoSeekFileTestCache \
$(NULL)
-check_PROGRAMS = \
- NoSeekFileTest \
- URLTest \
- RcTest \
- IntTypesTest \
- Point2dTest \
- snappingrangetest \
- Range2dTest \
- string_tableTest \
- $(NULL)
-
-#if CURL
-## This test needs an http server running to be useful
-#check_PROGRAMS += CurlStreamTest
-#CurlStreamTest_SOURCES = CurlStreamTest.cpp
-#CurlStreamTest_CPPFLAGS = '-DINPUT="$(srcdir)/CurlStreamTest.cpp"'
-#endif
-
-NoSeekFileTest_SOURCES = NoSeekFileTest.cpp
-NoSeekFileTest_CPPFLAGS = $(AM_CPPFLAGS) \
- '-DINPUT="$(srcdir)/NoSeekFileTest.cpp"'
-
-URLTest_SOURCES = URLTest.cpp
-URLTest_CPPFLAGS = $(AM_CPPFLAGS) \
- '-DBUILDDIR="$(abs_builddir)"'
+check_PROGRAMS =
-RcTest_SOURCES = RcTest.cpp
-RcTest_CPPFLAGS = $(AM_CPPFLAGS) \
- -DSRCDIR="$(srcdir)"
+if BUILD_EGL_DEVICE
+# this tests the low level EGL interface, used by OpenVG, OpenGLES1, and OpenGLES2.
+check_PROGRAMS += test_egl
-IntTypesTest_SOURCES = IntTypesTest.cpp
-IntTypesTest_CPPFLAGS = $(AM_CPPFLAGS) \
- -DSRCDIR="$(srcdir)"
-
-# Test the Memory class
-#memtest_SOURCES = memtest.cpp
-
-Point2dTest_SOURCES = Point2dTest.cpp
-Range2dTest_SOURCES = Range2dTest.cpp
-snappingrangetest_SOURCES = snappingrangetest.cpp
+test_egl_SOURCES = test_egl.cpp
+test_egl_CPPFLAGS = $(AM_CPPFLAGS) $(EGL_CFLAGS) -I$(top_srcdir)/libdevice/egl
+test_egl_LDADD = \
+ ../../libdevice/libgnashdevice.la \
+ ../../libbase/libgnashbase.la \
+ $(EXTRA_EGL_LIBS) \
+ $(EGL_LIBS) \
+ $(BOOST_LIBS) \
+ $(NULL)
+endif
+
+# if BUILD_X11_DEVICE
+# check_PROGRAMS += test_x11
+# endif
+
+if BUILD_DIRECTFB_DEVICE
+check_PROGRAMS += test_directfb
+endif
+
+if ENABLE_INPUT_EVENTS
+check_PROGRAMS += test_events
+
+test_events_SOURCES = test_events.cpp
+test_events_CPPFLAGS = $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/libdevice/events \
+ -I$(top_srcdir)/libcore
+test_events_LDADD = \
+ ../../libdevice/libgnashdevice.la \
+ ../../libbase/libgnashbase.la \
+ $(EXTRA_EVENTS_LIBS) \
+ $(TS_LIBS) \
+ $(CURL_LIBS) \
+ $(EVENTS_LIBS) \
+ $(NULL)
+endif
+
+if BUILD_RAWFB_DEVICE
+check_PROGRAMS += test_rawfb
+
+# this tests the low level EGL interface, used by OpenVG, OpenGLES1,
+# and OpenGLES2.
+test_rawfb_SOURCES = test_rawfb.cpp
+test_rawfb_CPPFLAGS = $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/libbase \
+ -I$(top_srcdir)/libdevice/rawfb
+test_rawfb_LDADD = \
+ ../../libdevice/libgnashdevice.la \
+ ../../libbase/libgnashbase.la \
+ $(NULL)
+endif
-string_tableTest_SOURCES = string_tableTest.cpp
-string_tableTest_CPPFLAGS = $(AM_CPPFLAGS) \
- -DSRCDIR="$(srcdir)"
-string_tableTest_LDFLAGS = $(BOOST_LIBS)
+if BUILD_VAAPI_DEVICE
+check_PROGRAMS += test_vaapi
+endif
+#
+# Testing stuff
+#
TEST_DRIVERS = ../simple.exp
TEST_CASES = \
$(check_PROGRAMS) \
diff --git a/libdevice/directfb/test_dfb.cpp b/testsuite/libdevice.all/test_dfb.cpp
similarity index 100%
rename from libdevice/directfb/test_dfb.cpp
rename to testsuite/libdevice.all/test_dfb.cpp
diff --git a/libdevice/egl/test_egl.cpp b/testsuite/libdevice.all/test_egl.cpp
similarity index 98%
rename from libdevice/egl/test_egl.cpp
rename to testsuite/libdevice.all/test_egl.cpp
index b17c9d6..cf25a07 100644
--- a/libdevice/egl/test_egl.cpp
+++ b/testsuite/libdevice.all/test_egl.cpp
@@ -34,13 +34,12 @@
#include <fcntl.h>
#include "log.h"
-#include "dejagnu.h"
#include "eglDevice.h"
#include "configTemplates.h"
#include "GnashDevice.h"
-#ifdef BUILD_X11_DEVICE
-# include "x11/X11Device.h"
+#ifdef HAVE_DEJAGNU_H
+#include "dejagnu.h"
#endif
#ifdef HAVE_EGL_EGL_H
@@ -52,7 +51,6 @@
TestState runtest;
using namespace gnash;
-using namespace std;
using namespace renderer;
void test_egl(EGLDevice &egl, GnashDevice::rtype_t rtype, int argc, char *argv[]);
@@ -108,7 +106,7 @@ test_egl(EGLDevice &egl, GnashDevice::rtype_t rtype, int argc, char *argv[])
// This is a utility method for converting integer error codes to
// something human readable for debugging.
- string result = "EGL_BAD_CONFIG";
+ std::string result = "EGL_BAD_CONFIG";
if (egl.getErrorString(EGL_BAD_CONFIG) == result) {
runtest.pass("EGLDevice::getErrorString()");
} else {
@@ -154,6 +152,9 @@ test_egl(EGLDevice &egl, GnashDevice::rtype_t rtype, int argc, char *argv[])
#else
# ifdef BUILD_RAWFB_DEVICE
win = open("/dev/fb0", O_RDWR);
+ if (win <= 0) {
+ win = open("/dev/graphicsfb0", O_RDWR);
+ }
# endif
# ifdef BUILD_X11_DEVICE
x11::X11Device x11(egl.getNativeVisual());
diff --git a/libdevice/events/test_events.cpp b/testsuite/libdevice.all/test_events.cpp
similarity index 100%
rename from libdevice/events/test_events.cpp
rename to testsuite/libdevice.all/test_events.cpp
diff --git a/libdevice/rawfb/test_rawfb.cpp b/testsuite/libdevice.all/test_rawfb.cpp
similarity index 97%
rename from libdevice/rawfb/test_rawfb.cpp
rename to testsuite/libdevice.all/test_rawfb.cpp
index 2058389..93d4614 100644
--- a/libdevice/rawfb/test_rawfb.cpp
+++ b/testsuite/libdevice.all/test_rawfb.cpp
@@ -165,6 +165,13 @@ main(int argc, char *argv[])
boost::uint8_t *fbp = 0;
fbp = rfb.getFBMemory();
+
+ if (fbp > 0) {
+ runtest.pass("RawFBDevice::getFBMemory()");
+ } else {
+ runtest.fail("RawFBDevice::getFBMemory()");
+ exit;
+ }
for(y=100; y<102; y++); /* Where we are going to put the pixel */
diff --git a/libdevice/vaapi/test_vaapi.cpp b/testsuite/libdevice.all/test_vaapi.cpp
similarity index 100%
rename from libdevice/vaapi/test_vaapi.cpp
rename to testsuite/libdevice.all/test_vaapi.cpp
diff --git a/libdevice/x11/test_x11.cpp b/testsuite/libdevice.all/test_x11.cpp
similarity index 100%
rename from libdevice/x11/test_x11.cpp
rename to testsuite/libdevice.all/test_x11.cpp
diff --git a/testsuite/libmedia.all/Makefile.am b/testsuite/libmedia.all/Makefile.am
index 6100486..b651342 100644
--- a/testsuite/libmedia.all/Makefile.am
+++ b/testsuite/libmedia.all/Makefile.am
@@ -30,8 +30,13 @@ AM_LDFLAGS = \
$(GSTREAMER_APP_LIBS) \
$(GSTREAMER_LIBS) \
$(BOOST_LIBS) \
+ $(EGL_LIBS) \
$(NULL)
+if ANDROID
+AM_LDFLAGS += -lui -llog
+endif # ANDROID
+
localedir = $(datadir)/locale
INCLUDES = \
diff --git a/testsuite/media/Makefile.am b/testsuite/media/Makefile.am
index a6cc498..1834cfd 100644
--- a/testsuite/media/Makefile.am
+++ b/testsuite/media/Makefile.am
@@ -41,6 +41,7 @@ EXTRA_DIST = \
majorscale.sco \
brokenchord.wav \
audio_timewarp.flv \
+ silence.mp3 \
$(NULL)
.sco.wav:
diff --git a/testsuite/media/silence.mp3 b/testsuite/media/silence.mp3
new file mode 100644
index 0000000..4b10adb
Binary files /dev/null and b/testsuite/media/silence.mp3 differ
diff --git a/testsuite/misc-haxe.all/classes.all/net/NetStream_as.hx b/testsuite/misc-haxe.all/classes.all/net/NetStream_as.hx
index 4f186a0..d6771f4 100644
--- a/testsuite/misc-haxe.all/classes.all/net/NetStream_as.hx
+++ b/testsuite/misc-haxe.all/classes.all/net/NetStream_as.hx
@@ -49,20 +49,20 @@ class NetStream_as {
#if !flash6
#if !flash9
var nc:NetConnection = new NetConnection();
- nc.connect(null);
+ nc.connect(null);
var x1:NetStream = new NetStream(nc);
- var my_video:Video = untyped Video.attachVideo(x1);
- x1.play("test");
+ var my_video:Video = untyped Video.attachVideo(x1);
+ x1.play("test");
#else
- var nc:NetConnection = new NetConnection();
- nc.connect(null);
- var x1:NetStream = new NetStream(nc);
- x1.addEventListener(NetStatusEvent.NET_STATUS, function(e){ trace(e);});
+ var nc:NetConnection = new NetConnection();
+ nc.connect(null);
+ var x1:NetStream = new NetStream(nc);
+ x1.addEventListener(NetStatusEvent.NET_STATUS, function(e){ trace(e);});
x1.addEventListener(AsyncErrorEvent.ASYNC_ERROR, function(e){trace(e);});
-
- var my_video:Video = new Video();
- my_video.attachNetStream(x1);
- x1.play("/home/sharad/Desktop/cubes.swf");
+
+ var my_video:Video = new Video();
+ my_video.attachNetStream(x1);
+ x1.play("/home/sharad/Desktop/cubes.swf");
#end
// Make sure we actually get a valid class
if (Std.is(x1, NetStream)) {
@@ -70,200 +70,200 @@ class NetStream_as {
} else {
DejaGnu.fail("NetStream class doesn't exist");
}
- // Tests to see if all the properties exist. All these do is test for
- // existance of a property, and don't test the functionality at all. This
- // is primarily useful only to test completeness of the API implementation.
- //FIXME: This read-only property must be initialized before it can be tested
- if (Type.typeof(x1.bufferLength) == ValueType.TInt) {
- DejaGnu.pass("NetStream.bufferLength property exists");
- } else {
- DejaGnu.fail("NetStream.bufferLength property doesn't exist");
- }
- if (Type.typeof(x1.bufferTime) == ValueType.TFloat) {
- DejaGnu.pass("NetStream.bufferTime property exists");
- } else {
- DejaGnu.fail("NetStream.bufferTime property doesn't exist");
- }
- if (Type.typeof(x1.bytesLoaded) == ValueType.TInt) {
- DejaGnu.pass("NetStream.bytesLoaded property exists");
- } else {
- DejaGnu.fail("NetStream.bytesLoaded property doesn't exist");
- }
- #if flash9
- if (Type.typeof(x1.bytesTotal) == ValueType.TFloat) {
- DejaGnu.pass("NetStream.bytesTotal property exists");
- } else {
- DejaGnu.fail("NetStream.bytesTotal property doesn't exist");
- }
- #end
- if (Type.typeof(x1.time) == ValueType.TInt) {
- DejaGnu.pass("NetStream.time property exists");
- } else {
- DejaGnu.fail("NetStream.time property doesn't exist");
- }
+ // Tests to see if all the properties exist. All these do is test for
+ // existance of a property, and don't test the functionality at all. This
+ // is primarily useful only to test completeness of the API implementation.
+ //FIXME: This read-only property must be initialized before it can be tested
+ if (Type.typeof(x1.bufferLength) == ValueType.TInt) {
+ DejaGnu.pass("NetStream.bufferLength property exists");
+ } else {
+ DejaGnu.fail("NetStream.bufferLength property doesn't exist");
+ }
+ if (Type.typeof(x1.bufferTime) == ValueType.TFloat) {
+ DejaGnu.pass("NetStream.bufferTime property exists");
+ } else {
+ DejaGnu.fail("NetStream.bufferTime property doesn't exist");
+ }
+ if (Type.typeof(x1.bytesLoaded) == ValueType.TInt) {
+ DejaGnu.pass("NetStream.bytesLoaded property exists");
+ } else {
+ DejaGnu.fail("NetStream.bytesLoaded property doesn't exist");
+ }
+#if flash9
+ if (Type.typeof(x1.bytesTotal) == ValueType.TFloat) {
+ DejaGnu.pass("NetStream.bytesTotal property exists");
+ } else {
+ DejaGnu.fail("NetStream.bytesTotal property doesn't exist");
+ }
+#end
+ if (Type.typeof(x1.time) == ValueType.TInt) {
+ DejaGnu.pass("NetStream.time property exists");
+ } else {
+ DejaGnu.fail("NetStream.time property doesn't exist");
+ }
#if !flash9
- if (Type.typeof(x1.bytesTotal) == ValueType.TInt) {
- DejaGnu.pass("NetStream.bytesTotal property exists");
- } else {
- DejaGnu.fail("NetStream.bytesTotal property doesn't exist");
- }
- if (Type.typeof(x1.currentFps) == ValueType.TInt) {
- DejaGnu.pass("NetStream.currentFps property exists");
- } else {
- DejaGnu.fail("NetStream.currentFps property doesn't exist");
- }
+ if (Type.typeof(x1.bytesTotal) == ValueType.TInt) {
+ DejaGnu.pass("NetStream.bytesTotal property exists");
+ } else {
+ DejaGnu.fail("NetStream.bytesTotal property doesn't exist");
+ }
+ if (Type.typeof(x1.currentFps) == ValueType.TInt) {
+ DejaGnu.pass("NetStream.currentFps property exists");
+ } else {
+ DejaGnu.fail("NetStream.currentFps property doesn't exist");
+ }
#end
- // Not implemented for gnash
- if (Type.typeof(x1.liveDelay) == ValueType.TInt) {
- DejaGnu.pass("NetStream.liveDelay property exists");
- } else {
- DejaGnu.xfail("NetStream.liveDelay property doesn't exist");
- }
+ // Not implemented for gnash
+ if (Type.typeof(x1.liveDelay) == ValueType.TInt) {
+ DejaGnu.xpass("NetStream.liveDelay property exists");
+ } else {
+ DejaGnu.xfail("NetStream.liveDelay property doesn't exist");
+ }
#if flash9
- if (Type.typeof(x1.currentFPS) == ValueType.TInt) {
- DejaGnu.pass("NetStream.currentFPS property exists");
- } else {
- DejaGnu.fail("NetStream.currentFPS property doesn't exist");
- }
- //FIXME: This property only exists in haXe
- if (Type.typeof(x1.audioCodec) == ValueType.TInt) {
- DejaGnu.pass("NetStream.audioCodec property exists");
- } else {
- DejaGnu.fail("NetStream.audioCodec property doesn't exist");
- }
- if (Type.typeof(x1.checkPolicyFile) == ValueType.TBool) {
- DejaGnu.pass("NetStream.checkPolicyFile property exists");
- } else {
- DejaGnu.fail("NetStream.checkPolicyFile property doesn't exist");
- }
- if (Std.is(x1.client, Dynamic)) {
- DejaGnu.pass("NetStream.client property exists");
- } else {
- DejaGnu.fail("NetStream.client property doesn't exist");
- }
- //FIXME: This property only exists in haXe
- if (Type.typeof(x1.decodedFrames) == ValueType.TInt) {
- DejaGnu.pass("NetStream.decodedFrames property exists");
- } else {
- DejaGnu.fail("NetStream.decodedFrames property doesn't exist");
- }
- if (Type.typeof(x1.objectEncoding) == ValueType.TInt) {
- DejaGnu.pass("NetStream.objectEncoding property exists");
- } else {
- DejaGnu.fail("NetStream.objectEncoding property doesn't exist");
- }
- if (Std.is(x1.soundTransform, SoundTransform)) {
- DejaGnu.pass("NetStream.soundTransform property exists");
- } else {
- DejaGnu.fail("NetStream.soundTransform property doesn't exist");
- }
- //FIXME: This property only exists in haXe
- if (Type.typeof(x1.videoCodec) == ValueType.TInt) {
- DejaGnu.pass("NetStream.videoCodec property exists");
- } else {
- DejaGnu.fail("NetStream.videoCodec property doesn't exist");
- }
+ if (Type.typeof(x1.currentFPS) == ValueType.TInt) {
+ DejaGnu.pass("NetStream.currentFPS property exists");
+ } else {
+ DejaGnu.fail("NetStream.currentFPS property doesn't exist");
+ }
+ //FIXME: This property only exists in haXe
+ if (Type.typeof(x1.audioCodec) == ValueType.TInt) {
+ DejaGnu.pass("NetStream.audioCodec property exists");
+ } else {
+ DejaGnu.fail("NetStream.audioCodec property doesn't exist");
+ }
+ if (Type.typeof(x1.checkPolicyFile) == ValueType.TBool) {
+ DejaGnu.pass("NetStream.checkPolicyFile property exists");
+ } else {
+ DejaGnu.fail("NetStream.checkPolicyFile property doesn't exist");
+ }
+ if (Std.is(x1.client, Dynamic)) {
+ DejaGnu.pass("NetStream.client property exists");
+ } else {
+ DejaGnu.fail("NetStream.client property doesn't exist");
+ }
+ //FIXME: This property only exists in haXe
+ if (Type.typeof(x1.decodedFrames) == ValueType.TInt) {
+ DejaGnu.pass("NetStream.decodedFrames property exists");
+ } else {
+ DejaGnu.fail("NetStream.decodedFrames property doesn't exist");
+ }
+ if (Type.typeof(x1.objectEncoding) == ValueType.TInt) {
+ DejaGnu.pass("NetStream.objectEncoding property exists");
+ } else {
+ DejaGnu.fail("NetStream.objectEncoding property doesn't exist");
+ }
+ if (Std.is(x1.soundTransform, SoundTransform)) {
+ DejaGnu.pass("NetStream.soundTransform property exists");
+ } else {
+ DejaGnu.fail("NetStream.soundTransform property doesn't exist");
+ }
+ //FIXME: This property only exists in haXe
+ if (Type.typeof(x1.videoCodec) == ValueType.TInt) {
+ DejaGnu.pass("NetStream.videoCodec property exists");
+ } else {
+ DejaGnu.fail("NetStream.videoCodec property doesn't exist");
+ }
#end
-
- // Tests to see if all the methods exist. All these do is test for
- // existance of a method, and don't test the functionality at all. This
- // is primarily useful only to test completeness of the API implementation.
- //FIXME: This function exists for AS2 in haXe, but not in Adobe spec
- if (Type.typeof(x1.attachAudio) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::attachAudio() method exists");
- } else {
- DejaGnu.fail("NetStream::attachAudio() method doesn't exist");
- }
- if (Type.typeof(x1.close) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::close() method exists");
- } else {
- DejaGnu.fail("NetStream::close() method doesn't exist");
- }
- if (Type.typeof(x1.pause) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::pause() method exists");
- } else {
- DejaGnu.fail("NetStream::pause() method doesn't exist");
- }
- if (Type.typeof(x1.play) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::play() method exists");
- } else {
- DejaGnu.fail("NetStream::play() method doesn't exist");
- }
- //FIXME: This function exists for AS2 in haXe, but not in Adobe spec
- if (Type.typeof(x1.publish) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::publish() method exists");
- } else {
- DejaGnu.fail("NetStream::publish() method doesn't exist");
- }
- //FIXME: This function exists for AS2 in haXe, but not in Adobe spec
- if (Type.typeof(x1.receiveAudio) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::receiveAudio() method exists");
- } else {
- DejaGnu.fail("NetStream::receiveAudio() method doesn't exist");
- }
- //FIXME: This function exists for AS2 in haXe, but not in Adobe spec
- if (Type.typeof(x1.receiveVideo) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::receiveVideo() method exists");
- } else {
- DejaGnu.fail("NetStream::receiveVideo() method doesn't exist");
- }
- if (Type.typeof(x1.seek) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::seek() method exists");
- } else {
- DejaGnu.fail("NetStream::seek() method doesn't exist");
- }
- //FIXME: This function exists for AS2 in haXe, but not in Adobe spec
- if (Type.typeof(x1.send) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::send() method exists");
- } else {
- DejaGnu.fail("NetStream::send() method doesn't exist");
- }
- if (Type.typeof(x1.close) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::close() method exists");
- } else {
- DejaGnu.fail("NetStream::close() method doesn't exist");
- }
+
+ // Tests to see if all the methods exist. All these do is test for
+ // existance of a method, and don't test the functionality at all. This
+ // is primarily useful only to test completeness of the API implementation.
+ //FIXME: This function exists for AS2 in haXe, but not in Adobe spec
+ if (Type.typeof(x1.attachAudio) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::attachAudio() method exists");
+ } else {
+ DejaGnu.fail("NetStream::attachAudio() method doesn't exist");
+ }
+ if (Type.typeof(x1.close) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::close() method exists");
+ } else {
+ DejaGnu.fail("NetStream::close() method doesn't exist");
+ }
+ if (Type.typeof(x1.pause) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::pause() method exists");
+ } else {
+ DejaGnu.fail("NetStream::pause() method doesn't exist");
+ }
+ if (Type.typeof(x1.play) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::play() method exists");
+ } else {
+ DejaGnu.fail("NetStream::play() method doesn't exist");
+ }
+ //FIXME: This function exists for AS2 in haXe, but not in Adobe spec
+ if (Type.typeof(x1.publish) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::publish() method exists");
+ } else {
+ DejaGnu.fail("NetStream::publish() method doesn't exist");
+ }
+ //FIXME: This function exists for AS2 in haXe, but not in Adobe spec
+ if (Type.typeof(x1.receiveAudio) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::receiveAudio() method exists");
+ } else {
+ DejaGnu.fail("NetStream::receiveAudio() method doesn't exist");
+ }
+ //FIXME: This function exists for AS2 in haXe, but not in Adobe spec
+ if (Type.typeof(x1.receiveVideo) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::receiveVideo() method exists");
+ } else {
+ DejaGnu.fail("NetStream::receiveVideo() method doesn't exist");
+ }
+ if (Type.typeof(x1.seek) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::seek() method exists");
+ } else {
+ DejaGnu.fail("NetStream::seek() method doesn't exist");
+ }
+ //FIXME: This function exists for AS2 in haXe, but not in Adobe spec
+ if (Type.typeof(x1.send) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::send() method exists");
+ } else {
+ DejaGnu.fail("NetStream::send() method doesn't exist");
+ }
+ if (Type.typeof(x1.close) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::close() method exists");
+ } else {
+ DejaGnu.fail("NetStream::close() method doesn't exist");
+ }
#if !flash9
- if (Type.typeof(x1.setBufferTime) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::setBufferTime() method exists");
- } else {
- DejaGnu.fail("NetStream::setBufferTime() method doesn't exist");
- }
+ if (Type.typeof(x1.setBufferTime) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::setBufferTime() method exists");
+ } else {
+ DejaGnu.fail("NetStream::setBufferTime() method doesn't exist");
+ }
#end
#if flash9
- if (Type.typeof(x1.attachCamera) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::attachCamera() method exists");
- } else {
- DejaGnu.fail("NetStream::attachCamera() method doesn't exist");
- }
- //FIXME: Property receiveVideoFPS not found on flash.net.NetStream and there is no default value
- // if (Type.typeof(x1.receiveVideoFPS) == ValueType.TFunction) {
- // DejaGnu.pass("NetStream::receiveVideoFPS() method exists");
- // } else {
- // DejaGnu.fail("NetStream::receiveVideoFPS() method doesn't exist");
- // }
- // AIR only
- // if (x1.resetDRMVouchers == null) {
- // DejaGnu.pass("NetStream::resetDRMVouchers() method exists");
- // } else {
- // DejaGnu.fail("NetStream::resetDRMVouchers() method doesn't exist");
- // }
- if (Type.typeof(x1.resume) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::resume() method exists");
- } else {
- DejaGnu.fail("NetStream::resume() method doesn't exist");
- }
- // AIR only
- // if (x1.setDRMAuthenticationCredentials == null) {
- // DejaGnu.pass("NetStream::setDRMAuthenticationCredentials() method exists");
- // } else {
- // DejaGnu.fail("NetStream::setDRMAuthenticationCredentials() method doesn't exist");
- // }
- if (Type.typeof(x1.togglePause) == ValueType.TFunction) {
- DejaGnu.pass("NetStream::togglePause() method exists");
- } else {
- DejaGnu.fail("NetStream::togglePause() method doesn't exist");
- }
+ if (Type.typeof(x1.attachCamera) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::attachCamera() method exists");
+ } else {
+ DejaGnu.fail("NetStream::attachCamera() method doesn't exist");
+ }
+ //FIXME: Property receiveVideoFPS not found on flash.net.NetStream and there is no default value
+ // if (Type.typeof(x1.receiveVideoFPS) == ValueType.TFunction) {
+ // DejaGnu.pass("NetStream::receiveVideoFPS() method exists");
+ // } else {
+ // DejaGnu.fail("NetStream::receiveVideoFPS() method doesn't exist");
+ // }
+ // AIR only
+ // if (x1.resetDRMVouchers == null) {
+ // DejaGnu.pass("NetStream::resetDRMVouchers() method exists");
+ // } else {
+ // DejaGnu.fail("NetStream::resetDRMVouchers() method doesn't exist");
+ // }
+ if (Type.typeof(x1.resume) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::resume() method exists");
+ } else {
+ DejaGnu.fail("NetStream::resume() method doesn't exist");
+ }
+ // AIR only
+ // if (x1.setDRMAuthenticationCredentials == null) {
+ // DejaGnu.pass("NetStream::setDRMAuthenticationCredentials() method exists");
+ // } else {
+ // DejaGnu.fail("NetStream::setDRMAuthenticationCredentials() method doesn't exist");
+ // }
+ if (Type.typeof(x1.togglePause) == ValueType.TFunction) {
+ DejaGnu.pass("NetStream::togglePause() method exists");
+ } else {
+ DejaGnu.fail("NetStream::togglePause() method doesn't exist");
+ }
#end
// Call this after finishing all tests. It prints out the totals.
@@ -277,6 +277,6 @@ class NetStream_as {
// local Variables:
// mode: C++
-// indent-tabs-mode: t
+// indent-tabs-mode: nil
// End:
diff --git a/testsuite/misc-ming.all/Makefile.am b/testsuite/misc-ming.all/Makefile.am
index fbbae8b..05e8d81 100644
--- a/testsuite/misc-ming.all/Makefile.am
+++ b/testsuite/misc-ming.all/Makefile.am
@@ -93,6 +93,10 @@ AM_LDFLAGS = \
$(top_builddir)/libcore/libgnashcore.la \
$(NULL)
+if ANDROID
+AM_LDFLAGS += -lui -llog
+endif # ANDROID
+
check_PROGRAMS = \
ResolveEventsTest \
ResolveEventsTest-Runner \
@@ -144,6 +148,7 @@ check_PROGRAMS = \
callFunction_test \
duplicate_movie_clip_test \
duplicate_movie_clip_test2 \
+ empty_clip_action_test \
event_handler_scope_test \
masks_testrunner \
key_event_test \
@@ -233,6 +238,7 @@ check_SCRIPTS = \
callFunction_testrunner \
duplicate_movie_clip_testrunner \
duplicate_movie_clip_test2runner \
+ empty_clip_action_testrunner \
event_handler_scope_testrunner \
matrix_testrunner \
static_vs_dynamic1_testrunner \
@@ -853,6 +859,19 @@ duplicate_movie_clip_test2runner: $(srcdir)/../generic-testrunner.sh duplicate_m
chmod 755 $@
+empty_clip_action_test_SOURCES = \
+ empty_clip_action_test.c \
+ $(NULL)
+empty_clip_action_test_LDADD = libgnashmingutils.la
+
+empty_clip_action_test.swf: empty_clip_action_test
+ ./empty_clip_action_test $(abs_mediadir)
+
+empty_clip_action_testrunner: $(srcdir)/../generic-testrunner.sh empty_clip_action_test.swf
+ sh $(srcdir)/../generic-testrunner.sh -r5 $(top_builddir) empty_clip_action_test.swf > $@
+ chmod 755 $@
+
+
event_handler_scope_test_SOURCES = \
event_handler_scope_test.c \
$(NULL)
@@ -1478,10 +1497,12 @@ instanceNameTestRunner: $(srcdir)/../generic-testrunner.sh instanceNameTest.swf
sh $(srcdir)/../generic-testrunner.sh $(top_builddir) instanceNameTest.swf > $@
chmod 755 $@
-Dejagnu_SOURCES = \
- Dejagnu.c \
+Dejagnu_SOURCES = Dejagnu.c
+Dejagnu_LDADD = \
+ $(top_builddir)/testsuite/libtestsuite.la \
+ libgnashmingutils.la \
+ $(AM_LDFLAGS) \
$(NULL)
-Dejagnu_LDADD = libgnashmingutils.la
Dejagnu.swf: Dejagnu
./Dejagnu $(abs_mediadir)
@@ -1530,6 +1551,7 @@ TEST_CASES = \
callFunction_testrunner \
duplicate_movie_clip_testrunner \
duplicate_movie_clip_test2runner \
+ empty_clip_action_testrunner \
event_handler_scope_testrunner \
masks_testrunner \
masks_test2runner \
diff --git a/testsuite/misc-ming.all/NetStream-SquareTest.c b/testsuite/misc-ming.all/NetStream-SquareTest.c
index 106eaee..f393f8d 100644
--- a/testsuite/misc-ming.all/NetStream-SquareTest.c
+++ b/testsuite/misc-ming.all/NetStream-SquareTest.c
@@ -91,7 +91,7 @@ main(int argc, char** argv)
"nc.connect(null);"
"check(nc.isConnected, 'NetConnection is connected after .connect(null)');"
"check(!NetStream.prototype.hasOwnProperty('currentFPS'));" // version 7 here
- "xcheck(!NetStream.prototype.hasOwnProperty('currentFps'));"
+ "check(!NetStream.prototype.hasOwnProperty('currentFps'));"
"stream = new NetStream();"
"check_equals ( typeof(stream.bytesTotal), 'undefined' );" // not connected..
"stream.play('fake');" // just test not to segfault..
diff --git a/testsuite/misc-ming.all/TODO b/testsuite/misc-ming.all/TODO
index 8d82b09..44d41d6 100644
--- a/testsuite/misc-ming.all/TODO
+++ b/testsuite/misc-ming.all/TODO
@@ -1,3 +1,2 @@
- Test runner for BitmapSmoothingTest.c
- Test runner for easysound.as ?
-- Check, improve and automate red5test.as !
diff --git a/testsuite/misc-ming.all/Video-EmbedSquareTest.c b/testsuite/misc-ming.all/Video-EmbedSquareTest.c
index 1fea05a..89682e6 100644
--- a/testsuite/misc-ming.all/Video-EmbedSquareTest.c
+++ b/testsuite/misc-ming.all/Video-EmbedSquareTest.c
@@ -89,7 +89,10 @@ main(int argc, char** argv)
mo = newSWFMovie();
SWFMovie_setDimension(mo, 320, 96);
- if (mo == NULL) return -1;
+ if (mo == NULL) {
+ fclose(flv);
+ return -1;
+ }
SWFMovie_setRate(mo, 5);
diff --git a/testsuite/misc-ming.all/XMLSocketTest.as b/testsuite/misc-ming.all/XMLSocketTest.as
index b1d883a..586e82c 100644
--- a/testsuite/misc-ming.all/XMLSocketTest.as
+++ b/testsuite/misc-ming.all/XMLSocketTest.as
@@ -71,14 +71,75 @@ function handleDisconnect() {
checkResults();
};
-myXML = new XMLSocket;
-myXML.onConnect = handleConnect;
-myXML.onData = handleData;
-myXML.onClose = handleDisconnect;
-receivedArray = new Array();
-
-ret = myXML.connect("localhost.localdomain", 2229);
-check_equals(ret, true);
+function test1()
+{
+ trace("-- RUNNING TEST1 --");
+ myXML = new XMLSocket;
+ myXML.onConnect = handleConnect;
+ myXML.onData = handleData;
+ myXML.onClose = handleDisconnect;
+ receivedArray = new Array();
+
+ ret = myXML.connect("localhost", 2229);
+ check_equals(ret, true);
+}
+
+// Check that XMLSocket can be instanciated from subclass
+// See https://savannah.gnu.org/bugs/?38084
+function test2()
+{
+ trace("-- RUNNING TEST2 --");
+ receivedArray = new Array();
+
+ SC1 = function() { };
+ SC1.name = 'SC1 ctor';
+ SC1.prototype = new XMLSocket();
+
+ // None of these get called
+ SC1.prototype.onConnect = function() { fail("SC1 prototype onConnect called"); };
+ SC1.prototype.onData = function() { fail("SC1 prototype onData called"); };
+ SC1.prototype.onClose = function() { fail("SC1 prototype onClose called"); };
+
+ //trace("SC1.constructor is: " + SC1.constructor);
+ //trace("SC1.constructor.name is: " + SC1.constructor.name);
+ //trace("SC1.__constructor__ is: " + SC1.__constructor__);
+
+ SC2 = function() { };
+ SC2.prototype = new SC1();
+
+ // None of these get called
+ SC2.prototype.onConnect = function() { fail("SC2 prototype onConnect called"); };
+ SC2.prototype.onData = function() { fail("SC2 prototype onData called"); };
+ SC2.prototype.onClose = function() { fail("SC2 prototype onClose called"); };
+
+
+ trace('About to instanciate an SC2 now');
+ o = new SC2();
+ o.onConnect = function() { fail("instance onConnect called"); };
+ o.onData = function() { fail("instance onData called"); };
+ o.onClose = function() { fail("instance onClose called"); };
+
+ ret = o.connect("localhost", 2229);
+ xcheck_equals(ret, true);
+ nextTest();
+}
+
+currtest = 0;
+tests = new Array();
+tests.push(test1);
+tests.push(test2);
+
+function nextTest()
+{
+ if ( tests.length > currtest ) {
+ tests[currtest++]();
+ } else {
+ trace("ENDOFTEST");
+ loadMovie ("FSCommand:quit", "");
+ }
+}
+
+nextTest();
stop();
@@ -96,15 +157,13 @@ function checkResults() {
check_equals(receivedArray[9], expectedArray[9]);
check_equals(receivedArray[10], expectedArray[10]);
check_equals(receivedArray[11], expectedArray[11]);
+ // NOTE: this ('undefined') fails with LNX 10,0,12,10
check_equals(receivedArray[12], expectedArray[12]);
check_equals(receivedArray[13], expectedArray[13]);
check_equals(receivedArray[14], expectedArray[14]);
check_equals(receivedArray[15].length, 15000);
check_equals(receivedArray[15].charAt(0), 'a');
check_equals(receivedArray[16], expectedArray[16]);
-
- trace("ENDOFTEST");
-
- loadMovie ("FSCommand:quit", "");
+ nextTest();
};
diff --git a/testsuite/misc-ming.all/event_handler_scope_test.c b/testsuite/misc-ming.all/empty_clip_action_test.c
similarity index 50%
copy from testsuite/misc-ming.all/event_handler_scope_test.c
copy to testsuite/misc-ming.all/empty_clip_action_test.c
index f5132ee..1577c5e 100644
--- a/testsuite/misc-ming.all/event_handler_scope_test.c
+++ b/testsuite/misc-ming.all/empty_clip_action_test.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2005-2013 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
@@ -20,20 +20,55 @@
#include <stdlib.h>
#include <stdio.h>
#include <ming.h>
+#include <assert.h>
#include "ming_utils.h"
#define OUTPUT_VERSION 6
-#define OUTPUT_FILENAME "event_handler_scope_test.swf"
+#define OUTPUT_FILENAME "empty_clip_action_test.swf"
+
+// So this is about as hacky as you get. The idea is that we change the
+// CHANGEOBJECT2 tag so that the first action (containing just a single
+// null-byte) is truncated to nothing: event_length is updated to zero, the
+// following two bytes are skipped and then of course the tag length itself has
+// to be reduced by one.
+
+// So far as I'm aware you can't do this programmatically in Ming, but of
+// course if the output stream ever changes this will be completely broken.
+void spesiulOutputMethod(byte b, void *data);
+void spesiulOutputMethod(byte b, void *data)
+{
+ static long count = 0;
+ byte c = b;
+ FILE *f = (FILE *)data;
+
+ if (count == 0x293b) {
+ assert( b == 122);
+ c = 120;
+ }
+ if (count == 0x2953) {
+ assert( b == 2);
+ c = 0;
+ }
+ if (count == 0x2954 || count == 0x2955) {
+ assert( b == 0);
+ ++count;
+ return;
+ }
+
+ fputc(c, f);
+ ++count;
+}
+
int
main(int argc, char** argv)
{
SWFMovie mo;
- SWFMovieClip mc, dejagnuclip;
- SWFDisplayItem it;
- SWFShape sh_red;
+ SWFMovieClip mc2, dejagnuclip;
+ SWFDisplayItem it2;
+ FILE* fh;
const char *srcdir=".";
if ( argc>1 )
@@ -51,56 +86,42 @@ main(int argc, char** argv)
dejagnuclip = get_dejagnu_clip((SWFBlock)get_default_font(srcdir), 10, 0, 0, 800, 600);
SWFMovie_add(mo, (SWFBlock)dejagnuclip);
- add_actions(mo, "x1=0; x2=0; x3=0;");
+ add_actions(mo, "x2=0;");
SWFMovie_nextFrame(mo); /* 1st frame */
- mc = newSWFMovieClip();
- sh_red = make_fill_square (100, 200, 60, 60, 255, 0, 0, 255, 0, 0);
- SWFMovieClip_add(mc, (SWFBlock)sh_red);
- SWFMovieClip_nextFrame(mc); //frame1
- SWFMovieClip_nextFrame(mc); //frame2
- add_clip_actions(mc, " if (scope_test == 1); scope_test = 2; stop();");
- SWFMovieClip_nextFrame(mc); //frame3
-
- it = SWFMovie_add(mo, (SWFBlock)mc);
- SWFDisplayItem_setDepth(it, 20);
- SWFDisplayItem_setName(it, "mc");
- /* Define onClipEnterFrame */
- SWFDisplayItem_addAction(it,
+ mc2 = newSWFMovieClip();
+
+ it2 = SWFMovie_add(mo, (SWFBlock)mc2);
+ SWFDisplayItem_setDepth(it2, 20);
+ SWFDisplayItem_setName(it2, "mc2");
+ SWFDisplayItem_addAction(it2,
+ compileSWFActionCode(""),
+ SWFACTION_KEYPRESS);
+ SWFDisplayItem_addAction(it2,
compileSWFActionCode(" _root.note('onClipEnterFrame triggered'); "
- " var scope_test = 1; "), // Define mc.scope_test
+ " _root.x2 = 14; "),
SWFACTION_ENTERFRAME);
- /* Define onEnterFrame */
- add_actions(mo, " mc.onEnterFrame = function () "
- " { _root.note('user defined onEnterFrame called'); "
- " scope_test = 3; " // Define _root.scope_test
- " var scope_test = 4; }; " ); // Define a local var
-
- check_equals(mo, "_root.scope_test", "undefined");
- check_equals(mo, "_root.mc.scope_test", "undefined");
+
SWFMovie_nextFrame(mo); /* 2nd frame */
- check_equals(mo, "_root.mc.scope_test", "1");
- check_equals(mo, "_root.scope_test", "3");
+ check_equals(mo, "_root.x2", "14");
SWFMovie_nextFrame(mo); /* 3rd frame */
- check_equals(mo, "_root.mc.scope_test", "2");
+ SWFDisplayItem_remove(it2);
+
SWFMovie_nextFrame(mo); /* 4th frame */
-
- check_equals(mo, "_root.scope_test", "3");
- SWFMovie_nextFrame(mo); /* 5th frame */
-
- SWFDisplayItem_remove(it);
- check_equals(mo, "_root.mc.scope_test", "undefined");
+
add_actions(mo, " _root.totals(); stop(); ");
- SWFMovie_nextFrame(mo); /* 6th frame */
- //Output movie
+ SWFMovie_nextFrame(mo); /* 5th frame */
+
+ // Output movie
puts("Saving " OUTPUT_FILENAME );
- SWFMovie_save(mo, OUTPUT_FILENAME);
+ // ..but wait! Now entering crazy-land.
+ fh = fopen(OUTPUT_FILENAME, "w");
+ SWFMovie_output(mo, spesiulOutputMethod, fh);
+ fclose(fh);
return 0;
}
-
-
diff --git a/testsuite/misc-ming.all/loading/loadMovieTestRunner.cpp b/testsuite/misc-ming.all/loading/loadMovieTestRunner.cpp
index 53d76f3..f3981a0 100644
--- a/testsuite/misc-ming.all/loading/loadMovieTestRunner.cpp
+++ b/testsuite/misc-ming.all/loading/loadMovieTestRunner.cpp
@@ -84,7 +84,7 @@ waitForLoad(MovieClip* from)
// Wait for the movie to load
// TODO: drop this test and use a self-containment instead
do {
- usleep(500); // give it some time...
+ usleep(5000); // give it some time...
tester->advance(); // loads (should) happen on next advance
coverart = getCoverArt();
} while (coverart == from);
diff --git a/testsuite/misc-ming.all/sound/EmbeddedSoundTest-Runner.cpp b/testsuite/misc-ming.all/sound/EmbeddedSoundTest-Runner.cpp
index fe4fb90..b31d731 100644
--- a/testsuite/misc-ming.all/sound/EmbeddedSoundTest-Runner.cpp
+++ b/testsuite/misc-ming.all/sound/EmbeddedSoundTest-Runner.cpp
@@ -47,7 +47,6 @@ main(int /*argc*/, char** /*argv*/)
assert(root);
VM& vm = getVM(*getObject(root));
- string_table& st = vm.getStringTable();
const size_t framecount = root->get_frame_count();
diff --git a/testsuite/misc-ming.all/sound/eventSoundTest1-Runner.cpp b/testsuite/misc-ming.all/sound/eventSoundTest1-Runner.cpp
index edaf52e..3f69e96 100644
--- a/testsuite/misc-ming.all/sound/eventSoundTest1-Runner.cpp
+++ b/testsuite/misc-ming.all/sound/eventSoundTest1-Runner.cpp
@@ -62,7 +62,6 @@ main(int /*argc*/, char** /*argv*/)
assert(root);
VM& vm = getVM(*getObject(root));
- string_table& st = vm.getStringTable();
if ( ! tester.canTestSound() )
{
diff --git a/testsuite/movies.all/Makefile.am b/testsuite/movies.all/Makefile.am
index 82dcf0a..4968a72 100644
--- a/testsuite/movies.all/Makefile.am
+++ b/testsuite/movies.all/Makefile.am
@@ -53,6 +53,10 @@ AM_LDFLAGS = \
$(OPENGL_LIBS) \
$(NULL)
+if ANDROID
+AM_LDFLAGS += -lui -llog
+endif # ANDROID
+
gravity_embedded_TestRunner_SOURCES = \
gravity_embedded-TestRunner.cpp \
$(NULL)
@@ -62,6 +66,7 @@ gravity_embedded_TestRunner_LDADD = \
$(NULL)
gravity_embedded_TestRunner_CXXFLAGS = \
-DSRCDIR='"$(srcdir)"' \
+ $(CROSS_CXXFLAGS) \
$(NULL)
gravity_embedded_TestRunner_DEPENDENCIES = \
$(top_builddir)/testsuite/libtestsuite.la \
@@ -78,6 +83,7 @@ tic_tac2_TestRunner_LDADD = \
$(NULL)
tic_tac2_TestRunner_CXXFLAGS = \
-DSRCDIR='"$(srcdir)"' \
+ $(CROSS_CXXFLAGS) \
$(NULL)
tic_tac2_TestRunner_DEPENDENCIES = \
$(top_builddir)/testsuite/libtestsuite.la \
diff --git a/testsuite/samples/Makefile.am b/testsuite/samples/Makefile.am
index ceca58c..5c59ef8 100644
--- a/testsuite/samples/Makefile.am
+++ b/testsuite/samples/Makefile.am
@@ -42,9 +42,17 @@ AM_CPPFLAGS = \
$(NULL)
AM_LDFLAGS = \
+ $(CROSS_LDFLAGS) \
$(OPENGL_LIBS) \
+ $(EGL_LIBS) \
$(NULL)
+if ANDROID
+LDADD = -lui -llog
+endif # ANDROID
+
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
+
GNASH_LIBS = \
$(top_builddir)/testsuite/libtestsuite.la \
$(top_builddir)/libcore/libgnashcore.la \
@@ -69,9 +77,11 @@ clip_as_button2_TestRunner_SOURCES = \
$(NULL)
clip_as_button2_TestRunner_LDADD = \
$(GNASH_LIBS) \
+ $(LDADD) \
$(NULL)
clip_as_button2_TestRunner_CXXFLAGS = \
-DSRCDIR=\"$(srcdir)\" \
+ $(CROSS_CXXFLAGS) \
$(NULL)
subshapes_TestRunner_SOURCES = \
@@ -79,9 +89,11 @@ subshapes_TestRunner_SOURCES = \
$(NULL)
subshapes_TestRunner_LDADD = \
$(GNASH_LIBS) \
+ $(LDADD) \
$(NULL)
subshapes_TestRunner_CXXFLAGS = \
-DSRCDIR=\"$(srcdir)\" \
+ $(CROSS_CXXFLAGS) \
$(NULL)
gotoFrameOnKeyEvent_TestRunner_SOURCES = \
@@ -89,9 +101,11 @@ gotoFrameOnKeyEvent_TestRunner_SOURCES = \
$(NULL)
gotoFrameOnKeyEvent_TestRunner_LDADD = \
$(GNASH_LIBS) \
+ $(LDADD) \
$(NULL)
gotoFrameOnKeyEvent_TestRunner_CXXFLAGS = \
-DSRCDIR=\"$(srcdir)\" \
+ $(CROSS_CXXFLAGS) \
$(NULL)
GotoAndPlayTestRunner: Makefile $(srcdir)/../generic-testrunner.sh $(srcdir)/GotoAndPlayTest.swf
@@ -107,9 +121,11 @@ test_15bpp_bitmap_TestRunner_SOURCES = \
$(NULL)
test_15bpp_bitmap_TestRunner_LDADD = \
$(GNASH_LIBS) \
+ $(LDADD) \
$(NULL)
test_15bpp_bitmap_TestRunner_CXXFLAGS = \
-DSRCDIR=\"$(srcdir)\" \
+ $(CROSS_CXXFLAGS) \
$(NULL)
clean-local:
diff --git a/utilities/Makefile.am b/utilities/Makefile.am
index 9aceb12..e4fa18e 100644
--- a/utilities/Makefile.am
+++ b/utilities/Makefile.am
@@ -27,18 +27,30 @@ AUTOMAKE_OPTIONS = # dejagnu
GNASH_LIBS = \
$(top_builddir)/libcore/libgnashcore.la \
$(top_builddir)/libbase/libgnashbase.la \
- $(top_builddir)/libmedia/libgnashmedia.la \
- $(top_builddir)/libsound/libgnashsound.la \
$(top_builddir)/librender/libgnashrender.la \
$(NULL)
+if BUILD_LIBMEDIA
+GNASH_LIBS += $(top_builddir)/libmedia/libgnashmedia.la
+endif
+if BUILD_LIBSOUND
+GNASH_LIBS += $(top_builddir)/libsound/libgnashsound.la
+endif
+
+AM_CXXFLAGS = $(CROSS_CXXFLAGS)
+
AM_LDFLAGS = \
$(LIBINTL) \
$(LIBADD_DL) \
$(PTHREAD_LIBS) \
+ $(BOOST_LIBS) \
$(GNASH_LIBS) \
$(NULL)
+if ANDROID
+AM_LDFLAGS += -lui -llog
+endif # ANDROID
+
localedir = $(datadir)/locale
AM_CPPFLAGS = \
diff --git a/utilities/findmicrophones.cpp b/utilities/findmicrophones.cpp
index 51e9e97..4849f2d 100644
--- a/utilities/findmicrophones.cpp
+++ b/utilities/findmicrophones.cpp
@@ -20,6 +20,8 @@
#include "gnashconfig.h"
#endif
+#include "gst/GlibDeprecated.h"
+
#include "rc.h"
#ifdef HAVE_GST_GST_H
#include "gst/gst.h"
diff --git a/utilities/findwebcams.cpp b/utilities/findwebcams.cpp
index 8acc433..f3ba993 100644
--- a/utilities/findwebcams.cpp
+++ b/utilities/findwebcams.cpp
@@ -20,6 +20,8 @@
#include "gnashconfig.h"
#endif
+#include "gst/GlibDeprecated.h"
+
#include <vector>
#include <string>
#include <iostream>
diff --git a/utilities/processor.cpp b/utilities/processor.cpp
index e11b375..95c1f94 100644
--- a/utilities/processor.cpp
+++ b/utilities/processor.cpp
@@ -54,6 +54,7 @@
#include "StreamProvider.h"
#include "RunResources.h"
#include "HostInterface.h"
+#include "Movie.h"
#ifdef RENDERER_AGG
#include "Renderer.h"
@@ -61,6 +62,7 @@
#endif
extern "C"{
+
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
@@ -82,6 +84,7 @@ namespace boost
}
#endif
+
// How many seconds to wait for a frame advancement
// before kicking the movie (forcing it to next frame)
static const double waitforadvance = 5;
@@ -328,12 +331,15 @@ main(int argc, char *argv[])
return EXIT_FAILURE;
}
+#ifdef USE_MEDIA
boost::shared_ptr<gnash::media::MediaHandler> mediaHandler;
- boost::shared_ptr<sound::sound_handler> soundHandler;
-
std::string mh = rcfile.getMediaHandler();
mediaHandler.reset(media::MediaFactory::instance().get(mh));
+#endif
+#if defined(USE_SOUND) && defined(USE_MEDIA)
+ boost::shared_ptr<sound::sound_handler> soundHandler;
soundHandler.reset(new sound::NullSoundHandler(mediaHandler.get()));
+#endif
boost::shared_ptr<SWF::TagLoadersTable> loaders(new SWF::TagLoadersTable());
addDefaultLoaders(*loaders);
@@ -355,8 +361,12 @@ main(int argc, char *argv[])
{
RunResources runResources;
+#if defined(USE_SOUND) && defined(USE_MEDIA)
runResources.setSoundHandler(soundHandler);
+#endif
+#ifdef USE_MEDIA
runResources.setMediaHandler(mediaHandler);
+#endif
runResources.setTagLoaders(loaders);
boost::shared_ptr<StreamProvider> sp(new StreamProvider(*i, *i));
runResources.setStreamProvider(sp);
hooks/post-receive
--
GNU Shockwave Flash (SWF) player
More information about the pkg-flash-devel
mailing list