diff options
| author | Baptiste Daroussin <bapt@FreeBSD.org> | 2017-06-08 19:29:07 +0000 | 
|---|---|---|
| committer | Baptiste Daroussin <bapt@FreeBSD.org> | 2017-06-08 19:29:07 +0000 | 
| commit | 7ad21139cd51f34b1749abea843f7f513b4a6410 (patch) | |
| tree | 75256d41669ecdcdfe88b3f6d39c3b1691451b8f /mdoc_validate.c | |
| parent | 6cae2c9f93ec8d6e7a8bce06b82bed67f2d6450b (diff) | |
Diffstat (limited to 'mdoc_validate.c')
| -rw-r--r-- | mdoc_validate.c | 224 | 
1 files changed, 162 insertions, 62 deletions
| diff --git a/mdoc_validate.c b/mdoc_validate.c index e58e7a4721a9..9bf1efb3d784 100644 --- a/mdoc_validate.c +++ b/mdoc_validate.c @@ -1,4 +1,4 @@ -/*	$Id: mdoc_validate.c,v 1.318 2017/02/06 03:44:58 schwarze Exp $ */ +/*	$Id: mdoc_validate.c,v 1.332 2017/06/08 00:23:30 schwarze Exp $ */  /*   * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org> @@ -53,12 +53,13 @@ typedef	void	(*v_post)(POST_ARGS);  static	int	 build_list(struct roff_man *, int);  static	void	 check_text(struct roff_man *, int, int, char *); +static	void	 check_bsd(struct roff_man *, int, int, char *);  static	void	 check_argv(struct roff_man *,  			struct roff_node *, struct mdoc_argv *);  static	void	 check_args(struct roff_man *, struct roff_node *);  static	int	 child_an(const struct roff_node *); -static	size_t		macro2len(int); -static	void	 rewrite_macro2len(char **); +static	size_t		macro2len(enum roff_tok); +static	void	 rewrite_macro2len(struct roff_man *, char **);  static	void	 post_an(POST_ARGS);  static	void	 post_an_norm(POST_ARGS); @@ -105,11 +106,11 @@ static	void	 post_sh_authors(POST_ARGS);  static	void	 post_sm(POST_ARGS);  static	void	 post_st(POST_ARGS);  static	void	 post_std(POST_ARGS); +static	void	 post_useless(POST_ARGS);  static	void	 post_xr(POST_ARGS);  static	void	 post_xx(POST_ARGS); -static	v_post mdoc_valids[MDOC_MAX] = { -	NULL,		/* Ap */ +static	const v_post __mdoc_valids[MDOC_MAX - MDOC_Dd] = {  	post_dd,	/* Dd */  	post_dt,	/* Dt */  	post_os,	/* Os */ @@ -125,6 +126,7 @@ static	v_post mdoc_valids[MDOC_MAX] = {  	post_it,	/* It */  	NULL,		/* Ad */  	post_an,	/* An */ +	NULL,		/* Ap */  	post_defaults,	/* Ar */  	NULL,		/* Cd */  	NULL,		/* Cm */ @@ -201,7 +203,7 @@ static	v_post mdoc_valids[MDOC_MAX] = {  	post_sm,	/* Sm */  	post_hyph,	/* Sx */  	NULL,		/* Sy */ -	NULL,		/* Tn */ +	post_useless,	/* Tn */  	post_xx,	/* Ux */  	NULL,		/* Xc */  	NULL,		/* Xo */ @@ -227,16 +229,14 @@ static	v_post mdoc_valids[MDOC_MAX] = {  	post_en,	/* En */  	post_xx,	/* Dx */  	NULL,		/* %Q */ -	post_par,	/* br */ -	post_par,	/* sp */  	NULL,		/* %U */  	NULL,		/* Ta */ -	NULL,		/* ll */  }; +static	const v_post *const mdoc_valids = __mdoc_valids - MDOC_Dd;  #define	RSORD_MAX 14 /* Number of `Rs' blocks. */ -static	const int rsord[RSORD_MAX] = { +static	const enum roff_tok rsord[RSORD_MAX] = {  	MDOC__A,  	MDOC__T,  	MDOC__B, @@ -284,7 +284,7 @@ void  mdoc_node_validate(struct roff_man *mdoc)  {  	struct roff_node *n; -	v_post *p; +	const v_post *p;  	n = mdoc->last;  	mdoc->last = mdoc->last->child; @@ -303,6 +303,10 @@ mdoc_node_validate(struct roff_man *mdoc)  		if (n->sec != SEC_SYNOPSIS ||  		    (n->parent->tok != MDOC_Cd && n->parent->tok != MDOC_Fd))  			check_text(mdoc, n->line, n->pos, n->string); +		if (n->parent->tok == MDOC_Sh || +		    n->parent->tok == MDOC_Ss || +		    n->parent->tok == MDOC_It) +			check_bsd(mdoc, n->line, n->pos, n->string);  		break;  	case ROFFT_EQN:  	case ROFFT_TBL: @@ -326,6 +330,20 @@ mdoc_node_validate(struct roff_man *mdoc)  		/* Call the macro's postprocessor. */ +		if (n->tok < ROFF_MAX) { +			switch(n->tok) { +			case ROFF_br: +			case ROFF_sp: +				post_par(mdoc); +				break; +			default: +				roff_validate(mdoc); +				break; +			} +			break; +		} + +		assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);  		p = mdoc_valids + n->tok;  		if (*p)  			(*p)(mdoc); @@ -371,6 +389,25 @@ check_text(struct roff_man *mdoc, int ln, int pos, char *p)  }  static void +check_bsd(struct roff_man *mdoc, int ln, int pos, char *p) +{ +	const char	*cp; + +	if ((cp = strstr(p, "OpenBSD")) != NULL) +		mandoc_msg(MANDOCERR_BX, mdoc->parse, +		    ln, pos + (cp - p), "Ox"); +	if ((cp = strstr(p, "NetBSD")) != NULL) +		mandoc_msg(MANDOCERR_BX, mdoc->parse, +		    ln, pos + (cp - p), "Nx"); +	if ((cp = strstr(p, "FreeBSD")) != NULL) +		mandoc_msg(MANDOCERR_BX, mdoc->parse, +		    ln, pos + (cp - p), "Fx"); +	if ((cp = strstr(p, "DragonFly")) != NULL) +		mandoc_msg(MANDOCERR_BX, mdoc->parse, +		    ln, pos + (cp - p), "Dx"); +} + +static void  post_bl_norm(POST_ARGS)  {  	struct roff_node *n; @@ -450,7 +487,7 @@ post_bl_norm(POST_ARGS)  				    mdoc->parse, argv->line,  				    argv->pos, "Bl -width %s",  				    argv->value[0]); -			rewrite_macro2len(argv->value); +			rewrite_macro2len(mdoc, argv->value);  			n->norm->Bl.width = argv->value[0];  			break;  		case MDOC_Offset: @@ -465,7 +502,7 @@ post_bl_norm(POST_ARGS)  				    mdoc->parse, argv->line,  				    argv->pos, "Bl -offset %s",  				    argv->value[0]); -			rewrite_macro2len(argv->value); +			rewrite_macro2len(mdoc, argv->value);  			n->norm->Bl.offs = argv->value[0];  			break;  		default: @@ -592,7 +629,7 @@ post_bd(POST_ARGS)  				    mdoc->parse, argv->line,  				    argv->pos, "Bd -offset %s",  				    argv->value[0]); -			rewrite_macro2len(argv->value); +			rewrite_macro2len(mdoc, argv->value);  			n->norm->Bd.offs = argv->value[0];  			break;  		case MDOC_Compact: @@ -659,11 +696,11 @@ post_eoln(POST_ARGS)  {  	struct roff_node	*n; +	post_useless(mdoc);  	n = mdoc->last;  	if (n->child != NULL) -		mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse, -		    n->line, n->pos, "%s %s", -		    mdoc_macronames[n->tok], n->child->string); +		mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse, n->line, +		    n->pos, "%s %s", roff_name[n->tok], n->child->string);  	while (n->child != NULL)  		roff_node_delete(mdoc, n->child); @@ -757,6 +794,9 @@ post_lb(POST_ARGS)  		return;  	} +	mandoc_vmsg(MANDOCERR_LB_BAD, mdoc->parse, n->child->line, +	    n->child->pos, "Lb %s", n->child->string); +  	roff_word_alloc(mdoc, n->line, n->pos, "library");  	mdoc->last->flags = NODE_NOSRC;  	roff_word_alloc(mdoc, n->line, n->pos, "\\(Lq"); @@ -817,7 +857,7 @@ post_std(POST_ARGS)  			return;  	mandoc_msg(MANDOCERR_ARG_STD, mdoc->parse, -	    n->line, n->pos, mdoc_macronames[n->tok]); +	    n->line, n->pos, roff_name[n->tok]);  }  static void @@ -852,7 +892,17 @@ post_obsolete(POST_ARGS)  	n = mdoc->last;  	if (n->type == ROFFT_ELEM || n->type == ROFFT_BLOCK)  		mandoc_msg(MANDOCERR_MACRO_OBS, mdoc->parse, -		    n->line, n->pos, mdoc_macronames[n->tok]); +		    n->line, n->pos, roff_name[n->tok]); +} + +static void +post_useless(POST_ARGS) +{ +	struct roff_node *n; + +	n = mdoc->last; +	mandoc_msg(MANDOCERR_MACRO_USELESS, mdoc->parse, +	    n->line, n->pos, roff_name[n->tok]);  }  /* @@ -1029,15 +1079,25 @@ static void  post_nd(POST_ARGS)  {  	struct roff_node	*n; +	size_t			 sz;  	n = mdoc->last;  	if (n->type != ROFFT_BODY)  		return; +	if (n->sec != SEC_NAME) +		mandoc_msg(MANDOCERR_ND_LATE, mdoc->parse, +		    n->line, n->pos, "Nd"); +  	if (n->child == NULL)  		mandoc_msg(MANDOCERR_ND_EMPTY, mdoc->parse,  		    n->line, n->pos, "Nd"); +	else if (n->last->type == ROFFT_TEXT && +	    (sz = strlen(n->last->string)) != 0 && +	    n->last->string[sz - 1] == '.') +		mandoc_msg(MANDOCERR_ND_DOT, mdoc->parse, +		    n->last->line, n->last->pos + sz - 1, NULL);  	post_hyph(mdoc);  } @@ -1056,7 +1116,7 @@ post_display(POST_ARGS)  				roff_node_delete(mdoc, n);  		} else if (n->child == NULL)  			mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse, -			    n->line, n->pos, mdoc_macronames[n->tok]); +			    n->line, n->pos, roff_name[n->tok]);  		else if (n->tok == MDOC_D1)  			post_hyph(mdoc);  		break; @@ -1079,7 +1139,7 @@ post_display(POST_ARGS)  			if (np->type == ROFFT_BLOCK && np->tok == MDOC_Bd) {  				mandoc_vmsg(MANDOCERR_BD_NEST,  				    mdoc->parse, n->line, n->pos, -				    "%s in Bd", mdoc_macronames[n->tok]); +				    "%s in Bd", roff_name[n->tok]);  				break;  			}  		} @@ -1265,10 +1325,10 @@ post_it(POST_ARGS)  		/* FALLTHROUGH */  	case LIST_item:  		if ((nch = nit->head->child) != NULL) -			mandoc_vmsg(MANDOCERR_ARG_SKIP, -			    mdoc->parse, nit->line, nit->pos, -			    "It %s", nch->string == NULL ? -			    mdoc_macronames[nch->tok] : nch->string); +			mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse, +			    nit->line, nit->pos, "It %s", +			    nch->string == NULL ? roff_name[nch->tok] : +			    nch->string);  		break;  	case LIST_column:  		cols = (int)nbl->norm->Bl.ncols; @@ -1306,7 +1366,7 @@ post_bl_block(POST_ARGS)  			switch (nc->tok) {  			case MDOC_Pp:  			case MDOC_Lp: -			case MDOC_br: +			case ROFF_br:  				break;  			default:  				nc = NULL; @@ -1315,14 +1375,13 @@ post_bl_block(POST_ARGS)  			if (ni->next == NULL) {  				mandoc_msg(MANDOCERR_PAR_MOVE,  				    mdoc->parse, nc->line, nc->pos, -				    mdoc_macronames[nc->tok]); +				    roff_name[nc->tok]);  				mdoc_node_relink(mdoc, nc);  			} else if (n->norm->Bl.comp == 0 &&  			    n->norm->Bl.type != LIST_column) {  				mandoc_vmsg(MANDOCERR_PAR_SKIP,  				    mdoc->parse, nc->line, nc->pos, -				    "%s before It", -				    mdoc_macronames[nc->tok]); +				    "%s before It", roff_name[nc->tok]);  				roff_node_delete(mdoc, nc);  			} else  				break; @@ -1335,17 +1394,17 @@ post_bl_block(POST_ARGS)   * If the argument of -offset or -width is a macro,   * replace it with the associated default width.   */ -void -rewrite_macro2len(char **arg) +static void +rewrite_macro2len(struct roff_man *mdoc, char **arg)  {  	size_t		  width; -	int		  tok; +	enum roff_tok	  tok;  	if (*arg == NULL)  		return;  	else if ( ! strcmp(*arg, "Ds"))  		width = 6; -	else if ((tok = mdoc_hash_find(*arg)) == TOKEN_NONE) +	else if ((tok = roffhash_find(mdoc->mdocmac, *arg, 0)) == TOKEN_NONE)  		return;  	else  		width = macro2len(tok); @@ -1423,6 +1482,8 @@ post_bl(POST_ARGS)  	struct roff_node	*nparent, *nprev; /* of the Bl block */  	struct roff_node	*nblock, *nbody;  /* of the Bl */  	struct roff_node	*nchild, *nnext;  /* of the Bl body */ +	const char		*prev_Er; +	int			 order;  	nbody = mdoc->last;  	switch (nbody->type) { @@ -1486,8 +1547,7 @@ post_bl(POST_ARGS)  		}  		mandoc_msg(MANDOCERR_BL_MOVE, mdoc->parse, -		    nchild->line, nchild->pos, -		    mdoc_macronames[nchild->tok]); +		    nchild->line, nchild->pos, roff_name[nchild->tok]);  		/*  		 * Move the node out of the Bl block. @@ -1524,6 +1584,34 @@ post_bl(POST_ARGS)  		nchild = nnext;  	} + +	if (mdoc->meta.os_e != MDOC_OS_NETBSD) +		return; + +	prev_Er = NULL; +	for (nchild = nbody->child; nchild != NULL; nchild = nchild->next) { +		if (nchild->tok != MDOC_It) +			continue; +		if ((nnext = nchild->head->child) == NULL) +			continue; +		if (nnext->type == ROFFT_BLOCK) +			nnext = nnext->body->child; +		if (nnext == NULL || nnext->tok != MDOC_Er) +			continue; +		nnext = nnext->child; +		if (prev_Er != NULL) { +			order = strcmp(prev_Er, nnext->string); +			if (order > 0) +				mandoc_vmsg(MANDOCERR_ER_ORDER, +				    mdoc->parse, nnext->line, nnext->pos, +				    "Er %s %s", prev_Er, nnext->string); +			else if (order == 0) +				mandoc_vmsg(MANDOCERR_ER_REP, +				    mdoc->parse, nnext->line, nnext->pos, +				    "Er %s", prev_Er); +		} +		prev_Er = nnext->string; +	}  }  static void @@ -1565,7 +1653,7 @@ post_sm(POST_ARGS)  	mandoc_vmsg(MANDOCERR_SM_BAD,  	    mdoc->parse, nch->line, nch->pos, -	    "%s %s", mdoc_macronames[mdoc->last->tok], nch->string); +	    "%s %s", roff_name[mdoc->last->tok], nch->string);  	mdoc_node_relink(mdoc, nch);  	return;  } @@ -1608,7 +1696,7 @@ post_root(POST_ARGS)  		mandoc_msg(MANDOCERR_DOC_EMPTY, mdoc->parse, 0, 0, NULL);  	else if (n->tok != MDOC_Sh)  		mandoc_msg(MANDOCERR_SEC_BEFORE, mdoc->parse, -		    n->line, n->pos, mdoc_macronames[n->tok]); +		    n->line, n->pos, roff_name[n->tok]);  }  static void @@ -1642,9 +1730,8 @@ post_rs(POST_ARGS)  				break;  		if (i == RSORD_MAX) { -			mandoc_msg(MANDOCERR_RS_BAD, -			    mdoc->parse, nch->line, nch->pos, -			    mdoc_macronames[nch->tok]); +			mandoc_msg(MANDOCERR_RS_BAD, mdoc->parse, +			    nch->line, nch->pos, roff_name[nch->tok]);  			i = -1;  		} else if (nch->tok == MDOC__J || nch->tok == MDOC__B)  			np->norm->Rs.quote_T++; @@ -1797,7 +1884,7 @@ post_sh_name(POST_ARGS)  			/* FALLTHROUGH */  		default:  			mandoc_msg(MANDOCERR_NAMESEC_BAD, mdoc->parse, -			    n->line, n->pos, mdoc_macronames[n->tok]); +			    n->line, n->pos, roff_name[n->tok]);  			continue;  		}  		break; @@ -1867,7 +1954,7 @@ post_sh_see_also(POST_ARGS)  			if (isalpha((const unsigned char)*name))  				return;  		lastpunct = n->string; -		if (n->next == NULL) +		if (n->next == NULL || n->next->tok == MDOC_Rs)  			mandoc_vmsg(MANDOCERR_XR_PUNCT, mdoc->parse,  			    n->line, n->pos, "%s after %s(%s)",  			    lastpunct, lastname, lastsec); @@ -1918,7 +2005,7 @@ post_sh_head(POST_ARGS)  		    sec != SEC_CUSTOM ? secnames[sec] :  		    (nch = mdoc->last->child) == NULL ? "" :  		    nch->type == ROFFT_TEXT ? nch->string : -		    mdoc_macronames[nch->tok]); +		    roff_name[nch->tok]);  	/* The SYNOPSIS gets special attention in other areas. */ @@ -2014,6 +2101,9 @@ post_ignpar(POST_ARGS)  	struct roff_node *np;  	switch (mdoc->last->type) { +	case ROFFT_BLOCK: +		post_prevpar(mdoc); +		return;  	case ROFFT_HEAD:  		post_hyph(mdoc);  		return; @@ -2027,8 +2117,8 @@ post_ignpar(POST_ARGS)  		if (np->tok == MDOC_Pp || np->tok == MDOC_Lp) {  			mandoc_vmsg(MANDOCERR_PAR_SKIP,  			    mdoc->parse, np->line, np->pos, -			    "%s after %s", mdoc_macronames[np->tok], -			    mdoc_macronames[mdoc->last->tok]); +			    "%s after %s", roff_name[np->tok], +			    roff_name[mdoc->last->tok]);  			roff_node_delete(mdoc, np);  		} @@ -2036,8 +2126,8 @@ post_ignpar(POST_ARGS)  		if (np->tok == MDOC_Pp || np->tok == MDOC_Lp) {  			mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,  			    np->line, np->pos, "%s at the end of %s", -			    mdoc_macronames[np->tok], -			    mdoc_macronames[mdoc->last->tok]); +			    roff_name[np->tok], +			    roff_name[mdoc->last->tok]);  			roff_node_delete(mdoc, np);  		}  } @@ -2060,7 +2150,7 @@ post_prevpar(POST_ARGS)  	if (n->prev->tok != MDOC_Pp &&  	    n->prev->tok != MDOC_Lp && -	    n->prev->tok != MDOC_br) +	    n->prev->tok != ROFF_br)  		return;  	if (n->tok == MDOC_Bl && n->norm->Bl.comp)  		return; @@ -2070,9 +2160,8 @@ post_prevpar(POST_ARGS)  		return;  	mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse, -	    n->prev->line, n->prev->pos, -	    "%s before %s", mdoc_macronames[n->prev->tok], -	    mdoc_macronames[n->tok]); +	    n->prev->line, n->prev->pos, "%s before %s", +	    roff_name[n->prev->tok], roff_name[n->tok]);  	roff_node_delete(mdoc, n->prev);  } @@ -2082,10 +2171,10 @@ post_par(POST_ARGS)  	struct roff_node *np;  	np = mdoc->last; -	if (np->tok != MDOC_br && np->tok != MDOC_sp) +	if (np->tok != ROFF_br && np->tok != ROFF_sp)  		post_prevpar(mdoc); -	if (np->tok == MDOC_sp) { +	if (np->tok == ROFF_sp) {  		if (np->child != NULL && np->child->next != NULL)  			mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,  			    np->child->next->line, np->child->next->pos, @@ -2093,21 +2182,20 @@ post_par(POST_ARGS)  	} else if (np->child != NULL)  		mandoc_vmsg(MANDOCERR_ARG_SKIP,  		    mdoc->parse, np->line, np->pos, "%s %s", -		    mdoc_macronames[np->tok], np->child->string); +		    roff_name[np->tok], np->child->string);  	if ((np = mdoc->last->prev) == NULL) {  		np = mdoc->last->parent;  		if (np->tok != MDOC_Sh && np->tok != MDOC_Ss)  			return;  	} else if (np->tok != MDOC_Pp && np->tok != MDOC_Lp && -	    (mdoc->last->tok != MDOC_br || -	     (np->tok != MDOC_sp && np->tok != MDOC_br))) +	    (mdoc->last->tok != ROFF_br || +	     (np->tok != ROFF_sp && np->tok != ROFF_br)))  		return;  	mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse, -	    mdoc->last->line, mdoc->last->pos, -	    "%s after %s", mdoc_macronames[mdoc->last->tok], -	    mdoc_macronames[np->tok]); +	    mdoc->last->line, mdoc->last->pos, "%s after %s", +	    roff_name[mdoc->last->tok], roff_name[np->tok]);  	roff_node_delete(mdoc, mdoc->last);  } @@ -2251,11 +2339,19 @@ static void  post_bx(POST_ARGS)  {  	struct roff_node	*n, *nch; +	const char		*macro;  	n = mdoc->last;  	nch = n->child;  	if (nch != NULL) { +		macro = !strcmp(nch->string, "Open") ? "Ox" : +		    !strcmp(nch->string, "Net") ? "Nx" : +		    !strcmp(nch->string, "Free") ? "Fx" : +		    !strcmp(nch->string, "DragonFly") ? "Dx" : NULL; +		if (macro != NULL) +			mandoc_msg(MANDOCERR_BX, mdoc->parse, +			    n->line, n->pos, macro);  		mdoc->last = nch;  		nch = nch->next;  		mdoc->next = ROFF_NEXT_SIBLING; @@ -2322,11 +2418,11 @@ post_os(POST_ARGS)  	mdoc->meta.os = NULL;  	deroff(&mdoc->meta.os, n);  	if (mdoc->meta.os) -		return; +		goto out;  	if (mdoc->defos) {  		mdoc->meta.os = mandoc_strdup(mdoc->defos); -		return; +		goto out;  	}  #ifdef OSNAME @@ -2343,6 +2439,10 @@ post_os(POST_ARGS)  	}  	mdoc->meta.os = mandoc_strdup(defbuf);  #endif /*!OSNAME*/ + +out:	mdoc->meta.os_e = strstr(mdoc->meta.os, "OpenBSD") != NULL ? +	    MDOC_OS_OPENBSD : strstr(mdoc->meta.os, "NetBSD") != NULL ? +	    MDOC_OS_NETBSD : MDOC_OS_OTHER;  }  enum roff_sec @@ -2358,7 +2458,7 @@ mdoc_a2sec(const char *p)  }  static size_t -macro2len(int macro) +macro2len(enum roff_tok macro)  {  	switch (macro) { | 
