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