コード例 #1
0
static int
check_parent(PRE_ARGS, enum mdoct tok, enum mdoc_type t)
{

	assert(n->parent);
	if ((MDOC_ROOT == t || tok == n->parent->tok) &&
			(t == n->parent->type))
		return(1);

	mdoc_vmsg(mdoc, MANDOCERR_SYNTCHILD,
				n->line, n->pos, "want parent %s",
				MDOC_ROOT == t ? "<root>" : 
					mdoc_macronames[tok]);
	return(0);
}
コード例 #2
0
ファイル: mdoc_macro.c プロジェクト: Spenser309/CS551
static int
swarn(struct mdoc *mdoc, enum mdoc_type type, 
		int line, int pos, const struct mdoc_node *p)
{
	const char	*n, *t, *tt;
	enum mandocerr	 ec;

	n = t = "<root>";
	tt = "block";

	switch (type) {
	case (MDOC_BODY):
		tt = "multi-line";
		break;
	case (MDOC_HEAD):
		tt = "line";
		break;
	default:
		break;
	}

	switch (p->type) {
	case (MDOC_BLOCK):
		n = mdoc_macronames[p->tok];
		t = "block";
		break;
	case (MDOC_BODY):
		n = mdoc_macronames[p->tok];
		t = "multi-line";
		break;
	case (MDOC_HEAD):
		n = mdoc_macronames[p->tok];
		t = "line";
		break;
	default:
		break;
	}

	ec = (MDOC_IGN_SCOPE & mdoc->pflags) ?
		MANDOCERR_SCOPE : MANDOCERR_SYNTSCOPE;

	return(mdoc_vmsg(mdoc, ec, line, pos, 
				"%s scope breaks %s of %s", 
				tt, t, n));
}
コード例 #3
0
static int
check_count(struct mdoc *m, enum mdoc_type type, 
		enum check_lvl lvl, enum check_ineq ineq, int val)
{
	const char	*p;
	enum mandocerr	 t;

	if (m->last->type != type)
		return(1);
	
	switch (ineq) {
	case (CHECK_LT):
		p = "less than ";
		if (m->last->nchild < val)
			return(1);
		break;
	case (CHECK_GT):
		p = "more than ";
		if (m->last->nchild > val)
			return(1);
		break;
	case (CHECK_EQ):
		p = "";
		if (val == m->last->nchild)
			return(1);
		break;
	default:
		abort();
		/* NOTREACHED */
	}

	t = lvl == CHECK_WARN ? MANDOCERR_ARGCWARN : MANDOCERR_ARGCOUNT;

	return(mdoc_vmsg(m, t, m->last->line, m->last->pos,
			"want %s%d children (have %d)",
			p, val, m->last->nchild));
}
コード例 #4
0
/*
 * Parse a macro line, that is, a line beginning with the control
 * character.
 */
static int
mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
{
    enum mdoct	  tok;
    int		  i, j, sv;
    char		  mac[5];
    struct mdoc_node *n;

    /* Empty lines are ignored. */

    offs++;

    if ('\0' == buf[offs])
        return(1);

    i = offs;

    /* Accept tabs/whitespace after the initial control char. */

    if (' ' == buf[i] || '\t' == buf[i]) {
        i++;
        while (buf[i] && (' ' == buf[i] || '\t' == buf[i]))
            i++;
        if ('\0' == buf[i])
            return(1);
    }

    sv = i;

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

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

    tok = (j > 1 || j < 4) ? mdoc_hash_find(mac) : MDOC_MAX;
    if (MDOC_MAX == tok) {
        mdoc_vmsg(m, MANDOCERR_MACRO, ln, sv, "%s", buf + sv - 1);
        return(1);
    }

    /* Disregard the first trailing tab, if applicable. */

    if ('\t' == buf[i])
        i++;

    /* Jump to the next non-whitespace word. */

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

    /*
     * 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[i] && ' ' == buf[i - 1])
        mdoc_pmsg(m, ln, i - 1, MANDOCERR_EOLNSPACE);

    /*
     * If an initial macro or a list invocation, divert directly
     * into macro processing.
     */

    if (NULL == m->last || MDOC_It == tok || MDOC_El == tok) {
        if ( ! mdoc_macro(m, tok, ln, sv, &i, buf))
            goto err;
        return(1);
    }

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

    /*
     * If the first macro of a `Bl -column', open an `It' block
     * context around the parsed macro.
     */

    if (MDOC_Bl == n->tok && MDOC_BODY == n->type &&
            LIST_column == n->norm->Bl.type) {
        m->flags |= MDOC_FREECOL;
        if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf))
            goto err;
        return(1);
    }

    /*
     * If we're following a block-level `It' within a `Bl -column'
     * context (perhaps opened in the above block or in ptext()),
     * then open an `It' block context around the parsed macro.
     */

    if (MDOC_It == n->tok && MDOC_BLOCK == n->type &&
            NULL != n->parent &&
            MDOC_Bl == n->parent->tok &&
            LIST_column == n->parent->norm->Bl.type) {
        m->flags |= MDOC_FREECOL;
        if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf))
            goto err;
        return(1);
    }

    /* Normal processing of a macro. */

    if ( ! mdoc_macro(m, tok, ln, sv, &i, buf))
        goto err;

    return(1);

err:	/* Error out. */

    m->flags |= MDOC_HALT;
    return(0);
}
コード例 #5
0
static int
post_it(POST_ARGS)
{
	int		  i, cols, rc;
	enum mdoc_list	  lt;
	struct mdoc_node *n, *c;
	enum mandocerr	  er;

	if (MDOC_BLOCK != mdoc->last->type)
		return(1);

	n = mdoc->last->parent->parent;
	lt = n->norm->Bl.type;

	if (LIST__NONE == lt) {
		mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_LISTTYPE);
		return(1);
	}

	switch (lt) {
	case (LIST_tag):
		if (mdoc->last->head->child)
			break;
		/* FIXME: give this a dummy value. */
		mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS);
		break;
	case (LIST_hang):
		/* FALLTHROUGH */
	case (LIST_ohang):
		/* FALLTHROUGH */
	case (LIST_inset):
		/* FALLTHROUGH */
	case (LIST_diag):
		if (NULL == mdoc->last->head->child)
			mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS);
		break;
	case (LIST_bullet):
		/* FALLTHROUGH */
	case (LIST_dash):
		/* FALLTHROUGH */
	case (LIST_enum):
		/* FALLTHROUGH */
	case (LIST_hyphen):
		if (NULL == mdoc->last->body->child)
			mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY);
		/* FALLTHROUGH */
	case (LIST_item):
		if (mdoc->last->head->child)
			mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_ARGSLOST);
		break;
	case (LIST_column):
		cols = (int)n->norm->Bl.ncols;

		assert(NULL == mdoc->last->head->child);

		if (NULL == mdoc->last->body->child)
			mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY);

		for (i = 0, c = mdoc->last->child; c; c = c->next)
			if (MDOC_BODY == c->type)
				i++;

		if (i < cols)
			er = MANDOCERR_ARGCOUNT;
		else if (i == cols || i == cols + 1)
			break;
		else
			er = MANDOCERR_SYNTARGCOUNT;

		rc = mdoc_vmsg(mdoc, er, 
				mdoc->last->line, mdoc->last->pos, 
				"columns == %d (have %d)", cols, i);
		return(rc);
	default:
		break;
	}

	return(1);
}