man.c revision 1.1.1.12 1 1.1.1.12 joerg /* $Vendor-Id: man.c,v 1.112 2011/10/06 22:29:12 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.12 joerg man_alloc(struct roff *roff, 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.12 joerg p->roff = roff;
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 joerg
324 1.1.1.11 joerg n = man_node_alloc(m, line, pos, MAN_TEXT, MAN_MAX);
325 1.1.1.12 joerg n->string = roff_strdup(m->roff, word);
326 1.1 joerg
327 1.1 joerg if ( ! man_node_append(m, n))
328 1.1 joerg return(0);
329 1.1.1.6 joerg
330 1.1 joerg m->next = MAN_NEXT_SIBLING;
331 1.1 joerg return(1);
332 1.1 joerg }
333 1.1 joerg
334 1.1 joerg
335 1.1.1.5 joerg /*
336 1.1.1.5 joerg * Free all of the resources held by a node. This does NOT unlink a
337 1.1.1.5 joerg * node from its context; for that, see man_node_unlink().
338 1.1.1.5 joerg */
339 1.1.1.5 joerg static void
340 1.1 joerg man_node_free(struct man_node *p)
341 1.1 joerg {
342 1.1 joerg
343 1.1 joerg if (p->string)
344 1.1 joerg free(p->string);
345 1.1 joerg free(p);
346 1.1 joerg }
347 1.1 joerg
348 1.1 joerg
349 1.1 joerg void
350 1.1.1.5 joerg man_node_delete(struct man *m, struct man_node *p)
351 1.1 joerg {
352 1.1 joerg
353 1.1.1.5 joerg while (p->child)
354 1.1.1.5 joerg man_node_delete(m, p->child);
355 1.1.1.5 joerg
356 1.1.1.5 joerg man_node_unlink(m, p);
357 1.1 joerg man_node_free(p);
358 1.1 joerg }
359 1.1 joerg
360 1.1.1.11 joerg int
361 1.1.1.11 joerg man_addeqn(struct man *m, const struct eqn *ep)
362 1.1.1.11 joerg {
363 1.1.1.11 joerg struct man_node *n;
364 1.1.1.11 joerg
365 1.1.1.11 joerg assert( ! (MAN_HALT & m->flags));
366 1.1.1.11 joerg
367 1.1.1.12 joerg n = man_node_alloc(m, ep->ln, ep->pos, MAN_EQN, MAN_MAX);
368 1.1.1.11 joerg n->eqn = ep;
369 1.1.1.11 joerg
370 1.1.1.11 joerg if ( ! man_node_append(m, n))
371 1.1.1.11 joerg return(0);
372 1.1.1.11 joerg
373 1.1.1.11 joerg m->next = MAN_NEXT_SIBLING;
374 1.1.1.12 joerg return(man_descope(m, ep->ln, ep->pos));
375 1.1.1.11 joerg }
376 1.1 joerg
377 1.1.1.10 joerg int
378 1.1.1.10 joerg man_addspan(struct man *m, const struct tbl_span *sp)
379 1.1.1.10 joerg {
380 1.1.1.11 joerg struct man_node *n;
381 1.1.1.10 joerg
382 1.1.1.10 joerg assert( ! (MAN_HALT & m->flags));
383 1.1.1.11 joerg
384 1.1.1.11 joerg n = man_node_alloc(m, sp->line, 0, MAN_TBL, MAN_MAX);
385 1.1.1.11 joerg n->span = sp;
386 1.1.1.11 joerg
387 1.1.1.11 joerg if ( ! man_node_append(m, n))
388 1.1.1.10 joerg return(0);
389 1.1.1.11 joerg
390 1.1.1.11 joerg m->next = MAN_NEXT_SIBLING;
391 1.1.1.11 joerg return(man_descope(m, sp->line, 0));
392 1.1.1.10 joerg }
393 1.1.1.10 joerg
394 1.1.1.10 joerg static int
395 1.1.1.10 joerg man_descope(struct man *m, int line, int offs)
396 1.1.1.10 joerg {
397 1.1.1.10 joerg /*
398 1.1.1.10 joerg * Co-ordinate what happens with having a next-line scope open:
399 1.1.1.10 joerg * first close out the element scope (if applicable), then close
400 1.1.1.10 joerg * out the block scope (also if applicable).
401 1.1.1.10 joerg */
402 1.1.1.10 joerg
403 1.1.1.10 joerg if (MAN_ELINE & m->flags) {
404 1.1.1.10 joerg m->flags &= ~MAN_ELINE;
405 1.1.1.10 joerg if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
406 1.1.1.10 joerg return(0);
407 1.1.1.10 joerg }
408 1.1.1.10 joerg
409 1.1.1.10 joerg if ( ! (MAN_BLINE & m->flags))
410 1.1.1.10 joerg return(1);
411 1.1.1.10 joerg m->flags &= ~MAN_BLINE;
412 1.1.1.10 joerg
413 1.1.1.10 joerg if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
414 1.1.1.10 joerg return(0);
415 1.1.1.10 joerg return(man_body_alloc(m, line, offs, m->last->tok));
416 1.1.1.10 joerg }
417 1.1.1.10 joerg
418 1.1 joerg static int
419 1.1.1.6 joerg man_ptext(struct man *m, int line, char *buf, int offs)
420 1.1 joerg {
421 1.1.1.6 joerg int i;
422 1.1.1.6 joerg
423 1.1 joerg /* Literal free-form text whitespace is preserved. */
424 1.1 joerg
425 1.1 joerg if (MAN_LITERAL & m->flags) {
426 1.1.1.6 joerg if ( ! man_word_alloc(m, line, offs, buf + offs))
427 1.1 joerg return(0);
428 1.1.1.10 joerg return(man_descope(m, line, offs));
429 1.1 joerg }
430 1.1 joerg
431 1.1.1.6 joerg /* Pump blank lines directly into the backend. */
432 1.1 joerg
433 1.1.1.6 joerg for (i = offs; ' ' == buf[i]; i++)
434 1.1 joerg /* Skip leading whitespace. */ ;
435 1.1.1.4 joerg
436 1.1.1.4 joerg if ('\0' == buf[i]) {
437 1.1.1.6 joerg /* Allocate a blank entry. */
438 1.1.1.6 joerg if ( ! man_word_alloc(m, line, offs, ""))
439 1.1 joerg return(0);
440 1.1.1.10 joerg return(man_descope(m, line, offs));
441 1.1 joerg }
442 1.1 joerg
443 1.1.1.6 joerg /*
444 1.1.1.6 joerg * Warn if the last un-escaped character is whitespace. Then
445 1.1.1.6 joerg * strip away the remaining spaces (tabs stay!).
446 1.1.1.6 joerg */
447 1.1 joerg
448 1.1.1.6 joerg i = (int)strlen(buf);
449 1.1.1.6 joerg assert(i);
450 1.1.1.4 joerg
451 1.1.1.6 joerg if (' ' == buf[i - 1] || '\t' == buf[i - 1]) {
452 1.1.1.6 joerg if (i > 1 && '\\' != buf[i - 2])
453 1.1.1.10 joerg man_pmsg(m, line, i - 1, MANDOCERR_EOLNSPACE);
454 1.1.1.4 joerg
455 1.1.1.6 joerg for (--i; i && ' ' == buf[i]; i--)
456 1.1.1.6 joerg /* Spin back to non-space. */ ;
457 1.1.1.4 joerg
458 1.1.1.6 joerg /* Jump ahead of escaped whitespace. */
459 1.1.1.6 joerg i += '\\' == buf[i] ? 2 : 1;
460 1.1.1.4 joerg
461 1.1.1.6 joerg buf[i] = '\0';
462 1.1 joerg }
463 1.1 joerg
464 1.1.1.6 joerg if ( ! man_word_alloc(m, line, offs, buf + offs))
465 1.1 joerg return(0);
466 1.1 joerg
467 1.1.1.6 joerg /*
468 1.1.1.6 joerg * End-of-sentence check. If the last character is an unescaped
469 1.1.1.6 joerg * EOS character, then flag the node as being the end of a
470 1.1.1.6 joerg * sentence. The front-end will know how to interpret this.
471 1.1.1.6 joerg */
472 1.1.1.6 joerg
473 1.1.1.6 joerg assert(i);
474 1.1.1.9 joerg if (mandoc_eos(buf, (size_t)i, 0))
475 1.1.1.6 joerg m->last->flags |= MAN_EOS;
476 1.1 joerg
477 1.1.1.10 joerg return(man_descope(m, line, offs));
478 1.1 joerg }
479 1.1 joerg
480 1.1.1.2 joerg static int
481 1.1.1.6 joerg man_pmacro(struct man *m, int ln, char *buf, int offs)
482 1.1 joerg {
483 1.1.1.11 joerg int i, ppos;
484 1.1.1.5 joerg enum mant tok;
485 1.1 joerg char mac[5];
486 1.1 joerg struct man_node *n;
487 1.1 joerg
488 1.1.1.11 joerg if ('"' == buf[offs]) {
489 1.1.1.11 joerg man_pmsg(m, ln, offs, MANDOCERR_BADCOMMENT);
490 1.1.1.11 joerg return(1);
491 1.1.1.11 joerg } else if ('\0' == buf[offs])
492 1.1.1.3 joerg return(1);
493 1.1 joerg
494 1.1.1.11 joerg ppos = offs;
495 1.1 joerg
496 1.1.1.10 joerg /*
497 1.1.1.10 joerg * Copy the first word into a nil-terminated buffer.
498 1.1.1.10 joerg * Stop copying when a tab, space, or eoln is encountered.
499 1.1.1.10 joerg */
500 1.1 joerg
501 1.1.1.11 joerg i = 0;
502 1.1.1.11 joerg while (i < 4 && '\0' != buf[offs] &&
503 1.1.1.11 joerg ' ' != buf[offs] && '\t' != buf[offs])
504 1.1.1.11 joerg mac[i++] = buf[offs++];
505 1.1.1.11 joerg
506 1.1.1.11 joerg mac[i] = '\0';
507 1.1.1.11 joerg
508 1.1.1.11 joerg tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX;
509 1.1 joerg
510 1.1.1.10 joerg if (MAN_MAX == tok) {
511 1.1.1.11 joerg mandoc_vmsg(MANDOCERR_MACRO, m->parse, ln,
512 1.1.1.11 joerg ppos, "%s", buf + ppos - 1);
513 1.1 joerg return(1);
514 1.1 joerg }
515 1.1 joerg
516 1.1 joerg /* The macro is sane. Jump to the next word. */
517 1.1 joerg
518 1.1.1.11 joerg while (buf[offs] && ' ' == buf[offs])
519 1.1.1.11 joerg offs++;
520 1.1 joerg
521 1.1.1.6 joerg /*
522 1.1.1.6 joerg * Trailing whitespace. Note that tabs are allowed to be passed
523 1.1.1.6 joerg * into the parser as "text", so we only warn about spaces here.
524 1.1.1.6 joerg */
525 1.1.1.4 joerg
526 1.1.1.11 joerg if ('\0' == buf[offs] && ' ' == buf[offs - 1])
527 1.1.1.11 joerg man_pmsg(m, ln, offs - 1, MANDOCERR_EOLNSPACE);
528 1.1.1.4 joerg
529 1.1.1.5 joerg /*
530 1.1.1.10 joerg * Remove prior ELINE macro, as it's being clobbered by a new
531 1.1.1.5 joerg * macro. Note that NSCOPED macros do not close out ELINE
532 1.1.1.5 joerg * macros---they don't print text---so we let those slip by.
533 1.1.1.5 joerg */
534 1.1.1.5 joerg
535 1.1.1.5 joerg if ( ! (MAN_NSCOPED & man_macros[tok].flags) &&
536 1.1.1.5 joerg m->flags & MAN_ELINE) {
537 1.1 joerg n = m->last;
538 1.1.1.10 joerg assert(MAN_TEXT != n->type);
539 1.1.1.5 joerg
540 1.1.1.10 joerg /* Remove repeated NSCOPED macros causing ELINE. */
541 1.1.1.5 joerg
542 1.1.1.10 joerg if (MAN_NSCOPED & man_macros[n->tok].flags)
543 1.1.1.10 joerg n = n->parent;
544 1.1.1.10 joerg
545 1.1.1.11 joerg mandoc_vmsg(MANDOCERR_LINESCOPE, m->parse, n->line,
546 1.1.1.11 joerg n->pos, "%s", man_macronames[n->tok]);
547 1.1 joerg
548 1.1.1.5 joerg man_node_delete(m, n);
549 1.1 joerg m->flags &= ~MAN_ELINE;
550 1.1 joerg }
551 1.1 joerg
552 1.1.1.5 joerg /*
553 1.1.1.5 joerg * Save the fact that we're in the next-line for a block. In
554 1.1.1.5 joerg * this way, embedded roff instructions can "remember" state
555 1.1.1.5 joerg * when they exit.
556 1.1.1.5 joerg */
557 1.1 joerg
558 1.1.1.5 joerg if (MAN_BLINE & m->flags)
559 1.1.1.5 joerg m->flags |= MAN_BPLINE;
560 1.1 joerg
561 1.1.1.5 joerg /* Call to handler... */
562 1.1.1.5 joerg
563 1.1.1.5 joerg assert(man_macros[tok].fp);
564 1.1.1.11 joerg if ( ! (*man_macros[tok].fp)(m, tok, ln, ppos, &offs, buf))
565 1.1 joerg goto err;
566 1.1 joerg
567 1.1.1.5 joerg /*
568 1.1.1.5 joerg * We weren't in a block-line scope when entering the
569 1.1.1.5 joerg * above-parsed macro, so return.
570 1.1.1.5 joerg */
571 1.1.1.5 joerg
572 1.1.1.5 joerg if ( ! (MAN_BPLINE & m->flags)) {
573 1.1.1.5 joerg m->flags &= ~MAN_ILINE;
574 1.1 joerg return(1);
575 1.1.1.5 joerg }
576 1.1.1.5 joerg m->flags &= ~MAN_BPLINE;
577 1.1.1.5 joerg
578 1.1.1.5 joerg /*
579 1.1.1.5 joerg * If we're in a block scope, then allow this macro to slip by
580 1.1.1.5 joerg * without closing scope around it.
581 1.1.1.5 joerg */
582 1.1.1.5 joerg
583 1.1.1.5 joerg if (MAN_ILINE & m->flags) {
584 1.1.1.5 joerg m->flags &= ~MAN_ILINE;
585 1.1.1.5 joerg return(1);
586 1.1.1.5 joerg }
587 1.1 joerg
588 1.1 joerg /*
589 1.1 joerg * If we've opened a new next-line element scope, then return
590 1.1 joerg * now, as the next line will close out the block scope.
591 1.1 joerg */
592 1.1 joerg
593 1.1 joerg if (MAN_ELINE & m->flags)
594 1.1 joerg return(1);
595 1.1 joerg
596 1.1 joerg /* Close out the block scope opened in the prior line. */
597 1.1 joerg
598 1.1 joerg assert(MAN_BLINE & m->flags);
599 1.1 joerg m->flags &= ~MAN_BLINE;
600 1.1 joerg
601 1.1.1.6 joerg if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
602 1.1 joerg return(0);
603 1.1.1.11 joerg return(man_body_alloc(m, ln, ppos, m->last->tok));
604 1.1 joerg
605 1.1 joerg err: /* Error out. */
606 1.1 joerg
607 1.1 joerg m->flags |= MAN_HALT;
608 1.1 joerg return(0);
609 1.1 joerg }
610 1.1 joerg
611 1.1.1.5 joerg /*
612 1.1.1.5 joerg * Unlink a node from its context. If "m" is provided, the last parse
613 1.1.1.5 joerg * point will also be adjusted accordingly.
614 1.1.1.5 joerg */
615 1.1.1.5 joerg static void
616 1.1.1.5 joerg man_node_unlink(struct man *m, struct man_node *n)
617 1.1.1.5 joerg {
618 1.1.1.5 joerg
619 1.1.1.5 joerg /* Adjust siblings. */
620 1.1.1.5 joerg
621 1.1.1.5 joerg if (n->prev)
622 1.1.1.5 joerg n->prev->next = n->next;
623 1.1.1.5 joerg if (n->next)
624 1.1.1.5 joerg n->next->prev = n->prev;
625 1.1.1.5 joerg
626 1.1.1.5 joerg /* Adjust parent. */
627 1.1.1.5 joerg
628 1.1.1.5 joerg if (n->parent) {
629 1.1.1.5 joerg n->parent->nchild--;
630 1.1.1.5 joerg if (n->parent->child == n)
631 1.1.1.5 joerg n->parent->child = n->prev ? n->prev : n->next;
632 1.1.1.5 joerg }
633 1.1.1.5 joerg
634 1.1.1.5 joerg /* Adjust parse point, if applicable. */
635 1.1.1.5 joerg
636 1.1.1.5 joerg if (m && m->last == n) {
637 1.1.1.5 joerg /*XXX: this can occur when bailing from validation. */
638 1.1.1.5 joerg /*assert(NULL == n->next);*/
639 1.1.1.5 joerg if (n->prev) {
640 1.1.1.5 joerg m->last = n->prev;
641 1.1.1.5 joerg m->next = MAN_NEXT_SIBLING;
642 1.1.1.5 joerg } else {
643 1.1.1.5 joerg m->last = n->parent;
644 1.1.1.5 joerg m->next = MAN_NEXT_CHILD;
645 1.1.1.5 joerg }
646 1.1.1.5 joerg }
647 1.1.1.5 joerg
648 1.1.1.5 joerg if (m && m->first == n)
649 1.1.1.5 joerg m->first = NULL;
650 1.1.1.5 joerg }
651 1.1.1.12 joerg
652 1.1.1.12 joerg const struct mparse *
653 1.1.1.12 joerg man_mparse(const struct man *m)
654 1.1.1.12 joerg {
655 1.1.1.12 joerg
656 1.1.1.12 joerg assert(m && m->parse);
657 1.1.1.12 joerg return(m->parse);
658 1.1.1.12 joerg }
659