aboutsummaryrefslogtreecommitdiff
path: root/gas/doc/pretex.m4
blob: da62d49555350627ac626f3da81b49de6ad9e595 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
divert(-1)				-*-Text-*-

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
include 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 builtin 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__(`dnl')
_ppf__(`dumpdef')
_ppf__(`errprint')
_ppf__(`eval')
_ppf__(`ifdef')
_ppf__(`ifelse')
_ppf__(`include')
_ppf__(`incr')
_ppf__(`index')
_ppf__(`len')
_ppf__(`m4exit')
_ppf__(`m4wrap')
_ppf__(`maketemp')
_ppf__(`popdef')
_ppf__(`pushdef')
_ppf__(`shift')
_ppf__(`sinclude')
_ppf__(`substr')
_ppf__(`syscmd')
_ppf__(`sysval')
_ppf__(`traceoff')
_ppf__(`traceon')
_ppf__(`translit')
_ppf__(`undefine')
_ppf__(`undivert')

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>)
_define__(
	<_pushf__>,
	<_define__(<_IF_FS__>,
		_incr__(_IF_FS__))>)
_define__(
	<_popf__>,
	<_ifelse__(0,_IF_FS__,
			<<>_dnl__<>>,
			<_define__(<_IF_FS__>,_decr__(_IF_FS__))>)>)

_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 <_CS__> 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__(<_CS__>,<@_cs__(_eval__($1))>)
_define__(<_cs__>,<_ifelse__(
			0, $1, <chapter>,
			1, $1, <section>,
				<sub<>_cs__(_eval__($1 - 1))>)>)

_divert__<>_dnl__<>