diff options
Diffstat (limited to 'man_validate.c')
| -rw-r--r-- | man_validate.c | 214 | 
1 files changed, 128 insertions, 86 deletions
diff --git a/man_validate.c b/man_validate.c index e40b089f53b8..da2e557ebb5e 100644 --- a/man_validate.c +++ b/man_validate.c @@ -1,7 +1,7 @@ -/*	$Id: man_validate.c,v 1.80 2012/01/03 15:16:24 kristaps Exp $ */ +/*	$Id: man_validate.c,v 1.86 2013/10/17 20:54:58 schwarze Exp $ */  /*   * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2010, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>   *   * Permission to use, copy, modify, and distribute this software for any   * purpose with or without fee is hereby granted, provided that the above @@ -35,7 +35,7 @@  #include "libman.h"  #include "libmandoc.h" -#define	CHKARGS	  struct man *m, struct man_node *n +#define	CHKARGS	  struct man *man, struct man_node *n  typedef	int	(*v_check)(CHKARGS); @@ -49,12 +49,14 @@ static	int	  check_eq2(CHKARGS);  static	int	  check_le1(CHKARGS);  static	int	  check_ge2(CHKARGS);  static	int	  check_le5(CHKARGS); +static	int	  check_head1(CHKARGS);  static	int	  check_par(CHKARGS);  static	int	  check_part(CHKARGS);  static	int	  check_root(CHKARGS);  static	void	  check_text(CHKARGS);  static	int	  post_AT(CHKARGS); +static	int	  post_IP(CHKARGS);  static	int	  post_vs(CHKARGS);  static	int	  post_fi(CHKARGS);  static	int	  post_ft(CHKARGS); @@ -70,6 +72,8 @@ static	v_check	  posts_eq0[] = { check_eq0, NULL };  static	v_check	  posts_eq2[] = { check_eq2, NULL };  static	v_check	  posts_fi[] = { check_eq0, post_fi, NULL };  static	v_check	  posts_ft[] = { post_ft, NULL }; +static	v_check	  posts_ip[] = { post_IP, NULL }; +static	v_check	  posts_le1[] = { check_le1, NULL };  static	v_check	  posts_nf[] = { check_eq0, post_nf, NULL };  static	v_check	  posts_par[] = { check_par, NULL };  static	v_check	  posts_part[] = { check_part, NULL }; @@ -77,6 +81,7 @@ static	v_check	  posts_sec[] = { post_sec, NULL };  static	v_check	  posts_sp[] = { post_vs, check_le1, NULL };  static	v_check	  posts_th[] = { check_ge2, check_le5, post_TH, NULL };  static	v_check	  posts_uc[] = { post_UC, NULL }; +static	v_check	  posts_ur[] = { check_head1, check_part, NULL };  static	v_check	  pres_sec[] = { pre_sec, NULL };  static	const struct man_valid man_valids[MAN_MAX] = { @@ -88,7 +93,7 @@ static	const struct man_valid man_valids[MAN_MAX] = {  	{ NULL, posts_par }, /* LP */  	{ NULL, posts_par }, /* PP */  	{ NULL, posts_par }, /* P */ -	{ NULL, NULL }, /* IP */ +	{ NULL, posts_ip }, /* IP */  	{ NULL, NULL }, /* HP */  	{ NULL, NULL }, /* SM */  	{ NULL, NULL }, /* SB */ @@ -109,16 +114,20 @@ static	const struct man_valid man_valids[MAN_MAX] = {  	{ NULL, posts_part }, /* RS */  	{ NULL, NULL }, /* DT */  	{ NULL, posts_uc }, /* UC */ -	{ NULL, NULL }, /* PD */ +	{ NULL, posts_le1 }, /* PD */  	{ NULL, posts_at }, /* AT */  	{ NULL, NULL }, /* in */  	{ NULL, posts_ft }, /* ft */  	{ NULL, posts_eq2 }, /* OP */ +	{ NULL, posts_nf }, /* EX */ +	{ NULL, posts_fi }, /* EE */ +	{ NULL, posts_ur }, /* UR */ +	{ NULL, NULL }, /* UE */  };  int -man_valid_pre(struct man *m, struct man_node *n) +man_valid_pre(struct man *man, struct man_node *n)  {  	v_check		*cp; @@ -138,27 +147,27 @@ man_valid_pre(struct man *m, struct man_node *n)  	if (NULL == (cp = man_valids[n->tok].pres))  		return(1);  	for ( ; *cp; cp++) -		if ( ! (*cp)(m, n))  +		if ( ! (*cp)(man, n))   			return(0);  	return(1);  }  int -man_valid_post(struct man *m) +man_valid_post(struct man *man)  {  	v_check		*cp; -	if (MAN_VALID & m->last->flags) +	if (MAN_VALID & man->last->flags)  		return(1); -	m->last->flags |= MAN_VALID; +	man->last->flags |= MAN_VALID; -	switch (m->last->type) { +	switch (man->last->type) {  	case (MAN_TEXT):  -		check_text(m, m->last); +		check_text(man, man->last);  		return(1);  	case (MAN_ROOT): -		return(check_root(m, m->last)); +		return(check_root(man, man->last));  	case (MAN_EQN):  		/* FALLTHROUGH */  	case (MAN_TBL): @@ -167,10 +176,10 @@ man_valid_post(struct man *m)  		break;  	} -	if (NULL == (cp = man_valids[m->last->tok].posts)) +	if (NULL == (cp = man_valids[man->last->tok].posts))  		return(1);  	for ( ; *cp; cp++) -		if ( ! (*cp)(m, m->last)) +		if ( ! (*cp)(man, man->last))  			return(0);  	return(1); @@ -181,29 +190,29 @@ static int  check_root(CHKARGS)   { -	if (MAN_BLINE & m->flags) -		man_nmsg(m, n, MANDOCERR_SCOPEEXIT); -	else if (MAN_ELINE & m->flags) -		man_nmsg(m, n, MANDOCERR_SCOPEEXIT); +	if (MAN_BLINE & man->flags) +		man_nmsg(man, n, MANDOCERR_SCOPEEXIT); +	else if (MAN_ELINE & man->flags) +		man_nmsg(man, n, MANDOCERR_SCOPEEXIT); -	m->flags &= ~MAN_BLINE; -	m->flags &= ~MAN_ELINE; +	man->flags &= ~MAN_BLINE; +	man->flags &= ~MAN_ELINE; -	if (NULL == m->first->child) { -		man_nmsg(m, n, MANDOCERR_NODOCBODY); +	if (NULL == man->first->child) { +		man_nmsg(man, n, MANDOCERR_NODOCBODY);  		return(0); -	} else if (NULL == m->meta.title) { -		man_nmsg(m, n, MANDOCERR_NOTITLE); +	} else if (NULL == man->meta.title) { +		man_nmsg(man, n, MANDOCERR_NOTITLE);  		/*  		 * If a title hasn't been set, do so now (by  		 * implication, date and section also aren't set).  		 */ -	        m->meta.title = mandoc_strdup("unknown"); -		m->meta.msec = mandoc_strdup("1"); -		m->meta.date = mandoc_normdate -			(m->parse, NULL, n->line, n->pos); +	        man->meta.title = mandoc_strdup("unknown"); +		man->meta.msec = mandoc_strdup("1"); +		man->meta.date = mandoc_normdate +			(man->parse, NULL, n->line, n->pos);  	}  	return(1); @@ -214,12 +223,12 @@ check_text(CHKARGS)  {  	char		*cp, *p; -	if (MAN_LITERAL & m->flags) +	if (MAN_LITERAL & man->flags)  		return;  	cp = n->string;  	for (p = cp; NULL != (p = strchr(p, '\t')); p++) -		man_pmsg(m, n->line, (int)(p - cp), MANDOCERR_BADTAB); +		man_pmsg(man, n->line, (int)(p - cp), MANDOCERR_BADTAB);  }  #define	INEQ_DEFINE(x, ineq, name) \ @@ -228,7 +237,7 @@ check_##name(CHKARGS) \  { \  	if (n->nchild ineq (x)) \  		return(1); \ -	mandoc_vmsg(MANDOCERR_ARGCOUNT, m->parse, n->line, n->pos, \ +	mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line, n->pos, \  			"line arguments %s %d (have %d)", \  			#ineq, (x), n->nchild); \  	return(1); \ @@ -241,6 +250,17 @@ INEQ_DEFINE(2, >=, ge2)  INEQ_DEFINE(5, <=, le5)  static int +check_head1(CHKARGS) +{ + +	if (MAN_HEAD == n->type && 1 != n->nchild) +		mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line, +		    n->pos, "line arguments eq 1 (have %d)", n->nchild); + +	return(1); +} + +static int  post_ft(CHKARGS)  {  	char	*cp; @@ -282,14 +302,14 @@ post_ft(CHKARGS)  	if (0 == ok) {  		mandoc_vmsg -			(MANDOCERR_BADFONT, m->parse, +			(MANDOCERR_BADFONT, man->parse,  			 n->line, n->pos, "%s", cp);  		*cp = '\0';  	}  	if (1 < n->nchild)  		mandoc_vmsg -			(MANDOCERR_ARGCOUNT, m->parse, n->line,  +			(MANDOCERR_ARGCOUNT, man->parse, n->line,   			 n->pos, "want one child (have %d)",   			 n->nchild); @@ -301,7 +321,7 @@ pre_sec(CHKARGS)  {  	if (MAN_BLOCK == n->type) -		m->flags &= ~MAN_LITERAL; +		man->flags &= ~MAN_LITERAL;  	return(1);  } @@ -312,7 +332,7 @@ post_sec(CHKARGS)  	if ( ! (MAN_HEAD == n->type && 0 == n->nchild))   		return(1); -	man_nmsg(m, n, MANDOCERR_SYNTARGCOUNT); +	man_nmsg(man, n, MANDOCERR_SYNTARGCOUNT);  	return(0);  } @@ -321,7 +341,7 @@ check_part(CHKARGS)  {  	if (MAN_BODY == n->type && 0 == n->nchild) -		mandoc_msg(MANDOCERR_ARGCWARN, m->parse, n->line,  +		mandoc_msg(MANDOCERR_ARGCWARN, man->parse, n->line,   				n->pos, "want children (have none)");  	return(1); @@ -335,15 +355,15 @@ check_par(CHKARGS)  	switch (n->type) {  	case (MAN_BLOCK):  		if (0 == n->body->nchild) -			man_node_delete(m, n); +			man_node_delete(man, n);  		break;  	case (MAN_BODY):  		if (0 == n->nchild) -			man_nmsg(m, n, MANDOCERR_IGNPAR); +			man_nmsg(man, n, MANDOCERR_IGNPAR);  		break;  	case (MAN_HEAD):  		if (n->nchild) -			man_nmsg(m, n, MANDOCERR_ARGSLOST); +			man_nmsg(man, n, MANDOCERR_ARGSLOST);  		break;  	default:  		break; @@ -352,6 +372,24 @@ check_par(CHKARGS)  	return(1);  } +static int +post_IP(CHKARGS) +{ + +	switch (n->type) { +	case (MAN_BLOCK): +		if (0 == n->head->nchild && 0 == n->body->nchild) +			man_node_delete(man, n); +		break; +	case (MAN_BODY): +		if (0 == n->parent->head->nchild && 0 == n->nchild) +			man_nmsg(man, n, MANDOCERR_IGNPAR); +		break; +	default: +		break; +	} +	return(1); +}  static int  post_TH(CHKARGS) @@ -359,21 +397,16 @@ post_TH(CHKARGS)  	const char	*p;  	int		 line, pos; -	if (m->meta.title) -		free(m->meta.title); -	if (m->meta.vol) -		free(m->meta.vol); -	if (m->meta.source) -		free(m->meta.source); -	if (m->meta.msec) -		free(m->meta.msec); -	if (m->meta.date) -		free(m->meta.date); +	free(man->meta.title); +	free(man->meta.vol); +	free(man->meta.source); +	free(man->meta.msec); +	free(man->meta.date);  	line = n->line;  	pos = n->pos; -	m->meta.title = m->meta.vol = m->meta.date = -		m->meta.msec = m->meta.source = NULL; +	man->meta.title = man->meta.vol = man->meta.date = +		man->meta.msec = man->meta.source = NULL;  	/* ->TITLE<- MSEC DATE SOURCE VOL */ @@ -383,22 +416,22 @@ post_TH(CHKARGS)  			/* Only warn about this once... */  			if (isalpha((unsigned char)*p) &&   					! isupper((unsigned char)*p)) { -				man_nmsg(m, n, MANDOCERR_UPPERCASE); +				man_nmsg(man, n, MANDOCERR_UPPERCASE);  				break;  			}  		} -		m->meta.title = mandoc_strdup(n->string); +		man->meta.title = mandoc_strdup(n->string);  	} else -		m->meta.title = mandoc_strdup(""); +		man->meta.title = mandoc_strdup("");  	/* TITLE ->MSEC<- DATE SOURCE VOL */  	if (n)  		n = n->next;  	if (n && n->string) -		m->meta.msec = mandoc_strdup(n->string); +		man->meta.msec = mandoc_strdup(n->string);  	else -		m->meta.msec = mandoc_strdup(""); +		man->meta.msec = mandoc_strdup("");  	/* TITLE MSEC ->DATE<- SOURCE VOL */ @@ -406,30 +439,30 @@ post_TH(CHKARGS)  		n = n->next;  	if (n && n->string && '\0' != n->string[0]) {  		pos = n->pos; -		m->meta.date = mandoc_normdate -		    (m->parse, n->string, line, pos); +		man->meta.date = mandoc_normdate +		    (man->parse, n->string, line, pos);  	} else -		m->meta.date = mandoc_strdup(""); +		man->meta.date = mandoc_strdup("");  	/* TITLE MSEC DATE ->SOURCE<- VOL */  	if (n && (n = n->next)) -		m->meta.source = mandoc_strdup(n->string); +		man->meta.source = mandoc_strdup(n->string);  	/* TITLE MSEC DATE SOURCE ->VOL<- */  	/* If missing, use the default VOL name for MSEC. */  	if (n && (n = n->next)) -		m->meta.vol = mandoc_strdup(n->string); -	else if ('\0' != m->meta.msec[0] && -	    (NULL != (p = mandoc_a2msec(m->meta.msec)))) -		m->meta.vol = mandoc_strdup(p); +		man->meta.vol = mandoc_strdup(n->string); +	else if ('\0' != man->meta.msec[0] && +	    (NULL != (p = mandoc_a2msec(man->meta.msec)))) +		man->meta.vol = mandoc_strdup(p);  	/*  	 * Remove the `TH' node after we've processed it for our  	 * meta-data.  	 */ -	man_node_delete(m, m->last); +	man_node_delete(man, man->last);  	return(1);  } @@ -437,10 +470,10 @@ static int  post_nf(CHKARGS)  { -	if (MAN_LITERAL & m->flags) -		man_nmsg(m, n, MANDOCERR_SCOPEREP); +	if (MAN_LITERAL & man->flags) +		man_nmsg(man, n, MANDOCERR_SCOPEREP); -	m->flags |= MAN_LITERAL; +	man->flags |= MAN_LITERAL;  	return(1);  } @@ -448,10 +481,10 @@ static int  post_fi(CHKARGS)  { -	if ( ! (MAN_LITERAL & m->flags)) -		man_nmsg(m, n, MANDOCERR_WNOSCOPE); +	if ( ! (MAN_LITERAL & man->flags)) +		man_nmsg(man, n, MANDOCERR_WNOSCOPE); -	m->flags &= ~MAN_LITERAL; +	man->flags &= ~MAN_LITERAL;  	return(1);  } @@ -488,10 +521,8 @@ post_UC(CHKARGS)  			p = bsd_versions[0];  	} -	if (m->meta.source) -		free(m->meta.source); - -	m->meta.source = mandoc_strdup(p); +	free(man->meta.source); +	man->meta.source = mandoc_strdup(p);  	return(1);  } @@ -528,10 +559,8 @@ post_AT(CHKARGS)  			p = unix_versions[0];  	} -	if (m->meta.source) -		free(m->meta.source); - -	m->meta.source = mandoc_strdup(p); +	free(man->meta.source); +	man->meta.source = mandoc_strdup(p);  	return(1);  } @@ -539,12 +568,25 @@ static int  post_vs(CHKARGS)  { -	/*  -	 * Don't warn about this because it occurs in pod2man and would -	 * cause considerable (unfixable) warnage. -	 */ -	if (NULL == n->prev && MAN_ROOT == n->parent->type) -		man_node_delete(m, n); +	if (NULL != n->prev) +		return(1); + +	switch (n->parent->tok) { +	case (MAN_SH): +		/* FALLTHROUGH */ +	case (MAN_SS): +		man_nmsg(man, n, MANDOCERR_IGNPAR); +		/* FALLTHROUGH */ +	case (MAN_MAX): +		/*  +		 * Don't warn about this because it occurs in pod2man +		 * and would cause considerable (unfixable) warnage. +		 */ +		man_node_delete(man, n); +		break; +	default: +		break; +	}  	return(1);  }  | 
