XLP Release 2
A.J.Hurst
Version 2.4.0
20080822:162322
Table of Contents
1. Introduction
1.1 Background
Literate Programming is a technique developed by Donald
Knuth, and described in his seminal paper in the Computer
Journal, 1984. It is both a software process and a suite of
tools for supporting that process. Programs written as
literate programs go through two (conceptually) independent
processes known as tangling and weaving.
Tangling creates the actual source code for input to a
compiler; weaving creates a documentation file suitable for
processing by a document system such as TeX.
More modern versions of literate program tools have attempted
to decouple the N x M combinatorial explosion created by the
choice of N programming languages and M documentation systems,
by restricting the markup and presentational mechanisms. The
tool currently in use in the work described here is such a
tool: the markup of source documents is done in XML, and the
documentation device is handled by XML translators. This
reduces the problem from an N x M to an N + M one, where N =
1.
XLP started life as a literate programming tool developed
from nuweb, and modified to develop XML code rather than LaTeX
or HTML. It was extensively rewritten during 2003 to use an
XSLT script rather than a C program to do the tangle and weave
processes, so the code is completely platform independent. To
run the code, only an XSLT translator (any flavour) is needed. The
price for this conversion (apart from time) has been the loss
of a number of "syntactic sugar" features, but I don't
miss them much. They are gradually being reintroduced,
generally in an improved form.
This new version is currently used to define and maintain a
range of software that I use on a regular basis.
1.2 Synopsis
This program, or rather, suite of programs, performs literate
program analysis and construction over a literate program
file. Programs in any language can be constructed, as can
documentation in any form. There are two phases to the use of
the suite, each of which is handled by an XSLT file. The
first of these phases uses a common XSLT file, while the
second phase uses an XSLT file that is specific to the form of
documentation being generated. For naming purposes, the first
phase is known as the warp phase, while the second
phase is called the weft phase.
The first phase (warp phase) comprises two passes,
corresponding to the tangling and weaving operations of all
literate program systems. It is important to make the
distinction between phase and pass in this
context. This phase is performed by the litprog.xsl
file. Each of the passes within this phase is handled by a
mode (in the XSL technical sense). The first pass, or
mode=tangle, generates the tangled program files, and
the second pass mode=weave generates an intermediate
file of the woven documentation file.
This documentation file is then processed in phase two of the
suite (the weft phase) by a second XSLT file, which is
documentation language specific. There is only one pass in
the weft phase. Currently, there are two such XSLT files,
lit2html.xsl for HTML documentation, and
lit2tex.xsl for TeX documentation. The output of
this phase is an HTML or TeX document, suitable for processing
by a browser (HTML) or by the TeX system itself (TeX). There
are a standard set of macros (based upon plain TeX) that are
assumed by the TeX translator, and which are available
separately.
All three XSLT files (litprog.xsl for the warp phase,
and lit2html.xsl and lit2tex.xsl for the weft
phase) are described in this document, which is itself a
literate program document.
1.3 The source file structure (XLP files)
The warp (first) phase of XLP reads the input XLP file, a
document type definition for which is given in section 5, The litprog Document
Type Definition (see also the file <litprog.dtd 6.1>). In BNF, the grammar of this file is as
follows (terminals are represented in CAPITALS, although the
corresponding element names are lower case, except for
TableOfContents):
litxmlfile = TITLE AUTHOR VERSION DATE
( section | misc ) *
DocumentHistory?
.
section = TITLE (p | o | d | subsection | misc)* .
subsection = TITLE (p | o | d | subsubsection | misc)* .
subsubsection = TITLE (p | o | d | subsubsubsection | misc)* .
subsubsubsection = TITLE (p | o | d)* .
misc = TABLEOFCONTENTS | FILELIST | MACROLIST | IDENTIFIERLIST
.
o = (CODE | u | v)* .
d = (CODE | u | v)* .
u = USE-REFERENCE .
v = VARIABLE-REFERENCE .
p = (TEXT | u | v)* .
DocumentHistory = Modified* .
Modified = DATE AUTHOR VERSION COMMENT .
See the User Manual
(following) for explanations of these elements.
1.4 Some base definitions
Here we define some important system parameters.
The first one is the location for the
library of XSL translations for various base templates. Update
this to point at the directory used to store templates such as
basic2html.xsl, basic2tex.xsl, and so on (see
for example, <lit2html.xsl 4.1> and
<lit2tex.xsl 4.33>).
<LIBXSL 1.1> = file:///home/ajh/lib/xsl
The following list defines all documentation template names.
All the names of documentation templates that are passed
straight through phase one (the warp phase) should be
added to this list, in order to avoid any "No warp-tangle
template" or "No warp-weave template" errors.
<litprog: define documentation template name list 1.2> =<xsl:variable name="docos">
<xsl:text>|author|b|c|col|comment|date|description|dq|</xsl:text>
<xsl:text>DocumentHistory|em|i|itemize|item|</xsl:text>
<xsl:text>le|Modified|narrower|</xsl:text>
<xsl:text>section|smiley|subsection|subsubsection|</xsl:text>
<xsl:text>subsubsubsection|paragraph|parm|table|TableOfContents|TeX|</xsl:text>
<xsl:text>term|td|th|title|tr|tt|uri|verb|verbatim|version|</xsl:text>
<xsl:text></xsl:text>
</xsl:variable>
2. User Manual
2.1 Overview of an XLP Document
An XLP document is a well-formed XML document. For readers
unfamiliar with XML, an XML document consists of a set of
elements, each flagged with a starting and ending tag, and
containing other elements, text, or both. Tags are defined by
writing the element name within angle brackets
<>, and the ending or closing tag has a leading
/ before the name. The term "well-formed XML
document" means that all elements are strictly nested, and
there is one outer level or root element.
<p>An example of a <b>paragraph</b> element, with nested <b>bold</b> elements</p>
The structure of the XLP document is formally defined
elsewhere, but an informal description will suffice here. The
basic outline of an XLP literate program looks like this:
<?xml version="1.0"?>
<!DOCTYPE litprog SYSTEM "/home/ajh/lib/dtd/litprog.dtd">
<litprog>
... literate program content goes in here ...
</litprog>
The first line of this program is a declaration that the
document is an XML document, constructed according to the
rules of XML version 1.0. This line is optional. The
second line is mandatory, and specifies that the rules of this
particular XML document, an XLP (or XML Literate Program)
document, are defined in the
separate file /home/ajh/lib/dtd/litprog.dtd.
The top-level or root element is a litprog element. This
element contains all the literate programming content. Such
content comes in two basic forms: documentation and code.
Each of these two forms have their own set of elements. There
is limited mixing of these elements, but generally an element
is either pure code or pure documentation. These forms are
described in the next section.
The basic model is that the document has the structure of a
typical descriptive article: opening components are followed
by substantive components, which are then followed by closing
components. Opening material are things like title, author,
date, which are required (if present) to be in a particular
order. The substantive content is encapsulated within
sections, each contain possible subsections, subsubsections,
and even subsubsubsections. Closing material includes things
like tables of content and indices.
Interspersed within the document are the code chunks, which
are file and code definitions. These may generally appear at
any point in the document, but it is their document order that
defines how they are assembled into the overall code
files. Readers familiar with other literate programming
systems may view this arrangement as a conventional
alternation of code and documentation fragments, with a
superimposed document structure.
2.2 Documentation in an XLP Document
Documentation in an XLP document is built from the set of
elements:
author b c col comment date description dq DocumentHistory
em filelist i identlist item le macrolist Modified p section
subsection subsubsection subsubsubsection table
TableOfContents term TeX td th title tr uri verb verbatim
version
Generally, these are constrained as to where
they can appear, but some can be used in arbitrary order.
Their usage is described in the following list, where the
annotation "*" is used to mark those that are
constrained.
- author*
- The author of this literate program. Can appear in two
places: at the top level, after the title element,
or within a Modified element, after a date
element.
- b
- markup text in bold face
- c
- markup text in code (typewriter) face
- col
- The column specification element, used in tables. It is
an empty element, with one attribute, width, defining
the width of a column as a fraction (<=1.0) of the total
page width.
- comment*
- The last element within a Modified element,
describing the nature of this particular
modification.
- d
- define a code chunk (see code)
- date*
- Can appear after version in the document
header, or as the first element in a Modified
element. It defines the date of the document, or
modification, respectively.
- DocumentHistory*
- A sequence of Modified elements, each of which
contains a date, author, version,
comment sequence of nested elements, each of which
documents the appropriate data about the various
modifications to this literate program. If it is
present, it must be the last element in a litprog
element.
- dq
- place double quotes around text
- filelist*
- A place marker to indicate where the list of files
generated should be inserted. It can appear at the top
level, or within a (sub)section.
- i
- markup text in italic face
- identifierlist*
- A place marker to indicate where the table of identifier
cross references should be inserted. It can appear at the
top level, or within a (sub)section.
- item*
- Can only appear within a description,
enumerate or itemize element, where it defines
one of the list items.
- le
- The less than or equal to symbol, <=.
- macrolist*
- A place marker to indicate where the list of macro names
should be inserted. It can appear at the top level, or
within a (sub)section.
- Modified*
- contains date, author, version,
comment elements, defining attributes of each
modification of the literate program.
- o
- define an output file (see code)
- p
- markup a paragraph
- section*
- Can only appear as a top-level element within the
litprog element.
- subsection*
- Can only appear within a section element.
- subsubsection*
- Can only appear within a subsection element.
- subsubsubsection*
- Can only appear within a subsubsection element.
- TableOfContents*
- Defines the place in the literate program where the
table of contents should be inserted. Can only appear at the
top level of the document, or within a section or
sub(sub...)section.
- term*
- Can only appear within a description element,
where it defines the (documentation) term being
defined.
- TeX
- The TeX token.
- td*
- As for HTML, within a table row element (tr),
defines a table data cell.
- th*
- As for HTML, within a table row element (tr),
defines a table header cell.
- title*
- When this element appears immediately after the
opening litprog tag, it is the title of this
literate program. Within a section or sub..section, it is
the title of the corresponding (sub..)section.
- tr*
- As for HTML, defines a table row.
- u
- A use reference to a code fragment. In documentation,
during the weaving pass, the reference becomes a link to
the code fragment, unless an optional attribute
expand is present and non-empty, when the reference
is expanded to its value. In code fragments, during the
tangling pass, the reference is replaced by the expanded
code fragment, as a (recursive) macro expansion.
- uri
- markup a Universal Resource Indicator
- v
- markup a variable (see code)
- verb
- markup verbatim text in-line
- verbatim
- markup verbatim text as a display (paragraph) item.
- version*
- Can appear in either the literate program header
or a Modified element. In both cases, it follows
an author element.
2.3 Code in an XLP Document
Code elements in an XLP literate program take two forms: file
definitions, and code chunks. Code chunks are fragments of
code used to build other code chunks or file definitions. For
this reason, the distinction between code chunks and file
definitions is often blurred, and they are referred to
collectively as code chunks. It should be obvious from the
context when it is important for the distinction to be made.
The code fragments are assembled through a process of
expansion (in technical terms, a "macro expansion")
that replaces references to other chunks by the code defined
in that chunk.
Code within a chunk can be quite arbitrary: there is no
interpretation or parsing of the code, except for XML
elements. Remember that the document is one large XML file,
and text within a code chunk is interpreted according to the
rules of XML. In practice, this means that the characters
"less than" (<) and "ampersand"
(&) have special meanings, and must be
escaped if they are used within code text. The escape
sequences are < and &
respectively.
Alternatively, the block quoting mechanism of XML can be
used. This entails surrounding the entire text that needs to
be quoted with the special sequences <![CDATA[
and ]]>. All text within these
quote sequences will appear verbatim. It follows that if the
sequence ]]> is to appear within the
quoted text, it too must be escaped, for example with
]]>]<![CDATA[]]>]<![CDATA[>]]>><![CDATA[
(the three separate characters, each surrounded by close then
open escape sequences). Strictly speaking, breaking the
sequence once would suffice, but this is a more
sesquipedalian approach
!
There are three code elements that may appear within
documentation (and already mentioned above):
- o
- An output element. This element defines a file
built by the literate program. The name of the file is
given by the value of a required attribute, the file
attribute. Note that more than one file element may have
the same name, when the file is considered to be the
concatenation of all similarly named chunks, arranged document
in order. All file definitions are collected into a
list accessed by the element filelist.
- d
- A code chunk defining element. The name of the
code chunk (by which it may be referenced) is given by the
value of a required attribute name. Note that more
than one code chunk may have the same name, when the code
chunk is considered to be the concatenation of all similarly
named chunks, arranged in document order. It is an error to
have names that are common to both code and file chunks.
All code definitions and uses are collected into a list
accessed by the element macrolist.
- v
- A variable element. This may be either a
defining occurrence, or a using occurrence, although within
documentation it is unlikely to be the former. Within
documentation, is usually used to highlight discussion
about a particular variable within the code. See below for
use within a code chunk. All variable definitions and uses
are collected into a list accessed by the element
identifierlist.
There are three elements that may appear within code chunks (i.e.,
within o or d elements). These are:
- u
-
A code chunk using element. This element is normally
empty, and defines the point at which a code chunk is
expanded into the current code chunk or output file. It has
a mandatory attribute name, which cross-references
the corresponding code chunk(s).
It may also have the optional attribute include,
which, when it has the value no, negates the
inclusion of the reference code chunk. This may be used
to "comment out" code, while still retaining the
documentation surrounding the excluded code. The
documentation is annotated accordingly.
A second optional attribute is expand, which
normally has the default value no. When explicitly
set to yes however, it forces the expansion of the
chunk into the document at that point. When called within
code chunks, this is the default behaviour, but when
called within documentation chunks, this changes the
representation of the macro from a link to the expanded
text of the macro. This is useful for defining macros
used within the documentation, rather than code generation
(for example, the date at the head of this document was
generated in this way). Warning: multiple chunks
are not handled correctly, as of version 2.2.0.
- v
- A variable element. See also use within
documentation, above. This may be a defining occurrence, or
a using occurrence, depending upon the optional attribute
var. If var has the (default) value
use (var="use"), then the occurrence is
marked up as a use of the variable. If the attribute has
the value def (var="def"), then the
occurrence is marked up as a defining occurrence. Note that
there is no analysis of the content of the variable
element, which allows arbitrary lexical forms of variable
names to be used. (But be wary of languages such as perl,
or bash shell scripts, which use \$ and other signs to
flag usage of the variable. These annotations should be
excluded from the variable name.)
- com
- A comment element. This element may be used to
markup in-line comments within the code. How the comment is
rendered depends upon the subsequent weft phase, but it will
presumably capitalize upon the contextual position. (Aside:
the tangling of the output file could conceivable include
the comment as an in-line comment - the difficulty here is
that the literate programming system has no knowledge of the
syntactic form of such in-line comments.)
2.4 Running XLP
To use the XLP literate programming system, you need an XSLT
translator. I use xsltproc (see LibXML),
but other XSLT translators will work just as well with the
files described herein. In what follows, we assume the
xsltproc translator.
There are two phases to running the system, called the warp
and weft phases. The warp phase performs tangling and
weaving, and generates an intermediate file for the weft
phase. To run the warp phase, use the call:
xsltproc litprog.xsl yourXLPfile.xlp >yourXLPfile.xml
For the weft phase (document generation), use the call
xsltproc lit2html.xsl yourXLPfile.xml >yourXLPfile.html
This is for HTML generation. For TeX documentation, replace
the two occurrences of html in the above line
with tex.
Note that if documentation is not required, the weft phase
may be omitted.
3. The warp, or literate program phase
This phase is responsible for reading and translating the
source xlp file. There are two passes to this phase, known as
the tangle and weave passes. Each pass performs a
sweep over the input file, applying templates to the elements as
they are seen. In the first pass, the XSLT mode of
mode="tangle" is used; in the second pass,
mode="weave" is used.
In the tangle pass, all documentation chunks are effectively
ignored, while file chunks cause a new document to be written,
containing the code within the file chunk, with all code chunk
references expanded out through a process of macro
expansion. Each file chunk creates a new text document named
with the given file name, which can then be used for further
processing by compilers, etc..
In the weave pass, a new translation of the source XLP document
is made. This new document is given a .xml extension,
and its contents consist of much the same contents as are in
the original XLP file, but with some elements renamed, and
additional housekeeping information issued to assist the final
weft phase.
3.1 Templates defined in litprog.xsl
| name |
attributes |
mode |
purpose |
| / |
(none) |
(none) |
The root node |
| litprog |
(none) |
tangle |
tangle all output files |
| d |
name |
tangle |
define a code chunk named "@name" |
| o |
name |
tangle |
build a new output file, called "@name" |
| d/v | o/v |
var |
tangle |
define (var="def") or reference
(var="use") a variable (default is reference). |
| p |
|
tangle |
paragraph documentation, ignored |
| d/com|o/com |
|
tangle |
comment with a code/file chunk: ignored |
| u |
|
tangle |
chunk use, expand the referenced code chunk in-line |
| * |
|
tangle |
undefined element, issue a warning message |
| litprog |
|
weave |
Perform the weave pass |
| d | o |
|
weave |
document a code chunk (d) or output file (o) |
| d/v | o/v |
|
weave |
document a variable markup (either use or definition,
defined by element attribute var="use" (default) or
var="def") in code (d/v) or file
(o/v) |
| d/com | o/com |
|
weave |
document a comment markup in code (d/com)
or file (o/com) |
| v |
|
weave |
document a value reference to a code or file chunk |
| u |
expand |
weave |
document a use reference to a code or file chunk. If
the attribute expand is present and non-empty, replace
this element by the expanded code definition. |
| p |
|
weave |
document a paragraph of literate program text |
| section |
|
weave |
document a section of the literate program text |
| * |
|
weave |
undefined element, issue a warning message |
3.2 litprog.xsl: the warp translator
"litprog.xsl" 3.1 =
This is the XSLT transformer script for phase one, the
warp phase of the literate programming suite. It is
responsible for tangling the output documents, and
weaving the XML document for input to the weft
phase.
3.2.1 litprog: root template
<litprog: root template 3.2> =<xsl:template match="/">
<xsl:message><xsl:text>Tangling ...</xsl:text></xsl:message>
<xsl:apply-templates mode="tangle"/>
<xsl:message><xsl:text>Weaving ...</xsl:text></xsl:message>
<xsl:element name="LitprogXML">
<xsl:apply-templates mode="weave"/>
</xsl:element>
</xsl:template>
The root template is responsible for the two passes of
tangling and weaving. Note that the tangle phase generates
its own documents (in the XML technical sense), while all
the documentation for the weft phase is generated as the
"default" output of this phase by the tangle pass.
3.2.2 litprog: define variables
<litprog: define variables 3.3> =<xsl:variable name="
crossrefs">
<xsl:for-each select="//d|//o">
<xsl:value-of select="concat(@name,@file)"/>
<xsl:text>@</xsl:text>
<xsl:number format="1" level="multiple" count="section"/>
<xsl:text>.</xsl:text>
<xsl:number from="section" level="any" count="d|o"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="
premacro">
<xsl:text>[[</xsl:text>
<xsl:text>[[</xsl:text>
</xsl:variable>
<xsl:variable name="
postmacro">
<xsl:text>]]</xsl:text>
<xsl:text>]]</xsl:text>
</xsl:variable>
<litprog: define documentation template name list 1.2>
The variable crossrefs is set to a value built from
a newline separated list of code and file chunks, with each
entry (or line) in the form name@location, where
name is the name of the chunk or file, and
location is the chunk number defining that file or
chunk.
The value stored as the value of a chunk number is
multi-valued, in the form s.p, where s is the
section number and p is the part number within the
section.
The two variables premacro and postmacro
define the escape sequences used respectively to start and
end a macro text.
3.2.3 litprog: define script parameters
The script parameters give some control over the behaviour
of the literate programming system. Currently two are
defined: Verbose and machine.
Verbose can be set to a non-negative integer. When
0 (the default), no tracing information is given.
Progressively higher values give more information about the
progress of tangling and weaving.
machine is used to define the target of
compilation. Not currently interpreted.
<litprog: define script parameters 3.4> =<xsl:param name="
Verbose">1</xsl:param>
<xsl:param name="
machine">ararat</xsl:param>
3.2.4 litprog: define procedure templates
Define all the callable templates for the warp phase.
<litprog: define procedure templates 3.5> =
3.2.5 litprog: do-replace template
<litprog: do-replace template 3.6> =<xsl:template name="
do-replace">
<xsl:param name="
text"/>
<xsl:param name="
replace"/>
<xsl:param name="
by"/>
<xsl:choose>
<xsl:when test="contains($text,$replace)">
<xsl:value-of select="substring-before($text,$replace)"/>
<xsl:value-of select="$
by"/>
<xsl:call-template name="
do-replace">
<xsl:with-param name="
text"
select="substring-after($
text,$
replace)"/>
<xsl:with-param name="
replace"
select="$
replace"/>
<xsl:with-param name="
by"
select="$
by"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$
text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
do-replace is a procedure with three parameters,
text, replace, and by. Multiple
occurrences of replace in the string text are
recursively replaced by the value of by, and this
rebuilt value is returned as the value of the template
call.
3.2.6 litprog: count-trailing-blanks template
<litprog: count-trailing-blanks template 3.7> =<xsl:template name="
count-trailing-blanks">
<xsl:param name="
string"></xsl:param>
<xsl:param name="
count"></xsl:param>
<xsl:choose>
<xsl:when test="substring($string,string-length($string))=' '">
<xsl:call-template name="count-trailing-blanks">
<xsl:with-param name="string"
select="substring($string,1,
string-length($string)-1)"/>
<xsl:with-param name="count" select="$count+1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$count"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
count-trailing-blanks, as its name suggests,
(recursively) counts the trailing blanks in the string
parameter string and returns this value. The initial
value of the parameter count should be set as 0. The
actual value returned by the procedure is this initial value
plus the number of trailing blanks, hence the need to
initialize it correctly.
3.2.7 litprog: lookupchunkno template
<litprog: lookupchunkno template 3.8> =<xsl:template name="
lookupchunkno">
<xsl:param name="chunkname"></xsl:param>
<xsl:call-template name="lookupchunknoR">
<xsl:with-param name="chunkname" select="$chunkname"/>
<xsl:with-param name="table" select="$
crossrefs"/>
<xsl:with-param name="sep"></xsl:with-param>
</xsl:call-template>
</xsl:template>
Chunk referenced in 3.5Chunk defined in 3.8,
3.9
lookupchunkno returns a list of the chunk numbers of
a named chunk. The name of the required chunk is passed as
the parameter chunkname, and the procedure calls an
auxiliary recursive template lookupchunknoR to find
the actual chunk numbers.
<litprog: lookupchunkno template 3.9> =<xsl:template name="lookupchunknoR">
<xsl:param name="chunkname"></xsl:param>
<xsl:param name="table"></xsl:param>
<xsl:param name="sep"></xsl:param>
<xsl:variable name="find">
<xsl:value-of select="substring-after($table,concat($chunkname,'@'))"/>
</xsl:variable>
{Note 3.9.1}
<litprog: lookupchunknoR debug message 1 3.10> **** Chunk omitted!
<xsl:if test="$find!=''">
{Note 3.9.2}
<xsl:value-of select="$sep"/>
<xsl:value-of select="substring-before($find,'
')"/>
<xsl:call-template name="lookupchunknoR">
<xsl:with-param name="chunkname" select="$chunkname"/>
<xsl:with-param name="table" select="$find"/>
<xsl:with-param name="sep"><xsl:text>,</xsl:text></xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
Chunk referenced in 3.5Chunk defined in 3.8,
3.9
- {Note 3.9.1}
- The first key part of the lookup algorithm.
Jump straight to the match in the table of the required
chunk name. If it is there, the find variable is set to
the remainder of the table starting with the match. If it
is not there, the find variable will be empty.
- {Note 3.9.2}
- The second key part of the lookup
algorithm. Return the first part of the find string (it is
the desired chunk number, and use the (remainder of the)
find string as the lookup table for the next
recursion. The algorithm is order n, where n is the number
of matches in the cross reference table for chunkname.
lookupchunknoR takes as parameters the required
chunkname, a partially searched table of cross references,
and the separator string used to separate matches for the
chunk name. It returns a sep separated list of values that
match the second half of all (chunkname, chunkno) pairs in
the cross reference list.
The sep separator is passed as a parameter, since on the
first call, it must be empty. Otherwise we would return
lists of the form ,4,10,15 rather than
4,10,15.
<litprog: lookupchunknoR debug message 1 3.10> =<xsl:message>
<xsl:text>lookupchunknoR(</xsl:text>
<xsl:value-of select="$chunkname"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="$table"/>
<xsl:text>,'</xsl:text>
<xsl:value-of select="$sep"/>
<xsl:text>')</xsl:text>
</xsl:message>
This chunk is conditionally included to provide debugging
information about the progress of the chunk number lookup
procedure.
3.2.8 litprog: lookup template
<litprog: lookup template 3.11> =<xsl:template name="lookup">
<xsl:param name="key"></xsl:param>
<xsl:param name="table"></xsl:param>
<xsl:variable name="pkey">
<xsl:value-of select="$premacro"/>
<xsl:value-of select="$key"/>
<xsl:value-of select="$postmacro"/>
<xsl:value-of select="$premacro"/>
</xsl:variable>
<xsl:variable name="tail" select="substring-after($table,$pkey)"/>
<xsl:variable name="retval">
<xsl:value-of select="substring-before($tail,$postmacro)"/>
</xsl:variable>
<xsl:if test="$Verbose>=2">
<xsl:message>
<xsl:text>lookup:</xsl:text>
<xsl:text>
 key=</xsl:text>
<xsl:value-of select="$key"/>
<xsl:text>
 table=</xsl:text>
<xsl:value-of select="$table"/>
<xsl:text>
 pkey=</xsl:text>
<xsl:value-of select="$pkey"/>
<xsl:text>
 tail=</xsl:text>
<xsl:value-of select="$tail"/>
<xsl:text>
 retval=</xsl:text>
<xsl:value-of select="$retval"/>
<xsl:text>
</xsl:text>
</xsl:message>
</xsl:if>
<xsl:if test="$tail!=''">
<xsl:value-of select="$retval"/>
</xsl:if>
</xsl:template>
3.2.9 litprog: substparms template
This callable template takes a text string representing a
chunk definition, and substitutes for any formal parameters
used within the chunk. Formal parameters are found by
virtue of them being enclosed within 4 sets of square
brackets, as defined by the global variables
premacro and postmacro.
Note that there is a further complication in that formal
parameters nested inside actual parameters have been
escaped, by using 4 sets of curly brackets. These escapings
must be restored before parameter expansion can begin. This
is done by substituting square brackets for the curly ones.
<litprog: substparms template 3.12> =<xsl:template name="substparms">
<xsl:param name="text"></xsl:param>
<xsl:param name="parmtable"></xsl:param>
<substparms: unescape the escaped formal parameters 3.13>
<xsl:variable name="head">
<xsl:value-of select="substring-before($etext,$premacro)"
disable-output-escaping="no"/>
</xsl:variable>
<xsl:variable name="tail">
<xsl:value-of select="substring-after($etext,$postmacro)"
disable-output-escaping="no"/>
</xsl:variable>
<xsl:variable name="parmname">
<xsl:value-of select="substring-before(
substring-after($etext,$premacro),
$postmacro)"
disable-output-escaping="no"/>
</xsl:variable>
<xsl:if test="$Verbose>=2">
<xsl:message>
<xsl:text>substparms: text=</xsl:text>
<xsl:value-of select="$etext"/>
<xsl:text>
substparms: parmtable=</xsl:text>
<xsl:value-of select="$parmtable"/>
<xsl:text>
substparms: parmname=</xsl:text>
<xsl:value-of select="$parmname"/>
</xsl:message>
</xsl:if>
<xsl:variable name="value">
<xsl:call-template name="lookup">
<xsl:with-param name="key" select="$parmname"/>
<xsl:with-param name="table" select="$parmtable"/>
</xsl:call-template>
</xsl:variable>
<xsl:if test="$Verbose>=2">
<xsl:message>
<xsl:text>substparms: </xsl:text>
<xsl:value-of select="$parmname"/>
<xsl:text>=</xsl:text>
<xsl:value-of select="$value"/>
</xsl:message>
</xsl:if>
<substparms: build result string recursively 3.14>
<xsl:if test="$Verbose>=2">
<xsl:message>
<xsl:text>substparms: result=</xsl:text>
<xsl:value-of select="$result"/>
</xsl:message>
</xsl:if>
<xsl:value-of select="$result"/>
</xsl:template>
This is a challenging routine, as evidenced by the number
of debug components built in! Basically, we split the
incoming text string into a pre-formal parameter part (the
head), and a post-formal parameter part (the
tail), as indicated by the premacro and
postmacro strings of square brackets. The formal parameter
itself is looked up in the parameter table, and a result
string is built by concatenating the pre-string, the
parameter value, and a recursively expanded post-string.
<substparms: unescape the escaped formal parameters 3.13> =<xsl:variable name="etext">
<xsl:call-template name="do-replace">
<xsl:with-param name="text">
<xsl:call-template name="do-replace">
<xsl:with-param name="text">
<xsl:value-of select="$text"/>
</xsl:with-param>
<xsl:with-param name="replace">
<xsl:text>{{</xsl:text><xsl:text>{{</xsl:text>
</xsl:with-param>
<xsl:with-param name="by">
<xsl:value-of select="$premacro"/>
</xsl:with-param>
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="replace">
<xsl:text>}}</xsl:text><xsl:text>}}</xsl:text>
</xsl:with-param>
<xsl:with-param name="by">
<xsl:value-of select="$postmacro"/>
</xsl:with-param>
</xsl:call-template>
</xsl:variable>
We build a new version of the text string parameter in the
variable etext. Two nested calls on the
do-replace template are made, one to replace the
premacro escape, and one to replace the postmacro
escape.
<substparms: build result string recursively 3.14> =<xsl:variable name="result">
<xsl:choose>
<xsl:when test="$head=''">
<xsl:value-of select="$etext"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$head"/>
<xsl:value-of select="$value"/>
<xsl:if test="$tail!=''">
<xsl:call-template name="substparms">
<xsl:with-param name="text">
<xsl:value-of select="$tail"/>
</xsl:with-param>
<xsl:with-param name="parmtable" select="$parmtable"/>
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Build the result of macro expansion recursively. The (first) macro parameter is chopped out, leaving a head and tail string. The parameter is looked up to find its replacement value, and the result returned is the head string, the replacement text value, and the recursive expansion of the tail string.
3.3 litprog: the tangle pass
<litprog: the tangle pass 3.15> =
3.3.1 litprog: tangle all litprog files
<litprog: tangle all litprog files 3.16> =<xsl:template match="litprog" mode="tangle">
<xsl:for-each select="/litprog//o">
{Note 3.16.1}
<xsl:variable name="thisfile" select="@file"/>
<xsl:if test="not(preceding::o[@file=$thisfile])">
{Note 3.16.2}
<xsl:message>
{Note 3.16.3}
<xsl:text>Writing file "</xsl:text>
<xsl:value-of select="@file"/>
<xsl:text>"</xsl:text>
</xsl:message>
<xsl:document href="{$thisfile}" omit-xml-declaration="yes"
indent="yes" method="text">
{Note 3.16.4}
<xsl:apply-templates select="." mode="tangle"/>
{Note 3.16.5}
<xsl:for-each
select="following::o[@file=$thisfile]">
{Note 3.16.6}
<xsl:apply-templates select="." mode="tangle"/>
</xsl:for-each>
</xsl:document>
</xsl:if>
</xsl:for-each>
</xsl:template>
- {Note 3.16.1}
- see point 1
- {Note 3.16.2}
- see
point 2
- {Note 3.16.3}
- see point 3
- {Note 3.16.4}
- see point 4
- {Note 3.16.5}
- see
point 5
- {Note 3.16.6}
- see point 6
To tangle a complete litprog, we scan through all file
chunk definitions, expanding them into an appropriately
named file. Issue a message as each one is processed.
(version 2.4.0) There was a bug here: multiple chunks of
"o" elements did not get appended, since each one
started a new document, thus overwriting the previous chunk.
Here the new logic is this:
- Do all tangling by searching for "o" elements.
- For each one found, check if it is the first one
with this particular file name. If it isn't, ignore it.
- If it is, issue a message that we are tangling the
file, then ....
- ... start a new document with this file name ...
- ... tangle this chunk and ...
- ... tangle all following "o" chunks with the same filename.
3.3.2 litprog: tangle a single file definition chunk
<litprog: tangle a single file definition chunk 3.17> =<xsl:template match="o" mode="tangle">
<xsl:variable name="chunk">
<xsl:apply-templates mode="tangle"/>
</xsl:variable>
<xsl:variable name="chunks">
<xsl:choose>
<xsl:when test='starts-with($chunk,"
")'>
<xsl:value-of select="substring($chunk,2)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$chunk"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$chunks"/>
</xsl:template>
This is done in a manner similar to code chunk tangling.
Here, only the leading new line character is removed. Why?
Good question. When I have an answer, I'll add it to this
documentation.
3.3.3 litprog: tangle a code definition
<litprog: tangle a code definition 3.18> =
A code chunk is tangled in three stages.
Firstly, the chunk has any nested elements resolved and
expanded, as appropriate. This expansion is saved in the
local variable chunki (initial chunk).
<tangle code, initial chunk 3.19> =<xsl:variable name="chunki">
<xsl:apply-templates mode="tangle"/>
</xsl:variable>
Secondly, if the chunk ends in a newline character and the
trim attribute is set to yes, the trailing newline is
removed. The result of this operation is saved in the
variable chunke (end trimmed chunk).
<tangle code, end trimmed chunk 3.20> =<xsl:variable name="chunke">
<xsl:choose>
<xsl:when test='substring($chunki,string-length($chunki)) = "
"
and @trim="yes"'>
<xsl:value-of select="substring($chunki,1,string-length($chunki)-1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$chunki"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Thirdly, a leading newline character is removed, if
present. The result of this operation is saved in the
variable chunkes (start and end trimmed chunk).
<tangle code, start and end trimmed chunk 3.21> =<xsl:variable name="chunkes">
<xsl:choose>
<xsl:when test='starts-with($chunke,"
")'>
<xsl:value-of select="substring($chunke,2)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$chunke"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
The resultant value is returned as the result of tangling
this code fragment or chunk.
<tangle code, debugging 3.22> =<xsl:message>
<xsl:text>Depth of 'd' node = </xsl:text>
<xsl:value-of select="count(ancestor::*)"/>
<xsl:text></xsl:text>
</xsl:message>
<xsl:variable name="chunk">
<xsl:for-each select="*/text()">
<xsl:message><xsl:value-of select="name()"/></xsl:message>
<xsl:apply-templates select="." mode="tangle"/>
</xsl:for-each>
</xsl:variable>
<xsl:message><xsl:value-of select="$chunk"/></xsl:message>
<xsl:variable name="chunki">
<xsl:value-of select="$chunk"/>
<xsl:call-template name="do-replace">
<xsl:with-param name="text" select="$chunk"/>
<xsl:with-param name="replace">=</xsl:with-param>
<xsl:with-param name="by">:=</xsl:with-param>
</xsl:call-template>
</xsl:variable>
3.3.4 litprog: tangle variable declarations
<litprog: tangle variable declarations 3.23> =<xsl:template match="d/v | o/v" mode="tangle">
<xsl:apply-templates mode="tangle"/>
</xsl:template>
In tangle mode, variable definitions and uses are basically
passed straight through to the weft phase.
3.3.5 litprog: discard documentation in tangle mode
<litprog: discard documentation in tangle mode 3.24> =<xsl:template match="p" mode="tangle">
</xsl:template>
<xsl:template match="d/com|o/com" mode="tangle">
</xsl:template>
All documentation fragments are ignored in tangle mode.
3.3.6 litprog: tangle all chunks into a single use
<litprog: tangle all chunks into a single use 3.25> =
A use call on a chunk name has been made, which must be
expanded into the document-order concatenation of all code
chunk definitions with the same name.
3.3.6.1 litprog: replace the machine parameter in chunk name
<litprog: replace the machine parameter in chunk name 3.26> =<xsl:variable name="chunkname">
<xsl:call-template name="do-replace">
<xsl:with-param name="text" select="@name"/>
<xsl:with-param name="replace">{$machine}</xsl:with-param>
<xsl:with-param name="by" select="$machine"/>
</xsl:call-template>
</xsl:variable>
This bit is a hack. I really want a method to replace key
strings with parameters, but there isn't anything I can
think of other than using this "do-replace" with a
hard-coded substitution string. Incidentally, do-replace
is copied from Michael Kay's excellent book "XSLT
Programmer's Reference".
3.3.6.2 litprog: check whether to include a use chunk
<litprog: check whether to include a use chunk 3.27> =<xsl:variable name="include">
<xsl:choose>
<xsl:when test="@include">
<xsl:value-of select="@include"/>
</xsl:when>
<xsl:otherwise>yes</xsl:otherwise>
</xsl:choose>
</xsl:variable>
"include" is an attribute that allows the user to comment
out chunks of code, simply by putting an 'include="no"'
attribute into the chunk call. It defaults to "yes", so
set up that default.
3.3.6.3 litprog: save use parameters
<litprog: save use parameters 3.28> =<xsl:variable name="actuals" select="*"/>
3.3.6.4 litprog: compute indentations for use expansion
<litprog: compute indentations for use expansion 3.29> =<xsl:variable name="text-string">
<xsl:value-of select="string(preceding-sibling::text()[1])"/>
</xsl:variable>
<xsl:variable name="count-blanks">
<xsl:call-template name="count-trailing-blanks">
<xsl:with-param name="string" select="$text-string"/>
<xsl:with-param name="count">0</xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="blanks">
<xsl:value-of select="substring($text-string,
string-length($text-string)-$count-blanks+1,
$count-blanks)"/>
</xsl:variable>
<xsl:variable name="indent" select="$blanks"/>
Now some stuff to determine indentation. This is heavy
XML. We first pull in the most recent text node in the
tree. This will have the indentation blanks before this
call on 'u', and so we count and extract those blanks.
Following that processing, the value of variable
$blanks will be inserted after all new
lines in the text generated by this call on 'u'. That,
together with the indentation that appeared before the
call itself, will mean that all lines of the replacement
text will have the same indentation, assuming that they
are themselves aligned - any additional indentation is
preserved.
3.3.6.5 litprog: check definitions for non-use
<litprog: check definitions for non-use 3.30> =<xsl:if test="count(/litprog//d[@name=$chunkname])=0">
<xsl:message>
<xsl:text>No definition of <</xsl:text>
<xsl:value-of select="$chunkname" disable-output-escaping="no"/>
<xsl:text>></xsl:text>
</xsl:message>
</xsl:if>
Now check that we have some definitions of this chunk.
Count them and issue a warning if the count is zero.
3.3.6.6 litprog: include raw text and expand indentation
<litprog: include raw text and expand indentation 3.31> =
Firstly, cross reference this call on the chunk.
Then the real code expansion takes place. We collect up
all matching chunk definitions, and add them in document
order.
If the chunk is to be included, build the raw text of it,
and then expand all newlines with indentation as computed
above.
<litprog: include text and expand: start message 3.32> =<xsl:if test="$Verbose>1">
<xsl:message terminate="no">
<xsl:text>Using chunk named "</xsl:text>
<xsl:value-of select="$chunkname"/>
<xsl:text>" </xsl:text>
<xsl:for-each select="$actuals">
<xsl:value-of select="string(.)"/>
</xsl:for-each>
</xsl:message>
</xsl:if>
debug this call on expanding a chunk
<litprog: include text and expand: loop message 3.33> =<xsl:if test="$Verbose>1">
<xsl:message terminate="no">
<xsl:text>Matches are "</xsl:text>
<xsl:value-of select="@name" disable-output-escaping="no"/>
<xsl:text>"</xsl:text>
</xsl:message>
</xsl:if>
Show all the chunks that match this use instance.
<litprog: include text and expand: define parmtable 3.34> =<xsl:variable name="parmtable">
<xsl:if test="$Verbose>=2">
<xsl:message>
<xsl:text>building parmtable,parms=</xsl:text>
<xsl:value-of select="$actuals"/>
</xsl:message>
</xsl:if>
<xsl:for-each select="$actuals">
<xsl:value-of select="$premacro"/>
<xsl:value-of select="./@name"/>
<xsl:value-of select="$postmacro"/>
<xsl:value-of select="$premacro"/>
<xsl:call-template name="do-replace">
<xsl:with-param name="text">
<xsl:call-template name="do-replace">
<xsl:with-param name="text">
<xsl:apply-templates mode="tangle"/>
</xsl:with-param>
<xsl:with-param name="replace">
<xsl:value-of select="$premacro"/>
</xsl:with-param>
<xsl:with-param name="by">
<xsl:text>{{</xsl:text><xsl:text>{{</xsl:text>
</xsl:with-param>
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="replace">
<xsl:value-of select="$postmacro"/>
</xsl:with-param>
<xsl:with-param name="by">
<xsl:text>}}</xsl:text><xsl:text>}}</xsl:text>
</xsl:with-param>
</xsl:call-template>
<xsl:value-of select="$postmacro"/>
</xsl:for-each>
</xsl:variable>
<xsl:if test="$Verbose>=2">
<xsl:message>parmtable=<xsl:value-of select="$parmtable"/></xsl:message>
</xsl:if>
Build the parameter table. This is a string where each
actual parameter is surrounded by the pre- and post- macro
strings (as defined by the variables premacro and
postmacro respectively), then concatenated together
in parameter document order.
<litprog: include text and expand: define rawchunk 3.35> =<xsl:variable name="rawchunk">
<xsl:apply-templates select="." mode="tangle"/>
</xsl:variable>
Build the raw chunk corresponding to this use instance match.
<litprog: include text and expand: define raw2 3.36> =<xsl:variable name="raw2">
<xsl:call-template name="substparms">
<xsl:with-param name="text">
<xsl:value-of select="$rawchunk"/>
</xsl:with-param>
<xsl:with-param name="parmtable" select="$parmtable"/>
</xsl:call-template>
</xsl:variable>
Now expand the actual parameters into the raw chunk,
replacing all formal parameters.
<litprog: include text and expand: replace text 3.37> =<xsl:call-template name="do-replace">
<xsl:with-param name="text">
<xsl:value-of select="$raw2"/>
</xsl:with-param>
<xsl:with-param name="replace">
<xsl:text>
</xsl:text>
</xsl:with-param>
<xsl:with-param name="by">
<xsl:text>
</xsl:text>
<xsl:value-of select="$indent"/>
</xsl:with-param>
</xsl:call-template>
Now rebuild the replacement text by expanding all
newlines with their appropriate indentation. This is to
preserve the indentation established in the actual call on
this chunk.
3.3.7 litprog: default tangle template
<litprog: default tangle template 3.38> =<xsl:template match="*" mode="tangle">
<xsl:variable name="check">
<xsl:text>|</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>|</xsl:text>
</xsl:variable>
<xsl:if test="$Verbose and not(contains($docos,$check))">
<xsl:message terminate="no">
<xsl:text>No warp-tangle template for </xsl:text>
<xsl:value-of select="name()"/>
</xsl:message>
</xsl:if>
<xsl:element name="{name()}">
<xsl:apply-templates mode="tangle"/>
</xsl:element>
</xsl:template>
This is the default tangle template, invoked if there is no
other template defined to handled this element. Provide an
error message in the event of no tangle template.
3.4 litprog: the weave pass
<litprog: the weave pass 3.39> =
3.4.1 litprog: weave a litprog
<litprog: weave a litprog 3.40> =<xsl:template match="litprog" mode="weave">
<xsl:apply-templates mode="weave"/>
</xsl:template>
Not really much to this, since the whole litprog file is
scanned in document order, generating the intermediate
documentation file as we go.
3.4.2 litprog: weave a code or file definition
<litprog: weave a code or file definition 3.41> =<xsl:template match="d | o" mode="weave">
<xsl:variable name="chunkname">
<xsl:choose>
<xsl:when test="name()='d'">
<xsl:value-of select="@name"/>
</xsl:when>
<xsl:when test="name()='o'">
<xsl:value-of select="@file"/>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:element name="CODE">
<xsl:attribute name="type">
<xsl:choose>
<xsl:when test="name()='d'">define</xsl:when>
<xsl:when test="name()='o'">file</xsl:when>
</xsl:choose>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="$chunkname"/>
</xsl:attribute>
<xsl:attribute name="number">
<xsl:number format="1" level="multiple" count="section|DocumentHistory"/>
<xsl:text>.</xsl:text>
<xsl:number from="section" level="any" count="d|o"/>
</xsl:attribute>
<xsl:attribute name="defines">
<xsl:call-template name="lookupchunkno">
<xsl:with-param name="chunkname">
<xsl:value-of select="$chunkname"/>
</xsl:with-param>
</xsl:call-template>
</xsl:attribute>
<xsl:attribute name="uses">
{Note 3.41.1}
<xsl:variable name="defnode" select="."/>
<xsl:for-each select="child::u">
<xsl:if test="position()>1">
<xsl:text>, </xsl:text>
</xsl:if>
<litprog: d-weave debug message-1 3.42> **** Chunk omitted!
<xsl:call-template name="lookupchunkno">
<xsl:with-param name="chunkname" select="@name"/>
</xsl:call-template>
</xsl:for-each>
</xsl:attribute>
<xsl:apply-templates mode="weave"/>
</xsl:element>
<litprog: weave a code comment 3.43>
</xsl:template>
- {Note 3.41.1}
-
Build the uses attribute list, by scanning all child
u elements, and looking up their chunk numbers.
The d | o template, in the weave mode, builds a CODE
element in the woven .xml file, CODE elements define code
fragments. Such elements can have the following attributes:
- type
- for a d fragment, the type is define,
indicating a chunk definition. For an o fragment, the
type is file.
- name
- The name of the code chunk or fragment. For example,
the name of the following code chunk is litprog:
d | o-weave template. For a file fragment, the name
attribute gives the name of the file.
- number
- code chunks are numbered in sequence from the
beginning, for cross referencing purposes.
<litprog: d-weave debug message-1 3.42> =<xsl:message>
<xsl:text>Macro "</xsl:text>
<xsl:value-of select="$defnode/@name"/>
<xsl:text>" references "</xsl:text>
<xsl:value-of select="./@name"/>
<xsl:text>", </xsl:text>
<xsl:call-template name="lookupchunkno">
<xsl:with-param name="chunkname" select="@name"></xsl:with-param>
</xsl:call-template>
</xsl:message>
Generate a helpful debug message to show what other
fragments this code chunk uses.
<litprog: weave a code comment 3.43> =<xsl:if test='./com'>
<xsl:element name='NOTES'>
<xsl:for-each select="./com">
{Note 3.43.1}
<xsl:element name="NOTE">
<xsl:attribute name="HREF">
<xsl:value-of select="position()"/>
</xsl:attribute>
<xsl:apply-templates mode="weave"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:if>
- {Note 3.43.1}
-
Scan through all in-line comments (such as this one), and
for each one, generate a NOTE element, cross
referenced by the ordinal number of this comment within
the chunk.
<litprog: d/com|o/com-weave template 3.44> =<xsl:template match="d/com | o/com" mode="weave">
<xsl:variable name="mypos">
<xsl:value-of select="count(preceding-sibling::com)+1"/>
</xsl:variable>
<xsl:element name="COMMENT">
<xsl:attribute name="HREF">
<xsl:value-of select="$mypos"/>
</xsl:attribute>
</xsl:element>
</xsl:template>
This template, d/com|o/com, handles
comments with code fragments in the weave pass. The comment
itself is handled later, but for the moment, we just insert
a forward reference to it as a link in the current code
fragment. The reference is identified by the ordinal
position of the comment within this code fragment.
3.4.3 litprog: weave a variable markup
The elements 'u' (use) and 'v' (value) both refer to 'd'
(define) elements elsewhere in the document. The difference
is that in weave mode 'u' inserts a hot link to the actual
definition, whereas 'v' inserts the actual value defined in
the 'd' element. This is equivalent to macro expansion, and
is what happens to 'u' elements in tangle mode. In tangle
mode, 'v' elements are ignored. In other words, 'v'
elements are only relevant to document fragments.
<litprog: weave a variable markup 3.45> =<xsl:template match="v" mode="weave">
<xsl:choose>
<xsl:when test="@var='use' or not(@var)">
<xsl:element name="VAR">
<xsl:attribute name="VAR">use</xsl:attribute>
<xsl:value-of select="."/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="NAME">
<xsl:value-of select="@name"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<litprog: weave a variable markup 3.46> =<!-- handle variable markup -->
<xsl:template match="d/v | o/v" mode="weave">
<xsl:element name="VAR">
<xsl:attribute name="VAR">
<xsl:choose>
<xsl:when test="@var">
<xsl:value-of select="@var"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>use</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:if test="@name">
<xsl:attribute name="NAME">
<xsl:value-of select="@name"/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
3.4.4 litprog: u-weave template
The u-weave template is responsible for inserting a
link to the definition of the referenced code fragment,
in-line in the documentation. Note that at this stage, the
include parameter is simply passed on: it is not
interpreted as to whether the code fragment is actally
included until the documentation construction phase.
<litprog: u-weave template 3.47> =<xsl:template match="u" mode="weave">
<xsl:element name="USE">
<xsl:attribute name="NAME">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:if test="@expand">
<xsl:attribute name="EXPAND">
<xsl:value-of select="@expand"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@include">
<xsl:attribute name="INCLUDE">
<xsl:value-of select="@include"/>
</xsl:attribute>
</xsl:if>
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="name()='name' or name()='expand'">
</xsl:when>
<xsl:when test="name()='formal'">
<xsl:element name="formal">
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:value-of select="."/>
</xsl:element>
</xsl:when>
<xsl:when test="name()='actual'">
<xsl:element name="actual">
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:apply-templates mode="weave"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:element>
<xsl:if test="$Verbose>1">
<xsl:message>
<xsl:text>Macro "</xsl:text>
<xsl:value-of select="normalize-space(@name)"/>
<xsl:text>" referenced in weave mode in "</xsl:text>
<xsl:value-of select="ancestor::d/@name"/>
<xsl:text>"</xsl:text>
</xsl:message>
</xsl:if>
</xsl:template>
<litprog: u-weave template 3.48> =<xsl:template match="formal" mode="weave">
<xsl:element name="formal">
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:apply-templates mode="weave"/>
</xsl:element>
</xsl:template>
3.4.5 litprog: p-weave template
<litprog: p-weave template 3.49> =<xsl:template match="p" mode="weave">
<P><xsl:apply-templates mode="weave"/></P>
</xsl:template>
3.4.6 litprog: section-weave template
<litprog: section-weave template 3.50> =<xsl:template match="section" mode="weave">
<xsl:element name="section">
<xsl:choose>
<xsl:when test="@numbers">
<xsl:attribute name="numbers">
<xsl:value-of select="@numbers"/>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="numbers">yes</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="@newpage">
<xsl:attribute name="newpage">
<xsl:value-of select="@newpage"/>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="newpage">yes</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<xsl:attribute name="xref">
<xsl:value-of select="translate(./title,' ?():.,-','')"
disable-output-escaping="no"/>
</xsl:attribute>
<xsl:apply-templates mode="weave"/>
</xsl:element>
</xsl:template>
<xsl:template match="subsection" mode="weave">
<xsl:element name="subsection">
<xsl:choose>
<xsl:when test="@numbers">
<xsl:attribute name="numbers">
<xsl:value-of select="@numbers"/>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="numbers">no</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="@newpage">
<xsl:attribute name="newpage">
<xsl:value-of select="@newpage"/>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="newpage">no</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<xsl:attribute name="xref">
<xsl:value-of select="translate(./title,' ?():.,-','')"
disable-output-escaping="no"/>
</xsl:attribute>
<xsl:apply-templates mode="weave"/>
</xsl:element>
</xsl:template>
<xsl:template match="subsubsection" mode="weave">
<xsl:element name="subsubsection">
<xsl:attribute name="xref">
<xsl:value-of select="translate(./title,' ?():.,-','')"
disable-output-escaping="no"/>
</xsl:attribute>
<xsl:apply-templates mode="weave"/>
</xsl:element>
</xsl:template>
3.4.7 litprog: listing templates
<litprog: listing templates 3.51> =<xsl:template match="
filelist" mode="weave">
<xsl:text>
</xsl:text>
<xsl:element name="filelist">
</xsl:element>
</xsl:template>
<xsl:template match="
macrolist" mode="weave">
<xsl:text>
</xsl:text>
<xsl:element name="macrolist">
<xsl:if test="@namewidth">
<xsl:attribute name="namewidth">
<xsl:value-of select="@namewidth"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@definewidth">
<xsl:attribute name="definewidth">
<xsl:value-of select="@definewidth"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@usewidth">
<xsl:attribute name="usewidth">
<xsl:value-of select="@usewidth"/>
</xsl:attribute>
</xsl:if>
</xsl:element>
</xsl:template>
<xsl:template match="
identifierlist" mode="weave">
<xsl:text>
</xsl:text>
<xsl:element name="IdentifierDefinitions">
<xsl:if test="@namewidth">
<xsl:attribute name="namewidth">
<xsl:value-of select="@namewidth"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@definewidth">
<xsl:attribute name="definewidth">
<xsl:value-of select="@definewidth"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@usewidth">
<xsl:attribute name="usewidth">
<xsl:value-of select="@usewidth"/>
</xsl:attribute>
</xsl:if>
</xsl:element>
</xsl:template>
3.4.8 litprog: default weave template
<litprog: default weave template 3.52> =<xsl:template match="*" mode="weave">
<xsl:variable name="check">
<xsl:text>|</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>|</xsl:text>
</xsl:variable>
<xsl:if test="$Verbose>0 and not(contains($docos,$check))">
<xsl:message terminate="no">
<xsl:text>No warp-weave template for </xsl:text>
<xsl:value-of select="name()"/>
</xsl:message>
</xsl:if>
<xsl:element name="{name()}">
<xsl:for-each select="@*">
<xsl:attribute name="{name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:apply-templates mode="weave"/>
</xsl:element>
</xsl:template>
This template handles all elements not elsewhere handled in
the weave pass. Note that a table of documentation related
elements is kept, and if an element name is matched in this
table, no warning message is issued. All elements, whether
flagged or not, are passed straight through. Note that all
the attributes must be copied as well.
In performing the table lookup, note that the separator
must be present at both ends. This is to ensure that names
that are substrings are not matched implicitly.
4. The weft, or documentation phase
This phase retranslates the output file from phase 1, the XML
file. There is a translation script for each class of
documentation processors. Two are defined here,
lit2html.xsl, for translation to HTML, and
lit2tex.xsl, for translation to TeX.
4.1 lit2html.xsl
"lit2html.xsl" 4.1 =<?xml version="1.0"?>
<!DOCTYPE xsl:transform PUBLIC "-//MONASH-CSSE//DTD stylesheet 1.0//EN"
"file:///home/ajh/lib/dtd/stylesheet.dtd">
<!-- This is for version 2 -->
<xsl:transform
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xinclude="http://www.w3.org/2001/XInclude"
>
<xsl:output method="html" encoding="ASCII"/>
<xsl:include href="
<LIBXSL 1.1>/numbered2html.xsl"/>
<xsl:include href="
<LIBXSL 1.1>/basic2html.xsl"/>
<xsl:include href="
<LIBXSL 1.1>/biblio2html.xsl"/>
<xsl:include href="
<LIBXSL 1.1>/tables2htm