1*698f87a4SGarrett D'Amore /* $Id: man.c,v 1.121 2013/11/10 22:54:40 schwarze Exp $ */
295c635efSGarrett D'Amore /*
395c635efSGarrett D'Amore * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
495c635efSGarrett D'Amore *
595c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any
695c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above
795c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies.
895c635efSGarrett D'Amore *
995c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1095c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1195c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1295c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1395c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1495c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1595c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1695c635efSGarrett D'Amore */
1795c635efSGarrett D'Amore #ifdef HAVE_CONFIG_H
1895c635efSGarrett D'Amore #include "config.h"
1995c635efSGarrett D'Amore #endif
2095c635efSGarrett D'Amore
2195c635efSGarrett D'Amore #include <sys/types.h>
2295c635efSGarrett D'Amore
2395c635efSGarrett D'Amore #include <assert.h>
2495c635efSGarrett D'Amore #include <stdarg.h>
2595c635efSGarrett D'Amore #include <stdlib.h>
2695c635efSGarrett D'Amore #include <stdio.h>
2795c635efSGarrett D'Amore #include <string.h>
2895c635efSGarrett D'Amore
2995c635efSGarrett D'Amore #include "man.h"
3095c635efSGarrett D'Amore #include "mandoc.h"
3195c635efSGarrett D'Amore #include "libman.h"
3295c635efSGarrett D'Amore #include "libmandoc.h"
3395c635efSGarrett D'Amore
3495c635efSGarrett D'Amore const char *const __man_macronames[MAN_MAX] = {
3595c635efSGarrett D'Amore "br", "TH", "SH", "SS",
3695c635efSGarrett D'Amore "TP", "LP", "PP", "P",
3795c635efSGarrett D'Amore "IP", "HP", "SM", "SB",
3895c635efSGarrett D'Amore "BI", "IB", "BR", "RB",
3995c635efSGarrett D'Amore "R", "B", "I", "IR",
4095c635efSGarrett D'Amore "RI", "na", "sp", "nf",
4195c635efSGarrett D'Amore "fi", "RE", "RS", "DT",
4295c635efSGarrett D'Amore "UC", "PD", "AT", "in",
43*698f87a4SGarrett D'Amore "ft", "OP", "EX", "EE",
44*698f87a4SGarrett D'Amore "UR", "UE"
4595c635efSGarrett D'Amore };
4695c635efSGarrett D'Amore
4795c635efSGarrett D'Amore const char * const *man_macronames = __man_macronames;
4895c635efSGarrett D'Amore
4995c635efSGarrett D'Amore static struct man_node *man_node_alloc(struct man *, int, int,
5095c635efSGarrett D'Amore enum man_type, enum mant);
5195c635efSGarrett D'Amore static int man_node_append(struct man *,
5295c635efSGarrett D'Amore struct man_node *);
5395c635efSGarrett D'Amore static void man_node_free(struct man_node *);
5495c635efSGarrett D'Amore static void man_node_unlink(struct man *,
5595c635efSGarrett D'Amore struct man_node *);
5695c635efSGarrett D'Amore static int man_ptext(struct man *, int, char *, int);
5795c635efSGarrett D'Amore static int man_pmacro(struct man *, int, char *, int);
5895c635efSGarrett D'Amore static void man_free1(struct man *);
5995c635efSGarrett D'Amore static void man_alloc1(struct man *);
6095c635efSGarrett D'Amore static int man_descope(struct man *, int, int);
6195c635efSGarrett D'Amore
6295c635efSGarrett D'Amore
6395c635efSGarrett D'Amore const struct man_node *
man_node(const struct man * man)64*698f87a4SGarrett D'Amore man_node(const struct man *man)
6595c635efSGarrett D'Amore {
6695c635efSGarrett D'Amore
67*698f87a4SGarrett D'Amore assert( ! (MAN_HALT & man->flags));
68*698f87a4SGarrett D'Amore return(man->first);
6995c635efSGarrett D'Amore }
7095c635efSGarrett D'Amore
7195c635efSGarrett D'Amore
7295c635efSGarrett D'Amore const struct man_meta *
man_meta(const struct man * man)73*698f87a4SGarrett D'Amore man_meta(const struct man *man)
7495c635efSGarrett D'Amore {
7595c635efSGarrett D'Amore
76*698f87a4SGarrett D'Amore assert( ! (MAN_HALT & man->flags));
77*698f87a4SGarrett D'Amore return(&man->meta);
7895c635efSGarrett D'Amore }
7995c635efSGarrett D'Amore
8095c635efSGarrett D'Amore
8195c635efSGarrett D'Amore void
man_reset(struct man * man)8295c635efSGarrett D'Amore man_reset(struct man *man)
8395c635efSGarrett D'Amore {
8495c635efSGarrett D'Amore
8595c635efSGarrett D'Amore man_free1(man);
8695c635efSGarrett D'Amore man_alloc1(man);
8795c635efSGarrett D'Amore }
8895c635efSGarrett D'Amore
8995c635efSGarrett D'Amore
9095c635efSGarrett D'Amore void
man_free(struct man * man)9195c635efSGarrett D'Amore man_free(struct man *man)
9295c635efSGarrett D'Amore {
9395c635efSGarrett D'Amore
9495c635efSGarrett D'Amore man_free1(man);
9595c635efSGarrett D'Amore free(man);
9695c635efSGarrett D'Amore }
9795c635efSGarrett D'Amore
9895c635efSGarrett D'Amore
9995c635efSGarrett D'Amore struct man *
man_alloc(struct roff * roff,struct mparse * parse)10095c635efSGarrett D'Amore man_alloc(struct roff *roff, struct mparse *parse)
10195c635efSGarrett D'Amore {
10295c635efSGarrett D'Amore struct man *p;
10395c635efSGarrett D'Amore
10495c635efSGarrett D'Amore p = mandoc_calloc(1, sizeof(struct man));
10595c635efSGarrett D'Amore
10695c635efSGarrett D'Amore man_hash_init();
10795c635efSGarrett D'Amore p->parse = parse;
10895c635efSGarrett D'Amore p->roff = roff;
10995c635efSGarrett D'Amore
11095c635efSGarrett D'Amore man_alloc1(p);
11195c635efSGarrett D'Amore return(p);
11295c635efSGarrett D'Amore }
11395c635efSGarrett D'Amore
11495c635efSGarrett D'Amore
11595c635efSGarrett D'Amore int
man_endparse(struct man * man)116*698f87a4SGarrett D'Amore man_endparse(struct man *man)
11795c635efSGarrett D'Amore {
11895c635efSGarrett D'Amore
119*698f87a4SGarrett D'Amore assert( ! (MAN_HALT & man->flags));
120*698f87a4SGarrett D'Amore if (man_macroend(man))
12195c635efSGarrett D'Amore return(1);
122*698f87a4SGarrett D'Amore man->flags |= MAN_HALT;
12395c635efSGarrett D'Amore return(0);
12495c635efSGarrett D'Amore }
12595c635efSGarrett D'Amore
12695c635efSGarrett D'Amore
12795c635efSGarrett D'Amore int
man_parseln(struct man * man,int ln,char * buf,int offs)128*698f87a4SGarrett D'Amore man_parseln(struct man *man, int ln, char *buf, int offs)
12995c635efSGarrett D'Amore {
13095c635efSGarrett D'Amore
131*698f87a4SGarrett D'Amore man->flags |= MAN_NEWLINE;
13295c635efSGarrett D'Amore
133*698f87a4SGarrett D'Amore assert( ! (MAN_HALT & man->flags));
13495c635efSGarrett D'Amore
135*698f87a4SGarrett D'Amore return (roff_getcontrol(man->roff, buf, &offs) ?
136*698f87a4SGarrett D'Amore man_pmacro(man, ln, buf, offs) :
137*698f87a4SGarrett D'Amore man_ptext(man, ln, buf, offs));
13895c635efSGarrett D'Amore }
13995c635efSGarrett D'Amore
14095c635efSGarrett D'Amore
14195c635efSGarrett D'Amore static void
man_free1(struct man * man)14295c635efSGarrett D'Amore man_free1(struct man *man)
14395c635efSGarrett D'Amore {
14495c635efSGarrett D'Amore
14595c635efSGarrett D'Amore if (man->first)
14695c635efSGarrett D'Amore man_node_delete(man, man->first);
14795c635efSGarrett D'Amore if (man->meta.title)
14895c635efSGarrett D'Amore free(man->meta.title);
14995c635efSGarrett D'Amore if (man->meta.source)
15095c635efSGarrett D'Amore free(man->meta.source);
15195c635efSGarrett D'Amore if (man->meta.date)
15295c635efSGarrett D'Amore free(man->meta.date);
15395c635efSGarrett D'Amore if (man->meta.vol)
15495c635efSGarrett D'Amore free(man->meta.vol);
15595c635efSGarrett D'Amore if (man->meta.msec)
15695c635efSGarrett D'Amore free(man->meta.msec);
15795c635efSGarrett D'Amore }
15895c635efSGarrett D'Amore
15995c635efSGarrett D'Amore
16095c635efSGarrett D'Amore static void
man_alloc1(struct man * man)161*698f87a4SGarrett D'Amore man_alloc1(struct man *man)
16295c635efSGarrett D'Amore {
16395c635efSGarrett D'Amore
164*698f87a4SGarrett D'Amore memset(&man->meta, 0, sizeof(struct man_meta));
165*698f87a4SGarrett D'Amore man->flags = 0;
166*698f87a4SGarrett D'Amore man->last = mandoc_calloc(1, sizeof(struct man_node));
167*698f87a4SGarrett D'Amore man->first = man->last;
168*698f87a4SGarrett D'Amore man->last->type = MAN_ROOT;
169*698f87a4SGarrett D'Amore man->last->tok = MAN_MAX;
170*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD;
17195c635efSGarrett D'Amore }
17295c635efSGarrett D'Amore
17395c635efSGarrett D'Amore
17495c635efSGarrett D'Amore static int
man_node_append(struct man * man,struct man_node * p)17595c635efSGarrett D'Amore man_node_append(struct man *man, struct man_node *p)
17695c635efSGarrett D'Amore {
17795c635efSGarrett D'Amore
17895c635efSGarrett D'Amore assert(man->last);
17995c635efSGarrett D'Amore assert(man->first);
18095c635efSGarrett D'Amore assert(MAN_ROOT != p->type);
18195c635efSGarrett D'Amore
18295c635efSGarrett D'Amore switch (man->next) {
18395c635efSGarrett D'Amore case (MAN_NEXT_SIBLING):
18495c635efSGarrett D'Amore man->last->next = p;
18595c635efSGarrett D'Amore p->prev = man->last;
18695c635efSGarrett D'Amore p->parent = man->last->parent;
18795c635efSGarrett D'Amore break;
18895c635efSGarrett D'Amore case (MAN_NEXT_CHILD):
18995c635efSGarrett D'Amore man->last->child = p;
19095c635efSGarrett D'Amore p->parent = man->last;
19195c635efSGarrett D'Amore break;
19295c635efSGarrett D'Amore default:
19395c635efSGarrett D'Amore abort();
19495c635efSGarrett D'Amore /* NOTREACHED */
19595c635efSGarrett D'Amore }
19695c635efSGarrett D'Amore
19795c635efSGarrett D'Amore assert(p->parent);
19895c635efSGarrett D'Amore p->parent->nchild++;
19995c635efSGarrett D'Amore
20095c635efSGarrett D'Amore if ( ! man_valid_pre(man, p))
20195c635efSGarrett D'Amore return(0);
20295c635efSGarrett D'Amore
20395c635efSGarrett D'Amore switch (p->type) {
20495c635efSGarrett D'Amore case (MAN_HEAD):
20595c635efSGarrett D'Amore assert(MAN_BLOCK == p->parent->type);
20695c635efSGarrett D'Amore p->parent->head = p;
20795c635efSGarrett D'Amore break;
20895c635efSGarrett D'Amore case (MAN_TAIL):
20995c635efSGarrett D'Amore assert(MAN_BLOCK == p->parent->type);
21095c635efSGarrett D'Amore p->parent->tail = p;
21195c635efSGarrett D'Amore break;
21295c635efSGarrett D'Amore case (MAN_BODY):
21395c635efSGarrett D'Amore assert(MAN_BLOCK == p->parent->type);
21495c635efSGarrett D'Amore p->parent->body = p;
21595c635efSGarrett D'Amore break;
21695c635efSGarrett D'Amore default:
21795c635efSGarrett D'Amore break;
21895c635efSGarrett D'Amore }
21995c635efSGarrett D'Amore
22095c635efSGarrett D'Amore man->last = p;
22195c635efSGarrett D'Amore
22295c635efSGarrett D'Amore switch (p->type) {
22395c635efSGarrett D'Amore case (MAN_TBL):
22495c635efSGarrett D'Amore /* FALLTHROUGH */
22595c635efSGarrett D'Amore case (MAN_TEXT):
22695c635efSGarrett D'Amore if ( ! man_valid_post(man))
22795c635efSGarrett D'Amore return(0);
22895c635efSGarrett D'Amore break;
22995c635efSGarrett D'Amore default:
23095c635efSGarrett D'Amore break;
23195c635efSGarrett D'Amore }
23295c635efSGarrett D'Amore
23395c635efSGarrett D'Amore return(1);
23495c635efSGarrett D'Amore }
23595c635efSGarrett D'Amore
23695c635efSGarrett D'Amore
23795c635efSGarrett D'Amore static struct man_node *
man_node_alloc(struct man * man,int line,int pos,enum man_type type,enum mant tok)238*698f87a4SGarrett D'Amore man_node_alloc(struct man *man, int line, int pos,
23995c635efSGarrett D'Amore enum man_type type, enum mant tok)
24095c635efSGarrett D'Amore {
24195c635efSGarrett D'Amore struct man_node *p;
24295c635efSGarrett D'Amore
24395c635efSGarrett D'Amore p = mandoc_calloc(1, sizeof(struct man_node));
24495c635efSGarrett D'Amore p->line = line;
24595c635efSGarrett D'Amore p->pos = pos;
24695c635efSGarrett D'Amore p->type = type;
24795c635efSGarrett D'Amore p->tok = tok;
24895c635efSGarrett D'Amore
249*698f87a4SGarrett D'Amore if (MAN_NEWLINE & man->flags)
25095c635efSGarrett D'Amore p->flags |= MAN_LINE;
251*698f87a4SGarrett D'Amore man->flags &= ~MAN_NEWLINE;
25295c635efSGarrett D'Amore return(p);
25395c635efSGarrett D'Amore }
25495c635efSGarrett D'Amore
25595c635efSGarrett D'Amore
25695c635efSGarrett D'Amore int
man_elem_alloc(struct man * man,int line,int pos,enum mant tok)257*698f87a4SGarrett D'Amore man_elem_alloc(struct man *man, int line, int pos, enum mant tok)
25895c635efSGarrett D'Amore {
25995c635efSGarrett D'Amore struct man_node *p;
26095c635efSGarrett D'Amore
261*698f87a4SGarrett D'Amore p = man_node_alloc(man, line, pos, MAN_ELEM, tok);
262*698f87a4SGarrett D'Amore if ( ! man_node_append(man, p))
26395c635efSGarrett D'Amore return(0);
264*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD;
26595c635efSGarrett D'Amore return(1);
26695c635efSGarrett D'Amore }
26795c635efSGarrett D'Amore
26895c635efSGarrett D'Amore
26995c635efSGarrett D'Amore int
man_tail_alloc(struct man * man,int line,int pos,enum mant tok)270*698f87a4SGarrett D'Amore man_tail_alloc(struct man *man, int line, int pos, enum mant tok)
27195c635efSGarrett D'Amore {
27295c635efSGarrett D'Amore struct man_node *p;
27395c635efSGarrett D'Amore
274*698f87a4SGarrett D'Amore p = man_node_alloc(man, line, pos, MAN_TAIL, tok);
275*698f87a4SGarrett D'Amore if ( ! man_node_append(man, p))
27695c635efSGarrett D'Amore return(0);
277*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD;
27895c635efSGarrett D'Amore return(1);
27995c635efSGarrett D'Amore }
28095c635efSGarrett D'Amore
28195c635efSGarrett D'Amore
28295c635efSGarrett D'Amore int
man_head_alloc(struct man * man,int line,int pos,enum mant tok)283*698f87a4SGarrett D'Amore man_head_alloc(struct man *man, int line, int pos, enum mant tok)
28495c635efSGarrett D'Amore {
28595c635efSGarrett D'Amore struct man_node *p;
28695c635efSGarrett D'Amore
287*698f87a4SGarrett D'Amore p = man_node_alloc(man, line, pos, MAN_HEAD, tok);
288*698f87a4SGarrett D'Amore if ( ! man_node_append(man, p))
28995c635efSGarrett D'Amore return(0);
290*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD;
29195c635efSGarrett D'Amore return(1);
29295c635efSGarrett D'Amore }
29395c635efSGarrett D'Amore
29495c635efSGarrett D'Amore
29595c635efSGarrett D'Amore int
man_body_alloc(struct man * man,int line,int pos,enum mant tok)296*698f87a4SGarrett D'Amore man_body_alloc(struct man *man, int line, int pos, enum mant tok)
29795c635efSGarrett D'Amore {
29895c635efSGarrett D'Amore struct man_node *p;
29995c635efSGarrett D'Amore
300*698f87a4SGarrett D'Amore p = man_node_alloc(man, line, pos, MAN_BODY, tok);
301*698f87a4SGarrett D'Amore if ( ! man_node_append(man, p))
30295c635efSGarrett D'Amore return(0);
303*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD;
30495c635efSGarrett D'Amore return(1);
30595c635efSGarrett D'Amore }
30695c635efSGarrett D'Amore
30795c635efSGarrett D'Amore
30895c635efSGarrett D'Amore int
man_block_alloc(struct man * man,int line,int pos,enum mant tok)309*698f87a4SGarrett D'Amore man_block_alloc(struct man *man, int line, int pos, enum mant tok)
31095c635efSGarrett D'Amore {
31195c635efSGarrett D'Amore struct man_node *p;
31295c635efSGarrett D'Amore
313*698f87a4SGarrett D'Amore p = man_node_alloc(man, line, pos, MAN_BLOCK, tok);
314*698f87a4SGarrett D'Amore if ( ! man_node_append(man, p))
31595c635efSGarrett D'Amore return(0);
316*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD;
31795c635efSGarrett D'Amore return(1);
31895c635efSGarrett D'Amore }
31995c635efSGarrett D'Amore
32095c635efSGarrett D'Amore int
man_word_alloc(struct man * man,int line,int pos,const char * word)321*698f87a4SGarrett D'Amore man_word_alloc(struct man *man, int line, int pos, const char *word)
32295c635efSGarrett D'Amore {
32395c635efSGarrett D'Amore struct man_node *n;
32495c635efSGarrett D'Amore
325*698f87a4SGarrett D'Amore n = man_node_alloc(man, line, pos, MAN_TEXT, MAN_MAX);
326*698f87a4SGarrett D'Amore n->string = roff_strdup(man->roff, word);
32795c635efSGarrett D'Amore
328*698f87a4SGarrett D'Amore if ( ! man_node_append(man, n))
32995c635efSGarrett D'Amore return(0);
33095c635efSGarrett D'Amore
331*698f87a4SGarrett D'Amore man->next = MAN_NEXT_SIBLING;
33295c635efSGarrett D'Amore return(1);
33395c635efSGarrett D'Amore }
33495c635efSGarrett D'Amore
33595c635efSGarrett D'Amore
33695c635efSGarrett D'Amore /*
33795c635efSGarrett D'Amore * Free all of the resources held by a node. This does NOT unlink a
33895c635efSGarrett D'Amore * node from its context; for that, see man_node_unlink().
33995c635efSGarrett D'Amore */
34095c635efSGarrett D'Amore static void
man_node_free(struct man_node * p)34195c635efSGarrett D'Amore man_node_free(struct man_node *p)
34295c635efSGarrett D'Amore {
34395c635efSGarrett D'Amore
34495c635efSGarrett D'Amore if (p->string)
34595c635efSGarrett D'Amore free(p->string);
34695c635efSGarrett D'Amore free(p);
34795c635efSGarrett D'Amore }
34895c635efSGarrett D'Amore
34995c635efSGarrett D'Amore
35095c635efSGarrett D'Amore void
man_node_delete(struct man * man,struct man_node * p)351*698f87a4SGarrett D'Amore man_node_delete(struct man *man, struct man_node *p)
35295c635efSGarrett D'Amore {
35395c635efSGarrett D'Amore
35495c635efSGarrett D'Amore while (p->child)
355*698f87a4SGarrett D'Amore man_node_delete(man, p->child);
35695c635efSGarrett D'Amore
357*698f87a4SGarrett D'Amore man_node_unlink(man, p);
35895c635efSGarrett D'Amore man_node_free(p);
35995c635efSGarrett D'Amore }
36095c635efSGarrett D'Amore
36195c635efSGarrett D'Amore int
man_addeqn(struct man * man,const struct eqn * ep)362*698f87a4SGarrett D'Amore man_addeqn(struct man *man, const struct eqn *ep)
36395c635efSGarrett D'Amore {
36495c635efSGarrett D'Amore struct man_node *n;
36595c635efSGarrett D'Amore
366*698f87a4SGarrett D'Amore assert( ! (MAN_HALT & man->flags));
36795c635efSGarrett D'Amore
368*698f87a4SGarrett D'Amore n = man_node_alloc(man, ep->ln, ep->pos, MAN_EQN, MAN_MAX);
36995c635efSGarrett D'Amore n->eqn = ep;
37095c635efSGarrett D'Amore
371*698f87a4SGarrett D'Amore if ( ! man_node_append(man, n))
37295c635efSGarrett D'Amore return(0);
37395c635efSGarrett D'Amore
374*698f87a4SGarrett D'Amore man->next = MAN_NEXT_SIBLING;
375*698f87a4SGarrett D'Amore return(man_descope(man, ep->ln, ep->pos));
37695c635efSGarrett D'Amore }
37795c635efSGarrett D'Amore
37895c635efSGarrett D'Amore int
man_addspan(struct man * man,const struct tbl_span * sp)379*698f87a4SGarrett D'Amore man_addspan(struct man *man, const struct tbl_span *sp)
38095c635efSGarrett D'Amore {
38195c635efSGarrett D'Amore struct man_node *n;
38295c635efSGarrett D'Amore
383*698f87a4SGarrett D'Amore assert( ! (MAN_HALT & man->flags));
38495c635efSGarrett D'Amore
385*698f87a4SGarrett D'Amore n = man_node_alloc(man, sp->line, 0, MAN_TBL, MAN_MAX);
38695c635efSGarrett D'Amore n->span = sp;
38795c635efSGarrett D'Amore
388*698f87a4SGarrett D'Amore if ( ! man_node_append(man, n))
38995c635efSGarrett D'Amore return(0);
39095c635efSGarrett D'Amore
391*698f87a4SGarrett D'Amore man->next = MAN_NEXT_SIBLING;
392*698f87a4SGarrett D'Amore return(man_descope(man, sp->line, 0));
39395c635efSGarrett D'Amore }
39495c635efSGarrett D'Amore
39595c635efSGarrett D'Amore static int
man_descope(struct man * man,int line,int offs)396*698f87a4SGarrett D'Amore man_descope(struct man *man, int line, int offs)
39795c635efSGarrett D'Amore {
39895c635efSGarrett D'Amore /*
39995c635efSGarrett D'Amore * Co-ordinate what happens with having a next-line scope open:
40095c635efSGarrett D'Amore * first close out the element scope (if applicable), then close
40195c635efSGarrett D'Amore * out the block scope (also if applicable).
40295c635efSGarrett D'Amore */
40395c635efSGarrett D'Amore
404*698f87a4SGarrett D'Amore if (MAN_ELINE & man->flags) {
405*698f87a4SGarrett D'Amore man->flags &= ~MAN_ELINE;
406*698f87a4SGarrett D'Amore if ( ! man_unscope(man, man->last->parent, MANDOCERR_MAX))
40795c635efSGarrett D'Amore return(0);
40895c635efSGarrett D'Amore }
40995c635efSGarrett D'Amore
410*698f87a4SGarrett D'Amore if ( ! (MAN_BLINE & man->flags))
41195c635efSGarrett D'Amore return(1);
412*698f87a4SGarrett D'Amore man->flags &= ~MAN_BLINE;
41395c635efSGarrett D'Amore
414*698f87a4SGarrett D'Amore if ( ! man_unscope(man, man->last->parent, MANDOCERR_MAX))
41595c635efSGarrett D'Amore return(0);
416*698f87a4SGarrett D'Amore return(man_body_alloc(man, line, offs, man->last->tok));
41795c635efSGarrett D'Amore }
41895c635efSGarrett D'Amore
41995c635efSGarrett D'Amore static int
man_ptext(struct man * man,int line,char * buf,int offs)420*698f87a4SGarrett D'Amore man_ptext(struct man *man, int line, char *buf, int offs)
42195c635efSGarrett D'Amore {
42295c635efSGarrett D'Amore int i;
42395c635efSGarrett D'Amore
42495c635efSGarrett D'Amore /* Literal free-form text whitespace is preserved. */
42595c635efSGarrett D'Amore
426*698f87a4SGarrett D'Amore if (MAN_LITERAL & man->flags) {
427*698f87a4SGarrett D'Amore if ( ! man_word_alloc(man, line, offs, buf + offs))
42895c635efSGarrett D'Amore return(0);
429*698f87a4SGarrett D'Amore return(man_descope(man, line, offs));
43095c635efSGarrett D'Amore }
43195c635efSGarrett D'Amore
43295c635efSGarrett D'Amore for (i = offs; ' ' == buf[i]; i++)
43395c635efSGarrett D'Amore /* Skip leading whitespace. */ ;
43495c635efSGarrett D'Amore
435*698f87a4SGarrett D'Amore /*
436*698f87a4SGarrett D'Amore * Blank lines are ignored right after headings
437*698f87a4SGarrett D'Amore * but add a single vertical space elsewhere.
438*698f87a4SGarrett D'Amore */
439*698f87a4SGarrett D'Amore
44095c635efSGarrett D'Amore if ('\0' == buf[i]) {
44195c635efSGarrett D'Amore /* Allocate a blank entry. */
442*698f87a4SGarrett D'Amore if (MAN_SH != man->last->tok &&
443*698f87a4SGarrett D'Amore MAN_SS != man->last->tok) {
444*698f87a4SGarrett D'Amore if ( ! man_elem_alloc(man, line, offs, MAN_sp))
44595c635efSGarrett D'Amore return(0);
446*698f87a4SGarrett D'Amore man->next = MAN_NEXT_SIBLING;
447*698f87a4SGarrett D'Amore }
448*698f87a4SGarrett D'Amore return(1);
44995c635efSGarrett D'Amore }
45095c635efSGarrett D'Amore
45195c635efSGarrett D'Amore /*
45295c635efSGarrett D'Amore * Warn if the last un-escaped character is whitespace. Then
45395c635efSGarrett D'Amore * strip away the remaining spaces (tabs stay!).
45495c635efSGarrett D'Amore */
45595c635efSGarrett D'Amore
45695c635efSGarrett D'Amore i = (int)strlen(buf);
45795c635efSGarrett D'Amore assert(i);
45895c635efSGarrett D'Amore
45995c635efSGarrett D'Amore if (' ' == buf[i - 1] || '\t' == buf[i - 1]) {
46095c635efSGarrett D'Amore if (i > 1 && '\\' != buf[i - 2])
461*698f87a4SGarrett D'Amore man_pmsg(man, line, i - 1, MANDOCERR_EOLNSPACE);
46295c635efSGarrett D'Amore
46395c635efSGarrett D'Amore for (--i; i && ' ' == buf[i]; i--)
46495c635efSGarrett D'Amore /* Spin back to non-space. */ ;
46595c635efSGarrett D'Amore
46695c635efSGarrett D'Amore /* Jump ahead of escaped whitespace. */
46795c635efSGarrett D'Amore i += '\\' == buf[i] ? 2 : 1;
46895c635efSGarrett D'Amore
46995c635efSGarrett D'Amore buf[i] = '\0';
47095c635efSGarrett D'Amore }
47195c635efSGarrett D'Amore
472*698f87a4SGarrett D'Amore if ( ! man_word_alloc(man, line, offs, buf + offs))
47395c635efSGarrett D'Amore return(0);
47495c635efSGarrett D'Amore
47595c635efSGarrett D'Amore /*
47695c635efSGarrett D'Amore * End-of-sentence check. If the last character is an unescaped
47795c635efSGarrett D'Amore * EOS character, then flag the node as being the end of a
47895c635efSGarrett D'Amore * sentence. The front-end will know how to interpret this.
47995c635efSGarrett D'Amore */
48095c635efSGarrett D'Amore
48195c635efSGarrett D'Amore assert(i);
48295c635efSGarrett D'Amore if (mandoc_eos(buf, (size_t)i, 0))
483*698f87a4SGarrett D'Amore man->last->flags |= MAN_EOS;
48495c635efSGarrett D'Amore
485*698f87a4SGarrett D'Amore return(man_descope(man, line, offs));
48695c635efSGarrett D'Amore }
48795c635efSGarrett D'Amore
48895c635efSGarrett D'Amore static int
man_pmacro(struct man * man,int ln,char * buf,int offs)489*698f87a4SGarrett D'Amore man_pmacro(struct man *man, int ln, char *buf, int offs)
49095c635efSGarrett D'Amore {
49195c635efSGarrett D'Amore int i, ppos;
49295c635efSGarrett D'Amore enum mant tok;
49395c635efSGarrett D'Amore char mac[5];
49495c635efSGarrett D'Amore struct man_node *n;
49595c635efSGarrett D'Amore
49695c635efSGarrett D'Amore if ('"' == buf[offs]) {
497*698f87a4SGarrett D'Amore man_pmsg(man, ln, offs, MANDOCERR_BADCOMMENT);
49895c635efSGarrett D'Amore return(1);
49995c635efSGarrett D'Amore } else if ('\0' == buf[offs])
50095c635efSGarrett D'Amore return(1);
50195c635efSGarrett D'Amore
50295c635efSGarrett D'Amore ppos = offs;
50395c635efSGarrett D'Amore
50495c635efSGarrett D'Amore /*
50595c635efSGarrett D'Amore * Copy the first word into a nil-terminated buffer.
50695c635efSGarrett D'Amore * Stop copying when a tab, space, or eoln is encountered.
50795c635efSGarrett D'Amore */
50895c635efSGarrett D'Amore
50995c635efSGarrett D'Amore i = 0;
51095c635efSGarrett D'Amore while (i < 4 && '\0' != buf[offs] &&
51195c635efSGarrett D'Amore ' ' != buf[offs] && '\t' != buf[offs])
51295c635efSGarrett D'Amore mac[i++] = buf[offs++];
51395c635efSGarrett D'Amore
51495c635efSGarrett D'Amore mac[i] = '\0';
51595c635efSGarrett D'Amore
51695c635efSGarrett D'Amore tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX;
51795c635efSGarrett D'Amore
51895c635efSGarrett D'Amore if (MAN_MAX == tok) {
519*698f87a4SGarrett D'Amore mandoc_vmsg(MANDOCERR_MACRO, man->parse, ln,
52095c635efSGarrett D'Amore ppos, "%s", buf + ppos - 1);
52195c635efSGarrett D'Amore return(1);
52295c635efSGarrett D'Amore }
52395c635efSGarrett D'Amore
52495c635efSGarrett D'Amore /* The macro is sane. Jump to the next word. */
52595c635efSGarrett D'Amore
52695c635efSGarrett D'Amore while (buf[offs] && ' ' == buf[offs])
52795c635efSGarrett D'Amore offs++;
52895c635efSGarrett D'Amore
52995c635efSGarrett D'Amore /*
53095c635efSGarrett D'Amore * Trailing whitespace. Note that tabs are allowed to be passed
53195c635efSGarrett D'Amore * into the parser as "text", so we only warn about spaces here.
53295c635efSGarrett D'Amore */
53395c635efSGarrett D'Amore
53495c635efSGarrett D'Amore if ('\0' == buf[offs] && ' ' == buf[offs - 1])
535*698f87a4SGarrett D'Amore man_pmsg(man, ln, offs - 1, MANDOCERR_EOLNSPACE);
53695c635efSGarrett D'Amore
53795c635efSGarrett D'Amore /*
53895c635efSGarrett D'Amore * Remove prior ELINE macro, as it's being clobbered by a new
53995c635efSGarrett D'Amore * macro. Note that NSCOPED macros do not close out ELINE
54095c635efSGarrett D'Amore * macros---they don't print text---so we let those slip by.
54195c635efSGarrett D'Amore */
54295c635efSGarrett D'Amore
54395c635efSGarrett D'Amore if ( ! (MAN_NSCOPED & man_macros[tok].flags) &&
544*698f87a4SGarrett D'Amore man->flags & MAN_ELINE) {
545*698f87a4SGarrett D'Amore n = man->last;
54695c635efSGarrett D'Amore assert(MAN_TEXT != n->type);
54795c635efSGarrett D'Amore
54895c635efSGarrett D'Amore /* Remove repeated NSCOPED macros causing ELINE. */
54995c635efSGarrett D'Amore
55095c635efSGarrett D'Amore if (MAN_NSCOPED & man_macros[n->tok].flags)
55195c635efSGarrett D'Amore n = n->parent;
55295c635efSGarrett D'Amore
553*698f87a4SGarrett D'Amore mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line,
55495c635efSGarrett D'Amore n->pos, "%s breaks %s", man_macronames[tok],
55595c635efSGarrett D'Amore man_macronames[n->tok]);
55695c635efSGarrett D'Amore
557*698f87a4SGarrett D'Amore man_node_delete(man, n);
558*698f87a4SGarrett D'Amore man->flags &= ~MAN_ELINE;
55995c635efSGarrett D'Amore }
56095c635efSGarrett D'Amore
56195c635efSGarrett D'Amore /*
56295c635efSGarrett D'Amore * Remove prior BLINE macro that is being clobbered.
56395c635efSGarrett D'Amore */
564*698f87a4SGarrett D'Amore if ((man->flags & MAN_BLINE) &&
56595c635efSGarrett D'Amore (MAN_BSCOPE & man_macros[tok].flags)) {
566*698f87a4SGarrett D'Amore n = man->last;
56795c635efSGarrett D'Amore
56895c635efSGarrett D'Amore /* Might be a text node like 8 in
56995c635efSGarrett D'Amore * .TP 8
57095c635efSGarrett D'Amore * .SH foo
57195c635efSGarrett D'Amore */
57295c635efSGarrett D'Amore if (MAN_TEXT == n->type)
57395c635efSGarrett D'Amore n = n->parent;
57495c635efSGarrett D'Amore
57595c635efSGarrett D'Amore /* Remove element that didn't end BLINE, if any. */
57695c635efSGarrett D'Amore if ( ! (MAN_BSCOPE & man_macros[n->tok].flags))
57795c635efSGarrett D'Amore n = n->parent;
57895c635efSGarrett D'Amore
57995c635efSGarrett D'Amore assert(MAN_HEAD == n->type);
58095c635efSGarrett D'Amore n = n->parent;
58195c635efSGarrett D'Amore assert(MAN_BLOCK == n->type);
58295c635efSGarrett D'Amore assert(MAN_SCOPED & man_macros[n->tok].flags);
58395c635efSGarrett D'Amore
584*698f87a4SGarrett D'Amore mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line,
58595c635efSGarrett D'Amore n->pos, "%s breaks %s", man_macronames[tok],
58695c635efSGarrett D'Amore man_macronames[n->tok]);
58795c635efSGarrett D'Amore
588*698f87a4SGarrett D'Amore man_node_delete(man, n);
589*698f87a4SGarrett D'Amore man->flags &= ~MAN_BLINE;
59095c635efSGarrett D'Amore }
59195c635efSGarrett D'Amore
59295c635efSGarrett D'Amore /*
59395c635efSGarrett D'Amore * Save the fact that we're in the next-line for a block. In
59495c635efSGarrett D'Amore * this way, embedded roff instructions can "remember" state
59595c635efSGarrett D'Amore * when they exit.
59695c635efSGarrett D'Amore */
59795c635efSGarrett D'Amore
598*698f87a4SGarrett D'Amore if (MAN_BLINE & man->flags)
599*698f87a4SGarrett D'Amore man->flags |= MAN_BPLINE;
60095c635efSGarrett D'Amore
60195c635efSGarrett D'Amore /* Call to handler... */
60295c635efSGarrett D'Amore
60395c635efSGarrett D'Amore assert(man_macros[tok].fp);
604*698f87a4SGarrett D'Amore if ( ! (*man_macros[tok].fp)(man, tok, ln, ppos, &offs, buf))
60595c635efSGarrett D'Amore goto err;
60695c635efSGarrett D'Amore
60795c635efSGarrett D'Amore /*
60895c635efSGarrett D'Amore * We weren't in a block-line scope when entering the
60995c635efSGarrett D'Amore * above-parsed macro, so return.
61095c635efSGarrett D'Amore */
61195c635efSGarrett D'Amore
612*698f87a4SGarrett D'Amore if ( ! (MAN_BPLINE & man->flags)) {
613*698f87a4SGarrett D'Amore man->flags &= ~MAN_ILINE;
61495c635efSGarrett D'Amore return(1);
61595c635efSGarrett D'Amore }
616*698f87a4SGarrett D'Amore man->flags &= ~MAN_BPLINE;
61795c635efSGarrett D'Amore
61895c635efSGarrett D'Amore /*
61995c635efSGarrett D'Amore * If we're in a block scope, then allow this macro to slip by
62095c635efSGarrett D'Amore * without closing scope around it.
62195c635efSGarrett D'Amore */
62295c635efSGarrett D'Amore
623*698f87a4SGarrett D'Amore if (MAN_ILINE & man->flags) {
624*698f87a4SGarrett D'Amore man->flags &= ~MAN_ILINE;
62595c635efSGarrett D'Amore return(1);
62695c635efSGarrett D'Amore }
62795c635efSGarrett D'Amore
62895c635efSGarrett D'Amore /*
62995c635efSGarrett D'Amore * If we've opened a new next-line element scope, then return
63095c635efSGarrett D'Amore * now, as the next line will close out the block scope.
63195c635efSGarrett D'Amore */
63295c635efSGarrett D'Amore
633*698f87a4SGarrett D'Amore if (MAN_ELINE & man->flags)
63495c635efSGarrett D'Amore return(1);
63595c635efSGarrett D'Amore
63695c635efSGarrett D'Amore /* Close out the block scope opened in the prior line. */
63795c635efSGarrett D'Amore
638*698f87a4SGarrett D'Amore assert(MAN_BLINE & man->flags);
639*698f87a4SGarrett D'Amore man->flags &= ~MAN_BLINE;
64095c635efSGarrett D'Amore
641*698f87a4SGarrett D'Amore if ( ! man_unscope(man, man->last->parent, MANDOCERR_MAX))
64295c635efSGarrett D'Amore return(0);
643*698f87a4SGarrett D'Amore return(man_body_alloc(man, ln, ppos, man->last->tok));
64495c635efSGarrett D'Amore
64595c635efSGarrett D'Amore err: /* Error out. */
64695c635efSGarrett D'Amore
647*698f87a4SGarrett D'Amore man->flags |= MAN_HALT;
64895c635efSGarrett D'Amore return(0);
64995c635efSGarrett D'Amore }
65095c635efSGarrett D'Amore
65195c635efSGarrett D'Amore /*
652*698f87a4SGarrett D'Amore * Unlink a node from its context. If "man" is provided, the last parse
65395c635efSGarrett D'Amore * point will also be adjusted accordingly.
65495c635efSGarrett D'Amore */
65595c635efSGarrett D'Amore static void
man_node_unlink(struct man * man,struct man_node * n)656*698f87a4SGarrett D'Amore man_node_unlink(struct man *man, struct man_node *n)
65795c635efSGarrett D'Amore {
65895c635efSGarrett D'Amore
65995c635efSGarrett D'Amore /* Adjust siblings. */
66095c635efSGarrett D'Amore
66195c635efSGarrett D'Amore if (n->prev)
66295c635efSGarrett D'Amore n->prev->next = n->next;
66395c635efSGarrett D'Amore if (n->next)
66495c635efSGarrett D'Amore n->next->prev = n->prev;
66595c635efSGarrett D'Amore
66695c635efSGarrett D'Amore /* Adjust parent. */
66795c635efSGarrett D'Amore
66895c635efSGarrett D'Amore if (n->parent) {
66995c635efSGarrett D'Amore n->parent->nchild--;
67095c635efSGarrett D'Amore if (n->parent->child == n)
67195c635efSGarrett D'Amore n->parent->child = n->prev ? n->prev : n->next;
67295c635efSGarrett D'Amore }
67395c635efSGarrett D'Amore
67495c635efSGarrett D'Amore /* Adjust parse point, if applicable. */
67595c635efSGarrett D'Amore
676*698f87a4SGarrett D'Amore if (man && man->last == n) {
67795c635efSGarrett D'Amore /*XXX: this can occur when bailing from validation. */
67895c635efSGarrett D'Amore /*assert(NULL == n->next);*/
67995c635efSGarrett D'Amore if (n->prev) {
680*698f87a4SGarrett D'Amore man->last = n->prev;
681*698f87a4SGarrett D'Amore man->next = MAN_NEXT_SIBLING;
68295c635efSGarrett D'Amore } else {
683*698f87a4SGarrett D'Amore man->last = n->parent;
684*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD;
68595c635efSGarrett D'Amore }
68695c635efSGarrett D'Amore }
68795c635efSGarrett D'Amore
688*698f87a4SGarrett D'Amore if (man && man->first == n)
689*698f87a4SGarrett D'Amore man->first = NULL;
69095c635efSGarrett D'Amore }
69195c635efSGarrett D'Amore
69295c635efSGarrett D'Amore const struct mparse *
man_mparse(const struct man * man)693*698f87a4SGarrett D'Amore man_mparse(const struct man *man)
69495c635efSGarrett D'Amore {
69595c635efSGarrett D'Amore
696*698f87a4SGarrett D'Amore assert(man && man->parse);
697*698f87a4SGarrett D'Amore return(man->parse);
69895c635efSGarrett D'Amore }
699