From e5501471e172d4f6de0c3e4afca1fffb5cc93ea7 Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Sun, 2 Jul 2017 15:31:59 +0000 Subject: [PATCH] add warning "cross reference to self"; inspired by mdoclint --- main.c | 10 ++++++---- mandoc.1 | 22 ++++++++++++++++++++-- mandoc.h | 3 ++- mandoc_xr.c | 21 ++++++++++++++------- mandoc_xr.h | 6 +++--- mdoc_validate.c | 16 +++++++++++++--- read.c | 3 ++- 7 files changed, 60 insertions(+), 21 deletions(-) diff --git a/main.c b/main.c index df0cdabe..2c289e4a 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.296 2017/07/01 12:54:07 schwarze Exp $ */ +/* $Id: main.c,v 1.297 2017/07/02 15:31:59 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons * Copyright (c) 2010-2012, 2014-2017 Ingo Schwarze @@ -763,8 +763,7 @@ parse(struct curparse *curp, int fd, const char *file) if (man == NULL) return; - if (curp->mmin < MANDOCERR_STYLE) - mandoc_xr_reset(); + mandoc_xr_reset(); if (man->macroset == MACROSET_MDOC) { if (curp->outtype != OUTT_TREE || !curp->outopts->noval) mdoc_validate(man); @@ -816,7 +815,8 @@ parse(struct curparse *curp, int fd, const char *file) break; } } - check_xr(file); + if (curp->mmin < MANDOCERR_STYLE) + check_xr(file); mparse_updaterc(curp->mp, &rc); } @@ -833,6 +833,8 @@ check_xr(const char *file) manpath_base(&paths); for (xr = mandoc_xr_get(); xr != NULL; xr = xr->next) { + if (xr->line == -1) + continue; search.arch = NULL; search.sec = xr->sec; search.outkey = NULL; diff --git a/mandoc.1 b/mandoc.1 index ff2046e1..4189002c 100644 --- a/mandoc.1 +++ b/mandoc.1 @@ -1,4 +1,4 @@ -.\" $Id: mandoc.1,v 1.210 2017/07/01 09:47:30 schwarze Exp $ +.\" $Id: mandoc.1,v 1.211 2017/07/02 15:31:59 schwarze Exp $ .\" .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons .\" Copyright (c) 2012, 2014-2017 Ingo Schwarze @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: July 1 2017 $ +.Dd $Mdocdate: July 2 2017 $ .Dt MANDOC 1 .Os .Sh NAME @@ -1097,6 +1097,24 @@ The same standard section title occurs more than once. .Pq mdoc A standard section header occurs in a section of the manual where it normally isn't useful. +.It Sy "cross reference to self" +.Pq mdoc +An +.Ic \&Xr +macro refers to a name and section matching the section of the present +manual page and a name mentioned in an +.Ic \&Nm +macro in the NAME or SYNOPSIS section, or in an +.Ic \&Fn +or +.Ic \&Fo +macro in the SYNOPSIS. +Consider using +.Ic \&Nm +or +.Ic \&Fn +instead of +.Ic \&Xr . .It Sy "unusual Xr order" .Pq mdoc In the SEE ALSO section, an diff --git a/mandoc.h b/mandoc.h index cb263002..41bb2aa6 100644 --- a/mandoc.h +++ b/mandoc.h @@ -1,4 +1,4 @@ -/* $Id: mandoc.h,v 1.238 2017/07/01 09:47:30 schwarze Exp $ */ +/* $Id: mandoc.h,v 1.239 2017/07/02 15:31:59 schwarze Exp $ */ /* * Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons * Copyright (c) 2010-2017 Ingo Schwarze @@ -97,6 +97,7 @@ enum mandocerr { MANDOCERR_SEC_ORDER, /* sections out of conventional order: Sh title */ MANDOCERR_SEC_REP, /* duplicate section title: Sh title */ MANDOCERR_SEC_MSEC, /* unexpected section: Sh title for ... only */ + MANDOCERR_XR_SELF, /* cross reference to self: Xr name sec */ MANDOCERR_XR_ORDER, /* unusual Xr order: ... after ... */ MANDOCERR_XR_PUNCT, /* unusual Xr punctuation: ... after ... */ MANDOCERR_AN_MISSING, /* AUTHORS section without An macro */ diff --git a/mandoc_xr.c b/mandoc_xr.c index 22853616..f6cb46d4 100644 --- a/mandoc_xr.c +++ b/mandoc_xr.c @@ -1,4 +1,4 @@ -/* $Id: mandoc_xr.c,v 1.1 2017/07/01 09:47:30 schwarze Exp $ */ +/* $Id: mandoc_xr.c,v 1.2 2017/07/02 15:31:59 schwarze Exp $ */ /* * Copyright (c) 2017 Ingo Schwarze * @@ -59,17 +59,18 @@ mandoc_xr_reset(void) xr_first = xr_last = NULL; } -void +int mandoc_xr_add(const char *sec, const char *name, int line, int pos) { - struct mandoc_xr *xr; + struct mandoc_xr *xr, *oxr; const char *pend; size_t ssz, nsz, tsz; unsigned int slot; + int ret; uint32_t hv; if (xr_hash == NULL) - return; + return 0; ssz = strlen(sec) + 1; nsz = strlen(name) + 1; @@ -86,15 +87,21 @@ mandoc_xr_add(const char *sec, const char *name, int line, int pos) pend = xr->hashkey + tsz; hv = ohash_interval(xr->hashkey, &pend); slot = ohash_lookup_memory(xr_hash, xr->hashkey, tsz, hv); - if (ohash_find(xr_hash, slot) == NULL) { + if ((oxr = ohash_find(xr_hash, slot)) == NULL) { ohash_insert(xr_hash, slot, xr); if (xr_first == NULL) xr_first = xr; else xr_last->next = xr; xr_last = xr; - } else - free(xr); + return 0; + } + + ret = (oxr->line == -1) ^ (xr->line == -1); + if (xr->line == -1) + oxr->line = -1; + free(xr); + return ret; } struct mandoc_xr * diff --git a/mandoc_xr.h b/mandoc_xr.h index 3fe2f56d..bf82598d 100644 --- a/mandoc_xr.h +++ b/mandoc_xr.h @@ -1,4 +1,4 @@ -/* $Id: mandoc_xr.h,v 1.1 2017/07/01 09:47:30 schwarze Exp $ */ +/* $Id: mandoc_xr.h,v 1.2 2017/07/02 15:31:59 schwarze Exp $ */ /* * Copyright (c) 2017 Ingo Schwarze * @@ -19,12 +19,12 @@ struct mandoc_xr { struct mandoc_xr *next; char *sec; char *name; - int line; + int line; /* Or -1 for this page's own names. */ int pos; char hashkey[]; }; void mandoc_xr_reset(void); -void mandoc_xr_add(const char *, const char *, int, int); +int mandoc_xr_add(const char *, const char *, int, int); struct mandoc_xr *mandoc_xr_get(void); void mandoc_xr_free(void); diff --git a/mdoc_validate.c b/mdoc_validate.c index 6561976c..6391f684 100644 --- a/mdoc_validate.c +++ b/mdoc_validate.c @@ -1,4 +1,4 @@ -/* $Id: mdoc_validate.c,v 1.346 2017/07/01 09:47:30 schwarze Exp $ */ +/* $Id: mdoc_validate.c,v 1.347 2017/07/02 15:31:59 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons * Copyright (c) 2010-2017 Ingo Schwarze @@ -1104,6 +1104,8 @@ post_fname(POST_ARGS) if ( ! (cp[0] == '\0' || (cp[0] == '(' && cp[1] == '*'))) mandoc_msg(MANDOCERR_FN_PAREN, mdoc->parse, n->line, n->pos + pos, n->string); + if (n->sec == SEC_SYNOPSIS && mdoc->meta.msec != NULL) + mandoc_xr_add(mdoc->meta.msec, n->string, -1, -1); } static void @@ -1169,6 +1171,11 @@ post_nm(POST_ARGS) n = mdoc->last; + if ((n->sec == SEC_NAME || n->sec == SEC_SYNOPSIS) && + n->child != NULL && n->child->type == ROFFT_TEXT && + mdoc->meta.msec != NULL) + mandoc_xr_add(mdoc->meta.msec, n->child->string, -1, -1); + if (n->last != NULL && (n->last->tok == MDOC_Pp || n->last->tok == MDOC_Lp)) @@ -2339,8 +2346,11 @@ post_xr(POST_ARGS) n->line, n->pos, "Xr %s", nch->string); } else { assert(nch->next == n->last); - mandoc_xr_add(nch->next->string, nch->string, - nch->line, nch->pos); + if(mandoc_xr_add(nch->next->string, nch->string, + nch->line, nch->pos)) + mandoc_vmsg(MANDOCERR_XR_SELF, mdoc->parse, + nch->line, nch->pos, "Xr %s %s", + nch->string, nch->next->string); } post_delim(mdoc); } diff --git a/read.c b/read.c index 4e741edb..8fc671b0 100644 --- a/read.c +++ b/read.c @@ -1,4 +1,4 @@ -/* $Id: read.c,v 1.184 2017/07/01 09:47:30 schwarze Exp $ */ +/* $Id: read.c,v 1.185 2017/07/02 15:31:59 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010-2017 Ingo Schwarze @@ -139,6 +139,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = { "sections out of conventional order", "duplicate section title", "unexpected section", + "cross reference to self", "unusual Xr order", "unusual Xr punctuation", "AUTHORS section without An macro", -- 2.47.1