]> git.cameronkatri.com Git - mandoc.git/blob - man_macro.c
Added RS/RE macro pair (had to adjust closing rules, sec/ssec/rs/par).
[mandoc.git] / man_macro.c
1 /* $Id: man_macro.c,v 1.21 2009/08/19 09:14:50 kristaps Exp $ */
2 /*
3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 #include <assert.h>
18 #include <ctype.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include "libman.h"
23
24 #define REW_REWIND (0) /* See rew_scope(). */
25 #define REW_NOHALT (1) /* See rew_scope(). */
26 #define REW_HALT (2) /* See rew_scope(). */
27
28 static int in_line_eoln(MACRO_PROT_ARGS);
29 static int blk_imp(MACRO_PROT_ARGS);
30 static int blk_close(MACRO_PROT_ARGS);
31
32 static int rew_scope(enum man_type, struct man *, int);
33 static int rew_dohalt(int, enum man_type,
34 const struct man_node *);
35 static int rew_block(int, enum man_type,
36 const struct man_node *);
37
38 const struct man_macro __man_macros[MAN_MAX] = {
39 { in_line_eoln, 0 }, /* br */
40 { in_line_eoln, 0 }, /* TH */
41 { blk_imp, 0 }, /* SH */
42 { blk_imp, 0 }, /* SS */
43 { blk_imp, MAN_SCOPED }, /* TP */
44 { blk_imp, 0 }, /* LP */
45 { blk_imp, 0 }, /* PP */
46 { blk_imp, 0 }, /* P */
47 { blk_imp, 0 }, /* IP */
48 { blk_imp, 0 }, /* HP */
49 { in_line_eoln, MAN_SCOPED }, /* SM */
50 { in_line_eoln, MAN_SCOPED }, /* SB */
51 { in_line_eoln, 0 }, /* BI */
52 { in_line_eoln, 0 }, /* IB */
53 { in_line_eoln, 0 }, /* BR */
54 { in_line_eoln, 0 }, /* RB */
55 { in_line_eoln, MAN_SCOPED }, /* R */
56 { in_line_eoln, MAN_SCOPED }, /* B */
57 { in_line_eoln, MAN_SCOPED }, /* I */
58 { in_line_eoln, 0 }, /* IR */
59 { in_line_eoln, 0 }, /* RI */
60 { in_line_eoln, 0 }, /* na */
61 { in_line_eoln, 0 }, /* i */
62 { in_line_eoln, 0 }, /* sp */
63 { in_line_eoln, 0 }, /* nf */
64 { in_line_eoln, 0 }, /* fi */
65 { in_line_eoln, 0 }, /* r */
66 { blk_close, 0 }, /* RE */
67 { blk_imp, 0 }, /* RS */
68 };
69
70 const struct man_macro * const man_macros = __man_macros;
71
72
73 int
74 man_unscope(struct man *m, const struct man_node *n)
75 {
76
77 assert(n);
78 m->next = MAN_NEXT_SIBLING;
79
80 /* LINTED */
81 while (m->last != n) {
82 if ( ! man_valid_post(m))
83 return(0);
84 if ( ! man_action_post(m))
85 return(0);
86 m->last = m->last->parent;
87 assert(m->last);
88 }
89
90 if ( ! man_valid_post(m))
91 return(0);
92 return(man_action_post(m));
93 }
94
95
96 static int
97 rew_block(int ntok, enum man_type type, const struct man_node *n)
98 {
99
100 if (MAN_BLOCK == type && ntok == n->parent->tok &&
101 MAN_BODY == n->parent->type)
102 return(REW_REWIND);
103 return(ntok == n->tok ? REW_HALT : REW_NOHALT);
104 }
105
106
107 /*
108 * There are three scope levels: scoped to the root (all), scoped to the
109 * section (all less sections), and scoped to subsections (all less
110 * sections and subsections).
111 */
112 static int
113 rew_dohalt(int tok, enum man_type type, const struct man_node *n)
114 {
115 int c;
116
117 if (MAN_ROOT == n->type)
118 return(REW_HALT);
119 assert(n->parent);
120 if (MAN_ROOT == n->parent->type)
121 return(REW_REWIND);
122 if (MAN_VALID & n->flags)
123 return(REW_NOHALT);
124
125 /* Rewind to ourselves, first. */
126 if (type == n->type && tok == n->tok)
127 return(REW_REWIND);
128
129 switch (tok) {
130 case (MAN_SH):
131 break;
132 case (MAN_SS):
133 /* Rewind to a section, if a block. */
134 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
135 return(c);
136 break;
137 case (MAN_RS):
138 /* Rewind to a subsection, if a block. */
139 if (REW_NOHALT != (c = rew_block(MAN_SS, type, n)))
140 return(c);
141 /* Rewind to a section, if a block. */
142 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
143 return(c);
144 break;
145 default:
146 /* Rewind to an offsetter, if a block. */
147 if (REW_NOHALT != (c = rew_block(MAN_RS, type, n)))
148 return(c);
149 /* Rewind to a subsection, if a block. */
150 if (REW_NOHALT != (c = rew_block(MAN_SS, type, n)))
151 return(c);
152 /* Rewind to a section, if a block. */
153 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
154 return(c);
155 break;
156 }
157
158 return(REW_NOHALT);
159 }
160
161
162 /*
163 * Rewinding entails ascending the parse tree until a coherent point,
164 * for example, the `SH' macro will close out any intervening `SS'
165 * scopes. When a scope is closed, it must be validated and actioned.
166 */
167 static int
168 rew_scope(enum man_type type, struct man *m, int tok)
169 {
170 struct man_node *n;
171 int c;
172
173 /* LINTED */
174 for (n = m->last; n; n = n->parent) {
175 /*
176 * Whether we should stop immediately (REW_HALT), stop
177 * and rewind until this point (REW_REWIND), or keep
178 * rewinding (REW_NOHALT).
179 */
180 c = rew_dohalt(tok, type, n);
181 if (REW_HALT == c)
182 return(1);
183 if (REW_REWIND == c)
184 break;
185 }
186
187 /* Rewind until the current point. */
188
189 assert(n);
190 return(man_unscope(m, n));
191 }
192
193
194 /* ARGSUSED */
195 int
196 blk_close(MACRO_PROT_ARGS)
197 {
198 int ntok;
199 const struct man_node *nn;
200
201 switch (tok) {
202 case (MAN_RE):
203 ntok = MAN_RS;
204 break;
205 default:
206 abort();
207 /* NOTREACHED */
208 }
209
210 for (nn = m->last->parent; nn; nn = nn->parent)
211 if (ntok == nn->tok)
212 break;
213
214 if (NULL == nn)
215 if ( ! man_pwarn(m, line, ppos, WNOSCOPE))
216 return(0);
217
218 if ( ! rew_scope(MAN_BODY, m, ntok))
219 return(0);
220 if ( ! rew_scope(MAN_BLOCK, m, ntok))
221 return(0);
222 m->next = MAN_NEXT_SIBLING;
223 return(1);
224 }
225
226
227 /*
228 * Parse an implicit-block macro. These contain a MAN_HEAD and a
229 * MAN_BODY contained within a MAN_BLOCK. Rules for closing out other
230 * scopes, such as `SH' closing out an `SS', are defined in the rew
231 * routines.
232 */
233 int
234 blk_imp(MACRO_PROT_ARGS)
235 {
236 int w, la;
237 char *p;
238
239 /* Close out prior scopes. */
240
241 if ( ! rew_scope(MAN_BODY, m, tok))
242 return(0);
243 if ( ! rew_scope(MAN_BLOCK, m, tok))
244 return(0);
245
246 /* Allocate new block & head scope. */
247
248 if ( ! man_block_alloc(m, line, ppos, tok))
249 return(0);
250 if ( ! man_head_alloc(m, line, ppos, tok))
251 return(0);
252
253 /* Add line arguments. */
254
255 for (;;) {
256 la = *pos;
257 w = man_args(m, line, pos, buf, &p);
258
259 if (-1 == w)
260 return(0);
261 if (0 == w)
262 break;
263
264 if ( ! man_word_alloc(m, line, la, p))
265 return(0);
266 }
267
268 /* Close out head and open body (unless MAN_SCOPE). */
269
270 if (MAN_SCOPED & man_macros[tok].flags) {
271 m->flags |= MAN_BLINE;
272 return(1);
273 } else if ( ! rew_scope(MAN_HEAD, m, tok))
274 return(0);
275
276 return(man_body_alloc(m, line, ppos, tok));
277 }
278
279
280 int
281 in_line_eoln(MACRO_PROT_ARGS)
282 {
283 int w, la;
284 char *p;
285 struct man_node *n;
286
287 if ( ! man_elem_alloc(m, line, ppos, tok))
288 return(0);
289
290 n = m->last;
291
292 for (;;) {
293 la = *pos;
294 w = man_args(m, line, pos, buf, &p);
295
296 if (-1 == w)
297 return(0);
298 if (0 == w)
299 break;
300
301 if ( ! man_word_alloc(m, line, la, p))
302 return(0);
303 }
304
305 if (n == m->last && (MAN_SCOPED & man_macros[tok].flags)) {
306 m->flags |= MAN_ELINE;
307 return(1);
308 }
309
310 /*
311 * Note that when TH is pruned, we'll be back at the root, so
312 * make sure that we don't clobber as its sibling.
313 */
314
315 /* FIXME: clean this to use man_unscope(). */
316
317 for ( ; m->last; m->last = m->last->parent) {
318 if (m->last == n)
319 break;
320 if (m->last->type == MAN_ROOT)
321 break;
322 if ( ! man_valid_post(m))
323 return(0);
324 if ( ! man_action_post(m))
325 return(0);
326 }
327
328 assert(m->last);
329
330 /*
331 * Same here regarding whether we're back at the root.
332 */
333
334 if (m->last->type != MAN_ROOT && ! man_valid_post(m))
335 return(0);
336 if (m->last->type != MAN_ROOT && ! man_action_post(m))
337 return(0);
338 if (m->last->type != MAN_ROOT)
339 m->next = MAN_NEXT_SIBLING;
340
341 return(1);
342 }
343
344
345 int
346 man_macroend(struct man *m)
347 {
348
349 return(man_unscope(m, m->first));
350 }
351