Home | History | Annotate | Line # | Download | only in dist
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