=================================================================== RCS file: /cvs/mandoc/mansearch.c,v retrieving revision 1.70 retrieving revision 1.75 diff -u -p -r1.70 -r1.75 --- mandoc/mansearch.c 2017/04/17 20:05:08 1.70 +++ mandoc/mansearch.c 2017/07/19 14:05:13 1.75 @@ -1,4 +1,4 @@ -/* $OpenBSD: mansearch.c,v 1.70 2017/04/17 20:05:08 schwarze Exp $ */ +/* $OpenBSD: mansearch.c,v 1.75 2017/07/19 14:05:13 schwarze Exp $ */ /* * Copyright (c) 2012 Kristaps Dzonsons * Copyright (c) 2013-2017 Ingo Schwarze @@ -104,7 +104,8 @@ mansearch(const struct mansearch *search, } cur = maxres = 0; - *res = NULL; + if (res != NULL) + *res = NULL; outkey = KEY_Nd; if (search->outkey != NULL) @@ -155,7 +156,8 @@ mansearch(const struct mansearch *search, chdir_status = 1; if (dbm_open(MANDOC_DB) == -1) { - warn("%s/%s", paths->paths[i], MANDOC_DB); + if (errno != ENOENT) + warn("%s/%s", paths->paths[i], MANDOC_DB); continue; } @@ -172,6 +174,10 @@ mansearch(const struct mansearch *search, lstmatch(search->arch, page->arch) == 0) continue; + if (res == NULL) { + cur = 1; + break; + } if (cur + 1 > maxres) { maxres += 1024; *res = mandoc_reallocarray(*res, @@ -203,12 +209,13 @@ mansearch(const struct mansearch *search, if (cur && search->firstmatch) break; } - qsort(*res, cur, sizeof(struct manpage), manpage_compare); + if (res != NULL) + qsort(*res, cur, sizeof(struct manpage), manpage_compare); if (chdir_status && getcwd_status && chdir(buf) == -1) warn("%s", buf); exprfree(e); *sz = cur; - return 1; + return res != NULL || cur; } /* @@ -387,13 +394,29 @@ static int manpage_compare(const void *vp1, const void *vp2) { const struct manpage *mp1, *mp2; + const char *cp1, *cp2; + size_t sz1, sz2; int diff; mp1 = vp1; mp2 = vp2; - return (diff = mp2->bits - mp1->bits) ? diff : - (diff = mp1->sec - mp2->sec) ? diff : - strcasecmp(mp1->names, mp2->names); + if ((diff = mp2->bits - mp1->bits) || + (diff = mp1->sec - mp2->sec)) + return diff; + + /* Fall back to alphabetic ordering of names. */ + sz1 = strcspn(mp1->names, "("); + sz2 = strcspn(mp2->names, "("); + if (sz1 < sz2) + sz1 = sz2; + if ((diff = strncasecmp(mp1->names, mp2->names, sz1))) + return diff; + + /* For identical names and sections, prefer arch-dependent. */ + cp1 = strchr(mp1->names + sz1, '/'); + cp2 = strchr(mp2->names + sz2, '/'); + return cp1 != NULL && cp2 != NULL ? strcasecmp(cp1, cp2) : + cp1 != NULL ? -1 : cp2 != NULL ? 1 : 0; } static char * @@ -516,6 +539,8 @@ buildoutput(size_t im, struct dbm_page *page) output = mandoc_malloc(sz); i = 0; lstcat(output, &i, input, " # "); + output[i++] = '\0'; + assert(i == sz); return output; } @@ -670,6 +695,12 @@ exprterm(const struct mansearch *search, int argc, cha return e; } + if (strcmp("-i", argv[*argi]) == 0 && *argi + 1 < argc) { + cs = 0; + ++*argi; + } else + cs = 1; + e = mandoc_calloc(1, sizeof(*e)); e->type = EXPR_TERM; e->bits = 0; @@ -688,7 +719,6 @@ exprterm(const struct mansearch *search, int argc, cha * If needed, request regular expression handling. */ - cs = 1; if (search->argmode == ARG_WORD) { e->bits = TYPE_Nm; e->match.type = DBM_REGEX;