示例#1
0
/*
 * Rewinding entails ascending the parse tree until a coherent point,
 * for example, the `SH' macro will close out any intervening `SS'
 * scopes.  When a scope is closed, it must be validated and actioned.
 */
static int
rew_scope(enum man_type type, struct man *man, enum mant tok)
{
	struct man_node	*n;
	enum rew	 c;

	/* LINTED */
	for (n = man->last; n; n = n->parent) {
		/* 
		 * Whether we should stop immediately (REW_HALT), stop
		 * and rewind until this point (REW_REWIND), or keep
		 * rewinding (REW_NOHALT).
		 */
		c = rew_dohalt(tok, type, n);
		if (REW_HALT == c)
			return(1);
		if (REW_REWIND == c)
			break;
	}

	/* 
	 * Rewind until the current point.  Warn if we're a roff
	 * instruction that's mowing over explicit scopes.
	 */
	assert(n);

	return(man_unscope(man, n, MANDOCERR_MAX));
}
static int
rew_sub(enum mdoc_type t, struct mdoc *mdoc, 
		enum mdoct tok, int line, int ppos)
{
	struct mdoc_node *n;

	n = mdoc->last;
	while (n) {
		switch (rew_dohalt(tok, t, n)) {
		case (REWIND_NONE):
			return(1);
		case (REWIND_THIS):
			n->lastline = line -
			    (MDOC_NEWLINE & mdoc->flags &&
			     ! (MDOC_EXPLICIT & mdoc_macros[tok].flags));
			break;
		case (REWIND_FORCE):
			mandoc_vmsg(MANDOCERR_SCOPEBROKEN, mdoc->parse, 
					line, ppos, "%s breaks %s", 
					mdoc_macronames[tok],
					mdoc_macronames[n->tok]);
			/* FALLTHROUGH */
		case (REWIND_MORE):
			n->lastline = line -
			    (MDOC_NEWLINE & mdoc->flags ? 1 : 0);
			n = n->parent;
			continue;
		case (REWIND_LATER):
			if (make_pending(n, tok, mdoc, line, ppos) ||
			    MDOC_BLOCK != t)
				return(1);
			/* FALLTHROUGH */
		case (REWIND_ERROR):
			mdoc_pmsg(mdoc, line, ppos, MANDOCERR_NOSCOPE);
			return(1);
		}
		break;
	}

	assert(n);
	if ( ! rew_last(mdoc, n))
		return(0);

	/*
	 * The current block extends an enclosing block.
	 * Now that the current block ends, close the enclosing block, too.
	 */
	while (NULL != (n = n->pending)) {
		if ( ! rew_last(mdoc, n))
			return(0);
		if (MDOC_HEAD == n->type &&
		    ! mdoc_body_alloc(mdoc, n->line, n->pos, n->tok))
			return(0);
	}

	return(1);
}
示例#3
0
static int
rew_sub(enum mdoc_type t, struct mdoc *m, 
		enum mdoct tok, int line, int ppos)
{
	struct mdoc_node *n;
	enum rew	  c;

	/* LINTED */
	for (n = m->last; n; n = n->parent) {
		c = rew_dohalt(tok, t, n);
		if (REWIND_HALT == c) {
			if (MDOC_BLOCK != t)
				return(1);
			if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags))
				return(1);
			/* FIXME: shouldn't raise an error */
			mdoc_pmsg(m, line, ppos, MANDOCERR_SYNTNOSCOPE);
			return(0);
		}
		if (REWIND_REWIND == c)
			break;
		else if (rew_dobreak(tok, n))
			continue;
		if ( ! swarn(m, t, line, ppos, n))
			return(0);
	}

	assert(n);
	if ( ! rew_last(m, n))
		return(0);

#ifdef	UGLY
	/*
	 * The current block extends an enclosing block beyond a line
	 * break.  Now that the current block ends, close the enclosing
	 * block, too.
	 */
	if (NULL != (n = n->pending)) {
		assert(MDOC_HEAD == n->type);
		if ( ! rew_last(m, n))
			return(0);
		if ( ! mdoc_body_alloc(m, n->line, n->pos, n->tok))
			return(0);
	}
#endif

	return(1);
}
示例#4
0
/*
 * We are trying to close a block identified by tok,
 * but the child block *broken is still open.
 * Thus, postpone closing the tok block
 * until the rew_sub call closing *broken.
 */
static int
make_pending(struct mdoc_node *broken, enum mdoct tok,
		struct mdoc *m, int line, int ppos)
{
	struct mdoc_node *breaker;

	/*
	 * Iterate backwards, searching for the block matching tok,
	 * that is, the block breaking the *broken block.
	 */
	for (breaker = broken->parent; breaker; breaker = breaker->parent) {

		/*
		 * If the *broken block had already been broken before
		 * and we encounter its breaker, make the tok block
		 * pending on the inner breaker.
		 * Graphically, "[A breaker=[B broken=[C->B B] tok=A] C]"
		 * becomes "[A broken=[B [C->B B] tok=A] C]"
		 * and finally "[A [B->A [C->B B] A] C]".
		 */
		if (breaker == broken->pending) {
			broken = breaker;
			continue;
		}

		if (REWIND_THIS != rew_dohalt(tok, MDOC_BLOCK, breaker))
			continue;
		if (MDOC_BODY == broken->type)
			broken = broken->parent;

		/*
		 * Found the breaker.
		 * If another, outer breaker is already pending on
		 * the *broken block, we must not clobber the link
		 * to the outer breaker, but make it pending on the
		 * new, now inner breaker.
		 * Graphically, "[A breaker=[B broken=[C->A A] tok=B] C]"
		 * becomes "[A breaker=[B->A broken=[C A] tok=B] C]"
		 * and finally "[A [B->A [C->B A] B] C]".
		 */
		if (broken->pending) {
			struct mdoc_node *taker;

			/*
			 * If the breaker had also been broken before,
			 * it cannot take on the outer breaker itself,
			 * but must hand it on to its own breakers.
			 * Graphically, this is the following situation:
			 * "[A [B breaker=[C->B B] broken=[D->A A] tok=C] D]"
			 * "[A taker=[B->A breaker=[C->B B] [D->C A] C] D]"
			 */
			taker = breaker;
			while (taker->pending)
				taker = taker->pending;
			taker->pending = broken->pending;
		}
		broken->pending = breaker;
		mandoc_vmsg(MANDOCERR_SCOPENEST, m->parse, line, ppos,
				"%s breaks %s", mdoc_macronames[tok],
				mdoc_macronames[broken->tok]);
		return(1);
	}

	/*
	 * Found no matching block for tok.
	 * Are you trying to close a block that is not open?
	 */
	return(0);
}