Beispiel #1
0
static int
rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
{
	struct mdoc_node *n, *np;

	assert(to);
	mdoc->next = MDOC_NEXT_SIBLING;

	/* LINTED */
	while (mdoc->last != to) {
		/*
		 * Save the parent here, because we may delete the
		 * m->last node in the post-validation phase and reset
		 * it to m->last->parent, causing a step in the closing
		 * out to be lost.
		 */
		np = mdoc->last->parent;
		if ( ! mdoc_valid_post(mdoc))
			return(0);
		n = mdoc->last;
		mdoc->last = np;
		assert(mdoc->last);
		mdoc->last->last = n;
	}

	return(mdoc_valid_post(mdoc));
}
Beispiel #2
0
static int
rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
{

	assert(to);
	mdoc->next = MDOC_NEXT_SIBLING;

	/* LINTED */
	while (mdoc->last != to) {
		if ( ! mdoc_valid_post(mdoc))
			return(0);
		if ( ! mdoc_action_post(mdoc))
			return(0);
		mdoc->last = mdoc->last->parent;
		assert(mdoc->last);
	}

	if ( ! mdoc_valid_post(mdoc))
		return(0);
	return(mdoc_action_post(mdoc));
}
Beispiel #3
0
static int
node_append(struct mdoc *mdoc, struct mdoc_node *p)
{

    assert(mdoc->last);
    assert(mdoc->first);
    assert(MDOC_ROOT != p->type);

    switch (mdoc->next) {
    case (MDOC_NEXT_SIBLING):
        mdoc->last->next = p;
        p->prev = mdoc->last;
        p->parent = mdoc->last->parent;
        break;
    case (MDOC_NEXT_CHILD):
        mdoc->last->child = p;
        p->parent = mdoc->last;
        break;
    default:
        abort();
        /* NOTREACHED */
    }

    p->parent->nchild++;

    /*
     * Copy over the normalised-data pointer of our parent.  Not
     * everybody has one, but copying a null pointer is fine.
     */

    switch (p->type) {
    case (MDOC_BODY):
    /* FALLTHROUGH */
    case (MDOC_TAIL):
    /* FALLTHROUGH */
    case (MDOC_HEAD):
        p->norm = p->parent->norm;
        break;
    default:
        break;
    }

    if ( ! mdoc_valid_pre(mdoc, p))
        return(0);

    switch (p->type) {
    case (MDOC_HEAD):
        assert(MDOC_BLOCK == p->parent->type);
        p->parent->head = p;
        break;
    case (MDOC_TAIL):
        assert(MDOC_BLOCK == p->parent->type);
        p->parent->tail = p;
        break;
    case (MDOC_BODY):
        if (p->end)
            break;
        assert(MDOC_BLOCK == p->parent->type);
        p->parent->body = p;
        break;
    default:
        break;
    }

    mdoc->last = p;

    switch (p->type) {
    case (MDOC_TBL):
    /* FALLTHROUGH */
    case (MDOC_TEXT):
        if ( ! mdoc_valid_post(mdoc))
            return(0);
        break;
    default:
        break;
    }

    return(1);
}
Beispiel #4
0
/*
 * Parse free-form text, that is, a line that does not begin with the
 * control character.
 */
static int
mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs)
{
	char		 *c, *ws, *end;
	struct mdoc_node *n;

	assert(mdoc->last);
	n = mdoc->last;

	/*
	 * Divert directly to list processing if we're encountering a
	 * columnar MDOC_BLOCK with or without a prior MDOC_BLOCK entry
	 * (a MDOC_BODY means it's already open, in which case we should
	 * process within its context in the normal way).
	 */

	if (MDOC_Bl == n->tok && MDOC_BODY == n->type &&
	    LIST_column == n->norm->Bl.type) {
		/* `Bl' is open without any children. */
		mdoc->flags |= MDOC_FREECOL;
		mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf);
		return(1);
	}

	if (MDOC_It == n->tok && MDOC_BLOCK == n->type &&
	    NULL != n->parent &&
	    MDOC_Bl == n->parent->tok &&
	    LIST_column == n->parent->norm->Bl.type) {
		/* `Bl' has block-level `It' children. */
		mdoc->flags |= MDOC_FREECOL;
		mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf);
		return(1);
	}

	/*
	 * Search for the beginning of unescaped trailing whitespace (ws)
	 * and for the first character not to be output (end).
	 */

	/* FIXME: replace with strcspn(). */
	ws = NULL;
	for (c = end = buf + offs; *c; c++) {
		switch (*c) {
		case ' ':
			if (NULL == ws)
				ws = c;
			continue;
		case '\t':
			/*
			 * Always warn about trailing tabs,
			 * even outside literal context,
			 * where they should be put on the next line.
			 */
			if (NULL == ws)
				ws = c;
			/*
			 * Strip trailing tabs in literal context only;
			 * outside, they affect the next line.
			 */
			if (MDOC_LITERAL & mdoc->flags)
				continue;
			break;
		case '\\':
			/* Skip the escaped character, too, if any. */
			if (c[1])
				c++;
			/* FALLTHROUGH */
		default:
			ws = NULL;
			break;
		}
		end = c + 1;
	}
	*end = '\0';

	if (ws)
		mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse,
		    line, (int)(ws-buf), NULL);

	if (buf[offs] == '\0' && ! (mdoc->flags & MDOC_LITERAL)) {
		mandoc_msg(MANDOCERR_FI_BLANK, mdoc->parse,
		    line, (int)(c - buf), NULL);

		/*
		 * Insert a `sp' in the case of a blank line.  Technically,
		 * blank lines aren't allowed, but enough manuals assume this
		 * behaviour that we want to work around it.
		 */
		mdoc_elem_alloc(mdoc, line, offs, MDOC_sp, NULL);
		mdoc->next = MDOC_NEXT_SIBLING;
		mdoc_valid_post(mdoc);
		return(1);
	}

	mdoc_word_alloc(mdoc, line, offs, buf+offs);

	if (mdoc->flags & MDOC_LITERAL)
		return(1);

	/*
	 * 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(buf < end);

	if (mandoc_eos(buf+offs, (size_t)(end-buf-offs)))
		mdoc->last->flags |= MDOC_EOS;
	return(1);
}