[Pkg-ruby-extras-maintainers] r949 - in packages-wip: .
libxslt-ruby libxslt-ruby/trunk libxslt-ruby/trunk/debian
libxslt-ruby/trunk/debian/patches libxslt-ruby/trunk/debug
libxslt-ruby/trunk/examples libxslt-ruby/trunk/tests
libxslt-ruby/trunk/tests/imports libxslt-ruby/trunk/tests/subdir
Filipe Lautert
filipe-guest at alioth.debian.org
Fri Nov 3 17:17:39 CET 2006
Author: filipe-guest
Date: 2006-11-03 17:17:38 +0100 (Fri, 03 Nov 2006)
New Revision: 949
Added:
packages-wip/libxslt-ruby/
packages-wip/libxslt-ruby/tags/
packages-wip/libxslt-ruby/trunk/
packages-wip/libxslt-ruby/trunk/AUTHORS
packages-wip/libxslt-ruby/trunk/README
packages-wip/libxslt-ruby/trunk/changelog.gz
packages-wip/libxslt-ruby/trunk/debian/
packages-wip/libxslt-ruby/trunk/debian/README.Debian
packages-wip/libxslt-ruby/trunk/debian/changelog
packages-wip/libxslt-ruby/trunk/debian/compat
packages-wip/libxslt-ruby/trunk/debian/control
packages-wip/libxslt-ruby/trunk/debian/control.in
packages-wip/libxslt-ruby/trunk/debian/copyright
packages-wip/libxslt-ruby/trunk/debian/docs
packages-wip/libxslt-ruby/trunk/debian/patches/
packages-wip/libxslt-ruby/trunk/debian/patches/001-configure_extconf_rb.patch
packages-wip/libxslt-ruby/trunk/debian/patches/002-configure_init_function.patch
packages-wip/libxslt-ruby/trunk/debian/patches/003-fix_test.patch
packages-wip/libxslt-ruby/trunk/debian/patches/004-fix_examples.patch
packages-wip/libxslt-ruby/trunk/debian/rules
packages-wip/libxslt-ruby/trunk/debug/
packages-wip/libxslt-ruby/trunk/debug/memwatch.c
packages-wip/libxslt-ruby/trunk/debug/memwatch.h
packages-wip/libxslt-ruby/trunk/examples/
packages-wip/libxslt-ruby/trunk/examples/commentary.dtd
packages-wip/libxslt-ruby/trunk/examples/functions.xsl
packages-wip/libxslt-ruby/trunk/examples/fuzface.rb
packages-wip/libxslt-ruby/trunk/examples/fuzface.xml
packages-wip/libxslt-ruby/trunk/examples/fuzface.xsl
packages-wip/libxslt-ruby/trunk/examples/fuzface_REXML.rb
packages-wip/libxslt-ruby/trunk/examples/fuzface_XML-Simple.rb
packages-wip/libxslt-ruby/trunk/examples/fuzface_data.rb
packages-wip/libxslt-ruby/trunk/examples/fuzface_error.rb
packages-wip/libxslt-ruby/trunk/examples/fuzface_to_s.rb
packages-wip/libxslt-ruby/trunk/examples/info.rb
packages-wip/libxslt-ruby/trunk/examples/ramblings.xsl
packages-wip/libxslt-ruby/trunk/examples/test.xml
packages-wip/libxslt-ruby/trunk/examples/test.xsl
packages-wip/libxslt-ruby/trunk/examples/test_functions.rb
packages-wip/libxslt-ruby/trunk/examples/test_parameters.rb
packages-wip/libxslt-ruby/trunk/extconf.rb
packages-wip/libxslt-ruby/trunk/extfunc.c
packages-wip/libxslt-ruby/trunk/extfunc.h
packages-wip/libxslt-ruby/trunk/parameters.c
packages-wip/libxslt-ruby/trunk/parameters.h
packages-wip/libxslt-ruby/trunk/parser.c
packages-wip/libxslt-ruby/trunk/parser.h
packages-wip/libxslt-ruby/trunk/rb_utils.c
packages-wip/libxslt-ruby/trunk/rb_utils.h
packages-wip/libxslt-ruby/trunk/tests/
packages-wip/libxslt-ruby/trunk/tests/imports/
packages-wip/libxslt-ruby/trunk/tests/imports/pass/
packages-wip/libxslt-ruby/trunk/tests/subdir/
packages-wip/libxslt-ruby/trunk/tests/subdir/result.xsl
packages-wip/libxslt-ruby/trunk/tests/subdir/test.xsl
packages-wip/libxslt-ruby/trunk/tests/t.xml
packages-wip/libxslt-ruby/trunk/tests/t.xsl
packages-wip/libxslt-ruby/trunk/tests/test.rb
packages-wip/libxslt-ruby/trunk/xslt.c
packages-wip/libxslt-ruby/trunk/xslt.h
Log:
[svn-inject] Installing original source of libxslt-ruby
Added: packages-wip/libxslt-ruby/trunk/AUTHORS
===================================================================
--- packages-wip/libxslt-ruby/trunk/AUTHORS 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/AUTHORS 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,23 @@
+= Authors
+
+Gregoire Lejeune <gregoire dot lejeune at free dot fr>
+* Maintener
+
+Eustáquio "TaQ" Rangel <eustaquiorangel at yahoo dot com>
+* Add parameters support
+
+Brendan Taylor <whateley at gmail dot com>
+* Add external function support
+* Add media_type function
+* Changes to the way XSLT files are loaded, so that we can keep their base URI straight
+
+<kiyoya at gmail dot com>
+* Add definitions for some error classes and sets libxml error function
+
+== Thanks to :
+
+knu <knu at freebsd dot org> for FreeBSD port (see http://www.freshports.org/textproc/ruby-xslt/)
+
+Robert Shaw <rshaw at opendarwin dot org> for opendarwin port (see http://rb-xslt.darwinports.com/)
+
+Alexis Bernard aka alex__ for testing
Added: packages-wip/libxslt-ruby/trunk/README
===================================================================
--- packages-wip/libxslt-ruby/trunk/README 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/README 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,137 @@
+= Ruby/XSLT
+
+== About
+
+Ruby/XSLT is a simple XSLT class based on libxml <http://xmlsoft.org/> and libxslt <http://xmlsoft.org/XSLT/>
+
+== Licence
+
+Copyright (C) 2003, 2004, 2005 Gregoire Lejeune <gregoire dot lejeune at free dot fr>
+
+Ruby/XSLT is freely distributable according to the terms of the
+GNU General Public License (see the file 'COPYING').
+
+This program is distributed without any warranty. See the file
+'COPYING' for details.
+
+== DOWNLOAD
+
+=== Last version
+* version 0.9.2[http://gregoire.lejeune.free.fr/ruby-xslt_0.9.2.tar.gz]
+
+=== Old versions
+* version 0.9.1[http://gregoire.lejeune.free.fr/ruby-xslt_0.9.1.tar.gz]
+* version 0.8.2[http://gregoire.lejeune.free.fr/ruby-xslt_0.8.2.tar.gz]
+* version 0.8.1[http://gregoire.lejeune.free.fr/ruby-xslt_0.8.1.tar.gz]
+* version 0.8.0[http://gregoire.lejeune.free.fr/ruby-xslt_0.8.0.tar.gz]
+* version 0.7.0[http://gregoire.lejeune.free.fr/ruby-xslt_0.7.0.tar.gz]
+* version 0.6.0[http://gregoire.lejeune.free.fr/ruby-xslt_0.6.0.tar.gz]
+* version 0.5.0[http://gregoire.lejeune.free.fr/ruby-xslt_0.5.0.tar.gz]
+* version 0.4.0[http://gregoire.lejeune.free.fr/ruby-xslt_0.4.0.tar.gz]
+* version 0.3.0[http://gregoire.lejeune.free.fr/ruby-xslt_0.3.0.tar.gz]
+* version 0.2.0[http://gregoire.lejeune.free.fr/ruby-xslt_0.2.0.tar.gz]
+* version 0.1.0[http://gregoire.lejeune.free.fr/ruby-xslt_0.1.0.tar.gz]
+
+=== CVS access
+The CVS repository is available at rubyforge.org[http://rubyforge.org/projects/ruby-asp]. You can browse[http://rubyforge.org/cgi-bin/viewcvs.cgi/ruby-xslt/?cvsroot=ruby-asp] it or access it via anonymous access :
+
+ cvs -d :pserver:anonymous at rubyforge.org:/var/cvs/ruby-asp login
+ cvs -d :pserver:anonymous at rubyforge.org:/var/cvs/ruby-asp checkout ruby-xslt
+
+See this page[http://rubyforge.org/scm/?group_id=423] for more informations
+
+== INSTALLATION
+
+ ruby extconf.rb # see CONFIGURATION for more options
+ make
+ make test
+ make doc
+ sudo make install
+
+=== CONFIGURATION
+
+ --help display this help and exit
+
+ --with-xslt-lib=PATH
+ --with-xslt-include=PATH
+ --with-xslt-dir=PATH specify the directory name for the libxslt include
+ files and/or library
+
+ --enable-error-handler enables a VERY crude error handler. Error messages
+ are appended to the class variable XML::XSLT and can
+ be accessed with the class method XML::XSLT.errors
+ (will change in a future version)
+ --disable-exslt disables libexslt support <http://exslt.org/>
+
+ --enable-debug compile with memwatch
+ <http://www.linkdata.se/sourcecode.html>
+
+== EXAMPLES
+
+=== Simple example
+ require 'xml/xslt'
+
+ xslt = XML::XSLT.new()
+ xslt.xml = "text.xml"
+ xslt.xsl = "test.xsl"
+
+ out = xslt.serve()
+ print out;
+
+=== REXML support
+ require 'rexml/document'
+ require 'xml/xslt'
+
+ xslt = XML::XSLT.new()
+
+ xslt.xml = REXML::Document.new File.open( "test.xml" )
+ xslt.xsl = REXML::Document.new File.open( "test.xsl" )
+
+ out = xslt.serve()
+ print out;
+
+=== XML::Smart support
+ require 'xml/smart'
+ require 'xml/xslt'
+
+ xslt = XML::XSLT.new()
+
+ xslt.xml = XML::Smart.open( "test.xml" )
+ xslt.xsl = XML::Smart.open( "test.xsl" )
+
+ out = xslt.serve()
+ print out;
+
+=== Parameters support
+ require "xml/xslt"
+
+ xslt = XML::XSLT.new()
+ xslt.xsl = "parameter.xsl"
+ xslt.xml = "test.xml"
+ xslt.parameters = { "p1" => "the first parameter ...",
+ "p2" => "'and the second one!'" }
+ xslt.save("test1.html")
+
+ xslt.parameters = { "p1" => "Ruby...",
+ "p2" => "'...is cool !'" }
+ xslt.save("test2.html")
+
+=== External functions support
+ require "xml/xslt"
+
+ class XML::XSLT
+ def round_trip( arg )
+ arg
+ end
+ def type( arg )
+ arg.class.to_s
+ end
+ end
+
+ xslt = XML::XSLT.new()
+ xslt.xsl = "functions.xsl"
+ xslt.xml = "test.xml"
+ XML::XSLT.extFunction("round-trip", "http://test.none", xslt)
+ XML::XSLT.extFunction("type", "http://test.none", xslt)
+
+ print xslt.serve
Added: packages-wip/libxslt-ruby/trunk/changelog.gz
===================================================================
(Binary files differ)
Property changes on: packages-wip/libxslt-ruby/trunk/changelog.gz
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages-wip/libxslt-ruby/trunk/debian/README.Debian
===================================================================
--- packages-wip/libxslt-ruby/trunk/debian/README.Debian 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debian/README.Debian 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,10 @@
+The same - but check /usr/share/doc/libxslt-ruby1.8/examples too.
+
+ -- Filipe Lautert <filipe at icewall.org> Thu, 31 Oct 2006 23:58:12 -0300
+
+Better docs will be included soon, in the form of manpages and.. stuff.
+In the meantime, check /usr/share/doc/libxslt-ruby1.8/tests/ for examples
+showing proper use of this module.
+
+ -- Andres Salomon <dilinger at voxel.net> Mon, 19 Jul 2004 20:02:54 -0400
+
Added: packages-wip/libxslt-ruby/trunk/debian/changelog
===================================================================
--- packages-wip/libxslt-ruby/trunk/debian/changelog 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debian/changelog 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,33 @@
+libxslt-ruby (0.9.2-1) unstable; urgency=low
+
+ * Package adopted. Closes: #335699.
+ * Version upgrade after a long time with no upgrade. Now using
+ Gregoire Lejeune version.
+
+ -- Filipe Lautert <filipelautert at celepar.pr.gov.br> Wed, 1 Nov 2006 01:15:23 -0300
+
+libxslt-ruby (0.3.4-3) unstable; urgency=low
+
+ * Orphan package, set maintainer to QA group.
+ * Add 006-wall_fix.patch to fix a build error involving gcc args; thanks
+ to Andreas Jochens (closes: #297722).
+
+ -- Andres Salomon <dilinger at voxel.net> Tue, 25 Oct 2005 01:47:19 -0400
+
+libxslt-ruby (0.3.4-2) unstable; urgency=low
+
+ * Add 005-no_math_check.patch to not check for -lm or atan during
+ build; thanks to Andreas Jochens (closes: #265476).
+
+ -- Andres Salomon <dilinger at voxel.net> Wed, 29 Dec 2004 08:00:15 -0500
+
+libxslt-ruby (0.3.4-1) unstable; urgency=low
+
+ * Initial release (closes: #258771).
+ * Add 001-libxmldir_override.patch to clean up some hardcoded ugliness.
+ * Add 002-ruby18_fixes.patch to make libxslt-ruby work correctly w/
+ ruby1.8.
+ * Add 003-no_usr_local.patch to replace all /usr/local's w/ /usr.
+ * Add 004-fix_fuzface.patch to make fuzface.rb find libxslt.
+
+ -- Andres Salomon <dilinger at voxel.net> Tue, 20 Jul 2004 23:35:11 -0400
Added: packages-wip/libxslt-ruby/trunk/debian/compat
===================================================================
--- packages-wip/libxslt-ruby/trunk/debian/compat 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debian/compat 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1 @@
+4
Added: packages-wip/libxslt-ruby/trunk/debian/control
===================================================================
--- packages-wip/libxslt-ruby/trunk/debian/control 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debian/control 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,14 @@
+Source: libxslt-ruby
+Section: admin
+Priority: optional
+Maintainer: Filipe Lautert <filipelautert at celepar.pr.gov.br>
+Uploaders: Debian Ruby Extras Maintainers <pkg-ruby-extras-maintainers at lists.alioth.debian.org>, Antonio S. de A. Terceiro <asaterceiro at inf.ufrgs.br>, David Moreno Garza <damog at debian.org>, David Nusinow <dnusinow at debian.org>, Paul van Tilburg <paulvt at debian.org>, Esteban Manchado Velázquez <zoso at debian.org>, Arnaud Cornet <arnaud.cornet at gmail.com>, Lucas Nussbaum <lucas at lucas-nussbaum.net>, Thierry Reding <thierry at doppeltgemoppelt.de>, Marc Dequènes (Duck) <Duck at DuckCorp.org>, Ari Pollak <ari at debian.org>, Daigo Moriwaki <daigo at debian.org>, Vincent Fourmond <vincent.fourmond at 9online.fr>, Rudi Cilibrasi <cilibrar at cilibrar.com>, Patrick Ringl <patrick_ at freenet.de>
+Build-Depends: debhelper (>> 4.1.0), cdbs, ruby-pkg-tools (>= 0.8), ruby, ruby1.8-dev, libxml2-dev, libxslt1-dev, zlib1g-dev
+Standards-Version: 3.6.2
+
+Package: libxslt-ruby1.8
+Architecture: any
+Depends: ${shlibs:Depends}, libxml-ruby1.8
+Description: Ruby interface to libxslt
+ libxslt-ruby is a Ruby interface for processing XSLT. Its usage is
+ very simple. It's based on libxslt and libxml.
Added: packages-wip/libxslt-ruby/trunk/debian/control.in
===================================================================
--- packages-wip/libxslt-ruby/trunk/debian/control.in 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debian/control.in 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,14 @@
+Source: libxslt-ruby
+Section: admin
+Priority: optional
+Maintainer: Filipe Lautert <filipelautert at celepar.pr.gov.br>
+Uploaders: @RUBY_EXTRAS_TEAM@
+Build-Depends: debhelper (>> 4.1.0), cdbs, ruby-pkg-tools (>= 0.8), ruby, ruby1.8-dev, libxml2-dev, libxslt1-dev, zlib1g-dev
+Standards-Version: 3.6.2
+
+Package: libxslt-ruby1.8
+Architecture: any
+Depends: ${shlibs:Depends}, libxml-ruby1.8
+Description: Ruby interface to libxslt
+ libxslt-ruby is a Ruby interface for processing XSLT. Its usage is
+ very simple. It's based on libxslt and libxml.
Added: packages-wip/libxslt-ruby/trunk/debian/copyright
===================================================================
--- packages-wip/libxslt-ruby/trunk/debian/copyright 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debian/copyright 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,8 @@
+Copyright:
+
+ xslt-ruby is copyrighted free software of Gregoire Lejeune and distributed
+ under the GPL.
+
+On Debian systems, the full text of the GNU General Public License can be
+found at /usr/share/common-licenses/GPL.
+
Added: packages-wip/libxslt-ruby/trunk/debian/docs
===================================================================
--- packages-wip/libxslt-ruby/trunk/debian/docs 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debian/docs 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,5 @@
+README
+tests
+AUTHORS
+changelog.gz
+examples
Added: packages-wip/libxslt-ruby/trunk/debian/patches/001-configure_extconf_rb.patch
===================================================================
--- packages-wip/libxslt-ruby/trunk/debian/patches/001-configure_extconf_rb.patch 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debian/patches/001-configure_extconf_rb.patch 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,20 @@
+--- extconf.rb 2006-11-01 00:57:08.613064254 -0300
++++ /home/lautert/tmp/ruby-xslt/extconf.rb 2006-11-01 00:56:42.022663140 -0300
+@@ -88,7 +88,7 @@
+ puts
+
+ create_header()
+-create_makefile("xml/xslt")
++create_makefile("xml/libxslt")
+
+ ###### Modify Makefile: #######
+ File.rename( "Makefile", "Makefile.orig" )
+@@ -102,7 +102,7 @@
+ newmkfl.puts("test: all") # insert the "test" target
+ newmkfl.puts("\t\t at cd tests && ruby test.rb && cd ..")
+ newmkfl.puts("doc: all") # insert the "doc" target
+- newmkfl.puts("\t\t at rdoc -S -t \"Ruby/XSLT Documentation\" README AUTHORS ChangeLog xslt.c")
++ newmkfl.puts("\t\t at rdoc -S -t \"Ruby/XSLT Documentation\" README AUTHORS ChangeLog libxslt.c")
+ when /^distclean:/
+ newmkfl.puts(line)
+ newmkfl.puts("\t\t at -$(RM) memwatch.h memwatch.c Makefile.orig")
Added: packages-wip/libxslt-ruby/trunk/debian/patches/002-configure_init_function.patch
===================================================================
--- packages-wip/libxslt-ruby/trunk/debian/patches/002-configure_init_function.patch 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debian/patches/002-configure_init_function.patch 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,11 @@
+--- xslt.c 2005-11-16 23:21:43.000000000 -0200
++++ /home/lautert/tmp/ruby-xslt/xslt.c 2006-11-01 00:59:12.904939168 -0300
+@@ -555,7 +555,7 @@
+ * ----------------------------------------------------------------------------
+ */
+
+-void Init_xslt( void ) {
++void Init_libxslt( void ) {
+ mXML = rb_define_module( "XML" );
+ cXSLT = rb_define_class_under( mXML, "XSLT", rb_cObject );
+
Added: packages-wip/libxslt-ruby/trunk/debian/patches/003-fix_test.patch
===================================================================
--- packages-wip/libxslt-ruby/trunk/debian/patches/003-fix_test.patch 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debian/patches/003-fix_test.patch 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,15 @@
+--- tests/test.rb 2005-11-13 22:22:27.000000000 -0200
++++ /home/lautert/tmp/ruby-xslt/tests/test.rb 2006-11-01 01:06:38.891666770 -0300
+@@ -1,7 +1,11 @@
+ #!ruby
+
+ require "test/unit"
+-require "../xslt"
++begin
++ require "../libxslt"
++rescue LoadError
++ require "xml/libxslt"
++end
+
+ # Test::Unit suite for flattenx extension
+ #
Added: packages-wip/libxslt-ruby/trunk/debian/patches/004-fix_examples.patch
===================================================================
--- packages-wip/libxslt-ruby/trunk/debian/patches/004-fix_examples.patch 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debian/patches/004-fix_examples.patch 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,102 @@
+diff -urN examples/fuzface_data.rb /home/lautert/tmp/ruby-xslt/examples/fuzface_data.rb
+--- examples/fuzface_data.rb 2005-11-07 05:42:28.000000000 -0200
++++ /home/lautert/tmp/ruby-xslt/examples/fuzface_data.rb 2006-11-01 01:16:33.420635109 -0300
+@@ -1,6 +1,6 @@
+ #!/usr/bin/ruby -w
+
+-require '../xslt'
++require 'xml/libxslt'
+
+ xslt = XML::XSLT.new()
+ xslt.xml = IO::readlines( "fuzface.xml" ).join
+diff -urN examples/fuzface_error.rb /home/lautert/tmp/ruby-xslt/examples/fuzface_error.rb
+--- examples/fuzface_error.rb 2005-11-07 10:05:39.000000000 -0200
++++ /home/lautert/tmp/ruby-xslt/examples/fuzface_error.rb 2006-11-01 01:16:53.560938919 -0300
+@@ -1,6 +1,6 @@
+ #!/usr/bin/ruby -w
+
+-require '../xslt'
++require 'xml/libxslt'
+
+ xslt = XML::XSLT.new()
+
+diff -urN examples/fuzface.rb /home/lautert/tmp/ruby-xslt/examples/fuzface.rb
+--- examples/fuzface.rb 2005-11-07 05:42:28.000000000 -0200
++++ /home/lautert/tmp/ruby-xslt/examples/fuzface.rb 2006-11-01 01:16:19.050418338 -0300
+@@ -1,6 +1,6 @@
+ #!/usr/bin/ruby -w
+
+-require '../xslt'
++require 'xml/libxslt'
+
+ xslt = XML::XSLT.new()
+ xslt.xmlfile = "fuzface.xml"
+diff -urN examples/fuzface_REXML.rb /home/lautert/tmp/ruby-xslt/examples/fuzface_REXML.rb
+--- examples/fuzface_REXML.rb 2005-11-07 10:06:11.000000000 -0200
++++ /home/lautert/tmp/ruby-xslt/examples/fuzface_REXML.rb 2006-11-01 01:17:01.981065945 -0300
+@@ -1,6 +1,6 @@
+ #!/usr/bin/ruby -w
+ require 'rexml/document'
+-require '../xslt'
++require 'xml/libxslt'
+
+ xslt = XML::XSLT.new()
+
+@@ -8,4 +8,4 @@
+ xslt.xsl = REXML::Document.new File.open( "fuzface.xsl" )
+
+ out = xslt.serve()
+-puts out
+\ No newline at end of file
++puts out
+diff -urN examples/fuzface_to_s.rb /home/lautert/tmp/ruby-xslt/examples/fuzface_to_s.rb
+--- examples/fuzface_to_s.rb 2005-11-07 05:42:28.000000000 -0200
++++ /home/lautert/tmp/ruby-xslt/examples/fuzface_to_s.rb 2006-11-01 01:17:17.601301563 -0300
+@@ -1,6 +1,6 @@
+ #!/usr/bin/ruby -w
+
+-require '../xslt'
++require 'xml/libxslt'
+
+ xslt = XML::XSLT.new()
+ xslt.xsl = "fuzface.xsl"
+diff -urN examples/fuzface_XML-Simple.rb /home/lautert/tmp/ruby-xslt/examples/fuzface_XML-Simple.rb
+--- examples/fuzface_XML-Simple.rb 2005-11-07 05:42:28.000000000 -0200
++++ /home/lautert/tmp/ruby-xslt/examples/fuzface_XML-Simple.rb 2006-11-01 01:17:25.121415004 -0300
+@@ -1,7 +1,7 @@
+ #!/usr/bin/ruby -w
+
+ require 'xml/smart'
+-require '../xslt'
++require 'xml/libxslt'
+
+ xslt = XML::XSLT.new()
+
+diff -urN examples/info.rb /home/lautert/tmp/ruby-xslt/examples/info.rb
+--- examples/info.rb 2005-11-07 05:42:28.000000000 -0200
++++ /home/lautert/tmp/ruby-xslt/examples/info.rb 2006-11-01 01:17:47.311749738 -0300
+@@ -1,5 +1,5 @@
+ #!/usr/bin/ruby
+-require "../xslt"
++require 'xml/libxslt'
+
+ print "MAX_DEPTH = ", XML::XSLT::MAX_DEPTH, "\n"
+ print "MAX_SORT = ", XML::XSLT::MAX_SORT, "\n"
+diff -urN examples/test_functions.rb /home/lautert/tmp/ruby-xslt/examples/test_functions.rb
+--- examples/test_functions.rb 2005-11-07 05:42:28.000000000 -0200
++++ /home/lautert/tmp/ruby-xslt/examples/test_functions.rb 2006-11-01 01:18:16.822194899 -0300
+@@ -1,4 +1,4 @@
+-require "../xslt"
++require 'xml/libxslt'
+
+ class XML::XSLT
+ def round_trip( arg )
+diff -urN examples/test_parameters.rb /home/lautert/tmp/ruby-xslt/examples/test_parameters.rb
+--- examples/test_parameters.rb 2005-11-07 05:42:28.000000000 -0200
++++ /home/lautert/tmp/ruby-xslt/examples/test_parameters.rb 2006-11-01 01:18:29.742389797 -0300
+@@ -1,4 +1,4 @@
+-require "../xslt"
++require 'xml/libxslt'
+
+ xslt = XML::XSLT.new()
+ xslt.xsl = "test.xsl"
Added: packages-wip/libxslt-ruby/trunk/debian/rules
===================================================================
--- packages-wip/libxslt-ruby/trunk/debian/rules 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debian/rules 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,10 @@
+#!/usr/bin/make -f
+#
+# CDBS file to build the Foo Ruby package.
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/rules/simple-patchsys.mk
+include /usr/share/ruby-pkg-tools/1/class/ruby-extconf-rb.mk
+include /usr/share/ruby-pkg-tools/1/rules/uploaders.mk
+
+DEB_COMPRESS_EXCLUDE := .xml
Property changes on: packages-wip/libxslt-ruby/trunk/debian/rules
___________________________________________________________________
Name: svn:executable
+
Added: packages-wip/libxslt-ruby/trunk/debug/memwatch.c
===================================================================
--- packages-wip/libxslt-ruby/trunk/debug/memwatch.c 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debug/memwatch.c 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,2664 @@
+/*
+** MEMWATCH.C
+** Nonintrusive ANSI C memory leak / overwrite detection
+** Copyright (C) 1992-2003 Johan Lindh
+** All rights reserved.
+** Version 2.71
+
+ This file is part of MEMWATCH.
+
+ MEMWATCH is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ MEMWATCH 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 MEMWATCH; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+**
+** 920810 JLI [1.00]
+** 920830 JLI [1.10 double-free detection]
+** 920912 JLI [1.15 mwPuts, mwGrab/Drop, mwLimit]
+** 921022 JLI [1.20 ASSERT and VERIFY]
+** 921105 JLI [1.30 C++ support and TRACE]
+** 921116 JLI [1.40 mwSetOutFunc]
+** 930215 JLI [1.50 modified ASSERT/VERIFY]
+** 930327 JLI [1.51 better auto-init & PC-lint support]
+** 930506 JLI [1.55 MemWatch class, improved C++ support]
+** 930507 JLI [1.60 mwTest & CHECK()]
+** 930809 JLI [1.65 Abort/Retry/Ignore]
+** 930820 JLI [1.70 data dump when unfreed]
+** 931016 JLI [1.72 modified C++ new/delete handling]
+** 931108 JLI [1.77 mwSetAssertAction() & some small changes]
+** 940110 JLI [1.80 no-mans-land alloc/checking]
+** 940328 JLI [2.00 version 2.0 rewrite]
+** Improved NML (no-mans-land) support.
+** Improved performance (especially for free()ing!).
+** Support for 'read-only' buffers (checksums)
+** ^^ NOTE: I never did this... maybe I should?
+** FBI (free'd block info) tagged before freed blocks
+** Exporting of the mwCounter variable
+** mwBreakOut() localizes debugger support
+** Allocation statistics (global, per-module, per-line)
+** Self-repair ability with relinking
+** 950913 JLI [2.10 improved garbage handling]
+** 951201 JLI [2.11 improved auto-free in emergencies]
+** 960125 JLI [X.01 implemented auto-checking using mwAutoCheck()]
+** 960514 JLI [2.12 undefining of existing macros]
+** 960515 JLI [2.13 possibility to use default new() & delete()]
+** 960516 JLI [2.20 suppression of file flushing on unfreed msgs]
+** 960516 JLI [2.21 better support for using MEMWATCH with DLL's]
+** 960710 JLI [X.02 multiple logs and mwFlushNow()]
+** 960801 JLI [2.22 merged X.01 version with current]
+** 960805 JLI [2.30 mwIsXXXXAddr() to avoid unneeded GP's]
+** 960805 JLI [2.31 merged X.02 version with current]
+** 961002 JLI [2.32 support for realloc() + fixed STDERR bug]
+** 961222 JLI [2.40 added mwMark() & mwUnmark()]
+** 970101 JLI [2.41 added over/underflow checking after failed ASSERT/VERIFY]
+** 970113 JLI [2.42 added support for PC-Lint 7.00g]
+** 970207 JLI [2.43 added support for strdup()]
+** 970209 JLI [2.44 changed default filename to lowercase]
+** 970405 JLI [2.45 fixed bug related with atexit() and some C++ compilers]
+** 970723 JLI [2.46 added MW_ARI_NULLREAD flag]
+** 970813 JLI [2.47 stabilized marker handling]
+** 980317 JLI [2.48 ripped out C++ support; wasn't working good anyway]
+** 980318 JLI [2.50 improved self-repair facilities & SIGSEGV support]
+** 980417 JLI [2.51 more checks for invalid addresses]
+** 980512 JLI [2.52 moved MW_ARI_NULLREAD to occur before aborting]
+** 990112 JLI [2.53 added check for empty heap to mwIsOwned]
+** 990217 JLI [2.55 improved the emergency repairs diagnostics and NML]
+** 990224 JLI [2.56 changed ordering of members in structures]
+** 990303 JLI [2.57 first maybe-fixit-for-hpux test]
+** 990516 JLI [2.58 added 'static' to the definition of mwAutoInit]
+** 990517 JLI [2.59 fixed some high-sensitivity warnings]
+** 990610 JLI [2.60 fixed some more high-sensitivity warnings]
+** 990715 JLI [2.61 changed TRACE/ASSERT/VERIFY macro names]
+** 991001 JLI [2.62 added CHECK_BUFFER() and mwTestBuffer()]
+** 991007 JLI [2.63 first shot at a 64-bit compatible version]
+** 991009 JLI [2.64 undef's strdup() if defined, mwStrdup made const]
+** 000704 JLI [2.65 added some more detection for 64-bits]
+** 010502 JLI [2.66 incorporated some user fixes]
+** [mwRelink() could print out garbage pointer (thanks mac at phobos.ca)]
+** [added array destructor for C++ (thanks rdasilva at connecttel.com)]
+** [added mutex support (thanks rdasilva at connecttel.com)]
+** 010531 JLI [2.67 fix: mwMutexXXX() was declared even if MW_HAVE_MUTEX was not defined]
+** 010619 JLI [2.68 fix: mwRealloc() could leave the mutex locked]
+** 020918 JLI [2.69 changed to GPL, added C++ array allocation by Howard Cohen]
+** 030212 JLI [2.70 mwMalloc() bug for very large allocations (4GB on 32bits)]
+** 030520 JLI [2.71 added ULONG_LONG_MAX as a 64-bit detector (thanks Sami Salonen)]
+*/
+
+#define __MEMWATCH_C 1
+
+#ifdef MW_NOCPP
+#define MEMWATCH_NOCPP
+#endif
+#ifdef MW_STDIO
+#define MEMWATCH_STDIO
+#endif
+
+/***********************************************************************
+** Include files
+***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <time.h>
+#include <limits.h>
+#include "memwatch.h"
+
+#ifndef toupper
+#include <ctype.h>
+#endif
+
+#if defined(WIN32) || defined(__WIN32__)
+#define MW_HAVE_MUTEX 1
+#include <windows.h>
+#endif
+
+#if defined(MW_PTHREADS) || defined(HAVE_PTHREAD_H)
+#define MW_HAVE_MUTEX 1
+#include <pthread.h>
+#endif
+
+/***********************************************************************
+** Defines & other weird stuff
+***********************************************************************/
+
+/*lint -save -e767 */
+#define VERSION "2.71" /* the current version number */
+#define CHKVAL(mw) (0xFE0180L^(long)mw->count^(long)mw->size^(long)mw->line)
+#define FLUSH() mwFlush()
+#define TESTS(f,l) if(mwTestAlways) (void)mwTestNow(f,l,1)
+#define PRECHK 0x01234567L
+#define POSTCHK 0x76543210L
+#define mwBUFFER_TO_MW(p) ( (mwData*) (void*) ( ((char*)p)-mwDataSize-mwOverflowZoneSize ) )
+/*lint -restore */
+
+#define MW_NML 0x0001
+
+#ifdef _MSC_VER
+#define COMMIT "c" /* Microsoft C requires the 'c' to perform as desired */
+#else
+#define COMMIT "" /* Normal ANSI */
+#endif /* _MSC_VER */
+
+#ifdef __cplusplus
+#define CPPTEXT "++"
+#else
+#define CPPTEXT ""
+#endif /* __cplusplus */
+
+#ifdef MEMWATCH_STDIO
+#define mwSTDERR stderr
+#else
+#define mwSTDERR mwLog
+#endif
+
+#ifdef MW_HAVE_MUTEX
+#define MW_MUTEX_INIT() mwMutexInit()
+#define MW_MUTEX_TERM() mwMutexTerm()
+#define MW_MUTEX_LOCK() mwMutexLock()
+#define MW_MUTEX_UNLOCK() mwMutexUnlock()
+#else
+#define MW_MUTEX_INIT()
+#define MW_MUTEX_TERM()
+#define MW_MUTEX_LOCK()
+#define MW_MUTEX_UNLOCK()
+#endif
+
+/***********************************************************************
+** If you really, really know what you're doing,
+** you can predefine these things yourself.
+***********************************************************************/
+
+#ifndef mwBYTE_DEFINED
+# if CHAR_BIT != 8
+# error need CHAR_BIT to be 8!
+# else
+typedef unsigned char mwBYTE;
+# define mwBYTE_DEFINED 1
+# endif
+#endif
+
+#if defined(ULONGLONG_MAX) || defined(ULLONG_MAX) || defined(_UI64_MAX) || defined(ULONG_LONG_MAX)
+# define mw64BIT 1
+# define mwROUNDALLOC_DEFAULT 8
+#else
+# if UINT_MAX <= 0xFFFFUL
+# define mw16BIT 1
+# define mwROUNDALLOC_DEFAULT 2
+# else
+# if ULONG_MAX > 0xFFFFFFFFUL
+# define mw64BIT 1
+# define mwROUNDALLOC_DEFAULT 8
+# else
+# define mw32BIT 1
+# define mwROUNDALLOC_DEFAULT 4
+# endif
+# endif
+#endif
+
+/* mwROUNDALLOC is the number of bytes to */
+/* round up to, to ensure that the end of */
+/* the buffer is suitable for storage of */
+/* any kind of object */
+#ifndef mwROUNDALLOC
+# define mwROUNDALLOC mwROUNDALLOC_DEFAULT
+#endif
+
+#ifndef mwDWORD_DEFINED
+#if ULONG_MAX == 0xFFFFFFFFUL
+typedef unsigned long mwDWORD;
+#define mwDWORD_DEFINED "unsigned long"
+#endif
+#endif
+
+#ifndef mwDWORD_DEFINED
+#if UINT_MAX == 0xFFFFFFFFUL
+typedef unsigned int mwDWORD;
+#define mwDWORD_DEFINED "unsigned int"
+#endif
+#endif
+
+#ifndef mwDWORD_DEFINED
+#if USHRT_MAX == 0xFFFFFFFFUL
+typedef unsigned short mwDWORD;
+#define mwDWORD_DEFINED "unsigned short"
+#endif
+#endif
+
+#ifndef mwBYTE_DEFINED
+#error "can't find out the correct type for a 8 bit scalar"
+#endif
+
+#ifndef mwDWORD_DEFINED
+#error "can't find out the correct type for a 32 bit scalar"
+#endif
+
+/***********************************************************************
+** Typedefs & structures
+***********************************************************************/
+
+/* main data holding area, precedes actual allocation */
+typedef struct mwData_ mwData;
+struct mwData_ {
+ mwData* prev; /* previous allocation in chain */
+ mwData* next; /* next allocation in chain */
+ const char* file; /* file name where allocated */
+ long count; /* action count */
+ long check; /* integrity check value */
+#if 0
+ long crc; /* data crc value */
+#endif
+ size_t size; /* size of allocation */
+ int line; /* line number where allocated */
+ unsigned flag; /* flag word */
+ };
+
+/* statistics structure */
+typedef struct mwStat_ mwStat;
+struct mwStat_ {
+ mwStat* next; /* next statistic buffer */
+ const char* file;
+ long total; /* total bytes allocated */
+ long num; /* total number of allocations */
+ long max; /* max allocated at one time */
+ long curr; /* current allocations */
+ int line;
+ };
+
+/* grabbing structure, 1K in size */
+typedef struct mwGrabData_ mwGrabData;
+struct mwGrabData_ {
+ mwGrabData* next;
+ int type;
+ char blob[ 1024 - sizeof(mwGrabData*) - sizeof(int) ];
+ };
+
+typedef struct mwMarker_ mwMarker;
+struct mwMarker_ {
+ void *host;
+ char *text;
+ mwMarker *next;
+ int level;
+ };
+
+#if defined(WIN32) || defined(__WIN32__)
+typedef HANDLE mwMutex;
+#endif
+
+#if defined(MW_PTHREADS) || defined(HAVE_PTHREAD_H)
+typedef pthread_mutex_t mwMutex;
+#endif
+
+/***********************************************************************
+** Static variables
+***********************************************************************/
+
+static int mwInited = 0;
+static int mwInfoWritten = 0;
+static int mwUseAtexit = 0;
+static FILE* mwLog = NULL;
+static int mwFlushing = 0;
+static int mwStatLevel = MW_STAT_DEFAULT;
+static int mwNML = MW_NML_DEFAULT;
+static int mwFBI = 0;
+static long mwAllocLimit = 0L;
+static int mwUseLimit = 0;
+
+static long mwNumCurAlloc = 0L;
+static mwData* mwHead = NULL;
+static mwData* mwTail = NULL;
+static int mwDataSize = 0;
+static unsigned char mwOverflowZoneTemplate[] = "mEmwAtch";
+static int mwOverflowZoneSize = mwROUNDALLOC;
+
+static void (*mwOutFunction)(int) = NULL;
+static int (*mwAriFunction)(const char*) = NULL;
+static int mwAriAction = MW_ARI_ABORT;
+
+static char mwPrintBuf[MW_TRACE_BUFFER+8];
+
+static unsigned long mwCounter = 0L;
+static long mwErrors = 0L;
+
+static int mwTestFlags = 0;
+static int mwTestAlways = 0;
+
+static FILE* mwLogB1 = NULL;
+static int mwFlushingB1 = 0;
+
+static mwStat* mwStatList = NULL;
+static long mwStatTotAlloc = 0L;
+static long mwStatMaxAlloc = 0L;
+static long mwStatNumAlloc = 0L;
+static long mwStatCurAlloc = 0L;
+static long mwNmlNumAlloc = 0L;
+static long mwNmlCurAlloc = 0L;
+
+static mwGrabData* mwGrabList = NULL;
+static long mwGrabSize = 0L;
+
+static void * mwLastFree[MW_FREE_LIST];
+static const char *mwLFfile[MW_FREE_LIST];
+static int mwLFline[MW_FREE_LIST];
+static int mwLFcur = 0;
+
+static mwMarker* mwFirstMark = NULL;
+
+static FILE* mwLogB2 = NULL;
+static int mwFlushingB2 = 0;
+
+#ifdef MW_HAVE_MUTEX
+static mwMutex mwGlobalMutex;
+#endif
+
+/***********************************************************************
+** Static function declarations
+***********************************************************************/
+
+static void mwAutoInit( void );
+static FILE* mwLogR( void );
+static void mwLogW( FILE* );
+static int mwFlushR( void );
+static void mwFlushW( int );
+static void mwFlush( void );
+static void mwIncErr( void );
+static void mwUnlink( mwData*, const char* file, int line );
+static int mwRelink( mwData*, const char* file, int line );
+static int mwIsHeapOK( mwData *mw );
+static int mwIsOwned( mwData* mw, const char* file, int line );
+static int mwTestBuf( mwData* mw, const char* file, int line );
+static void mwDefaultOutFunc( int );
+static void mwWrite( const char* format, ... );
+static void mwLogFile( const char* name );
+static size_t mwFreeUp( size_t, int );
+static const void *mwTestMem( const void *, unsigned, int );
+static int mwStrCmpI( const char *s1, const char *s2 );
+static int mwTestNow( const char *file, int line, int always_invoked );
+static void mwDropAll( void );
+static const char *mwGrabType( int type );
+static unsigned mwGrab_( unsigned kb, int type, int silent );
+static unsigned mwDrop_( unsigned kb, int type, int silent );
+static int mwARI( const char* text );
+static void mwStatReport( void );
+static mwStat* mwStatGet( const char*, int, int );
+static void mwStatAlloc( size_t, const char*, int );
+static void mwStatFree( size_t, const char*, int );
+static int mwCheckOF( const void * p );
+static void mwWriteOF( void * p );
+static char mwDummy( char c );
+#ifdef MW_HAVE_MUTEX
+static void mwMutexInit( void );
+static void mwMutexTerm( void );
+static void mwMutexLock( void );
+static void mwMutexUnlock( void );
+#endif
+
+/***********************************************************************
+** System functions
+***********************************************************************/
+
+void mwInit( void ) {
+ time_t tid;
+
+ if( mwInited++ > 0 ) return;
+
+ MW_MUTEX_INIT();
+
+ /* start a log if none is running */
+ if( mwLogR() == NULL ) mwLogFile( "memwatch.log" );
+ if( mwLogR() == NULL ) {
+ int i;
+ char buf[32];
+ /* oops, could not open it! */
+ /* probably because it's already open */
+ /* so we try some other names */
+ for( i=1; i<100; i++ ) {
+ sprintf( buf, "memwat%02d.log", i );
+ mwLogFile( buf );
+ if( mwLogR() != NULL ) break;
+ }
+ }
+
+ /* initialize the statistics */
+ mwStatList = NULL;
+ mwStatTotAlloc = 0L;
+ mwStatCurAlloc = 0L;
+ mwStatMaxAlloc = 0L;
+ mwStatNumAlloc = 0L;
+ mwNmlCurAlloc = 0L;
+ mwNmlNumAlloc = 0L;
+
+ /* calculate the buffer size to use for a mwData */
+ mwDataSize = sizeof(mwData);
+ while( mwDataSize % mwROUNDALLOC ) mwDataSize ++;
+
+ /* write informational header if needed */
+ if( !mwInfoWritten ) {
+ mwInfoWritten = 1;
+ (void) time( &tid );
+ mwWrite(
+ "\n============="
+ " MEMWATCH " VERSION " Copyright (C) 1992-1999 Johan Lindh "
+ "=============\n");
+ mwWrite( "\nStarted at %s\n", ctime( &tid ) );
+
+/**************************************************************** Generic */
+ mwWrite( "Modes: " );
+#ifdef mwNew
+ mwWrite( "C++ " );
+#endif /* mwNew */
+#ifdef __STDC__
+ mwWrite( "__STDC__ " );
+#endif /* __STDC__ */
+#ifdef mw16BIT
+ mwWrite( "16-bit " );
+#endif
+#ifdef mw32BIT
+ mwWrite( "32-bit " );
+#endif
+#ifdef mw64BIT
+ mwWrite( "64-bit " );
+#endif
+ mwWrite( "mwDWORD==(" mwDWORD_DEFINED ")\n" );
+ mwWrite( "mwROUNDALLOC==%d sizeof(mwData)==%d mwDataSize==%d\n",
+ mwROUNDALLOC, sizeof(mwData), mwDataSize );
+/**************************************************************** Generic */
+
+/************************************************************ Microsoft C */
+#ifdef _MSC_VER
+ mwWrite( "Compiled using Microsoft C" CPPTEXT
+ " %d.%02d\n", _MSC_VER / 100, _MSC_VER % 100 );
+#endif /* _MSC_VER */
+/************************************************************ Microsoft C */
+
+/************************************************************** Borland C */
+#ifdef __BORLANDC__
+ mwWrite( "Compiled using Borland C"
+#ifdef __cplusplus
+ "++ %d.%01d\n", __BCPLUSPLUS__/0x100, (__BCPLUSPLUS__%0x100)/0x10 );
+#else
+ " %d.%01d\n", __BORLANDC__/0x100, (__BORLANDC__%0x100)/0x10 );
+#endif /* __cplusplus */
+#endif /* __BORLANDC__ */
+/************************************************************** Borland C */
+
+/************************************************************** Watcom C */
+#ifdef __WATCOMC__
+ mwWrite( "Compiled using Watcom C %d.%02d ",
+ __WATCOMC__/100, __WATCOMC__%100 );
+#ifdef __FLAT__
+ mwWrite( "(32-bit flat model)" );
+#endif /* __FLAT__ */
+ mwWrite( "\n" );
+#endif /* __WATCOMC__ */
+/************************************************************** Watcom C */
+
+ mwWrite( "\n" );
+ FLUSH();
+ }
+
+ if( mwUseAtexit ) (void) atexit( mwAbort );
+ return;
+ }
+
+void mwAbort( void ) {
+ mwData *mw;
+ mwMarker *mrk;
+ char *data;
+ time_t tid;
+ int c, i, j;
+ int errors;
+
+ tid = time( NULL );
+ mwWrite( "\nStopped at %s\n", ctime( &tid) );
+
+ if( !mwInited )
+ mwWrite( "internal: mwAbort(): MEMWATCH not initialized!\n" );
+
+ /* release the grab list */
+ mwDropAll();
+
+ /* report mwMarked items */
+ while( mwFirstMark ) {
+ mrk = mwFirstMark->next;
+ mwWrite( "mark: %p: %s\n", mwFirstMark->host, mwFirstMark->text );
+ free( mwFirstMark->text );
+ free( mwFirstMark );
+ mwFirstMark = mrk;
+ mwErrors ++;
+ }
+
+ /* release all still allocated memory */
+ errors = 0;
+ while( mwHead != NULL && errors < 3 ) {
+ if( !mwIsOwned(mwHead, __FILE__, __LINE__ ) ) {
+ if( errors < 3 )
+ {
+ errors ++;
+ mwWrite( "internal: NML/unfreed scan restarting\n" );
+ FLUSH();
+ mwHead = mwHead;
+ continue;
+ }
+ mwWrite( "internal: NML/unfreed scan aborted, heap too damaged\n" );
+ FLUSH();
+ break;
+ }
+ mwFlushW(0);
+ if( !(mwHead->flag & MW_NML) ) {
+ mwErrors++;
+ data = ((char*)mwHead)+mwDataSize;
+ mwWrite( "unfreed: <%ld> %s(%d), %ld bytes at %p ",
+ mwHead->count, mwHead->file, mwHead->line, (long)mwHead->size, data+mwOverflowZoneSize );
+ if( mwCheckOF( data ) ) {
+ mwWrite( "[underflowed] ");
+ FLUSH();
+ }
+ if( mwCheckOF( (data+mwOverflowZoneSize+mwHead->size) ) ) {
+ mwWrite( "[overflowed] ");
+ FLUSH();
+ }
+ mwWrite( " \t{" );
+ j = 16; if( mwHead->size < 16 ) j = (int) mwHead->size;
+ for( i=0;i<16;i++ ) {
+ if( i<j ) mwWrite( "%02X ",
+ (unsigned char) *(data+mwOverflowZoneSize+i) );
+ else mwWrite( ".. " );
+ }
+ for( i=0;i<j;i++ ) {
+ c = *(data+mwOverflowZoneSize+i);
+ if( c < 32 || c > 126 ) c = '.';
+ mwWrite( "%c", c );
+ }
+ mwWrite( "}\n" );
+ mw = mwHead;
+ mwUnlink( mw, __FILE__, __LINE__ );
+ free( mw );
+ }
+ else {
+ data = ((char*)mwHead) + mwDataSize + mwOverflowZoneSize;
+ if( mwTestMem( data, mwHead->size, MW_VAL_NML ) ) {
+ mwErrors++;
+ mwWrite( "wild pointer: <%ld> NoMansLand %p alloc'd at %s(%d)\n",
+ mwHead->count, data + mwOverflowZoneSize, mwHead->file, mwHead->line );
+ FLUSH();
+ }
+ mwNmlNumAlloc --;
+ mwNmlCurAlloc -= mwHead->size;
+ mw = mwHead;
+ mwUnlink( mw, __FILE__, __LINE__ );
+ free( mw );
+ }
+ }
+
+ if( mwNmlNumAlloc ) mwWrite("internal: NoMansLand block counter %ld, not zero\n", mwNmlNumAlloc );
+ if( mwNmlCurAlloc ) mwWrite("internal: NoMansLand byte counter %ld, not zero\n", mwNmlCurAlloc );
+
+ /* report statistics */
+ mwStatReport();
+ FLUSH();
+
+ mwInited = 0;
+ mwHead = mwTail = NULL;
+ if( mwErrors )
+ fprintf(mwSTDERR,"MEMWATCH detected %ld anomalies\n",mwErrors);
+ mwLogFile( NULL );
+ mwErrors = 0;
+
+ MW_MUTEX_TERM();
+
+ }
+
+void mwTerm( void ) {
+ if( mwInited == 1 )
+ {
+ mwAbort();
+ return;
+ }
+ if( !mwInited )
+ mwWrite("internal: mwTerm(): MEMWATCH has not been started!\n");
+ else
+ mwInited --;
+ }
+
+void mwStatistics( int level )
+{
+ mwAutoInit();
+ if( level<0 ) level=0;
+ if( mwStatLevel != level )
+ {
+ mwWrite( "statistics: now collecting on a %s basis\n",
+ level<1?"global":(level<2?"module":"line") );
+ mwStatLevel = level;
+ }
+}
+
+void mwAutoCheck( int onoff ) {
+ mwAutoInit();
+ mwTestAlways = onoff;
+ if( onoff ) mwTestFlags = MW_TEST_ALL;
+ }
+
+void mwSetOutFunc( void (*func)(int) ) {
+ mwAutoInit();
+ mwOutFunction = func;
+ }
+
+static void mwWriteOF( void *p )
+{
+ int i;
+ unsigned char *ptr;
+ ptr = (unsigned char*) p;
+ for( i=0; i<mwOverflowZoneSize; i++ )
+ {
+ *(ptr+i) = mwOverflowZoneTemplate[i%8];
+ }
+ return;
+}
+
+static int mwCheckOF( const void *p )
+{
+ int i;
+ const unsigned char *ptr;
+ ptr = (const unsigned char *) p;
+ for( i=0; i<mwOverflowZoneSize; i++ )
+ {
+ if( *(ptr+i) != mwOverflowZoneTemplate[i%8] )
+ return 1; /* errors found */
+ }
+ return 0; /* no errors */
+}
+
+int mwTest( const char *file, int line, int items ) {
+ mwAutoInit();
+ mwTestFlags = items;
+ return mwTestNow( file, line, 0 );
+ }
+
+/*
+** Returns zero if there are no errors.
+** Returns nonzero if there are errors.
+*/
+int mwTestBuffer( const char *file, int line, void *p ) {
+ mwData* mw;
+
+ mwAutoInit();
+
+ /* do the quick ownership test */
+ mw = (mwData*) mwBUFFER_TO_MW( p );
+
+ if( mwIsOwned( mw, file, line ) ) {
+ return mwTestBuf( mw, file, line );
+ }
+ return 1;
+ }
+
+void mwBreakOut( const char* cause ) {
+ fprintf(mwSTDERR, "breakout: %s\n", cause);
+ mwWrite("breakout: %s\n", cause );
+ return;
+ }
+
+/*
+** 981217 JLI: is it possible that ->next is not always set?
+*/
+void * mwMark( void *p, const char *desc, const char *file, unsigned line ) {
+ mwMarker *mrk;
+ unsigned n, isnew;
+ char *buf;
+ int tot, oflow = 0;
+ char wherebuf[128];
+
+ mwAutoInit();
+ TESTS(NULL,0);
+
+ if( desc == NULL ) desc = "unknown";
+ if( file == NULL ) file = "unknown";
+
+ tot = sprintf( wherebuf, "%.48s called from %s(%d)", desc, file, line );
+ if( tot >= (int)sizeof(wherebuf) ) { wherebuf[sizeof(wherebuf)-1] = 0; oflow = 1; }
+
+ if( p == NULL ) {
+ mwWrite("mark: %s(%d), no mark for NULL:'%s' may be set\n", file, line, desc );
+ return p;
+ }
+
+ if( mwFirstMark != NULL && !mwIsReadAddr( mwFirstMark, sizeof( mwMarker ) ) )
+ {
+ mwWrite("mark: %s(%d), mwFirstMark (%p) is trashed, can't mark for %s\n",
+ file, line, mwFirstMark, desc );
+ return p;
+ }
+
+ for( mrk=mwFirstMark; mrk; mrk=mrk->next )
+ {
+ if( mrk->next != NULL && !mwIsReadAddr( mrk->next, sizeof( mwMarker ) ) )
+ {
+ mwWrite("mark: %s(%d), mark(%p)->next(%p) is trashed, can't mark for %s\n",
+ file, line, mrk, mrk->next, desc );
+ return p;
+ }
+ if( mrk->host == p ) break;
+ }
+
+ if( mrk == NULL ) {
+ isnew = 1;
+ mrk = (mwMarker*) malloc( sizeof( mwMarker ) );
+ if( mrk == NULL ) {
+ mwWrite("mark: %s(%d), no mark for %p:'%s', out of memory\n", file, line, p, desc );
+ return p;
+ }
+ mrk->next = NULL;
+ n = 0;
+ }
+ else {
+ isnew = 0;
+ n = strlen( mrk->text );
+ }
+
+ n += strlen( wherebuf );
+ buf = (char*) malloc( n+3 );
+ if( buf == NULL ) {
+ if( isnew ) free( mrk );
+ mwWrite("mark: %s(%d), no mark for %p:'%s', out of memory\n", file, line, p, desc );
+ return p;
+ }
+
+ if( isnew ) {
+ memcpy( buf, wherebuf, n+1 );
+ mrk->next = mwFirstMark;
+ mrk->host = p;
+ mrk->text = buf;
+ mrk->level = 1;
+ mwFirstMark = mrk;
+ }
+ else {
+ strcpy( buf, mrk->text );
+ strcat( buf, ", " );
+ strcat( buf, wherebuf );
+ free( mrk->text );
+ mrk->text = buf;
+ mrk->level ++;
+ }
+
+ if( oflow ) {
+ mwIncErr();
+ mwTrace( " [WARNING: OUTPUT BUFFER OVERFLOW - SYSTEM UNSTABLE]\n" );
+ }
+ return p;
+ }
+
+void* mwUnmark( void *p, const char *file, unsigned line ) {
+ mwMarker *mrk, *prv;
+ mrk = mwFirstMark;
+ prv = NULL;
+ while( mrk ) {
+ if( mrk->host == p ) {
+ if( mrk->level < 2 ) {
+ if( prv ) prv->next = mrk->next;
+ else mwFirstMark = mrk->next;
+ free( mrk->text );
+ free( mrk );
+ return p;
+ }
+ mrk->level --;
+ return p;
+ }
+ prv = mrk;
+ mrk = mrk->next;
+ }
+ mwWrite("mark: %s(%d), no mark found for %p\n", file, line, p );
+ return p;
+ }
+
+
+/***********************************************************************
+** Abort/Retry/Ignore handlers
+***********************************************************************/
+
+static int mwARI( const char *estr ) {
+ char inbuf[81];
+ int c;
+ fprintf(mwSTDERR, "\n%s\nMEMWATCH: Abort, Retry or Ignore? ", estr);
+ (void) fgets(inbuf,sizeof(inbuf),stdin);
+ for( c=0; inbuf[c] && inbuf[c] <= ' '; c++ ) ;
+ c = inbuf[c];
+ if( c == 'R' || c == 'r' ) {
+ mwBreakOut( estr );
+ return MW_ARI_RETRY;
+ }
+ if( c == 'I' || c == 'i' ) return MW_ARI_IGNORE;
+ return MW_ARI_ABORT;
+ }
+
+/* standard ARI handler (exported) */
+int mwAriHandler( const char *estr ) {
+ mwAutoInit();
+ return mwARI( estr );
+ }
+
+/* used to set the ARI function */
+void mwSetAriFunc( int (*func)(const char *) ) {
+ mwAutoInit();
+ mwAriFunction = func;
+ }
+
+/***********************************************************************
+** Allocation handlers
+***********************************************************************/
+
+void* mwMalloc( size_t size, const char* file, int line) {
+ size_t needed;
+ mwData *mw;
+ char *ptr;
+ void *p;
+
+ mwAutoInit();
+
+ MW_MUTEX_LOCK();
+
+ TESTS(file,line);
+
+ mwCounter ++;
+ needed = mwDataSize + mwOverflowZoneSize*2 + size;
+ if( needed < size )
+ {
+ /* theoretical case: req size + mw overhead exceeded size_t limits */
+ return NULL;
+ }
+
+ /* if this allocation would violate the limit, fail it */
+ if( mwUseLimit && ((long)size + mwStatCurAlloc > mwAllocLimit) ) {
+ mwWrite( "limit fail: <%ld> %s(%d), %ld wanted %ld available\n",
+ mwCounter, file, line, (long)size, mwAllocLimit - mwStatCurAlloc );
+ mwIncErr();
+ FLUSH();
+ MW_MUTEX_UNLOCK();
+ return NULL;
+ }
+
+ mw = (mwData*) malloc( needed );
+ if( mw == NULL ) {
+ if( mwFreeUp(needed,0) >= needed ) {
+ mw = (mwData*) malloc(needed);
+ if( mw == NULL ) {
+ mwWrite( "internal: mwFreeUp(%u) reported success, but malloc() fails\n", needed );
+ mwIncErr();
+ FLUSH();
+ }
+ }
+ if( mw == NULL ) {
+ mwWrite( "fail: <%ld> %s(%d), %ld wanted %ld allocated\n",
+ mwCounter, file, line, (long)size, mwStatCurAlloc );
+ mwIncErr();
+ FLUSH();
+ MW_MUTEX_UNLOCK();
+ return NULL;
+ }
+ }
+
+ mw->count = mwCounter;
+ mw->prev = NULL;
+ mw->next = mwHead;
+ mw->file = file;
+ mw->size = size;
+ mw->line = line;
+ mw->flag = 0;
+ mw->check = CHKVAL(mw);
+
+ if( mwHead ) mwHead->prev = mw;
+ mwHead = mw;
+ if( mwTail == NULL ) mwTail = mw;
+
+ ptr = ((char*)mw) + mwDataSize;
+ mwWriteOF( ptr ); /* '*(long*)ptr = PRECHK;' */
+ ptr += mwOverflowZoneSize;
+ p = ptr;
+ memset( ptr, MW_VAL_NEW, size );
+ ptr += size;
+ mwWriteOF( ptr ); /* '*(long*)ptr = POSTCHK;' */
+
+ mwNumCurAlloc ++;
+ mwStatCurAlloc += (long) size;
+ mwStatTotAlloc += (long) size;
+ if( mwStatCurAlloc > mwStatMaxAlloc )
+ mwStatMaxAlloc = mwStatCurAlloc;
+ mwStatNumAlloc ++;
+
+ if( mwStatLevel ) mwStatAlloc( size, file, line );
+
+ MW_MUTEX_UNLOCK();
+ return p;
+ }
+
+void* mwRealloc( void *p, size_t size, const char* file, int line) {
+ int oldUseLimit, i;
+ mwData *mw;
+ char *ptr;
+
+ mwAutoInit();
+
+ if( p == NULL ) return mwMalloc( size, file, line );
+ if( size == 0 ) { mwFree( p, file, line ); return NULL; }
+
+ MW_MUTEX_LOCK();
+
+ /* do the quick ownership test */
+ mw = (mwData*) mwBUFFER_TO_MW( p );
+ if( mwIsOwned( mw, file, line ) ) {
+
+ /* if the buffer is an NML, treat this as a double-free */
+ if( mw->flag & MW_NML )
+ {
+ mwIncErr();
+ if( *((unsigned char*)(mw)+mwDataSize+mwOverflowZoneSize) != MW_VAL_NML )
+ {
+ mwWrite( "internal: <%ld> %s(%d), no-mans-land MW-%p is corrupted\n",
+ mwCounter, file, line, mw );
+ }
+ goto check_dbl_free;
+ }
+
+ /* if this allocation would violate the limit, fail it */
+ if( mwUseLimit && ((long)size + mwStatCurAlloc - (long)mw->size > mwAllocLimit) ) {
+ TESTS(file,line);
+ mwCounter ++;
+ mwWrite( "limit fail: <%ld> %s(%d), %ld wanted %ld available\n",
+ mwCounter, file, line, (unsigned long)size - mw->size, mwAllocLimit - mwStatCurAlloc );
+ mwIncErr();
+ FLUSH();
+ MW_MUTEX_UNLOCK();
+ return NULL;
+ }
+
+ /* fake realloc operation */
+ oldUseLimit = mwUseLimit;
+ mwUseLimit = 0;
+ ptr = (char*) mwMalloc( size, file, line );
+ if( ptr != NULL ) {
+ if( size < mw->size )
+ memcpy( ptr, p, size );
+ else
+ memcpy( ptr, p, mw->size );
+ mwFree( p, file, line );
+ }
+ mwUseLimit = oldUseLimit;
+ MW_MUTEX_UNLOCK();
+ return (void*) ptr;
+ }
+
+ /* Unknown pointer! */
+
+ /* using free'd pointer? */
+check_dbl_free:
+ for(i=0;i<MW_FREE_LIST;i++) {
+ if( mwLastFree[i] == p ) {
+ mwIncErr();
+ mwWrite( "realloc: <%ld> %s(%d), %p was"
+ " freed from %s(%d)\n",
+ mwCounter, file, line, p,
+ mwLFfile[i], mwLFline[i] );
+ FLUSH();
+ MW_MUTEX_UNLOCK();
+ return NULL;
+ }
+ }
+
+ /* some weird pointer */
+ mwIncErr();
+ mwWrite( "realloc: <%ld> %s(%d), unknown pointer %p\n",
+ mwCounter, file, line, p );
+ FLUSH();
+ MW_MUTEX_UNLOCK();
+ return NULL;
+ }
+
+char *mwStrdup( const char* str, const char* file, int line ) {
+ size_t len;
+ char *newstring;
+
+ MW_MUTEX_LOCK();
+
+ if( str == NULL ) {
+ mwIncErr();
+ mwWrite( "strdup: <%ld> %s(%d), strdup(NULL) called\n",
+ mwCounter, file, line );
+ FLUSH();
+ MW_MUTEX_UNLOCK();
+ return NULL;
+ }
+
+ len = strlen( str ) + 1;
+ newstring = (char*) mwMalloc( len, file, line );
+ if( newstring != NULL ) memcpy( newstring, str, len );
+ MW_MUTEX_UNLOCK();
+ return newstring;
+ }
+
+void mwFree( void* p, const char* file, int line ) {
+ int i;
+ mwData* mw;
+ char buffer[ sizeof(mwData) + (mwROUNDALLOC*3) + 64 ];
+
+ /* this code is in support of C++ delete */
+ if( file == NULL ) {
+ mwFree_( p );
+ MW_MUTEX_UNLOCK();
+ return;
+ }
+
+ mwAutoInit();
+
+ MW_MUTEX_LOCK();
+ TESTS(file,line);
+ mwCounter ++;
+
+ /* on NULL free, write a warning and return */
+ if( p == NULL ) {
+ mwWrite( "NULL free: <%ld> %s(%d), NULL pointer free'd\n",
+ mwCounter, file, line );
+ FLUSH();
+ MW_MUTEX_UNLOCK();
+ return;
+ }
+
+ /* do the quick ownership test */
+ mw = (mwData*) mwBUFFER_TO_MW( p );
+
+ if( mwIsOwned( mw, file, line ) ) {
+ (void) mwTestBuf( mw, file, line );
+
+ /* if the buffer is an NML, treat this as a double-free */
+ if( mw->flag & MW_NML )
+ {
+ if( *(((unsigned char*)mw)+mwDataSize+mwOverflowZoneSize) != MW_VAL_NML )
+ {
+ mwWrite( "internal: <%ld> %s(%d), no-mans-land MW-%p is corrupted\n",
+ mwCounter, file, line, mw );
+ }
+ goto check_dbl_free;
+ }
+
+ /* update the statistics */
+ mwNumCurAlloc --;
+ mwStatCurAlloc -= (long) mw->size;
+ if( mwStatLevel ) mwStatFree( mw->size, mw->file, mw->line );
+
+ /* we should either free the allocation or keep it as NML */
+ if( mwNML ) {
+ mw->flag |= MW_NML;
+ mwNmlNumAlloc ++;
+ mwNmlCurAlloc += (long) mw->size;
+ memset( ((char*)mw)+mwDataSize+mwOverflowZoneSize, MW_VAL_NML, mw->size );
+ }
+ else {
+ /* unlink the allocation, and enter the post-free data */
+ mwUnlink( mw, file, line );
+ memset( mw, MW_VAL_DEL,
+ mw->size + mwDataSize+mwOverflowZoneSize+mwOverflowZoneSize );
+ if( mwFBI ) {
+ memset( mw, '.', mwDataSize + mwOverflowZoneSize );
+ sprintf( buffer, "FBI<%ld>%s(%d)", mwCounter, file, line );
+ strncpy( (char*)(void*)mw, buffer, mwDataSize + mwOverflowZoneSize );
+ }
+ free( mw );
+ }
+
+ /* add the pointer to the last-free track */
+ mwLFfile[ mwLFcur ] = file;
+ mwLFline[ mwLFcur ] = line;
+ mwLastFree[ mwLFcur++ ] = p;
+ if( mwLFcur == MW_FREE_LIST ) mwLFcur = 0;
+
+ MW_MUTEX_UNLOCK();
+ return;
+ }
+
+ /* check for double-freeing */
+check_dbl_free:
+ for(i=0;i<MW_FREE_LIST;i++) {
+ if( mwLastFree[i] == p ) {
+ mwIncErr();
+ mwWrite( "double-free: <%ld> %s(%d), %p was"
+ " freed from %s(%d)\n",
+ mwCounter, file, line, p,
+ mwLFfile[i], mwLFline[i] );
+ FLUSH();
+ MW_MUTEX_UNLOCK();
+ return;
+ }
+ }
+
+ /* some weird pointer... block the free */
+ mwIncErr();
+ mwWrite( "WILD free: <%ld> %s(%d), unknown pointer %p\n",
+ mwCounter, file, line, p );
+ FLUSH();
+ MW_MUTEX_UNLOCK();
+ return;
+ }
+
+void* mwCalloc( size_t a, size_t b, const char *file, int line ) {
+ void *p;
+ size_t size = a * b;
+ p = mwMalloc( size, file, line );
+ if( p == NULL ) return NULL;
+ memset( p, 0, size );
+ return p;
+ }
+
+void mwFree_( void *p ) {
+ MW_MUTEX_LOCK();
+ TESTS(NULL,0);
+ MW_MUTEX_UNLOCK();
+ free(p);
+ }
+
+void* mwMalloc_( size_t size ) {
+ MW_MUTEX_LOCK();
+ TESTS(NULL,0);
+ MW_MUTEX_UNLOCK();
+ return malloc( size );
+ }
+
+void* mwRealloc_( void *p, size_t size ) {
+ MW_MUTEX_LOCK();
+ TESTS(NULL,0);
+ MW_MUTEX_UNLOCK();
+ return realloc( p, size );
+ }
+
+void* mwCalloc_( size_t a, size_t b ) {
+ MW_MUTEX_LOCK();
+ TESTS(NULL,0);
+ MW_MUTEX_UNLOCK();
+ return calloc( a, b );
+ }
+
+void mwFlushNow( void ) {
+ if( mwLogR() ) fflush( mwLogR() );
+ return;
+ }
+
+void mwDoFlush( int onoff ) {
+ mwFlushW( onoff<1?0:onoff );
+ if( onoff ) if( mwLogR() ) fflush( mwLogR() );
+ return;
+ }
+
+void mwLimit( long lim ) {
+ TESTS(NULL,0);
+ mwWrite("limit: old limit = ");
+ if( !mwAllocLimit ) mwWrite( "none" );
+ else mwWrite( "%ld bytes", mwAllocLimit );
+ mwWrite( ", new limit = ");
+ if( !lim ) {
+ mwWrite( "none\n" );
+ mwUseLimit = 0;
+ }
+ else {
+ mwWrite( "%ld bytes\n", lim );
+ mwUseLimit = 1;
+ }
+ mwAllocLimit = lim;
+ FLUSH();
+ }
+
+void mwSetAriAction( int action ) {
+ MW_MUTEX_LOCK();
+ TESTS(NULL,0);
+ mwAriAction = action;
+ MW_MUTEX_UNLOCK();
+ return;
+ }
+
+int mwAssert( int exp, const char *exps, const char *fn, int ln ) {
+ int i;
+ char buffer[MW_TRACE_BUFFER+8];
+ if( exp ) {
+ return 0;
+ }
+ mwAutoInit();
+ MW_MUTEX_LOCK();
+ TESTS(fn,ln);
+ mwIncErr();
+ mwCounter++;
+ mwWrite( "assert trap: <%ld> %s(%d), %s\n", mwCounter, fn, ln, exps );
+ if( mwAriFunction != NULL ) {
+ sprintf( buffer, "MEMWATCH: assert trap: %s(%d), %s", fn, ln, exps );
+ i = (*mwAriFunction)(buffer);
+ switch( i ) {
+ case MW_ARI_IGNORE:
+ mwWrite( "assert trap: <%ld> IGNORED - execution continues\n", mwCounter );
+ MW_MUTEX_UNLOCK();
+ return 0;
+ case MW_ARI_RETRY:
+ mwWrite( "assert trap: <%ld> RETRY - executing again\n", mwCounter );
+ MW_MUTEX_UNLOCK();
+ return 1;
+ }
+ }
+ else {
+ if( mwAriAction & MW_ARI_IGNORE ) {
+ mwWrite( "assert trap: <%ld> AUTO IGNORED - execution continues\n", mwCounter );
+ MW_MUTEX_UNLOCK();
+ return 0;
+ }
+ fprintf(mwSTDERR,"\nMEMWATCH: assert trap: %s(%d), %s\n", fn, ln, exps );
+ }
+
+ FLUSH();
+ (void) mwTestNow( fn, ln, 1 );
+ FLUSH();
+
+ if( mwAriAction & MW_ARI_NULLREAD ) {
+ /* This is made in an attempt to kick in */
+ /* any debuggers or OS stack traces */
+ FLUSH();
+ /*lint -save -e413 */
+ i = *((int*)NULL);
+ mwDummy( (char)i );
+ /*lint -restore */
+ }
+
+ MW_MUTEX_UNLOCK();
+ exit(255);
+ /* NOT REACHED - the return statement is in to keep */
+ /* stupid compilers from squeaking about differing return modes. */
+ /* Smart compilers instead say 'code unreachable...' */
+ /*lint -save -e527 */
+ return 0;
+ /*lint -restore */
+ }
+
+int mwVerify( int exp, const char *exps, const char *fn, int ln ) {
+ int i;
+ char buffer[MW_TRACE_BUFFER+8];
+ if( exp ) {
+ return 0;
+ }
+ mwAutoInit();
+ MW_MUTEX_LOCK();
+ TESTS(fn,ln);
+ mwIncErr();
+ mwCounter++;
+ mwWrite( "verify trap: <%ld> %s(%d), %s\n", mwCounter, fn, ln, exps );
+ if( mwAriFunction != NULL ) {
+ sprintf( buffer, "MEMWATCH: verify trap: %s(%d), %s", fn, ln, exps );
+ i = (*mwAriFunction)(buffer);
+ if( i == 0 ) {
+ mwWrite( "verify trap: <%ld> IGNORED - execution continues\n", mwCounter );
+ MW_MUTEX_UNLOCK();
+ return 0;
+ }
+ if( i == 1 ) {
+ mwWrite( "verify trap: <%ld> RETRY - executing again\n", mwCounter );
+ MW_MUTEX_UNLOCK();
+ return 1;
+ }
+ }
+ else {
+ if( mwAriAction & MW_ARI_NULLREAD ) {
+ /* This is made in an attempt to kick in */
+ /* any debuggers or OS stack traces */
+ FLUSH();
+ /*lint -save -e413 */
+ i = *((int*)NULL);
+ mwDummy( (char)i );
+ /*lint -restore */
+ }
+ if( mwAriAction & MW_ARI_IGNORE ) {
+ mwWrite( "verify trap: <%ld> AUTO IGNORED - execution continues\n", mwCounter );
+ MW_MUTEX_UNLOCK();
+ return 0;
+ }
+ fprintf(mwSTDERR,"\nMEMWATCH: verify trap: %s(%d), %s\n", fn, ln, exps );
+ }
+ FLUSH();
+ (void) mwTestNow( fn, ln, 1 );
+ FLUSH();
+ MW_MUTEX_UNLOCK();
+ exit(255);
+ /* NOT REACHED - the return statement is in to keep */
+ /* stupid compilers from squeaking about differing return modes. */
+ /* Smart compilers instead say 'code unreachable...' */
+ /*lint -save -e527 */
+ return 0;
+ /*lint -restore */
+ }
+
+void mwTrace( const char *format, ... ) {
+ int tot, oflow = 0;
+ va_list mark;
+
+ mwAutoInit();
+ MW_MUTEX_LOCK();
+ TESTS(NULL,0);
+ if( mwOutFunction == NULL ) mwOutFunction = mwDefaultOutFunc;
+
+ va_start( mark, format );
+ tot = vsprintf( mwPrintBuf, format, mark );
+ va_end( mark );
+ if( tot >= MW_TRACE_BUFFER ) { mwPrintBuf[MW_TRACE_BUFFER] = 0; oflow = 1; }
+ for(tot=0;mwPrintBuf[tot];tot++)
+ (*mwOutFunction)( mwPrintBuf[tot] );
+ if( oflow ) {
+ mwIncErr();
+ mwTrace( " [WARNING: OUTPUT BUFFER OVERFLOW - SYSTEM UNSTABLE]\n" );
+ }
+
+ FLUSH();
+ MW_MUTEX_UNLOCK();
+ }
+
+
+/***********************************************************************
+** Grab & Drop
+***********************************************************************/
+
+unsigned mwGrab( unsigned kb ) {
+ TESTS(NULL,0);
+ return mwGrab_( kb, MW_VAL_GRB, 0 );
+ }
+
+unsigned mwDrop( unsigned kb ) {
+ TESTS(NULL,0);
+ return mwDrop_( kb, MW_VAL_GRB, 0 );
+ }
+
+static void mwDropAll() {
+ TESTS(NULL,0);
+ (void) mwDrop_( 0, MW_VAL_GRB, 0 );
+ (void) mwDrop_( 0, MW_VAL_NML, 0 );
+ if( mwGrabList != NULL )
+ mwWrite( "internal: the grab list is not empty after mwDropAll()\n");
+ }
+
+static const char *mwGrabType( int type ) {
+ switch( type ) {
+ case MW_VAL_GRB:
+ return "grabbed";
+ case MW_VAL_NML:
+ return "no-mans-land";
+ default:
+ /* do nothing */
+ ;
+ }
+ return "<unknown type>";
+ }
+
+static unsigned mwGrab_( unsigned kb, int type, int silent ) {
+ unsigned i = kb;
+ mwGrabData *gd;
+ if( !kb ) i = kb = 65000U;
+
+ for(;kb;kb--) {
+ if( mwUseLimit &&
+ (mwStatCurAlloc + mwGrabSize + (long)sizeof(mwGrabData) > mwAllocLimit) ) {
+ if( !silent ) {
+ mwWrite("grabbed: all allowed memory to %s (%u kb)\n",
+ mwGrabType(type), i-kb);
+ FLUSH();
+ }
+ return i-kb;
+ }
+ gd = (mwGrabData*) malloc( sizeof(mwGrabData) );
+ if( gd == NULL ) {
+ if( !silent ) {
+ mwWrite("grabbed: all available memory to %s (%u kb)\n",
+ mwGrabType(type), i-kb);
+ FLUSH();
+ }
+ return i-kb;
+ }
+ mwGrabSize += (long) sizeof(mwGrabData);
+ gd->next = mwGrabList;
+ memset( gd->blob, type, sizeof(gd->blob) );
+ gd->type = type;
+ mwGrabList = gd;
+ }
+ if( !silent ) {
+ mwWrite("grabbed: %u kilobytes of %s memory\n", i, mwGrabType(type) );
+ FLUSH();
+ }
+ return i;
+ }
+
+static unsigned mwDrop_( unsigned kb, int type, int silent ) {
+ unsigned i = kb;
+ mwGrabData *gd,*tmp,*pr;
+ const void *p;
+
+ if( mwGrabList == NULL && kb == 0 ) return 0;
+ if( !kb ) i = kb = 60000U;
+
+ pr = NULL;
+ gd = mwGrabList;
+ for(;kb;) {
+ if( gd == NULL ) {
+ if( i-kb > 0 && !silent ) {
+ mwWrite("dropped: all %s memory (%u kb)\n", mwGrabType(type), i-kb);
+ FLUSH();
+ }
+ return i-kb;
+ }
+ if( gd->type == type ) {
+ if( pr ) pr->next = gd->next;
+ kb --;
+ tmp = gd;
+ if( mwGrabList == gd ) mwGrabList = gd->next;
+ gd = gd->next;
+ p = mwTestMem( tmp->blob, sizeof( tmp->blob ), type );
+ if( p != NULL ) {
+ mwWrite( "wild pointer: <%ld> %s memory hit at %p\n",
+ mwCounter, mwGrabType(type), p );
+ FLUSH();
+ }
+ mwGrabSize -= (long) sizeof(mwGrabData);
+ free( tmp );
+ }
+ else {
+ pr = gd;
+ gd = gd->next;
+ }
+ }
+ if( !silent ) {
+ mwWrite("dropped: %u kilobytes of %s memory\n", i, mwGrabType(type) );
+ FLUSH();
+ }
+ return i;
+ }
+
+/***********************************************************************
+** No-Mans-Land
+***********************************************************************/
+
+void mwNoMansLand( int level ) {
+ mwAutoInit();
+ TESTS(NULL,0);
+ switch( level ) {
+ case MW_NML_NONE:
+ (void) mwDrop_( 0, MW_VAL_NML, 0 );
+ break;
+ case MW_NML_FREE:
+ break;
+ case MW_NML_ALL:
+ (void) mwGrab_( 0, MW_VAL_NML, 0 );
+ break;
+ default:
+ return;
+ }
+ mwNML = level;
+ }
+
+/***********************************************************************
+** Static functions
+***********************************************************************/
+
+static void mwAutoInit( void )
+{
+ if( mwInited ) return;
+ mwUseAtexit = 1;
+ mwInit();
+ return;
+}
+
+static FILE *mwLogR() {
+ if( (mwLog == mwLogB1) && (mwLog == mwLogB2) ) return mwLog;
+ if( mwLog == mwLogB1 ) mwLogB2 = mwLog;
+ if( mwLog == mwLogB2 ) mwLogB1 = mwLog;
+ if( mwLogB1 == mwLogB2 ) mwLog = mwLogB1;
+ if( (mwLog == mwLogB1) && (mwLog == mwLogB2) ) {
+ mwWrite("internal: log file handle damaged and recovered\n");
+ FLUSH();
+ return mwLog;
+ }
+ fprintf(mwSTDERR,"\nMEMWATCH: log file handle destroyed, using mwSTDERR\n" );
+ mwLog = mwLogB1 = mwLogB2 = mwSTDERR;
+ return mwSTDERR;
+ }
+
+static void mwLogW( FILE *p ) {
+ mwLog = mwLogB1 = mwLogB2 = p;
+ }
+
+static int mwFlushR() {
+ if( (mwFlushing == mwFlushingB1) && (mwFlushing == mwFlushingB2) ) return mwFlushing;
+ if( mwFlushing == mwFlushingB1 ) mwFlushingB2 = mwFlushing;
+ if( mwFlushing == mwFlushingB2 ) mwFlushingB1 = mwFlushing;
+ if( mwFlushingB1 == mwFlushingB2 ) mwFlushing = mwFlushingB1;
+ if( (mwFlushing == mwFlushingB1) && (mwFlushing == mwFlushingB2) ) {
+ mwWrite("internal: flushing flag damaged and recovered\n");
+ FLUSH();
+ return mwFlushing;
+ }
+ mwWrite("internal: flushing flag destroyed, so set to true\n");
+ mwFlushing = mwFlushingB1 = mwFlushingB2 = 1;
+ return 1;
+ }
+
+static void mwFlushW( int n ) {
+ mwFlushing = mwFlushingB1 = mwFlushingB2 = n;
+ }
+
+static void mwIncErr() {
+ mwErrors++;
+ mwFlushW( mwFlushR()+1 );
+ FLUSH();
+ }
+
+static void mwFlush() {
+ if( mwLogR() == NULL ) return;
+#ifdef MW_FLUSH
+ fflush( mwLogR() );
+#else
+ if( mwFlushR() ) fflush( mwLogR() );
+#endif
+ return;
+ }
+
+static void mwUnlink( mwData* mw, const char* file, int line ) {
+ if( mw->prev == NULL ) {
+ if( mwHead != mw )
+ mwWrite( "internal: <%ld> %s(%d), MW-%p: link1 NULL, but not head\n",
+ mwCounter, file, line, mw );
+ mwHead = mw->next;
+ }
+ else {
+ if( mw->prev->next != mw )
+ mwWrite( "internal: <%ld> %s(%d), MW-%p: link1 failure\n",
+ mwCounter, file, line, mw );
+ else mw->prev->next = mw->next;
+ }
+ if( mw->next == NULL ) {
+ if( mwTail != mw )
+ mwWrite( "internal: <%ld> %s(%d), MW-%p: link2 NULL, but not tail\n",
+ mwCounter, file, line, mw );
+ mwTail = mw->prev;
+ }
+ else {
+ if( mw->next->prev != mw )
+ mwWrite( "internal: <%ld> %s(%d), MW-%p: link2 failure\n",
+ mwCounter, file, line, mw );
+ else mw->next->prev = mw->prev;
+ }
+ }
+
+/*
+** Relinking tries to repair a damaged mw block.
+** Returns nonzero if it thinks it successfully
+** repaired the heap chain.
+*/
+static int mwRelink( mwData* mw, const char* file, int line ) {
+ int fails;
+ mwData *mw1, *mw2;
+ long count, size;
+ mwStat *ms;
+
+ if( file == NULL ) file = "unknown";
+
+ if( mw == NULL ) {
+ mwWrite("relink: cannot repair MW at NULL\n");
+ FLUSH();
+ goto emergency;
+ }
+
+ if( !mwIsSafeAddr(mw, mwDataSize) ) {
+ mwWrite("relink: MW-%p is a garbage pointer\n", mw);
+ FLUSH();
+ goto emergency;
+ }
+
+ mwWrite("relink: <%ld> %s(%d) attempting to repair MW-%p...\n", mwCounter, file, line, mw );
+ FLUSH();
+ fails = 0;
+
+ /* Repair from head */
+ if( mwHead != mw ) {
+ if( !mwIsSafeAddr( mwHead, mwDataSize ) ) {
+ mwWrite("relink: failed for MW-%p; head pointer destroyed\n", mw );
+ FLUSH();
+ goto emergency;
+ }
+ for( mw1=mwHead; mw1; mw1=mw1->next ) {
+ if( mw1->next == mw ) {
+ mw->prev = mw1;
+ break;
+ }
+ if( mw1->next &&
+ ( !mwIsSafeAddr(mw1->next, mwDataSize ) || mw1->next->prev != mw1) ) {
+ mwWrite("relink: failed for MW-%p; forward chain fragmented at MW-%p: 'next' is %p\n", mw, mw1, mw1->next );
+ FLUSH();
+ goto emergency;
+ }
+ }
+ if( mw1 == NULL ) {
+ mwWrite("relink: MW-%p not found in forward chain search\n", mw );
+ FLUSH();
+ fails ++;
+ }
+ }
+ else
+ {
+ mwWrite( "relink: MW-%p is the head (first) allocation\n", mw );
+ if( mw->prev != NULL )
+ {
+ mwWrite( "relink: MW-%p prev pointer is non-NULL, you have a wild pointer\n", mw );
+ mw->prev = NULL;
+ }
+ }
+
+ /* Repair from tail */
+ if( mwTail != mw ) {
+ if( !mwIsSafeAddr( mwTail, mwDataSize ) ) {
+ mwWrite("relink: failed for MW-%p; tail pointer destroyed\n", mw );
+ FLUSH();
+ goto emergency;
+ }
+ for( mw1=mwTail; mw1; mw1=mw1->prev ) {
+ if( mw1->prev == mw ) {
+ mw->next = mw1;
+ break;
+ }
+ if( mw1->prev && (!mwIsSafeAddr(mw1->prev, mwDataSize ) || mw1->prev->next != mw1) ) {
+ mwWrite("relink: failed for MW-%p; reverse chain fragmented at MW-%p, 'prev' is %p\n", mw, mw1, mw1->prev );
+ FLUSH();
+ goto emergency;
+ }
+ }
+ if( mw1 == NULL ) {
+ mwWrite("relink: MW-%p not found in reverse chain search\n", mw );
+ FLUSH();
+ fails ++;
+ }
+ }
+ else
+ {
+ mwWrite( "relink: MW-%p is the tail (last) allocation\n", mw );
+ if( mw->next != NULL )
+ {
+ mwWrite( "relink: MW-%p next pointer is non-NULL, you have a wild pointer\n", mw );
+ mw->next = NULL;
+ }
+ }
+
+ if( fails > 1 ) {
+ mwWrite("relink: heap appears intact, MW-%p probably garbage pointer\n", mw );
+ FLUSH();
+ goto verifyok;
+ }
+
+ /* restore MW info where possible */
+ if( mwIsReadAddr( mw->file, 1 ) ) {
+ ms = mwStatGet( mw->file, -1, 0 );
+ if( ms == NULL ) mw->file = "<relinked>";
+ }
+ mw->check = CHKVAL(mw);
+ goto verifyok;
+
+ /* Emergency repair */
+ emergency:
+
+ if( mwHead == NULL && mwTail == NULL )
+ {
+ if( mwStatCurAlloc == 0 )
+ mwWrite("relink: <%ld> %s(%d) heap is empty, nothing to repair\n", mwCounter, file, line );
+ else
+ mwWrite("relink: <%ld> %s(%d) heap damaged beyond repair\n", mwCounter, file, line );
+ FLUSH();
+ return 0;
+ }
+
+ mwWrite("relink: <%ld> %s(%d) attempting emergency repairs...\n", mwCounter, file, line );
+ FLUSH();
+
+ if( mwHead == NULL || mwTail == NULL )
+ {
+ if( mwHead == NULL ) mwWrite("relink: mwHead is NULL, but mwTail is %p\n", mwTail );
+ else mwWrite("relink: mwTail is NULL, but mwHead is %p\n", mwHead );
+ }
+
+ mw1=NULL;
+ if( mwHead != NULL )
+ {
+ if( !mwIsReadAddr( mwHead, mwDataSize ) || mwHead->check != CHKVAL(mwHead) )
+ {
+ mwWrite("relink: mwHead (MW-%p) is damaged, skipping forward scan\n", mwHead );
+ mwHead = NULL;
+ goto scan_reverse;
+ }
+ if( mwHead->prev != NULL )
+ {
+ mwWrite("relink: the mwHead pointer's 'prev' member is %p, not NULL\n", mwHead->prev );
+ }
+ for( mw1=mwHead; mw1; mw1=mw1->next )
+ {
+ if( mw1->next )
+ {
+ if( !mwIsReadAddr(mw1->next,mwDataSize) ||
+ !mw1->next->check != CHKVAL(mw1) ||
+ mw1->next->prev != mw1 )
+ {
+ mwWrite("relink: forward chain's last intact MW is MW-%p, %ld %sbytes at %s(%d)\n",
+ mw1, mw1->size, (mw->flag & MW_NML)?"NoMansLand ":"", mw1->file, mw1->line );
+ if( mwIsReadAddr(mw1->next,mwDataSize ) )
+ {
+ mwWrite("relink: forward chain's first damaged MW is MW-%p, %ld %sbytes at %s(%d)\n",
+ mw1->next, mw1->size, (mw->flag & MW_NML)?"NoMansLand ":"",
+ mwIsReadAddr(mw1->file,16)?mw1->file:"<garbage-pointer>", mw1->line );
+ }
+ else
+ {
+ mwWrite("relink: the 'next' pointer of this MW points to %p, which is out-of-legal-access\n",
+ mw1->next );
+ }
+ break;
+ }
+ }
+ }
+ }
+
+
+scan_reverse:
+ mw2=NULL;
+ if( mwTail != NULL )
+ {
+ if( !mwIsReadAddr(mwTail,mwDataSize) || mwTail->check != CHKVAL(mwTail) )
+ {
+ mwWrite("relink: mwTail (%p) is damaged, skipping reverse scan\n", mwTail );
+ mwTail = NULL;
+ goto analyze;
+ }
+ if( mwTail->next != NULL )
+ {
+ mwWrite("relink: the mwTail pointer's 'next' member is %p, not NULL\n", mwTail->next );
+ }
+ for( mw2=mwTail; mw2; mw2=mw2->prev )
+ {
+ if( mw2->prev )
+ {
+ if( !mwIsReadAddr(mw2->prev,mwDataSize) ||
+ !mw2->prev->check != CHKVAL(mw2) ||
+ mw2->prev->next != mw2 )
+ {
+ mwWrite("relink: reverse chain's last intact MW is MW-%p, %ld %sbytes at %s(%d)\n",
+ mw2, mw2->size, (mw->flag & MW_NML)?"NoMansLand ":"", mw2->file, mw2->line );
+ if( mwIsReadAddr(mw2->prev,mwDataSize ) )
+ {
+ mwWrite("relink: reverse chain's first damaged MW is MW-%p, %ld %sbytes at %s(%d)\n",
+ mw2->prev, mw2->size, (mw->flag & MW_NML)?"NoMansLand ":"",
+ mwIsReadAddr(mw2->file,16)?mw2->file:"<garbage-pointer>", mw2->line );
+ }
+ else
+ {
+ mwWrite("relink: the 'prev' pointer of this MW points to %p, which is out-of-legal-access\n",
+ mw2->prev );
+ }
+ break;
+ }
+ }
+ }
+ }
+
+analyze:
+ if( mwHead == NULL && mwTail == NULL )
+ {
+ mwWrite("relink: both head and tail pointers damaged, aborting program\n");
+ mwFlushW(1);
+ FLUSH();
+ abort();
+ }
+ if( mwHead == NULL )
+ {
+ mwHead = mw2;
+ mwWrite("relink: heap truncated, MW-%p designated as new mwHead\n", mw2 );
+ mw2->prev = NULL;
+ mw1 = mw2 = NULL;
+ }
+ if( mwTail == NULL )
+ {
+ mwTail = mw1;
+ mwWrite("relink: heap truncated, MW-%p designated as new mwTail\n", mw1 );
+ mw1->next = NULL;
+ mw1 = mw2 = NULL;
+ }
+ if( mw1 == NULL && mw2 == NULL &&
+ mwHead->prev == NULL && mwTail->next == NULL ) {
+ mwWrite("relink: verifying heap integrity...\n" );
+ FLUSH();
+ goto verifyok;
+ }
+ if( mw1 && mw2 && mw1 != mw2 ) {
+ mw1->next = mw2;
+ mw2->prev = mw1;
+ mwWrite("relink: emergency repairs successful, assessing damage...\n");
+ FLUSH();
+ }
+ else {
+ mwWrite("relink: heap totally destroyed, aborting program\n");
+ mwFlushW(1);
+ FLUSH();
+ abort();
+ }
+
+ /* Verify by checking that the number of active allocations */
+ /* match the number of entries in the chain */
+verifyok:
+ if( !mwIsHeapOK( NULL ) ) {
+ mwWrite("relink: heap verification FAILS - aborting program\n");
+ mwFlushW(1);
+ FLUSH();
+ abort();
+ }
+ for( size=count=0, mw1=mwHead; mw1; mw1=mw1->next ) {
+ count ++;
+ size += (long) mw1->size;
+ }
+ if( count == mwNumCurAlloc ) {
+ mwWrite("relink: successful, ");
+ if( size == mwStatCurAlloc ) {
+ mwWrite("no allocations lost\n");
+ }
+ else {
+ if( mw != NULL ) {
+ mwWrite("size information lost for MW-%p\n", mw);
+ mw->size = 0;
+ }
+ }
+ }
+ else {
+ mwWrite("relink: partial, %ld MW-blocks of %ld bytes lost\n",
+ mwNmlNumAlloc+mwNumCurAlloc-count, mwNmlCurAlloc+mwStatCurAlloc-size );
+ return 0;
+ }
+
+ return 1;
+ }
+
+/*
+** If mwData* is NULL:
+** Returns 0 if heap chain is broken.
+** Returns 1 if heap chain is intact.
+** If mwData* is not NULL:
+** Returns 0 if mwData* is missing or if chain is broken.
+** Returns 1 if chain is intact and mwData* is found.
+*/
+static int mwIsHeapOK( mwData *includes_mw ) {
+ int found = 0;
+ mwData *mw;
+
+ for( mw = mwHead; mw; mw=mw->next ) {
+ if( includes_mw == mw ) found++;
+ if( !mwIsSafeAddr( mw, mwDataSize ) ) return 0;
+ if( mw->prev ) {
+ if( !mwIsSafeAddr( mw->prev, mwDataSize ) ) return 0;
+ if( mw==mwHead || mw->prev->next != mw ) return 0;
+ }
+ if( mw->next ) {
+ if( !mwIsSafeAddr( mw->next, mwDataSize ) ) return 0;
+ if( mw==mwTail || mw->next->prev != mw ) return 0;
+ }
+ else if( mw!=mwTail ) return 0;
+ }
+
+ if( includes_mw != NULL && !found ) return 0;
+
+ return 1;
+ }
+
+static int mwIsOwned( mwData* mw, const char *file, int line ) {
+ int retv;
+ mwStat *ms;
+
+ /* see if the address is legal according to OS */
+ if( !mwIsSafeAddr( mw, mwDataSize ) ) return 0;
+
+ /* make sure we have _anything_ allocated */
+ if( mwHead == NULL && mwTail == NULL && mwStatCurAlloc == 0 )
+ return 0;
+
+ /* calculate checksum */
+ if( mw->check != CHKVAL(mw) ) {
+ /* may be damaged checksum, see if block is in heap */
+ if( mwIsHeapOK( mw ) ) {
+ /* damaged checksum, repair it */
+ mwWrite( "internal: <%ld> %s(%d), checksum for MW-%p is incorrect\n",
+ mwCounter, file, line, mw );
+ mwIncErr();
+ if( mwIsReadAddr( mw->file, 1 ) ) {
+ ms = mwStatGet( mw->file, -1, 0 );
+ if( ms == NULL ) mw->file = "<relinked>";
+ }
+ else mw->file = "<unknown>";
+ mw->size = 0;
+ mw->check = CHKVAL(mw);
+ return 1;
+ }
+ /* no, it's just some garbage data */
+ return 0;
+ }
+
+ /* check that the non-NULL pointers are safe */
+ if( mw->prev && !mwIsSafeAddr( mw->prev, mwDataSize ) ) mwRelink( mw, file, line );
+ if( mw->next && !mwIsSafeAddr( mw->next, mwDataSize ) ) mwRelink( mw, file, line );
+
+ /* safe address, checksum OK, proceed with heap checks */
+
+ /* see if the block is in the heap */
+ retv = 0;
+ if( mw->prev ) { if( mw->prev->next == mw ) retv ++; }
+ else { if( mwHead == mw ) retv++; }
+ if( mw->next ) { if( mw->next->prev == mw ) retv ++; }
+ else { if( mwTail == mw ) retv++; }
+ if( mw->check == CHKVAL(mw) ) retv ++;
+ if( retv > 2 ) return 1;
+
+ /* block not in heap, check heap for corruption */
+
+ if( !mwIsHeapOK( mw ) ) {
+ if( mwRelink( mw, file, line ) )
+ return 1;
+ }
+
+ /* unable to repair */
+ mwWrite( "internal: <%ld> %s(%d), mwIsOwned fails for MW-%p\n",
+ mwCounter, file, line, mw );
+ mwIncErr();
+
+ return 0;
+ }
+
+/*
+** mwTestBuf:
+** Checks a buffers links and pre/postfixes.
+** Writes errors found to the log.
+** Returns zero if no errors found.
+*/
+static int mwTestBuf( mwData* mw, const char* file, int line ) {
+ int retv = 0;
+ char *p;
+
+ if( file == NULL ) file = "unknown";
+
+ if( !mwIsSafeAddr( mw, mwDataSize + mwOverflowZoneSize ) ) {
+ mwWrite( "internal: <%ld> %s(%d): pointer MW-%p is invalid\n",
+ mwCounter, file, line, mw );
+ mwIncErr();
+ return 2;
+ }
+
+ if( mw->check != CHKVAL(mw) ) {
+ mwWrite( "internal: <%ld> %s(%d), info trashed; relinking\n",
+ mwCounter, file, line );
+ mwIncErr();
+ if( !mwRelink( mw, file, line ) ) return 2;
+ }
+
+ if( mw->prev && mw->prev->next != mw ) {
+ mwWrite( "internal: <%ld> %s(%d), buffer <%ld> %s(%d) link1 broken\n",
+ mwCounter,file,line, (long)mw->size, mw->count, mw->file, mw->line );
+ mwIncErr();
+ if( !mwRelink( mw, file, line ) ) retv = 2;
+ }
+ if( mw->next && mw->next->prev != mw ) {
+ mwWrite( "internal: <%ld> %s(%d), buffer <%ld> %s(%d) link2 broken\n",
+ mwCounter,file,line, (long)mw->size, mw->count, mw->file, mw->line );
+ mwIncErr();
+ if( !mwRelink( mw, file, line ) ) retv = 2;
+ }
+
+ p = ((char*)mw) + mwDataSize;
+ if( mwCheckOF( p ) ) {
+ mwWrite( "underflow: <%ld> %s(%d), %ld bytes alloc'd at <%ld> %s(%d)\n",
+ mwCounter,file,line, (long)mw->size, mw->count, mw->file, mw->line );
+ mwIncErr();
+ retv = 1;
+ }
+ p += mwOverflowZoneSize + mw->size;
+ if( mwIsReadAddr( p, mwOverflowZoneSize ) && mwCheckOF( p ) ) {
+ mwWrite( "overflow: <%ld> %s(%d), %ld bytes alloc'd at <%ld> %s(%d)\n",
+ mwCounter,file,line, (long)mw->size, mw->count, mw->file, mw->line );
+ mwIncErr();
+ retv = 1;
+ }
+
+ return retv;
+ }
+
+static void mwDefaultOutFunc( int c ) {
+ if( mwLogR() ) fputc( c, mwLogR() );
+ }
+
+static void mwWrite( const char *format, ... ) {
+ int tot, oflow = 0;
+ va_list mark;
+ mwAutoInit();
+ if( mwOutFunction == NULL ) mwOutFunction = mwDefaultOutFunc;
+ va_start( mark, format );
+ tot = vsprintf( mwPrintBuf, format, mark );
+ va_end( mark );
+ if( tot >= MW_TRACE_BUFFER ) { mwPrintBuf[MW_TRACE_BUFFER] = 0; oflow = 1; }
+ for(tot=0;mwPrintBuf[tot];tot++)
+ (*mwOutFunction)( mwPrintBuf[tot] );
+ if( oflow ) {
+ mwWrite( "\ninternal: mwWrite(): WARNING! OUTPUT EXCEEDED %u CHARS: SYSTEM UNSTABLE\n", MW_TRACE_BUFFER-1 );
+ FLUSH();
+ }
+ return;
+ }
+
+static void mwLogFile( const char *name ) {
+ time_t tid;
+ (void) time( &tid );
+ if( mwLogR() != NULL ) {
+ fclose( mwLogR() );
+ mwLogW( NULL );
+ }
+ if( name == NULL ) return;
+ mwLogW( fopen( name, "a" COMMIT ) );
+ if( mwLogR() == NULL )
+ mwWrite( "logfile: failed to open/create file '%s'\n", name );
+ }
+
+/*
+** Try to free NML memory until a contiguous allocation of
+** 'needed' bytes can be satisfied. If this is not enough
+** and the 'urgent' parameter is nonzero, grabbed memory is
+** also freed.
+*/
+static size_t mwFreeUp( size_t needed, int urgent ) {
+ void *p;
+ mwData *mw, *mw2;
+ char *data;
+
+ /* free grabbed NML memory */
+ for(;;) {
+ if( mwDrop_( 1, MW_VAL_NML, 1 ) == 0 ) break;
+ p = malloc( needed );
+ if( p == NULL ) continue;
+ free( p );
+ return needed;
+ }
+
+ /* free normal NML memory */
+ mw = mwHead;
+ while( mw != NULL ) {
+ if( !(mw->flag & MW_NML) ) mw = mw->next;
+ else {
+ data = ((char*)mw)+mwDataSize+mwOverflowZoneSize;
+ if( mwTestMem( data, mw->size, MW_VAL_NML ) ) {
+ mwIncErr();
+ mwWrite( "wild pointer: <%ld> NoMansLand %p alloc'd at %s(%d)\n",
+ mw->count, data + mwOverflowZoneSize, mw->file, mw->line );
+ }
+ mw2 = mw->next;
+ mwUnlink( mw, "mwFreeUp", 0 );
+ free( mw );
+ mw = mw2;
+ p = malloc( needed );
+ if( p == NULL ) continue;
+ free( p );
+ return needed;
+ }
+ }
+
+ /* if not urgent (for internal purposes), fail */
+ if( !urgent ) return 0;
+
+ /* free grabbed memory */
+ for(;;) {
+ if( mwDrop_( 1, MW_VAL_GRB, 1 ) == 0 ) break;
+ p = malloc( needed );
+ if( p == NULL ) continue;
+ free( p );
+ return needed;
+ }
+
+ return 0;
+ }
+
+static const void * mwTestMem( const void *p, unsigned len, int c ) {
+ const unsigned char *ptr;
+ ptr = (const unsigned char *) p;
+ while( len-- ) {
+ if( *ptr != (unsigned char)c ) return (const void*)ptr;
+ ptr ++;
+ }
+ return NULL;
+ }
+
+static int mwStrCmpI( const char *s1, const char *s2 ) {
+ if( s1 == NULL || s2 == NULL ) return 0;
+ while( *s1 ) {
+ if( toupper(*s2) == toupper(*s1) ) { s1++; s2++; continue; }
+ return 1;
+ }
+ return 0;
+ }
+
+#define AIPH() if( always_invoked ) { mwWrite("autocheck: <%ld> %s(%d) ", mwCounter, file, line ); always_invoked = 0; }
+
+static int mwTestNow( const char *file, int line, int always_invoked ) {
+ int retv = 0;
+ mwData *mw;
+ char *data;
+
+ if( file && !always_invoked )
+ mwWrite("check: <%ld> %s(%d), checking %s%s%s\n",
+ mwCounter, file, line,
+ (mwTestFlags & MW_TEST_CHAIN) ? "chain ": "",
+ (mwTestFlags & MW_TEST_ALLOC) ? "alloc ": "",
+ (mwTestFlags & MW_TEST_NML) ? "nomansland ": ""
+ );
+
+ if( mwTestFlags & MW_TEST_CHAIN ) {
+ for( mw = mwHead; mw; mw=mw->next ) {
+ if( !mwIsSafeAddr(mw, mwDataSize) ) {
+ AIPH();
+ mwWrite("check: heap corruption detected\n");
+ mwIncErr();
+ return retv + 1;
+ }
+ if( mw->prev ) {
+ if( !mwIsSafeAddr(mw->prev, mwDataSize) ) {
+ AIPH();
+ mwWrite("check: heap corruption detected\n");
+ mwIncErr();
+ return retv + 1;
+ }
+ if( mw==mwHead || mw->prev->next != mw ) {
+ AIPH();
+ mwWrite("check: heap chain broken, prev link incorrect\n");
+ mwIncErr();
+ retv ++;
+ }
+ }
+ if( mw->next ) {
+ if( !mwIsSafeAddr(mw->next, mwDataSize) ) {
+ AIPH();
+ mwWrite("check: heap corruption detected\n");
+ mwIncErr();
+ return retv + 1;
+ }
+ if( mw==mwTail || mw->next->prev != mw ) {
+ AIPH();
+ mwWrite("check: heap chain broken, next link incorrect\n");
+ mwIncErr();
+ retv ++;
+ }
+ }
+ else if( mw!=mwTail ) {
+ AIPH();
+ mwWrite("check: heap chain broken, tail incorrect\n");
+ mwIncErr();
+ retv ++;
+ }
+ }
+ }
+ if( mwTestFlags & MW_TEST_ALLOC ) {
+ for( mw = mwHead; mw; mw=mw->next ) {
+ if( mwTestBuf( mw, file, line ) ) retv ++;
+ }
+ }
+ if( mwTestFlags & MW_TEST_NML ) {
+ for( mw = mwHead; mw; mw=mw->next ) {
+ if( (mw->flag & MW_NML) ) {
+ data = ((char*)mw)+mwDataSize+mwOverflowZoneSize;
+ if( mwTestMem( data, mw->size, MW_VAL_NML ) ) {
+ mwIncErr();
+ mwWrite( "wild pointer: <%ld> NoMansLand %p alloc'd at %s(%d)\n",
+ mw->count, data + mwOverflowZoneSize, mw->file, mw->line );
+ }
+ }
+ }
+ }
+
+
+ if( file && !always_invoked && !retv )
+ mwWrite("check: <%ld> %s(%d), complete; no errors\n",
+ mwCounter, file, line );
+ return retv;
+ }
+
+/**********************************************************************
+** Statistics
+**********************************************************************/
+
+static void mwStatReport()
+{
+ mwStat* ms, *ms2;
+ const char *modname;
+ int modnamelen;
+
+ /* global statistics report */
+ mwWrite( "\nMemory usage statistics (global):\n" );
+ mwWrite( " N)umber of allocations made: %ld\n", mwStatNumAlloc );
+ mwWrite( " L)argest memory usage : %ld\n", mwStatMaxAlloc );
+ mwWrite( " T)otal of all alloc() calls: %ld\n", mwStatTotAlloc );
+ mwWrite( " U)nfreed bytes totals : %ld\n", mwStatCurAlloc );
+ FLUSH();
+
+ if( mwStatLevel < 1 ) return;
+
+ /* on a per-module basis */
+ mwWrite( "\nMemory usage statistics (detailed):\n");
+ mwWrite( " Module/Line Number Largest Total Unfreed \n");
+ for( ms=mwStatList; ms; ms=ms->next )
+ {
+ if( ms->line == -1 )
+ {
+ if( ms->file == NULL || !mwIsReadAddr(ms->file,22) ) modname = "<unknown>";
+ else modname = ms->file;
+ modnamelen = strlen(modname);
+ if( modnamelen > 42 )
+ {
+ modname = modname + modnamelen - 42;
+ }
+
+ mwWrite(" %-42s %-8ld %-8ld %-8ld %-8ld\n",
+ modname, ms->num, ms->max, ms->total, ms->curr );
+ if( ms->file && mwStatLevel > 1 )
+ {
+ for( ms2=mwStatList; ms2; ms2=ms2->next )
+ {
+ if( ms2->line!=-1 && ms2->file!=NULL && !mwStrCmpI( ms2->file, ms->file ) )
+ {
+ mwWrite( " %-8d %-8ld %-8ld %-8ld %-8ld\n",
+ ms2->line, ms2->num, ms2->max, ms2->total, ms2->curr );
+ }
+ }
+ }
+ }
+ }
+}
+
+static mwStat* mwStatGet( const char *file, int line, int makenew ) {
+ mwStat* ms;
+
+ if( mwStatLevel < 2 ) line = -1;
+
+ for( ms=mwStatList; ms!=NULL; ms=ms->next ) {
+ if( line != ms->line ) continue;
+ if( file==NULL ) {
+ if( ms->file == NULL ) break;
+ continue;
+ }
+ if( ms->file == NULL ) continue;
+ if( !strcmp( ms->file, file ) ) break;
+ }
+
+ if( ms != NULL ) return ms;
+
+ if( !makenew ) return NULL;
+
+ ms = (mwStat*) malloc( sizeof(mwStat) );
+ if( ms == NULL ) {
+ if( mwFreeUp( sizeof(mwStat), 0 ) < sizeof(mwStat) ||
+ (ms=(mwStat*)malloc(sizeof(mwStat))) == NULL ) {
+ mwWrite("internal: memory low, statistics incomplete for '%s'\n", file );
+ return NULL;
+ }
+ }
+ ms->file = file;
+ ms->line = line;
+ ms->total = 0L;
+ ms->max = 0L;
+ ms->num = 0L;
+ ms->curr = 0L;
+ ms->next = mwStatList;
+ mwStatList = ms;
+ return ms;
+ }
+
+static void mwStatAlloc( size_t size, const char* file, int line ) {
+ mwStat* ms;
+
+ /* update the module statistics */
+ ms = mwStatGet( file, -1, 1 );
+ if( ms != NULL ) {
+ ms->total += (long) size;
+ ms->curr += (long) size;
+ ms->num ++;
+ if( ms->curr > ms->max ) ms->max = ms->curr;
+ }
+
+ /* update the line statistics */
+ if( mwStatLevel > 1 && line != -1 && file ) {
+ ms = mwStatGet( file, line, 1 );
+ if( ms != NULL ) {
+ ms->total += (long) size;
+ ms->curr += (long) size;
+ ms->num ++;
+ if( ms->curr > ms->max ) ms->max = ms->curr;
+ }
+ }
+
+ }
+
+static void mwStatFree( size_t size, const char* file, int line ) {
+ mwStat* ms;
+
+ /* update the module statistics */
+ ms = mwStatGet( file, -1, 1 );
+ if( ms != NULL ) ms->curr -= (long) size;
+
+ /* update the line statistics */
+ if( mwStatLevel > 1 && line != -1 && file ) {
+ ms = mwStatGet( file, line, 1 );
+ if( ms != NULL ) ms->curr -= (long) size;
+ }
+ }
+
+/***********************************************************************
+** Safe memory checkers
+**
+** Using ifdefs, implement the operating-system specific mechanism
+** of identifying a piece of memory as legal to access with read
+** and write priviliges. Default: return nonzero for non-NULL pointers.
+***********************************************************************/
+
+static char mwDummy( char c )
+{
+ return c;
+}
+
+#ifndef MW_SAFEADDR
+#ifdef WIN32
+#define MW_SAFEADDR
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+int mwIsReadAddr( const void *p, unsigned len )
+{
+ if( p == NULL ) return 0;
+ if( IsBadReadPtr(p,len) ) return 0;
+ return 1;
+}
+int mwIsSafeAddr( void *p, unsigned len )
+{
+ /* NOTE: For some reason, under Win95 the IsBad... */
+ /* can return false for invalid pointers. */
+ if( p == NULL ) return 0;
+ if( IsBadReadPtr(p,len) || IsBadWritePtr(p,len) ) return 0;
+ return 1;
+}
+#endif /* WIN32 */
+#endif /* MW_SAFEADDR */
+
+#ifndef MW_SAFEADDR
+#ifdef SIGSEGV
+#define MW_SAFEADDR
+
+typedef void (*mwSignalHandlerPtr)( int );
+mwSignalHandlerPtr mwOldSIGSEGV = (mwSignalHandlerPtr) 0;
+jmp_buf mwSIGSEGVjump;
+static void mwSIGSEGV( int n );
+
+static void mwSIGSEGV( int n )
+{
+ n = n;
+ longjmp( mwSIGSEGVjump, 1 );
+}
+
+int mwIsReadAddr( const void *p, unsigned len )
+{
+ const char *ptr;
+
+ if( p == NULL ) return 0;
+ if( !len ) return 1;
+
+ /* set up to catch the SIGSEGV signal */
+ mwOldSIGSEGV = signal( SIGSEGV, mwSIGSEGV );
+
+ if( setjmp( mwSIGSEGVjump ) )
+ {
+ signal( SIGSEGV, mwOldSIGSEGV );
+ return 0;
+ }
+
+ /* read all the bytes in the range */
+ ptr = (const char *)p;
+ ptr += len;
+
+ /* the reason for this rather strange construct is that */
+ /* we want to keep the number of used parameters and locals */
+ /* to a minimum. if we use len for a counter gcc will complain */
+ /* it may get clobbered by longjmp() at high warning levels. */
+ /* it's a harmless warning, but this way we don't have to see it. */
+ do
+ {
+ ptr --;
+ if( *ptr == 0x7C ) (void) mwDummy( (char)0 );
+ } while( (const void*) ptr != p );
+
+ /* remove the handler */
+ signal( SIGSEGV, mwOldSIGSEGV );
+
+ return 1;
+}
+int mwIsSafeAddr( void *p, unsigned len )
+{
+ char *ptr;
+
+ if( p == NULL ) return 0;
+ if( !len ) return 1;
+
+ /* set up to catch the SIGSEGV signal */
+ mwOldSIGSEGV = signal( SIGSEGV, mwSIGSEGV );
+
+ if( setjmp( mwSIGSEGVjump ) )
+ {
+ signal( SIGSEGV, mwOldSIGSEGV );
+ return 0;
+ }
+
+ /* read and write-back all the bytes in the range */
+ ptr = (char *)p;
+ ptr += len;
+
+ /* the reason for this rather strange construct is that */
+ /* we want to keep the number of used parameters and locals */
+ /* to a minimum. if we use len for a counter gcc will complain */
+ /* it may get clobbered by longjmp() at high warning levels. */
+ /* it's a harmless warning, but this way we don't have to see it. */
+ do
+ {
+ ptr --;
+ *ptr = mwDummy( *ptr );
+ } while( (void*) ptr != p );
+
+ /* remove the handler */
+ signal( SIGSEGV, mwOldSIGSEGV );
+
+ return 1;
+}
+#endif /* SIGSEGV */
+#endif /* MW_SAFEADDR */
+
+#ifndef MW_SAFEADDR
+int mwIsReadAddr( const void *p, unsigned len )
+{
+ if( p == NULL ) return 0;
+ if( len == 0 ) return 1;
+ return 1;
+}
+int mwIsSafeAddr( void *p, unsigned len )
+{
+ if( p == NULL ) return 0;
+ if( len == 0 ) return 1;
+ return 1;
+}
+#endif
+
+/**********************************************************************
+** Mutex handling
+**********************************************************************/
+
+#if defined(WIN32) || defined(__WIN32__)
+
+static void mwMutexInit( void )
+{
+ mwGlobalMutex = CreateMutex( NULL, FALSE, NULL);
+ return;
+}
+
+static void mwMutexTerm( void )
+{
+ CloseHandle( mwGlobalMutex );
+ return;
+}
+
+static void mwMutexLock( void )
+{
+ if( WaitForSingleObject(mwGlobalMutex, 1000 ) == WAIT_TIMEOUT )
+ {
+ mwWrite( "mwMutexLock: timed out, possible deadlock\n" );
+ }
+ return;
+}
+
+static void mwMutexUnlock( void )
+{
+ ReleaseMutex( mwGlobalMutex );
+ return;
+}
+
+#endif
+
+#if defined(MW_PTHREADS) || defined(HAVE_PTHREAD_H)
+
+static void mwMutexInit( void )
+{
+ pthread_mutex_init( &mwGlobalMutex, NULL );
+ return;
+}
+
+static void mwMutexTerm( void )
+{
+ pthread_mutex_destroy( &mwGlobalMutex );
+ return;
+}
+
+static void mwMutexLock( void )
+{
+ pthread_mutex_lock(&mwGlobalMutex);
+ return;
+}
+
+static void mwMutexUnlock( void )
+{
+ pthread_mutex_unlock(&mwGlobalMutex);
+ return;
+}
+
+#endif
+
+/**********************************************************************
+** C++ new & delete
+**********************************************************************/
+
+#if 0 /* 980317: disabled C++ */
+
+#ifdef __cplusplus
+#ifndef MEMWATCH_NOCPP
+
+int mwNCur = 0;
+const char *mwNFile = NULL;
+int mwNLine = 0;
+
+class MemWatch {
+public:
+ MemWatch();
+ ~MemWatch();
+ };
+
+MemWatch::MemWatch() {
+ if( mwInited ) return;
+ mwUseAtexit = 0;
+ mwInit();
+ }
+
+MemWatch::~MemWatch() {
+ if( mwUseAtexit ) return;
+ mwTerm();
+ }
+
+/*
+** This global new will catch all 'new' calls where MEMWATCH is
+** not active.
+*/
+void* operator new( unsigned size ) {
+ mwNCur = 0;
+ return mwMalloc( size, "<unknown>", 0 );
+ }
+
+/*
+** This is the new operator that's called when a module uses mwNew.
+*/
+void* operator new( unsigned size, const char *file, int line ) {
+ mwNCur = 0;
+ return mwMalloc( size, file, line );
+ }
+
+/*
+** This is the new operator that's called when a module uses mwNew[].
+** -- hjc 07/16/02
+*/
+void* operator new[] ( unsigned size, const char *file, int line ) {
+ mwNCur = 0;
+ return mwMalloc( size, file, line );
+ }
+
+/*
+** Since this delete operator will recieve ALL delete's
+** even those from within libraries, we must accept
+** delete's before we've been initialized. Nor can we
+** reliably check for wild free's if the mwNCur variable
+** is not set.
+*/
+void operator delete( void *p ) {
+ if( p == NULL ) return;
+ if( !mwInited ) {
+ free( p );
+ return;
+ }
+ if( mwNCur ) {
+ mwFree( p, mwNFile, mwNLine );
+ mwNCur = 0;
+ return;
+ }
+ mwFree_( p );
+ }
+
+void operator delete[]( void *p ) {
+ if( p == NULL ) return;
+ if( !mwInited ) {
+ free( p );
+ return;
+ }
+ if( mwNCur ) {
+ mwFree( p, mwNFile, mwNLine );
+ mwNCur = 0;
+ return;
+ }
+ mwFree_( p );
+ }
+
+#endif /* MEMWATCH_NOCPP */
+#endif /* __cplusplus */
+
+#endif /* 980317: disabled C++ */
+
+/* MEMWATCH.C */
Added: packages-wip/libxslt-ruby/trunk/debug/memwatch.h
===================================================================
--- packages-wip/libxslt-ruby/trunk/debug/memwatch.h 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/debug/memwatch.h 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,707 @@
+/*
+** MEMWATCH.H
+** Nonintrusive ANSI C memory leak / overwrite detection
+** Copyright (C) 1992-2002 Johan Lindh
+** All rights reserved.
+** Version 2.71
+**
+************************************************************************
+**
+** PURPOSE:
+**
+** MEMWATCH has been written to allow guys and gals that like to
+** program in C a public-domain memory error control product.
+** I hope you'll find it's as advanced as most commercial packages.
+** The idea is that you use it during the development phase and
+** then remove the MEMWATCH define to produce your final product.
+** MEMWATCH is distributed in source code form in order to allow
+** you to compile it for your platform with your own compiler.
+** It's aim is to be 100% ANSI C, but some compilers are more stingy
+** than others. If it doesn't compile without warnings, please mail
+** me the configuration of operating system and compiler you are using
+** along with a description of how to modify the source, and the version
+** number of MEMWATCH that you are using.
+**
+************************************************************************
+
+ This file is part of MEMWATCH.
+
+ MEMWATCH is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ MEMWATCH 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 MEMWATCH; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+************************************************************************
+**
+** REVISION HISTORY:
+**
+** 920810 JLI [1.00]
+** 920830 JLI [1.10 double-free detection]
+** 920912 JLI [1.15 mwPuts, mwGrab/Drop, mwLimit]
+** 921022 JLI [1.20 ASSERT and VERIFY]
+** 921105 JLI [1.30 C++ support and TRACE]
+** 921116 JLI [1.40 mwSetOutFunc]
+** 930215 JLI [1.50 modified ASSERT/VERIFY]
+** 930327 JLI [1.51 better auto-init & PC-lint support]
+** 930506 JLI [1.55 MemWatch class, improved C++ support]
+** 930507 JLI [1.60 mwTest & CHECK()]
+** 930809 JLI [1.65 Abort/Retry/Ignore]
+** 930820 JLI [1.70 data dump when unfreed]
+** 931016 JLI [1.72 modified C++ new/delete handling]
+** 931108 JLI [1.77 mwSetAssertAction() & some small changes]
+** 940110 JLI [1.80 no-mans-land alloc/checking]
+** 940328 JLI [2.00 version 2.0 rewrite]
+** Improved NML (no-mans-land) support.
+** Improved performance (especially for free()ing!).
+** Support for 'read-only' buffers (checksums)
+** ^^ NOTE: I never did this... maybe I should?
+** FBI (free'd block info) tagged before freed blocks
+** Exporting of the mwCounter variable
+** mwBreakOut() localizes debugger support
+** Allocation statistics (global, per-module, per-line)
+** Self-repair ability with relinking
+** 950913 JLI [2.10 improved garbage handling]
+** 951201 JLI [2.11 improved auto-free in emergencies]
+** 960125 JLI [X.01 implemented auto-checking using mwAutoCheck()]
+** 960514 JLI [2.12 undefining of existing macros]
+** 960515 JLI [2.13 possibility to use default new() & delete()]
+** 960516 JLI [2.20 suppression of file flushing on unfreed msgs]
+** 960516 JLI [2.21 better support for using MEMWATCH with DLL's]
+** 960710 JLI [X.02 multiple logs and mwFlushNow()]
+** 960801 JLI [2.22 merged X.01 version with current]
+** 960805 JLI [2.30 mwIsXXXXAddr() to avoid unneeded GP's]
+** 960805 JLI [2.31 merged X.02 version with current]
+** 961002 JLI [2.32 support for realloc() + fixed STDERR bug]
+** 961222 JLI [2.40 added mwMark() & mwUnmark()]
+** 970101 JLI [2.41 added over/underflow checking after failed ASSERT/VERIFY]
+** 970113 JLI [2.42 added support for PC-Lint 7.00g]
+** 970207 JLI [2.43 added support for strdup()]
+** 970209 JLI [2.44 changed default filename to lowercase]
+** 970405 JLI [2.45 fixed bug related with atexit() and some C++ compilers]
+** 970723 JLI [2.46 added MW_ARI_NULLREAD flag]
+** 970813 JLI [2.47 stabilized marker handling]
+** 980317 JLI [2.48 ripped out C++ support; wasn't working good anyway]
+** 980318 JLI [2.50 improved self-repair facilities & SIGSEGV support]
+** 980417 JLI [2.51 more checks for invalid addresses]
+** 980512 JLI [2.52 moved MW_ARI_NULLREAD to occur before aborting]
+** 990112 JLI [2.53 added check for empty heap to mwIsOwned]
+** 990217 JLI [2.55 improved the emergency repairs diagnostics and NML]
+** 990224 JLI [2.56 changed ordering of members in structures]
+** 990303 JLI [2.57 first maybe-fixit-for-hpux test]
+** 990516 JLI [2.58 added 'static' to the definition of mwAutoInit]
+** 990517 JLI [2.59 fixed some high-sensitivity warnings]
+** 990610 JLI [2.60 fixed some more high-sensitivity warnings]
+** 990715 JLI [2.61 changed TRACE/ASSERT/VERIFY macro names]
+** 991001 JLI [2.62 added CHECK_BUFFER() and mwTestBuffer()]
+** 991007 JLI [2.63 first shot at a 64-bit compatible version]
+** 991009 JLI [2.64 undef's strdup() if defined, mwStrdup made const]
+** 000704 JLI [2.65 added some more detection for 64-bits]
+** 010502 JLI [2.66 incorporated some user fixes]
+** [mwRelink() could print out garbage pointer (thanks mac at phobos.ca)]
+** [added array destructor for C++ (thanks rdasilva at connecttel.com)]
+** [added mutex support (thanks rdasilva at connecttel.com)]
+** 010531 JLI [2.67 fix: mwMutexXXX() was declared even if MW_HAVE_MUTEX was not defined]
+** 010619 JLI [2.68 fix: mwRealloc() could leave the mutex locked]
+** 020918 JLI [2.69 changed to GPL, added C++ array allocation by Howard Cohen]
+** 030212 JLI [2.70 mwMalloc() bug for very large allocations (4GB on 32bits)]
+** 030520 JLI [2.71 added ULONG_LONG_MAX as a 64-bit detector (thanks Sami Salonen)]
+**
+** To use, simply include 'MEMWATCH.H' as a header file,
+** and add MEMWATCH.C to your list of files, and define the macro
+** 'MEMWATCH'. If this is not defined, MEMWATCH will disable itself.
+**
+** To call the standard C malloc / realloc / calloc / free; use mwMalloc_(),
+** mwCalloc_() and mwFree_(). Note that mwFree_() will correctly
+** free both malloc()'d memory as well as mwMalloc()'d.
+**
+** 980317: C++ support has been disabled.
+** The code remains, but is not compiled.
+**
+** For use with C++, which allows use of inlining in header files
+** and class specific new/delete, you must also define 'new' as
+** 'mwNew' and 'delete' as 'mwDelete'. Do this *after* you include
+** C++ header files from libraries, otherwise you can mess up their
+** class definitions. If you don't define these, the C++ allocations
+** will not have source file and line number information. Also note,
+** most C++ class libraries implement their own C++ memory management,
+** and don't allow anyone to override them. MFC belongs to this crew.
+** In these cases, the only thing to do is to use MEMWATCH_NOCPP.
+**
+** You can capture output from MEMWATCH using mwSetOutFunc().
+** Just give it the adress of a "void myOutFunc(int c)" function,
+** and all characters to be output will be redirected there.
+**
+** A failing ASSERT() or VERIFY() will normally always abort your
+** program. This can be changed using mwSetAriFunc(). Give it a
+** pointer to a "int myAriFunc(const char *)" function. Your function
+** must ask the user whether to Abort, Retry or Ignore the trap.
+** Return 2 to Abort, 1 to Retry or 0 to Ignore. Beware retry; it
+** causes the expression to be evaluated again! MEMWATCH has a
+** default ARI handler. It's disabled by default, but you can enable
+** it by calling 'mwDefaultAri()'. Note that this will STILL abort
+** your program unless you define MEMWATCH_STDIO to allow MEMWATCH
+** to use the standard C I/O streams. Also, setting the ARI function
+** will cause MEMWATCH *NOT* to write the ARI error to stderr. The
+** error string is passed to the ARI function instead, as the
+** 'const char *' parameter.
+**
+** You can disable MEMWATCH's ASSERT/VERIFY and/or TRACE implementations.
+** This can be useful if you're using a debug terminal or smart debugger.
+** Disable them by defining MW_NOASSERT, MW_NOVERIFY or MW_NOTRACE.
+**
+** MEMWATCH fills all allocated memory with the byte 0xFE, so if
+** you're looking at erroneous data which are all 0xFE:s, the
+** data probably was not initialized by you. The exception is
+** calloc(), which will fill with zero's. All freed buffers are
+** zapped with 0xFD. If this is what you look at, you're using
+** data that has been freed. If this is the case, be aware that
+** MEMWATCH places a 'free'd block info' structure immediately
+** before the freed data. This block contains info about where
+** the block was freed. The information is in readable text,
+** in the format "FBI<counter>filename(line)", for example:
+** "FBI<267>test.c(12)". Using FBI's slows down free(), so it's
+** disabled by default. Use mwFreeBufferInfo(1) to enable it.
+**
+** To aid in tracking down wild pointer writes, MEMWATCH can perform
+** no-mans-land allocations. No-mans-land will contain the byte 0xFC.
+** MEMWATCH will, when this is enabled, convert recently free'd memory
+** into NML allocations.
+**
+** MEMWATCH protects it's own data buffers with checksums. If you
+** get an internal error, it means you're overwriting wildly,
+** or using an uninitialized pointer.
+**
+************************************************************************
+**
+** Note when compiling with Microsoft C:
+** - MSC ignores fflush() by default. This is overridden, so that
+** the disk log will always be current.
+**
+** This utility has been tested with:
+** PC-lint 7.0k, passed as 100% ANSI C compatible
+** Microsoft Visual C++ on Win16 and Win32
+** Microsoft C on DOS
+** SAS C on an Amiga 500
+** Gnu C on a PC running Red Hat Linux
+** ...and using an (to me) unknown compiler on an Atari machine.
+**
+************************************************************************
+**
+** Format of error messages in MEMWATCH.LOG:
+** message: <sequence-number> filename(linenumber), information
+**
+** Errors caught by MemWatch, when they are detected, and any
+** actions taken besides writing to the log file MEMWATCH.LOG:
+**
+** Double-freeing:
+** A pointer that was recently freed and has not since been
+** reused was freed again. The place where the previous free()
+** was executed is displayed.
+** Detect: delete or free() using the offending pointer.
+** Action: The delete or free() is cancelled, execution continues.
+** Underflow:
+** You have written just ahead of the allocated memory.
+** The size and place of the allocation is displayed.
+** Detect: delete or free() of the damaged buffer.
+** Action: The buffer is freed, but there may be secondary damage.
+** Overflow:
+** Like underflow, but you've written after the end of the buffer.
+** Detect: see Underflow.
+** Action: see Underflow.
+** WILD free:
+** An unrecognized pointer was passed to delete or free().
+** The pointer may have been returned from a library function;
+** in that case, use mwFree_() to force free() of it.
+** Also, this may be a double-free, but the previous free was
+** too long ago, causing MEMWATCH to 'forget' it.
+** Detect: delete or free() of the offending pointer.
+** Action: The delete or free() is cancelled, execution continues.
+** NULL free:
+** It's unclear to me whether or not freeing of NULL pointers
+** is legal in ANSI C, therefore a warning is written to the log file,
+** but the error counter remains the same. This is legal using C++,
+** so the warning does not appear with delete.
+** Detect: When you free(NULL).
+** Action: The free() is cancelled.
+** Failed:
+** A request to allocate memory failed. If the allocation is
+** small, this may be due to memory depletion, but is more likely
+** to be memory fragmentation problems. The amount of memory
+** allocated so far is displayed also.
+** Detect: When you new, malloc(), realloc() or calloc() memory.
+** Action: NULL is returned.
+** Realloc:
+** A request to re-allocate a memory buffer failed for reasons
+** other than out-of-memory. The specific reason is shown.
+** Detect: When you realloc()
+** Action: realloc() is cancelled, NULL is returned
+** Limit fail:
+** A request to allocate memory failed since it would violate
+** the limit set using mwLimit(). mwLimit() is used to stress-test
+** your code under simulated low memory conditions.
+** Detect: At new, malloc(), realloc() or calloc().
+** Action: NULL is returned.
+** Assert trap:
+** An ASSERT() failed. The ASSERT() macro works like C's assert()
+** macro/function, except that it's interactive. See your C manual.
+** Detect: On the ASSERT().
+** Action: Program ends with an advisory message to stderr, OR
+** Program writes the ASSERT to the log and continues, OR
+** Program asks Abort/Retry/Ignore? and takes that action.
+** Verify trap:
+** A VERIFY() failed. The VERIFY() macro works like ASSERT(),
+** but if MEMWATCH is not defined, it still evaluates the
+** expression, but it does not act upon the result.
+** Detect: On the VERIFY().
+** Action: Program ends with an advisory message to stderr, OR
+** Program writes the VERIFY to the log and continues, OR
+** Program asks Abort/Retry/Ignore? and takes that action.
+** Wild pointer:
+** A no-mans-land buffer has been written into. MEMWATCH can
+** allocate and distribute chunks of memory solely for the
+** purpose of trying to catch random writes into memory.
+** Detect: Always on CHECK(), but can be detected in several places.
+** Action: The error is logged, and if an ARI handler is installed,
+** it is executed, otherwise, execution continues.
+** Unfreed:
+** A memory buffer you allocated has not been freed.
+** You are informed where it was allocated, and whether any
+** over or underflow has occured. MemWatch also displays up to
+** 16 bytes of the data, as much as it can, in hex and text.
+** Detect: When MemWatch terminates.
+** Action: The buffer is freed.
+** Check:
+** An error was detected during a CHECK() operation.
+** The associated pointer is displayed along with
+** the file and line where the CHECK() was executed.
+** Followed immediately by a normal error message.
+** Detect: When you CHECK()
+** Action: Depends on the error
+** Relink:
+** After a MEMWATCH internal control block has been trashed,
+** MEMWATCH tries to repair the damage. If successful, program
+** execution will continue instead of aborting. Some information
+** about the block may be gone permanently, though.
+** Detect: N/A
+** Action: Relink successful: program continues.
+** Relink fails: program aborts.
+** Internal:
+** An internal error is flagged by MEMWATCH when it's control
+** structures have been damaged. You are likely using an uninitialized
+** pointer somewhere in your program, or are zapping memory all over.
+** The message may give you additional diagnostic information.
+** If possible, MEMWATCH will recover and continue execution.
+** Detect: Various actions.
+** Action: Whatever is needed
+** Mark:
+** The program terminated without umarking all marked pointers. Marking
+** can be used to track resources other than memory. mwMark(pointer,text,...)
+** when the resource is allocated, and mwUnmark(pointer) when it's freed.
+** The 'text' is displayed for still marked pointers when the program
+** ends.
+** Detect: When MemWatch terminates.
+** Action: The error is logged.
+**
+**
+************************************************************************
+**
+** The author may be reached by e-mail at the address below. If you
+** mail me about source code changes in MEMWATCH, remember to include
+** MW's version number.
+**
+** Johan Lindh
+** johan at linkdata.se
+**
+** The latest version of MEMWATCH may be downloaded from
+** http://www.linkdata.se/
+*/
+
+#ifndef __MEMWATCH_H
+#define __MEMWATCH_H
+
+/* Make sure that malloc(), realloc(), calloc() and free() are declared. */
+/*lint -save -e537 */
+#include <stdlib.h>
+/*lint -restore */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+** Constants used
+** All MEMWATCH constants start with the prefix MW_, followed by
+** a short mnemonic which indicates where the constant is used,
+** followed by a descriptive text about it.
+*/
+
+#define MW_ARI_NULLREAD 0x10 /* Null read (to start debugger) */
+#define MW_ARI_ABORT 0x04 /* ARI handler says: abort program! */
+#define MW_ARI_RETRY 0x02 /* ARI handler says: retry action! */
+#define MW_ARI_IGNORE 0x01 /* ARI handler says: ignore error! */
+
+#define MW_VAL_NEW 0xFE /* value in newly allocated memory */
+#define MW_VAL_DEL 0xFD /* value in newly deleted memory */
+#define MW_VAL_NML 0xFC /* value in no-mans-land */
+#define MW_VAL_GRB 0xFB /* value in grabbed memory */
+
+#define MW_TEST_ALL 0xFFFF /* perform all tests */
+#define MW_TEST_CHAIN 0x0001 /* walk the heap chain */
+#define MW_TEST_ALLOC 0x0002 /* test allocations & NML guards */
+#define MW_TEST_NML 0x0004 /* test all-NML areas for modifications */
+
+#define MW_NML_NONE 0 /* no NML */
+#define MW_NML_FREE 1 /* turn FREE'd memory into NML */
+#define MW_NML_ALL 2 /* all unused memory is NML */
+#define MW_NML_DEFAULT 0 /* the default NML setting */
+
+#define MW_STAT_GLOBAL 0 /* only global statistics collected */
+#define MW_STAT_MODULE 1 /* collect statistics on a module basis */
+#define MW_STAT_LINE 2 /* collect statistics on a line basis */
+#define MW_STAT_DEFAULT 0 /* the default statistics setting */
+
+/*
+** MemWatch internal constants
+** You may change these and recompile MemWatch to change the limits
+** of some parameters. Respect the recommended minimums!
+*/
+#define MW_TRACE_BUFFER 2048 /* (min 160) size of TRACE()'s output buffer */
+#define MW_FREE_LIST 64 /* (min 4) number of free()'s to track */
+
+/*
+** Exported variables
+** In case you have to remove the 'const' keyword because your compiler
+** doesn't support it, be aware that changing the values may cause
+** unpredictable behaviour.
+** - mwCounter contains the current action count. You can use this to
+** place breakpoints using a debugger, if you want.
+*/
+#ifndef __MEMWATCH_C
+extern const unsigned long mwCounter;
+#endif
+
+/*
+** System functions
+** Normally, it is not nessecary to call any of these. MEMWATCH will
+** automatically initialize itself on the first MEMWATCH function call,
+** and set up a call to mwAbort() using atexit(). Some C++ implementations
+** run the atexit() chain before the program has terminated, so you
+** may have to use mwInit() or the MemWatch C++ class to get good
+** behaviour.
+** - mwInit() can be called to disable the atexit() usage. If mwInit()
+** is called directly, you must call mwTerm() to end MemWatch, or
+** mwAbort().
+** - mwTerm() is usually not nessecary to call; but if called, it will
+** call mwAbort() if it finds that it is cancelling the 'topmost'
+** mwInit() call.
+** - mwAbort() cleans up after MEMWATCH, reports unfreed buffers, etc.
+*/
+void mwInit( void );
+void mwTerm( void );
+void mwAbort( void );
+
+/*
+** Setup functions
+** These functions control the operation of MEMWATCH's protective features.
+** - mwFlushNow() causes MEMWATCH to flush it's buffers.
+** - mwDoFlush() controls whether MEMWATCH flushes the disk buffers after
+** writes. The default is smart flushing: MEMWATCH will not flush buffers
+** explicitly until memory errors are detected. Then, all writes are
+** flushed until program end or mwDoFlush(0) is called.
+** - mwLimit() sets the allocation limit, an arbitrary limit on how much
+** memory your program may allocate in bytes. Used to stress-test app.
+** Also, in virtual-memory or multitasking environs, puts a limit on
+** how much MW_NML_ALL can eat up.
+** - mwGrab() grabs up X kilobytes of memory. Allocates actual memory,
+** can be used to stress test app & OS both.
+** - mwDrop() drops X kilobytes of grabbed memory.
+** - mwNoMansLand() sets the behaviour of the NML logic. See the
+** MW_NML_xxx for more information. The default is MW_NML_DEFAULT.
+** - mwStatistics() sets the behaviour of the statistics collector. See
+** the MW_STAT_xxx defines for more information. Default MW_STAT_DEFAULT.
+** - mwFreeBufferInfo() enables or disables the tagging of free'd buffers
+** with freeing information. This information is written in text form,
+** using sprintf(), so it's pretty slow. Disabled by default.
+** - mwAutoCheck() performs a CHECK() operation whenever a MemWatch function
+** is used. Slows down performance, of course.
+** - mwCalcCheck() calculates checksums for all data buffers. Slow!
+** - mwDumpCheck() logs buffers where stored & calc'd checksums differ. Slow!!
+** - mwMark() sets a generic marker. Returns the pointer given.
+** - mwUnmark() removes a generic marker. If, at the end of execution, some
+** markers are still in existence, these will be reported as leakage.
+** returns the pointer given.
+*/
+void mwFlushNow( void );
+void mwDoFlush( int onoff );
+void mwLimit( long bytes );
+unsigned mwGrab( unsigned kilobytes );
+unsigned mwDrop( unsigned kilobytes );
+void mwNoMansLand( int mw_nml_level );
+void mwStatistics( int level );
+void mwFreeBufferInfo( int onoff );
+void mwAutoCheck( int onoff );
+void mwCalcCheck( void );
+void mwDumpCheck( void );
+void * mwMark( void *p, const char *description, const char *file, unsigned line );
+void * mwUnmark( void *p, const char *file, unsigned line );
+
+/*
+** Testing/verification/tracing
+** All of these macros except VERIFY() evaluates to a null statement
+** if MEMWATCH is not defined during compilation.
+** - mwIsReadAddr() checks a memory area for read privilige.
+** - mwIsSafeAddr() checks a memory area for both read & write privilige.
+** This function and mwIsReadAddr() is highly system-specific and
+** may not be implemented. If this is the case, they will default
+** to returning nonzero for any non-NULL pointer.
+** - CHECK() does a complete memory integrity test. Slow!
+** - CHECK_THIS() checks only selected components.
+** - CHECK_BUFFER() checks the indicated buffer for errors.
+** - mwASSERT() or ASSERT() If the expression evaluates to nonzero, execution continues.
+** Otherwise, the ARI handler is called, if present. If not present,
+** the default ARI action is taken (set with mwSetAriAction()).
+** ASSERT() can be disabled by defining MW_NOASSERT.
+** - mwVERIFY() or VERIFY() works just like ASSERT(), but when compiling without
+** MEMWATCH the macro evaluates to the expression.
+** VERIFY() can be disabled by defining MW_NOVERIFY.
+** - mwTRACE() or TRACE() writes some text and data to the log. Use like printf().
+** TRACE() can be disabled by defining MW_NOTRACE.
+*/
+int mwIsReadAddr( const void *p, unsigned len );
+int mwIsSafeAddr( void *p, unsigned len );
+int mwTest( const char *file, int line, int mw_test_flags );
+int mwTestBuffer( const char *file, int line, void *p );
+int mwAssert( int, const char*, const char*, int );
+int mwVerify( int, const char*, const char*, int );
+
+/*
+** User I/O functions
+** - mwTrace() works like printf(), but dumps output either to the
+** function specified with mwSetOutFunc(), or the log file.
+** - mwPuts() works like puts(), dumps output like mwTrace().
+** - mwSetOutFunc() allows you to give the adress of a function
+** where all user output will go. (exeption: see mwSetAriFunc)
+** Specifying NULL will direct output to the log file.
+** - mwSetAriFunc() gives MEMWATCH the adress of a function to call
+** when an 'Abort, Retry, Ignore' question is called for. The
+** actual error message is NOT printed when you've set this adress,
+** but instead it is passed as an argument. If you call with NULL
+** for an argument, the ARI handler is disabled again. When the
+** handler is disabled, MEMWATCH will automatically take the
+** action specified by mwSetAriAction().
+** - mwSetAriAction() sets the default ARI return value MEMWATCH should
+** use if no ARI handler is specified. Defaults to MW_ARI_ABORT.
+** - mwAriHandler() is an ANSI ARI handler you can use if you like. It
+** dumps output to stderr, and expects input from stdin.
+** - mwBreakOut() is called in certain cases when MEMWATCH feels it would
+** be nice to break into a debugger. If you feel like MEMWATCH, place
+** an execution breakpoint on this function.
+*/
+void mwTrace( const char* format_string, ... );
+void mwPuts( const char* text );
+void mwSetOutFunc( void (*func)(int) );
+void mwSetAriFunc( int (*func)(const char*) );
+void mwSetAriAction( int mw_ari_value );
+int mwAriHandler( const char* cause );
+void mwBreakOut( const char* cause );
+
+/*
+** Allocation/deallocation functions
+** These functions are the ones actually to perform allocations
+** when running MEMWATCH, for both C and C++ calls.
+** - mwMalloc() debugging allocator
+** - mwMalloc_() always resolves to a clean call of malloc()
+** - mwRealloc() debugging re-allocator
+** - mwRealloc_() always resolves to a clean call of realloc()
+** - mwCalloc() debugging allocator, fills with zeros
+** - mwCalloc_() always resolves to a clean call of calloc()
+** - mwFree() debugging free. Can only free memory which has
+** been allocated by MEMWATCH.
+** - mwFree_() resolves to a) normal free() or b) debugging free.
+** Can free memory allocated by MEMWATCH and malloc() both.
+** Does not generate any runtime errors.
+*/
+void* mwMalloc( size_t, const char*, int );
+void* mwMalloc_( size_t );
+void* mwRealloc( void *, size_t, const char*, int );
+void* mwRealloc_( void *, size_t );
+void* mwCalloc( size_t, size_t, const char*, int );
+void* mwCalloc_( size_t, size_t );
+void mwFree( void*, const char*, int );
+void mwFree_( void* );
+char* mwStrdup( const char *, const char*, int );
+
+/*
+** Enable/disable precompiler block
+** This block of defines and if(n)defs make sure that references
+** to MEMWATCH is completely removed from the code if the MEMWATCH
+** manifest constant is not defined.
+*/
+#ifndef __MEMWATCH_C
+#ifdef MEMWATCH
+
+#define mwASSERT(exp) while(mwAssert((int)(exp),#exp,__FILE__,__LINE__))
+#ifndef MW_NOASSERT
+#ifndef ASSERT
+#define ASSERT mwASSERT
+#endif /* !ASSERT */
+#endif /* !MW_NOASSERT */
+#define mwVERIFY(exp) while(mwVerify((int)(exp),#exp,__FILE__,__LINE__))
+#ifndef MW_NOVERIFY
+#ifndef VERIFY
+#define VERIFY mwVERIFY
+#endif /* !VERIFY */
+#endif /* !MW_NOVERIFY */
+#define mwTRACE mwTrace
+#ifndef MW_NOTRACE
+#ifndef TRACE
+#define TRACE mwTRACE
+#endif /* !TRACE */
+#endif /* !MW_NOTRACE */
+
+/* some compilers use a define and not a function */
+/* for strdup(). */
+#ifdef strdup
+#undef strdup
+#endif
+
+#define malloc(n) mwMalloc(n,__FILE__,__LINE__)
+#define strdup(p) mwStrdup(p,__FILE__,__LINE__)
+#define realloc(p,n) mwRealloc(p,n,__FILE__,__LINE__)
+#define calloc(n,m) mwCalloc(n,m,__FILE__,__LINE__)
+#define free(p) mwFree(p,__FILE__,__LINE__)
+#define CHECK() mwTest(__FILE__,__LINE__,MW_TEST_ALL)
+#define CHECK_THIS(n) mwTest(__FILE__,__LINE__,n)
+#define CHECK_BUFFER(b) mwTestBuffer(__FILE__,__LINE__,b)
+#define MARK(p) mwMark(p,#p,__FILE__,__LINE__)
+#define UNMARK(p) mwUnmark(p,__FILE__,__LINE__)
+
+#else /* MEMWATCH */
+
+#define mwASSERT(exp)
+#ifndef MW_NOASSERT
+#ifndef ASSERT
+#define ASSERT mwASSERT
+#endif /* !ASSERT */
+#endif /* !MW_NOASSERT */
+
+#define mwVERIFY(exp) exp
+#ifndef MW_NOVERIFY
+#ifndef VERIFY
+#define VERIFY mwVERIFY
+#endif /* !VERIFY */
+#endif /* !MW_NOVERIFY */
+
+/*lint -esym(773,mwTRACE) */
+#define mwTRACE /*lint -save -e506 */ 1?(void)0:mwDummyTraceFunction /*lint -restore */
+#ifndef MW_NOTRACE
+#ifndef TRACE
+/*lint -esym(773,TRACE) */
+#define TRACE mwTRACE
+#endif /* !TRACE */
+#endif /* !MW_NOTRACE */
+
+extern void mwDummyTraceFunction(const char *,...);
+/*lint -save -e652 */
+#define mwDoFlush(n)
+#define mwPuts(s)
+#define mwInit()
+#define mwGrab(n)
+#define mwDrop(n)
+#define mwLimit(n)
+#define mwTest(f,l)
+#define mwSetOutFunc(f)
+#define mwSetAriFunc(f)
+#define mwDefaultAri()
+#define mwNomansland()
+#define mwStatistics(f)
+#define mwMark(p,t,f,n) (p)
+#define mwUnmark(p,f,n) (p)
+#define mwMalloc(n,f,l) malloc(n)
+#define mwStrdup(p,f,l) strdup(p)
+#define mwRealloc(p,n,f,l) realloc(p,n)
+#define mwCalloc(n,m,f,l) calloc(n,m)
+#define mwFree(p) free(p)
+#define mwMalloc_(n) malloc(n)
+#define mwRealloc_(p,n) realloc(p,n)
+#define mwCalloc_(n,m) calloc(n,m)
+#define mwFree_(p) free(p)
+#define mwAssert(e,es,f,l)
+#define mwVerify(e,es,f,l) (e)
+#define mwTrace mwDummyTrace
+#define mwTestBuffer(f,l,b) (0)
+#define CHECK()
+#define CHECK_THIS(n)
+#define CHECK_BUFFER(b)
+#define MARK(p) (p)
+#define UNMARK(p) (p)
+/*lint -restore */
+
+#endif /* MEMWATCH */
+#endif /* !__MEMWATCH_C */
+
+#ifdef __cplusplus
+ }
+#endif
+
+#if 0 /* 980317: disabled C++ */
+
+/*
+** C++ support section
+** Implements the C++ support. Please note that in order to avoid
+** messing up library classes, C++ support is disabled by default.
+** You must NOT enable it until AFTER the inclusion of all header
+** files belonging to code that are not compiled with MEMWATCH, and
+** possibly for some that are! The reason for this is that a C++
+** class may implement it's own new() function, and the preprocessor
+** would substitute this crucial declaration for MEMWATCH new().
+** You can forcibly deny C++ support by defining MEMWATCH_NOCPP.
+** To enble C++ support, you must be compiling C++, MEMWATCH must
+** be defined, MEMWATCH_NOCPP must not be defined, and finally,
+** you must define 'new' to be 'mwNew', and 'delete' to be 'mwDelete'.
+** Unlike C, C++ code can begin executing *way* before main(), for
+** example if a global variable is created. For this reason, you can
+** declare a global variable of the class 'MemWatch'. If this is
+** is the first variable created, it will then check ALL C++ allocations
+** and deallocations. Unfortunately, this evaluation order is not
+** guaranteed by C++, though the compilers I've tried evaluates them
+** in the order encountered.
+*/
+#ifdef __cplusplus
+#ifndef __MEMWATCH_C
+#ifdef MEMWATCH
+#ifndef MEMWATCH_NOCPP
+extern int mwNCur;
+extern const char *mwNFile;
+extern int mwNLine;
+class MemWatch {
+public:
+ MemWatch();
+ ~MemWatch();
+ };
+void * operator new(size_t);
+void * operator new(size_t,const char *,int);
+void * operator new[] (size_t,const char *,int); // hjc 07/16/02
+void operator delete(void *);
+#define mwNew new(__FILE__,__LINE__)
+#define mwDelete (mwNCur=1,mwNFile=__FILE__,mwNLine=__LINE__),delete
+#endif /* MEMWATCH_NOCPP */
+#endif /* MEMWATCH */
+#endif /* !__MEMWATCH_C */
+#endif /* __cplusplus */
+
+#endif /* 980317: disabled C++ */
+
+#endif /* __MEMWATCH_H */
+
+/* EOF MEMWATCH.H */
Added: packages-wip/libxslt-ruby/trunk/examples/commentary.dtd
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/commentary.dtd 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/commentary.dtd 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,34 @@
+<!ELEMENT commentary (meta, body)>
+<!ELEMENT meta (author, version, date, id, title, subtitle?)>
+
+<!-- Metadata about the requirements -->
+<!ENTITY % string "#PCDATA">
+<!ENTITY % character "#PCDATA">
+<!ENTITY % letter "#PCDATA">
+<!ENTITY % number_att "CDATA">
+
+
+<!ELEMENT author (first_name, last_name, email)>
+
+<!ELEMENT first_name (%string;)>
+<!ELEMENT last_name (%string;)>
+<!ELEMENT email (%string;)>
+
+<!ELEMENT version (#PCDATA)>
+<!ELEMENT date (#PCDATA)>
+<!ELEMENT id (#PCDATA)>
+<!ELEMENT title (#PCDATA)>
+<!ELEMENT subtitle (#PCDATA)>
+
+<!ELEMENT body (para+)>
+
+
+<!ELEMENT para (#PCDATA|thought|url|ol)*>
+<!ATTLIST para
+ style (default|ps) "default">
+
+<!ELEMENT ol (li+)>
+<!ELEMENT li (#PCDATA)>
+<!ELEMENT url (#PCDATA)>
+<!ELEMENT thought (#PCDATA)>
+
Added: packages-wip/libxslt-ruby/trunk/examples/functions.xsl
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/functions.xsl 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/functions.xsl 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+
+<xsl:stylesheet
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:src="http://xml.apache.org/xindice/Query"
+ xmlns:ex="http://test.none"
+ xsl:version="1.0">
+<xsl:output
+ encoding="UTF-8"
+ indent="yes"
+ />
+
+<xsl:variable name="number" select="1"/>
+<xsl:variable name="string" select="'comment appelle-tu ça?'"/>
+<xsl:variable name="bool" select="true()"/>
+<xsl:variable name="nodes" select="nodes"/>
+
+<xsl:template match="/">
+ <table>
+ <tr><th>value-of</th><th>ex:type()</th><th>ex:round-trip()</th></tr>
+ <tr>
+ <td><xsl:value-of select="$nodes"/></td>
+ <td><xsl:value-of select="ex:type($nodes)"/></td>
+ <td><xsl:apply-templates select="ex:round-trip($nodes)"/></td>
+ </tr>
+ <xsl:call-template name="row">
+ <xsl:with-param name="value" select="$number"/>
+ </xsl:call-template>
+ <xsl:call-template name="row">
+ <xsl:with-param name="value" select="$string"/>
+ </xsl:call-template>
+ <xsl:call-template name="row">
+ <xsl:with-param name="value" select="$bool"/>
+ </xsl:call-template>
+ </table>
+</xsl:template>
+
+<xsl:template name="row">
+ <xsl:param name="value"/>
+ <tr>
+ <td><xsl:value-of select="$value"/></td>
+ <td><xsl:value-of select="ex:type($value)"/></td>
+ <td><xsl:value-of select="ex:round-trip($value)"/></td>
+ </tr>
+</xsl:template>
+
+<xsl:template match="node">
+ <xsl:value-of select="."/>(<xsl:value-of select="@number"/>)
+</xsl:template>
+
+</xsl:stylesheet>
Added: packages-wip/libxslt-ruby/trunk/examples/fuzface.rb
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/fuzface.rb 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/fuzface.rb 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,13 @@
+#!/usr/bin/ruby -w
+
+require '../xslt'
+
+xslt = XML::XSLT.new()
+xslt.xmlfile = "fuzface.xml"
+xslt.xslfile = "fuzface.xsl"
+
+out = xslt.serve()
+print out;
+
+out = xslt.serve()
+print out;
Added: packages-wip/libxslt-ruby/trunk/examples/fuzface.xml
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/fuzface.xml 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/fuzface.xml 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="fuzface.xsl" type="text/xsl"?>
+
+<!DOCTYPE commentary SYSTEM "commentary.dtd">
+
+<commentary>
+ <meta>
+ <author>
+ <first_name>Sean</first_name>
+ <last_name>Chittenden</last_name>
+ <email>sean at chittenden.org</email>
+ </author>
+ <version>$Version$</version>
+ <date>$Date: 2005/11/07 07:42:28 $</date>
+ <id>$Id: fuzface.xml,v 1.1 2005/11/07 07:42:28 greg Exp $</id>
+ <title>Fuzface...</title>
+ <subtitle>The Internet's a big place and here's some proof...</subtitle>
+ </meta>
+
+ <body>
+ <para>
+ I think it's a tragedy that I'm going to start off my new
+ commentary by talking about facial hair and the Internet.
+ Something about that just screams pathetic, but whatever: it's
+ humor and that's life.
+ </para>
+
+ <para>
+ I've been working at home for a while now, which has been great.
+ I've been doing a lot of reading, good work, contributing to the
+ FreeBSD project, and living life at my own pace. The problem?
+ I don't have to interact with people, so I've let my appearance
+ slide a bit, most notably I've gone two weeks without shaving
+ and I have an awful hairy face.
+ </para>
+
+ <para>
+ Nothing is worse than going for a hard run, coming back, and
+ then bending your head down so that the hairs under your chin
+ touch the hairs on your neck. This has to be one of the most
+ disgusting/gross feelings I've experienced in a while. While
+ today wasn't the first time I'd experienced such a slimy tangled
+ mess, it is the first time I seriously considered shaving part
+ of my face, but not all of it: I was considering a beard.
+ </para>
+
+ <para>
+ Alright, so it's 5pm and I'm a sweaty post-run mess (it was 110
+ degrees in direct sunlight according to my thermometer) and
+ considering the possibility of growing a beard. Swifty nift?
+ Maybe. This is something I'd never done before, let alone
+ seriously consider. Normally I'd call my dad for such manly
+ advice, but he is: a) normally in another state, and; b) in
+ another country right now probably growing a beard (he's
+ notorious for coming back from a trip with a gnarly unshaven
+ face, sometimes he'll shape it into a decent beard). So, what's
+ a tech-junkie to do? Hop on the Internet and see if Google's
+ able to provide me with some inspiration.
+ </para>
+
+ <para>
+ Sure enough, I typed in "pictures of bearded men" and I was able
+ to find something: 14,000 pages of something to be exact.
+ Anyway, so most of these were rinky dink sites, a few of them
+ had some promise. One guy was trying to start a tradition where
+ everyone grows a beard for New Years. As I was scrolling down
+ the page trying to find some pictures, my mind was having the
+ following thought process: <thought>This seems like a dumb
+ idea... New Years provides a perfectly good excuse to kiss some
+ total stranger that you've had your eye on for the duration of a
+ New Years party. Why waste such an opportunity with a crappy
+ kiss?</thought> And at about this point I said this page sucks,
+ and flipped back to my search results.
+ </para>
+
+ <para>
+ Since I'd never done this before, I didn't know what was
+ fashionably correct in terms of where a guy should shave under
+ his neck, or what the deal was... I knew there were lots of
+ styles out there, just none that I could picture in my mind
+ (save maybe Santa Claus and a few really gnarly beards that are
+ long enough to be used as full-body covering. Oooh! And don't
+ forget the Russian and Amish beards, those stand out in my mind
+ too.). Google, being pretty comprehensive, and the Internet
+ being huge, found the exact screwball page I was looking for:
+ <url>http://fuzface-gallery.tripod.com/</url>
+ </para>
+
+ <para>
+ I don't know if I really should be amazed at the sheer number of
+ entries that Google returned, or that the Internet is big enough
+ to house such random gallery of crap, but it is and it never
+ ceases to amaze me... it's almost as amazing as the fact that
+ some bozo spent the time to create such a page. Don't people
+ have lives? Oh wait, I just visited his page... so back to my
+ diatribe...
+ </para>
+
+ <para>
+ There were tons of faces, lots of men, lots of hair, and plenty
+ of styles to choose from. Page after page of faces and hair.
+ Ugh. This wasn't getting any where and I was now entertaining
+ the rebound though of shaving my head. Time to close my browser
+ and hop in the shower: I reak. So what'd I do? Well, after
+ looking through enough of those pictures, I decided a few
+ things:
+ </para>
+
+ <para>
+ <ol>
+ <li>
+ I'm amazed that the Internet is big enough to foster the
+ creation of such random and utterly useless information. Then
+ again, I've been on and using the Net since '95, so this
+ shouldn't surprise me that much.
+ </li>
+
+ <li>
+ There are a lot of guys out there with varying tastes in,
+ shall we say, "facial hair styles," most of which I find
+ pretty unappealing.
+ </li>
+
+ <li>
+ I don't like beards. After one clogged drain, two
+ reapplications of shaving cream, and a few pases with the
+ razor, it took me about 5-10 minutes to get a nice cleanly
+ shaven face.
+ </li>
+
+ <li>
+ <crass comment>And - back me up here fellas, you can
+ sympathize with this feeling after you get done looking
+ through a magazine for a hair-cut style (ladies.. just smile
+ and nod and pretend you care) - after looking at a few dozen
+ pictures of men, I was able to safely reaffirm my desire for
+ heterosexual relations (translation from Bill Clintonese: have
+ sex with a woman). And with that thought in mind, I began to
+ pine for the college porn collection of old. Mmmm,
+ Playboy.</crass comment>
+ </li>
+ </ol>
+ </para>
+
+ <para>
+ ::grin:: Until next time. -Sean
+ </para>
+
+ <para style="ps">
+ P.S. To the guys out there with beards, this is just my
+ opinion: take it with a grain of salt.
+ </para>
+ </body>
+</commentary>
Added: packages-wip/libxslt-ruby/trunk/examples/fuzface.xsl
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/fuzface.xsl 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/fuzface.xsl 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:include href="ramblings.xsl" />
+</xsl:stylesheet>
Added: packages-wip/libxslt-ruby/trunk/examples/fuzface_REXML.rb
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/fuzface_REXML.rb 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/fuzface_REXML.rb 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,11 @@
+#!/usr/bin/ruby -w
+require 'rexml/document'
+require '../xslt'
+
+xslt = XML::XSLT.new()
+
+xslt.xml = REXML::Document.new File.open( "fuzface.xml" )
+xslt.xsl = REXML::Document.new File.open( "fuzface.xsl" )
+
+out = xslt.serve()
+puts out
\ No newline at end of file
Added: packages-wip/libxslt-ruby/trunk/examples/fuzface_XML-Simple.rb
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/fuzface_XML-Simple.rb 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/fuzface_XML-Simple.rb 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,12 @@
+#!/usr/bin/ruby -w
+
+require 'xml/smart'
+require '../xslt'
+
+xslt = XML::XSLT.new()
+
+xslt.xml = XML::Smart.open( "fuzface.xml" )
+xslt.xsl = XML::Smart.open( "fuzface.xsl" )
+
+out = xslt.serve()
+puts out
Added: packages-wip/libxslt-ruby/trunk/examples/fuzface_data.rb
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/fuzface_data.rb 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/fuzface_data.rb 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,13 @@
+#!/usr/bin/ruby -w
+
+require '../xslt'
+
+xslt = XML::XSLT.new()
+xslt.xml = IO::readlines( "fuzface.xml" ).join
+xslt.xsl = IO::readlines( "fuzface.xsl" ).join
+
+out = xslt.serve()
+print out;
+
+out = xslt.serve()
+print out;
Added: packages-wip/libxslt-ruby/trunk/examples/fuzface_error.rb
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/fuzface_error.rb 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/fuzface_error.rb 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,86 @@
+#!/usr/bin/ruby -w
+
+require '../xslt'
+
+xslt = XML::XSLT.new()
+
+print "\n-------------------------------------------------\n"
+print "ERROR #1 : XML XSL inverse\n"
+begin
+xslt.xsl = IO::readlines( "fuzface.xml" ).join( )
+rescue => e
+ print "Error trapped by ", e.class, " : ", e.message, "\n"
+ p XML::XSLT::errors
+end
+
+begin
+ xslt.xml = IO::readlines( "fuzface.xsl" ).join( )
+rescue => e
+ print "Error trapped by ", e.class, " : ", e.message, "\n"
+ p XML::XSLT::errors
+end
+
+begin
+ out = xslt.serve()
+rescue => e
+ print "Error trapped by ", e.class, " : ", e.message, "\n"
+ p XML::XSLT::errors
+end
+
+print "\n-------------------------------------------------\n"
+print "ERROR #2 : XSL error\n"
+begin
+ xslt.xml = IO::readlines( "fuzface.xml" ).join( )
+rescue => e
+ print "Error trapped by ", e.class, " : ", e.message, "\n"
+ p XML::XSLT::errors
+end
+
+begin
+ xslt.xsl = "totototototot"
+rescue => e
+ print "Error trapped by ", e.class, " : ", e.message, "\n"
+ p XML::XSLT::errors
+end
+
+begin
+ out = xslt.serve()
+rescue => e
+ print "Error trapped by ", e.class, " : ", e.message, "\n"
+ p XML::XSLT::errors
+end
+
+print "\n-------------------------------------------------\n"
+print "ERROR #3 : XML error\n"
+begin
+ xslt.xml = "totototototot"
+rescue => e
+ print "Error trapped by ", e.class, " : ", e.message, "\n"
+ p XML::XSLT::errors
+end
+
+begin
+ xslt.xsl = IO::readlines( "fuzface.xsl" ).join( )
+rescue => e
+ print "Error trapped by ", e.class, " : ", e.message, "\n"
+ p XML::XSLT::errors
+end
+
+begin
+ out = xslt.serve()
+rescue => e
+ print "Error trapped by ", e.class, " : ", e.message, "\n"
+ p XML::XSLT::errors
+end
+
+print "\n-------------------------------------------------\n"
+print "SUCCESS !\n"
+xslt.xml = IO::readlines( "fuzface.xml" ).join( )
+xslt.xsl = IO::readlines( "fuzface.xsl" ).join( )
+begin
+ out = xslt.serve()
+rescue => e
+ print "Error trapped by ", e.class, " : ", e.message, "\n"
+ p XML::XSLT::errors
+end
+
Added: packages-wip/libxslt-ruby/trunk/examples/fuzface_to_s.rb
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/fuzface_to_s.rb 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/fuzface_to_s.rb 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,9 @@
+#!/usr/bin/ruby -w
+
+require '../xslt'
+
+xslt = XML::XSLT.new()
+xslt.xsl = "fuzface.xsl"
+
+print xslt.xsl_to_s;
+puts
Added: packages-wip/libxslt-ruby/trunk/examples/info.rb
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/info.rb 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/info.rb 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,19 @@
+#!/usr/bin/ruby
+require "../xslt"
+
+print "MAX_DEPTH = ", XML::XSLT::MAX_DEPTH, "\n"
+print "MAX_SORT = ", XML::XSLT::MAX_SORT, "\n"
+print "ENGINE_VERSION = ", XML::XSLT::ENGINE_VERSION, "\n"
+print "LIBXSLT_VERSION = ", XML::XSLT::LIBXSLT_VERSION, "\n"
+print "LIBXML_VERSION = ", XML::XSLT::LIBXML_VERSION, "\n"
+print "XSLT_NAMESPACE = ", XML::XSLT::XSLT_NAMESPACE, "\n"
+print "DEFAULT_VENDOR = ", XML::XSLT::DEFAULT_VENDOR, "\n"
+print "DEFAULT_VERSION = ", XML::XSLT::DEFAULT_VERSION, "\n"
+print "DEFAULT_URL = ", XML::XSLT::DEFAULT_URL, "\n"
+print "NAMESPACE_LIBXSLT = ", XML::XSLT::NAMESPACE_LIBXSLT, "\n"
+print "NAMESPACE_NORM_SAXON = ", XML::XSLT::NAMESPACE_NORM_SAXON, "\n"
+print "NAMESPACE_SAXON = ", XML::XSLT::NAMESPACE_SAXON, "\n"
+print "NAMESPACE_XT = ", XML::XSLT::NAMESPACE_XT, "\n"
+print "NAMESPACE_XALAN = ", XML::XSLT::NAMESPACE_XALAN, "\n"
+
+print "RUBY_XSLT_VERSION = ", XML::XSLT::RUBY_XSLT_VERSION, "\n"
Added: packages-wip/libxslt-ruby/trunk/examples/ramblings.xsl
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/ramblings.xsl 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/ramblings.xsl 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,46 @@
+<?xml version="1.0" ?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:template match="/">
+ <xsl:element name="html">
+ <xsl:element name="head">
+ <xsl:element name="title">Ramblings - <xsl:value-of select="commentary/meta/title" /> - <xsl:value-of select="commentary/meta/subtitle" /></xsl:element>
+ </xsl:element>
+
+ <xsl:element name="body">
+ <xsl:element name="h1"><xsl:value-of select="commentary/meta/title" /></xsl:element>
+ <xsl:element name="h3"><xsl:value-of select="commentary/meta/subtitle" /></xsl:element>
+ By: <xsl:value-of select="commentary/meta/author/first_name" /> <xsl:value-of select="commentary/meta/author/last_name" /><xsl:element name="br" />
+ Date: <xsl:value-of select="commentary/meta/date" /><xsl:element name="br" />
+
+ <xsl:for-each select="./commentary/body">
+ <xsl:apply-templates />
+ </xsl:for-each>
+
+ </xsl:element>
+ </xsl:element>
+</xsl:template>
+
+<xsl:template match="para">
+ <xsl:element name="p">
+ <xsl:apply-templates />
+ </xsl:element>
+</xsl:template>
+
+<xsl:template match="ol">
+ <xsl:element name="ol">
+ <xsl:apply-templates select="li" />
+ </xsl:element>
+</xsl:template>
+
+<xsl:template match="li">
+ <xsl:element name="li">
+ <xsl:value-of select="." />
+ </xsl:element>
+</xsl:template>
+
+<xsl:template match="thought">
+ <xsl:element name="i">
+ <xsl:value-of select="." />
+ </xsl:element>
+</xsl:template>
+</xsl:stylesheet>
Added: packages-wip/libxslt-ruby/trunk/examples/test.xml
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/test.xml 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/test.xml 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
+<nodes>
+ <node number="1">Hello, </node>
+ <node number="2">World!</node>
+</nodes>
Added: packages-wip/libxslt-ruby/trunk/examples/test.xsl
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/test.xsl 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/test.xsl 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="text" encoding="iso-8859-1" indent="no"/>
+<xsl:param name="p1"/>
+<xsl:param name="p2"/>
+
+<xsl:template match="/">
+ p1:<xsl:value-of select="$p1"/>
+ p2:<xsl:value-of select="$p2"/>
+ <xsl:apply-templates/>
+</xsl:template>
+
+<xsl:template match="node">
+ <xsl:value-of select="."/>(<xsl:value-of select="@number"/>)
+</xsl:template>
+
+</xsl:stylesheet>
+
Added: packages-wip/libxslt-ruby/trunk/examples/test_functions.rb
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/test_functions.rb 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/test_functions.rb 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,18 @@
+require "../xslt"
+
+class XML::XSLT
+ def round_trip( arg )
+ arg
+ end
+ def type( arg )
+ arg.class.to_s
+ end
+end
+
+xslt = XML::XSLT.new()
+xslt.xsl = "functions.xsl"
+xslt.xml = "test.xml"
+XML::XSLT.extFunction("round-trip", "http://test.none", xslt)
+XML::XSLT.extFunction("type", "http://test.none", xslt)
+
+puts xslt.serve
Added: packages-wip/libxslt-ruby/trunk/examples/test_parameters.rb
===================================================================
--- packages-wip/libxslt-ruby/trunk/examples/test_parameters.rb 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/examples/test_parameters.rb 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,13 @@
+require "../xslt"
+
+xslt = XML::XSLT.new()
+xslt.xsl = "test.xsl"
+xslt.xml = "test.xml"
+xslt.parameters = { "p1" => "the first parameter ...",
+ "p2" => "'and the second one!'" }
+#xslt.save("test.html")
+puts xslt.serve
+xslt.parameters = { "p1" => "Ruby...",
+ "p2" => "'...is cool !'" }
+#xslt.save("test.html")
+puts xslt.serve
Added: packages-wip/libxslt-ruby/trunk/extconf.rb
===================================================================
--- packages-wip/libxslt-ruby/trunk/extconf.rb 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/extconf.rb 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,114 @@
+#!/usr/bin/ruby -w
+# See the LICENSE file for copyright and distribution information
+
+require "mkmf"
+
+def help
+ print <<HELP
+"extconf.rb" configures this package to adapt to many kinds of systems.
+
+Usage: ruby extconf.rb [OPTION]...
+
+Configuration:
+ --help display this help and exit
+
+ --with-xslt-lib=PATH
+ --with-xslt-include=PATH
+ --with-xslt-dir=PATH specify the directory name for the libxslt include
+ files and/or library
+
+ --enable-error-handler enables a VERY crude error handler. Error messages
+ are appended to the class variable XML::XSLT and can
+ be accessed with the class method XML::XSLT.errors
+ (will change in a future version)
+ --disable-exslt disables libexslt support <http://exslt.org/>
+
+ --enable-debug compile with memwatch
+ <http://www.linkdata.se/sourcecode.html>
+
+HELP
+end
+
+if ARGV.include?( "--help" )
+ help()
+ exit 0
+end
+
+if enable_config("debug", false)
+ File.symlink( "debug/memwatch.h", "memwatch.h" ) if( ! File.exist?("memwatch.h") )
+ File.symlink( "debug/memwatch.c", "memwatch.c" ) if( ! File.exist?("memwatch.c") )
+ $CFLAGS += " -DMEMWATCH -D__DEBUG__"
+end
+
+if enable_config("error-handler", false)
+ $CFLAGS += " -DUSE_ERROR_HANDLER"
+end
+
+$LIBPATH.push(Config::CONFIG['libdir'])
+
+def crash(str)
+ printf(" extconf failure: %s\n", str)
+ exit 1
+end
+
+#unless have_library("z", "inflate")
+# crash("need zlib")
+#else
+# $defs.push('-DHAVE_ZLIB_H')
+#end
+
+if dir_config( "xslt" ) != [nil, nil]
+ inc, lib = dir_config( 'xslt' )
+ $LDFLAGS << " -L#{lib} -lxslt -lxml2 -lz -lpthread -liconv -lm"
+ $CFLAGS << " -I#{inc}"
+elsif ex = find_executable( "xslt-config" )
+ $LDFLAGS << ' ' + `#{ex} --libs`.chomp
+ $CFLAGS << ' ' + `#{ex} --cflags`.chomp
+else
+ crash(<<EOL)
+need libxslt.
+
+ Install the library or try one of the following options to extconf.rb:
+
+ --with-xslt-lib=/path/to/libxslt/lib
+ --with-xslt-include=/path/to/libxslt/include
+EOL
+end
+
+if enable_config("exslt", true)
+ $LDFLAGS << " -lexslt"
+ $CFLAGS += " -DUSE_EXSLT"
+end
+
+$CFLAGS = '-g -Wall ' + $CFLAGS
+
+puts "compile with : "
+puts " CFLAGS = #{$CFLAGS}"
+puts " LDFLAGS = #{$LDFLAGS}"
+puts
+
+create_header()
+create_makefile("xml/xslt")
+
+###### Modify Makefile: #######
+File.rename( "Makefile", "Makefile.orig" )
+oldmkfl = File.open( "Makefile.orig" )
+newmkfl = File.open( "Makefile", "w" )
+oldmkfl.each_line{ |line|
+ case(line)
+ when /^all:/
+ newmkfl.puts(line)
+ newmkfl.puts("")
+ newmkfl.puts("test: all") # insert the "test" target
+ newmkfl.puts("\t\t at cd tests && ruby test.rb && cd ..")
+ newmkfl.puts("doc: all") # insert the "doc" target
+ newmkfl.puts("\t\t at rdoc -S -t \"Ruby/XSLT Documentation\" README AUTHORS ChangeLog xslt.c")
+ when /^distclean:/
+ newmkfl.puts(line)
+ newmkfl.puts("\t\t at -$(RM) memwatch.h memwatch.c Makefile.orig")
+ newmkfl.puts("\t\t at -$(RM)r doc")
+ else
+ newmkfl.puts(line)
+ end
+}
+newmkfl.close
Property changes on: packages-wip/libxslt-ruby/trunk/extconf.rb
___________________________________________________________________
Name: svn:executable
+
Added: packages-wip/libxslt-ruby/trunk/extfunc.c
===================================================================
--- packages-wip/libxslt-ruby/trunk/extfunc.c 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/extfunc.c 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,216 @@
+/**
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune at free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "xslt.h"
+
+extern VALUE mXML;
+extern VALUE cXSLT;
+
+/**
+ * external function support, patch from :
+ *
+ * Brendan Taylor
+ * whateley at gmail.com
+ *
+ */
+
+
+/* converts an xmlXPathObjectPtr to a Ruby VALUE
+ * number -> float
+ * boolean -> boolean
+ * string -> string
+ * nodeset -> an array of REXML::Elements
+ */
+VALUE xpathObj2value(xmlXPathObjectPtr obj, xmlDocPtr doc)
+{
+ VALUE ret = Qnil;
+
+ if (obj == NULL) {
+ return ret;
+ }
+
+ switch (obj->type) {
+ case XPATH_NODESET:
+ rb_require("rexml/document");
+ ret = rb_ary_new();
+
+ if ((obj->nodesetval != NULL) && (obj->nodesetval->nodeNr != 0)) {
+ xmlBufferPtr buff = xmlBufferCreate();
+ xmlNodePtr node;
+ int i;
+
+ // this assumes all the nodes are elements, which is a bad idea
+ for (i = 0; i < obj->nodesetval->nodeNr; i++) {
+ node = obj->nodesetval->nodeTab[i];
+
+ if( node->type == XML_ELEMENT_NODE ) {
+ xmlNodeDump(buff, doc, node, 0, 0);
+
+ VALUE cREXML = rb_const_get(rb_cObject, rb_intern("REXML"));
+ VALUE cDocument = rb_const_get(cREXML, rb_intern("Document"));
+ VALUE rDocument = rb_funcall(cDocument, rb_intern("new"), 1,rb_str_new2((char *)buff->content));
+ VALUE rElement = rb_funcall(rDocument, rb_intern("root"), 0);
+
+ rb_ary_push(ret, rElement);
+
+ // empty the buffer (xmlNodeDump appends rather than replaces)
+ xmlBufferEmpty(buff);
+ } else if ( node->type == XML_TEXT_NODE ) {
+ rb_ary_push(ret, rb_str_new2((char *)node->content));
+ }
+ }
+ xmlBufferFree(buff);
+ }
+ break;
+ case XPATH_BOOLEAN:
+ ret = obj->boolval ? Qtrue : Qfalse;
+ break;
+ case XPATH_NUMBER:
+ ret = rb_float_new(obj->floatval);
+ break;
+ case XPATH_STRING:
+ ret = rb_str_new2((char *) obj->stringval);
+ break;
+ /* these cases were in libxslt's python bindings, but i don't know what they are, so i'll leave them alone */
+ case XPATH_XSLT_TREE:
+ case XPATH_POINT:
+ case XPATH_RANGE:
+ case XPATH_LOCATIONSET:
+ default:
+ rb_warning("xpathObj2value: can't convert XPath object type %d to Ruby object\n", obj->type );
+ }
+ xmlXPathFreeObject(obj);
+ return ret;
+}
+
+/*
+ * converts a Ruby VALUE to an xmlXPathObjectPtr
+ * boolean -> boolean
+ * number -> number
+ * string -> escaped string
+ * array -> array of parsed nodes
+ */
+xmlXPathObjectPtr value2xpathObj (VALUE val) {
+ xmlXPathObjectPtr ret = NULL;
+
+ switch (TYPE(val)) {
+ case T_TRUE:
+ case T_FALSE:
+ ret = xmlXPathNewBoolean(RTEST(val));
+ break;
+ case T_FIXNUM:
+ case T_FLOAT:
+ ret = xmlXPathNewFloat(NUM2DBL(val));
+ break;
+ case T_STRING:
+ {
+ xmlChar *str;
+
+ // we need the Strdup (this is the major bugfix for 0.8.1)
+ str = xmlStrdup((const xmlChar *) STR2CSTR(val));
+ ret = xmlXPathWrapString(str);
+ }
+ break;
+ case T_NIL:
+ ret = xmlXPathNewNodeSet(NULL);
+ break;
+ case T_ARRAY: {
+ int i,j;
+ ret = xmlXPathNewNodeSet(NULL);
+
+ for(i = RARRAY(val)->len; i > 0; i--) {
+ xmlXPathObjectPtr obj = value2xpathObj( rb_ary_shift( val ) );
+ if ((obj->nodesetval != NULL) && (obj->nodesetval->nodeNr != 0)) {
+ for(j = 0; j < obj->nodesetval->nodeNr; j++) {
+ xmlXPathNodeSetAdd( ret->nodesetval, obj->nodesetval->nodeTab[j] );
+ }
+ }
+ }
+ break; }
+ case T_DATA:
+ case T_OBJECT: {
+ if( strcmp( getRubyObjectName( val ), "REXML::Document" ) == 0 || strcmp(getRubyObjectName( val ), "REXML::Element") == 0 ) {
+
+ VALUE to_s = rb_funcall( val, rb_intern( "to_s" ), 0 );
+ xmlDocPtr doc = xmlParseDoc((xmlChar *) STR2CSTR(to_s));
+
+ ret = xmlXPathNewNodeSet((xmlNode *)doc->children);
+ break;
+ } else if( strcmp( getRubyObjectName( val ), "REXML::Text" ) == 0 ) {
+ VALUE to_s = rb_funcall( val, rb_intern( "to_s" ), 0 );
+
+ xmlChar *str;
+
+ str = xmlStrdup((const xmlChar *) STR2CSTR(to_s));
+ ret = xmlXPathWrapString(str);
+ break;
+ }
+ // this drops through so i can reuse the error message
+ }
+ default:
+ rb_warning( "value2xpathObj: can't convert class %s to XPath object\n", getRubyObjectName(val));
+ return NULL;
+ }
+
+ return ret;
+}
+
+/*
+ * chooses what registered function to call and calls it
+ */
+void xmlXPathFuncCallback( xmlXPathParserContextPtr ctxt, int nargs) {
+ VALUE result, arguments[nargs];
+ VALUE ns_hash, func_hash, object;
+ const xmlChar *namespace;
+ char *rb_func, *chr;
+ xmlXPathObjectPtr obj;
+ int i;
+
+ if (ctxt == NULL || ctxt->context == NULL)
+ return;
+
+ rb_func = strdup((char *)ctxt->context->function);
+ namespace = ctxt->context->functionURI;
+
+ ns_hash = rb_cvar_get(cXSLT, rb_intern("@@extFunctions"));
+
+ func_hash = rb_hash_aref(ns_hash, rb_str_new2((char *)namespace));
+
+ if(func_hash == Qnil) {
+ rb_warning( "xmlXPathFuncCallback: namespace %s not found!\n", namespace );
+ }
+
+ object = rb_hash_aref(func_hash, rb_str_new2((char *)rb_func));
+
+ for (i = nargs - 1; i >= 0; i--) {
+ obj = valuePop(ctxt);
+ arguments[i] = xpathObj2value(obj, ctxt->context->doc);
+ }
+
+ /* -s are common in XSLT function names, but illegal for Ruby method names */
+ while( (chr = strchr(rb_func, '-')) != NULL ) {
+ chr[0] = '_'; /* so we pretend the - was a _ all along */
+ }
+
+ result = rb_funcall2( object, rb_intern(rb_func), nargs, arguments);
+
+ free( rb_func );
+
+ obj = value2xpathObj(result);
+ valuePush(ctxt, obj);
+}
Added: packages-wip/libxslt-ruby/trunk/extfunc.h
===================================================================
--- packages-wip/libxslt-ruby/trunk/extfunc.h 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/extfunc.h 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,26 @@
+/**
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune at free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "xslt.h"
+
+#include <libxml/xpathInternals.h>
+#include <libxslt/extensions.h>
+
+VALUE xpathObj2value( xmlXPathObjectPtr, xmlDocPtr );
+xmlXPathObjectPtr value2xpathObj( VALUE );
+void xmlXPathFuncCallback( xmlXPathParserContextPtr, int );
Added: packages-wip/libxslt-ruby/trunk/parameters.c
===================================================================
--- packages-wip/libxslt-ruby/trunk/parameters.c 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/parameters.c 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune at free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "xslt.h"
+
+/**
+ * parameters support, patch from :
+ *
+ * Eustáquio "TaQ" Rangel
+ * eustaquiorangel at yahoo.com
+ * http://beam.to/taq
+ *
+ */
+VALUE each_pair( VALUE obj ) {
+ return rb_funcall( obj, rb_intern("each"), 0, 0 );
+}
+
+VALUE process_pair( VALUE pair, VALUE rbparams ) {
+ VALUE key, value;
+ // Thx to alex__
+ int count = FIX2INT( rb_funcall( rbparams, rb_intern("size"), 0, 0 ) );
+ // static int count = 0;
+ char *xValue = NULL;
+
+ Check_Type( pair, T_ARRAY );
+
+ key = RARRAY(pair)->ptr[0];
+ value = RARRAY(pair)->ptr[1];
+
+ Check_Type( key, T_STRING );
+ Check_Type( value, T_STRING );
+
+ xValue = STR2CSTR( value );
+ if( xValue[0] != '\'' && xValue[strlen( xValue ) - 1] != '\'' ) {
+ value = rb_str_concat( value, rb_str_new2( "'" ) );
+ value = rb_str_concat( rb_str_new2( "'" ), value );
+ }
+
+ rb_ary_store( rbparams, count, key );
+ rb_ary_store( rbparams, count + 1, value );
+
+ count += 2;
+ return Qnil;
+}
Added: packages-wip/libxslt-ruby/trunk/parameters.h
===================================================================
--- packages-wip/libxslt-ruby/trunk/parameters.h 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/parameters.h 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,20 @@
+/**
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune at free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+VALUE each_pair( VALUE );
+VALUE process_pair( VALUE, VALUE );
Added: packages-wip/libxslt-ruby/trunk/parser.c
===================================================================
--- packages-wip/libxslt-ruby/trunk/parser.c 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/parser.c 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,228 @@
+/**
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune at free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "xslt.h"
+#include "parser.h"
+
+extern VALUE cXSLT;
+
+xmlDocPtr parse_xml( char* xml, int iXmlType ) {
+ xmlDocPtr tXMLDocument = NULL;
+
+#ifdef USE_ERROR_HANDLER
+ VALUE error_arr = rb_cvar_get(cXSLT, rb_intern("@@errors"));
+ int iInitialNumberOfErrors = RARRAY(error_arr)->len;
+#endif
+
+ /** Act: Parse XML */
+ if( iXmlType == RUBY_XSLT_XMLSRC_TYPE_STR ) {
+ tXMLDocument = xmlParseMemory( xml, strlen( xml ) );
+ } else if( iXmlType == RUBY_XSLT_XMLSRC_TYPE_FILE ) {
+ tXMLDocument = xmlParseFile( xml );
+ }
+
+ if( tXMLDocument == NULL ) {
+ rb_raise( eXSLTParsingError, "XML parsing error" );
+ return( NULL );
+ }
+
+#ifdef USE_ERROR_HANDLER
+ if(RARRAY(error_arr)->len > iInitialNumberOfErrors) {
+ rb_raise( eXSLTTransformationError, "Stylesheet transformation error" );
+ }
+#endif
+
+ return( tXMLDocument );
+}
+
+xsltStylesheetPtr parse_xsl( char* xsl, int iXslType ) {
+ xsltStylesheetPtr tParsedXslt = NULL;
+ xmlDocPtr tXSLDocument = NULL;
+
+ /** Rem: For encoding */
+ xmlCharEncodingHandlerPtr encoder = NULL;
+ const xmlChar *encoding = NULL;
+
+#ifdef USE_ERROR_HANDLER
+ VALUE error_arr = rb_cvar_get(cXSLT, rb_intern("@@errors"));
+ int iInitialNumberOfErrors = RARRAY(error_arr)->len;
+#endif
+
+ /** Act: Encoding support */
+ xmlInitCharEncodingHandlers( );
+
+ /** Act: Parse XSL */
+ if( iXslType == RUBY_XSLT_XSLSRC_TYPE_STR ) {
+ tXSLDocument = xmlParseMemory( xsl, strlen( xsl ) );
+ if( tXSLDocument == NULL ) {
+ rb_raise( eXSLTParsingError, "XSL parsing error" );
+ return( NULL );
+ }
+
+ tParsedXslt = xsltParseStylesheetDoc( tXSLDocument );
+ } else if( iXslType == RUBY_XSLT_XSLSRC_TYPE_FILE ) {
+ tParsedXslt = xsltParseStylesheetFile( BAD_CAST xsl );
+ }
+
+ if( tParsedXslt == NULL ) {
+ rb_raise( eXSLTParsingError, "XSL Stylesheet parsing error" );
+ return( NULL );
+ }
+
+ /** Act: Get encoding */
+ XSLT_GET_IMPORT_PTR( encoding, tParsedXslt, encoding )
+ encoder = xmlFindCharEncodingHandler((char *)encoding);
+
+ if( encoding != NULL ) {
+ encoder = xmlFindCharEncodingHandler((char *)encoding);
+ if( (encoder != NULL) && (xmlStrEqual((const xmlChar *)encoder->name, (const xmlChar *) "UTF-8")) ) {
+ encoder = NULL;
+ }
+ }
+
+#ifdef USE_ERROR_HANDLER
+ if(RARRAY(error_arr)->len > iInitialNumberOfErrors) {
+ rb_raise( eXSLTTransformationError, "Stylesheet transformation error" );
+ }
+#endif
+
+ return( tParsedXslt );
+}
+
+/**
+ * xOut = parser( char *xml, int iXmlType, char *xslt, int iXslType, char **pxParams );
+ */
+char* parse( xsltStylesheetPtr tParsedXslt, xmlDocPtr tXMLDocument, char **pxParams ) {
+ xmlDocPtr tXMLDocumentResult = NULL;
+ int iXMLDocumentResult;
+ xmlChar *tXMLDocumentResultString;
+ int tXMLDocumentResultLenght;
+
+#ifdef USE_ERROR_HANDLER
+ VALUE error_arr = rb_cvar_get(cXSLT, rb_intern("@@errors"));
+ int iInitialNumberOfErrors = RARRAY(error_arr)->len;
+#endif
+
+ tXMLDocumentResult = xsltApplyStylesheet( tParsedXslt, tXMLDocument, (const char**) pxParams );
+ if( tXMLDocumentResult == NULL ) {
+ rb_raise( eXSLTTransformationError, "Stylesheet transformation error" );
+ return( NULL );
+ }
+
+ iXMLDocumentResult = xsltSaveResultToString( &tXMLDocumentResultString, &tXMLDocumentResultLenght, tXMLDocumentResult, tParsedXslt );
+
+ xmlFreeDoc(tXMLDocumentResult);
+
+#ifdef USE_ERROR_HANDLER
+ if(RARRAY(error_arr)->len > iInitialNumberOfErrors) {
+ rb_raise( eXSLTTransformationError, "Stylesheet transformation error" );
+ }
+#endif
+
+ return((char*)tXMLDocumentResultString);
+}
+
+/**
+ * vOut = object_to_string( VALUE object );
+ */
+VALUE object_to_string( VALUE object ) {
+ VALUE vOut = Qnil;
+
+ switch( TYPE( object ) ) {
+ case T_STRING:
+ {
+ if( isFile( STR2CSTR( object ) ) == 0 ) {
+ vOut = object;
+ } else {
+ long iBufferLength;
+ long iCpt;
+ char *xBuffer;
+
+ FILE* fStream = fopen( STR2CSTR( object ), "r" );
+ if( fStream == NULL ) {
+ return( Qnil );
+ }
+
+ fseek( fStream, 0L, 2 );
+ iBufferLength = ftell( fStream );
+ xBuffer = (char *)malloc( (int)iBufferLength + 1 );
+ if( !xBuffer )
+ rb_raise( rb_eNoMemError, "Memory allocation error" );
+
+ xBuffer[iBufferLength] = 0;
+ fseek( fStream, 0L, 0 );
+ iCpt = fread( xBuffer, 1, (int)iBufferLength, fStream );
+
+ if( iCpt != iBufferLength ) {
+ free( (char *)xBuffer );
+ rb_raise( rb_eSystemCallError, "Read file error" );
+ }
+
+ vOut = rb_str_new2( xBuffer );
+ free( xBuffer );
+
+ fclose( fStream );
+ }
+ }
+ break;
+
+ case T_DATA:
+ case T_OBJECT:
+ {
+ if( strcmp( getRubyObjectName( object ), "XML::Smart::Dom" ) == 0 ||
+ strcmp( getRubyObjectName( object ), "XML::Simple::Dom" ) == 0 ) {
+ vOut = rb_funcall( object, rb_intern( "to_s" ), 0 );
+ } else if ( strcmp( getRubyObjectName( object ), "REXML::Document" ) == 0 ) {
+ vOut = rb_funcall( object, rb_intern( "to_s" ), 0 );
+ } else {
+ rb_raise( rb_eSystemCallError, "Can't read XML from object %s", getRubyObjectName( object ) );
+ }
+ }
+ break;
+
+ default:
+ rb_raise( rb_eArgError, "XML object #0x%x not supported", TYPE( object ) );
+ }
+
+ return( vOut );
+}
+
+/**
+ * bOut = objectIsFile( VALUE object );
+ */
+int objectIsFile( VALUE object ) {
+ int bOut = 0;
+
+ switch( TYPE( object ) ) {
+ case T_STRING:
+ {
+ if( isFile( STR2CSTR( object ) ) == 0 )
+ bOut = 0;
+ else
+ bOut = 1;
+ }
+ break;
+
+ case T_DATA:
+ case T_OBJECT:
+ default:
+ bOut = 0;
+ }
+
+ return( bOut );
+}
Added: packages-wip/libxslt-ruby/trunk/parser.h
===================================================================
--- packages-wip/libxslt-ruby/trunk/parser.h 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/parser.h 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune at free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __RUBY_XSLT_PARSER_H__
+#define __RUBY_XSLT_PARSER_H__
+extern int xmlLoadExtDtdDefaultValue;
+
+xmlDocPtr parse_xml( char* , int );
+xsltStylesheetPtr parse_xsl( char*, int );
+char* parse( xsltStylesheetPtr, xmlDocPtr, char ** );
+
+VALUE object_to_string( VALUE );
+int objectIsFile( VALUE );
+#endif
+
Added: packages-wip/libxslt-ruby/trunk/rb_utils.c
===================================================================
--- packages-wip/libxslt-ruby/trunk/rb_utils.c 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/rb_utils.c 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune at free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "rb_utils.h"
+
+char * getRubyObjectName( VALUE rb_Object ) {
+ VALUE klass = rb_funcall( rb_Object, rb_intern( "class" ), 0 );
+ return( STR2CSTR( rb_funcall( klass, rb_intern( "to_s" ), 0 ) ) );
+}
+
+int isFile( const char *filename ) {
+ struct stat stbuf;
+
+ if( stat( filename, &stbuf ) ) return 0;
+ return( ( (stbuf.st_mode & S_IFMT) == S_IFREG ) ? 1 : 0 );
+}
Added: packages-wip/libxslt-ruby/trunk/rb_utils.h
===================================================================
--- packages-wip/libxslt-ruby/trunk/rb_utils.h 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/rb_utils.h 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune at free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_RB_UTILS_H__
+#define __RUBY_RB_UTILS_H__
+
+#include <ruby.h>
+#include <rubyio.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+char * getRubyObjectName( VALUE );
+int isFile( const char *filename );
+
+#endif
Added: packages-wip/libxslt-ruby/trunk/tests/subdir/result.xsl
===================================================================
--- packages-wip/libxslt-ruby/trunk/tests/subdir/result.xsl 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/tests/subdir/result.xsl 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,3 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:template name="result">PASS</xsl:template>
+</xsl:stylesheet>
Added: packages-wip/libxslt-ruby/trunk/tests/subdir/test.xsl
===================================================================
--- packages-wip/libxslt-ruby/trunk/tests/subdir/test.xsl 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/tests/subdir/test.xsl 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,8 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:import href="result.xsl"/>
+ <xsl:output omit-xml-declaration="yes"/>
+
+ <xsl:template match="/">
+ <xsl:call-template name="result"/>
+ </xsl:template>
+</xsl:stylesheet>
Added: packages-wip/libxslt-ruby/trunk/tests/t.xml
===================================================================
--- packages-wip/libxslt-ruby/trunk/tests/t.xml 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/tests/t.xml 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<test>This is a test file</test>
Added: packages-wip/libxslt-ruby/trunk/tests/t.xsl
===================================================================
--- packages-wip/libxslt-ruby/trunk/tests/t.xsl 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/tests/t.xsl 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,6 @@
+<?xml version="1.0" ?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:template match="/">
+ <xsl:apply-templates />
+ </xsl:template>
+</xsl:stylesheet>
Added: packages-wip/libxslt-ruby/trunk/tests/test.rb
===================================================================
--- packages-wip/libxslt-ruby/trunk/tests/test.rb 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/tests/test.rb 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,125 @@
+#!ruby
+
+require "test/unit"
+require "../xslt"
+
+# Test::Unit suite for flattenx extension
+#
+# $Id: test.rb,v 1.4 2005/11/14 00:22:27 whateley Exp $
+# $Author: whateley $
+
+class XsltTest < Test::Unit::TestCase
+ def setup
+ if @xslt.nil? == true
+ @xslt = XML::XSLT.new( )
+ @testOut = "<?xml version=\"1.0\"?>\nThis is a test file\n"
+ @xml_simple = true
+ begin
+ require "xml/simple"
+ rescue LoadError => e
+ @xml_simple = false
+ end
+
+ @xml_smart = true
+ begin
+ require "xml/smart"
+ rescue LoadError => e
+ @xml_smart = false
+ end
+ end
+ end
+
+ def test_instance
+ assert_instance_of( XML::XSLT, @xslt )
+ end
+
+ def test_from_file
+ @xslt.xml = "t.xml"
+ @xslt.xsl = "t.xsl"
+ out = @xslt.serve
+ assert_equal( @testOut, out )
+ end
+
+ def test_from_data
+ @xslt.xml = IO::readlines( "t.xml" ).join
+ @xslt.xsl = IO::readlines( "t.xsl" ).join
+ out = @xslt.serve
+ assert_equal( @testOut, out )
+ end
+
+ def test_from_simple
+ if @xml_simple
+ require 'xml/simple'
+ @xslt.xml = XML::Simple.open( "t.xml" )
+ @xslt.xsl = XML::Simple.open( "t.xsl" )
+ out = @xslt.serve()
+ assert_equal( @testOut, out )
+ else
+ assert( true )
+ end
+ end
+
+ def test_from_smart
+ if @xml_smart
+ require 'xml/smart'
+ @xslt.xml = XML::Smart.open( "t.xml" )
+ @xslt.xsl = XML::Smart.open( "t.xsl" )
+ out = @xslt.serve()
+ assert_equal( @testOut, out )
+ else
+ assert( true )
+ end
+ end
+
+ def test_from_rexml
+ require 'rexml/document'
+ @xslt.xml = REXML::Document.new File.open( "t.xml" )
+ @xslt.xsl = REXML::Document.new File.open( "t.xsl" )
+ out = @xslt.serve()
+ assert_equal( @testOut, out )
+ end
+
+ def test_error_1
+ begin
+ @xslt.xsl = "nil"
+ rescue => e
+ assert_instance_of( XML::XSLT::ParsingError, e )
+ end
+ end
+
+ def test_error_2
+ begin
+ @xslt.xml = "nil"
+ rescue => e
+ assert_instance_of( XML::XSLT::ParsingError, e )
+ end
+ end
+
+ def test_error_3
+ begin
+ @xslt.xml = "t.xsl"
+ rescue => e
+ assert_instance_of( XML::XSLT::ParsingError, e )
+ end
+ end
+
+ def test_base_uri_1
+ @xslt.xml = "<test/>"
+ xsl = "subdir/test.xsl"
+
+ # the base URI of a loaded XSL file should be the URI of that file
+ assert_nothing_raised( XML::XSLT::ParsingError ) do
+ @xslt.xsl = xsl
+ end
+ end
+
+ def test_base_uri_2
+ @xslt.xml = "<test/>"
+ xsl = File.read("subdir/test.xsl")
+
+ # a file loaded from memory has no base URI, so this should fail
+ assert_raises( XML::XSLT::ParsingError ) do
+ @xslt.xsl = xsl
+ end
+ end
+end
Added: packages-wip/libxslt-ruby/trunk/xslt.c
===================================================================
--- packages-wip/libxslt-ruby/trunk/xslt.c 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/xslt.c 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,619 @@
+/**
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune at free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "xslt.h"
+
+VALUE mXML;
+VALUE cXSLT;
+VALUE eXSLTError;
+VALUE eXSLTParsingError;
+VALUE eXSLTTransformationError;
+
+void ruby_xslt_free( RbTxslt *pRbTxslt ) {
+ if( pRbTxslt != NULL ) {
+ if( pRbTxslt->tParsedXslt != NULL )
+ xsltFreeStylesheet(pRbTxslt->tParsedXslt);
+
+ if( pRbTxslt->tXMLDocument != NULL )
+ xmlFreeDoc(pRbTxslt->tXMLDocument);
+
+ free( pRbTxslt );
+ }
+
+ /* xsltCleanupGlobals(); */
+ xmlCleanupParser();
+ xmlMemoryDump();
+}
+
+void ruby_xslt_mark( RbTxslt *pRbTxslt ) {
+ if( pRbTxslt == NULL ) return;
+ if( !NIL_P(pRbTxslt->xXmlData) ) rb_gc_mark( pRbTxslt->xXmlData );
+ if( !NIL_P(pRbTxslt->oXmlObject) ) rb_gc_mark( pRbTxslt->oXmlObject );
+ if( !NIL_P(pRbTxslt->xXmlString) ) rb_gc_mark( pRbTxslt->xXmlString );
+
+ if( !NIL_P(pRbTxslt->xXslData) ) rb_gc_mark( pRbTxslt->xXslData );
+ if( !NIL_P(pRbTxslt->oXslObject) ) rb_gc_mark( pRbTxslt->oXslObject );
+ if( !NIL_P(pRbTxslt->xXslString) ) rb_gc_mark( pRbTxslt->xXslString );
+
+ if( !NIL_P(pRbTxslt->xXmlResultCache) ) rb_gc_mark( pRbTxslt->xXmlResultCache );
+
+ if( !NIL_P(pRbTxslt->pxParams) ) rb_gc_mark( pRbTxslt->pxParams );
+}
+
+/**
+ * oXSLT = XML::XSLT::new()
+ *
+ * Create a new XML::XSLT object
+ */
+VALUE ruby_xslt_new( VALUE class ) {
+ RbTxslt *pRbTxslt;
+
+ pRbTxslt = (RbTxslt *)malloc(sizeof(RbTxslt));
+ if( pRbTxslt == NULL )
+ rb_raise(rb_eNoMemError, "No memory left for XSLT struct");
+
+ pRbTxslt->iXmlType = RUBY_XSLT_XMLSRC_TYPE_NULL;
+ pRbTxslt->xXmlData = Qnil;
+ pRbTxslt->oXmlObject = Qnil;
+ pRbTxslt->xXmlString = Qnil;
+ pRbTxslt->tXMLDocument = NULL;
+
+ pRbTxslt->iXslType = RUBY_XSLT_XSLSRC_TYPE_NULL;
+ pRbTxslt->xXslData = Qnil;
+ pRbTxslt->oXslObject = Qnil;
+ pRbTxslt->xXslString = Qnil;
+ pRbTxslt->tParsedXslt = NULL;
+
+ pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_NULL;
+ pRbTxslt->xXmlResultCache = Qnil;
+
+ pRbTxslt->pxParams = Qnil;
+ pRbTxslt->iNbParams = 0;
+
+ xmlInitMemory();
+ xmlSubstituteEntitiesDefault( 1 );
+ xmlLoadExtDtdDefaultValue = 1;
+
+ return( Data_Wrap_Struct( class, ruby_xslt_mark, ruby_xslt_free, pRbTxslt ) );
+}
+
+/**
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * oXSLT.xml=<data|REXML::Document|XML::Smart|file>
+ *
+ * Set XML data.
+ *
+ * Parameter can be type String, REXML::Document, XML::Smart::Dom or Filename
+ *
+ * Examples :
+ * # Parameter as String
+ * oXSLT.xml = <<XML
+ * <?xml version="1.0" encoding="UTF-8"?>
+ * <test>This is a test string</test>
+ * XML
+ *
+ * # Parameter as REXML::Document
+ * require 'rexml/document'
+ * oXSLT.xml = REXML::Document.new File.open( "test.xml" )
+ *
+ * # Parameter as XML::Smart::Dom
+ * require 'xml/smart'
+ * oXSLT.xml = XML::Smart.open( "test.xml" )
+ *
+ * # Parameter as Filename
+ * oXSLT.xml = "test.xml"
+ */
+VALUE ruby_xslt_xml_obj_set( VALUE self, VALUE xml_doc_obj ) {
+ RbTxslt *pRbTxslt;
+ Data_Get_Struct( self, RbTxslt, pRbTxslt );
+
+ pRbTxslt->oXmlObject = xml_doc_obj;
+ pRbTxslt->xXmlString = object_to_string( xml_doc_obj );
+ if( pRbTxslt->xXmlString == Qnil ) {
+ rb_raise( eXSLTError, "Can't get XML data" );
+ }
+ pRbTxslt->iXmlType = RUBY_XSLT_XMLSRC_TYPE_STR;
+ pRbTxslt->xXmlData = pRbTxslt->xXmlString;
+
+ pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_NULL;
+
+ pRbTxslt->tXMLDocument = parse_xml( STR2CSTR( pRbTxslt->xXmlData ), pRbTxslt->iXmlType );
+ if( pRbTxslt->tXMLDocument == NULL ) {
+ rb_raise( eXSLTParsingError, "XML parsing error" );
+ }
+
+ pRbTxslt->iXmlType = RUBY_XSLT_XMLSRC_TYPE_PARSED;
+
+ return( Qnil );
+}
+
+/**
+ * XML::XSLT#xmlfile=<file> is deprecated. Please use XML::XSLT#xml=<file>
+ */
+VALUE ruby_xslt_xml_obj_set_d( VALUE self, VALUE xml_doc_obj ) {
+ rb_warn( "XML::XSLT#xmlfile=<file> is deprecated. Please use XML::XSLT#xml=<file> !" );
+ return( ruby_xslt_xml_obj_set( self, xml_doc_obj ) );
+}
+
+/**
+ * string = oXSLT.xml
+ *
+ * Return XML, set by XML::XSLT#xml=, as string
+ */
+VALUE ruby_xslt_xml_2str_get( VALUE self ) {
+ RbTxslt *pRbTxslt;
+ Data_Get_Struct( self, RbTxslt, pRbTxslt );
+
+ return( pRbTxslt->xXmlString );
+}
+
+/**
+ * object = oXSLT.xmlobject
+ *
+ * Return the XML object set by XML::XSLT#xml=
+ */
+VALUE ruby_xslt_xml_2obj_get( VALUE self ) {
+ RbTxslt *pRbTxslt;
+ Data_Get_Struct( self, RbTxslt, pRbTxslt );
+
+ return( pRbTxslt->oXmlObject );
+}
+
+/**
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * oXSLT.xsl=<data|REXML::Document|XML::Smart|file>
+ *
+ * Set XSL data.
+ *
+ * Parameter can be type String, REXML::Document, XML::Smart::Dom or Filename
+ *
+ * Examples :
+ * # Parameter as String
+ * oXSLT.xsl = <<XML
+ * <?xml version="1.0" ?>
+ * <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ * <xsl:template match="/">
+ * <xsl:apply-templates />
+ * </xsl:template>
+ * </xsl:stylesheet>
+ * XML
+ *
+ * # Parameter as REXML::Document
+ * require 'rexml/document'
+ * oXSLT.xsl = REXML::Document.new File.open( "test.xsl" )
+ *
+ * # Parameter as XML::Smart::Dom
+ * require 'xml/smart'
+ * oXSLT.xsl = XML::Smart.open( "test.xsl" )
+ *
+ * # Parameter as Filename
+ * oXSLT.xsl = "test.xsl"
+ */
+VALUE ruby_xslt_xsl_obj_set( VALUE self, VALUE xsl_doc_obj ) {
+ RbTxslt *pRbTxslt;
+ Data_Get_Struct( self, RbTxslt, pRbTxslt );
+
+ pRbTxslt->oXslObject = xsl_doc_obj;
+ pRbTxslt->xXslString = object_to_string( xsl_doc_obj );
+ if( pRbTxslt->xXslString == Qnil ) {
+ rb_raise( eXSLTError, "Can't get XSL data" );
+ }
+
+ if( objectIsFile( xsl_doc_obj ) ) {
+ pRbTxslt->iXslType = RUBY_XSLT_XSLSRC_TYPE_FILE;
+ pRbTxslt->xXslData = pRbTxslt->oXslObject;
+ } else {
+ pRbTxslt->iXslType = RUBY_XSLT_XSLSRC_TYPE_STR;
+ pRbTxslt->xXslData = pRbTxslt->xXslString;
+ }
+
+ pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_NULL;
+
+ pRbTxslt->tParsedXslt = parse_xsl( STR2CSTR( pRbTxslt->xXslData ), pRbTxslt->iXslType );
+ if( pRbTxslt->tParsedXslt == NULL ) {
+ rb_raise( eXSLTParsingError, "XSL Stylesheet parsing error" );
+ }
+
+ pRbTxslt->iXslType = RUBY_XSLT_XSLSRC_TYPE_PARSED;
+
+ return( Qnil );
+}
+
+/**
+ * XML::XSLT#xslfile=<file> is deprecated. Please use XML::XSLT#xsl=<file>
+ */
+VALUE ruby_xslt_xsl_obj_set_d( VALUE self, VALUE xsl_doc_obj ) {
+ rb_warning( "XML::XSLT#xslfile=<file> is deprecated. Please use XML::XSLT#xsl=<file> !" );
+ return( ruby_xslt_xsl_obj_set( self, xsl_doc_obj ) );
+}
+
+/**
+ * string = oXSLT.xsl
+ *
+ * Return XSL, set by XML::XSLT#xsl=, as string
+ */
+VALUE ruby_xslt_xsl_2str_get( VALUE self ) {
+ RbTxslt *pRbTxslt;
+ Data_Get_Struct( self, RbTxslt, pRbTxslt );
+
+ return( pRbTxslt->xXslString );
+}
+
+/**
+ * object = oXSLT.xslobject
+ *
+ * Return the XSL object set by XML::XSLT#xsl=
+ */
+VALUE ruby_xslt_xsl_2obj_get( VALUE self ) {
+ RbTxslt *pRbTxslt;
+ Data_Get_Struct( self, RbTxslt, pRbTxslt );
+
+ return( pRbTxslt->oXslObject );
+}
+
+/**
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * output_string = oXSLT.serve( )
+ *
+ * Return the stylesheet transformation
+ */
+VALUE ruby_xslt_serve( VALUE self ) {
+ RbTxslt *pRbTxslt;
+ char *xOut;
+ char **pxParams = NULL;
+
+ Data_Get_Struct( self, RbTxslt, pRbTxslt );
+
+ if( pRbTxslt->iXmlResultType == RUBY_XSLT_XMLSRC_TYPE_NULL ) {
+
+ if( pRbTxslt->pxParams != Qnil ){
+ int iCpt;
+
+ pxParams = (char **)ALLOCA_N( void *, pRbTxslt->iNbParams );
+ MEMZERO( pxParams, void *, pRbTxslt->iNbParams );
+
+ for( iCpt = 0; iCpt <= pRbTxslt->iNbParams - 3; iCpt++ ) {
+ pxParams[iCpt] = STR2CSTR( rb_ary_entry( pRbTxslt->pxParams, iCpt ) );
+ }
+ }
+
+ if( pRbTxslt->iXslType != RUBY_XSLT_XSLSRC_TYPE_NULL &&
+ pRbTxslt->iXmlType != RUBY_XSLT_XMLSRC_TYPE_NULL ) {
+ xOut = parse( pRbTxslt->tParsedXslt, pRbTxslt->tXMLDocument, pxParams );
+ if( xOut == NULL ) {
+ pRbTxslt->xXmlResultCache = Qnil;
+ pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_NULL;
+ } else {
+ pRbTxslt->xXmlResultCache = rb_str_new2( xOut );
+ pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_STR;
+ }
+ } else {
+ pRbTxslt->xXmlResultCache = Qnil;
+ pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_NULL;
+ }
+ }
+
+ return( pRbTxslt->xXmlResultCache );
+}
+
+/**
+ * oXSLT.save( "result.xml" )
+ *
+ * Save the stylesheet transformation to file
+ */
+VALUE ruby_xslt_save( VALUE self, VALUE xOutFilename ) {
+ char *xOut;
+ VALUE rOut;
+ FILE *fOutFile;
+
+ rOut = ruby_xslt_serve( self );
+
+ if( rOut != Qnil ) {
+ xOut = STR2CSTR( rOut );
+
+ fOutFile = fopen( STR2CSTR( xOutFilename ), "w" );
+ if( fOutFile == NULL ) {
+ free( xOut );
+ rb_raise( rb_eRuntimeError, "Can't create file %s\n", STR2CSTR( xOutFilename ) );
+ rOut = Qnil;
+ } else {
+ fwrite( xOut, 1, strlen( xOut ), fOutFile );
+ fclose( fOutFile );
+ }
+ }
+
+ return( rOut );
+}
+
+/**
+ * ----------------------------------------------------------------------------
+ */
+
+#ifdef USE_ERROR_HANDLER
+/**
+ * Brendan Taylor
+ * whateley at gmail.com
+ */
+/**
+ * error_ary = XML::XSLT::errors( )
+ *
+ * Return an Array containing all the xml errors
+ *
+ * This method is only available if Ruby/XSLT has been configured with --enable-error-handler option
+ */
+VALUE rb_xslt_errors(VALUE class) {
+ return rb_cvar_get(class, rb_intern("@@errors"));
+}
+
+void xsltErrorFuncHandler(void *ctx, const char *msg, ...) {
+ va_list ap;
+ char *str;
+ char *larger;
+ int chars;
+ int size = 150;
+
+ VALUE error_arr = rb_cvar_get(cXSLT, rb_intern("@@errors"));
+
+ /* this is taken verbatim from the libxslt python bindings */
+ str = (char *) xmlMalloc(150);
+ if (str == NULL)
+ return;
+
+ while (1) {
+ va_start(ap, msg);
+ chars = vsnprintf(str, size, msg, ap);
+ va_end(ap);
+ if ((chars > -1) && (chars < size))
+ break;
+ if (chars > -1)
+ size += chars + 1;
+ else
+ size += 100;
+ if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
+ xmlFree(str);
+ return;
+ }
+ str = larger;
+ }
+
+ rb_ary_push(error_arr, rb_str_new2(str));
+}
+#endif
+
+/**
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * parameters support, patch from :
+ *
+ * Eustáquio "TaQ" Rangel
+ * eustaquiorangel at yahoo.com
+ * http://beam.to/taq
+ *
+ * Corrections : Greg
+ */
+/**
+ * oXSLT.parameters={ "key" => "value", "key" => "value", ... }
+ */
+VALUE ruby_xslt_parameters_set( VALUE self, VALUE parameters ) {
+ RbTxslt *pRbTxslt;
+ Check_Type( parameters, T_HASH );
+
+ Data_Get_Struct( self, RbTxslt, pRbTxslt );
+
+ if( !NIL_P(parameters) ){
+ pRbTxslt->pxParams = rb_ary_new( );
+ // each_pair and process_pair defined ind parameters.c
+ (void)rb_iterate( each_pair, parameters, process_pair, pRbTxslt->pxParams );
+ pRbTxslt->iNbParams = FIX2INT( rb_funcall( parameters, rb_intern("size"), 0, 0 ) ) * 2 + 2;
+ pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_NULL;
+ }
+
+ return( Qnil );
+}
+
+/**
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * media type information, path from :
+ *
+ * Brendan Taylor
+ * whateley at gmail.com
+ *
+ */
+/**
+ * mediaTypeString = oXSLT.mediaType( )
+ *
+ * Return the XSL output's media type
+ */
+VALUE ruby_xslt_media_type( VALUE self ) {
+ RbTxslt *pRbTxslt;
+ xsltStylesheetPtr vXSLTSheet = NULL;
+
+ Data_Get_Struct( self, RbTxslt, pRbTxslt );
+
+ vXSLTSheet = pRbTxslt->tParsedXslt;
+
+ if ( (vXSLTSheet == NULL) || (vXSLTSheet->mediaType == NULL) ) {
+ return Qnil;
+ } else {
+ return rb_str_new2( (char *)(vXSLTSheet->mediaType) );
+ }
+}
+
+/**
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ * XML::XSLT::extFunction( "round-trip", "http://test.none", rbObj )
+ * registers an extension function "round-trip" in the namespace "http://test.none"
+ *
+ * when XPath like ex:round-trip(arg) is encountered in the XSLT it will call the method "round_trip" on the rbObj object with the argument arg
+ */
+ VALUE ruby_xslt_ext_function( VALUE class, VALUE name, VALUE ns_uri, VALUE receiver ) {
+ VALUE ns_hash, func_hash;
+
+ ns_hash = rb_cvar_get(cXSLT, rb_intern("@@extFunctions"));
+
+ func_hash = rb_hash_aref(ns_hash, ns_uri);
+
+ if(func_hash == Qnil) {
+ /* we've seen no reference to this URI, so create one */
+ func_hash = rb_hash_new();
+ rb_hash_aset(ns_hash, ns_uri, func_hash);
+ }
+
+ rb_hash_aset(func_hash, name, receiver);
+
+ xsltRegisterExtModuleFunction( BAD_CAST STR2CSTR(name), BAD_CAST STR2CSTR(ns_uri), xmlXPathFuncCallback );
+
+ return Qnil;
+ }
+
+/**
+ * string = oXSLT.xsl_to_s( )
+ */
+VALUE ruby_xslt_to_s( VALUE self ) {
+ VALUE vStrOut;
+ RbTxslt *pRbTxslt;
+ xsltStylesheetPtr vXSLTSheet = NULL;
+ char *xKlassName = rb_class2name( CLASS_OF( self ) );
+
+ Data_Get_Struct( self, RbTxslt, pRbTxslt );
+
+ //vXSLTSheet = xsltParseStylesheetDoc( xmlParseMemory( STR2CSTR( pRbTxslt->xXslData ), strlen( STR2CSTR( pRbTxslt->xXslData ) ) ) );
+ vXSLTSheet = pRbTxslt->tParsedXslt;
+ if (vXSLTSheet == NULL) return Qnil;
+
+ vStrOut = rb_str_new( 0, strlen(xKlassName)+1024 );
+ (void) sprintf( RSTRING(vStrOut)->ptr,
+ "#<%s: parent=%p,next=%p,imports=%p,docList=%p,"
+ "doc=%p,stripSpaces=%p,stripAll=%d,cdataSection=%p,"
+ "variables=%p,templates=%p,templatesHash=%p,"
+ "rootMatch=%p,keyMatch=%p,elemMatch=%p,"
+ "attrMatch=%p,parentMatch=%p,textMatch=%p,"
+ "piMatch=%p,commentMatch=%p,nsAliases=%p,"
+ "attributeSets=%p,nsHash=%p,nsDefs=%p,keys=%p,"
+ "method=%s,methodURI=%s,version=%s,encoding=%s,"
+ "omitXmlDeclaration=%d,decimalFormat=%p,standalone=%d,"
+ "doctypePublic=%s,doctypeSystem=%s,indent=%d,"
+ "mediaType=%s,preComps=%p,warnings=%d,errors=%d,"
+ "exclPrefix=%s,exclPrefixTab=%p,exclPrefixNr=%d,"
+ "exclPrefixMax=%d>",
+ xKlassName,
+ vXSLTSheet->parent, vXSLTSheet->next, vXSLTSheet->imports, vXSLTSheet->docList,
+ vXSLTSheet->doc, vXSLTSheet->stripSpaces, vXSLTSheet->stripAll, vXSLTSheet->cdataSection,
+ vXSLTSheet->variables, vXSLTSheet->templates, vXSLTSheet->templatesHash,
+ vXSLTSheet->rootMatch, vXSLTSheet->keyMatch, vXSLTSheet->elemMatch,
+ vXSLTSheet->attrMatch, vXSLTSheet->parentMatch, vXSLTSheet->textMatch,
+ vXSLTSheet->piMatch, vXSLTSheet->commentMatch, vXSLTSheet->nsAliases,
+ vXSLTSheet->attributeSets, vXSLTSheet->nsHash, vXSLTSheet->nsDefs, vXSLTSheet->keys,
+ vXSLTSheet->method, vXSLTSheet->methodURI, vXSLTSheet->version, vXSLTSheet->encoding,
+ vXSLTSheet->omitXmlDeclaration, vXSLTSheet->decimalFormat, vXSLTSheet->standalone,
+ vXSLTSheet->doctypePublic, vXSLTSheet->doctypeSystem, vXSLTSheet->indent,
+ vXSLTSheet->mediaType, vXSLTSheet->preComps, vXSLTSheet->warnings, vXSLTSheet->errors,
+ vXSLTSheet->exclPrefix, vXSLTSheet->exclPrefixTab, vXSLTSheet->exclPrefixNr,
+ vXSLTSheet->exclPrefixMax );
+
+ RSTRING(vStrOut)->len = strlen( RSTRING(vStrOut)->ptr );
+ if( OBJ_TAINTED(self) ) OBJ_TAINT(vStrOut);
+
+ // xsltFreeStylesheet(vXSLTSheet);
+
+ return( vStrOut );
+}
+
+/**
+ * ----------------------------------------------------------------------------
+ */
+
+void Init_xslt( void ) {
+ mXML = rb_define_module( "XML" );
+ cXSLT = rb_define_class_under( mXML, "XSLT", rb_cObject );
+
+ eXSLTError = rb_define_class_under( cXSLT, "XSLTError", rb_eRuntimeError );
+ eXSLTParsingError = rb_define_class_under( cXSLT, "ParsingError", eXSLTError );
+ eXSLTTransformationError = rb_define_class_under( cXSLT, "TransformationError", eXSLTError );
+
+ rb_define_const( cXSLT, "MAX_DEPTH", INT2NUM(xsltMaxDepth) );
+ rb_define_const( cXSLT, "MAX_SORT", INT2NUM(XSLT_MAX_SORT) );
+ rb_define_const( cXSLT, "ENGINE_VERSION", rb_str_new2(xsltEngineVersion) );
+ rb_define_const( cXSLT, "LIBXSLT_VERSION", INT2NUM(xsltLibxsltVersion) );
+ rb_define_const( cXSLT, "LIBXML_VERSION", INT2NUM(xsltLibxmlVersion) );
+ rb_define_const( cXSLT, "XSLT_NAMESPACE", rb_str_new2((char *)XSLT_NAMESPACE) );
+ rb_define_const( cXSLT, "DEFAULT_VENDOR", rb_str_new2(XSLT_DEFAULT_VENDOR) );
+ rb_define_const( cXSLT, "DEFAULT_VERSION", rb_str_new2(XSLT_DEFAULT_VERSION) );
+ rb_define_const( cXSLT, "DEFAULT_URL", rb_str_new2(XSLT_DEFAULT_URL) );
+ rb_define_const( cXSLT, "NAMESPACE_LIBXSLT", rb_str_new2((char *)XSLT_LIBXSLT_NAMESPACE) );
+ rb_define_const( cXSLT, "NAMESPACE_NORM_SAXON", rb_str_new2((char *)XSLT_NORM_SAXON_NAMESPACE) );
+ rb_define_const( cXSLT, "NAMESPACE_SAXON", rb_str_new2((char *)XSLT_SAXON_NAMESPACE) );
+ rb_define_const( cXSLT, "NAMESPACE_XT", rb_str_new2((char *)XSLT_XT_NAMESPACE) );
+ rb_define_const( cXSLT, "NAMESPACE_XALAN", rb_str_new2((char *)XSLT_XALAN_NAMESPACE) );
+
+ rb_define_const( cXSLT, "RUBY_XSLT_VERSION", rb_str_new2(RUBY_XSLT_VERSION) );
+
+ rb_define_singleton_method( cXSLT, "new", ruby_xslt_new, 0 );
+ rb_define_singleton_method( cXSLT, "extFunction", ruby_xslt_ext_function, 3);
+
+ /* a hash of hashes. might be more elegant if it were its own class */
+ /* keeps track of what functions are registered in what namespaces */
+ rb_define_class_variable( cXSLT, "@@extFunctions", rb_hash_new());
+
+ rb_define_method( cXSLT, "serve", ruby_xslt_serve, 0 );
+ rb_define_method( cXSLT, "save", ruby_xslt_save, 1 );
+
+ rb_define_method( cXSLT, "xml=", ruby_xslt_xml_obj_set, 1 );
+ rb_define_method( cXSLT, "xmlfile=", ruby_xslt_xml_obj_set_d, 1 ); // DEPRECATED
+ rb_define_method( cXSLT, "xml", ruby_xslt_xml_2str_get, 0 );
+ rb_define_method( cXSLT, "xmlobject", ruby_xslt_xml_2obj_get, 0 );
+
+ rb_define_method( cXSLT, "xsl=", ruby_xslt_xsl_obj_set, 1 );
+ rb_define_method( cXSLT, "xslfile=", ruby_xslt_xsl_obj_set_d, 1 ); // DEPRECATED
+ rb_define_method( cXSLT, "xsl", ruby_xslt_xsl_2str_get, 0 );
+ rb_define_method( cXSLT, "xslobject", ruby_xslt_xsl_2obj_get, 0 );
+
+ rb_define_method( cXSLT, "parameters=", ruby_xslt_parameters_set, 1 );
+ rb_define_method( cXSLT, "xsl_to_s", ruby_xslt_to_s, 0 );
+
+ rb_define_method( cXSLT, "mediaType", ruby_xslt_media_type, 0 );
+
+#ifdef USE_ERROR_HANDLER
+ /* this is really quite inelegant */
+ xmlSetGenericErrorFunc( NULL, xsltErrorFuncHandler );
+ xsltSetGenericErrorFunc( NULL, xsltErrorFuncHandler );
+ rb_define_class_variable( cXSLT, "@@errors", rb_ary_new());
+ rb_define_singleton_method( cXSLT, "errors", rb_xslt_errors, 0 );
+#endif
+
+#ifdef USE_EXSLT
+ exsltRegisterAll();
+#endif
+}
Added: packages-wip/libxslt-ruby/trunk/xslt.h
===================================================================
--- packages-wip/libxslt-ruby/trunk/xslt.h 2006-11-01 22:00:28 UTC (rev 948)
+++ packages-wip/libxslt-ruby/trunk/xslt.h 2006-11-03 16:17:38 UTC (rev 949)
@@ -0,0 +1,98 @@
+/**
+ * Copyright (C) 2005 Gregoire Lejeune <gregoire.lejeune at free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XSLT_H__
+#define __RUBY_XSLT_H__
+
+#include <ruby.h>
+#include <rubyio.h>
+
+#include <string.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/debugXML.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/xmlIO.h>
+#include <libxml/xinclude.h>
+#include <libxml/catalog.h>
+
+#include <libxslt/extra.h>
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/imports.h>
+
+#ifdef USE_EXSLT
+ #include <libexslt/exslt.h>
+#endif
+
+#ifdef MEMWATCH
+ #include "memwatch.h"
+#endif
+
+#include "rb_utils.h"
+#include "parser.h"
+#include "parameters.h"
+#include "extfunc.h"
+
+#define RUBY_XSLT_VERSION "0.9.2"
+#define RUBY_XSLT_VERNUM 092
+
+#define RUBY_XSLT_XSLSRC_TYPE_NULL 0
+#define RUBY_XSLT_XSLSRC_TYPE_STR 1
+#define RUBY_XSLT_XSLSRC_TYPE_FILE 2
+#define RUBY_XSLT_XSLSRC_TYPE_REXML 4
+#define RUBY_XSLT_XSLSRC_TYPE_SMART 8
+#define RUBY_XSLT_XSLSRC_TYPE_PARSED 16
+
+#define RUBY_XSLT_XMLSRC_TYPE_NULL 0
+#define RUBY_XSLT_XMLSRC_TYPE_STR 1
+#define RUBY_XSLT_XMLSRC_TYPE_FILE 2
+#define RUBY_XSLT_XMLSRC_TYPE_REXML 4
+#define RUBY_XSLT_XMLSRC_TYPE_SMART 8
+#define RUBY_XSLT_XMLSRC_TYPE_PARSED 16
+
+RUBY_EXTERN VALUE eXSLTError;
+RUBY_EXTERN VALUE eXSLTParsingError;
+RUBY_EXTERN VALUE eXSLTTransformationError;
+
+typedef struct RbTxslt {
+ int iXmlType;
+ VALUE xXmlData;
+ VALUE oXmlObject;
+ VALUE xXmlString;
+ xmlDocPtr tXMLDocument;
+
+ int iXslType;
+ VALUE xXslData;
+ VALUE oXslObject;
+ VALUE xXslString;
+ xsltStylesheetPtr tParsedXslt;
+
+ int iXmlResultType;
+ VALUE xXmlResultCache;
+
+ VALUE pxParams;
+ int iNbParams;
+
+} RbTxslt;
+
+#endif
More information about the pkg-ruby-extras-maintainers
mailing list