]> git.cameronkatri.com Git - mandoc.git/blob - man.c
At the end of mansearch(), fchdir() back to where we started from;
[mandoc.git] / man.c
1 /* $Id: man.c,v 1.128 2014/03/30 19:47:48 schwarze Exp $ */
2 /*
3 * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
5 * Copyright (c) 2011 Joerg Sonnenberger <joerg@netbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <sys/types.h>
24
25 #include <assert.h>
26 #include <ctype.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include "man.h"
33 #include "mandoc.h"
34 #include "mandoc_aux.h"
35 #include "libman.h"
36 #include "libmandoc.h"
37
38 const char *const __man_macronames[MAN_MAX] = {
39 "br", "TH", "SH", "SS",
40 "TP", "LP", "PP", "P",
41 "IP", "HP", "SM", "SB",
42 "BI", "IB", "BR", "RB",
43 "R", "B", "I", "IR",
44 "RI", "na", "sp", "nf",
45 "fi", "RE", "RS", "DT",
46 "UC", "PD", "AT", "in",
47 "ft", "OP", "EX", "EE",
48 "UR", "UE", "ll"
49 };
50
51 const char * const *man_macronames = __man_macronames;
52
53 static struct man_node *man_node_alloc(struct man *, int, int,
54 enum man_type, enum mant);
55 static int man_node_append(struct man *,
56 struct man_node *);
57 static void man_node_free(struct man_node *);
58 static void man_node_unlink(struct man *,
59 struct man_node *);
60 static int man_ptext(struct man *, int, char *, int);
61 static int man_pmacro(struct man *, int, char *, int);
62 static void man_free1(struct man *);
63 static void man_alloc1(struct man *);
64 static int man_descope(struct man *, int, int);
65
66
67 const struct man_node *
68 man_node(const struct man *man)
69 {
70
71 assert( ! (MAN_HALT & man->flags));
72 return(man->first);
73 }
74
75
76 const struct man_meta *
77 man_meta(const struct man *man)
78 {
79
80 assert( ! (MAN_HALT & man->flags));
81 return(&man->meta);
82 }
83
84
85 void
86 man_reset(struct man *man)
87 {
88
89 man_free1(man);
90 man_alloc1(man);
91 }
92
93
94 void
95 man_free(struct man *man)
96 {
97
98 man_free1(man);
99 free(man);
100 }
101
102
103 struct man *
104 man_alloc(struct roff *roff, struct mparse *parse, int quick)
105 {
106 struct man *p;
107
108 p = mandoc_calloc(1, sizeof(struct man));
109
110 man_hash_init();
111 p->parse = parse;
112 p->quick = quick;
113 p->roff = roff;
114
115 man_alloc1(p);
116 return(p);
117 }
118
119
120 int
121 man_endparse(struct man *man)
122 {
123
124 assert( ! (MAN_HALT & man->flags));
125 if (man_macroend(man))
126 return(1);
127 man->flags |= MAN_HALT;
128 return(0);
129 }
130
131
132 int
133 man_parseln(struct man *man, int ln, char *buf, int offs)
134 {
135
136 man->flags |= MAN_NEWLINE;
137
138 assert( ! (MAN_HALT & man->flags));
139
140 return (roff_getcontrol(man->roff, buf, &offs) ?
141 man_pmacro(man, ln, buf, offs) :
142 man_ptext(man, ln, buf, offs));
143 }
144
145
146 static void
147 man_free1(struct man *man)
148 {
149
150 if (man->first)
151 man_node_delete(man, man->first);
152 if (man->meta.title)
153 free(man->meta.title);
154 if (man->meta.source)
155 free(man->meta.source);
156 if (man->meta.date)
157 free(man->meta.date);
158 if (man->meta.vol)
159 free(man->meta.vol);
160 if (man->meta.msec)
161 free(man->meta.msec);
162 }
163
164
165 static void
166 man_alloc1(struct man *man)
167 {
168
169 memset(&man->meta, 0, sizeof(struct man_meta));
170 man->flags = 0;
171 man->last = mandoc_calloc(1, sizeof(struct man_node));
172 man->first = man->last;
173 man->last->type = MAN_ROOT;
174 man->last->tok = MAN_MAX;
175 man->next = MAN_NEXT_CHILD;
176 }
177
178
179 static int
180 man_node_append(struct man *man, struct man_node *p)
181 {
182
183 assert(man->last);
184 assert(man->first);
185 assert(MAN_ROOT != p->type);
186
187 switch (man->next) {
188 case (MAN_NEXT_SIBLING):
189 man->last->next = p;
190 p->prev = man->last;
191 p->parent = man->last->parent;
192 break;
193 case (MAN_NEXT_CHILD):
194 man->last->child = p;
195 p->parent = man->last;
196 break;
197 default:
198 abort();
199 /* NOTREACHED */
200 }
201
202 assert(p->parent);
203 p->parent->nchild++;
204
205 if ( ! man_valid_pre(man, p))
206 return(0);
207
208 switch (p->type) {
209 case (MAN_HEAD):
210 assert(MAN_BLOCK == p->parent->type);
211 p->parent->head = p;
212 break;
213 case (MAN_TAIL):
214 assert(MAN_BLOCK == p->parent->type);
215 p->parent->tail = p;
216 break;
217 case (MAN_BODY):
218 assert(MAN_BLOCK == p->parent->type);
219 p->parent->body = p;
220 break;
221 default:
222 break;
223 }
224
225 man->last = p;
226
227 switch (p->type) {
228 case (MAN_TBL):
229 /* FALLTHROUGH */
230 case (MAN_TEXT):
231 if ( ! man_valid_post(man))
232 return(0);
233 break;
234 default:
235 break;
236 }
237
238 return(1);
239 }
240
241
242 static struct man_node *
243 man_node_alloc(struct man *man, int line, int pos,
244 enum man_type type, enum mant tok)
245 {
246 struct man_node *p;
247
248 p = mandoc_calloc(1, sizeof(struct man_node));
249 p->line = line;
250 p->pos = pos;
251 p->type = type;
252 p->tok = tok;
253
254 if (MAN_NEWLINE & man->flags)
255 p->flags |= MAN_LINE;
256 man->flags &= ~MAN_NEWLINE;
257 return(p);
258 }
259
260
261 int
262 man_elem_alloc(struct man *man, int line, int pos, enum mant tok)
263 {
264 struct man_node *p;
265
266 p = man_node_alloc(man, line, pos, MAN_ELEM, tok);
267 if ( ! man_node_append(man, p))
268 return(0);
269 man->next = MAN_NEXT_CHILD;
270 return(1);
271 }
272
273
274 int
275 man_tail_alloc(struct man *man, int line, int pos, enum mant tok)
276 {
277 struct man_node *p;
278
279 p = man_node_alloc(man, line, pos, MAN_TAIL, tok);
280 if ( ! man_node_append(man, p))
281 return(0);
282 man->next = MAN_NEXT_CHILD;
283 return(1);
284 }
285
286
287 int
288 man_head_alloc(struct man *man, int line, int pos, enum mant tok)
289 {
290 struct man_node *p;
291
292 p = man_node_alloc(man, line, pos, MAN_HEAD, tok);
293 if ( ! man_node_append(man, p))
294 return(0);
295 man->next = MAN_NEXT_CHILD;
296 return(1);
297 }
298
299
300 int
301 man_body_alloc(struct man *man, int line, int pos, enum mant tok)
302 {
303 struct man_node *p;
304
305 p = man_node_alloc(man, line, pos, MAN_BODY, tok);
306 if ( ! man_node_append(man, p))
307 return(0);
308 man->next = MAN_NEXT_CHILD;
309 return(1);
310 }
311
312
313 int
314 man_block_alloc(struct man *man, int line, int pos, enum mant tok)
315 {
316 struct man_node *p;
317
318 p = man_node_alloc(man, line, pos, MAN_BLOCK, tok);
319 if ( ! man_node_append(man, p))
320 return(0);
321 man->next = MAN_NEXT_CHILD;
322 return(1);
323 }
324
325 int
326 man_word_alloc(struct man *man, int line, int pos, const char *word)
327 {
328 struct man_node *n;
329
330 n = man_node_alloc(man, line, pos, MAN_TEXT, MAN_MAX);
331 n->string = roff_strdup(man->roff, word);
332
333 if ( ! man_node_append(man, n))
334 return(0);
335
336 man->next = MAN_NEXT_SIBLING;
337 return(1);
338 }
339
340
341 /*
342 * Free all of the resources held by a node. This does NOT unlink a
343 * node from its context; for that, see man_node_unlink().
344 */
345 static void
346 man_node_free(struct man_node *p)
347 {
348
349 if (p->string)
350 free(p->string);
351 free(p);
352 }
353
354
355 void
356 man_node_delete(struct man *man, struct man_node *p)
357 {
358
359 while (p->child)
360 man_node_delete(man, p->child);
361
362 man_node_unlink(man, p);
363 man_node_free(p);
364 }
365
366 int
367 man_addeqn(struct man *man, const struct eqn *ep)
368 {
369 struct man_node *n;
370
371 assert( ! (MAN_HALT & man->flags));
372
373 n = man_node_alloc(man, ep->ln, ep->pos, MAN_EQN, MAN_MAX);
374 n->eqn = ep;
375
376 if ( ! man_node_append(man, n))
377 return(0);
378
379 man->next = MAN_NEXT_SIBLING;
380 return(man_descope(man, ep->ln, ep->pos));
381 }
382
383 int
384 man_addspan(struct man *man, const struct tbl_span *sp)
385 {
386 struct man_node *n;
387
388 assert( ! (MAN_HALT & man->flags));
389
390 n = man_node_alloc(man, sp->line, 0, MAN_TBL, MAN_MAX);
391 n->span = sp;
392
393 if ( ! man_node_append(man, n))
394 return(0);
395
396 man->next = MAN_NEXT_SIBLING;
397 return(man_descope(man, sp->line, 0));
398 }
399
400 static int
401 man_descope(struct man *man, int line, int offs)
402 {
403 /*
404 * Co-ordinate what happens with having a next-line scope open:
405 * first close out the element scope (if applicable), then close
406 * out the block scope (also if applicable).
407 */
408
409 if (MAN_ELINE & man->flags) {
410 man->flags &= ~MAN_ELINE;
411 if ( ! man_unscope(man, man->last->parent, MANDOCERR_MAX))
412 return(0);
413 }
414
415 if ( ! (MAN_BLINE & man->flags))
416 return(1);
417 man->flags &= ~MAN_BLINE;
418
419 if ( ! man_unscope(man, man->last->parent, MANDOCERR_MAX))
420 return(0);
421 return(man_body_alloc(man, line, offs, man->last->tok));
422 }
423
424 static int
425 man_ptext(struct man *man, int line, char *buf, int offs)
426 {
427 int i;
428
429 /* Literal free-form text whitespace is preserved. */
430
431 if (MAN_LITERAL & man->flags) {
432 if ( ! man_word_alloc(man, line, offs, buf + offs))
433 return(0);
434 return(man_descope(man, line, offs));
435 }
436
437 for (i = offs; ' ' == buf[i]; i++)
438 /* Skip leading whitespace. */ ;
439
440 /*
441 * Blank lines are ignored right after headings
442 * but add a single vertical space elsewhere.
443 */
444
445 if ('\0' == buf[i]) {
446 /* Allocate a blank entry. */
447 if (MAN_SH != man->last->tok &&
448 MAN_SS != man->last->tok) {
449 if ( ! man_elem_alloc(man, line, offs, MAN_sp))
450 return(0);
451 man->next = MAN_NEXT_SIBLING;
452 }
453 return(1);
454 }
455
456 /*
457 * Warn if the last un-escaped character is whitespace. Then
458 * strip away the remaining spaces (tabs stay!).
459 */
460
461 i = (int)strlen(buf);
462 assert(i);
463
464 if (' ' == buf[i - 1] || '\t' == buf[i - 1]) {
465 if (i > 1 && '\\' != buf[i - 2])
466 man_pmsg(man, line, i - 1, MANDOCERR_EOLNSPACE);
467
468 for (--i; i && ' ' == buf[i]; i--)
469 /* Spin back to non-space. */ ;
470
471 /* Jump ahead of escaped whitespace. */
472 i += '\\' == buf[i] ? 2 : 1;
473
474 buf[i] = '\0';
475 }
476
477 if ( ! man_word_alloc(man, line, offs, buf + offs))
478 return(0);
479
480 /*
481 * End-of-sentence check. If the last character is an unescaped
482 * EOS character, then flag the node as being the end of a
483 * sentence. The front-end will know how to interpret this.
484 */
485
486 assert(i);
487 if (mandoc_eos(buf, (size_t)i))
488 man->last->flags |= MAN_EOS;
489
490 return(man_descope(man, line, offs));
491 }
492
493 static int
494 man_pmacro(struct man *man, int ln, char *buf, int offs)
495 {
496 int i, ppos;
497 enum mant tok;
498 char mac[5];
499 struct man_node *n;
500
501 if ('"' == buf[offs]) {
502 man_pmsg(man, ln, offs, MANDOCERR_BADCOMMENT);
503 return(1);
504 } else if ('\0' == buf[offs])
505 return(1);
506
507 ppos = offs;
508
509 /*
510 * Copy the first word into a nil-terminated buffer.
511 * Stop copying when a tab, space, or eoln is encountered.
512 */
513
514 i = 0;
515 while (i < 4 && '\0' != buf[offs] &&
516 ' ' != buf[offs] && '\t' != buf[offs])
517 mac[i++] = buf[offs++];
518
519 mac[i] = '\0';
520
521 tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX;
522
523 if (MAN_MAX == tok) {
524 mandoc_vmsg(MANDOCERR_MACRO, man->parse, ln,
525 ppos, "%s", buf + ppos - 1);
526 return(1);
527 }
528
529 /* The macro is sane. Jump to the next word. */
530
531 while (buf[offs] && ' ' == buf[offs])
532 offs++;
533
534 /*
535 * Trailing whitespace. Note that tabs are allowed to be passed
536 * into the parser as "text", so we only warn about spaces here.
537 */
538
539 if ('\0' == buf[offs] && ' ' == buf[offs - 1])
540 man_pmsg(man, ln, offs - 1, MANDOCERR_EOLNSPACE);
541
542 /*
543 * Remove prior ELINE macro, as it's being clobbered by a new
544 * macro. Note that NSCOPED macros do not close out ELINE
545 * macros---they don't print text---so we let those slip by.
546 */
547
548 if ( ! (MAN_NSCOPED & man_macros[tok].flags) &&
549 man->flags & MAN_ELINE) {
550 n = man->last;
551 assert(MAN_TEXT != n->type);
552
553 /* Remove repeated NSCOPED macros causing ELINE. */
554
555 if (MAN_NSCOPED & man_macros[n->tok].flags)
556 n = n->parent;
557
558 mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line,
559 n->pos, "%s breaks %s", man_macronames[tok],
560 man_macronames[n->tok]);
561
562 man_node_delete(man, n);
563 man->flags &= ~MAN_ELINE;
564 }
565
566 /*
567 * Remove prior BLINE macro that is being clobbered.
568 */
569 if ((man->flags & MAN_BLINE) &&
570 (MAN_BSCOPE & man_macros[tok].flags)) {
571 n = man->last;
572
573 /* Might be a text node like 8 in
574 * .TP 8
575 * .SH foo
576 */
577 if (MAN_TEXT == n->type)
578 n = n->parent;
579
580 /* Remove element that didn't end BLINE, if any. */
581 if ( ! (MAN_BSCOPE & man_macros[n->tok].flags))
582 n = n->parent;
583
584 assert(MAN_HEAD == n->type);
585 n = n->parent;
586 assert(MAN_BLOCK == n->type);
587 assert(MAN_SCOPED & man_macros[n->tok].flags);
588
589 mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line,
590 n->pos, "%s breaks %s", man_macronames[tok],
591 man_macronames[n->tok]);
592
593 man_node_delete(man, n);
594 man->flags &= ~MAN_BLINE;
595 }
596
597 /*
598 * Save the fact that we're in the next-line for a block. In
599 * this way, embedded roff instructions can "remember" state
600 * when they exit.
601 */
602
603 if (MAN_BLINE & man->flags)
604 man->flags |= MAN_BPLINE;
605
606 /* Call to handler... */
607
608 assert(man_macros[tok].fp);
609 if ( ! (*man_macros[tok].fp)(man, tok, ln, ppos, &offs, buf))
610 goto err;
611
612 /* In quick mode (for mandocdb), abort after the NAME section. */
613
614 if (man->quick && MAN_SH == tok &&
615 strcmp(man->last->prev->child->string, "NAME"))
616 return(2);
617
618 /*
619 * We weren't in a block-line scope when entering the
620 * above-parsed macro, so return.
621 */
622
623 if ( ! (MAN_BPLINE & man->flags)) {
624 man->flags &= ~MAN_ILINE;
625 return(1);
626 }
627 man->flags &= ~MAN_BPLINE;
628
629 /*
630 * If we're in a block scope, then allow this macro to slip by
631 * without closing scope around it.
632 */
633
634 if (MAN_ILINE & man->flags) {
635 man->flags &= ~MAN_ILINE;
636 return(1);
637 }
638
639 /*
640 * If we've opened a new next-line element scope, then return
641 * now, as the next line will close out the block scope.
642 */
643
644 if (MAN_ELINE & man->flags)
645 return(1);
646
647 /* Close out the block scope opened in the prior line. */
648
649 assert(MAN_BLINE & man->flags);
650 man->flags &= ~MAN_BLINE;
651
652 if ( ! man_unscope(man, man->last->parent, MANDOCERR_MAX))
653 return(0);
654 return(man_body_alloc(man, ln, ppos, man->last->tok));
655
656 err: /* Error out. */
657
658 man->flags |= MAN_HALT;
659 return(0);
660 }
661
662 /*
663 * Unlink a node from its context. If "man" is provided, the last parse
664 * point will also be adjusted accordingly.
665 */
666 static void
667 man_node_unlink(struct man *man, struct man_node *n)
668 {
669
670 /* Adjust siblings. */
671
672 if (n->prev)
673 n->prev->next = n->next;
674 if (n->next)
675 n->next->prev = n->prev;
676
677 /* Adjust parent. */
678
679 if (n->parent) {
680 n->parent->nchild--;
681 if (n->parent->child == n)
682 n->parent->child = n->prev ? n->prev : n->next;
683 }
684
685 /* Adjust parse point, if applicable. */
686
687 if (man && man->last == n) {
688 /*XXX: this can occur when bailing from validation. */
689 /*assert(NULL == n->next);*/
690 if (n->prev) {
691 man->last = n->prev;
692 man->next = MAN_NEXT_SIBLING;
693 } else {
694 man->last = n->parent;
695 man->next = MAN_NEXT_CHILD;
696 }
697 }
698
699 if (man && man->first == n)
700 man->first = NULL;
701 }
702
703 const struct mparse *
704 man_mparse(const struct man *man)
705 {
706
707 assert(man && man->parse);
708 return(man->parse);
709 }
710
711 void
712 man_deroff(char **dest, const struct man_node *n)
713 {
714 char *cp;
715 size_t sz;
716
717 if (MAN_TEXT != n->type) {
718 for (n = n->child; n; n = n->next)
719 man_deroff(dest, n);
720 return;
721 }
722
723 /* Skip leading whitespace and escape sequences. */
724
725 cp = n->string;
726 while ('\0' != *cp) {
727 if ('\\' == *cp) {
728 cp++;
729 mandoc_escape((const char **)&cp, NULL, NULL);
730 } else if (isspace((unsigned char)*cp))
731 cp++;
732 else
733 break;
734 }
735
736 /* Skip trailing whitespace. */
737
738 for (sz = strlen(cp); sz; sz--)
739 if (0 == isspace((unsigned char)cp[sz-1]))
740 break;
741
742 /* Skip empty strings. */
743
744 if (0 == sz)
745 return;
746
747 if (NULL == *dest) {
748 *dest = mandoc_strndup(cp, sz);
749 return;
750 }
751
752 mandoc_asprintf(&cp, "%s %*s", *dest, (int)sz, cp);
753 free(*dest);
754 *dest = cp;
755 }