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