Example #1
0
/* ARGSUSED */
int
blk_close(MACRO_PROT_ARGS)
{
	enum mant	 	 ntok;
	const struct man_node	*nn;

	switch (tok) {
	case (MAN_RE):
		ntok = MAN_RS;
		break;
	case (MAN_UE):
		ntok = MAN_UR;
		break;
	default:
		abort();
		/* NOTREACHED */
	}

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

	if (NULL == nn) {
		man_pmsg(man, line, ppos, MANDOCERR_NOSCOPE);
		if ( ! rew_scope(MAN_BLOCK, man, MAN_PP))
			return(0);
	} else 
		man_unscope(man, nn, MANDOCERR_MAX);

	return(1);
}
Example #2
0
/* ARGSUSED */
int
blk_close(MACRO_PROT_ARGS)
{
	enum mant	 	 ntok;
	const struct man_node	*nn;

	switch (tok) {
	case (MAN_RE):
		ntok = MAN_RS;
		break;
	default:
		abort();
		/* NOTREACHED */
	}

	for (nn = m->last->parent; nn; nn = nn->parent)
		if (ntok == nn->tok)
			break;

	if (NULL == nn)
		man_pmsg(m, line, ppos, MANDOCERR_NOSCOPE);

	if ( ! rew_scope(MAN_BODY, m, ntok))
		return(0);
	if ( ! rew_scope(MAN_BLOCK, m, ntok))
		return(0);

	return(1);
}
Example #3
0
static void
check_text(CHKARGS)
{
	char		*cp, *p;

	if (MAN_LITERAL & man->flags)
		return;

	cp = n->string;
	for (p = cp; NULL != (p = strchr(p, '\t')); p++)
		man_pmsg(man, n->line, (int)(p - cp), MANDOCERR_BADTAB);
}
Example #4
0
static int
man_pmacro(struct man *man, int ln, char *buf, int offs)
{
	int		 i, ppos;
	enum mant	 tok;
	char		 mac[5];
	struct man_node	*n;

	if ('"' == buf[offs]) {
		man_pmsg(man, ln, offs, MANDOCERR_BADCOMMENT);
		return(1);
	} else if ('\0' == buf[offs])
		return(1);

	ppos = offs;

	/*
	 * Copy the first word into a nil-terminated buffer.
	 * Stop copying when a tab, space, or eoln is encountered.
	 */

	i = 0;
	while (i < 4 && '\0' != buf[offs] && 
			' ' != buf[offs] && '\t' != buf[offs])
		mac[i++] = buf[offs++];

	mac[i] = '\0';

	tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX;

	if (MAN_MAX == tok) {
		mandoc_vmsg(MANDOCERR_MACRO, man->parse, ln, 
				ppos, "%s", buf + ppos - 1);
		return(1);
	}

	/* The macro is sane.  Jump to the next word. */

	while (buf[offs] && ' ' == buf[offs])
		offs++;

	/* 
	 * Trailing whitespace.  Note that tabs are allowed to be passed
	 * into the parser as "text", so we only warn about spaces here.
	 */

	if ('\0' == buf[offs] && ' ' == buf[offs - 1])
		man_pmsg(man, ln, offs - 1, MANDOCERR_EOLNSPACE);

	/* 
	 * Remove prior ELINE macro, as it's being clobbered by a new
	 * macro.  Note that NSCOPED macros do not close out ELINE
	 * macros---they don't print text---so we let those slip by.
	 */

	if ( ! (MAN_NSCOPED & man_macros[tok].flags) &&
			man->flags & MAN_ELINE) {
		n = man->last;
		assert(MAN_TEXT != n->type);

		/* Remove repeated NSCOPED macros causing ELINE. */

		if (MAN_NSCOPED & man_macros[n->tok].flags)
			n = n->parent;

		mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line, 
		    n->pos, "%s breaks %s", man_macronames[tok],
		    man_macronames[n->tok]);

		man_node_delete(man, n);
		man->flags &= ~MAN_ELINE;
	}

	/*
	 * Remove prior BLINE macro that is being clobbered.
	 */
	if ((man->flags & MAN_BLINE) &&
	    (MAN_BSCOPE & man_macros[tok].flags)) {
		n = man->last;

		/* Might be a text node like 8 in
		 * .TP 8
		 * .SH foo
		 */
		if (MAN_TEXT == n->type)
			n = n->parent;

		/* Remove element that didn't end BLINE, if any. */
		if ( ! (MAN_BSCOPE & man_macros[n->tok].flags))
			n = n->parent;

		assert(MAN_HEAD == n->type);
		n = n->parent;
		assert(MAN_BLOCK == n->type);
		assert(MAN_SCOPED & man_macros[n->tok].flags);

		mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line, 
		    n->pos, "%s breaks %s", man_macronames[tok],
		    man_macronames[n->tok]);

		man_node_delete(man, n);
		man->flags &= ~MAN_BLINE;
	}

	/*
	 * Save the fact that we're in the next-line for a block.  In
	 * this way, embedded roff instructions can "remember" state
	 * when they exit.
	 */

	if (MAN_BLINE & man->flags)
		man->flags |= MAN_BPLINE;

	/* Call to handler... */

	assert(man_macros[tok].fp);
	if ( ! (*man_macros[tok].fp)(man, tok, ln, ppos, &offs, buf))
		goto err;

	/* 
	 * We weren't in a block-line scope when entering the
	 * above-parsed macro, so return.
	 */

	if ( ! (MAN_BPLINE & man->flags)) {
		man->flags &= ~MAN_ILINE; 
		return(1);
	}
	man->flags &= ~MAN_BPLINE;

	/*
	 * If we're in a block scope, then allow this macro to slip by
	 * without closing scope around it.
	 */

	if (MAN_ILINE & man->flags) {
		man->flags &= ~MAN_ILINE;
		return(1);
	}

	/* 
	 * If we've opened a new next-line element scope, then return
	 * now, as the next line will close out the block scope.
	 */

	if (MAN_ELINE & man->flags)
		return(1);

	/* Close out the block scope opened in the prior line.  */

	assert(MAN_BLINE & man->flags);
	man->flags &= ~MAN_BLINE;

	if ( ! man_unscope(man, man->last->parent, MANDOCERR_MAX))
		return(0);
	return(man_body_alloc(man, ln, ppos, man->last->tok));

err:	/* Error out. */

	man->flags |= MAN_HALT;
	return(0);
}
Example #5
0
static int
man_ptext(struct man *man, int line, char *buf, int offs)
{
	int		 i;

	/* Literal free-form text whitespace is preserved. */

	if (MAN_LITERAL & man->flags) {
		if ( ! man_word_alloc(man, line, offs, buf + offs))
			return(0);
		return(man_descope(man, line, offs));
	}

	for (i = offs; ' ' == buf[i]; i++)
		/* Skip leading whitespace. */ ;

	/*
	 * Blank lines are ignored right after headings
	 * but add a single vertical space elsewhere.
	 */

	if ('\0' == buf[i]) {
		/* Allocate a blank entry. */
		if (MAN_SH != man->last->tok &&
		    MAN_SS != man->last->tok) {
			if ( ! man_elem_alloc(man, line, offs, MAN_sp))
				return(0);
			man->next = MAN_NEXT_SIBLING;
		}
		return(1);
	}

	/* 
	 * Warn if the last un-escaped character is whitespace. Then
	 * strip away the remaining spaces (tabs stay!).   
	 */

	i = (int)strlen(buf);
	assert(i);

	if (' ' == buf[i - 1] || '\t' == buf[i - 1]) {
		if (i > 1 && '\\' != buf[i - 2])
			man_pmsg(man, line, i - 1, MANDOCERR_EOLNSPACE);

		for (--i; i && ' ' == buf[i]; i--)
			/* Spin back to non-space. */ ;

		/* Jump ahead of escaped whitespace. */
		i += '\\' == buf[i] ? 2 : 1;

		buf[i] = '\0';
	}

	if ( ! man_word_alloc(man, line, offs, buf + offs))
		return(0);

	/*
	 * End-of-sentence check.  If the last character is an unescaped
	 * EOS character, then flag the node as being the end of a
	 * sentence.  The front-end will know how to interpret this.
	 */

	assert(i);
	if (mandoc_eos(buf, (size_t)i, 0))
		man->last->flags |= MAN_EOS;

	return(man_descope(man, line, offs));
}
Example #6
0
static int
man_ptext(struct man *m, int line, char *buf, int offs)
{
	int		 i;

	/* Literal free-form text whitespace is preserved. */

	if (MAN_LITERAL & m->flags) {
		if ( ! man_word_alloc(m, line, offs, buf + offs))
			return(0);
		return(man_descope(m, line, offs));
	}

	/* Pump blank lines directly into the backend. */

	for (i = offs; ' ' == buf[i]; i++)
		/* Skip leading whitespace. */ ;

	if ('\0' == buf[i]) {
		/* Allocate a blank entry. */
		if ( ! man_word_alloc(m, line, offs, ""))
			return(0);
		return(man_descope(m, line, offs));
	}

	/* 
	 * Warn if the last un-escaped character is whitespace. Then
	 * strip away the remaining spaces (tabs stay!).   
	 */

	i = (int)strlen(buf);
	assert(i);

	if (' ' == buf[i - 1] || '\t' == buf[i - 1]) {
		if (i > 1 && '\\' != buf[i - 2])
			man_pmsg(m, line, i - 1, MANDOCERR_EOLNSPACE);

		for (--i; i && ' ' == buf[i]; i--)
			/* Spin back to non-space. */ ;

		/* Jump ahead of escaped whitespace. */
		i += '\\' == buf[i] ? 2 : 1;

		buf[i] = '\0';
	}

	if ( ! man_word_alloc(m, line, offs, buf + offs))
		return(0);

	/*
	 * End-of-sentence check.  If the last character is an unescaped
	 * EOS character, then flag the node as being the end of a
	 * sentence.  The front-end will know how to interpret this.
	 */

	assert(i);
	if (mandoc_eos(buf, (size_t)i, 0))
		m->last->flags |= MAN_EOS;

	return(man_descope(m, line, offs));
}