.\" Automatically generated by Pod::Man 4.09 (Pod::Simple 3.35)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
. ds C`
. ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\"
.\" If the F register is >0, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.if !\nF .nr F 0
.if \nF>0 \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. if !\nF==2 \{\
. nr % 0
. nr F 2
. \}
.\}
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
. \" fudge factors for nroff and troff
.if n \{\
. ds #H 0
. ds #V .8m
. ds #F .3m
. ds #[ \f1
. ds #] \fP
.\}
.if t \{\
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
. ds #V .6m
. ds #F 0
. ds #[ \&
. ds #] \&
.\}
. \" simple accents for nroff and troff
.if n \{\
. ds ' \&
. ds ` \&
. ds ^ \&
. ds , \&
. ds ~ ~
. ds /
.\}
.if t \{\
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
. \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
. \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
. \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
. ds : e
. ds 8 ss
. ds o a
. ds d- d\h'-1'\(ga
. ds D- D\h'-1'\(hy
. ds th \o'bp'
. ds Th \o'LP'
. ds ae ae
. ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "MP4H 1"
.TH MP4H 1 "2018-06-27" "HTML Tools" "HTML Tools"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
mp4h \- Macro Processor for HTML Documents
.SH "VERSION"
.IX Header "VERSION"
This documentation describes mp4h version 1.3.1.
.SH "INTRODUCTION"
.IX Header "INTRODUCTION"
The \fBmp4h\fR software is a macro-processor specifically designed to deal
with \s-1HTML\s0 documents. It allows powerful programming constructs, with a
syntax familiar to \s-1HTML\s0 authors.
.PP
This software is based on
\&\fBMeta-HTML\fR \f(CW\*(C`\*(C'\fR,
written by Brian J. Fox, Even if both syntaxes look similar, source
code is completely different. Indeed, a subset of \fBMeta-HTML\fR was used
as a part of a more complex program, \fB\s-1WML\s0\fR
(Website Meta Language \f(CW\*(C`\*(C'\fR)
written by Ralf S. Engelschall and which I maintain since January 1999.
For licensing reasons, it was hard to hack \fBMeta-HTML\fR and so I decided
to write my own macro-processor.
.PP
Instead of rewriting it from scratch, I preferred using another
macro-processor engine. I chose
\&\s-1GNU\s0 \fBm4\fR \f(CW\*(C`\*(C'\fR,
written by Rene Seindal, because of its numerous advantages :
this software is stable, robust and very well documented.
This version of \fBmp4h\fR is derived from \s-1GNU\s0 \fBm4\fR version 1.4n, which is a
development version.
.PP
The \fBmp4h\fR software is not an \s-1HTML\s0 editor; its unique goal is to
provide an easy way to define its own macros inside \s-1HTML\s0 documents.
There is no plan to add functionalities to automagically produce valid
\&\s-1HTML\s0 documents, if you want to clean up your code or validate it,
simply use a post-processor like
tidy \f(CW\*(C`\*(C'\fR.
.SH "COMMAND LINE OPTIONS"
.IX Header "COMMAND LINE OPTIONS"
Optional arguments are enclosed within square brackets.
All option synonyms have a similar syntax, so when a long option accepts
an argument, short option do too.
.PP
Syntax call is
.PP
.Vb 1
\& mp4h [options] [filename [filename] ...]
.Ve
.PP
Options are described below. If no filename is specified, or if its
name is \f(CW\*(C`\-\*(C'\fR, then characters are read on standard input.
.SS "Operation modes"
.IX Subsection "Operation modes"
.IP "\fB\-\-help\fR display an help message and exit" 2
.IX Item "--help display an help message and exit"
.PD 0
.IP "\fB\-\-version\fR output \fBmp4h\fR version information and exit" 2
.IX Item "--version output mp4h version information and exit"
.IP "\fB\-E \-\-fatal\-warnings\fR stop execution after first warning" 2
.IX Item "-E --fatal-warnings stop execution after first warning"
.IP "\fB\-Q \-\-quiet \-\-silent\fR suppress some warnings for builtins" 2
.IX Item "-Q --quiet --silent suppress some warnings for builtins"
.ie n .IP "\fB\-S \-\-safety\-level=\f(CB""NUMBER""\fB\fR disable risky functions; 0 means no filtering, 1 disable ""execute"" and 2 disable this one too plus all filesystem related functions: ""file\-exists"", ""real\-path"", ""get\-file\-properties"", ""directory\-contents"" and ""include""." 2
.el .IP "\fB\-S \-\-safety\-level=\f(CBNUMBER\fB\fR disable risky functions; 0 means no filtering, 1 disable \f(CWexecute\fR and 2 disable this one too plus all filesystem related functions: \f(CWfile\-exists\fR, \f(CWreal\-path\fR, \f(CWget\-file\-properties\fR, \f(CWdirectory\-contents\fR and \f(CWinclude\fR." 2
.IX Item "-S --safety-level=NUMBER disable risky functions; 0 means no filtering, 1 disable execute and 2 disable this one too plus all filesystem related functions: file-exists, real-path, get-file-properties, directory-contents and include."
.PD
.SS "Preprocessor features"
.IX Subsection "Preprocessor features"
.ie n .IP "\fB\-I \-\-include=\f(CB""DIRECTORY""\fB\fR search this directory for includes and packages" 2
.el .IP "\fB\-I \-\-include=\f(CBDIRECTORY\fB\fR search this directory for includes and packages" 2
.IX Item "-I --include=DIRECTORY search this directory for includes and packages"
.PD 0
.ie n .IP "\fB\-D \-\-define=\f(CB""NAME\f(CB""[=VALUE]""\f(CB""\fB\fR set variable \s-1NAME\s0 to \s-1VALUE,\s0 or empty" 2
.el .IP "\fB\-D \-\-define=\f(CBNAME\f(CB[=VALUE]\f(CB\fB\fR set variable \s-1NAME\s0 to \s-1VALUE,\s0 or empty" 2
.IX Item "-D --define=NAME[=VALUE] set variable NAME to VALUE, or empty"
.ie n .IP "\fB\-U \-\-undefine=\f(CB""COMMAND""\fB\fR delete builtin \s-1COMMAND\s0" 2
.el .IP "\fB\-U \-\-undefine=\f(CBCOMMAND\fB\fR delete builtin \s-1COMMAND\s0" 2
.IX Item "-U --undefine=COMMAND delete builtin COMMAND"
.ie n .IP "\fB\-s \-\-synclines\fR generate `#line \s-1NO ""FILE""\s0' lines" 2
.el .IP "\fB\-s \-\-synclines\fR generate `#line \s-1NO ``FILE''\s0' lines" 2
.IX Item "-s --synclines generate `#line NO FILE' lines"
.PD
.SS "Parser features"
.IX Subsection "Parser features"
.ie n .IP "\fB\-c \-\-caseless=\f(CB""NUMBER""\fB\fR set case sensitiveness according to the bits of ""NUMBER"". A null bit means symbol is case sensitive, and bits are defined as followed: 0 for tags, 1 for variables and 2 for entities. Default value is 3, i.e. only entities are case sensitive." 2
.el .IP "\fB\-c \-\-caseless=\f(CBNUMBER\fB\fR set case sensitiveness according to the bits of \f(CWNUMBER\fR. A null bit means symbol is case sensitive, and bits are defined as followed: 0 for tags, 1 for variables and 2 for entities. Default value is 3, i.e. only entities are case sensitive." 2
.IX Item "-c --caseless=NUMBER set case sensitiveness according to the bits of NUMBER. A null bit means symbol is case sensitive, and bits are defined as followed: 0 for tags, 1 for variables and 2 for entities. Default value is 3, i.e. only entities are case sensitive."
.PD 0
.ie n .IP "\fB\-e \-\-encoding=\f(CB""NAME""\fB\fR specify document encoding. Valid options are `8bit' (default) or `utf8'." 2
.el .IP "\fB\-e \-\-encoding=\f(CBNAME\fB\fR specify document encoding. Valid options are `8bit' (default) or `utf8'." 2
.IX Item "-e --encoding=NAME specify document encoding. Valid options are `8bit' (default) or `utf8'."
.ie n .IP "\fB\-X \-\-expansion=\f(CB""NUMBER""\fB\fR set parser behaviour according to the bits of ""NUMBER""" 2
.el .IP "\fB\-X \-\-expansion=\f(CBNUMBER\fB\fR set parser behaviour according to the bits of \f(CWNUMBER\fR" 2
.IX Item "-X --expansion=NUMBER set parser behaviour according to the bits of NUMBER"
.PD
.PP
\&\s-1NUMBER\s0 is a combination of
.IP "\fB1\fR do not parse unknown tags" 2
.IX Item "1 do not parse unknown tags"
.PD 0
.IP "\fB2\fR unknown tags are assumed being simple" 2
.IX Item "2 unknown tags are assumed being simple"
.IP "\fB4\fR trailing star in tag name do not make this tag simple" 2
.IX Item "4 trailing star in tag name do not make this tag simple"
.IP "\fB8\fR an unmatched end tag closes all previous unmatched begin tags" 2
.IX Item "8 an unmatched end tag closes all previous unmatched begin tags"
.IP "\fB16\fR interpret backslashes as printf" 2
.IX Item "16 interpret backslashes as printf"
.IP "\fB32\fR remove trailing slash in tag attributes" 2
.IX Item "32 remove trailing slash in tag attributes"
.IP "\fB64\fR do not remove trailing star in tag name" 2
.IX Item "64 do not remove trailing star in tag name"
.IP "\fB128\fR do not remove leading star in tag name" 2
.IX Item "128 do not remove leading star in tag name"
.IP "\fB256\fR do not add a space before trailing slash in tag attributes" 2
.IX Item "256 do not add a space before trailing slash in tag attributes"
.IP "\fB1024\fR suppress warnings about bad nested tags" 2
.IX Item "1024 suppress warnings about bad nested tags"
.IP "\fB2048\fR suppress warnings about missing trailing slash" 2
.IX Item "2048 suppress warnings about missing trailing slash"
.PD
.PP
In version 1.3.1, default value is 3114=2+8+32+1024+2048.
.SS "Limits control"
.IX Subsection "Limits control"
.ie n .IP "\fB\-H \-\-hashsize=\f(CB""PRIME""\fB\fR set symbol lookup hash table size (default 509)" 2
.el .IP "\fB\-H \-\-hashsize=\f(CBPRIME\fB\fR set symbol lookup hash table size (default 509)" 2
.IX Item "-H --hashsize=PRIME set symbol lookup hash table size (default 509)"
.PD 0
.ie n .IP "\fB\-L \-nesting\-limit=\f(CB""NUMBER""\fB\fR change artificial nesting limit (default 250)" 2
.el .IP "\fB\-L \-nesting\-limit=\f(CBNUMBER\fB\fR change artificial nesting limit (default 250)" 2
.IX Item "-L -nesting-limit=NUMBER change artificial nesting limit (default 250)"
.PD
.SS "Debugging"
.IX Subsection "Debugging"
.ie n .IP "\fB\-d \-\-debug=\f(CB""FLAGS""\fB\fR set debug level (no \s-1FLAGS\s0 implies `aeq')" 2
.el .IP "\fB\-d \-\-debug=\f(CBFLAGS\fB\fR set debug level (no \s-1FLAGS\s0 implies `aeq')" 2
.IX Item "-d --debug=FLAGS set debug level (no FLAGS implies `aeq')"
.PD 0
.ie n .IP "\fB\-t \-\-trace=\f(CB""NAME""\fB\fR trace \s-1NAME\s0 when it will be defined" 2
.el .IP "\fB\-t \-\-trace=\f(CBNAME\fB\fR trace \s-1NAME\s0 when it will be defined" 2
.IX Item "-t --trace=NAME trace NAME when it will be defined"
.ie n .IP "\fB\-l \-\-arglength=\f(CB""NUMBER""\fB\fR restrict macro tracing size" 2
.el .IP "\fB\-l \-\-arglength=\f(CBNUMBER\fB\fR restrict macro tracing size" 2
.IX Item "-l --arglength=NUMBER restrict macro tracing size"
.ie n .IP "\fB\-o \-\-error\-output=\f(CB""FILE""\fB\fR redirect debug and trace output" 2
.el .IP "\fB\-o \-\-error\-output=\f(CBFILE\fB\fR redirect debug and trace output" 2
.IX Item "-o --error-output=FILE redirect debug and trace output"
.PD
.PP
Flags are any of:
.IP "\fBt\fR trace for all macro calls, not only debugging-on'ed" 2
.IX Item "t trace for all macro calls, not only debugging-on'ed"
.PD 0
.IP "\fBa\fR show actual arguments" 2
.IX Item "a show actual arguments"
.IP "\fBe\fR show expansion" 2
.IX Item "e show expansion"
.IP "\fBc\fR show before collect, after collect and after call" 2
.IX Item "c show before collect, after collect and after call"
.IP "\fBx\fR add a unique macro call id, useful with c flag" 2
.IX Item "x add a unique macro call id, useful with c flag"
.IP "\fBf\fR say current input file name" 2
.IX Item "f say current input file name"
.IP "\fBl\fR say current input line number" 2
.IX Item "l say current input line number"
.IP "\fBp\fR show results of path searches" 2
.IX Item "p show results of path searches"
.IP "\fBm\fR show results of module operations" 2
.IX Item "m show results of module operations"
.IP "\fBi\fR show changes in input files" 2
.IX Item "i show changes in input files"
.IP "\fBV\fR shorthand for all of the above flags" 2
.IX Item "V shorthand for all of the above flags"
.PD
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
The \fBmp4h\fR software is a macro-processor, which means that keywords are
replaced by other text. This chapter describes all primitives.
As \fBmp4h\fR has been specially designed for \s-1HTML\s0 documents, its syntax is
very similar to \s-1HTML,\s0 with tags and attributes. One important feature
has no equivalent in \s-1HTML:\s0 comments until end of line. All text
following three colons is discarded until end of line, like
.PP
.Vb 1
\& ;;; This is a comment
.Ve
.SS "Function Macros"
.IX Subsection "Function Macros"
\&\fBNote:\fR
All examples in this documentation are processed through \fBmp4h\fR with
expansion flags set to zero (see a description of possible expansion
flags at the end of document), it is why simple tags contain a trailing
slash. But \fBmp4h\fR can output plain \s-1HTML\s0 files with other expansion
flags.
.PP
The definition of new tags is the most common task provided by \fBmp4h\fR.
As with \s-1HTML,\s0 macro names are case insensitive, unless \f(CW\*(C`\-c\*(C'\fR
option is used to change this default behaviour. In this documentation,
only lowercase letters are used.
There are two kinds of tags: simple and complex. A simple tag has the
following form:
.PP
.Vb 1
\&
.Ve
.PP
whereas a complex tag looks like:
.PP
.Vb 3
\&
\& body
\&
.Ve
.PP
Since version 0.9.1, \fBmp4h\fR knows \s-1XHTML\s0 syntax too, so your input file
may conform to \s-1HTML\s0 or \s-1XHTML\s0 syntax. In this manual, we adopt the
latter, which is why simple tags have a trailing slash in attributes.
If you want to produce \s-1HTML\s0 files with this input file, you may either
choose an adequate \f(CW\*(C`\-\-expansion\*(C'\fR flag or use a post-processor like
tidy \f(CW\*(C`\*(C'\fR.
.PP
When a simple tag is defined by \fBmp4h\fR, it can be parsed even if the
trailing slash is omitted, because \fBmp4h\fR knows that this tag is
simple. But it is a good practice to always append a trailing slash to
simple tags.
.PP
In macro descriptions below, a slash indicates a simple tag, and a V
letter that attributes are read verbatim (without expansion) (see the
chapter on macro expansion for further details).
.IP "\(bu" 2
define-tag
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[attributes=verbatim]\*(C'\fR \f(CW\*(C`[endtag=required]\*(C'\fR \f(CW\*(C`[whitespace=delete]\*(C'\fR
.PP
This function lets you define your own tags. First argument is the
command name. Replacement text is the function body.
.PP
Source:
.PP
.Vb 2
\& bar
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& bar
.Ve
.PP
Even if spaces have usually few incidence on \s-1HTML\s0 syntax, it is
important to note that
.PP
.Vb 1
\& bar
.Ve
.PP
and
.PP
.Vb 3
\&
\& bar
\&
.Ve
.PP
are not equivalent, the latter form contains two newlines that were not
present in the former.
.ie n .IP """whitespace=delete""" 4
.el .IP "\f(CWwhitespace=delete\fR" 4
.IX Item "whitespace=delete"
Some spaces are suppressed in replacement text, in particular any
leading or trailing spaces, and newlines not enclosed within angle
brackets.
.ie n .IP """endtag=required""" 4
.el .IP "\f(CWendtag=required\fR" 4
.IX Item "endtag=required"
Define a complex tag
.Sp
Source:
.Sp
.Vb 2
\& bar
\&
.Ve
.Sp
Output:
.Sp
.Vb 1
\& bar
.Ve
.Sp
Source:
.Sp
.Vb 3
\& ;;;
\& body is: %body
\& Here it is
.Ve
.Sp
Output:
.Sp
.Vb 1
\& body is: Here it is
.Ve
.ie n .IP """attributes=verbatim""" 4
.el .IP "\f(CWattributes=verbatim\fR" 4
.IX Item "attributes=verbatim"
By default attributes are expanded before text is replaced. If this
attribute is used, attributes are inserted into replacement text without
expansion.
.Sp
Source:
.Sp
.Vb 6
\& quux
\&
\& Body: %Ubody
\& Attributes: %Uattributes
\&
\& Here we go
.Ve
.Sp
Output:
.Sp
.Vb 2
\& Body: Here we go
\& Attributes: txt=
.Ve
.IP "\(bu" 2
provide-tag
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[attributes=verbatim]\*(C'\fR \f(CW\*(C`[endtag=required]\*(C'\fR \f(CW\*(C`[whitespace=delete]\*(C'\fR
.PP
This command is similar to the previous one, except that no operation is
performed if this command was already defined.
.IP "\(bu" 2
let \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CInew\f(CW=\f(CIold\f(CW\*(C'\fR
.PP
Copy a function. This command is useful to save a macro definition
before redefining it.
.PP
Source:
.PP
.Vb 4
\& one
\&
\& two
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& twoone
.Ve
.IP "\(bu" 2
undef \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR
.PP
Delete a command definition.
.PP
Source:
.PP
.Vb 3
\& one
\&
\&
.Ve
.PP
Output:
.PP
.Vb 1
\&
.Ve
.IP "\(bu" 2
set-hook
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[position=before|after]\*(C'\fR \f(CW\*(C`[action=insert|append|replace]\*(C'\fR
.PP
Add text to a predefined macro. This mechanism allows modifications
of existing macros without having to worry about its type, whether it is
complex or not.
.PP
Source:
.PP
.Vb 6
\&
\&
\& Before
\&
\& After
\&
.Ve
.PP
Output:
.PP
.Vb 2
\& Before10
\& After
.Ve
.IP "\(bu" 2
get-hook \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[position=before|after]\*(C'\fR
.PP
Print current hooks of a macro.
.PP
Source:
.PP
.Vb 2
\& Text inserted with position=before:!
\& Text inserted with position=after:!
.Ve
.PP
Output:
.PP
.Vb 4
\& Text inserted with position=before:
\& Before!
\& Text inserted with position=after:
\& After!
.Ve
.IP "\(bu" 2
attributes-quote \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CW%attributes\f(CW\*(C'\fR
.PP
Like \f(CW%attributes\fR, except that \f(CW\*(C`attr=value\*(C'\fR pairs are
printed with double quotes surrounding attribute values, and a leading
space is added if some text is printed.
.PP
Source:
.PP
.Vb 6
\& ;;;
\& %attributes
\& />
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 2
\& id=logo src=logo.gif name=Logo alt=Our logo
\&
\&
\&
\&
.Ve
.IP "\(bu" 2
attributes-extract \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname1\f(CW\*(C'\fR \f(CW\*(C`[,\f(CIname2\f(CW[,\f(CIname3\f(CW...]]\*(C'\fR \f(CW\*(C`\f(CW%attributes\f(CW\*(C'\fR
.PP
Extract from \f(CW%attributes\fR the \f(CW\*(C`attr=value\*(C'\fR pairs for
names matching any of \fIname1\fR, \fIname2\fR....
.PP
Source:
.PP
.Vb 4
\&
\& />
\&
\&
.Ve
.PP
Output:
.PP
.Vb 1
\&
.Ve
.IP "\(bu" 2
attributes-remove \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname1\f(CW\*(C'\fR \f(CW\*(C`[,\f(CIname2\f(CW[,\f(CIname3\f(CW...]]\*(C'\fR \f(CW\*(C`\f(CW%attributes\f(CW\*(C'\fR
.PP
Remove from \f(CW%attributes\fR the \f(CW\*(C`attr=value\*(C'\fR pairs for
names matching any of \fIname1\fR, \fIname2\fR....
.PP
Source:
.PP
.Vb 4
\&
\& /> />
\&
\&
.Ve
.PP
Output:
.PP
.Vb 1
\&
.Ve
.PP
\&\fBNote:\fR
The two previous functions are special, because unlike all other macros,
their expansion do not form a group. This is necessary to parse the
resulting list of attributes.
.PP
In those two functions, names of attributes may be regular expressions.
Main goal of these primitives is to help writing macros accepting any
kind of attributes without having to declare them. A canonical example
is
.PP
Source:
.PP
.Vb 8
\&
\&
\& />
\& />
\& href="">
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 2
\& Welcome
.Ve
.PP
But we want now to add an image attribute. So we may write
.PP
Source:
.PP
.Vb 10
\&
\&
\& />
\& />
\& href="">
\&
\& />
\& src="" alt="" border=0 />
\&
\& />
\&
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 3
\&
.Ve
.PP
We need a mechanism to tell \fBmp4h\fR that some attributes refer to
specific \s-1HTML\s0 tags. A solution is to prepend attribute with tag name,
e.g.
.PP
Source:
.PP
.Vb 10
\&
\&
\& />
\& />
\& href="">
\&
\& />
\& src="" alt="" />
\&
\& />
\&
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 3
\&
.Ve
.PP
This example shows that regular expressions may be used within
attributes names, but it is still incomplete, because we want to remove
prefix from attributes. One solution is with \f(CW\*(C`subst\-in\-string\*(C'\fR,
but there is a more elegant one:
.PP
Source:
.PP
.Vb 10
\&
\&
\& />
\& />
\& href="">
\&
\& />
\& src="" alt="" />
\&
\& />
\&
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 3
\&
.Ve
.PP
When there are subexpressions within regular expressions, they are
printed instead of the whole expression. Note also that I put a colon
before the prefix in order not to mix them with \s-1XML\s0 namespaces.
.SS "Entities"
.IX Subsection "Entities"
Entities are macros in the same way as tags, but they do not take
any arguments. Whereas tags are normally used to mark up text,
entities contain already marked up text. Also note that unlike tags,
entities are by default case sensitive.
.PP
An entity has the following form:
.PP
.Vb 1
\& &entity;
.Ve
.IP "\(bu" 2
define-entity
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR
.PP
This function lets you define your own entities.
First argument is the entity name. Replacement text is the function body.
.PP
Source:
.PP
.Vb 2
\& bar
\& &foo;
.Ve
.PP
Output:
.PP
.Vb 1
\& bar
.Ve
.SS "Variables"
.IX Subsection "Variables"
Variables are a special case of simple tags, because they do not accept
attributes. In fact their use is different, because variables contain
text whereas macros act like operators.
A nice feature concerning variables is their manipulation as arrays.
Indeed variables can be considered like newline separated lists, which
will allow powerful manipulation functions as we will see below.
.IP "\(bu" 2
set-var \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW[=\f(CIvalue\f(CW]\*(C'\fR \f(CW\*(C`[\f(CIname\f(CW[=\f(CIvalue\f(CW]] ...\*(C'\fR
.PP
This command sets variables.
.IP "\(bu" 2
set-var-verbatim \f(CW\*(C`S\*(C'\fR\f(CW\*(C`V\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW[=\f(CIvalue\f(CW]\*(C'\fR \f(CW\*(C`[\f(CIname\f(CW[=\f(CIvalue\f(CW]] ...\*(C'\fR
.PP
As above but attributes are read verbatim.
.IP "\(bu" 2
set-var-x
.Sp
\&\f(CW\*(C`name=\f(CIvariable\-name\f(CW\*(C'\fR
.PP
This command assigns a variable the value of the body of the
command. This is particularly useful when variable values contain
newlines and/or quotes.
.PP
Note that the variable can not be indexed with this command.
Note also, that this command behaves as set-var-verbatim: The body
is not expanded until the variable is shown with get-var.
.IP "\(bu" 2
get-var \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[\f(CIname\f(CW] ...\*(C'\fR
.PP
Show variable contents. If a numeric value within square brackets is
appended to a variable name, it represents the index of an array.
The first index of arrays is 0 by convention.
.PP
Source:
.PP
.Vb 5
\&
\& This is version
\& Operating system is
\& ""
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& This is version 0.10.1
.Ve
.PP
Operating system is
\*(L"Linux
\*(R"
.PP
Source:
.PP
.Vb 5
\&
\&
.Ve
.PP
Output:
.PP
.Vb 4
\& 200
\& 1
\& 2
\& 3
.Ve
.IP "\(bu" 2
get-var-once \f(CW\*(C`S\*(C'\fR\f(CW\*(C`V\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[\f(CIname\f(CW] ...\*(C'\fR
.PP
As above but attributes are not expanded.
.PP
Source:
.PP
.Vb 7
\& 0.10.1
\& ;;;
\& Here is version
\& ;;;
\& Here is version
\& ;;;
\& Here is version
.Ve
.PP
Output:
.PP
.Vb 3
\& Here is version 0.10.1
\& Here is version 0.10.1
\& Here is version
.Ve
.IP "\(bu" 2
preserve \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[\f(CIname\f(CW] ...\*(C'\fR
.PP
All variables are global, there is no variable or macro scope.
For this reason a stack is used to preserve variables. When this
command is invoked, arguments are names of variables, whose values
are put at the top of the stack and variables are reset to an
empty string.
.IP "\(bu" 2
restore \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[\f(CIname\f(CW] ...\*(C'\fR
.PP
This is the opposite: arguments are names of variables, which are set to
the value found at the top of the stack, and stack is popped down.
.PP
\&\fBNote:\fR
The \f(CW\*(C`preserve\*(C'\fR tag pushes its last argument first, whereas
\&\f(CW\*(C`restore\*(C'\fR first pops its first argument.
.PP
Source:
.PP
.Vb 10
\&
\&
\&
\& Inside: src= name= text=
\&
\&
\&
\& Before: src= name= text=
\&
\& After: src= name= text=
.Ve
.PP
Output:
.PP
.Vb 3
\& Before: src=foo.png name= text=Hello, World!
\& Inside: src=bar name=quux text=
\& After: src=foo.png name= text=Hello, World!
.Ve
.IP "\(bu" 2
unset-var \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[\f(CIname\f(CW] ...\*(C'\fR
.PP
Undefine variables.
.IP "\(bu" 2
var-exists \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR
.PP
Returns \f(CW\*(C`true\*(C'\fR when this variable exists.
.IP "\(bu" 2
increment \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[by=\f(CIvalue\f(CW]\*(C'\fR
.PP
Increment the variable whose name is the first argument. Default
increment is one.
.ie n .IP """by=\fIvalue\fP""" 4
.el .IP "\f(CWby=\f(CIvalue\f(CW\fR" 4
.IX Item "by=value"
Change increment amount.
.PP
Source:
.PP
.Vb 4
\&
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 3
\& 10
\& 11
\& 8
.Ve
.IP "\(bu" 2
decrement \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[by=\f(CIvalue\f(CW]\*(C'\fR
.PP
Decrement the variable whose name is the first argument. Default
decrement is one.
.ie n .IP """by=\fIvalue\fP""" 4
.el .IP "\f(CWby=\f(CIvalue\f(CW\fR" 4
.IX Item "by=value"
Change decrement amount.
.PP
Source:
.PP
.Vb 4
\&
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 3
\& 10
\& 9
\& 6
.Ve
.IP "\(bu" 2
copy-var \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIsrc\f(CW\*(C'\fR \f(CW\*(C`\f(CIdest\f(CW\*(C'\fR
.PP
Copy a variable into another.
.PP
Source:
.PP
.Vb 3
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& 10
.Ve
.IP "\(bu" 2
defvar \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`\f(CIvalue\f(CW\*(C'\fR
.PP
If this variable is not defined or is defined to an empty string, then
it is set to the second argument.
.PP
Source:
.PP
.Vb 3
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 2
\& Title
\& Title
.Ve
.IP "\(bu" 2
symbol-info \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR
.PP
Show information on symbols. If it is a variable name, the \f(CW\*(C`STRING\*(C'\fR word is printed as well as the number of lines contained within
this variable.
.PP
If it is a macro name, one of the following messages is printed:
\&\f(CW\*(C`PRIM COMPLEX\*(C'\fR, \f(CW\*(C`PRIM TAG\*(C'\fR,
\&\f(CW\*(C`USER COMPLEX\*(C'\fR or \f(CW\*(C`USER TAG\*(C'\fR
.PP
Source:
.PP
.Vb 8
\&
\& bar
\& quux
\&
\&
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 6
\& STRING
\& 5
\& PRIM TAG
\& PRIM COMPLEX
\& USER TAG
\& USER COMPLEX
.Ve
.SS "String Functions"
.IX Subsection "String Functions"
.IP "\(bu" 2
string-length \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR
.PP
Prints the length of the string.
.PP
Source:
.PP
.Vb 8
\& ;;;
\& />
\& ;;;
\& /> />;;;
\&
.Ve
.PP
Output:
.PP
.Vb 2
\& 7
\& 7
.Ve
.IP "\(bu" 2
downcase \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR
.PP
Convert to lowercase letters.
.PP
Source:
.PP
.Vb 1
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& does it work?
.Ve
.IP "\(bu" 2
upcase \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR
.PP
Convert to uppercase letters.
.PP
Source:
.PP
.Vb 1
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& DOES IT WORK?
.Ve
.IP "\(bu" 2
capitalize \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR
.PP
Convert to a title, with a capital letter at the beginning of every
word.
.PP
Source:
.PP
.Vb 1
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& Does It Work?
.Ve
.IP "\(bu" 2
substring \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR \f(CW\*(C`[\f(CIstart\f(CW [\f(CIend\f(CW]]\*(C'\fR
.PP
Extracts a substring from a string. First argument is original string,
second and third are respectively start and end indexes. By convention
first character has a null index.
.PP
Source:
.PP
.Vb 3
\&
\& 4 />
\& 4 6 />
.Ve
.PP
Output:
.PP
.Vb 2
\& efghijk
\& ef
.Ve
.IP "\(bu" 2
string-eq \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring1\f(CW\*(C'\fR \f(CW\*(C`\f(CIstring2\f(CW\*(C'\fR \f(CW\*(C`[caseless=true]\*(C'\fR
.PP
Returns \f(CW\*(C`true\*(C'\fR if first two arguments are equal.
.PP
Source:
.PP
.Vb 2
\& 1:
\& 2:
.Ve
.PP
Output:
.PP
.Vb 2
\& 1:
\& 2:true
.Ve
.ie n .IP """caseless=true""" 4
.el .IP "\f(CWcaseless=true\fR" 4
.IX Item "caseless=true"
Comparison is case insensitive.
.PP
Source:
.PP
.Vb 2
\& 1:
\& 2:
.Ve
.PP
Output:
.PP
.Vb 2
\& 1:true
\& 2:true
.Ve
.IP "\(bu" 2
string-neq \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring1\f(CW\*(C'\fR \f(CW\*(C`\f(CIstring2\f(CW\*(C'\fR \f(CW\*(C`[caseless=true]\*(C'\fR
.PP
Returns \f(CW\*(C`true\*(C'\fR if the first two arguments are not equal.
.PP
Source:
.PP
.Vb 2
\& 1:
\& 2:
.Ve
.PP
Output:
.PP
.Vb 2
\& 1:true
\& 2:
.Ve
.ie n .IP """caseless=true""" 4
.el .IP "\f(CWcaseless=true\fR" 4
.IX Item "caseless=true"
Comparison is case insensitive.
.PP
Source:
.PP
.Vb 2
\& 1:
\& 2:
.Ve
.PP
Output:
.PP
.Vb 2
\& 1:
\& 2:
.Ve
.IP "\(bu" 2
string-compare \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring1\f(CW\*(C'\fR \f(CW\*(C`\f(CIstring2\f(CW\*(C'\fR \f(CW\*(C`[caseless=true]\*(C'\fR
.PP
Compares two strings and returns one of the values less,
greater or equal depending on this comparison.
.PP
Source:
.PP
.Vb 2
\& 1:
\& 2:
.Ve
.PP
Output:
.PP
.Vb 2
\& 1:less
\& 2:equal
.Ve
.ie n .IP """caseless=true""" 4
.el .IP "\f(CWcaseless=true\fR" 4
.IX Item "caseless=true"
Comparison is case insensitive.
.PP
Source:
.PP
.Vb 1
\& 1:
.Ve
.PP
Output:
.PP
.Vb 1
\& 1:equal
.Ve
.IP "\(bu" 2
char-offsets \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR \f(CW\*(C`\f(CIcharacter\f(CW\*(C'\fR \f(CW\*(C`[caseless=true]\*(C'\fR
.PP
Prints an array containing indexes where the character appear in the
string.
.ie n .IP """caseless=true""" 4
.el .IP "\f(CWcaseless=true\fR" 4
.IX Item "caseless=true"
Comparison is case insensitive.
.PP
Source:
.PP
.Vb 2
\& 1:
\& 2:
.Ve
.PP
Output:
.PP
.Vb 5
\& 1:0
\& 8
\& 2:0
\& 4
\& 8
.Ve
.IP "\(bu" 2
printf \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIformat\f(CW\*(C'\fR \f(CW\*(C`\f(CIstring\f(CW\*(C'\fR \f(CW\*(C`[\f(CIstring\f(CW ...]\*(C'\fR
.PP
Prints according to a given format. Currently only the
\&\f(CW%s\fR flag character is recognized, and \f(CW\*(C`$\*(C'\fR extension
is supported to change order of arguments.
.PP
Source:
.PP
.Vb 2
\& 1:
\& 2:
.Ve
.PP
Output:
.PP
.Vb 2
\& 1:foo baz bar 10
\& 2:foo 10 bar baz
.Ve
.SS "Regular Expressions"
.IX Subsection "Regular Expressions"
Regular expression support is provided by the \s-1PCRE\s0 (Perl Compatible
Regular Expressions) library package, which is open source software,
copyright by the University of Cambridge.
This is a very nice piece of software, latest versions are available at
\f(CW\*(C`\*(C'\fR.
.PP
Before version 1.0.6, \s-1POSIX\s0 regular expressions were implemented.
For this reason, the following macros recognize two attributes,
\&\f(CW\*(C`caseless=true\*(C'\fR and \f(CW\*(C`singleline=true|false\*(C'\fR.
But Perl allows a much better control on regular expressions with so
called modifiers, which are assed to the new \f(CW\*(C`reflags\*(C'\fR
attribute. It may contain one or more modifiers:
.IP "\fBi\fR Matching is case insensitive" 2
.IX Item "i Matching is case insensitive"
.PD 0
.ie n .IP "\fBm\fR Treat string as multiple lines. When set, a ""^"" matches any beginning of line, and ""$"" any end of line. By default, they match begin and end of string." 2
.el .IP "\fBm\fR Treat string as multiple lines. When set, a \f(CW^\fR matches any beginning of line, and \f(CW$\fR any end of line. By default, they match begin and end of string." 2
.IX Item "m Treat string as multiple lines. When set, a ^ matches any beginning of line, and $ any end of line. By default, they match begin and end of string."
.ie n .IP "\fBs\fR Treat string as single line. A dot (""."") may also match a newline, whereas it does not by default." 2
.el .IP "\fBs\fR Treat string as single line. A dot (\f(CW.\fR) may also match a newline, whereas it does not by default." 2
.IX Item "s Treat string as single line. A dot (.) may also match a newline, whereas it does not by default."
.IP "\fBx\fR Allow formatted regular expression, that means whitespaces, newlines and comments are removed from regular expression before processing." 2
.IX Item "x Allow formatted regular expression, that means whitespaces, newlines and comments are removed from regular expression before processing."
.PD
.PP
\&\fBNote:\fR
Attribute \f(CW\*(C`singleline=true\*(C'\fR is a synonym for the \f(CW\*(C`s\*(C'\fR
modifier, whereas \f(CW\*(C`singleline=false\*(C'\fR is a synonym for the
\&\f(CW\*(C`m\*(C'\fR modifier. This behaviour was different up to \fBmp4h\fR 1.0.6.
.IP "\(bu" 2
subst-in-string \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR \f(CW\*(C`\f(CIregexp\f(CW\*(C'\fR \f(CW\*(C`[\f(CIreplacement\f(CW]\*(C'\fR \f(CW\*(C`[caseless=true]\*(C'\fR \f(CW\*(C`[singleline=true|false]\*(C'\fR \f(CW\*(C`[reflags=[imsx]]\*(C'\fR
.PP
Replace a regular expression in a string by a replacement text.
.PP
Source:
.PP
.Vb 3
\&
\& "[c\-e]" />
\& "([c\-e])" "\e\e1 " />
.Ve
.PP
Output:
.PP
.Vb 2
\& abfghijk
\& abc d e fghijk
.Ve
.PP
Source:
.PP
.Vb 6
\&
\& ".$" "" />
\& ".$" "" singleline=false />
\& "
\& ([a\-c]) | [0\-9]
\& " ":\e\e1:" reflags=x />
.Ve
.PP
Output:
.PP
.Vb 9
\& abcdefghijk
\& abcdefghijk
\& abcdefghij
\& abcdefghij
\& abcdefghij
\& abcdefghij
\& :a::b::c:defghijk
\& :a::b::c:defghijk
\& :a::b::c:defghijk
.Ve
.IP "\(bu" 2
subst-in-var \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`\f(CIregexp\f(CW\*(C'\fR \f(CW\*(C`[\f(CIreplacement\f(CW]\*(C'\fR \f(CW\*(C`[caseless=true]\*(C'\fR \f(CW\*(C`[singleline=true|false]\*(C'\fR \f(CW\*(C`[reflags=[imsx]]\*(C'\fR
.PP
Performs substitutions inside variable content.
.IP "\(bu" 2
match \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR \f(CW\*(C`\f(CIregexp\f(CW\*(C'\fR \f(CW\*(C`[caseless=true]\*(C'\fR \f(CW\*(C`[singleline=true|false]\*(C'\fR \f(CW\*(C`[reflags=[imsx]]\*(C'\fR \f(CW\*(C`[action=report|extract|delete|startpos|endpos|length]\*(C'\fR
.ie n .IP """action=report""" 4
.el .IP "\f(CWaction=report\fR" 4
.IX Item "action=report"
Prints \f(CW\*(C`true\*(C'\fR if string contains regexp.
.ie n .IP """action=extract""" 4
.el .IP "\f(CWaction=extract\fR" 4
.IX Item "action=extract"
Prints the expression matching regexp in string.
.ie n .IP """action=delete""" 4
.el .IP "\f(CWaction=delete\fR" 4
.IX Item "action=delete"
Prints the string without the expression matching regexp in string.
.ie n .IP """action=startpos""" 4
.el .IP "\f(CWaction=startpos\fR" 4
.IX Item "action=startpos"
Prints the first char of the expression matching regexp in string.
If there is no match, returns \f(CW\*(C`\-1\*(C'\fR.
.ie n .IP """action=endpos""" 4
.el .IP "\f(CWaction=endpos\fR" 4
.IX Item "action=endpos"
Prints the last char of the expression matching regexp in string.
If there is no match, returns \f(CW\*(C`\-1\*(C'\fR.
.ie n .IP """action=length""" 4
.el .IP "\f(CWaction=length\fR" 4
.IX Item "action=length"
Prints the length of the expression matching regexp in string.
.PP
Source:
.PP
.Vb 6
\& 1:
\& 2:
\& 3:
\& 4:
\& 5:
\& 6:
.Ve
.PP
Output:
.PP
.Vb 6
\& 1:true
\& 2:cde
\& 3:abfghijk
\& 4:2
\& 5:5
\& 6:3
.Ve
.SS "Arrays"
.IX Subsection "Arrays"
With \fBmp4h\fR one can easily deal with string arrays. Variables can be
treated as a single value or as a newline separated list of strings.
Thus after defining
.PP
.PP
one can view its content or one of these values:
.PP
Source:
.PP
.Vb 2
\&
\&
.Ve
.PP
Output:
.PP
.Vb 5
\& 0
\& 1
\& 2
\& 3
\& 2
.Ve
.IP "\(bu" 2
array-size \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR
.PP
Returns an array size which is the number of lines present in the
variable.
.PP
Source:
.PP
.Vb 1
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& 4
.Ve
.IP "\(bu" 2
array-push \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`\f(CIvalue\f(CW\*(C'\fR
.PP
Add a value (or more if this value contains newlines) at the end of an
array.
.PP
Source:
.PP
.Vb 2
\&
\&
.Ve
.PP
Output:
.PP
.Vb 7
\& 0
\& 1
\& 2
\& 3
\& 10
\& 11
\& 12
.Ve
.IP "\(bu" 2
array-pop \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR
.PP
Remove the toplevel value of an array and returns this string.
.IP "\(bu" 2
array-topvalue \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR
.PP
Prints the last entry of an array.
.PP
Source:
.PP
.Vb 1
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& 12
.Ve
.IP "\(bu" 2
array-add-unique \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`\f(CIvalue\f(CW\*(C'\fR \f(CW\*(C`[caseless=true]\*(C'\fR
.PP
Add a value at the end of an array if this value is not already present
in this variable.
.PP
Source:
.PP
.Vb 2
\&
\&
.Ve
.PP
Output:
.PP
.Vb 7
\& 0
\& 1
\& 2
\& 3
\& 10
\& 11
\& 12
.Ve
.ie n .IP """caseless=true""" 4
.el .IP "\f(CWcaseless=true\fR" 4
.IX Item "caseless=true"
Comparison is case insensitive.
.IP "\(bu" 2
array-concat \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname1\f(CW\*(C'\fR \f(CW\*(C`[\f(CIname2\f(CW] ...\*(C'\fR
.PP
Concatenates all arrays into the first one.
.PP
Source:
.PP
.Vb 3
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 2
\& foo
\& bar
.Ve
.IP "\(bu" 2
array-member \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`\f(CIvalue\f(CW\*(C'\fR \f(CW\*(C`[caseless=true]\*(C'\fR
.PP
If value is contained in array, returns its index otherwise returns \-1.
.PP
Source:
.PP
.Vb 1
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& 5
.Ve
.ie n .IP """caseless=true""" 4
.el .IP "\f(CWcaseless=true\fR" 4
.IX Item "caseless=true"
Comparison is case insensitive.
.IP "\(bu" 2
array-shift \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`\f(CIoffset\f(CW\*(C'\fR \f(CW\*(C`[start=\f(CIstart\f(CW]\*(C'\fR
.PP
Shifts an array. If offset is negative, indexes below 0 are lost.
If offset is positive, first indexes are filled with empty strings.
.PP
Source:
.PP
.Vb 4
\&
\& Now:
\&
\& And:
.Ve
.PP
Output:
.PP
.Vb 1
\& Now:
.Ve
.PP
0
1
2
3
10
11
12
.PP
And: 2
3
10
11
12
.ie n .IP """start=\fIstart\fP""" 4
.el .IP "\f(CWstart=\f(CIstart\f(CW\fR" 4
.IX Item "start=start"
Change origin of shifts (default is 0).
.Sp
Source:
.Sp
.Vb 1
\&
.Ve
.Sp
Output:
.Sp
.Vb 3
\& 2
\& 3
\& 12
.Ve
.IP "\(bu" 2
sort \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[caseless=true]\*(C'\fR \f(CW\*(C`[numeric=true]\*(C'\fR \f(CW\*(C`[sortorder=reverse]\*(C'\fR
.PP
Sort lines of an array in place. Default is to sort lines
alphabetically.
.PP
Source:
.PP
.Vb 1
\&
.Ve
.PP
Output:
.PP
.Vb 3
\& 12
\& 2
\& 3
.Ve
.ie n .IP """caseless=true""" 4
.el .IP "\f(CWcaseless=true\fR" 4
.IX Item "caseless=true"
Comparison is case insensitive.
.ie n .IP """numeric=true""" 4
.el .IP "\f(CWnumeric=true\fR" 4
.IX Item "numeric=true"
Sort lines numerically
.Sp
Source:
.Sp
.Vb 1
\&
.Ve
.Sp
Output:
.Sp
.Vb 3
\& 2
\& 3
\& 12
.Ve
.ie n .IP """sortorder=reverse""" 4
.el .IP "\f(CWsortorder=reverse\fR" 4
.IX Item "sortorder=reverse"
Reverse sort order
.Sp
Source:
.Sp
.Vb 2
\& ;;;
\&
.Ve
.Sp
Output:
.Sp
.Vb 3
\& 12
\& 3
\& 2
.Ve
.SS "Numerical operators"
.IX Subsection "Numerical operators"
These operators perform basic arithmetic operations. When all operands
are integers result is an integer too, otherwise it is a float. These
operators are self-explanatory.
.IP "\(bu" 2
add \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CInumber1\f(CW\*(C'\fR \f(CW\*(C`\f(CInumber2\f(CW\*(C'\fR \f(CW\*(C`[\f(CInumber3\f(CW] ...\*(C'\fR
.IP "\(bu" 2
substract \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CInumber1\f(CW\*(C'\fR \f(CW\*(C`\f(CInumber2\f(CW\*(C'\fR \f(CW\*(C`[\f(CInumber3\f(CW] ...\*(C'\fR
.IP "\(bu" 2
multiply \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CInumber1\f(CW\*(C'\fR \f(CW\*(C`\f(CInumber2\f(CW\*(C'\fR \f(CW\*(C`[\f(CInumber3\f(CW] ...\*(C'\fR
.IP "\(bu" 2
divide \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CInumber1\f(CW\*(C'\fR \f(CW\*(C`\f(CInumber2\f(CW\*(C'\fR \f(CW\*(C`[\f(CInumber3\f(CW] ...\*(C'\fR
.IP "\(bu" 2
min \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CInumber1\f(CW\*(C'\fR \f(CW\*(C`\f(CInumber2\f(CW\*(C'\fR \f(CW\*(C`[\f(CInumber3\f(CW] ...\*(C'\fR
.IP "\(bu" 2
max \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CInumber1\f(CW\*(C'\fR \f(CW\*(C`\f(CInumber2\f(CW\*(C'\fR \f(CW\*(C`[\f(CInumber3\f(CW] ...\*(C'\fR
.PP
Source:
.PP
.Vb 2
\&
\&
.Ve
.PP
Output:
.PP
.Vb 2
\& 21
\& 21.000000
.Ve
.PP
Source:
.PP
.Vb 4
\&
\& />" /> />
\&
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& 720
.Ve
.IP "\(bu" 2
modulo \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CInumber1\f(CW\*(C'\fR \f(CW\*(C`\f(CInumber2\f(CW\*(C'\fR
.PP
Unlike functions listed above the modulo function cannot handle more
than 2 arguments, and these arguments must be integers.
.PP
Source:
.PP
.Vb 1
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& 2
.Ve
.PP
Those functions compare two numbers and returns \f(CW\*(C`true\*(C'\fR when this
comparison is true. If one argument is not a number, comparison
is false.
.IP "\(bu" 2
gt \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CInumber1\f(CW\*(C'\fR \f(CW\*(C`\f(CInumber2\f(CW\*(C'\fR
.PP
Returns \f(CW\*(C`true\*(C'\fR if first argument is greater than second.
.IP "\(bu" 2
lt \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CInumber1\f(CW\*(C'\fR \f(CW\*(C`\f(CInumber2\f(CW\*(C'\fR
.PP
Returns \f(CW\*(C`true\*(C'\fR if first argument is lower than second.
.IP "\(bu" 2
eq \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CInumber1\f(CW\*(C'\fR \f(CW\*(C`\f(CInumber2\f(CW\*(C'\fR
.PP
Returns \f(CW\*(C`true\*(C'\fR if arguments are equal.
.IP "\(bu" 2
neq \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CInumber1\f(CW\*(C'\fR \f(CW\*(C`\f(CInumber2\f(CW\*(C'\fR
.PP
Returns \f(CW\*(C`true\*(C'\fR if arguments are not equal.
.SS "Relational operators"
.IX Subsection "Relational operators"
.IP "\(bu" 2
not \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR
.PP
Returns \f(CW\*(C`true\*(C'\fR if string is empty, otherwise returns an empty string.
.IP "\(bu" 2
and \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR \f(CW\*(C`[\f(CIstring\f(CW] ...\*(C'\fR
.PP
Returns the last argument if all arguments are non empty.
.IP "\(bu" 2
or \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR \f(CW\*(C`[\f(CIstring\f(CW] ...\*(C'\fR
.PP
Returns the first non empty argument.
.SS "Flow functions"
.IX Subsection "Flow functions"
.IP "\(bu" 2
group \f(CW\*(C`S\*(C'\fR\f(CW\*(C`V\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIexpression\f(CW\*(C'\fR \f(CW\*(C`[\f(CIexpression\f(CW] ...\*(C'\fR \f(CW\*(C`[separator=\f(CIstring\f(CW]\*(C'\fR
.PP
This function groups multiple statements into a single one. Some
examples will be seen below with conditional operations.
.PP
A less intuitive but very helpful use of this macro is to preserve newlines
when \f(CW\*(C`whitespace=delete\*(C'\fR is specified.
.PP
Source:
.PP
.Vb 10
\&
\& Text on
\& 3 lines without
\& whitespace=delete
\&
\&
\& Text on
\& 3 lines with
\& whitespace=delete
\&
\&
\&
\&
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 3
\& Text on
\& 3 lines without
\& whitespace=delete
.Ve
.PP
Text on3 lines withwhitespace=delete
Text on
3 lines with
whitespace=delete
.PP
Note that newlines are suppressed in \f(CW\*(C`text2\*(C'\fR and result is
certainly unwanted.
.IP "\(bu" 2
compound
.Sp
\&\f(CW\*(C`\f(CIexpression\f(CW\*(C'\fR \f(CW\*(C`[\f(CIexpression\f(CW] ...\*(C'\fR \f(CW\*(C`[separator=\f(CIstring\f(CW]\*(C'\fR
.PP
Like \f(CW\*(C`group\*(C'\fR, but this tag is complex.
.ie n .IP """separator=\fIstring\fP""" 4
.el .IP "\f(CWseparator=\f(CIstring\f(CW\fR" 4
.IX Item "separator=string"
By default arguments are put aside. This attribute define a separator
inserted between arguments.
.IP "\(bu" 2
disjoin \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIexpression\f(CW\*(C'\fR
.PP
Does the opposite job to \f(CW\*(C`group\*(C'\fR, its argument is no more
treated as a single object when processed by another command.
.IP "\(bu" 2
noexpand \f(CW\*(C`S\*(C'\fR\f(CW\*(C`V\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIcommand\f(CW\*(C'\fR \f(CW\*(C`[\f(CIcommand\f(CW] ...\*(C'\fR
.PP
Prints its arguments without expansion. They will never be expanded
unless the \f(CW\*(C`expand\*(C'\fR tag is used to cancel this \f(CW\*(C`noexpand\*(C'\fR tag.
.IP "\(bu" 2
expand \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIcommand\f(CW\*(C'\fR \f(CW\*(C`[\f(CIcommand\f(CW] ...\*(C'\fR
.PP
Cancels the \f(CW\*(C`noexpand\*(C'\fR tag.
.PP
Source:
.PP
.Vb 5
\& bar=LT=/define\-tag>" "=LT=" "<" />
\&
\& quux=LT=/define\-tag>" "=LT="
\& "" />
\&
.Ve
.PP
Output:
.PP
.Vb 3
\& bar
\& quux
\& bar
.Ve
.IP "\(bu" 2
if \f(CW\*(C`S\*(C'\fR\f(CW\*(C`V\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR \f(CW\*(C`\f(CIthen\-clause\f(CW\*(C'\fR \f(CW\*(C`[\f(CIelse\-clause\f(CW]\*(C'\fR
.PP
If string is non empty, second argument is evaluated otherwise third
argument is evaluated.
.PP
Source:
.PP
.Vb 5
\&
\&
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 2
\& yes
\& no
.Ve
.IP "\(bu" 2
ifeq \f(CW\*(C`S\*(C'\fR\f(CW\*(C`V\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring1\f(CW\*(C'\fR \f(CW\*(C`\f(CIstring2\f(CW\*(C'\fR \f(CW\*(C`\f(CIthen\-clause\f(CW\*(C'\fR \f(CW\*(C`[\f(CIelse\-clause\f(CW]\*(C'\fR
.PP
If first two arguments are identical strings, third argument is evaluated
otherwise fourth argument is evaluated.
.IP "\(bu" 2
ifneq \f(CW\*(C`S\*(C'\fR\f(CW\*(C`V\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring1\f(CW\*(C'\fR \f(CW\*(C`\f(CIstring2\f(CW\*(C'\fR \f(CW\*(C`\f(CIthen\-clause\f(CW\*(C'\fR \f(CW\*(C`[\f(CIelse\-clause\f(CW]\*(C'\fR
.PP
If first two arguments are not identical strings, third argument is
evaluated otherwise fourth argument is evaluated.
.IP "\(bu" 2
when
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR
.PP
When argument is not empty, its body is evaluated.
.IP "\(bu" 2
while \f(CW\*(C`V\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIcond\f(CW\*(C'\fR
.PP
While condition is true, body function is evaluated.
.PP
Source:
.PP
.Vb 4
\&
\& 0 />>;;;
\& ;;;
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& 10 9 8 7 6 5 4 3 2 1
.Ve
.IP "\(bu" 2
foreach
.Sp
\&\f(CW\*(C`\f(CIvariable\f(CW\*(C'\fR \f(CW\*(C`\f(CIarray\f(CW\*(C'\fR \f(CW\*(C`[start=\f(CIstart\f(CW]\*(C'\fR \f(CW\*(C`[end=\f(CIend\f(CW]\*(C'\fR \f(CW\*(C`[step=\f(CIpas\f(CW]\*(C'\fR
.PP
This macro is similar to the \f(CW\*(C`foreach\*(C'\fR Perl's macro:
a variable loops over array values and function body is evaluated for each
value.
.PP
first argument is a generic variable name, and second is the name of an
array.
.PP
Source:
.PP
.Vb 2
\&
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& 1 2 3 4 5 6
.Ve
.ie n .IP """start=\fIstart\fP""" 4
.el .IP "\f(CWstart=\f(CIstart\f(CW\fR" 4
.IX Item "start=start"
Skips first indexes.
.Sp
Source:
.Sp
.Vb 2
\&
\&
.Ve
.Sp
Output:
.Sp
.Vb 1
\& 4 5 6
.Ve
.ie n .IP """end=\fIend\fP""" 4
.el .IP "\f(CWend=\f(CIend\f(CW\fR" 4
.IX Item "end=end"
Stops after index has reached that value.
.Sp
Source:
.Sp
.Vb 2
\&
\&
.Ve
.Sp
Output:
.Sp
.Vb 1
\& 1 2 3
.Ve
.ie n .IP """step=\fIstep\fP""" 4
.el .IP "\f(CWstep=\f(CIstep\f(CW\fR" 4
.IX Item "step=step"
Change index increment (default is 1).
If step is negative, array is treated in reverse order.
.Sp
Source:
.Sp
.Vb 3
\&
\&
\&
.Ve
.Sp
Output:
.Sp
.Vb 2
\& 1 3 5
\& 6 4 2
.Ve
.IP "\(bu" 2
var-case \f(CW\*(C`S\*(C'\fR\f(CW\*(C`V\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIvar1\f(CW=\f(CIvalue1\f(CW \f(CIaction1\f(CW\*(C'\fR \f(CW\*(C`[\f(CIvar2\f(CW=\f(CIvalue2\f(CW \f(CIaction2\f(CW ...\*(C'\fR
.PP
This command performs multiple conditions with a single instruction.
.PP
Source:
.PP
.Vb 11
\&
\&
\& x />
\& x=2 x />
\& y=1 y />
\& y=2 y />
\& />
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& x1y0
\&
\&
\& y\-1
.Ve
.IP "\(bu" 2
break \f(CW\*(C`S\*(C'\fR
.PP
Breaks the innermost \f(CW\*(C`while\*(C'\fR loop.
.PP
Source:
.PP
.Vb 5
\&
\& 0 />>;;;
\& ;;;
\& 5 />;;;
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& 10 9 8 7 6
.Ve
.IP "\(bu" 2
return \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`[up=number]\*(C'\fR \f(CW\*(C`\f(CIstring\f(CW\*(C'\fR
.PP
This command immediately exits from the innermost macro.
A message may also be inserted. But this macro changes token parsing
so its use may become very hazardous in some situations.
.ie n .IP """up=\fInumber\fP""" 4
.el .IP "\f(CWup=\f(CInumber\f(CW\fR" 4
.IX Item "up=number"
This attribute determines how much levels have to be exited. By default
only one level is skipped. With a null value, all current macros are
exited from. A negative value do the same, and stops processing current
file.
.IP "\(bu" 2
warning \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR
.PP
Prints a warning on standard error.
.IP "\(bu" 2
exit \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`[status=\f(CIrc\f(CW]\*(C'\fR \f(CW\*(C`[message=\f(CIstring\f(CW]\*(C'\fR
.PP
Immediately exits program.
.ie n .IP """message=\fIstring\fP""" 4
.el .IP "\f(CWmessage=\f(CIstring\f(CW\fR" 4
.IX Item "message=string"
Prints a message to the standard error.
.ie n .IP """status=\fIrc\fP""" 4
.el .IP "\f(CWstatus=\f(CIrc\f(CW\fR" 4
.IX Item "status=rc"
Selects the code returned by the program (\-1 by default).
.IP "\(bu" 2
at-end-of-file
.PP
This is a special command: its content is stored and will be
expanded after end of input.
.SS "File functions"
.IX Subsection "File functions"
.IP "\(bu" 2
directory-contents \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIdirname\f(CW\*(C'\fR \f(CW\*(C`[matching=regexp]\*(C'\fR
.PP
Returns a newline separated list of files contained in a given directory.
.PP
Source:
.PP
.Vb 1
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& mp4h.mp4h
.Ve
.IP "\(bu" 2
real-path \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`patname=\f(CIpathname\f(CW\*(C'\fR
.PP
Resolves all symbolic links, extra ``/'' characters and references
to /./ and /../ in pathname, and expands into the resulting absolute pathname.
All but the last component of pathname must exist when real-path is called.
.PP
This tag is particularly useful when comparing if file or directory names
are identical.
.PP
Source:
.PP
.Vb 1
\& />
.Ve
.PP
Output:
.PP
.Vb 1
\& /build/mp4h\-1.3.1/doc/mp4h.mp4h
.Ve
.IP "\(bu" 2
file-exists \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIfilename\f(CW\*(C'\fR
.PP
Returns \f(CW\*(C`true\*(C'\fR if file exists.
.IP "\(bu" 2
get-file-properties \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIfilename\f(CW\*(C'\fR
.PP
Returns an array of information on this file. These information are:
size, type, ctime, mtime, atime, owner and group.
.PP
Source:
.PP
.Vb 1
\& />
.Ve
.PP
Output:
.PP
.Vb 7
\& 68604
\& FILE
\& 1530057894
\& 1530057894
\& 1530057894
\& root
\& root
.Ve
.IP "\(bu" 2
include \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`file=\f(CIfilename\f(CW | command=\f(CIcommand\-line\f(CW\*(C'\fR \f(CW\*(C`[alt=\f(CIaction\f(CW]\*(C'\fR \f(CW\*(C`[verbatim=true]\*(C'\fR
.PP
Insert the contents of a file in the file system \- if the \f(CW\*(C`file\*(C'\fR
attribute is given \-, or the output from executing a system command \- if the
\&\f(CW\*(C`command\*(C'\fR attribute is given \- into the input stream.
For backwards compatibility, if neither the \f(CW\*(C`file\*(C'\fR nor the
\&\f(CW\*(C`command\*(C'\fR attributes are given, the first argument is taken
as a file to include.
.ie n .IP """file=\fIfilename\fP""" 4
.el .IP "\f(CWfile=\f(CIfilename\f(CW\fR" 4
.IX Item "file=filename"
The given file is read and inserted into the input stream.
This attribute cannot be combined with the command attribute.
.Sp
Files are first searched in current directory, then in
directories specified on command-line with the \f(CW\*(C`\-I\*(C'\fR option, next
in directories listed in the \f(CW\*(C`MP4HLIB\*(C'\fR environment
variable (it used to be \f(CW\*(C`MP4HPATH\*(C'\fR for versions prior to
1.3), and last under the compile-time location
(\f(CW\*(C`/usr/local/lib/mp4h/1.3.1:/usr/local/share/mp4h\*(C'\fR
by default).
.ie n .IP """command=\fIcommand\-line\fP""" 4
.el .IP "\f(CWcommand=\f(CIcommand\-line\f(CW\fR" 4
.IX Item "command=command-line"
The given command line is executed on the operating system, and the output
of it is inserted in the input stream. This attribute cannot be combined
with the file attribute.
.Sp
The given command line is executed using the
\&\fIpopen\fR\|(3) standard C library routine. The command is executed using the standard
system shell, which on Posix compliant systems is \fIsh\fR\|(1).
.ie n .IP """alt=\fIaction\fP""" 4
.el .IP "\f(CWalt=\f(CIaction\f(CW\fR" 4
.IX Item "alt=action"
If file is not found, this alternate action is handled. If this attribute
is not set and file is not found, then an error is raised. This attribute has no effect
when the command attribute is specified.
.ie n .IP """verbatim=true""" 4
.el .IP "\f(CWverbatim=true\fR" 4
.IX Item "verbatim=true"
File content is included without expansion.
This is similar to using the \fBm4\fR undivert macro with a filename as argument.
.PP
Source:
.PP
.Vb 1
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& Linux
.Ve
.IP "\(bu" 2
use \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`name=\f(CIpackage\f(CW\*(C'\fR
.PP
Load definitions from a package file.
.IP "\(bu" 2
comment
.PP
This tag does nothing, its body is simply discarded.
.IP "\(bu" 2
set-eol-comment \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`[\f(CIstring\f(CW]\*(C'\fR
.PP
Change comment characters.
.IP "\(bu" 2
set-quotes \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`[\f(CIstring\f(CW \f(CIstring\f(CW]\*(C'\fR \f(CW\*(C`[display=visible]\*(C'\fR
.PP
By default, all characters between \f(CW\*(C`<@[\*(C'\fR and
\&\f(CW\*(C`]@\*(C'\fR> pairs are read without
parsing. When called without argument, this macro inhibates this
feature. When called with two arguments, it redefines begin and end
delimiters. Begin delimiter must begin with a left-angle bracket, and
end delimiter must end with a right-angle bracket.
.ie n .IP """display=visible""" 4
.el .IP "\f(CWdisplay=visible\fR" 4
.IX Item "display=visible"
Delimiters are also written into output.
.SS "Diversion functions"
.IX Subsection "Diversion functions"
Diversions are a way of temporarily saving output.
The output of \fBmp4h\fR can at any time be diverted to a temporary file,
and be reinserted into the output stream, undiverted, again at a later time.
.PP
Numbered diversions are counted from 0 upwards,
diversion number 0 being the normal output stream.
The number of simultaneous diversions is limited mainly by the memory used
to describe them, because \fBmp4h\fR tries to keep diversions in memory.
However, there is a limit to the overall memory usable by all diversions
taken altogether. When this maximum is about to be exceeded, a
temporary file is opened to receive the contents of the biggest
diversion still in memory, freeing this memory for other diversions.
So, it is theoretically possible that the number of diversions be
limited by the number of available file descriptors.
.IP "\(bu" 2
divert \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`[ divnum=\f(CIdiversion\-number\f(CW ]\*(C'\fR
.PP
Output is diverted using this tag, where diversion-number is the diversion
to be used. If the divnum attribute is left out, diversion-number is assumed
to be zero.
If output is diverted to a non-existent diversion, it is simply discarded.
This can be used to suppress unwanted output. See the example below.
.PP
When all \fBmp4h\fR input will have been processed, all existing diversions
are automatically undiverted, in numerical order.
.PP
Several calls of divert with the same argument do not overwrite the previous diverted text, but append to it.
.PP
Source:
.PP
.Vb 4
\&
\& This is sent nowhere...
\&
\& This is output.
.Ve
.PP
Output:
.PP
.Vb 1
\& This is sent nowhere...
.Ve
.PP
This is output.
.IP "\(bu" 2
undivert \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`[ divnum=\f(CIdiversion\-number\f(CW ]\*(C'\fR
.PP
This tag explicitly undiverts diverted text saved in the diversion with the
specified number. If the divnum attribute is not given, all diversions
are undiverted, in numerical order.
.PP
When diverted text is undiverted, it is not reread by \fBmp4h\fR,
but rather copied directly to the current output. It is therefore
not an error to undivert into a diversion.
.PP
Unlike \fBm4\fR, the \fBmp4h\fR undivert tag does not allow a file name
as argument. The same can be accomplished with the include tag
with the verbatim=\*(L"true\*(R" attribute.
.PP
Source:
.PP
.Vb 5
\&
\& This text is diverted.
\&
\& This text is not diverted.
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& This text is diverted.
.Ve
.PP
This text is not diverted.
.IP "\(bu" 2
divnum \f(CW\*(C`S\*(C'\fR
.PP
This tag expands to the number of the current diversion.
.PP
Source:
.PP
.Vb 6
\& Initial
\&
\& Diversion one:
\&
\& Diversion two:
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& Initial 0
.Ve
.PP
Diversion one: 1
.PP
Diversion two: 2
.SS "Debugging functions"
.IX Subsection "Debugging functions"
When constructs become complex it could be hard to debug them.
Functions listed below are very useful when you could not figure what is
wrong. These functions are not perfect yet and must be improved in
future releases.
.IP "\(bu" 2
function-def \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR
.PP
Prints the replacement text of a user defined macro. For instance, the
macro used to generate all examples of this documentation is
.PP
Source:
.PP
.Vb 1
\&
.Ve
.PP
Output:
.PP
.Vb 2
\&
\& " ">" />[^;\en]*\en[ \et]*" "" />$" "" reflags=m />
.PP
Output:
.PP
.PP
" />
.IP "\(bu" 2
debugmode \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIstring\f(CW\*(C'\fR
.PP
This command acts like the \f(CW\*(C`\-d\*(C'\fR flag but can be ynamically
changed.
.IP "\(bu" 2
debugfile \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIfilename\f(CW\*(C'\fR
.PP
Selects a file where debugging messages are diverted.
If this filename is empty, debugging messages are sent back to standard
error, and if it is set to \f(CW\*(C`\-\*(C'\fR these messages are discarded.
.PP
\&\fBNote:\fR
There is no way to print these debugging messages into the document
being processed.
.IP "\(bu" 2
debugging-on \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[\f(CIname\f(CW] ...\*(C'\fR
.PP
Declare these macros traced, i.e. information about these macros will
be printed if \f(CW\*(C`\-d\*(C'\fR flag or \f(CW\*(C`debugmode\*(C'\fR macro are used.
.IP "\(bu" 2
debugging-off \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW\*(C'\fR \f(CW\*(C`[\f(CIname\f(CW] ...\*(C'\fR
.PP
These macros are no more traced.
.SS "Miscellaneous"
.IX Subsection "Miscellaneous"
.IP "\(bu" 2
_\|_file_\|_ \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`[\f(CIname\f(CW]\*(C'\fR
.PP
Without argument this macro prints current input filename.
With an argument, this macro sets the string returned by future
invocation of this macro.
.IP "\(bu" 2
_\|_line_\|_ \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`[\f(CInumber\f(CW]\*(C'\fR
.PP
Without argument this macro prints current number line in input file.
With an argument, this macro sets the number returned by future
invocation of this macro.
.PP
Source:
.PP
.Vb 1
\& This is <_\|_file_\|_/>, line <_\|_line_\|_/>.
.Ve
.PP
Output:
.PP
.Vb 1
\& This is ./mp4h.mp4h, line 2201.
.Ve
.PP
If you closely look at source code you will see that this number is
wrong. Indeed the number line is the end of the entire block containing
this instruction.
.IP "\(bu" 2
_\|_version_\|_ \f(CW\*(C`S\*(C'\fR
.PP
Prints the version of \fBmp4h\fR.
.IP "\(bu" 2
dnl \f(CW\*(C`S\*(C'\fR
.PP
Discard all characters until newline is reached. This macro ensures that
following string is a comment and does not depend of the value of
comment characters.
.PP
Source:
.PP
.Vb 4
\& This is a comment
\& foo
\& This is a comment
\& bar
.Ve
.PP
Output:
.PP
.Vb 2
\& foo
\& bar
.Ve
.IP "\(bu" 2
date \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`[epoch]\*(C'\fR
.PP
Prints local time according to the epoch passed on argument. If there
is no argument, current local time is printed.
.ie n .IP """time""" 4
.el .IP "\f(CWtime\fR" 4
.IX Item "time"
An epoch time specification.
.ie n .IP """format""" 4
.el .IP "\f(CWformat\fR" 4
.IX Item "format"
A format specification as used with the \fIstrftime\fR\|(3) C library routine.
.PP
Source:
.PP
.Vb 4
\&
\& /> />
\& />
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& Wed Jun 27 00:04:54 2018
.Ve
.PP
Wed Jun 27 00:04:54 2018
2018\-06\-27 00:04:54
.IP "\(bu" 2
timer \f(CW\*(C`S\*(C'\fR
.PP
Prints the time spent since last call to this macro. The printed value
is the number of clock ticks, and so is dependent of your \s-1CPU.\s0
.PP
Source:
.PP
.Vb 4
\&
\& The number of clock ticks since the beginning of the parsing of
\& this example by &mp4h; is:
\&
.Ve
.PP
Output:
.PP
.Vb 2
\& user 23
\& sys 23
.Ve
.PP
The number of clock ticks since the beginning of the parsing of
this example by \fBmp4h\fR is:
user 23
sys 23
.IP "\(bu" 2
mp4h\-l10n \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CIname\f(CW=\f(CIvalue\f(CW\*(C'\fR
.PP
Set locale-specific variables. By default, the portable \*(L"C\*(R" locale is
selected. As locales have different names on different platforms, you
must refer to your system documentation to find which values are adapted
to your system.
.IP "\(bu" 2
mp4h\-output\-radix \f(CW\*(C`S\*(C'\fR
.Sp
\&\f(CW\*(C`\f(CInumber\f(CW\*(C'\fR
.PP
Change the output format of floats by setting the number of digits after
the decimal point. Default is to print numbers in the \*(L"%6.f\*(R" format.
.PP
Source:
.PP
.Vb 3
\&
\&
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& 4.600000
.Ve
.PP
4.60
.SH "EXTERNAL PACKAGES"
.IX Header "EXTERNAL PACKAGES"
It is possible to include external files with the \f(CW\*(C`include\*(C'\fR
command. Files are first searched in current directory, then in
directories specified on command-line with the \f(CW\*(C`\-I\*(C'\fR option, next
in directories listed in the \f(CW\*(C`MP4HLIB\*(C'\fR environment
variable (it used to be \f(CW\*(C`MP4HPATH\*(C'\fR for versions prior to
1.3), and last under the compile-time location
(\f(CW\*(C`/usr/local/lib/mp4h/1.3.1:/usr/local/share/mp4h\*(C'\fR
by default).
.PP
Another way to include packages is with the \f(CW\*(C`use\*(C'\fR command.
There are two differences between \f(CW\*(C`use\*(C'\fR and \f(CW\*(C`include\*(C'\fR:
first, package name has no suffix; and more important, a package cannot
be loaded more than once.
.SH "MACRO EXPANSION"
.IX Header "MACRO EXPANSION"
This part describes internal mechanism of macro expansion.
It must be as precise and exhaustive as possible so
contact me \f(CW\*(C`\*(C'\fR
if you have any suggestion.
.SS "Basics"
.IX Subsection "Basics"
Let us begin with some examples:
.PP
Source:
.PP
.Vb 8
\&
\& This is a simple tag
\&
\&
\& This is a complex tag
\&
\&
\& Body function
.Ve
.PP
Output:
.PP
.Vb 1
\& This is a simple tag
\&
\&
\& This is a complex tag
.Ve
.PP
User defined macros may have attributes like \s-1HTML\s0 tags. To handle these
attributes in replacement text, following conventions have been adopted
(mostly derived from \fBMeta-HTML\fR):
.IP "\(bu" 2
Sequence \f(CW%name\fR is replaced by the command name.
.IP "\(bu" 2
Attributes are numbered from 0. In replacement text,
\&\f(CW%0\fR is replaced by first argument, \f(CW%1\fR
by the 2nd, etc.
As there is no limitation on the number of arguments,
\&\f(CW%20\fR is the 21st argument and not the third followed by the 0
letter.
.Sp
Source:
.Sp
.Vb 4
\&
\& %1
\&
\&
.Ve
.Sp
Output:
.Sp
.Vb 1
\& The Gimp
.Ve
.IP "\(bu" 2
Sequence \f(CW\*(C`%#\*(C'\fR prints number of attributes.
.IP "\(bu" 2
Sequence \f(CW\*(C`%%\*(C'\fR is replaced by \f(CW\*(C`%\*(C'\fR, which is useful in
nested definitions.
.Sp
Source:
.Sp
.Vb 12
\& ;;;
\& outer, # attributes: %#
\& ;;;
\& inner1, # attributes: %#;;;
\& ;;;
\& ;;;
\& inner2, # attributes: %%#;;;
\& ;;;
\&
\&
\&
\&
.Ve
.Sp
Output:
.Sp
.Vb 3
\& outer, # attributes: 2
\& inner1, # attributes: 2
\& inner2, # attributes: 5
.Ve
.IP "\(bu" 2
Sequence \f(CW%attributes\fR is replaced by the space separated
list of attributes.
.Sp
Source:
.Sp
.Vb 7
\&
\&
\&
\&
\&
\&
\&
.Ve
.Sp
Output:
.Sp
.Vb 2
\& Dr. Foo
\& hello@foo.com
.Ve
.IP "\(bu" 2
Sequence \f(CW%body\fR is replaced by the body of a complex macro.
.Sp
Source:
.Sp
.Vb 7
\&
\&
\& %body
\&
\&
\&
\&
.Ve
.Sp
Output:
.Sp
.Vb 3
\&
\&
\&
.Ve
.IP "\(bu" 2
The two forms above accept modifiers. When \f(CW%Aattributes\fR
or \f(CW%Abody\fR is used, a newline separated list of attributes is
printed.
.Sp
Source:
.Sp
.Vb 8
\&
\&
\&
\& : " />
\&
\&
\&
\&
.Ve
.Sp
Output:
.Sp
.Vb 1
\& %0: name=Dr. Foo%1: mail=hello@foo.com
.Ve
.IP "\(bu" 2
Another alternate form is obtained by replacing \f(CW\*(C`A\*(C'\fR
by \f(CW\*(C`U\*(C'\fR, in which case text is replaced but will not be
expanded.
This does make sense only when macro has been defined with
\&\f(CW\*(C`attributes=verbatim\*(C'\fR, otherwise attributes are expanded
before replacement.
.Sp
Source:
.Sp
.Vb 11
\&
\& Before expansion: %Uattributes
\& After expansion: %attributes
\&
\&
\& Before expansion: %Uattributes
\& After expansion: %attributes
\&
\& and here %attributes
\& />
\& />
.Ve
.Sp
Output:
.Sp
.Vb 2
\& Before expansion: and here we go
\& After expansion: and here we go
\&
\&
\& Before expansion:
\& After expansion: and here we go
.Ve
.IP "\(bu" 2
Modifiers \f(CW\*(C`A\*(C'\fR and \f(CW\*(C`U\*(C'\fR can be combined.
.PP
\&\fBNote:\fR
Input expansion is completely different in \fBMeta-HTML\fR and in \fBmp4h\fR.
With \fBMeta-HTML\fR it is sometimes necessary to use other constructs like
\&\f(CW%xbody\fR and \f(CW%qbody\fR.
In order to improve compatibity with \fBMeta-HTML\fR, these constructs are
recognized and are interpreted like \f(CW%body\fR.
Another feature provided for compatibility reason is the fact that for
simple tags \f(CW%body\fR and \f(CW%attributes\fR are equivalent.
These features are in the current \fBmp4h\fR version but may disappear in
future releases.
.SS "Attributes"
.IX Subsection "Attributes"
Attributes are separated by spaces, tabulations or newlines, and each
attribute must be a valid \fBmp4h\fR entity. For instance with the
definitions above, \f(CW\*(C`\*(C'\fR can not be an attribute since it
must be finished by \f(CW\*(C`\*(C'\fR.
But this is valid:
.PP
.Vb 1
\& />
.Ve
.PP
or even
.PP
.Vb 1
\& />
.Ve
.PP
In these examples, the \f(CW\*(C`foo\*(C'\fR tag has only one argument.
.PP
Under certain circumstances it is necessary to group multiple statements
into a single one. This can be done with double quotes or with the
\&\f(CW\*(C`group\*(C'\fR primitive, e.g.
.PP
.Vb 2
\& />
.Ve
.PP
\&\fBNote:\fR
Unlike \s-1HTML\s0 single quotes can not replace doube quotes for this purpose.
.PP
If double quotes appear in an argument, they must be escaped by a
backslash \f(CW\*(C`\e\*(C'\fR.
.PP
Source:
.PP
.Vb 2
\&
\&
.Ve
.PP
Output:
.PP
.Vb 1
\& Text with double quotes " inside
.Ve
.SS "Macro evaluation"
.IX Subsection "Macro evaluation"
Macros are characterized by
.IP "\(bu" 2
name
.IP "\(bu" 2
container status (simple or complex)
.IP "\(bu" 2
if attributes are expanded or not
.IP "\(bu" 2
function type (primitive or user defined macro)
.IP "\(bu" 2
for primitives, address of corresponding code in memory and for
user defined macros the replacement text
.PP
Characters are read on input until a left angle bracket is found.
Then macro name is read. After that attributes are read, verbatim or not
depending on how this macro as been defined. And if this macro is
complex, its body is read verbatim. When this is finished, some special
sequences in replacement text are replaced (like \f(CW%body\fR, \f(CW%attributes\fR, \f(CW%0\fR, \f(CW%1\fR, etc.) and resulting text is put on
input stack in order to be rescanned.
.PP
\&\fBNote:\fR
By default attributes are evaluated before any replacement.
.PP
Consider the following example, to change text in typewriter font:
.PP
%body
.PP
This definition has a major drawback:
.PP
Source:
.PP
.Vb 1
\& This is an example
.Ve
.PP
Output:
.PP
.Vb 1
\& This is an example
.Ve
.PP
We would like the inner tags be removed.
.PP
First idea is to use an auxiliary variable to know whether we still
are inside such an environment:
.PP
1 \*(L"\*(R" />
\f(CW%body\fR
1 \*(L"\*(R" />
.PP
(the presence of asterisks in \s-1HTML\s0 tags is explained in next section).
.PP
Source:
.PP
.Vb 1
\& This is an example
.Ve
.PP
Output:
.PP
.Vb 1
\& This is an example
.Ve
.PP
But if we use simple tags, as in the example below, our definition does
not seem to work. It is because attributes are expanded before they are
put into replacement text.
.PP
Source:
.PP
.Vb 2
\& %attributes
\& " />
.Ve
.PP
Output:
.PP
.Vb 1
\& This is an example
.Ve
.PP
If we want to prevent this problem we have to forbid attributes
expansion with
.PP
Source:
.PP
.Vb 4
\& ;;;
\& %attributes;;;
\&
\& " />
.Ve
.PP
Output:
.PP
.Vb 1
\& This is an example
.Ve
.SS "Expansion flags"
.IX Subsection "Expansion flags"
When you want to embed some server-side scripting language in your
pages, you face up some weird problems, like in
.PP
>Hello
.PP
The question is how do \fBmp4h\fR know that this input has some extra
delimiters? The answer is that \fBmp4h\fR should not try to handle some
special delimiters, because it cannot handle all of them (there are \s-1ASP,\s0
ePerl, \s-1PHP,...\s0 and some of them are customizable). Now, remember that \fBmp4h\fR
is a macro-processor, not an \s-1XML\s0 parser. So we must focus on macros,and
format our input file so that it can be parsed without any problem.
Previous example may be written
.PP
\*(R">Hello
.PP
because quotes prevent inner right-angle bracket from closing the
\&\f(CW\*(C`a\*(C'\fR tag.
.PP
Another common problem is when we need to print only a begin or an end
tag alone. For instance it is very desirable to define its own headers
and footers with
.PP
... put here some information ....
.PP
Asterisks mark these tags as pseudo-simple tags, which means that they
are complex \s-1HTML\s0 tags, but used as simple tags within \fBmp4h\fR because
tags would not be well nested otherwise.
.PP
This asterisk is called ``trailing star'', it appears at the end of the
tag name.
.PP
Sometimes \s-1HTML\s0 tags are not parsable, as in this javascript code:
.PP
.Vb 5
\& ...
\& document.write(\*(Aq<*img src="foo.gif"\*(Aq);
\& if (text) document.write(\*(Aq alt="\*(Aq+text+\*(Aq"\*(Aq);
\& document.write(\*(Aq>\*(Aq);
\& ...
.Ve
.PP
The ``leading star'' is an asterisk between left-angle bracket and
tag name, which prevents this tag from being parsed.
.PP
That said we can now understand what the \f(CW\*(C`\-\-expansion\*(C'\fR flag is
for. It controls how expansion is performed by mp4h. It is followed by
an integer, which is a bit sum of the following values
.IP "\fB1\fR do not parse unknown tags." 2
.IX Item "1 do not parse unknown tags."
When set, \s-1HTML\s0 tags are not parsed.
When unset, \s-1HTML\s0 tags are parsed, i.e. that attributes and/or body is
collected.
.IP "\fB2\fR unknown tags are assumed being simple." 2
.IX Item "2 unknown tags are assumed being simple."
When set, \s-1HTML\s0 tags are simple by default.
When unset, \s-1HTML\s0 tags are complex by default, unless their attribute
contain a trailing slash or a trailing star appear just after tag name
(see below).
.IP "\fB4\fR trailing star in tag name do not make this tag simple." 2
.IX Item "4 trailing star in tag name do not make this tag simple."
When set, trailing star in tag name has no special effect.
When unset, it causes an \s-1HTML\s0 tag to be simple.
.IP "\fB8\fR an unmatched end tag closes all previous unmatched begin tags." 2
.IX Item "8 an unmatched end tag closes all previous unmatched begin tags."
When set, all missing end closing tags are automatically inserted.
When unset, an unmatched end tag is discarded and interpreted as normal
text, so processing goes on until matching and tag is found.
.IP "\fB16\fR interpret backslashes as printf." 2
.IX Item "16 interpret backslashes as printf."
When set, backslashes before non special characters are removed.
When unset, they are preserved.
.IP "\fB32\fR remove trailing slash in tag attributes." 2
.IX Item "32 remove trailing slash in tag attributes."
When set, remove trailing slash in tag attributes on output.
When unset, they are preserved.
.IP "\fB64\fR do not remove trailing star in tag name." 2
.IX Item "64 do not remove trailing star in tag name."
When set, trailing star after tag name are preserved on output.
When unset, they are removed.
.IP "\fB128\fR do not remove leading star in tag name." 2
.IX Item "128 do not remove leading star in tag name."
When set, leading star before tag name are preserved on output.
When unset, they are removed.
.IP "\fB256\fR do not add a space before trailing slash in tag attributes" 2
.IX Item "256 do not add a space before trailing slash in tag attributes"
By default, a space is inserted before trailing slash in tag attributes.
When set, this space is not prepended.
.IP "\fB1024\fR suppress warnings about bad nested tags." 2
.IX Item "1024 suppress warnings about bad nested tags."
When set, warnings about bad nested tags are not displayed.
When unset, they are printed on standard error.
.IP "\fB2048\fR suppress warnings about missing trailing slash." 2
.IX Item "2048 suppress warnings about missing trailing slash."
When set, warnings about missing trailing slash are not displayed.
When unset, they are printed on standard error.
.PP
Run
.PP
.Vb 1
\& mp4h \-h
.Ve
.PP
to find default value. Current value matches \s-1HTML\s0 syntax, and it will
tend to zero when \s-1XHTML\s0 syntax becomes more familiar.
.SH "AUTHOR"
.IX Header "AUTHOR"
Denis Barbier \f(CW\*(C`\*(C'\fR
.PP
Mp4h has its own
homepage \f(CW\*(C`\*(C'\fR.
.SH "THANKS"
.IX Header "THANKS"
Sincere thanks to Brian J. Fox for writing \fBMeta-HTML\fR and Rene
Seindal for maintaining this wonderful macro parser called \s-1GNU\s0 \fBm4\fR.