Hi, Stuart Henderson wrote on Mon, Sep 04, 2023 at 11:07:52AM +0100: > On 2023/09/04 11:05, Stefan Hagen wrote:
>> $ man 1 autoconf >> There is more than one version of this manpage available (show with -w). > oh that's a decent alternative. Indeed, in particular in combination with the other idea of only giving the heads-up for clashes *with the same section number*. That reduces the waste of screen real estate to a single line, even that is only printed when it really matters, and there are only a handful of cases in the base system: genuine clashes in base: ld(1) - ld.1 and ld.bfd.1 perldelta(1) - perldelta.1 and perl5361delta.1 documentation bugs in base, same function documented twice: CRYPTO_EX_dup(3), pem_password_cb(3), tls_reset(3) See below for an improved patch, resulting in: $ man FvwmPager Multiple versions of FvwmPager(1) are available; list them with -w. FvwmPager(1) General Commands Manual FvwmPager(1) NAME FvwmPager - the FVWM Pager module [...] $ man autoconf AUTOCONF(4) Device Drivers Manual (amd64) AUTOCONF(4) NAME autoconf - diagnostics from the autoconfiguration code [...] $ man 1 autoconf Multiple versions of autoconf(1) are available; list them with -w. AUTOCONF(1) FSF AUTOCONF(1) NAME autoconf - Generate configuration scripts [...] $ man CRYPTO_EX_dup Multiple versions of CRYPTO_EX_dup(3) are available; list them with -w. CRYPTO_SET_EX_DATA(3) Library Functions Manual CRYPTO_SET_EX_DATA(3) NAME CRYPTO_EX_new, CRYPTO_EX_free, CRYPTO_EX_dup, CRYPTO_get_ex_new_index, CRYPTO_set_ex_data, CRYPTO_get_ex_data, CRYPTO_free_ex_data, CRYPTO_new_ex_data - functions supporting application-specific data [...] Lightly tested so far. >> Then you could stop after the second match in the same section. Actually, i think that's not even worth bothering. The main performance penalty is that, even when one page is found in the base system, parsing the Xenocara and ports databases is still needed - but on modern hardware, the delay is only a few milliseconds. It almost never happens that there are two pages with matching names and section numbers in the base system, so the optimization would almost never trigger. Consequently, it makes more sense to drop the optimization outright. Yours, Ingo Index: main.c =================================================================== RCS file: /cvs/src/usr.bin/mandoc/main.c,v retrieving revision 1.263 diff -u -p -r1.263 main.c --- main.c 4 Sep 2023 13:08:11 -0000 1.263 +++ main.c 4 Sep 2023 14:36:19 -0000 @@ -500,16 +500,23 @@ main(int argc, char *argv[]) continue; } - /* Search for the best section. */ + /* + * Prioritize when displaying only one page. + * Penalty 2000 for a wrong filename extension + * 1000 for a wrong directory name + * 10 per manpath index + * 1 per section number index + */ - best_prio = 40; + best_prio = INT_MAX; for (ib = i = 0; i < resnsz; i++) { sec = resn[i].file + strlen(conf.manpath.paths[resn[i].ipath]); sec += strcspn(sec, "123456789"); if (sec[0] == '\0') continue; /* No section at all. */ - prio = sec_prios[sec[0] - '1']; + prio = resn[i].ipath * 10 + + sec_prios[sec[0] - '1']; if (search.sec != NULL) { ssz = strlen(search.sec); if (strncmp(sec, search.sec, ssz) == 0) @@ -517,7 +524,7 @@ main(int argc, char *argv[]) } else sec++; /* Prefer without suffix. */ if (*sec != '/') - prio += 10; /* Wrong dir name. */ + prio += 1000; /* Wrong dir name. */ if (search.sec != NULL) { ep = strchr(sec, '\0'); if (ep - sec > 3 && @@ -525,14 +532,23 @@ main(int argc, char *argv[]) ep -= 3; if ((size_t)(ep - sec) < ssz + 3 || strncmp(ep - ssz, search.sec, - ssz) != 0) /* Wrong file */ - prio += 20; /* extension. */ + ssz) != 0) /* Wrong file */ + prio += 2000; /* extension. */ } if (prio >= best_prio) continue; best_prio = prio; ib = i; } + for (i = 0; i < resnsz; i++) { + if (i != ib && resn[i].sec == resn[ib].sec) { + mandoc_asprintf(&resn[ib].seealso, + "Multiple versions of %s(%d) are " + "available; list them with -w.\n", + *argv, resn[ib].sec); + break; + } + } res = mandoc_reallocarray(res, ressz + 1, sizeof(*res)); memcpy(res + ressz++, resn + ib, sizeof(*resn)); @@ -706,6 +722,7 @@ fs_append(char **file, size_t filesz, in page->file = copy ? mandoc_strdup(*file) : *file; page->names = NULL; page->output = NULL; + page->seealso = NULL; page->bits = NAME_FILE & NAME_MASK; page->ipath = ipath; page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10; @@ -897,6 +914,8 @@ process_onefile(struct mparse *mp, struc outdata_alloc(outst, &conf->output); terminal_sepline(outst->outdata); } + if (resp->seealso != NULL && outst->outtype <= OUTT_TREE) + printf("%s\n", resp->seealso); if (resp->form == FORM_SRC) parse(mp, fd, resp->file, outst, conf); Index: mansearch.c =================================================================== RCS file: /cvs/src/usr.bin/mandoc/mansearch.c,v retrieving revision 1.67 diff -u -p -r1.67 mansearch.c --- mansearch.c 26 Dec 2022 19:16:02 -0000 1.67 +++ mansearch.c 4 Sep 2023 14:36:19 -0000 @@ -196,6 +196,7 @@ mansearch(const struct mansearch *search } mpage->names = buildnames(page); mpage->output = buildoutput(outkey, page); + mpage->seealso = NULL; mpage->bits = search->firstmatch ? rp->bits : 0; mpage->ipath = i; mpage->sec = *page->sect - '0'; @@ -208,14 +209,6 @@ mansearch(const struct mansearch *search ohash_delete(htab); free(htab); dbm_close(); - - /* - * In man(1) mode, prefer matches in earlier trees - * over matches in later trees. - */ - - if (cur && search->firstmatch) - break; } if (res != NULL && cur > 1) qsort(*res, cur, sizeof(struct manpage), manpage_compare); @@ -394,6 +387,7 @@ mansearch_free(struct manpage *res, size free(res[i].file); free(res[i].names); free(res[i].output); + free(res[i].seealso); } free(res); } Index: mansearch.h =================================================================== RCS file: /cvs/src/usr.bin/mandoc/mansearch.h,v retrieving revision 1.24 diff -u -p -r1.24 mansearch.h --- mansearch.h 30 Apr 2019 18:48:26 -0000 1.24 +++ mansearch.h 4 Sep 2023 14:36:19 -0000 @@ -92,6 +92,7 @@ struct manpage { char *file; /* to be prefixed by manpath */ char *names; /* a list of names with sections */ char *output; /* user-defined additional output */ + char *seealso; /* preamble in OUTMODE_ONE */ uint64_t bits; /* name type mask */ size_t ipath; /* number of the manpath */ int sec; /* section number, 10 means invalid */