man.c revision 1.1.1.10 1 1.1.1.10 joerg /* $Vendor-Id: man.c,v 1.96 2011/01/03 11:31:26 kristaps Exp $ */
2 1.1 joerg /*
3 1.1.1.9 joerg * Copyright (c) 2008, 2009, 2010 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.6 joerg #include "mandoc.h"
30 1.1 joerg #include "libman.h"
31 1.1.1.3 joerg #include "libmandoc.h"
32 1.1 joerg
33 1.1 joerg const char *const __man_macronames[MAN_MAX] = {
34 1.1 joerg "br", "TH", "SH", "SS",
35 1.1 joerg "TP", "LP", "PP", "P",
36 1.1 joerg "IP", "HP", "SM", "SB",
37 1.1 joerg "BI", "IB", "BR", "RB",
38 1.1 joerg "R", "B", "I", "IR",
39 1.1.1.10 joerg "RI", "na", "sp", "nf",
40 1.1.1.10 joerg "fi", "RE", "RS", "DT",
41 1.1.1.10 joerg "UC", "PD", "AT", "in",
42 1.1.1.10 joerg "ft"
43 1.1 joerg };
44 1.1 joerg
45 1.1 joerg const char * const *man_macronames = __man_macronames;
46 1.1 joerg
47 1.1 joerg static struct man_node *man_node_alloc(int, int,
48 1.1.1.5 joerg enum man_type, enum mant);
49 1.1 joerg static int man_node_append(struct man *,
50 1.1 joerg struct man_node *);
51 1.1.1.10 joerg static int man_span_alloc(struct man *,
52 1.1.1.10 joerg const struct tbl_span *);
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 joerg man_node(const struct man *m)
65 1.1 joerg {
66 1.1 joerg
67 1.1.1.10 joerg assert( ! (MAN_HALT & m->flags));
68 1.1.1.10 joerg return(m->first);
69 1.1 joerg }
70 1.1 joerg
71 1.1 joerg
72 1.1 joerg const struct man_meta *
73 1.1 joerg man_meta(const struct man *m)
74 1.1 joerg {
75 1.1 joerg
76 1.1.1.10 joerg assert( ! (MAN_HALT & m->flags));
77 1.1.1.10 joerg return(&m->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.10 joerg man_alloc(struct regset *regs, void *data, mandocmsg msg)
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 joerg p->data = data;
108 1.1.1.6 joerg p->msg = msg;
109 1.1.1.8 joerg p->regs = regs;
110 1.1.1.3 joerg
111 1.1.1.3 joerg man_alloc1(p);
112 1.1 joerg return(p);
113 1.1 joerg }
114 1.1 joerg
115 1.1 joerg
116 1.1 joerg int
117 1.1 joerg man_endparse(struct man *m)
118 1.1 joerg {
119 1.1 joerg
120 1.1.1.10 joerg assert( ! (MAN_HALT & m->flags));
121 1.1.1.10 joerg if (man_macroend(m))
122 1.1 joerg return(1);
123 1.1 joerg m->flags |= MAN_HALT;
124 1.1 joerg return(0);
125 1.1 joerg }
126 1.1 joerg
127 1.1 joerg
128 1.1 joerg int
129 1.1.1.6 joerg man_parseln(struct man *m, int ln, char *buf, int offs)
130 1.1 joerg {
131 1.1 joerg
132 1.1.1.10 joerg assert( ! (MAN_HALT & m->flags));
133 1.1.1.6 joerg return(('.' == buf[offs] || '\'' == buf[offs]) ?
134 1.1.1.6 joerg man_pmacro(m, ln, buf, offs) :
135 1.1.1.6 joerg man_ptext(m, ln, buf, offs));
136 1.1 joerg }
137 1.1 joerg
138 1.1 joerg
139 1.1 joerg static void
140 1.1 joerg man_free1(struct man *man)
141 1.1 joerg {
142 1.1 joerg
143 1.1 joerg if (man->first)
144 1.1.1.5 joerg man_node_delete(man, man->first);
145 1.1 joerg if (man->meta.title)
146 1.1 joerg free(man->meta.title);
147 1.1 joerg if (man->meta.source)
148 1.1 joerg free(man->meta.source);
149 1.1.1.6 joerg if (man->meta.rawdate)
150 1.1.1.6 joerg free(man->meta.rawdate);
151 1.1 joerg if (man->meta.vol)
152 1.1 joerg free(man->meta.vol);
153 1.1.1.6 joerg if (man->meta.msec)
154 1.1.1.6 joerg free(man->meta.msec);
155 1.1 joerg }
156 1.1 joerg
157 1.1 joerg
158 1.1.1.3 joerg static void
159 1.1 joerg man_alloc1(struct man *m)
160 1.1 joerg {
161 1.1 joerg
162 1.1.1.3 joerg memset(&m->meta, 0, sizeof(struct man_meta));
163 1.1 joerg m->flags = 0;
164 1.1.1.3 joerg m->last = mandoc_calloc(1, sizeof(struct man_node));
165 1.1 joerg m->first = m->last;
166 1.1 joerg m->last->type = MAN_ROOT;
167 1.1.1.5 joerg m->last->tok = MAN_MAX;
168 1.1 joerg m->next = MAN_NEXT_CHILD;
169 1.1 joerg }
170 1.1 joerg
171 1.1 joerg
172 1.1 joerg static int
173 1.1 joerg man_node_append(struct man *man, struct man_node *p)
174 1.1 joerg {
175 1.1 joerg
176 1.1 joerg assert(man->last);
177 1.1 joerg assert(man->first);
178 1.1 joerg assert(MAN_ROOT != p->type);
179 1.1 joerg
180 1.1 joerg switch (man->next) {
181 1.1 joerg case (MAN_NEXT_SIBLING):
182 1.1 joerg man->last->next = p;
183 1.1 joerg p->prev = man->last;
184 1.1 joerg p->parent = man->last->parent;
185 1.1 joerg break;
186 1.1 joerg case (MAN_NEXT_CHILD):
187 1.1 joerg man->last->child = p;
188 1.1 joerg p->parent = man->last;
189 1.1 joerg break;
190 1.1 joerg default:
191 1.1 joerg abort();
192 1.1 joerg /* NOTREACHED */
193 1.1 joerg }
194 1.1 joerg
195 1.1.1.5 joerg assert(p->parent);
196 1.1 joerg p->parent->nchild++;
197 1.1 joerg
198 1.1 joerg if ( ! man_valid_pre(man, p))
199 1.1 joerg return(0);
200 1.1 joerg
201 1.1 joerg switch (p->type) {
202 1.1 joerg case (MAN_HEAD):
203 1.1 joerg assert(MAN_BLOCK == p->parent->type);
204 1.1 joerg p->parent->head = p;
205 1.1 joerg break;
206 1.1 joerg case (MAN_BODY):
207 1.1 joerg assert(MAN_BLOCK == p->parent->type);
208 1.1 joerg p->parent->body = p;
209 1.1 joerg break;
210 1.1 joerg default:
211 1.1 joerg break;
212 1.1 joerg }
213 1.1 joerg
214 1.1 joerg man->last = p;
215 1.1 joerg
216 1.1 joerg switch (p->type) {
217 1.1.1.10 joerg case (MAN_TBL):
218 1.1.1.10 joerg /* FALLTHROUGH */
219 1.1 joerg case (MAN_TEXT):
220 1.1 joerg if ( ! man_valid_post(man))
221 1.1 joerg return(0);
222 1.1 joerg break;
223 1.1 joerg default:
224 1.1 joerg break;
225 1.1 joerg }
226 1.1 joerg
227 1.1 joerg return(1);
228 1.1 joerg }
229 1.1 joerg
230 1.1 joerg
231 1.1 joerg static struct man_node *
232 1.1.1.5 joerg man_node_alloc(int line, int pos, enum man_type type, enum mant tok)
233 1.1 joerg {
234 1.1 joerg struct man_node *p;
235 1.1 joerg
236 1.1.1.3 joerg p = mandoc_calloc(1, sizeof(struct man_node));
237 1.1 joerg p->line = line;
238 1.1 joerg p->pos = pos;
239 1.1 joerg p->type = type;
240 1.1 joerg p->tok = tok;
241 1.1 joerg return(p);
242 1.1 joerg }
243 1.1 joerg
244 1.1 joerg
245 1.1 joerg int
246 1.1.1.5 joerg man_elem_alloc(struct man *m, int line, int pos, enum mant tok)
247 1.1 joerg {
248 1.1 joerg struct man_node *p;
249 1.1 joerg
250 1.1 joerg p = man_node_alloc(line, pos, MAN_ELEM, tok);
251 1.1 joerg if ( ! man_node_append(m, p))
252 1.1 joerg return(0);
253 1.1 joerg m->next = MAN_NEXT_CHILD;
254 1.1 joerg return(1);
255 1.1 joerg }
256 1.1 joerg
257 1.1 joerg
258 1.1 joerg int
259 1.1.1.5 joerg man_head_alloc(struct man *m, int line, int pos, enum mant tok)
260 1.1 joerg {
261 1.1 joerg struct man_node *p;
262 1.1 joerg
263 1.1 joerg p = man_node_alloc(line, pos, MAN_HEAD, tok);
264 1.1 joerg if ( ! man_node_append(m, p))
265 1.1 joerg return(0);
266 1.1 joerg m->next = MAN_NEXT_CHILD;
267 1.1 joerg return(1);
268 1.1 joerg }
269 1.1 joerg
270 1.1 joerg
271 1.1 joerg int
272 1.1.1.5 joerg man_body_alloc(struct man *m, int line, int pos, enum mant tok)
273 1.1 joerg {
274 1.1 joerg struct man_node *p;
275 1.1 joerg
276 1.1 joerg p = man_node_alloc(line, pos, MAN_BODY, tok);
277 1.1 joerg if ( ! man_node_append(m, p))
278 1.1 joerg return(0);
279 1.1 joerg m->next = MAN_NEXT_CHILD;
280 1.1 joerg return(1);
281 1.1 joerg }
282 1.1 joerg
283 1.1 joerg
284 1.1 joerg int
285 1.1.1.5 joerg man_block_alloc(struct man *m, int line, int pos, enum mant tok)
286 1.1 joerg {
287 1.1 joerg struct man_node *p;
288 1.1 joerg
289 1.1 joerg p = man_node_alloc(line, pos, MAN_BLOCK, tok);
290 1.1 joerg if ( ! man_node_append(m, p))
291 1.1 joerg return(0);
292 1.1 joerg m->next = MAN_NEXT_CHILD;
293 1.1 joerg return(1);
294 1.1 joerg }
295 1.1 joerg
296 1.1.1.10 joerg static int
297 1.1.1.10 joerg man_span_alloc(struct man *m, const struct tbl_span *span)
298 1.1.1.10 joerg {
299 1.1.1.10 joerg struct man_node *n;
300 1.1.1.10 joerg
301 1.1.1.10 joerg /* FIXME: grab from span */
302 1.1.1.10 joerg n = man_node_alloc(0, 0, MAN_TBL, MAN_MAX);
303 1.1.1.10 joerg n->span = span;
304 1.1.1.10 joerg
305 1.1.1.10 joerg if ( ! man_node_append(m, n))
306 1.1.1.10 joerg return(0);
307 1.1.1.10 joerg
308 1.1.1.10 joerg m->next = MAN_NEXT_SIBLING;
309 1.1.1.10 joerg return(1);
310 1.1.1.10 joerg }
311 1.1 joerg
312 1.1.1.6 joerg int
313 1.1.1.6 joerg man_word_alloc(struct man *m, int line, int pos, const char *word)
314 1.1 joerg {
315 1.1 joerg struct man_node *n;
316 1.1.1.6 joerg size_t sv, len;
317 1.1.1.6 joerg
318 1.1.1.6 joerg len = strlen(word);
319 1.1 joerg
320 1.1.1.5 joerg n = man_node_alloc(line, pos, MAN_TEXT, MAN_MAX);
321 1.1.1.3 joerg n->string = mandoc_malloc(len + 1);
322 1.1.1.6 joerg sv = strlcpy(n->string, word, len + 1);
323 1.1 joerg
324 1.1 joerg /* Prohibit truncation. */
325 1.1 joerg assert(sv < len + 1);
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 joerg
361 1.1.1.10 joerg int
362 1.1.1.10 joerg man_addspan(struct man *m, const struct tbl_span *sp)
363 1.1.1.10 joerg {
364 1.1.1.10 joerg
365 1.1.1.10 joerg assert( ! (MAN_HALT & m->flags));
366 1.1.1.10 joerg if ( ! man_span_alloc(m, sp))
367 1.1.1.10 joerg return(0);
368 1.1.1.10 joerg return(man_descope(m, 0, 0));
369 1.1.1.10 joerg }
370 1.1.1.10 joerg
371 1.1.1.10 joerg static int
372 1.1.1.10 joerg man_descope(struct man *m, int line, int offs)
373 1.1.1.10 joerg {
374 1.1.1.10 joerg /*
375 1.1.1.10 joerg * Co-ordinate what happens with having a next-line scope open:
376 1.1.1.10 joerg * first close out the element scope (if applicable), then close
377 1.1.1.10 joerg * out the block scope (also if applicable).
378 1.1.1.10 joerg */
379 1.1.1.10 joerg
380 1.1.1.10 joerg if (MAN_ELINE & m->flags) {
381 1.1.1.10 joerg m->flags &= ~MAN_ELINE;
382 1.1.1.10 joerg if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
383 1.1.1.10 joerg return(0);
384 1.1.1.10 joerg }
385 1.1.1.10 joerg
386 1.1.1.10 joerg if ( ! (MAN_BLINE & m->flags))
387 1.1.1.10 joerg return(1);
388 1.1.1.10 joerg m->flags &= ~MAN_BLINE;
389 1.1.1.10 joerg
390 1.1.1.10 joerg if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
391 1.1.1.10 joerg return(0);
392 1.1.1.10 joerg return(man_body_alloc(m, line, offs, m->last->tok));
393 1.1.1.10 joerg }
394 1.1.1.10 joerg
395 1.1.1.10 joerg
396 1.1 joerg static int
397 1.1.1.6 joerg man_ptext(struct man *m, int line, char *buf, int offs)
398 1.1 joerg {
399 1.1.1.6 joerg int i;
400 1.1.1.6 joerg
401 1.1.1.6 joerg /* Ignore bogus comments. */
402 1.1.1.6 joerg
403 1.1.1.6 joerg if ('\\' == buf[offs] &&
404 1.1.1.6 joerg '.' == buf[offs + 1] &&
405 1.1.1.10 joerg '"' == buf[offs + 2]) {
406 1.1.1.10 joerg man_pmsg(m, line, offs, MANDOCERR_BADCOMMENT);
407 1.1.1.10 joerg return(1);
408 1.1.1.10 joerg }
409 1.1 joerg
410 1.1 joerg /* Literal free-form text whitespace is preserved. */
411 1.1 joerg
412 1.1 joerg if (MAN_LITERAL & m->flags) {
413 1.1.1.6 joerg if ( ! man_word_alloc(m, line, offs, buf + offs))
414 1.1 joerg return(0);
415 1.1.1.10 joerg return(man_descope(m, line, offs));
416 1.1 joerg }
417 1.1 joerg
418 1.1.1.6 joerg /* Pump blank lines directly into the backend. */
419 1.1 joerg
420 1.1.1.6 joerg for (i = offs; ' ' == buf[i]; i++)
421 1.1 joerg /* Skip leading whitespace. */ ;
422 1.1.1.4 joerg
423 1.1.1.4 joerg if ('\0' == buf[i]) {
424 1.1.1.6 joerg /* Allocate a blank entry. */
425 1.1.1.6 joerg if ( ! man_word_alloc(m, line, offs, ""))
426 1.1 joerg return(0);
427 1.1.1.10 joerg return(man_descope(m, line, offs));
428 1.1 joerg }
429 1.1 joerg
430 1.1.1.6 joerg /*
431 1.1.1.6 joerg * Warn if the last un-escaped character is whitespace. Then
432 1.1.1.6 joerg * strip away the remaining spaces (tabs stay!).
433 1.1.1.6 joerg */
434 1.1 joerg
435 1.1.1.6 joerg i = (int)strlen(buf);
436 1.1.1.6 joerg assert(i);
437 1.1.1.4 joerg
438 1.1.1.6 joerg if (' ' == buf[i - 1] || '\t' == buf[i - 1]) {
439 1.1.1.6 joerg if (i > 1 && '\\' != buf[i - 2])
440 1.1.1.10 joerg man_pmsg(m, line, i - 1, MANDOCERR_EOLNSPACE);
441 1.1.1.4 joerg
442 1.1.1.6 joerg for (--i; i && ' ' == buf[i]; i--)
443 1.1.1.6 joerg /* Spin back to non-space. */ ;
444 1.1.1.4 joerg
445 1.1.1.6 joerg /* Jump ahead of escaped whitespace. */
446 1.1.1.6 joerg i += '\\' == buf[i] ? 2 : 1;
447 1.1.1.4 joerg
448 1.1.1.6 joerg buf[i] = '\0';
449 1.1 joerg }
450 1.1 joerg
451 1.1.1.6 joerg if ( ! man_word_alloc(m, line, offs, buf + offs))
452 1.1 joerg return(0);
453 1.1 joerg
454 1.1.1.6 joerg /*
455 1.1.1.6 joerg * End-of-sentence check. If the last character is an unescaped
456 1.1.1.6 joerg * EOS character, then flag the node as being the end of a
457 1.1.1.6 joerg * sentence. The front-end will know how to interpret this.
458 1.1.1.6 joerg */
459 1.1.1.6 joerg
460 1.1.1.6 joerg assert(i);
461 1.1.1.9 joerg if (mandoc_eos(buf, (size_t)i, 0))
462 1.1.1.6 joerg m->last->flags |= MAN_EOS;
463 1.1 joerg
464 1.1.1.10 joerg return(man_descope(m, line, offs));
465 1.1 joerg }
466 1.1 joerg
467 1.1 joerg
468 1.1.1.2 joerg static int
469 1.1.1.6 joerg man_pmacro(struct man *m, int ln, char *buf, int offs)
470 1.1 joerg {
471 1.1.1.5 joerg int i, j, ppos;
472 1.1.1.5 joerg enum mant tok;
473 1.1 joerg char mac[5];
474 1.1 joerg struct man_node *n;
475 1.1 joerg
476 1.1 joerg /* Comments and empties are quickly ignored. */
477 1.1 joerg
478 1.1.1.6 joerg offs++;
479 1.1.1.6 joerg
480 1.1.1.6 joerg if ('\0' == buf[offs])
481 1.1.1.3 joerg return(1);
482 1.1 joerg
483 1.1.1.6 joerg i = offs;
484 1.1 joerg
485 1.1.1.5 joerg /*
486 1.1.1.5 joerg * Skip whitespace between the control character and initial
487 1.1.1.5 joerg * text. "Whitespace" is both spaces and tabs.
488 1.1.1.5 joerg */
489 1.1.1.6 joerg
490 1.1.1.5 joerg if (' ' == buf[i] || '\t' == buf[i]) {
491 1.1 joerg i++;
492 1.1.1.5 joerg while (buf[i] && (' ' == buf[i] || '\t' == buf[i]))
493 1.1 joerg i++;
494 1.1.1.4 joerg if ('\0' == buf[i])
495 1.1 joerg goto out;
496 1.1 joerg }
497 1.1 joerg
498 1.1 joerg ppos = i;
499 1.1 joerg
500 1.1.1.10 joerg /*
501 1.1.1.10 joerg * Copy the first word into a nil-terminated buffer.
502 1.1.1.10 joerg * Stop copying when a tab, space, or eoln is encountered.
503 1.1.1.10 joerg */
504 1.1 joerg
505 1.1.1.10 joerg j = 0;
506 1.1.1.10 joerg while (j < 4 && '\0' != buf[i] && ' ' != buf[i] && '\t' != buf[i])
507 1.1.1.10 joerg mac[j++] = buf[i++];
508 1.1.1.3 joerg mac[j] = '\0';
509 1.1 joerg
510 1.1.1.10 joerg tok = (j > 0 && j < 4) ? man_hash_find(mac) : MAN_MAX;
511 1.1.1.10 joerg if (MAN_MAX == tok) {
512 1.1.1.10 joerg man_vmsg(m, MANDOCERR_MACRO, ln, 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 joerg while (buf[i] && ' ' == buf[i])
519 1.1 joerg i++;
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.4 joerg if ('\0' == buf[i] && ' ' == buf[i - 1])
527 1.1.1.10 joerg man_pmsg(m, ln, i - 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.10 joerg man_vmsg(m, MANDOCERR_LINESCOPE, n->line, n->pos,
546 1.1.1.10 joerg "%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.5 joerg if ( ! (*man_macros[tok].fp)(m, tok, ln, ppos, &i, buf))
565 1.1 joerg goto err;
566 1.1 joerg
567 1.1 joerg out:
568 1.1.1.5 joerg /*
569 1.1.1.5 joerg * We weren't in a block-line scope when entering the
570 1.1.1.5 joerg * above-parsed macro, so return.
571 1.1.1.5 joerg */
572 1.1.1.5 joerg
573 1.1.1.5 joerg if ( ! (MAN_BPLINE & m->flags)) {
574 1.1.1.5 joerg m->flags &= ~MAN_ILINE;
575 1.1 joerg return(1);
576 1.1.1.5 joerg }
577 1.1.1.5 joerg m->flags &= ~MAN_BPLINE;
578 1.1.1.5 joerg
579 1.1.1.5 joerg /*
580 1.1.1.5 joerg * If we're in a block scope, then allow this macro to slip by
581 1.1.1.5 joerg * without closing scope around it.
582 1.1.1.5 joerg */
583 1.1.1.5 joerg
584 1.1.1.5 joerg if (MAN_ILINE & m->flags) {
585 1.1.1.5 joerg m->flags &= ~MAN_ILINE;
586 1.1.1.5 joerg return(1);
587 1.1.1.5 joerg }
588 1.1 joerg
589 1.1 joerg /*
590 1.1 joerg * If we've opened a new next-line element scope, then return
591 1.1 joerg * now, as the next line will close out the block scope.
592 1.1 joerg */
593 1.1 joerg
594 1.1 joerg if (MAN_ELINE & m->flags)
595 1.1 joerg return(1);
596 1.1 joerg
597 1.1 joerg /* Close out the block scope opened in the prior line. */
598 1.1 joerg
599 1.1 joerg assert(MAN_BLINE & m->flags);
600 1.1 joerg m->flags &= ~MAN_BLINE;
601 1.1 joerg
602 1.1.1.6 joerg if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
603 1.1 joerg return(0);
604 1.1.1.6 joerg return(man_body_alloc(m, ln, offs, m->last->tok));
605 1.1 joerg
606 1.1 joerg err: /* Error out. */
607 1.1 joerg
608 1.1 joerg m->flags |= MAN_HALT;
609 1.1 joerg return(0);
610 1.1 joerg }
611 1.1 joerg
612 1.1 joerg
613 1.1 joerg int
614 1.1.1.6 joerg man_vmsg(struct man *man, enum mandocerr t,
615 1.1.1.6 joerg int ln, int pos, const char *fmt, ...)
616 1.1 joerg {
617 1.1 joerg char buf[256];
618 1.1 joerg va_list ap;
619 1.1 joerg
620 1.1 joerg va_start(ap, fmt);
621 1.1.1.6 joerg vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
622 1.1 joerg va_end(ap);
623 1.1.1.6 joerg return((*man->msg)(t, man->data, ln, pos, buf));
624 1.1 joerg }
625 1.1.1.5 joerg
626 1.1.1.5 joerg
627 1.1.1.5 joerg /*
628 1.1.1.5 joerg * Unlink a node from its context. If "m" is provided, the last parse
629 1.1.1.5 joerg * point will also be adjusted accordingly.
630 1.1.1.5 joerg */
631 1.1.1.5 joerg static void
632 1.1.1.5 joerg man_node_unlink(struct man *m, struct man_node *n)
633 1.1.1.5 joerg {
634 1.1.1.5 joerg
635 1.1.1.5 joerg /* Adjust siblings. */
636 1.1.1.5 joerg
637 1.1.1.5 joerg if (n->prev)
638 1.1.1.5 joerg n->prev->next = n->next;
639 1.1.1.5 joerg if (n->next)
640 1.1.1.5 joerg n->next->prev = n->prev;
641 1.1.1.5 joerg
642 1.1.1.5 joerg /* Adjust parent. */
643 1.1.1.5 joerg
644 1.1.1.5 joerg if (n->parent) {
645 1.1.1.5 joerg n->parent->nchild--;
646 1.1.1.5 joerg if (n->parent->child == n)
647 1.1.1.5 joerg n->parent->child = n->prev ? n->prev : n->next;
648 1.1.1.5 joerg }
649 1.1.1.5 joerg
650 1.1.1.5 joerg /* Adjust parse point, if applicable. */
651 1.1.1.5 joerg
652 1.1.1.5 joerg if (m && m->last == n) {
653 1.1.1.5 joerg /*XXX: this can occur when bailing from validation. */
654 1.1.1.5 joerg /*assert(NULL == n->next);*/
655 1.1.1.5 joerg if (n->prev) {
656 1.1.1.5 joerg m->last = n->prev;
657 1.1.1.5 joerg m->next = MAN_NEXT_SIBLING;
658 1.1.1.5 joerg } else {
659 1.1.1.5 joerg m->last = n->parent;
660 1.1.1.5 joerg m->next = MAN_NEXT_CHILD;
661 1.1.1.5 joerg }
662 1.1.1.5 joerg }
663 1.1.1.5 joerg
664 1.1.1.5 joerg if (m && m->first == n)
665 1.1.1.5 joerg m->first = NULL;
666 1.1.1.5 joerg }
667