man.c revision 1.1.1.11 1 1.1.1.11 joerg /* $Vendor-Id: man.c,v 1.107 2011/03/29 08:30:49 kristaps Exp $ */
2 1.1 joerg /*
3 1.1.1.11 joerg * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps (at) bsd.lv>
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.1.4 joerg #ifdef HAVE_CONFIG_H
18 1.1.1.4 joerg #include "config.h"
19 1.1.1.4 joerg #endif
20 1.1.1.4 joerg
21 1.1 joerg #include <sys/types.h>
22 1.1 joerg
23 1.1 joerg #include <assert.h>
24 1.1 joerg #include <stdarg.h>
25 1.1 joerg #include <stdlib.h>
26 1.1 joerg #include <stdio.h>
27 1.1 joerg #include <string.h>
28 1.1 joerg
29 1.1.1.11 joerg #include "man.h"
30 1.1.1.6 joerg #include "mandoc.h"
31 1.1 joerg #include "libman.h"
32 1.1.1.3 joerg #include "libmandoc.h"
33 1.1 joerg
34 1.1 joerg const char *const __man_macronames[MAN_MAX] = {
35 1.1 joerg "br", "TH", "SH", "SS",
36 1.1 joerg "TP", "LP", "PP", "P",
37 1.1 joerg "IP", "HP", "SM", "SB",
38 1.1 joerg "BI", "IB", "BR", "RB",
39 1.1 joerg "R", "B", "I", "IR",
40 1.1.1.10 joerg "RI", "na", "sp", "nf",
41 1.1.1.10 joerg "fi", "RE", "RS", "DT",
42 1.1.1.10 joerg "UC", "PD", "AT", "in",
43 1.1.1.10 joerg "ft"
44 1.1 joerg };
45 1.1 joerg
46 1.1 joerg const char * const *man_macronames = __man_macronames;
47 1.1 joerg
48 1.1.1.11 joerg static struct man_node *man_node_alloc(struct man *, int, int,
49 1.1.1.5 joerg enum man_type, enum mant);
50 1.1 joerg static int man_node_append(struct man *,
51 1.1 joerg struct man_node *);
52 1.1.1.5 joerg static void man_node_free(struct man_node *);
53 1.1.1.5 joerg static void man_node_unlink(struct man *,
54 1.1.1.5 joerg struct man_node *);
55 1.1.1.6 joerg static int man_ptext(struct man *, int, char *, int);
56 1.1.1.6 joerg static int man_pmacro(struct man *, int, char *, int);
57 1.1 joerg static void man_free1(struct man *);
58 1.1.1.3 joerg static void man_alloc1(struct man *);
59 1.1.1.10 joerg static int man_descope(struct man *, int, int);
60 1.1 joerg
61 1.1 joerg
62 1.1 joerg const struct man_node *
63 1.1 joerg man_node(const struct man *m)
64 1.1 joerg {
65 1.1 joerg
66 1.1.1.10 joerg assert( ! (MAN_HALT & m->flags));
67 1.1.1.10 joerg return(m->first);
68 1.1 joerg }
69 1.1 joerg
70 1.1 joerg
71 1.1 joerg const struct man_meta *
72 1.1 joerg man_meta(const struct man *m)
73 1.1 joerg {
74 1.1 joerg
75 1.1.1.10 joerg assert( ! (MAN_HALT & m->flags));
76 1.1.1.10 joerg return(&m->meta);
77 1.1 joerg }
78 1.1 joerg
79 1.1 joerg
80 1.1.1.3 joerg void
81 1.1 joerg man_reset(struct man *man)
82 1.1 joerg {
83 1.1 joerg
84 1.1 joerg man_free1(man);
85 1.1.1.3 joerg man_alloc1(man);
86 1.1 joerg }
87 1.1 joerg
88 1.1 joerg
89 1.1 joerg void
90 1.1 joerg man_free(struct man *man)
91 1.1 joerg {
92 1.1 joerg
93 1.1 joerg man_free1(man);
94 1.1 joerg free(man);
95 1.1 joerg }
96 1.1 joerg
97 1.1 joerg
98 1.1 joerg struct man *
99 1.1.1.11 joerg man_alloc(struct regset *regs, struct mparse *parse)
100 1.1 joerg {
101 1.1 joerg struct man *p;
102 1.1 joerg
103 1.1.1.3 joerg p = mandoc_calloc(1, sizeof(struct man));
104 1.1 joerg
105 1.1 joerg man_hash_init();
106 1.1.1.11 joerg p->parse = parse;
107 1.1.1.8 joerg p->regs = regs;
108 1.1.1.3 joerg
109 1.1.1.3 joerg man_alloc1(p);
110 1.1 joerg return(p);
111 1.1 joerg }
112 1.1 joerg
113 1.1 joerg
114 1.1 joerg int
115 1.1 joerg man_endparse(struct man *m)
116 1.1 joerg {
117 1.1 joerg
118 1.1.1.10 joerg assert( ! (MAN_HALT & m->flags));
119 1.1.1.10 joerg if (man_macroend(m))
120 1.1 joerg return(1);
121 1.1 joerg m->flags |= MAN_HALT;
122 1.1 joerg return(0);
123 1.1 joerg }
124 1.1 joerg
125 1.1 joerg
126 1.1 joerg int
127 1.1.1.6 joerg man_parseln(struct man *m, int ln, char *buf, int offs)
128 1.1 joerg {
129 1.1 joerg
130 1.1.1.11 joerg m->flags |= MAN_NEWLINE;
131 1.1.1.11 joerg
132 1.1.1.10 joerg assert( ! (MAN_HALT & m->flags));
133 1.1.1.11 joerg
134 1.1.1.11 joerg return (mandoc_getcontrol(buf, &offs) ?
135 1.1.1.6 joerg man_pmacro(m, ln, buf, offs) :
136 1.1.1.6 joerg man_ptext(m, ln, buf, offs));
137 1.1 joerg }
138 1.1 joerg
139 1.1 joerg
140 1.1 joerg static void
141 1.1 joerg man_free1(struct man *man)
142 1.1 joerg {
143 1.1 joerg
144 1.1 joerg if (man->first)
145 1.1.1.5 joerg man_node_delete(man, man->first);
146 1.1 joerg if (man->meta.title)
147 1.1 joerg free(man->meta.title);
148 1.1 joerg if (man->meta.source)
149 1.1 joerg free(man->meta.source);
150 1.1.1.11 joerg if (man->meta.date)
151 1.1.1.11 joerg free(man->meta.date);
152 1.1 joerg if (man->meta.vol)
153 1.1 joerg free(man->meta.vol);
154 1.1.1.6 joerg if (man->meta.msec)
155 1.1.1.6 joerg free(man->meta.msec);
156 1.1 joerg }
157 1.1 joerg
158 1.1 joerg
159 1.1.1.3 joerg static void
160 1.1 joerg man_alloc1(struct man *m)
161 1.1 joerg {
162 1.1 joerg
163 1.1.1.3 joerg memset(&m->meta, 0, sizeof(struct man_meta));
164 1.1 joerg m->flags = 0;
165 1.1.1.3 joerg m->last = mandoc_calloc(1, sizeof(struct man_node));
166 1.1 joerg m->first = m->last;
167 1.1 joerg m->last->type = MAN_ROOT;
168 1.1.1.5 joerg m->last->tok = MAN_MAX;
169 1.1 joerg m->next = MAN_NEXT_CHILD;
170 1.1 joerg }
171 1.1 joerg
172 1.1 joerg
173 1.1 joerg static int
174 1.1 joerg man_node_append(struct man *man, struct man_node *p)
175 1.1 joerg {
176 1.1 joerg
177 1.1 joerg assert(man->last);
178 1.1 joerg assert(man->first);
179 1.1 joerg assert(MAN_ROOT != p->type);
180 1.1 joerg
181 1.1 joerg switch (man->next) {
182 1.1 joerg case (MAN_NEXT_SIBLING):
183 1.1 joerg man->last->next = p;
184 1.1 joerg p->prev = man->last;
185 1.1 joerg p->parent = man->last->parent;
186 1.1 joerg break;
187 1.1 joerg case (MAN_NEXT_CHILD):
188 1.1 joerg man->last->child = p;
189 1.1 joerg p->parent = man->last;
190 1.1 joerg break;
191 1.1 joerg default:
192 1.1 joerg abort();
193 1.1 joerg /* NOTREACHED */
194 1.1 joerg }
195 1.1 joerg
196 1.1.1.5 joerg assert(p->parent);
197 1.1 joerg p->parent->nchild++;
198 1.1 joerg
199 1.1 joerg if ( ! man_valid_pre(man, p))
200 1.1 joerg return(0);
201 1.1 joerg
202 1.1 joerg switch (p->type) {
203 1.1 joerg case (MAN_HEAD):
204 1.1 joerg assert(MAN_BLOCK == p->parent->type);
205 1.1 joerg p->parent->head = p;
206 1.1 joerg break;
207 1.1.1.11 joerg case (MAN_TAIL):
208 1.1.1.11 joerg assert(MAN_BLOCK == p->parent->type);
209 1.1.1.11 joerg p->parent->tail = p;
210 1.1.1.11 joerg break;
211 1.1 joerg case (MAN_BODY):
212 1.1 joerg assert(MAN_BLOCK == p->parent->type);
213 1.1 joerg p->parent->body = p;
214 1.1 joerg break;
215 1.1 joerg default:
216 1.1 joerg break;
217 1.1 joerg }
218 1.1 joerg
219 1.1 joerg man->last = p;
220 1.1 joerg
221 1.1 joerg switch (p->type) {
222 1.1.1.10 joerg case (MAN_TBL):
223 1.1.1.10 joerg /* FALLTHROUGH */
224 1.1 joerg case (MAN_TEXT):
225 1.1 joerg if ( ! man_valid_post(man))
226 1.1 joerg return(0);
227 1.1 joerg break;
228 1.1 joerg default:
229 1.1 joerg break;
230 1.1 joerg }
231 1.1 joerg
232 1.1 joerg return(1);
233 1.1 joerg }
234 1.1 joerg
235 1.1 joerg
236 1.1 joerg static struct man_node *
237 1.1.1.11 joerg man_node_alloc(struct man *m, int line, int pos,
238 1.1.1.11 joerg enum man_type type, enum mant tok)
239 1.1 joerg {
240 1.1 joerg struct man_node *p;
241 1.1 joerg
242 1.1.1.3 joerg p = mandoc_calloc(1, sizeof(struct man_node));
243 1.1 joerg p->line = line;
244 1.1 joerg p->pos = pos;
245 1.1 joerg p->type = type;
246 1.1 joerg p->tok = tok;
247 1.1.1.11 joerg
248 1.1.1.11 joerg if (MAN_NEWLINE & m->flags)
249 1.1.1.11 joerg p->flags |= MAN_LINE;
250 1.1.1.11 joerg m->flags &= ~MAN_NEWLINE;
251 1.1 joerg return(p);
252 1.1 joerg }
253 1.1 joerg
254 1.1 joerg
255 1.1 joerg int
256 1.1.1.5 joerg man_elem_alloc(struct man *m, int line, int pos, enum mant tok)
257 1.1 joerg {
258 1.1 joerg struct man_node *p;
259 1.1 joerg
260 1.1.1.11 joerg p = man_node_alloc(m, line, pos, MAN_ELEM, tok);
261 1.1 joerg if ( ! man_node_append(m, p))
262 1.1 joerg return(0);
263 1.1 joerg m->next = MAN_NEXT_CHILD;
264 1.1 joerg return(1);
265 1.1 joerg }
266 1.1 joerg
267 1.1 joerg
268 1.1 joerg int
269 1.1.1.11 joerg man_tail_alloc(struct man *m, int line, int pos, enum mant tok)
270 1.1 joerg {
271 1.1 joerg struct man_node *p;
272 1.1 joerg
273 1.1.1.11 joerg p = man_node_alloc(m, line, pos, MAN_TAIL, tok);
274 1.1 joerg if ( ! man_node_append(m, p))
275 1.1 joerg return(0);
276 1.1 joerg m->next = MAN_NEXT_CHILD;
277 1.1 joerg return(1);
278 1.1 joerg }
279 1.1 joerg
280 1.1 joerg
281 1.1 joerg int
282 1.1.1.11 joerg man_head_alloc(struct man *m, int line, int pos, enum mant tok)
283 1.1 joerg {
284 1.1 joerg struct man_node *p;
285 1.1 joerg
286 1.1.1.11 joerg p = man_node_alloc(m, line, pos, MAN_HEAD, tok);
287 1.1 joerg if ( ! man_node_append(m, p))
288 1.1 joerg return(0);
289 1.1 joerg m->next = MAN_NEXT_CHILD;
290 1.1 joerg return(1);
291 1.1 joerg }
292 1.1 joerg
293 1.1 joerg
294 1.1 joerg int
295 1.1.1.11 joerg man_body_alloc(struct man *m, int line, int pos, enum mant tok)
296 1.1 joerg {
297 1.1 joerg struct man_node *p;
298 1.1 joerg
299 1.1.1.11 joerg p = man_node_alloc(m, line, pos, MAN_BODY, tok);
300 1.1 joerg if ( ! man_node_append(m, p))
301 1.1 joerg return(0);
302 1.1 joerg m->next = MAN_NEXT_CHILD;
303 1.1 joerg return(1);
304 1.1 joerg }
305 1.1 joerg
306 1.1.1.10 joerg
307 1.1.1.11 joerg int
308 1.1.1.11 joerg man_block_alloc(struct man *m, int line, int pos, enum mant tok)
309 1.1.1.11 joerg {
310 1.1.1.11 joerg struct man_node *p;
311 1.1.1.10 joerg
312 1.1.1.11 joerg p = man_node_alloc(m, line, pos, MAN_BLOCK, tok);
313 1.1.1.11 joerg if ( ! man_node_append(m, p))
314 1.1.1.10 joerg return(0);
315 1.1.1.11 joerg m->next = MAN_NEXT_CHILD;
316 1.1.1.10 joerg return(1);
317 1.1.1.10 joerg }
318 1.1 joerg
319 1.1.1.6 joerg int
320 1.1.1.6 joerg man_word_alloc(struct man *m, int line, int pos, const char *word)
321 1.1 joerg {
322 1.1 joerg struct man_node *n;
323 1.1.1.6 joerg size_t sv, len;
324 1.1.1.6 joerg
325 1.1.1.6 joerg len = strlen(word);
326 1.1 joerg
327 1.1.1.11 joerg n = man_node_alloc(m, line, pos, MAN_TEXT, MAN_MAX);
328 1.1.1.3 joerg n->string = mandoc_malloc(len + 1);
329 1.1.1.6 joerg sv = strlcpy(n->string, word, len + 1);
330 1.1 joerg
331 1.1 joerg /* Prohibit truncation. */
332 1.1 joerg assert(sv < len + 1);
333 1.1 joerg
334 1.1 joerg if ( ! man_node_append(m, n))
335 1.1 joerg return(0);
336 1.1.1.6 joerg
337 1.1 joerg m->next = MAN_NEXT_SIBLING;
338 1.1 joerg return(1);
339 1.1 joerg }
340 1.1 joerg
341 1.1 joerg
342 1.1.1.5 joerg /*
343 1.1.1.5 joerg * Free all of the resources held by a node. This does NOT unlink a
344 1.1.1.5 joerg * node from its context; for that, see man_node_unlink().
345 1.1.1.5 joerg */
346 1.1.1.5 joerg static void
347 1.1 joerg man_node_free(struct man_node *p)
348 1.1 joerg {
349 1.1 joerg
350 1.1 joerg if (p->string)
351 1.1 joerg free(p->string);
352 1.1 joerg free(p);
353 1.1 joerg }
354 1.1 joerg
355 1.1 joerg
356 1.1 joerg void
357 1.1.1.5 joerg man_node_delete(struct man *m, struct man_node *p)
358 1.1 joerg {
359 1.1 joerg
360 1.1.1.5 joerg while (p->child)
361 1.1.1.5 joerg man_node_delete(m, p->child);
362 1.1.1.5 joerg
363 1.1.1.5 joerg man_node_unlink(m, p);
364 1.1 joerg man_node_free(p);
365 1.1 joerg }
366 1.1 joerg
367 1.1.1.11 joerg int
368 1.1.1.11 joerg man_addeqn(struct man *m, const struct eqn *ep)
369 1.1.1.11 joerg {
370 1.1.1.11 joerg struct man_node *n;
371 1.1.1.11 joerg
372 1.1.1.11 joerg assert( ! (MAN_HALT & m->flags));
373 1.1.1.11 joerg
374 1.1.1.11 joerg n = man_node_alloc(m, ep->line, ep->pos, MAN_EQN, MAN_MAX);
375 1.1.1.11 joerg n->eqn = ep;
376 1.1.1.11 joerg
377 1.1.1.11 joerg if ( ! man_node_append(m, n))
378 1.1.1.11 joerg return(0);
379 1.1.1.11 joerg
380 1.1.1.11 joerg m->next = MAN_NEXT_SIBLING;
381 1.1.1.11 joerg return(man_descope(m, ep->line, ep->pos));
382 1.1.1.11 joerg }
383 1.1 joerg
384 1.1.1.10 joerg int
385 1.1.1.10 joerg man_addspan(struct man *m, const struct tbl_span *sp)
386 1.1.1.10 joerg {
387 1.1.1.11 joerg struct man_node *n;
388 1.1.1.10 joerg
389 1.1.1.10 joerg assert( ! (MAN_HALT & m->flags));
390 1.1.1.11 joerg
391 1.1.1.11 joerg n = man_node_alloc(m, sp->line, 0, MAN_TBL, MAN_MAX);
392 1.1.1.11 joerg n->span = sp;
393 1.1.1.11 joerg
394 1.1.1.11 joerg if ( ! man_node_append(m, n))
395 1.1.1.10 joerg return(0);
396 1.1.1.11 joerg
397 1.1.1.11 joerg m->next = MAN_NEXT_SIBLING;
398 1.1.1.11 joerg return(man_descope(m, sp->line, 0));
399 1.1.1.10 joerg }
400 1.1.1.10 joerg
401 1.1.1.10 joerg static int
402 1.1.1.10 joerg man_descope(struct man *m, int line, int offs)
403 1.1.1.10 joerg {
404 1.1.1.10 joerg /*
405 1.1.1.10 joerg * Co-ordinate what happens with having a next-line scope open:
406 1.1.1.10 joerg * first close out the element scope (if applicable), then close
407 1.1.1.10 joerg * out the block scope (also if applicable).
408 1.1.1.10 joerg */
409 1.1.1.10 joerg
410 1.1.1.10 joerg if (MAN_ELINE & m->flags) {
411 1.1.1.10 joerg m->flags &= ~MAN_ELINE;
412 1.1.1.10 joerg if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
413 1.1.1.10 joerg return(0);
414 1.1.1.10 joerg }
415 1.1.1.10 joerg
416 1.1.1.10 joerg if ( ! (MAN_BLINE & m->flags))
417 1.1.1.10 joerg return(1);
418 1.1.1.10 joerg m->flags &= ~MAN_BLINE;
419 1.1.1.10 joerg
420 1.1.1.10 joerg if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
421 1.1.1.10 joerg return(0);
422 1.1.1.10 joerg return(man_body_alloc(m, line, offs, m->last->tok));
423 1.1.1.10 joerg }
424 1.1.1.10 joerg
425 1.1 joerg static int
426 1.1.1.6 joerg man_ptext(struct man *m, int line, char *buf, int offs)
427 1.1 joerg {
428 1.1.1.6 joerg int i;
429 1.1.1.6 joerg
430 1.1 joerg /* Literal free-form text whitespace is preserved. */
431 1.1 joerg
432 1.1 joerg if (MAN_LITERAL & m->flags) {
433 1.1.1.6 joerg if ( ! man_word_alloc(m, line, offs, buf + offs))
434 1.1 joerg return(0);
435 1.1.1.10 joerg return(man_descope(m, line, offs));
436 1.1 joerg }
437 1.1 joerg
438 1.1.1.6 joerg /* Pump blank lines directly into the backend. */
439 1.1 joerg
440 1.1.1.6 joerg for (i = offs; ' ' == buf[i]; i++)
441 1.1 joerg /* Skip leading whitespace. */ ;
442 1.1.1.4 joerg
443 1.1.1.4 joerg if ('\0' == buf[i]) {
444 1.1.1.6 joerg /* Allocate a blank entry. */
445 1.1.1.6 joerg if ( ! man_word_alloc(m, line, offs, ""))
446 1.1 joerg return(0);
447 1.1.1.10 joerg return(man_descope(m, line, offs));
448 1.1 joerg }
449 1.1 joerg
450 1.1.1.6 joerg /*
451 1.1.1.6 joerg * Warn if the last un-escaped character is whitespace. Then
452 1.1.1.6 joerg * strip away the remaining spaces (tabs stay!).
453 1.1.1.6 joerg */
454 1.1 joerg
455 1.1.1.6 joerg i = (int)strlen(buf);
456 1.1.1.6 joerg assert(i);
457 1.1.1.4 joerg
458 1.1.1.6 joerg if (' ' == buf[i - 1] || '\t' == buf[i - 1]) {
459 1.1.1.6 joerg if (i > 1 && '\\' != buf[i - 2])
460 1.1.1.10 joerg man_pmsg(m, line, i - 1, MANDOCERR_EOLNSPACE);
461 1.1.1.4 joerg
462 1.1.1.6 joerg for (--i; i && ' ' == buf[i]; i--)
463 1.1.1.6 joerg /* Spin back to non-space. */ ;
464 1.1.1.4 joerg
465 1.1.1.6 joerg /* Jump ahead of escaped whitespace. */
466 1.1.1.6 joerg i += '\\' == buf[i] ? 2 : 1;
467 1.1.1.4 joerg
468 1.1.1.6 joerg buf[i] = '\0';
469 1.1 joerg }
470 1.1 joerg
471 1.1.1.6 joerg if ( ! man_word_alloc(m, line, offs, buf + offs))
472 1.1 joerg return(0);
473 1.1 joerg
474 1.1.1.6 joerg /*
475 1.1.1.6 joerg * End-of-sentence check. If the last character is an unescaped
476 1.1.1.6 joerg * EOS character, then flag the node as being the end of a
477 1.1.1.6 joerg * sentence. The front-end will know how to interpret this.
478 1.1.1.6 joerg */
479 1.1.1.6 joerg
480 1.1.1.6 joerg assert(i);
481 1.1.1.9 joerg if (mandoc_eos(buf, (size_t)i, 0))
482 1.1.1.6 joerg m->last->flags |= MAN_EOS;
483 1.1 joerg
484 1.1.1.10 joerg return(man_descope(m, line, offs));
485 1.1 joerg }
486 1.1 joerg
487 1.1.1.2 joerg static int
488 1.1.1.6 joerg man_pmacro(struct man *m, int ln, char *buf, int offs)
489 1.1 joerg {
490 1.1.1.11 joerg int i, ppos;
491 1.1.1.5 joerg enum mant tok;
492 1.1 joerg char mac[5];
493 1.1 joerg struct man_node *n;
494 1.1 joerg
495 1.1.1.11 joerg if ('"' == buf[offs]) {
496 1.1.1.11 joerg man_pmsg(m, ln, offs, MANDOCERR_BADCOMMENT);
497 1.1.1.11 joerg return(1);
498 1.1.1.11 joerg } else if ('\0' == buf[offs])
499 1.1.1.3 joerg return(1);
500 1.1 joerg
501 1.1.1.11 joerg ppos = offs;
502 1.1 joerg
503 1.1.1.10 joerg /*
504 1.1.1.10 joerg * Copy the first word into a nil-terminated buffer.
505 1.1.1.10 joerg * Stop copying when a tab, space, or eoln is encountered.
506 1.1.1.10 joerg */
507 1.1 joerg
508 1.1.1.11 joerg i = 0;
509 1.1.1.11 joerg while (i < 4 && '\0' != buf[offs] &&
510 1.1.1.11 joerg ' ' != buf[offs] && '\t' != buf[offs])
511 1.1.1.11 joerg mac[i++] = buf[offs++];
512 1.1.1.11 joerg
513 1.1.1.11 joerg mac[i] = '\0';
514 1.1.1.11 joerg
515 1.1.1.11 joerg tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX;
516 1.1 joerg
517 1.1.1.10 joerg if (MAN_MAX == tok) {
518 1.1.1.11 joerg mandoc_vmsg(MANDOCERR_MACRO, m->parse, ln,
519 1.1.1.11 joerg ppos, "%s", buf + ppos - 1);
520 1.1 joerg return(1);
521 1.1 joerg }
522 1.1 joerg
523 1.1 joerg /* The macro is sane. Jump to the next word. */
524 1.1 joerg
525 1.1.1.11 joerg while (buf[offs] && ' ' == buf[offs])
526 1.1.1.11 joerg offs++;
527 1.1 joerg
528 1.1.1.6 joerg /*
529 1.1.1.6 joerg * Trailing whitespace. Note that tabs are allowed to be passed
530 1.1.1.6 joerg * into the parser as "text", so we only warn about spaces here.
531 1.1.1.6 joerg */
532 1.1.1.4 joerg
533 1.1.1.11 joerg if ('\0' == buf[offs] && ' ' == buf[offs - 1])
534 1.1.1.11 joerg man_pmsg(m, ln, offs - 1, MANDOCERR_EOLNSPACE);
535 1.1.1.4 joerg
536 1.1.1.5 joerg /*
537 1.1.1.10 joerg * Remove prior ELINE macro, as it's being clobbered by a new
538 1.1.1.5 joerg * macro. Note that NSCOPED macros do not close out ELINE
539 1.1.1.5 joerg * macros---they don't print text---so we let those slip by.
540 1.1.1.5 joerg */
541 1.1.1.5 joerg
542 1.1.1.5 joerg if ( ! (MAN_NSCOPED & man_macros[tok].flags) &&
543 1.1.1.5 joerg m->flags & MAN_ELINE) {
544 1.1 joerg n = m->last;
545 1.1.1.10 joerg assert(MAN_TEXT != n->type);
546 1.1.1.5 joerg
547 1.1.1.10 joerg /* Remove repeated NSCOPED macros causing ELINE. */
548 1.1.1.5 joerg
549 1.1.1.10 joerg if (MAN_NSCOPED & man_macros[n->tok].flags)
550 1.1.1.10 joerg n = n->parent;
551 1.1.1.10 joerg
552 1.1.1.11 joerg mandoc_vmsg(MANDOCERR_LINESCOPE, m->parse, n->line,
553 1.1.1.11 joerg n->pos, "%s", man_macronames[n->tok]);
554 1.1 joerg
555 1.1.1.5 joerg man_node_delete(m, n);
556 1.1 joerg m->flags &= ~MAN_ELINE;
557 1.1 joerg }
558 1.1 joerg
559 1.1.1.5 joerg /*
560 1.1.1.5 joerg * Save the fact that we're in the next-line for a block. In
561 1.1.1.5 joerg * this way, embedded roff instructions can "remember" state
562 1.1.1.5 joerg * when they exit.
563 1.1.1.5 joerg */
564 1.1 joerg
565 1.1.1.5 joerg if (MAN_BLINE & m->flags)
566 1.1.1.5 joerg m->flags |= MAN_BPLINE;
567 1.1 joerg
568 1.1.1.5 joerg /* Call to handler... */
569 1.1.1.5 joerg
570 1.1.1.5 joerg assert(man_macros[tok].fp);
571 1.1.1.11 joerg if ( ! (*man_macros[tok].fp)(m, tok, ln, ppos, &offs, buf))
572 1.1 joerg goto err;
573 1.1 joerg
574 1.1.1.5 joerg /*
575 1.1.1.5 joerg * We weren't in a block-line scope when entering the
576 1.1.1.5 joerg * above-parsed macro, so return.
577 1.1.1.5 joerg */
578 1.1.1.5 joerg
579 1.1.1.5 joerg if ( ! (MAN_BPLINE & m->flags)) {
580 1.1.1.5 joerg m->flags &= ~MAN_ILINE;
581 1.1 joerg return(1);
582 1.1.1.5 joerg }
583 1.1.1.5 joerg m->flags &= ~MAN_BPLINE;
584 1.1.1.5 joerg
585 1.1.1.5 joerg /*
586 1.1.1.5 joerg * If we're in a block scope, then allow this macro to slip by
587 1.1.1.5 joerg * without closing scope around it.
588 1.1.1.5 joerg */
589 1.1.1.5 joerg
590 1.1.1.5 joerg if (MAN_ILINE & m->flags) {
591 1.1.1.5 joerg m->flags &= ~MAN_ILINE;
592 1.1.1.5 joerg return(1);
593 1.1.1.5 joerg }
594 1.1 joerg
595 1.1 joerg /*
596 1.1 joerg * If we've opened a new next-line element scope, then return
597 1.1 joerg * now, as the next line will close out the block scope.
598 1.1 joerg */
599 1.1 joerg
600 1.1 joerg if (MAN_ELINE & m->flags)
601 1.1 joerg return(1);
602 1.1 joerg
603 1.1 joerg /* Close out the block scope opened in the prior line. */
604 1.1 joerg
605 1.1 joerg assert(MAN_BLINE & m->flags);
606 1.1 joerg m->flags &= ~MAN_BLINE;
607 1.1 joerg
608 1.1.1.6 joerg if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
609 1.1 joerg return(0);
610 1.1.1.11 joerg return(man_body_alloc(m, ln, ppos, m->last->tok));
611 1.1 joerg
612 1.1 joerg err: /* Error out. */
613 1.1 joerg
614 1.1 joerg m->flags |= MAN_HALT;
615 1.1 joerg return(0);
616 1.1 joerg }
617 1.1 joerg
618 1.1.1.5 joerg /*
619 1.1.1.5 joerg * Unlink a node from its context. If "m" is provided, the last parse
620 1.1.1.5 joerg * point will also be adjusted accordingly.
621 1.1.1.5 joerg */
622 1.1.1.5 joerg static void
623 1.1.1.5 joerg man_node_unlink(struct man *m, struct man_node *n)
624 1.1.1.5 joerg {
625 1.1.1.5 joerg
626 1.1.1.5 joerg /* Adjust siblings. */
627 1.1.1.5 joerg
628 1.1.1.5 joerg if (n->prev)
629 1.1.1.5 joerg n->prev->next = n->next;
630 1.1.1.5 joerg if (n->next)
631 1.1.1.5 joerg n->next->prev = n->prev;
632 1.1.1.5 joerg
633 1.1.1.5 joerg /* Adjust parent. */
634 1.1.1.5 joerg
635 1.1.1.5 joerg if (n->parent) {
636 1.1.1.5 joerg n->parent->nchild--;
637 1.1.1.5 joerg if (n->parent->child == n)
638 1.1.1.5 joerg n->parent->child = n->prev ? n->prev : n->next;
639 1.1.1.5 joerg }
640 1.1.1.5 joerg
641 1.1.1.5 joerg /* Adjust parse point, if applicable. */
642 1.1.1.5 joerg
643 1.1.1.5 joerg if (m && m->last == n) {
644 1.1.1.5 joerg /*XXX: this can occur when bailing from validation. */
645 1.1.1.5 joerg /*assert(NULL == n->next);*/
646 1.1.1.5 joerg if (n->prev) {
647 1.1.1.5 joerg m->last = n->prev;
648 1.1.1.5 joerg m->next = MAN_NEXT_SIBLING;
649 1.1.1.5 joerg } else {
650 1.1.1.5 joerg m->last = n->parent;
651 1.1.1.5 joerg m->next = MAN_NEXT_CHILD;
652 1.1.1.5 joerg }
653 1.1.1.5 joerg }
654 1.1.1.5 joerg
655 1.1.1.5 joerg if (m && m->first == n)
656 1.1.1.5 joerg m->first = NULL;
657 1.1.1.5 joerg }
658