示例#1
0
/*
 * Close out block partial/full explicit.  
 */
static int
blk_exp_close(MACRO_PROT_ARGS)
{
	struct mdoc_node *body;		/* Our own body. */
	struct mdoc_node *later;	/* A sub-block starting later. */
	struct mdoc_node *n;		/* For searching backwards. */

	int	 	 j, lastarg, maxargs, flushed, nl;
	enum margserr	 ac;
	enum mdoct	 atok, ntok;
	char		*p;

	nl = MDOC_NEWLINE & m->flags;

	switch (tok) {
	case (MDOC_Ec):
		maxargs = 1;
		break;
	default:
		maxargs = 0;
		break;
	}

	/*
	 * Search backwards for beginnings of blocks,
	 * both of our own and of pending sub-blocks.
	 */
	atok = rew_alt(tok);
	body = later = NULL;
	for (n = m->last; n; n = n->parent) {
		if (MDOC_VALID & n->flags)
			continue;

		/* Remember the start of our own body. */
		if (MDOC_BODY == n->type && atok == n->tok) {
			if (ENDBODY_NOT == n->end)
				body = n;
			continue;
		}

		if (MDOC_BLOCK != n->type || MDOC_Nm == n->tok)
			continue;
		if (atok == n->tok) {
			assert(body);

			/*
			 * Found the start of our own block.
			 * When there is no pending sub block,
			 * just proceed to closing out.
			 */
			if (NULL == later)
				break;

			/* 
			 * When there is a pending sub block,
			 * postpone closing out the current block
			 * until the rew_sub() closing out the sub-block.
			 */
			make_pending(later, tok, m, line, ppos);

			/*
			 * Mark the place where the formatting - but not
			 * the scope - of the current block ends.
			 */
			if ( ! mdoc_endbody_alloc(m, line, ppos,
			    atok, body, ENDBODY_SPACE))
				return(0);
			break;
		}

		/*
		 * When finding an open sub block, remember the last
		 * open explicit block, or, in case there are only
		 * implicit ones, the first open implicit block.
		 */
		if (later &&
		    MDOC_EXPLICIT & mdoc_macros[later->tok].flags)
			continue;
		if (MDOC_CALLABLE & mdoc_macros[n->tok].flags)
			later = n;
	}

	if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
		/* FIXME: do this in validate */
		if (buf[*pos]) 
			mdoc_pmsg(m, line, ppos, MANDOCERR_ARGSLOST);

		if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
			return(0);
		return(rew_sub(MDOC_BLOCK, m, tok, line, ppos));
	}

	if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
		return(0);

	if (NULL == later && maxargs > 0) 
		if ( ! mdoc_tail_alloc(m, line, ppos, rew_alt(tok)))
			return(0);

	for (flushed = j = 0; ; j++) {
		lastarg = *pos;

		if (j == maxargs && ! flushed) {
			if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
				return(0);
			flushed = 1;
		}

		ac = mdoc_args(m, line, pos, buf, tok, &p);

		if (ARGS_ERROR == ac)
			return(0);
		if (ARGS_PUNCT == ac)
			break;
		if (ARGS_EOLN == ac)
			break;

		ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);

		if (MDOC_MAX == ntok) {
			if ( ! dword(m, line, lastarg, p, DELIM_MAX))
				return(0);
			continue;
		}

		if ( ! flushed) {
			if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
				return(0);
			flushed = 1;
		}
		if ( ! mdoc_macro(m, ntok, line, lastarg, pos, buf))
			return(0);
		break;
	}

	if ( ! flushed && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
		return(0);

	if ( ! nl)
		return(1);
	return(append_delims(m, line, pos, buf));
}
示例#2
0
/*
 * Close out block partial/full explicit.
 */
static void
blk_exp_close(MACRO_PROT_ARGS)
{
	struct roff_node *body;		/* Our own body. */
	struct roff_node *endbody;	/* Our own end marker. */
	struct roff_node *itblk;	/* An It block starting later. */
	struct roff_node *later;	/* A sub-block starting later. */
	struct roff_node *n;		/* Search back to our block. */
	struct roff_node *target;	/* For find_pending(). */

	int		 j, lastarg, maxargs, nl, pending;
	enum margserr	 ac;
	int		 atok, ntok;
	char		*p;

	nl = MDOC_NEWLINE & mdoc->flags;

	switch (tok) {
	case MDOC_Ec:
		maxargs = 1;
		break;
	case MDOC_Ek:
		mdoc->flags &= ~MDOC_KEEP;
		/* FALLTHROUGH */
	default:
		maxargs = 0;
		break;
	}

	/*
	 * Search backwards for beginnings of blocks,
	 * both of our own and of pending sub-blocks.
	 */

	atok = rew_alt(tok);
	body = endbody = itblk = later = NULL;
	for (n = mdoc->last; n; n = n->parent) {
		if (n->flags & MDOC_ENDED) {
			if ( ! (n->flags & MDOC_VALID))
				n->flags |= MDOC_BROKEN;
			continue;
		}

		/* Remember the start of our own body. */

		if (n->type == ROFFT_BODY && atok == n->tok) {
			if (n->end == ENDBODY_NOT)
				body = n;
			continue;
		}

		if (n->type != ROFFT_BLOCK || n->tok == MDOC_Nm)
			continue;

		if (n->tok == MDOC_It) {
			itblk = n;
			continue;
		}

		if (atok == n->tok) {
			assert(body);

			/*
			 * Found the start of our own block.
			 * When there is no pending sub block,
			 * just proceed to closing out.
			 */

			if (later == NULL ||
			    (tok == MDOC_El && itblk == NULL))
				break;

			/*
			 * When there is a pending sub block, postpone
			 * closing out the current block until the
			 * rew_pending() closing out the sub-block.
			 * Mark the place where the formatting - but not
			 * the scope - of the current block ends.
			 */

			mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse,
			    line, ppos, "%s breaks %s",
			    mdoc_macronames[atok],
			    mdoc_macronames[later->tok]);

			endbody = mdoc_endbody_alloc(mdoc, line, ppos,
			    atok, body, ENDBODY_SPACE);

			if (tok == MDOC_El)
				itblk->flags |= MDOC_ENDED | MDOC_BROKEN;

			/*
			 * If a block closing macro taking arguments
			 * breaks another block, put the arguments
			 * into the end marker.
			 */

			if (maxargs)
				mdoc->next = ROFF_NEXT_CHILD;
			break;
		}

		/* Explicit blocks close out description lines. */

		if (n->tok == MDOC_Nd) {
			rew_last(mdoc, n);
			continue;
		}

		/* Breaking an open sub block. */

		n->flags |= MDOC_BROKEN;
		if (later == NULL)
			later = n;
	}

	if (body == NULL) {
		mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse,
		    line, ppos, mdoc_macronames[tok]);
		if (later != NULL)
			later->flags &= ~MDOC_BROKEN;
		if (maxargs && endbody == NULL) {
			/*
			 * Stray .Ec without previous .Eo:
			 * Break the output line, keep the arguments.
			 */
			roff_elem_alloc(mdoc, line, ppos, MDOC_br);
			rew_elem(mdoc, MDOC_br);
		}
	} else if (endbody == NULL) {
		rew_last(mdoc, body);
		if (maxargs)
			mdoc_tail_alloc(mdoc, line, ppos, atok);
	}

	if ( ! (mdoc_macros[tok].flags & MDOC_PARSED)) {
		if (buf[*pos] != '\0')
			mandoc_vmsg(MANDOCERR_ARG_SKIP,
			    mdoc->parse, line, ppos,
			    "%s %s", mdoc_macronames[tok],
			    buf + *pos);
		if (endbody == NULL && n != NULL)
			rew_pending(mdoc, n);
		return;
	}

	if (endbody != NULL)
		n = endbody;

	ntok = TOKEN_NONE;
	for (j = 0; ; j++) {
		lastarg = *pos;

		if (j == maxargs && n != NULL)
			rew_last(mdoc, n);

		ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
		if (ac == ARGS_PUNCT || ac == ARGS_EOLN)
			break;

		ntok = ac == ARGS_QWORD ? TOKEN_NONE :
		    lookup(mdoc, tok, line, lastarg, p);

		if (ntok == TOKEN_NONE) {
			dword(mdoc, line, lastarg, p, DELIM_MAX,
			    MDOC_JOIN & mdoc_macros[tok].flags);
			continue;
		}

		if (n != NULL)
			rew_last(mdoc, n);
		mdoc->flags &= ~MDOC_NEWLINE;
		mdoc_macro(mdoc, ntok, line, lastarg, pos, buf);
		break;
	}

	if (n != NULL) {
		if (ntok != TOKEN_NONE && n->flags & MDOC_BROKEN) {
			target = n;
			do
				target = target->parent;
			while ( ! (target->flags & MDOC_ENDED));
			pending = find_pending(mdoc, ntok, line, ppos,
			    target);
		} else
			pending = 0;
		if ( ! pending)
			rew_pending(mdoc, n);
	}
	if (nl)
		append_delims(mdoc, line, pos, buf);
}
示例#3
0
/*
 * Close out block partial/full explicit.  
 */
static int
blk_exp_close(MACRO_PROT_ARGS)
{
	int	 	 j, lastarg, maxargs, flushed, nl;
	enum margserr	 ac;
	enum mdoct	 ntok;
	char		*p;

	nl = MDOC_NEWLINE & m->flags;

	switch (tok) {
	case (MDOC_Ec):
		maxargs = 1;
		break;
	default:
		maxargs = 0;
		break;
	}

	if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
		/* FIXME: do this in validate */
		if (buf[*pos]) 
			if ( ! mdoc_pmsg(m, line, ppos, MANDOCERR_ARGSLOST))
				return(0);

		if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
			return(0);
		return(rew_sub(MDOC_BLOCK, m, tok, line, ppos));
	}

	if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
		return(0);

	if (maxargs > 0) 
		if ( ! mdoc_tail_alloc(m, line, ppos, rew_alt(tok)))
			return(0);

	for (flushed = j = 0; ; j++) {
		lastarg = *pos;

		if (j == maxargs && ! flushed) {
			if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
				return(0);
			flushed = 1;
		}

		ac = mdoc_args(m, line, pos, buf, tok, &p);

		if (ARGS_ERROR == ac)
			return(0);
		if (ARGS_PUNCT == ac)
			break;
		if (ARGS_EOLN == ac)
			break;

		ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);

		if (MDOC_MAX == ntok) {
			if ( ! mdoc_word_alloc(m, line, lastarg, p))
				return(0);
			continue;
		}

		if ( ! flushed) {
			if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
				return(0);
			flushed = 1;
		}
		if ( ! mdoc_macro(m, ntok, line, lastarg, pos, buf))
			return(0);
		break;
	}

	if ( ! flushed && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
		return(0);

	if ( ! nl)
		return(1);
	return(append_delims(m, line, pos, buf));
}