Commit Jeroen Witmond's xml-to-text translator, and use it for the FAQ.
Less double maintenance, hoorah!
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4830 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/FAQ.txt b/FAQ.txt
deleted file mode 100644
index 063a161..0000000
--- a/FAQ.txt
+++ /dev/null
@@ -1,361 +0,0 @@
-Valgrind FAQ, version 2.1.2
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Last revised 18 July 2004
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-1. Background
-2. Compiling, installing and configuring
-3. Valgrind aborts unexpectedly
-4. Valgrind behaves unexpectedly
-5. Memcheck doesn't find my bug
-6. Miscellaneous
-
-
------------------------------------------------------------------
-1. Background
------------------------------------------------------------------
-
-1.1. How do you pronounce "Valgrind"?
-
-The "Val" as in the world "value". The "grind" is pronounced with a
-short 'i' -- ie. "grinned" (rhymes with "tinned") rather than "grined"
-(rhymes with "find").
-
-Don't feel bad: almost everyone gets it wrong at first.
-
------------------------------------------------------------------
-
-1.2. Where does the name "Valgrind" come from?
-
-From Nordic mythology. Originally (before release) the project was
-named Heimdall, after the watchman of the Nordic gods. He could "see a
-hundred miles by day or night, hear the grass growing, see the wool
-growing on a sheep's back" (etc). This would have been a great name,
-but it was already taken by a security package "Heimdal".
-
-Keeping with the Nordic theme, Valgrind was chosen. Valgrind is the
-name of the main entrance to Valhalla (the Hall of the Chosen Slain in
-Asgard). Over this entrance there resides a wolf and over it there is
-the head of a boar and on it perches a huge eagle, whose eyes can see to
-the far regions of the nine worlds. Only those judged worthy by the
-guardians are allowed to pass through Valgrind. All others are refused
-entrance.
-
-It's not short for "value grinder", although that's not a bad guess.
-
-
------------------------------------------------------------------
-2. Compiling, installing and configuring
------------------------------------------------------------------
-
-2.1. When I trying building Valgrind, 'make' dies partway with an
- assertion failure, something like this: make: expand.c:489:
-
- allocated_variable_append: Assertion
- `current_variable_set_list->next != 0' failed.
-
-It's probably a bug in 'make'. Some, but not all, instances of version 3.79.1
-have this bug, see www.mail-archive.com/bug-make@gnu.org/msg01658.html. Try
-upgrading to a more recent version of 'make'. Alternatively, we have heard
-that unsetting the CFLAGS environment variable avoids the problem.
-
-
------------------------------------------------------------------
-3. Valgrind aborts unexpectedly
------------------------------------------------------------------
-
-3.1. Programs run OK on Valgrind, but at exit produce a bunch of errors a bit
- like this
-
- ==20755== Invalid read of size 4
- ==20755== at 0x40281C8A: _nl_unload_locale (loadlocale.c:238)
- ==20755== by 0x4028179D: free_mem (findlocale.c:257)
- ==20755== by 0x402E0962: __libc_freeres (set-freeres.c:34)
- ==20755== by 0x40048DCC: vgPlain___libc_freeres_wrapper
- (vg_clientfuncs.c:585)
- ==20755== Address 0x40CC304C is 8 bytes inside a block of size 380 free'd
- ==20755== at 0x400484C9: free (vg_clientfuncs.c:180)
- ==20755== by 0x40281CBA: _nl_unload_locale (loadlocale.c:246)
- ==20755== by 0x40281218: free_mem (setlocale.c:461)
- ==20755== by 0x402E0962: __libc_freeres (set-freeres.c:34)
-
- and then die with a segmentation fault.
-
-When the program exits, Valgrind runs the procedure __libc_freeres() in
-glibc. This is a hook for memory debuggers, so they can ask glibc to
-free up any memory it has used. Doing that is needed to ensure that
-Valgrind doesn't incorrectly report space leaks in glibc.
-
-Problem is that running __libc_freeres() in older glibc versions causes
-this crash.
-
-WORKAROUND FOR 1.1.X and later versions of Valgrind: use the
---run-libc-freeres=no flag. You may then get space leak reports for
-glibc-allocations (please _don't_ report these to the glibc people,
-since they are not real leaks), but at least the program runs.
-
------------------------------------------------------------------
-
-3.2. My (buggy) program dies like this:
- valgrind: vg_malloc2.c:442 (bszW_to_pszW):
- Assertion `pszW >= 0' failed.
-
-If Memcheck (the memory checker) shows any invalid reads, invalid writes
-and invalid frees in your program, the above may happen. Reason is that
-your program may trash Valgrind's low-level memory manager, which then
-dies with the above assertion, or something like this. The cure is to
-fix your program so that it doesn't do any illegal memory accesses. The
-above failure will hopefully go away after that.
-
------------------------------------------------------------------
-
-3.3. My program dies, printing a message like this along the way:
-
- disInstr: unhandled instruction bytes: 0x66 0xF 0x2E 0x5
-
-Older versions did not support some x86 instructions, particularly
-SSE/SSE2 instructions. Try a newer Valgrind; we now support almost all
-instructions. If it still happens with newer versions, if the failing
-instruction is an SSE/SSE2 instruction, you might be able to recompile
-your program without it by using the flag -march to gcc. Either way,
-let us know and we'll try to fix it.
-
-Another possibility is that your program has a bug and erroneously jumps
-to a non-code address, in which case you'll get a SIGILL signal.
-Memcheck/Addrcheck may issue a warning just before this happens, but they
-might not if the jump happens to land in addressable memory.
-
-
------------------------------------------------------------------
-4. Valgrind behaves unexpectedly
------------------------------------------------------------------
-
-4.1. My threaded server process runs unbelievably slowly on Valgrind.
- So slowly, in fact, that at first I thought it had completely
- locked up.
-
-We are not completely sure about this, but one possibility is that
-laptops with power management fool Valgrind's timekeeping mechanism,
-which is (somewhat in error) based on the x86 RDTSC instruction. A
-"fix" which is claimed to work is to run some other cpu-intensive
-process at the same time, so that the laptop's power-management
-clock-slowing does not kick in. We would be interested in hearing more
-feedback on this.
-
-Another possible cause is that versions prior to 1.9.6 did not support
-threading on glibc 2.3.X systems well. Hopefully the situation is much
-improved with 1.9.6 and later versions.
-
------------------------------------------------------------------
-
-4.2. My program uses the C++ STL and string classes. Valgrind
- reports 'still reachable' memory leaks involving these classes
- at the exit of the program, but there should be none.
-
-First of all: relax, it's probably not a bug, but a feature. Many
-implementations of the C++ standard libraries use their own memory pool
-allocators. Memory for quite a number of destructed objects is not
-immediately freed and given back to the OS, but kept in the pool(s) for
-later re-use. The fact that the pools are not freed at the exit() of
-the program cause Valgrind to report this memory as still reachable.
-The behaviour not to free pools at the exit() could be called a bug of
-the library though.
-
-Using gcc, you can force the STL to use malloc and to free memory as
-soon as possible by globally disabling memory caching. Beware! Doing
-so will probably slow down your program, sometimes drastically.
-
-- With gcc 2.91, 2.95, 3.0 and 3.1, compile all source using the STL
- with -D__USE_MALLOC. Beware! This is removed from gcc starting with
- version 3.3.
-
-- With gcc 3.2.2 and later, you should export the environment variable
- GLIBCPP_FORCE_NEW before running your program.
-
-- With gcc 3.4 and later, that variable has changed name to
- GLIBCXX_FORCE_NEW.
-
-There are other ways to disable memory pooling: using the malloc_alloc
-template with your objects (not portable, but should work for gcc) or
-even writing your own memory allocators. But all this goes beyond the
-scope of this FAQ. Start by reading
-http://gcc.gnu.org/onlinedocs/libstdc++/ext/howto.html#3 if you
-absolutely want to do that. But beware:
-
-1) there are currently changes underway for gcc which are not totally
- reflected in the docs right now ("now" == 26 Apr 03)
-
-2) allocators belong to the more messy parts of the STL and people went
- at great lengths to make it portable across platforms. Chances are
- good that your solution will work on your platform, but not on
- others.
-
------------------------------------------------------------------------------
-4.3. The stack traces given by Memcheck (or another tool) aren't helpful.
- How can I improve them?
-
-If they're not long enough, use --num-callers to make them longer.
-
-If they're not detailed enough, make sure you are compiling with -g to add
-debug information. And don't strip symbol tables (programs should be
-unstripped unless you run 'strip' on them; some libraries ship stripped).
-
-Also, for leak reports involving shared objects, if the shared object is
-unloaded before the program terminates, Valgrind will discard the debug
-information and the error message will be full of "???" entries. The
-workaround here is to avoid calling dlclose() on these shared objects.
-
-Also, -fomit-frame-pointer and -fstack-check can make stack traces worse.
-
-Some example sub-traces:
-
- With debug information and unstripped (best):
-
- Invalid write of size 1
- at 0x80483BF: really (malloc1.c:20)
- by 0x8048370: main (malloc1.c:9)
-
- With no debug information, unstripped:
-
- Invalid write of size 1
- at 0x80483BF: really (in /auto/homes/njn25/grind/head5/a.out)
- by 0x8048370: main (in /auto/homes/njn25/grind/head5/a.out)
-
- With no debug information, stripped:
-
- Invalid write of size 1
- at 0x80483BF: (within /auto/homes/njn25/grind/head5/a.out)
- by 0x8048370: (within /auto/homes/njn25/grind/head5/a.out)
- by 0x42015703: __libc_start_main (in /lib/tls/libc-2.3.2.so)
- by 0x80482CC: (within /auto/homes/njn25/grind/head5/a.out)
-
- With debug information and -fomit-frame-pointer:
-
- Invalid write of size 1
- at 0x80483C4: really (malloc1.c:20)
- by 0x42015703: __libc_start_main (in /lib/tls/libc-2.3.2.so)
- by 0x80482CC: ??? (start.S:81)
-
- A leak error message involving an unloaded shared object:
-
- 84 bytes in 1 blocks are possibly lost in loss record 488 of 713
- at 0x1B9036DA: operator new(unsigned) (vg_replace_malloc.c:132)
- by 0x1DB63EEB: ???
- by 0x1DB4B800: ???
- by 0x1D65E007: ???
- by 0x8049EE6: main (main.cpp:24)
-
------------------------------------------------------------------------------
-4.4. The stack traces given by Memcheck (or another tool) seem to
- have the wrong function name in them. What's happening?
-
-Occasionally Valgrind stack traces get the wrong function names.
-This is caused by glibc using aliases to effectively give one function
-two names. Most of the time Valgrind chooses a suitable name, but
-very occasionally it gets it wrong.
-
-Examples we know of are printing 'bcmp' instead of 'memcmp', 'index'
-instead of 'strchr', and 'rindex' instead of 'strrchr'.
-
------------------------------------------------------------------
-5. Memcheck doesn't find my bug
------------------------------------------------------------------
-
-5.1. I try running "valgrind --tool=memcheck my_program" and get
- Valgrind's startup message, but I don't get any errors and I know
- my program has errors.
-
-There are two possible causes of this.
-
-First, by default, Valgrind only traces the top-level process. So if your
-program spawns children, they won't be traced by Valgrind by default.
-Also, if your program is started by a shell script, Perl script, or
-something similar, Valgrind will trace the shell, or the Perl
-interpreter, or equivalent.
-
-To trace child processes, use the --trace-children=yes option.
-
-If you are tracing large trees of processes, it can be less disruptive
-to have the output sent over the network. Give Valgrind the flag
---log-socket=127.0.0.1:12345 (if you want logging output sent to port
-12345 on localhost). You can use the valgrind-listener program to
-listen on that port:
-
- valgrind-listener 12345
-
-Obviously you have to start the listener process first. See the
-documentation for more details.
-
-Second, if your program is statically linked, most Valgrind tools won't
-work as well, because they won't be able to replace certain functions,
-such as malloc(), with their own versions. A key indicator of this is
-if Memcheck says:
-
- No malloc'd blocks -- no leaks are possible
-
-when you know your program calls malloc(). The workaround is to avoid
-statically linking your program.
-
------------------------------------------------------------------
-
-5.2. Why doesn't Memcheck find the array overruns in this program?
-
- int static[5];
-
- int main(void)
- {
- int stack[5];
-
- static[5] = 0;
- stack [5] = 0;
-
- return 0;
- }
-
-Unfortunately, Memcheck doesn't do bounds checking on static or stack
-arrays. We'd like to, but it's just not possible to do in a reasonable
-way that fits with how Memcheck works. Sorry.
-
-
------------------------------------------------------------------
-6. Miscellaneous
------------------------------------------------------------------
-
-6.1. I tried writing a suppression but it didn't work. Can you
- write my suppression for me?
-
-Yes! Use the --gen-suppressions=yes feature to spit out suppressions
-automatically for you. You can then edit them if you like, eg.
-combining similar automatically generated suppressions using wildcards
-like '*'.
-
-If you really want to write suppressions by hand, read the manual
-carefully. Note particularly that C++ function names must be _mangled_.
-
------------------------------------------------------------------
-
-6.2. With Memcheck/Addrcheck's memory leak detector, what's the
- difference between "definitely lost", "possibly lost", "still
- reachable", and "suppressed"?
-
-The details are in section 3.6 of the manual.
-
-In short:
-
- - "definitely lost" means your program is leaking memory -- fix it!
-
- - "possibly lost" means your program is probably leaking memory,
- unless you're doing funny things with pointers.
-
- - "still reachable" means your program is probably ok -- it didn't
- free some memory it could have. This is quite common and often
- reasonable. Don't use --show-reachable=yes if you don't want to see
- these reports.
-
- - "suppressed" means that a leak error has been suppressed. There are
- some suppressions in the default suppression files. You can ignore
- suppressed errors.
-
------------------------------------------------------------------
-
-(this is the end of the FAQ.)
diff --git a/Makefile.am b/Makefile.am
index 95f29cf..2f95718 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -42,7 +42,6 @@
@PERL@ tests/vg_regtest $(TOOLS)
EXTRA_DIST = \
- FAQ.txt \
ACKNOWLEDGEMENTS \
README_DEVELOPERS \
README_PACKAGERS \
diff --git a/docs/Makefile.am b/docs/Makefile.am
index fee2b2a..b8307f0 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -7,7 +7,7 @@
# Comment out the next line to skip building print docs. The default
# is not to skip building print docs. Note, after changing it
# you of course need to re-run configure to make it take effect.
-BUILD_ALL_DOCS=yes
+BUILD_ALL_DOCS=no
##-------------------------------------------------------------
## END OF HACK
@@ -44,18 +44,24 @@
# stylesheet processor
XSLTPROC = xsltproc
-XSLTPROC_FLAGS = --nonet --xinclude
+XSLTPROC_FLAGS = --xinclude
# stylesheets
XSL_HTML_CHUNK_STYLE = $(mylibdir)/vg-html-chunk.xsl
XSL_HTML_SINGLE_STYLE = $(mylibdir)/vg-html-single.xsl
XSL_FO_STYLE = $(mylibdir)/vg-fo.xsl
-all-docs: html-docs print-docs
+all-docs: FAQ.txt html-docs print-docs
valid:
$(XMLLINT) $(XMLLINT_FLAGS) $(myxmldir)/index.xml
+# The text version of the FAQ.
+FAQ.txt: $(myxmldir)/FAQ.xml $(myxmldir)/vg-entities.xml $(mylibdir)/*.xslt
+ $(XSLTPROC) $(XSLTPROC_FLAGS) $(mylibdir)/untag-inline.xslt $(myxmldir)/FAQ.xml | \
+ $(XSLTPROC) $(XSLTPROC_FLAGS) $(mylibdir)/docbook2text.xslt - > FAQ.txt
+
+
# chunked html
html-docs:
@echo "Generating html files..."
@@ -113,14 +119,17 @@
# This is done at 'make dist' time. It builds the html and print docs
# and copies them into the docs/ directory in the tarball.
ifeq ($(BUILD_ALL_DOCS),yes)
-dist-hook: html-docs print-docs
+dist-hook: FAQ.txt html-docs print-docs
cp -r html $(distdir)
+ cp FAQ.txt $(distdir)/..
cp print/index.pdf $(distdir)
cp print/index.ps $(distdir)
else
-dist-hook: html-docs
+dist-hook: FAQ.txt html-docs
+ cp FAQ.txt $(distdir)/..
cp -r html $(distdir)
endif
distclean-local:
rm -rf html print
+ rm -f $(top_builddir)/FAQ.txt
diff --git a/docs/README b/docs/README
index af8fa16..6f6b5e3 100644
--- a/docs/README
+++ b/docs/README
@@ -178,12 +178,6 @@
- http://cvs.sourceforge.net/viewcvs.py/perl-xml/perl-xml-faq/
-TODO CRUCIAL:
--------------
-- Need to generate text FAQ from the valgrind/docs/xml/FAQ.xml (done at 'make
- dist' time along with the HTML docs using the "dist-hook"), and remove the
- old text FAQ which is in valgrind/.
-
TODO LESS CRUCIAL:
------------------
- add the HOWTO doc?
diff --git a/docs/lib/Makefile.am b/docs/lib/Makefile.am
index 627e39d..c589900 100644
--- a/docs/lib/Makefile.am
+++ b/docs/lib/Makefile.am
@@ -1,6 +1,16 @@
EXTRA_DIST = \
+ README_XML2TXT.txt \
+ copy.xslt \
+ text.justify.xslt \
+ docbook2text.xslt \
+ text.wrap.xslt \
+ str.dup.xslt \
+ untag-inline.xslt \
+ str.find-last.xslt \
vg-common.xsl \
vg-fo.xsl \
vg-html-chunk.xsl \
vg-html-single.xsl \
vg_basic.css
+
+
diff --git a/docs/lib/README_XML2TXT.txt b/docs/lib/README_XML2TXT.txt
new file mode 100644
index 0000000..3d70bec
--- /dev/null
+++ b/docs/lib/README_XML2TXT.txt
@@ -0,0 +1,59 @@
+README.txt file for the FAQ.xml to FAQ.txt transformer.
+=======================================================
+
+In valgrind-3.1.SVN, file docs/README contains, under the heading
+"TODO CRUCIAL", the item "Need to generate text FAQ from the
+valgrind/docs/xml/FAQ.xml (done at 'make dist' time along with the
+HTML docs using the 'dist-hook'), and remove the old text FAQ which is
+in valgrind/." This is an attempt to resolve this item using xsltproc
+and a number of xml style sheets. It is a hack in the sense that it
+does not support all of docbook, but only the subset currently used by
+file docs/xml/FAQ.xml.
+
+The transformation is done in two stages:
+
+1. Inline elements (literal, computeroutput and ulink) are replaced
+ with the corresponding text by stylesheet untag-inline.xslt. This
+ stylesheet uses copy.xslt to handle the non-inline elements.
+
+2. The actual formatting is done by stylesheet docbook2text.xslt. It
+ uses stylesheets str.dup.xslt, str.find-last.xslt,
+ text.justify.xslt and text.wrap.xslt to handle the formatting of
+ the text into a column with the approproate width and indentation.
+
+Stylesheets untag-inline.xslt and docbook2text.xslt are original
+work. Stylesheets copy.xslt, str.dup.xslt, str.find-last.xslt,
+text.justify.xslt and text.wrap.xslt are copied with some adaptations
+from the examples supplied with the XSLT Cookbook by Sal Mangano, (C)
+2003 O'Reilly & Associates, ISBN 0-596-00372-2. The O'Reilly Policy on
+Re-Use of Code Examples from Books
+<http://www.oreilly.com/pub/a/oreilly/ask_tim/2001/codepolicy.html>
+allows the use of these style sheets in valgrind for this purpose.
+
+The tarball contains:
+
+- File README.txt (this file).
+
+- the stylesheets copy.xslt, docbook2text.xslt, str.dup.xslt,
+ str.find-last.xslt, text.justify.xslt, text.wrap.xslt and
+ untag-inline.xslt.
+
+- File faq.txt.patch adds the generation of FAQ.txt to file
+ docs/Makefile.am. It is based on the assumptions that
+ * file FAQ.txt will be generated in directory docs.
+ * the stylesheets will be stored in directory docs/lib.
+ If a different output width is required (e.g. 80), you can use
+ command
+ $(XSLTPROC) $(XSLTPROC_FLAGS) $(libdir)/untag-inline.xslt $(xmldir)/FAQ.xml | \
+ $(XSLTPROC) $(XSLTPROC_FLAGS) --stringparam width 80 $(libdir)/docbook2text.xslt - > FAQ.txt
+
+- File FAQ.txt as generated on my system (Debian 3.1).
+
+Software used:
+xsltproc was compiled against libxml 20616, libxslt 10112 and libexslt 810
+libxslt 10112 was compiled against libxml 20616
+libexslt 810 was compiled against libxml 20616
+
+
+Copyright 2005 Jeroen N. Witmond, jnw@xs4all.nl
+GNU GENERAL PUBLIC LICENSE Version 2, June 1991 applies.
diff --git a/docs/lib/copy.xslt b/docs/lib/copy.xslt
new file mode 100644
index 0000000..b2c565d
--- /dev/null
+++ b/docs/lib/copy.xslt
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<!-- This file was copied with some adaptations from the examples
+supplied with the XSLT Cookbook by Sal Mangano, (C) 2003 O'Reilly &
+Associates, ISBN 0-596-00372-2. -->
+
+<xsl:output method="xml"/>
+
+<xsl:template match="/ | node() | @* | comment() | processing-instruction()">
+ <xsl:copy>
+ <xsl:apply-templates select="node() | @*"/>
+ </xsl:copy>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/docs/lib/docbook2text.xslt b/docs/lib/docbook2text.xslt
new file mode 100644
index 0000000..becc862
--- /dev/null
+++ b/docs/lib/docbook2text.xslt
@@ -0,0 +1,317 @@
+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- sgml -*- -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:text="http://www.ora.com/XSLTCookbook/namespaces/text"
+ xmlns:str="http://www.ora.com/XSLTCookbook/namespaces/strings">
+
+<xsl:include href="text.wrap.xslt"/>
+
+<xsl:strip-space elements="*"/>
+<xsl:preserve-space elements="screen programlisting"/>
+<xsl:output method="text"/>
+
+<!-- Transform a subset of docbook/xml into plain text. This -->
+<!-- stylesheet assumes that all elements that are to be formatted -->
+<!-- inline already have been handled by untag-inline.xslt. -->
+
+<!-- Maximum number of characters on one line. -->
+<xsl:param name="width" select="72"/>
+
+<!-- This stylesheet uses two named templates. The template named -->
+<!-- "header" writes its input, followed by a line of '~'s of -->
+<!-- the same length. The template named "ruler" produces a line of -->
+<!-- $width '-'s. They are implemented at the bottom of this file. -->
+
+<xsl:template match="/">
+ <!-- Title 'page' stuff. -->
+ <xsl:call-template name="header">
+ <xsl:with-param name="input" select="book/title"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="header">
+ <xsl:with-param name="input" select="book/bookinfo/releaseinfo"/>
+ </xsl:call-template>
+ <xsl:text>
</xsl:text>
+
+ <!-- List of sections. -->
+ <xsl:text>Table of Contents
</xsl:text>
+ <xsl:apply-templates select="book/sect1" mode="toc"/>
+ <xsl:text>
</xsl:text>
+
+ <!-- Contents. -->
+ <xsl:apply-templates select="book/sect1"/>
+</xsl:template>
+
+<xsl:template match="sect1" mode="toc">
+ <xsl:value-of select="position()"/>
+ <xsl:text>. </xsl:text>
+ <xsl:value-of select="title"/>
+ <xsl:text>
</xsl:text>
+</xsl:template>
+
+<!-- Processing of the contents starts here. -->
+
+<xsl:template match="sect1">
+ <!-- The FAQ contains two types of sect1: those containing a
+ qandaset (actually an unspecified number), and those containing a
+ sequence of paras. To get the number of blank lines right, these
+ must be treated separately. -->
+
+ <xsl:variable name="sectno" select="position()"/>
+
+ <xsl:call-template name="ruler"/>
+ <xsl:value-of select="$sectno"/>
+ <xsl:text>. </xsl:text>
+ <xsl:value-of select="title"/>
+ <xsl:text>
</xsl:text>
+ <xsl:call-template name="ruler"/>
+ <xsl:text>
</xsl:text>
+
+ <xsl:choose>
+ <xsl:when test="qandaset">
+ <xsl:apply-templates select="qandaset|para">
+ <xsl:with-param name="sectno" select="$sectno"/>
+ </xsl:apply-templates>
+ </xsl:when>
+
+ <xsl:when test="para">
+ <xsl:for-each select="para|screen|programlisting|itemizedlist|orderedlist">
+ <xsl:apply-templates select="."/>
+
+ <xsl:if test="position() != last()">
+ <xsl:text>
</xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:when>
+
+ <!-- Oops. sect1 contains elements we do not yet handle. -->
+ <xsl:otherwise>
+ <xsl:message>template match="sect1": Encountered
+ <<xsl:value-of select="name(.)"/>>.</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:text>
</xsl:text>
+</xsl:template>
+
+<xsl:template match="qandaset">
+ <xsl:param name="sectno"/>
+
+ <xsl:apply-templates select="qandaentry">
+ <xsl:with-param name="sectno" select="$sectno"/>
+ </xsl:apply-templates>
+</xsl:template>
+
+<xsl:template match="qandaentry">
+ <xsl:param name="sectno"/>
+
+ <xsl:variable name="questno" select="position()"/>
+
+ <xsl:variable name="prefix">
+ <xsl:value-of select="$sectno"/>
+ <xsl:text>.</xsl:text>
+ <xsl:value-of select="$questno"/>
+ <xsl:text>. </xsl:text>
+ </xsl:variable>
+ <xsl:variable name="prefix-length" select="string-length($prefix)"/>
+
+ <xsl:if test="$questno > 1">
+ <xsl:text>
</xsl:text>
+ <xsl:call-template name="ruler"/>
+ <xsl:text>
</xsl:text>
+ </xsl:if>
+
+ <xsl:apply-templates select="question">
+ <xsl:with-param name="prefix" select="$prefix"/>
+ <xsl:with-param name="indent" select="$prefix-length"/>
+ </xsl:apply-templates>
+
+ <xsl:text>
</xsl:text>
+
+ <xsl:apply-templates select="answer"/>
+</xsl:template>
+
+<xsl:template match="question">
+ <xsl:param name="prefix"/>
+ <xsl:param name="indent" select="0"/>
+
+ <xsl:for-each select="para|screen|programlisting">
+ <xsl:choose>
+ <xsl:when test="position() = 1 and $prefix">
+ <xsl:value-of select="$prefix"/>
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="indent" select="$indent"/>
+ <xsl:with-param name="dofirst" select="0"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="indent" select="$indent"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="position() != last()">
+ <xsl:text>
</xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="answer">
+ <xsl:param name="indent" select="0"/>
+
+ <xsl:for-each select="para|screen|programlisting|itemizedlist|orderedlist">
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="indent" select="$indent"/>
+ </xsl:apply-templates>
+
+ <xsl:if test="position() != last()">
+ <xsl:text>
</xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="para">
+ <xsl:param name="indent" select="0"/>
+ <xsl:param name="dofirst" select="1"/>
+
+ <xsl:for-each select="node()">
+ <xsl:choose>
+ <!-- Lists and blocks as children. -->
+ <xsl:when test="self::screen|self::programlisting|
+ self::itemizedlist|self::orderedlist">
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="indent" select="$indent"/>
+ </xsl:apply-templates>
+
+ <xsl:if test="position() != last()">
+ <xsl:text>
</xsl:text>
+ </xsl:if>
+ </xsl:when>
+
+ <!-- Text. Inline elements have been flattened by
+ untag-inline.xslt. -->
+ <xsl:when test="self::text()">
+ <xsl:choose>
+ <xsl:when test="position() = 1 and $dofirst = 0">
+ <xsl:apply-templates select="." mode="text:wrap">
+ <xsl:with-param name="width" select="$width"/>
+ <xsl:with-param name="indent" select="$indent"/>
+ <xsl:with-param name="dofirst" select="0"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="." mode="text:wrap">
+ <xsl:with-param name="width" select="$width"/>
+ <xsl:with-param name="indent" select="$indent"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+
+ <!-- Oops. para contains elements we do not yet handle. -->
+ <xsl:otherwise>
+ <xsl:message>template match="para": Encountered
+ <<xsl:value-of select="name(.)"/>>.</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="screen|programlisting">
+ <xsl:param name="indent" select="0"/>
+ <xsl:param name="dofirst" select="1"/><!-- ignored. -->
+
+ <xsl:variable name="myindent" select=" $indent + 2 " />
+
+ <xsl:apply-templates select="." mode="text:dump">
+ <xsl:with-param name="input" select="text()"/>
+ <xsl:with-param name="indent" select="$myindent"/>
+ </xsl:apply-templates>
+</xsl:template>
+
+<xsl:template match="itemizedlist">
+ <xsl:param name="indent" select="0"/>
+
+ <xsl:variable name="prefix" select=" '* ' "/>
+ <xsl:variable name="prefix-length" select="string-length($prefix)"/>
+
+ <xsl:for-each select="listitem">
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="prefix" select="$prefix"/>
+ <xsl:with-param name="indent" select="$prefix-length"/>
+ </xsl:apply-templates>
+
+ <xsl:if test="position() != last()">
+ <xsl:text>
</xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="orderedlist">
+ <xsl:param name="indent" select="0"/>
+
+ <xsl:for-each select="listitem">
+ <xsl:variable name="prefix">
+ <xsl:value-of select="position()"/>
+ <xsl:text>. </xsl:text>
+ </xsl:variable>
+ <xsl:variable name="prefix-length" select="string-length($prefix)"/>
+
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="prefix" select="$prefix"/>
+ <xsl:with-param name="indent" select="$prefix-length"/>
+ </xsl:apply-templates>
+
+ <xsl:if test="position() != last()">
+ <xsl:text>
</xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="listitem">
+ <xsl:param name="prefix"/>
+ <xsl:param name="indent" select="0"/>
+
+ <xsl:for-each select="para|screen|programlisting">
+ <xsl:choose>
+ <xsl:when test="position() = 1 and $prefix">
+ <xsl:value-of select="$prefix"/>
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="indent" select="$indent"/>
+ <xsl:with-param name="dofirst" select="0"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="indent" select="$indent"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+</xsl:template>
+
+<!-- Named utility templates. -->
+
+<xsl:template name="header">
+ <xsl:param name="input" select="0"/>
+ <xsl:variable name="input-length" select="string-length($input)"/>
+
+ <xsl:value-of select="$input"/>
+ <xsl:text>
</xsl:text>
+
+ <xsl:call-template name="str:dup">
+ <xsl:with-param name="input" select=" '~' "/>
+ <xsl:with-param name="count" select="$input-length"/>
+ </xsl:call-template>
+ <xsl:text>
</xsl:text>
+</xsl:template>
+
+<xsl:template name="ruler">
+ <xsl:call-template name="str:dup">
+ <xsl:with-param name="input" select=" '-' "/>
+ <xsl:with-param name="count" select="$width"/>
+ </xsl:call-template>
+ <xsl:text>
</xsl:text>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/docs/lib/str.dup.xslt b/docs/lib/str.dup.xslt
new file mode 100644
index 0000000..564b342
--- /dev/null
+++ b/docs/lib/str.dup.xslt
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:str="http://www.ora.com/XSLTCookbook/namespaces/strings">
+
+<!-- This file was copied with some adaptations from the examples
+supplied with the XSLT Cookbook by Sal Mangano, (C) 2003 O'Reilly &
+Associates, ISBN 0-596-00372-2. -->
+
+ <xsl:template name="str:dup">
+ <xsl:param name="input"/>
+ <xsl:param name="count" select="1"/>
+
+ <xsl:choose>
+ <xsl:when test="not($count) or not($input)"/>
+ <xsl:when test="$count = 1">
+ <xsl:value-of select="$input"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- If $count is odd append an extra copy of input -->
+ <xsl:if test="$count mod 2">
+ <xsl:value-of select="$input"/>
+ </xsl:if>
+ <!-- Recursively apply template after doubling input and
+ halving count -->
+ <xsl:call-template name="str:dup">
+ <xsl:with-param name="input" select="concat($input,$input)"/>
+ <xsl:with-param name="count" select="floor($count div 2)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/docs/lib/str.find-last.xslt b/docs/lib/str.find-last.xslt
new file mode 100644
index 0000000..2700fd3
--- /dev/null
+++ b/docs/lib/str.find-last.xslt
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" id="str.find-last"
+ xmlns:str="http://www.ora.com/XSLTCookbook/namespaces/strings" extension-element-prefixes="str">
+
+<!-- This file was copied with some adaptations from the examples
+supplied with the XSLT Cookbook by Sal Mangano, (C) 2003 O'Reilly &
+Associates, ISBN 0-596-00372-2. -->
+
+<xsl:template name="str:substring-before-last">
+ <xsl:param name="input"/>
+ <xsl:param name="substr"/>
+
+ <xsl:if test="$substr and contains($input, $substr)">
+ <xsl:variable name="temp" select="substring-after($input, $substr)" />
+ <xsl:value-of select="substring-before($input, $substr)" />
+ <xsl:if test="contains($temp, $substr)">
+ <xsl:value-of select="$substr" />
+ <xsl:call-template name="str:substring-before-last">
+ <xsl:with-param name="input" select="$temp" />
+ <xsl:with-param name="substr" select="$substr" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+
+</xsl:template>
+
+
+<xsl:template name="str:substring-after-last">
+ <xsl:param name="input"/>
+ <xsl:param name="substr"/>
+
+ <!-- Extract the string which comes after the first occurence -->
+ <xsl:variable name="temp" select="substring-after($input,$substr)"/>
+
+ <xsl:choose>
+ <xsl:when test="$substr and contains($temp,$substr)">
+ <xsl:call-template name="str:substring-after-last">
+ <xsl:with-param name="input" select="$temp"/>
+ <xsl:with-param name="substr" select="$substr"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$temp"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="xsl:stylesheet[@id='str.find-last'] | xsl:include[@href='str.find-last.xslt'] " >
+<tests>
+
+<!-- before -->
+ <test name="str:substring-before-last with no occurences of yes">
+ <xsl:call-template name="str:substring-before-last">
+ <xsl:with-param name="input" select=" 'No occurences' "/>
+ <xsl:with-param name="substr" select=" 'yes' "/>
+ </xsl:call-template>
+ </test>
+
+ <test name="str:substring-before-last starts with yes">
+ <xsl:call-template name="str:substring-before-last">
+ <xsl:with-param name="input" select=" 'yes occurences' "/>
+ <xsl:with-param name="substr" select=" 'yes' "/>
+ </xsl:call-template>
+ </test>
+
+ <test name="str:substring-before-last starts with yes and ends with yes">
+ <xsl:call-template name="str:substring-before-last">
+ <xsl:with-param name="input" select=" 'yes occurences yes' "/>
+ <xsl:with-param name="substr" select=" 'yes' "/>
+ </xsl:call-template>
+ </test>
+
+ <test name="str:substring-before-last 3 yes">
+ <xsl:call-template name="str:substring-before-last">
+ <xsl:with-param name="input" select=" 'yesyesyes' "/>
+ <xsl:with-param name="substr" select=" 'yes' "/>
+ </xsl:call-template>
+ </test>
+ <test name="str:substring-before-last empty input">
+ <xsl:call-template name="str:substring-before-last">
+ <xsl:with-param name="substr" select=" 'yes' "/>
+ </xsl:call-template>
+ </test>
+
+ <test name="str:substring-before-last empty search">
+ <xsl:call-template name="str:substring-before-last">
+ <xsl:with-param name="input" select=" 'No occurences' "/>
+ </xsl:call-template>
+
+ </test>
+
+ <test name="str:substring-before-last large">
+ <xsl:call-template name="str:substring-before-last">
+ <xsl:with-param name="input" select=" 'yesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyesyes' "/>
+ <xsl:with-param name="substr" select=" 'yes' "/>
+ </xsl:call-template>
+
+
+ </test>
+
+<!-- after -->
+
+ <test name="str:substring-after-last with no occurences of yes">
+ <xsl:call-template name="str:substring-after-last">
+ <xsl:with-param name="input" select=" 'No occurences' "/>
+ <xsl:with-param name="substr" select=" 'yes' "/>
+ </xsl:call-template>
+ </test>
+
+ <test name="str:substring-after-last starts with yes">
+ <xsl:call-template name="str:substring-after-last">
+ <xsl:with-param name="input" select=" 'yes occurences' "/>
+ <xsl:with-param name="substr" select=" 'yes' "/>
+ </xsl:call-template>
+ </test>
+
+ <test name="str:substring-after-last starts with yes and ends with yes">
+ <xsl:call-template name="str:substring-after-last">
+ <xsl:with-param name="input" select=" 'yes occurences yes' "/>
+ <xsl:with-param name="substr" select=" 'yes' "/>
+ </xsl:call-template>
+ </test>
+
+ <test name="str:substring-after-last 3 yes">
+ <xsl:call-template name="str:substring-after-last">
+ <xsl:with-param name="input" select=" 'yesyesyes' "/>
+ <xsl:with-param name="substr" select=" 'yes' "/>
+ </xsl:call-template>
+ </test>
+
+ <test name="str:substring-after-last 3 yes then no">
+ <xsl:call-template name="str:substring-after-last">
+ <xsl:with-param name="input" select=" 'yesyesyesno' "/>
+ <xsl:with-param name="substr" select=" 'yes' "/>
+ </xsl:call-template>
+ </test>
+
+ <test name="str:substring-after-last empty input">
+ <xsl:call-template name="str:substring-after-last">
+ <xsl:with-param name="substr" select=" 'yes' "/>
+ </xsl:call-template>
+ </test>
+
+ <test name="str:substring-after-last empty search">
+ <xsl:call-template name="str:substring-after-last">
+ <xsl:with-param name="input" select=" 'No occurences' "/>
+ </xsl:call-template>
+
+ </test>
+
+</tests>
+</xsl:template>
+
+ <xsl:template match="text()"/>
+
+</xsl:stylesheet>
diff --git a/docs/lib/text.justify.xslt b/docs/lib/text.justify.xslt
new file mode 100644
index 0000000..a6a8992
--- /dev/null
+++ b/docs/lib/text.justify.xslt
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:str="http://www.ora.com/XSLTCookbook/namespaces/strings"
+ xmlns:text="http://www.ora.com/XSLTCookbook/namespaces/text" extension-element-prefixes="text">
+
+<!-- This file was copied with some adaptations from the examples
+supplied with the XSLT Cookbook by Sal Mangano, (C) 2003 O'Reilly &
+Associates, ISBN 0-596-00372-2. -->
+
+<xsl:include href="str.dup.xslt"/>
+
+<xsl:template name="text:justify">
+ <xsl:param name="value" />
+ <xsl:param name="width" select="10"/>
+ <xsl:param name="align" select=" 'left' "/>
+
+ <!-- Truncate if too long -->
+ <xsl:variable name="output" select="substring($value,1,$width)"/>
+
+ <xsl:choose>
+ <xsl:when test="$align = 'left'">
+ <xsl:value-of select="$output"/>
+ <xsl:call-template name="str:dup">
+ <xsl:with-param name="input" select=" ' ' "/>
+ <xsl:with-param name="count" select="$width - string-length($output)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$align = 'right'">
+ <xsl:call-template name="str:dup">
+ <xsl:with-param name="input" select=" ' ' "/>
+ <xsl:with-param name="count" select="$width - string-length($output)"/>
+ </xsl:call-template>
+ <xsl:value-of select="$output"/>
+ </xsl:when>
+ <xsl:when test="$align = 'center'">
+ <xsl:call-template name="str:dup">
+ <xsl:with-param name="input" select=" ' ' "/>
+ <xsl:with-param name="count" select="floor(($width - string-length($output)) div 2)"/>
+ </xsl:call-template>
+ <xsl:value-of select="$output"/>
+ <xsl:call-template name="str:dup">
+ <xsl:with-param name="input" select=" ' ' "/>
+ <xsl:with-param name="count" select="ceiling(($width - string-length($output)) div 2)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>INVALID ALIGN</xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/docs/lib/text.wrap.xslt b/docs/lib/text.wrap.xslt
new file mode 100644
index 0000000..e77819e
--- /dev/null
+++ b/docs/lib/text.wrap.xslt
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" id="text.wrap"
+ xmlns:str="http://www.ora.com/XSLTCookbook/namespaces/strings"
+ xmlns:text="http://www.ora.com/XSLTCookbook/namespaces/text" exclude-result-prefixes="text">
+
+<!-- This file was copied with some adaptations from the examples
+supplied with the XSLT Cookbook by Sal Mangano, (C) 2003 O'Reilly &
+Associates, ISBN 0-596-00372-2. -->
+
+<xsl:include href="str.find-last.xslt"/>
+<xsl:include href="text.justify.xslt"/>
+
+<xsl:template match="node() | @*" mode="text:wrap" name="text:wrap">
+ <xsl:param name="input" select="normalize-space()"/>
+ <xsl:param name="width" select="70"/>
+ <xsl:param name="indent" select="0"/>
+ <xsl:param name="dofirst" select="1"/>
+ <xsl:param name="align" select=" 'left' "/>
+
+ <xsl:variable name="effective" select="$width - $indent"/>
+
+ <xsl:if test="$input">
+ <xsl:variable name="line">
+ <xsl:choose>
+ <xsl:when test="string-length($input) > $effective">
+ <xsl:variable name="candidate-line" select="substring($input,1,$effective)"/>
+ <xsl:choose>
+ <xsl:when test="contains($candidate-line,' ')">
+ <xsl:call-template name="str:substring-before-last">
+ <xsl:with-param name="input" select="$candidate-line"/>
+ <xsl:with-param name="substr" select=" ' ' "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$candidate-line"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$input"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:if test="$line">
+ <xsl:if test="$dofirst">
+ <xsl:call-template name="str:dup">
+ <xsl:with-param name="input" select=" ' ' "/>
+ <xsl:with-param name="count" select="$indent"/>
+ </xsl:call-template>
+ </xsl:if>
+
+ <xsl:call-template name="text:justify">
+ <xsl:with-param name="value" select="$line"/>
+ <xsl:with-param name="width" select="$effective"/>
+ <xsl:with-param name="align" select="$align"/>
+ </xsl:call-template>
+ <xsl:text>
</xsl:text>
+ </xsl:if>
+
+ <xsl:call-template name="text:wrap">
+ <xsl:with-param name="input" select="substring($input, string-length($line) + 2)"/>
+ <xsl:with-param name="width" select="$width"/>
+ <xsl:with-param name="indent" select="$indent"/>
+ <xsl:with-param name="align" select="$align"/>
+ </xsl:call-template>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template match="node() | @*" mode="text:dump" name="text:dump">
+ <xsl:param name="input" select="text()"/>
+ <xsl:param name="indent" select="0"/>
+
+ <xsl:if test="$input">
+ <xsl:variable name="line">
+ <xsl:choose>
+ <xsl:when test="contains($input, '
')">
+ <xsl:value-of select="substring-before($input, '
')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$input"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:if test="$line">
+ <xsl:call-template name="str:dup">
+ <xsl:with-param name="input" select=" ' ' "/>
+ <xsl:with-param name="count" select="$indent"/>
+ </xsl:call-template>
+ <xsl:value-of select="$line"/>
+ <xsl:text>
</xsl:text>
+ </xsl:if>
+
+ <xsl:call-template name="text:dump">
+ <xsl:with-param name="input" select="substring-after($input, '
')"/>
+ <xsl:with-param name="indent" select="$indent"/>
+ </xsl:call-template>
+ </xsl:if>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/docs/lib/untag-inline.xslt b/docs/lib/untag-inline.xslt
new file mode 100644
index 0000000..ea553a5
--- /dev/null
+++ b/docs/lib/untag-inline.xslt
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- sgml -*- -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:include href="copy.xslt"/>
+
+<xsl:strip-space elements="*"/>
+
+<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
+
+<!-- Preprocess a docbook/xml file, replacing elements that are to be -->
+<!-- formatted inline with the corresponding text. -->
+
+<xsl:template match="literal|computeroutput">
+ <xsl:value-of select="text()"/>
+</xsl:template>
+
+<xsl:template match="ulink">
+ <xsl:variable name="url" select="normalize-space(@url)"/>
+ <xsl:variable name="text" select="normalize-space(text())"/>
+
+ <xsl:if test="$text and $text != $url">
+ <xsl:text>'</xsl:text><xsl:value-of select="$text"/><xsl:text>' </xsl:text>
+ </xsl:if>
+ <xsl:text><</xsl:text><xsl:value-of select="$url"/><xsl:text>></xsl:text>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/docs/xml/FAQ.xml b/docs/xml/FAQ.xml
index f8b8c12..25f44b0 100644
--- a/docs/xml/FAQ.xml
+++ b/docs/xml/FAQ.xml
@@ -305,21 +305,27 @@
<para>Some example sub-traces:</para>
- <para>With debug information and unstripped (best):</para>
+ <itemizedlist>
+ <listitem>
+ <para>With debug information and unstripped (best):</para>
<programlisting>
Invalid write of size 1
at 0x80483BF: really (malloc1.c:20)
by 0x8048370: main (malloc1.c:9)
</programlisting>
+ </listitem>
- <para>With no debug information, unstripped:</para>
+ <listitem>
+ <para>With no debug information, unstripped:</para>
<programlisting>
Invalid write of size 1
at 0x80483BF: really (in /auto/homes/njn25/grind/head5/a.out)
by 0x8048370: main (in /auto/homes/njn25/grind/head5/a.out)
</programlisting>
+ </listitem>
- <para>With no debug information, stripped:</para>
+ <listitem>
+ <para>With no debug information, stripped:</para>
<programlisting>
Invalid write of size 1
at 0x80483BF: (within /auto/homes/njn25/grind/head5/a.out)
@@ -327,17 +333,20 @@
by 0x42015703: __libc_start_main (in /lib/tls/libc-2.3.2.so)
by 0x80482CC: (within /auto/homes/njn25/grind/head5/a.out)
</programlisting>
+ </listitem>
- <para>With debug information and -fomit-frame-pointer:</para>
+ <listitem>
+ <para>With debug information and -fomit-frame-pointer:</para>
<programlisting>
Invalid write of size 1
at 0x80483C4: really (malloc1.c:20)
by 0x42015703: __libc_start_main (in /lib/tls/libc-2.3.2.so)
by 0x80482CC: ??? (start.S:81)
</programlisting>
+ </listitem>
- <para>A leak error message involving an unloaded shared object:</para>
-
+ <listitem>
+ <para>A leak error message involving an unloaded shared object:</para>
<programlisting>
84 bytes in 1 blocks are possibly lost in loss record 488 of 713
at 0x1B9036DA: operator new(unsigned) (vg_replace_malloc.c:132)
@@ -346,6 +355,8 @@
by 0x1D65E007: ???
by 0x8049EE6: main (main.cpp:24)
</programlisting>
+ </listitem>
+ </itemizedlist>
</answer>
</qandaentry>