FreeBSD/contrib/mdocml/mdoc_macro.c
/*
 * Close out block partial/full explicit.
 */
Close out block partial/full explicit.
Close out block partial / full explicit .
static void
blk_exp_close(MACRO_PROT_ARGS)
{
	struct roff_node *body;		
	struct roff_node *endbody;	
	struct roff_node *itblk;	
	struct roff_node *later;	
	struct roff_node *n;		
	struct roff_node *target;	
	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;
	default:
		maxargs = 0;
		break;
	}
	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;
		}
		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);
			if (later == NULL ||
			    (tok == MDOC_El && itblk == NULL))
				break;
			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 (maxargs)
				mdoc->next = ROFF_NEXT_CHILD;
			break;
		}
		if (n->tok == MDOC_Nd) {
			rew_last(mdoc, n);
			continue;
		}
		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) {
			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);
}
static void blk_exp_close ( MACRO_PROT_ARGS ) { struct roff_node * body ; struct roff_node * endbody ; struct roff_node * itblk ; struct roff_node * later ; struct roff_node * n ; struct roff_node * target ; 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 ; default : maxargs = 0 ; break ; } 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 ; } 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 ) ; if ( later == NULL || ( tok == MDOC_El && itblk == NULL ) ) break ; mandoc_vmsg ( MANDOCERR_BLK_NEST , mdoc -> parse , line , ppos , " " , 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 ( maxargs ) mdoc -> next = ROFF_NEXT_CHILD ; break ; } if ( n -> tok == MDOC_Nd ) { rew_last ( mdoc , n ) ; continue ; } 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 ) { 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 , " " , 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 ) ; }
Close out block partial/full explicit.
Close out block partial / full explicit .
/* Our own body. */ /* Our own end marker. */ /* An It block starting later. */ /* A sub-block starting later. */ /* Search back to our block. */ /* For find_pending(). */ /* FALLTHROUGH */ /*
	 * Search backwards for beginnings of blocks,
	 * both of our own and of pending sub-blocks.
	 */ /* Remember the start of our own body. */ /*
			 * Found the start of our own block.
			 * When there is no pending sub block,
			 * just proceed to closing out.
			 */ /*
			 * 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.
			 */ /*
			 * If a block closing macro taking arguments
			 * breaks another block, put the arguments
			 * into the end marker.
			 */ /* Explicit blocks close out description lines. */ /* Breaking an open sub block. */ /*
			 * Stray .Ec without previous .Eo:
			 * Break the output line, keep the arguments.
			 */