=================================================================== RCS file: /cvs/mandoc/main.c,v retrieving revision 1.209 retrieving revision 1.215 diff -u -p -r1.209 -r1.215 --- mandoc/main.c 2014/12/21 14:49:28 1.209 +++ mandoc/main.c 2015/01/15 04:26:39 1.215 @@ -1,7 +1,7 @@ -/* $Id: main.c,v 1.209 2014/12/21 14:49:28 schwarze Exp $ */ +/* $Id: main.c,v 1.215 2015/01/15 04:26:39 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons - * Copyright (c) 2010, 2011, 2012, 2014 Ingo Schwarze + * Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze * Copyright (c) 2010 Joerg Sonnenberger * * Permission to use, copy, modify, and distribute this software for any @@ -82,6 +82,15 @@ struct curparse { char outopts[BUFSIZ]; /* buf of output opts */ }; +#if HAVE_SQLITE3 +static int fs_lookup(const struct manpaths *, + size_t ipath, const char *, + const char *, const char *, + struct manpage **, size_t *); +static void fs_search(const struct mansearch *, + const struct manpaths *, int, char**, + struct manpage **, size_t *); +#endif static int koptions(int *, char *); #if HAVE_SQLITE3 int mandocdb(int, char**); @@ -122,7 +131,7 @@ main(int argc, char *argv[]) int prio, best_prio, synopsis_only; char sec; #endif - enum mandoclevel rc; + enum mandoclevel rc, rctmp; enum outmode outmode; int fd; int show_usage; @@ -167,7 +176,7 @@ main(int argc, char *argv[]) memset(&curp, 0, sizeof(struct curparse)); curp.outtype = OUTT_LOCALE; - curp.wlevel = MANDOCLEVEL_FATAL; + curp.wlevel = MANDOCLEVEL_BADARG; options = MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1; defos = NULL; @@ -310,7 +319,8 @@ main(int argc, char *argv[]) argv = help_argv; argc = 1; } - } else if (((uc = argv[0]) != NULL) && + } else if (argc > 1 && + ((uc = argv[0]) != NULL) && ((isdigit(uc[0]) && (uc[1] == '\0' || (isalpha(uc[1]) && uc[2] == '\0'))) || (uc[0] == 'n' && uc[1] == '\0'))) { @@ -339,12 +349,11 @@ main(int argc, char *argv[]) mansearch_setup(1); if( ! mansearch(&search, &paths, argc, argv, &res, &sz)) usage(search.argmode); - resp = res; + if (sz == 0 && search.argmode == ARG_NAME) + fs_search(&search, &paths, argc, argv, &res, &sz); + if (sz == 0) { - if (search.argmode == ARG_NAME) - fprintf(stderr, "%s: No entry for %s " - "in the manual.\n", progname, argv[0]); rc = MANDOCLEVEL_BADARG; goto out; } @@ -363,6 +372,7 @@ main(int argc, char *argv[]) /* Iterate all matching manuals. */ + resp = res; for (i = 0; i < sz; i++) { if (outmode == OUTMODE_FLN) puts(res[i].file); @@ -404,9 +414,6 @@ main(int argc, char *argv[]) if (search.argmode == ARG_FILE && ! moptions(&options, auxpaths)) return((int)MANDOCLEVEL_BADARG); - if (use_pager && isatty(STDOUT_FILENO)) - spawn_pager(); - curp.mchars = mchars_alloc(); curp.mp = mparse_alloc(options, curp.wlevel, mmsg, curp.mchars, defos); @@ -417,37 +424,62 @@ main(int argc, char *argv[]) if (OUTT_MAN == curp.outtype) mparse_keep(curp.mp); - if (argc == 0) + if (argc == 0) { + if (use_pager && isatty(STDOUT_FILENO)) + spawn_pager(); parse(&curp, STDIN_FILENO, "", &rc); + } while (argc) { + rctmp = mparse_open(curp.mp, &fd, #if HAVE_SQLITE3 - if (resp != NULL) { - rc = mparse_open(curp.mp, &fd, resp->file); - if (fd == -1) - /* nothing */; + resp != NULL ? resp->file : +#endif + *argv); + if (rc < rctmp) + rc = rctmp; + + if (fd != -1) { + if (use_pager && isatty(STDOUT_FILENO)) + spawn_pager(); + use_pager = 0; + +#if HAVE_SQLITE3 + if (resp == NULL) +#endif + parse(&curp, fd, *argv, &rc); +#if HAVE_SQLITE3 else if (resp->form & FORM_SRC) { /* For .so only; ignore failure. */ chdir(paths.paths[resp->ipath]); parse(&curp, fd, resp->file, &rc); - } else - rc = passthrough(resp->file, fd, + } else { + rctmp = passthrough(resp->file, fd, synopsis_only); - resp++; - } else + if (rc < rctmp) + rc = rctmp; + } #endif - { - rc = mparse_open(curp.mp, &fd, *argv++); - if (fd != -1) - parse(&curp, fd, argv[-1], &rc); - } - if (mparse_wait(curp.mp) != MANDOCLEVEL_OK) - rc = MANDOCLEVEL_SYSERR; + rctmp = mparse_wait(curp.mp); + if (rc < rctmp) + rc = rctmp; + if (argc > 1 && curp.outtype <= OUTT_UTF8) + ascii_sepline(curp.outdata); + } + if (MANDOCLEVEL_OK != rc && curp.wstop) break; - argc--; + +#if HAVE_SQLITE3 + if (resp != NULL) + resp++; + else +#endif + argv++; + if (--argc) + mparse_reset(curp.mp); } if (curp.outfree) @@ -508,7 +540,99 @@ usage(enum argmode argmode) exit((int)MANDOCLEVEL_BADARG); } +#if HAVE_SQLITE3 +static int +fs_lookup(const struct manpaths *paths, size_t ipath, + const char *sec, const char *arch, const char *name, + struct manpage **res, size_t *ressz) +{ + struct manpage *page; + char *file; + int form; + + mandoc_asprintf(&file, "%s/man%s/%s.%s", + paths->paths[ipath], sec, name, sec); + if (access(file, R_OK) != -1) { + form = FORM_SRC; + goto found; + } + free(file); + + mandoc_asprintf(&file, "%s/cat%s/%s.0", + paths->paths[ipath], sec, name); + if (access(file, R_OK) != -1) { + form = FORM_CAT; + goto found; + } + free(file); + + if (arch != NULL) { + mandoc_asprintf(&file, "%s/man%s/%s/%s.%s", + paths->paths[ipath], sec, arch, name, sec); + if (access(file, R_OK) != -1) { + form = FORM_SRC; + goto found; + } + free(file); + } + return(0); + +found: + fprintf(stderr, "%s: outdated mandoc.db lacks %s(%s) entry,\n" + " consider running # makewhatis %s\n", + progname, name, sec, paths->paths[ipath]); + + *res = mandoc_reallocarray(*res, ++*ressz, sizeof(struct manpage)); + page = *res + (*ressz - 1); + page->file = file; + page->names = NULL; + page->output = NULL; + page->ipath = ipath; + page->bits = NAME_FILE & NAME_MASK; + page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10; + page->form = form; + return(1); +} + static void +fs_search(const struct mansearch *cfg, const struct manpaths *paths, + int argc, char **argv, struct manpage **res, size_t *ressz) +{ + const char *const sections[] = + {"1", "8", "6", "2", "3", "3p", "5", "7", "4", "9"}; + const size_t nsec = sizeof(sections)/sizeof(sections[0]); + + size_t ipath, isec, lastsz; + + assert(cfg->argmode == ARG_NAME); + + *res = NULL; + *ressz = lastsz = 0; + while (argc) { + for (ipath = 0; ipath < paths->sz; ipath++) { + if (cfg->sec != NULL) { + if (fs_lookup(paths, ipath, cfg->sec, + cfg->arch, *argv, res, ressz) && + cfg->firstmatch) + return; + } else for (isec = 0; isec < nsec; isec++) + if (fs_lookup(paths, ipath, sections[isec], + cfg->arch, *argv, res, ressz) && + cfg->firstmatch) + return; + } + if (*ressz == lastsz) + fprintf(stderr, + "%s: No entry for %s in the manual.\n", + progname, *argv); + lastsz = *ressz; + argv++; + argc--; + } +} +#endif + +static void parse(struct curparse *curp, int fd, const char *file, enum mandoclevel *level) { @@ -523,11 +647,6 @@ parse(struct curparse *curp, int fd, const char *file, rc = mparse_readfd(curp->mp, fd, file); - /* Stop immediately if the parse has failed. */ - - if (MANDOCLEVEL_FATAL <= rc) - goto cleanup; - /* * With -Wstop and warnings or errors of at least the requested * level, do not produce output. @@ -613,10 +732,7 @@ parse(struct curparse *curp, int fd, const char *file, if (mdoc && curp->outmdoc) (*curp->outmdoc)(curp->outdata, mdoc); - cleanup: - - mparse_reset(curp->mp); - +cleanup: if (*level < rc) *level = rc; } @@ -635,6 +751,8 @@ passthrough(const char *file, int fd, int synopsis_onl ssize_t nw; int print; + fflush(stdout); + if ((stream = fdopen(fd, "r")) == NULL) { close(fd); syscall = "fdopen"; @@ -790,7 +908,7 @@ woptions(struct curparse *curp, char *arg) curp->wlevel = MANDOCLEVEL_ERROR; break; case 4: - curp->wlevel = MANDOCLEVEL_FATAL; + curp->wlevel = MANDOCLEVEL_BADARG; break; default: fprintf(stderr, "%s: -W %s: Bad argument\n",