269 lines
9.2 KiB
Plaintext
269 lines
9.2 KiB
Plaintext
divert(-1) -*-Text-*-
|
||
` Copyright (c) 1991 Free Software Foundation, Inc.'
|
||
` This file defines and documents the M4 macros used '
|
||
` to preprocess some GNU manuals'
|
||
` $Id$'
|
||
|
||
I. INTRODUCTION
|
||
|
||
This collection of M4 macros is meant to help in pre-processing texinfo
|
||
files to allow configuring them by hosts; for example, the reader of an
|
||
as manual who only has access to a 386 may not really want to see crud about
|
||
VAXen.
|
||
|
||
A preprocessor is used, rather than extending texinfo, because this
|
||
way we can hack the conditionals in only one place; otherwise we would
|
||
have to write TeX macros, update makeinfo, and update the Emacs
|
||
info-formatting functions.
|
||
|
||
II. COMPATIBILITY
|
||
|
||
These macros should work with GNU m4 and System V m4; they do not work
|
||
with Sun or Berkeley M4.
|
||
|
||
III. USAGE
|
||
|
||
A. M4 INVOCATION
|
||
Assume this file is called "pretex.m4". Then, to preprocess a
|
||
document "mybook.texinfo" you might do something like the following:
|
||
|
||
m4 pretex.m4 none.m4 PARTIC.m4 mybook.texinfo >mybook-PARTIC.texinfo
|
||
|
||
---where your path is set to find GNU or SysV "m4", and the other m4
|
||
files mentioned are as follows:
|
||
|
||
none.m4: A file that defines, as 0, all the options you might
|
||
want to turn on using the conditionals defined below.
|
||
Unlike the C preprocessor, m4 does not default
|
||
undefined macros to 0. For example, here is a "none.m4"
|
||
I have been using:
|
||
_divert__(-1)
|
||
|
||
_define__(<_ALL_ARCH__>,<0>)
|
||
_define__(<_INTERNALS__>,<0>)
|
||
|
||
_define__(<_AMD29K__>,<0>)
|
||
_define__(<_I80386__>,<0>)
|
||
_define__(<_I960__>,<0>)
|
||
_define__(<_M680X0__>,<0>)
|
||
_define__(<_SPARC__>,<0>)
|
||
_define__(<_VAX__>,<0>)
|
||
|
||
_divert__<>
|
||
|
||
PARTIC.m4: A file that turns on whichever options you actually
|
||
want the manual configured for, in this particular
|
||
instance. Its contents are similar to one or more of
|
||
the lines in "none.m4", but of course the second
|
||
argument to _define__ is <1> rather than <0>.
|
||
|
||
This is also a convenient place to _define__ any macros
|
||
that you want to expand to different text for
|
||
different configurations---for example, the name of
|
||
the program being described.
|
||
|
||
Naturally, these are just suggested conventions; you could put your macro
|
||
definitions in any files or combinations of files you like.
|
||
|
||
These macros use the characters < and > as m4 quotes; if you need
|
||
these characters in your text, you will also want to use the macros
|
||
_0__ and _1__ from this package---see the description of "Quote
|
||
Handling" in the "Implementation" section below.
|
||
|
||
B. WHAT GOES IN THE PRE-TEXINFO SOURCE
|
||
|
||
For the most part, the text of your book. In addition, you can
|
||
have text that is included only conditionally, using the macros
|
||
_if__ and _fi__ defined below. They BOTH take an argument! This is
|
||
primarily meant for readability (so a human can more easily see what
|
||
conditional end matches what conditional beginning), but the argument
|
||
is actually used in the _fi__ as well as the _if__ implementation.
|
||
You should always give a _fi__ the same argument as its matching
|
||
_if__. Other arguments may appear to work for a while, but are almost
|
||
certain to produce the wrong output for some configurations.
|
||
|
||
For example, here is an excerpt from the very beginning of the
|
||
documentation for GNU as, to name the info file appropriately for
|
||
different configurations:
|
||
_if__(_ALL_ARCH__)
|
||
@setfilename as.info
|
||
_fi__(_ALL_ARCH__)
|
||
_if__(_M680X0__ && !_ALL_ARCH__)
|
||
@setfilename as-m680x0.info
|
||
_fi__(_M680X0__ && !_ALL_ARCH__)
|
||
_if__(_AMD29K__ && !_ALL_ARCH__)
|
||
@setfilename as-29k.info
|
||
_fi__(_AMD29K__ && !_ALL_ARCH__)
|
||
|
||
Note that you can use Boolean expressions in the arguments; the
|
||
expression language is that of the built-in m4 macro `eval', described
|
||
in the m4 manual.
|
||
|
||
IV. IMPLEMENTATION
|
||
|
||
A.PRIMITIVE RENAMING
|
||
First, we redefine m4's built-ins to avoid conflict with plain text.
|
||
The naming convention used is that our macros all begin with a single
|
||
underbar and end with two underbars. The asymmetry is meant to avoid
|
||
conflict with some other conventions (which we may want to document) that
|
||
are intended to avoid conflict, like ANSI C predefined macros.
|
||
|
||
define(`_undefine__',defn(`undefine'))
|
||
define(`_define__',defn(`define'))
|
||
define(`_defn__',defn(`defn'))
|
||
define(`_ppf__',`_define__(`_$1__',_defn__(`$1'))_undefine__(`$1')')
|
||
_ppf__(`builtin')
|
||
_ppf__(`changecom')
|
||
_ppf__(`changequote')
|
||
_ppf__(`decr')
|
||
_ppf__(`define')
|
||
_ppf__(`defn')
|
||
_ppf__(`divert')
|
||
_ppf__(`divnum')
|
||
_ppf__(`dnl')
|
||
_ppf__(`dumpdef')
|
||
_ppf__(`errprint')
|
||
_ppf__(`esyscmd')
|
||
_ppf__(`eval')
|
||
_ppf__(`format')
|
||
_ppf__(`ifdef')
|
||
_ppf__(`ifelse')
|
||
_ppf__(`include')
|
||
_ppf__(`incr')
|
||
_ppf__(`index')
|
||
_ppf__(`len')
|
||
_ppf__(`m4exit')
|
||
_ppf__(`m4wrap')
|
||
_ppf__(`maketemp')
|
||
_ppf__(`patsubst')
|
||
_ppf__(`popdef')
|
||
_ppf__(`pushdef')
|
||
_ppf__(`regexp')
|
||
_ppf__(`shift')
|
||
_ppf__(`sinclude')
|
||
_ppf__(`substr')
|
||
_ppf__(`syscmd')
|
||
_ppf__(`sysval')
|
||
_ppf__(`traceoff')
|
||
_ppf__(`traceon')
|
||
_ppf__(`translit')
|
||
_ppf__(`undefine')
|
||
_ppf__(`undivert')
|
||
_ppf__(`unix')
|
||
|
||
B. QUOTE HANDLING.
|
||
|
||
The characters used as quotes by M4, by default, are unfortunately
|
||
quite likely to occur in ordinary text. To avoid surprises, we will
|
||
use the characters <> ---which are just as suggestive (more so to
|
||
Francophones, perhaps) but a little less common in text (save for
|
||
those poor Francophones. You win some, you lose some). Still, we
|
||
expect also to have to set < and > occasionally in text; to do that,
|
||
we define a macro to turn off quote handling (_0__) and a macro to
|
||
turn it back on (_1__), according to our convention.
|
||
|
||
BEWARE: This seems to make < and > unusable as relational operations
|
||
in calls to the builtin "eval". So far I've gotten
|
||
along without; but a better choice may be possible.
|
||
|
||
Note that we postponed this for a while, for convenience in discussing
|
||
the issue and in the primitive renaming---not to mention in defining
|
||
_0__ and _1__ themselves! However, the quote redefinitions MUST
|
||
precede the _if__ / _fi__ definitions, because M4 will expand the text
|
||
as given---if we use the wrong quotes here, we will get the wrong
|
||
quotes when we use the conditionals.
|
||
|
||
_define__(_0__,`_changequote__(,)')_define__(_1__,`_changequote__(<,>)')
|
||
_1__
|
||
|
||
C. CONDITIONALS
|
||
|
||
We define two macros, _if__ and _fi__. BOTH take arguments! This is
|
||
meant both to help the human reader match up a _fi__ with its
|
||
corresponding _if__ and to aid in the implementation. You may use the
|
||
full expression syntax supported by M4 (see docn of `eval' builtin in
|
||
the m4 manual).
|
||
|
||
The conditional macros are carefully defined to avoid introducing
|
||
extra whitespace (i.e., blank lines or blank characters). One side
|
||
effect exists---
|
||
|
||
BEWARE: text following an `_if__' on the same line is
|
||
DISCARDED even if the condition is true; text
|
||
following a `_fi__' on the same line is also
|
||
always discarded.
|
||
|
||
The recommended convention is to always place _if__ and _fi__ on a
|
||
line by themselves. This will also aid the human reader. TeX won't
|
||
care about the line breaks; as for info, you may want to insert calls
|
||
to `@refill' at the end of paragraphs containing conditionalized text,
|
||
where you don't want line breaks separating unconditional from
|
||
conditional text. info formatting will then give you nice looking
|
||
paragraphs in the info file.
|
||
|
||
Nesting: conditionals are designed to nest, in the following way:
|
||
*nothing* is output between an outer pair of false conditionals, even
|
||
if there are true conditionals inside. A false conditional "defeats"
|
||
all conditionals within it. The counter _IF_FS__ is used to
|
||
implement this; kindly avoid redefining it directly.
|
||
|
||
_define__(<_IF_FS__>,<0>)
|
||
|
||
NOTE: The definitions for our "pushf" and "popf" macros use eval
|
||
rather than incr and decr, because GNU m4 (0.75) tries to call eval
|
||
for us when we say "incr" or "decr"---but doesn't notice we've changed
|
||
eval's name.
|
||
|
||
_define__(
|
||
<_pushf__>,
|
||
<_define__(<_IF_FS__>,
|
||
_eval__((_IF_FS__)+1))>)
|
||
_define__(
|
||
<_popf__>,
|
||
<_ifelse__(0,_IF_FS__,
|
||
<<>_dnl__<>>,
|
||
<_define__(<_IF_FS__>,_eval__((_IF_FS__)-1))>)>)
|
||
|
||
_define__(
|
||
<_if__>,
|
||
<_ifelse__(1,_eval__( ($1) ),
|
||
<<>_dnl__<>>,
|
||
<_pushf__<>_divert__(-1)>)>)
|
||
_define__(
|
||
<_fi__>,
|
||
<_ifelse__(1,_eval__( ($1) ),
|
||
<<>_dnl__<>>,
|
||
<_popf__<>_ifelse__(0,_IF_FS__,
|
||
<_divert__<>_dnl__<>>,<>)>)>)
|
||
|
||
D. CHAPTER/SECTION MACRO
|
||
In a parametrized manual, the heading level may need to be calculated;
|
||
for example, a manual that has a chapter on machine dependencies
|
||
should be conditionally structured as follows:
|
||
- IF the manual is configured for a SINGLE machine type, use
|
||
the chapter heading for that machine type, and run headings down
|
||
from there (top level for a particular machine is chapter, then within
|
||
that we have section, subsection etc);
|
||
- ELSE, if MANY machine types are described in the chapter,
|
||
use a generic chapter heading such as "@chapter Machine Dependencies",
|
||
use "section" for the top level description of EACH machine, and run
|
||
headings down from there (top level for a particular machine is
|
||
section, then within that we have subsection, subsubsection etc).
|
||
|
||
The macro <_CHAPSEC__> is for this purpose: its argument is evaluated (so
|
||
you can construct expressions to express choices such as above), then
|
||
expands as follows:
|
||
0: @chapter
|
||
1: @section
|
||
2: @subsection
|
||
3: @subsubsection
|
||
...and so on.
|
||
|
||
_define__(<_CHAPSEC__>,<@_cs__(_eval__($1))>)
|
||
_define__(<_cs__>,<_ifelse__(
|
||
0, $1, <chapter>,
|
||
1, $1, <section>,
|
||
<sub<>_cs__(_eval__($1 - 1))>)>)
|
||
|
||
_divert__<>_dnl__<>
|