Example #1
0
static void
post_SH(CHKARGS)
{
	struct roff_node	*nc;

	if (n->type != ROFFT_BODY || (nc = n->child) == NULL)
		return;

	if (nc->tok == MAN_PP && nc->body->child != NULL) {
		while (nc->body->last != NULL) {
			man->next = ROFF_NEXT_CHILD;
			roff_node_relink(man, nc->body->last);
			man->last = n;
		}
	}

	if (nc->tok == MAN_PP || nc->tok == ROFF_sp || nc->tok == ROFF_br) {
		mandoc_msg(MANDOCERR_PAR_SKIP, nc->line, nc->pos,
		    "%s after %s", roff_name[nc->tok], roff_name[n->tok]);
		roff_node_delete(man, nc);
	}

	/*
	 * Trailing PP is empty, so it is deleted by check_par().
	 * Trailing sp is significant.
	 */

	if ((nc = n->last) != NULL && nc->tok == ROFF_br) {
		mandoc_msg(MANDOCERR_PAR_SKIP,
		    nc->line, nc->pos, "%s at the end of %s",
		    roff_name[nc->tok], roff_name[n->tok]);
		roff_node_delete(man, nc);
	}
}
Example #2
0
static void
roff_valid_br(ROFF_VALID_ARGS)
{
	struct roff_node	*np;

	if (n->next != NULL && n->next->type == ROFFT_TEXT &&
	    *n->next->string == ' ') {
		mandoc_msg(MANDOCERR_PAR_SKIP, n->line, n->pos,
		    "br before text line with leading blank");
		roff_node_delete(man, n);
		return;
	}

	if ((np = n->prev) == NULL)
		return;

	switch (np->tok) {
	case ROFF_br:
	case ROFF_sp:
	case MDOC_Pp:
		mandoc_msg(MANDOCERR_PAR_SKIP,
		    n->line, n->pos, "br after %s", roff_name[np->tok]);
		roff_node_delete(man, n);
		break;
	default:
		break;
	}
}
Example #3
0
static void
check_root(CHKARGS)
{

	assert((man->flags & (MAN_BLINE | MAN_ELINE)) == 0);

	if (NULL == man->first->child)
		mandoc_msg(MANDOCERR_DOC_EMPTY, man->parse,
		    n->line, n->pos, NULL);
	else
		man->meta.hasbody = 1;

	if (NULL == man->meta.title) {
		mandoc_msg(MANDOCERR_TH_NOTITLE, man->parse,
		    n->line, n->pos, NULL);

		/*
		 * If a title hasn't been set, do so now (by
		 * implication, date and section also aren't set).
		 */

		man->meta.title = mandoc_strdup("");
		man->meta.msec = mandoc_strdup("");
		man->meta.date = man->quick ? mandoc_strdup("") :
		    mandoc_normdate(man->parse, NULL, n->line, n->pos);
	}
}
Example #4
0
void
man_state(struct roff_man *man, struct roff_node *n)
{

	switch(n->tok) {
	case MAN_nf:
	case MAN_EX:
		if (man->flags & MAN_LITERAL && ! (n->flags & NODE_VALID))
			mandoc_msg(MANDOCERR_NF_SKIP, man->parse,
			    n->line, n->pos, "nf");
		man->flags |= MAN_LITERAL;
		break;
	case MAN_fi:
	case MAN_EE:
		if ( ! (man->flags & MAN_LITERAL) &&
		     ! (n->flags & NODE_VALID))
			mandoc_msg(MANDOCERR_FI_SKIP, man->parse,
			    n->line, n->pos, "fi");
		man->flags &= ~MAN_LITERAL;
		break;
	default:
		break;
	}
	man->last->flags |= NODE_VALID;
}
Example #5
0
static void
check_par(CHKARGS)
{

	switch (n->type) {
	case ROFFT_BLOCK:
		if (n->body->child == NULL)
			roff_node_delete(man, n);
		break;
	case ROFFT_BODY:
		if (n->child != NULL &&
		    (n->child->tok == ROFF_sp || n->child->tok == ROFF_br)) {
			mandoc_msg(MANDOCERR_PAR_SKIP,
			    n->child->line, n->child->pos,
			    "%s after %s", roff_name[n->child->tok],
			    roff_name[n->tok]);
			roff_node_delete(man, n->child);
		}
		if (n->child == NULL)
			mandoc_msg(MANDOCERR_PAR_SKIP, n->line, n->pos,
			    "%s empty", roff_name[n->tok]);
		break;
	case ROFFT_HEAD:
		if (n->child != NULL)
			mandoc_msg(MANDOCERR_ARG_SKIP,
			    n->line, n->pos, "%s %s%s",
			    roff_name[n->tok], n->child->string,
			    n->child->next != NULL ? " ..." : "");
		break;
	default:
		break;
	}
}
Example #6
0
static void
check_root(CHKARGS)
{
	assert((man->flags & (MAN_BLINE | MAN_ELINE)) == 0);

	if (n->last == NULL || n->last->type == ROFFT_COMMENT)
		mandoc_msg(MANDOCERR_DOC_EMPTY, n->line, n->pos, NULL);
	else
		man->meta.hasbody = 1;

	if (NULL == man->meta.title) {
		mandoc_msg(MANDOCERR_TH_NOTITLE, n->line, n->pos, NULL);

		/*
		 * If a title hasn't been set, do so now (by
		 * implication, date and section also aren't set).
		 */

		man->meta.title = mandoc_strdup("");
		man->meta.msec = mandoc_strdup("");
		man->meta.date = man->quick ? mandoc_strdup("") :
		    mandoc_normdate(man, NULL, n->line, n->pos);
	}

	if (man->meta.os_e &&
	    (man->meta.rcsids & (1 << man->meta.os_e)) == 0)
		mandoc_msg(MANDOCERR_RCS_MISSING, 0, 0,
		    man->meta.os_e == MANDOC_OS_OPENBSD ?
		    "(OpenBSD)" : "(NetBSD)");
}
Example #7
0
/* ARGSUSED */
static enum rofferr
roff_ccond(ROFF_ARGS)
{

	if (NULL == r->last) {
		mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
		return(ROFF_IGN);
	}

	switch (r->last->tok) {
	case (ROFF_el):
		/* FALLTHROUGH */
	case (ROFF_ie):
		/* FALLTHROUGH */
	case (ROFF_if):
		break;
	default:
		mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
		return(ROFF_IGN);
	}

	if (r->last->endspan > -1) {
		mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
		return(ROFF_IGN);
	}

	if ((*bufp)[pos])
		mandoc_msg(MANDOCERR_ARGSLOST, r->parse, ln, pos, NULL);

	roffnode_pop(r);
	roffnode_cleanscope(r);
	return(ROFF_IGN);
}
Example #8
0
static void
cell(struct tbl_node *tbl, struct tbl_row *rp,
		int ln, const char *p, int *pos)
{
	int		 i;
	enum tbl_cellt	 c;

	/* Handle leading vertical lines */

	while (p[*pos] == ' ' || p[*pos] == '\t' || p[*pos] == '|') {
		if (p[*pos] == '|') {
			if (rp->vert < 2)
				rp->vert++;
			else
				mandoc_msg(MANDOCERR_TBLLAYOUT_VERT,
				    tbl->parse, ln, *pos, NULL);
		}
		(*pos)++;
	}

again:
	while (p[*pos] == ' ' || p[*pos] == '\t')
		(*pos)++;

	if (p[*pos] == '.' || p[*pos] == '\0')
		return;

	/* Parse the column position (`c', `l', `r', ...). */

	for (i = 0; i < KEYS_MAX; i++)
		if (tolower((unsigned char)p[*pos]) == keys[i].name)
			break;

	if (i == KEYS_MAX) {
		mandoc_vmsg(MANDOCERR_TBLLAYOUT_CHAR, tbl->parse,
		    ln, *pos, "%c", p[*pos]);
		(*pos)++;
		goto again;
	}
	c = keys[i].key;

	/* Special cases of spanners. */

	if (c == TBL_CELL_SPAN) {
		if (rp->last == NULL)
			mandoc_msg(MANDOCERR_TBLLAYOUT_SPAN,
			    tbl->parse, ln, *pos, NULL);
		else if (rp->last->pos == TBL_CELL_HORIZ ||
		    rp->last->pos == TBL_CELL_DHORIZ)
			c = rp->last->pos;
	} else if (c == TBL_CELL_DOWN && rp == tbl->first_row)
		mandoc_msg(MANDOCERR_TBLLAYOUT_DOWN,
		    tbl->parse, ln, *pos, NULL);

	(*pos)++;

	/* Allocate cell then parse its modifiers. */

	mods(tbl, cell_alloc(tbl, rp, c), ln, p, pos);
}
Example #9
0
static void
post_OP(CHKARGS)
{

	if (n->child == NULL)
		mandoc_msg(MANDOCERR_OP_EMPTY, n->line, n->pos, "OP");
	else if (n->child->next != NULL && n->child->next->next != NULL) {
		n = n->child->next->next;
		mandoc_msg(MANDOCERR_ARG_EXCESS,
		    n->line, n->pos, "OP ... %s", n->string);
	}
}
Example #10
0
void
tbl_restart(int line, int pos, struct tbl_node *tbl)
{
	if (TBL_PART_CDATA == tbl->part)
		mandoc_msg(MANDOCERR_TBLBLOCK, tbl->parse, 
				tbl->line, tbl->pos, NULL);

	tbl->part = TBL_PART_LAYOUT;
	tbl->line = line;
	tbl->pos = pos;

	if (NULL == tbl->first_span || NULL == tbl->first_span->first)
		mandoc_msg(MANDOCERR_TBLNODATA, tbl->parse,
				tbl->line, tbl->pos, NULL);
}
Example #11
0
void
tbl_end(struct tbl_node *tbl)
{

	if (NULL == tbl->first_span || NULL == tbl->first_span->first)
		mandoc_msg(MANDOCERR_TBLNODATA, tbl->parse, 
				tbl->line, tbl->pos, NULL);

	if (tbl->last_span)
		tbl->last_span->flags |= TBL_SPAN_LAST;

	if (TBL_PART_CDATA == tbl->part)
		mandoc_msg(MANDOCERR_TBLBLOCK, tbl->parse, 
				tbl->line, tbl->pos, NULL);
}
Example #12
0
/*
 * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs.
 * They're unusual because they're basically free-form text until a
 * macro is encountered.
 */
static void
phrase_ta(MACRO_PROT_ARGS)
{
	struct roff_node *body, *n;

	/* Make sure we are in a column list or ignore this macro. */

	body = NULL;
	for (n = mdoc->last; n != NULL; n = n->parent) {
		if (n->flags & MDOC_ENDED)
			continue;
		if (n->tok == MDOC_It && n->type == ROFFT_BODY)
			body = n;
		if (n->tok == MDOC_Bl)
			break;
	}

	if (n == NULL || n->norm->Bl.type != LIST_column) {
		mandoc_msg(MANDOCERR_TA_STRAY, mdoc->parse,
		    line, ppos, "Ta");
		return;
	}

	/* Advance to the next column. */

	rew_last(mdoc, body);
	roff_body_alloc(mdoc, line, ppos, MDOC_It);
	parse_rest(mdoc, TOKEN_NONE, line, pos, buf);
}
Example #13
0
static void
mparse_end(struct mparse *curp)
{

	if (MANDOCLEVEL_FATAL <= curp->file_status)
		return;

	if (curp->mdoc && ! mdoc_endparse(curp->mdoc)) {
		assert(MANDOCLEVEL_FATAL <= curp->file_status);
		return;
	}

	if (curp->man && ! man_endparse(curp->man)) {
		assert(MANDOCLEVEL_FATAL <= curp->file_status);
		return;
	}

	if ( ! (curp->man || curp->mdoc)) {
		mandoc_msg(MANDOCERR_NOTMANUAL, curp, 1, 0, NULL);
		curp->file_status = MANDOCLEVEL_FATAL;
		return;
	}

	roff_endparse(curp->roff);
}
Example #14
0
int
mparse_open(struct mparse *curp, const char *file)
{
	char		 *cp;
	int		  fd;

	curp->file = file;
	cp = strrchr(file, '.');
	curp->gzip = (cp != NULL && ! strcmp(cp + 1, "gz"));

	/* First try to use the filename as it is. */

	if ((fd = open(file, O_RDONLY)) != -1)
		return fd;

	/*
	 * If that doesn't work and the filename doesn't
	 * already  end in .gz, try appending .gz.
	 */

	if ( ! curp->gzip) {
		mandoc_asprintf(&cp, "%s.gz", file);
		fd = open(cp, O_RDONLY);
		free(cp);
		if (fd != -1) {
			curp->gzip = 1;
			return fd;
		}
	}

	/* Neither worked, give up. */

	mandoc_msg(MANDOCERR_FILE, curp, 0, 0, strerror(errno));
	return -1;
}
Example #15
0
static void
in_line_eoln(MACRO_PROT_ARGS)
{
	struct roff_node	*n;
	struct mdoc_arg		*arg;

	if ((tok == MDOC_Pp || tok == MDOC_Lp) &&
	    ! (mdoc->flags & MDOC_SYNOPSIS)) {
		n = mdoc->last;
		if (mdoc->next == ROFF_NEXT_SIBLING)
			n = n->parent;
		if (n->tok == MDOC_Nm)
			rew_last(mdoc, n->parent);
	}

	if (buf[*pos] == '\0' &&
	    (tok == MDOC_Fd || mdoc_macronames[tok][0] == '%')) {
		mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
		    line, ppos, mdoc_macronames[tok]);
		return;
	}

	mdoc_argv(mdoc, line, tok, &arg, pos, buf);
	mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
	if (parse_rest(mdoc, tok, line, pos, buf))
		return;
	rew_elem(mdoc, tok);
}
Example #16
0
static char *
roff_getname(struct roff *r, char **cpp, int ln, int pos)
{
	char	 *name, *cp;

	name = *cpp;
	if ('\0' == *name)
		return(name);

	/* Read until end of name. */
	for (cp = name; '\0' != *cp && ' ' != *cp; cp++) {
		if ('\\' != *cp)
			continue;
		cp++;
		if ('\\' == *cp)
			continue;
		mandoc_msg(MANDOCERR_NAMESC, r->parse, ln, pos, NULL);
		*cp = '\0';
		name = cp;
	}

	/* Nil-terminate name. */
	if ('\0' != *cp)
		*(cp++) = '\0';

	/* Read past spaces. */
	while (' ' == *cp)
		cp++;

	*cpp = cp;
	return(name);
}
Example #17
0
/* ARGSUSED */
static enum rofferr
roff_EN(ROFF_ARGS)
{

	mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
	return(ROFF_IGN);
}
Example #18
0
void
man_unscope(struct roff_man *man, const struct roff_node *to)
{
	struct roff_node *n;

	to = to->parent;
	n = man->last;
	while (n != to) {

		/* Reached the end of the document? */

		if (to == NULL && ! (n->flags & MAN_VALID)) {
			if (man->flags & (MAN_BLINE | MAN_ELINE) &&
			    man_macros[n->tok].flags & MAN_SCOPED) {
				mandoc_vmsg(MANDOCERR_BLK_LINE,
				    man->parse, n->line, n->pos,
				    "EOF breaks %s",
				    man_macronames[n->tok]);
				if (man->flags & MAN_ELINE)
					man->flags &= ~MAN_ELINE;
				else {
					assert(n->type == ROFFT_HEAD);
					n = n->parent;
					man->flags &= ~MAN_BLINE;
				}
				man->last = n;
				n = n->parent;
				roff_node_delete(man, man->last);
				continue;
			}
			if (n->type == ROFFT_BLOCK &&
			    man_macros[n->tok].fp == blk_exp)
				mandoc_msg(MANDOCERR_BLK_NOEND,
				    man->parse, n->line, n->pos,
				    man_macronames[n->tok]);
		}

		/*
		 * We might delete the man->last node
		 * in the post-validation phase.
		 * Save a pointer to the parent such that
		 * we know where to continue the iteration.
		 */

		man->last = n;
		n = n->parent;
		man->last->flags |= MAN_VALID;
	}

	/*
	 * If we ended up at the parent of the node we were
	 * supposed to rewind to, that means the target node
	 * got deleted, so add the next node we parse as a child
	 * of the parent instead of as a sibling of the target.
	 */

	man->next = (man->last == to) ?
	    ROFF_NEXT_CHILD : ROFF_NEXT_SIBLING;
}
Example #19
0
/*
 * Close out a generic explicit macro.
 */
void
blk_close(MACRO_PROT_ARGS)
{
	int			 ntok;
	const struct roff_node	*nn;
	char			*p;
	int			 nrew, target;

	nrew = 1;
	switch (tok) {
	case MAN_RE:
		ntok = MAN_RS;
		if ( ! man_args(man, line, pos, buf, &p))
			break;
		for (nn = man->last->parent; nn; nn = nn->parent)
			if (nn->tok == ntok && nn->type == ROFFT_BLOCK)
				nrew++;
		target = strtol(p, &p, 10);
		if (*p != '\0')
			mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse,
			    line, p - buf, "RE ... %s", p);
		if (target == 0)
			target = 1;
		nrew -= target;
		if (nrew < 1) {
			mandoc_vmsg(MANDOCERR_RE_NOTOPEN, man->parse,
			    line, ppos, "RE %d", target);
			return;
		}
		break;
	case MAN_UE:
		ntok = MAN_UR;
		break;
	default:
		abort();
	}

	for (nn = man->last->parent; nn; nn = nn->parent)
		if (nn->tok == ntok && nn->type == ROFFT_BLOCK && ! --nrew)
			break;

	if (nn == NULL) {
		mandoc_msg(MANDOCERR_BLK_NOTOPEN, man->parse,
		    line, ppos, man_macronames[tok]);
		rew_scope(man, MAN_PP);
	} else {
		line = man->last->line;
		ppos = man->last->pos;
		ntok = man->last->tok;
		man_unscope(man, nn);

		/* Move a trailing paragraph behind the block. */

		if (ntok == MAN_LP || ntok == MAN_PP || ntok == MAN_P) {
			*pos = strlen(buf);
			blk_imp(man, ntok, line, ppos, pos, buf);
		}
	}
}
Example #20
0
static void
post_UR(CHKARGS)
{
	if (n->type == ROFFT_HEAD && n->child == NULL)
		mandoc_msg(MANDOCERR_UR_NOHEAD, n->line, n->pos,
		    "%s", roff_name[n->tok]);
	check_part(man, n);
}
Example #21
0
static void
check_part(CHKARGS)
{

	if (n->type == MAN_BODY && n->child == NULL)
		mandoc_msg(MANDOCERR_BLK_EMPTY, man->parse,
		    n->line, n->pos, man_macronames[n->tok]);
}
Example #22
0
static void
check_part(CHKARGS)
{

	if (n->type == ROFFT_BODY && n->child == NULL)
		mandoc_msg(MANDOCERR_BLK_EMPTY, n->line, n->pos,
		    "%s", roff_name[n->tok]);
}
Example #23
0
/* ARGSUSED */
static enum rofferr
roff_line_ignore(ROFF_ARGS)
{

	if (ROFF_it == tok)
		mandoc_msg(MANDOCERR_REQUEST, r->parse, ln, ppos, "it");

	return(ROFF_IGN);
}
Example #24
0
static void
post_fi(CHKARGS)
{

	if ( ! (MAN_LITERAL & man->flags))
		mandoc_msg(MANDOCERR_FI_SKIP, man->parse,
		    n->line, n->pos, "fi");

	man->flags &= ~MAN_LITERAL;
}
Example #25
0
static void
post_nf(CHKARGS)
{

	if (man->flags & MAN_LITERAL)
		mandoc_msg(MANDOCERR_NF_SKIP, man->parse,
		    n->line, n->pos, "nf");

	man->flags |= MAN_LITERAL;
}
Example #26
0
static int
check_part(CHKARGS)
{

	if (MAN_BODY == n->type && 0 == n->nchild)
		mandoc_msg(MANDOCERR_ARGCWARN, man->parse, n->line, 
				n->pos, "want children (have none)");

	return(1);
}
Example #27
0
void
roff_endparse(struct roff *r)
{

	if (r->last)
		mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse,
				r->last->line, r->last->col, NULL);

	if (r->eqn) {
		mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse, 
				r->eqn->eqn.ln, r->eqn->eqn.pos, NULL);
		eqn_end(&r->eqn);
	}

	if (r->tbl) {
		mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse, 
				r->tbl->line, r->tbl->pos, NULL);
		tbl_end(&r->tbl);
	}
}
Example #28
0
char *
mandoc_normdate(struct mparse *parse, char *in, int ln, int pos)
{
	char		*out;
	time_t		 t;

	if (NULL == in || '\0' == *in ||
	    0 == strcmp(in, "$" "Mdocdate$")) {
		mandoc_msg(MANDOCERR_NODATE, parse, ln, pos, NULL);
		time(&t);
	}
	else if (!a2time(&t, "$" "Mdocdate: %b %d %Y $", in) &&
	    !a2time(&t, "%b %d, %Y", in) &&
	    !a2time(&t, "%Y-%m-%d", in)) {
		mandoc_msg(MANDOCERR_BADDATE, parse, ln, pos, NULL);
		t = 0;
	}
	out = t ? time2a(t) : NULL;
	return(out ? out : mandoc_strdup(in));
}
Example #29
0
/* ARGSUSED */
static enum rofferr
roff_T_(ROFF_ARGS)
{

	if (NULL == r->tbl)
		mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
	else
		tbl_restart(ppos, ln, r->tbl);

	return(ROFF_IGN);
}
Example #30
0
/* ARGSUSED */
static enum rofferr
roff_cblock(ROFF_ARGS)
{

	/*
	 * A block-close `..' should only be invoked as a child of an
	 * ignore macro, otherwise raise a warning and just ignore it.
	 */

	if (NULL == r->last) {
		mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
		return(ROFF_IGN);
	}

	switch (r->last->tok) {
	case (ROFF_am):
		/* FALLTHROUGH */
	case (ROFF_ami):
		/* FALLTHROUGH */
	case (ROFF_am1):
		/* FALLTHROUGH */
	case (ROFF_de):
		/* ROFF_de1 is remapped to ROFF_de in roff_block(). */
		/* FALLTHROUGH */
	case (ROFF_dei):
		/* FALLTHROUGH */
	case (ROFF_ig):
		break;
	default:
		mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
		return(ROFF_IGN);
	}

	if ((*bufp)[pos])
		mandoc_msg(MANDOCERR_ARGSLOST, r->parse, ln, pos, NULL);

	roffnode_pop(r);
	roffnode_cleanscope(r);
	return(ROFF_IGN);

}