=================================================================== RCS file: /cvs/mandoc/mandocdb.c,v retrieving revision 1.186 retrieving revision 1.220.2.12 diff -u -p -r1.186 -r1.220.2.12 --- mandoc/mandocdb.c 2015/03/13 00:19:41 1.186 +++ mandoc/mandocdb.c 2017/02/17 14:50:13 1.220.2.12 @@ -1,15 +1,16 @@ -/* $Id: mandocdb.c,v 1.186 2015/03/13 00:19:41 schwarze Exp $ */ +/* $Id: mandocdb.c,v 1.220.2.12 2017/02/17 14:50:13 schwarze Exp $ */ /* * Copyright (c) 2011, 2012 Kristaps Dzonsons - * Copyright (c) 2011-2015 Ingo Schwarze + * Copyright (c) 2011-2017 Ingo Schwarze + * Copyright (c) 2016 Ed Maste * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -23,6 +24,9 @@ #include #include +#if HAVE_ERR +#include +#endif #include #include #if HAVE_FTS @@ -30,8 +34,10 @@ #else #include "compat_fts.h" #endif -#include #include +#if HAVE_SANDBOX_INIT +#include +#endif #include #include #include @@ -39,18 +45,15 @@ #include #include -#if HAVE_OHASH -#include -#else -#include "compat_ohash.h" -#endif #include +#include "mandoc_aux.h" +#include "mandoc_ohash.h" +#include "mandoc.h" +#include "roff.h" #include "mdoc.h" #include "man.h" -#include "mandoc.h" -#include "mandoc_aux.h" -#include "manpath.h" +#include "manconf.h" #include "mansearch.h" extern int mansearch_keymax; @@ -101,6 +104,7 @@ struct mpage { char *arch; /* architecture from file content */ char *title; /* title from file content */ char *desc; /* description from file content */ + struct mpage *next; /* singly linked list */ struct mlink *mlinks; /* singly linked list */ int form; /* format from file content */ int name_head_done; @@ -129,14 +133,18 @@ enum stmt { STMT__MAX }; -typedef int (*mdoc_fp)(struct mpage *, const struct mdoc_meta *, - const struct mdoc_node *); +typedef int (*mdoc_fp)(struct mpage *, const struct roff_meta *, + const struct roff_node *); struct mdoc_handler { mdoc_fp fp; /* optional handler */ uint64_t mask; /* set unless handler returns 0 */ + int taboo; /* node flags that must not be set */ }; + +int mandocdb(int, char *[]); + static void dbclose(int); static void dbadd(struct mpage *); static void dbadd_mlink(const struct mlink *mlink); @@ -144,9 +152,11 @@ static void dbadd_mlink_name(const struct mlink *mlin static int dbopen(int); static void dbprune(void); static void filescan(const char *); -static void *hash_alloc(size_t, void *); -static void hash_free(void *, void *); -static void *hash_calloc(size_t, size_t, void *); +#if HAVE_FTS_COMPARE_CONST +static int fts_compare(const FTSENT *const *, const FTSENT *const *); +#else +static int fts_compare(const FTSENT **, const FTSENT **); +#endif static void mlink_add(struct mlink *, const struct stat *); static void mlink_check(struct mpage *, struct mlink *); static void mlink_free(struct mlink *); @@ -155,41 +165,41 @@ static void mpages_free(void); static void mpages_merge(struct mparse *); static void names_check(void); static void parse_cat(struct mpage *, int); -static void parse_man(struct mpage *, const struct man_meta *, - const struct man_node *); -static void parse_mdoc(struct mpage *, const struct mdoc_meta *, - const struct mdoc_node *); -static int parse_mdoc_body(struct mpage *, const struct mdoc_meta *, - const struct mdoc_node *); -static int parse_mdoc_head(struct mpage *, const struct mdoc_meta *, - const struct mdoc_node *); -static int parse_mdoc_Fd(struct mpage *, const struct mdoc_meta *, - const struct mdoc_node *); -static void parse_mdoc_fname(struct mpage *, const struct mdoc_node *); -static int parse_mdoc_Fn(struct mpage *, const struct mdoc_meta *, - const struct mdoc_node *); -static int parse_mdoc_Fo(struct mpage *, const struct mdoc_meta *, - const struct mdoc_node *); -static int parse_mdoc_Nd(struct mpage *, const struct mdoc_meta *, - const struct mdoc_node *); -static int parse_mdoc_Nm(struct mpage *, const struct mdoc_meta *, - const struct mdoc_node *); -static int parse_mdoc_Sh(struct mpage *, const struct mdoc_meta *, - const struct mdoc_node *); -static int parse_mdoc_Xr(struct mpage *, const struct mdoc_meta *, - const struct mdoc_node *); +static void parse_man(struct mpage *, const struct roff_meta *, + const struct roff_node *); +static void parse_mdoc(struct mpage *, const struct roff_meta *, + const struct roff_node *); +static int parse_mdoc_head(struct mpage *, const struct roff_meta *, + const struct roff_node *); +static int parse_mdoc_Fd(struct mpage *, const struct roff_meta *, + const struct roff_node *); +static void parse_mdoc_fname(struct mpage *, const struct roff_node *); +static int parse_mdoc_Fn(struct mpage *, const struct roff_meta *, + const struct roff_node *); +static int parse_mdoc_Fo(struct mpage *, const struct roff_meta *, + const struct roff_node *); +static int parse_mdoc_Nd(struct mpage *, const struct roff_meta *, + const struct roff_node *); +static int parse_mdoc_Nm(struct mpage *, const struct roff_meta *, + const struct roff_node *); +static int parse_mdoc_Sh(struct mpage *, const struct roff_meta *, + const struct roff_node *); +static int parse_mdoc_Va(struct mpage *, const struct roff_meta *, + const struct roff_node *); +static int parse_mdoc_Xr(struct mpage *, const struct roff_meta *, + const struct roff_node *); static void putkey(const struct mpage *, char *, uint64_t); static void putkeys(const struct mpage *, char *, size_t, uint64_t); static void putmdockey(const struct mpage *, - const struct mdoc_node *, uint64_t); + const struct roff_node *, uint64_t, int); static int render_string(char **, size_t *); -static void say(const char *, const char *, ...); +static void say(const char *, const char *, ...) + __attribute__((__format__ (__printf__, 2, 3))); static int set_basedir(const char *, int); static int treescan(void); static size_t utf8(unsigned int, char [7]); static char tempfilename[32]; -static char *progname; static int nodb; /* no database changes */ static int mparse_options; /* abort the parse early */ static int use_all; /* use all found files */ @@ -199,7 +209,7 @@ static int write_utf8; /* write UTF-8 output; else A static int exitcode; /* to be returned by main */ static enum op op; /* operational mode */ static char basedir[PATH_MAX]; /* current base directory */ -static struct mchars *mchars; /* table of named characters */ +static struct mpage *mpage_head; /* list of distinct manual pages */ static struct ohash mpages; /* table of distinct manual pages */ static struct ohash mlinks; /* table of directory entries */ static struct ohash names; /* table of all names */ @@ -209,159 +219,158 @@ static sqlite3_stmt *stmts[STMT__MAX]; /* current stat static uint64_t name_mask; static const struct mdoc_handler mdocs[MDOC_MAX] = { - { NULL, 0 }, /* Ap */ - { NULL, 0 }, /* Dd */ - { NULL, 0 }, /* Dt */ - { NULL, 0 }, /* Os */ - { parse_mdoc_Sh, TYPE_Sh }, /* Sh */ - { parse_mdoc_head, TYPE_Ss }, /* Ss */ - { NULL, 0 }, /* Pp */ - { NULL, 0 }, /* D1 */ - { NULL, 0 }, /* Dl */ - { NULL, 0 }, /* Bd */ - { NULL, 0 }, /* Ed */ - { NULL, 0 }, /* Bl */ - { NULL, 0 }, /* El */ - { NULL, 0 }, /* It */ - { NULL, 0 }, /* Ad */ - { NULL, TYPE_An }, /* An */ - { NULL, TYPE_Ar }, /* Ar */ - { NULL, TYPE_Cd }, /* Cd */ - { NULL, TYPE_Cm }, /* Cm */ - { NULL, TYPE_Dv }, /* Dv */ - { NULL, TYPE_Er }, /* Er */ - { NULL, TYPE_Ev }, /* Ev */ - { NULL, 0 }, /* Ex */ - { NULL, TYPE_Fa }, /* Fa */ - { parse_mdoc_Fd, 0 }, /* Fd */ - { NULL, TYPE_Fl }, /* Fl */ - { parse_mdoc_Fn, 0 }, /* Fn */ - { NULL, TYPE_Ft }, /* Ft */ - { NULL, TYPE_Ic }, /* Ic */ - { NULL, TYPE_In }, /* In */ - { NULL, TYPE_Li }, /* Li */ - { parse_mdoc_Nd, 0 }, /* Nd */ - { parse_mdoc_Nm, 0 }, /* Nm */ - { NULL, 0 }, /* Op */ - { NULL, 0 }, /* Ot */ - { NULL, TYPE_Pa }, /* Pa */ - { NULL, 0 }, /* Rv */ - { NULL, TYPE_St }, /* St */ - { NULL, TYPE_Va }, /* Va */ - { parse_mdoc_body, TYPE_Va }, /* Vt */ - { parse_mdoc_Xr, 0 }, /* Xr */ - { NULL, 0 }, /* %A */ - { NULL, 0 }, /* %B */ - { NULL, 0 }, /* %D */ - { NULL, 0 }, /* %I */ - { NULL, 0 }, /* %J */ - { NULL, 0 }, /* %N */ - { NULL, 0 }, /* %O */ - { NULL, 0 }, /* %P */ - { NULL, 0 }, /* %R */ - { NULL, 0 }, /* %T */ - { NULL, 0 }, /* %V */ - { NULL, 0 }, /* Ac */ - { NULL, 0 }, /* Ao */ - { NULL, 0 }, /* Aq */ - { NULL, TYPE_At }, /* At */ - { NULL, 0 }, /* Bc */ - { NULL, 0 }, /* Bf */ - { NULL, 0 }, /* Bo */ - { NULL, 0 }, /* Bq */ - { NULL, TYPE_Bsx }, /* Bsx */ - { NULL, TYPE_Bx }, /* Bx */ - { NULL, 0 }, /* Db */ - { NULL, 0 }, /* Dc */ - { NULL, 0 }, /* Do */ - { NULL, 0 }, /* Dq */ - { NULL, 0 }, /* Ec */ - { NULL, 0 }, /* Ef */ - { NULL, TYPE_Em }, /* Em */ - { NULL, 0 }, /* Eo */ - { NULL, TYPE_Fx }, /* Fx */ - { NULL, TYPE_Ms }, /* Ms */ - { NULL, 0 }, /* No */ - { NULL, 0 }, /* Ns */ - { NULL, TYPE_Nx }, /* Nx */ - { NULL, TYPE_Ox }, /* Ox */ - { NULL, 0 }, /* Pc */ - { NULL, 0 }, /* Pf */ - { NULL, 0 }, /* Po */ - { NULL, 0 }, /* Pq */ - { NULL, 0 }, /* Qc */ - { NULL, 0 }, /* Ql */ - { NULL, 0 }, /* Qo */ - { NULL, 0 }, /* Qq */ - { NULL, 0 }, /* Re */ - { NULL, 0 }, /* Rs */ - { NULL, 0 }, /* Sc */ - { NULL, 0 }, /* So */ - { NULL, 0 }, /* Sq */ - { NULL, 0 }, /* Sm */ - { NULL, 0 }, /* Sx */ - { NULL, TYPE_Sy }, /* Sy */ - { NULL, TYPE_Tn }, /* Tn */ - { NULL, 0 }, /* Ux */ - { NULL, 0 }, /* Xc */ - { NULL, 0 }, /* Xo */ - { parse_mdoc_Fo, 0 }, /* Fo */ - { NULL, 0 }, /* Fc */ - { NULL, 0 }, /* Oo */ - { NULL, 0 }, /* Oc */ - { NULL, 0 }, /* Bk */ - { NULL, 0 }, /* Ek */ - { NULL, 0 }, /* Bt */ - { NULL, 0 }, /* Hf */ - { NULL, 0 }, /* Fr */ - { NULL, 0 }, /* Ud */ - { NULL, TYPE_Lb }, /* Lb */ - { NULL, 0 }, /* Lp */ - { NULL, TYPE_Lk }, /* Lk */ - { NULL, TYPE_Mt }, /* Mt */ - { NULL, 0 }, /* Brq */ - { NULL, 0 }, /* Bro */ - { NULL, 0 }, /* Brc */ - { NULL, 0 }, /* %C */ - { NULL, 0 }, /* Es */ - { NULL, 0 }, /* En */ - { NULL, TYPE_Dx }, /* Dx */ - { NULL, 0 }, /* %Q */ - { NULL, 0 }, /* br */ - { NULL, 0 }, /* sp */ - { NULL, 0 }, /* %U */ - { NULL, 0 }, /* Ta */ - { NULL, 0 }, /* ll */ + { NULL, 0, 0 }, /* Ap */ + { NULL, 0, NODE_NOPRT }, /* Dd */ + { NULL, 0, NODE_NOPRT }, /* Dt */ + { NULL, 0, NODE_NOPRT }, /* Os */ + { parse_mdoc_Sh, TYPE_Sh, 0 }, /* Sh */ + { parse_mdoc_head, TYPE_Ss, 0 }, /* Ss */ + { NULL, 0, 0 }, /* Pp */ + { NULL, 0, 0 }, /* D1 */ + { NULL, 0, 0 }, /* Dl */ + { NULL, 0, 0 }, /* Bd */ + { NULL, 0, 0 }, /* Ed */ + { NULL, 0, 0 }, /* Bl */ + { NULL, 0, 0 }, /* El */ + { NULL, 0, 0 }, /* It */ + { NULL, 0, 0 }, /* Ad */ + { NULL, TYPE_An, 0 }, /* An */ + { NULL, TYPE_Ar, 0 }, /* Ar */ + { NULL, TYPE_Cd, 0 }, /* Cd */ + { NULL, TYPE_Cm, 0 }, /* Cm */ + { NULL, TYPE_Dv, 0 }, /* Dv */ + { NULL, TYPE_Er, 0 }, /* Er */ + { NULL, TYPE_Ev, 0 }, /* Ev */ + { NULL, 0, 0 }, /* Ex */ + { NULL, TYPE_Fa, 0 }, /* Fa */ + { parse_mdoc_Fd, 0, 0 }, /* Fd */ + { NULL, TYPE_Fl, 0 }, /* Fl */ + { parse_mdoc_Fn, 0, 0 }, /* Fn */ + { NULL, TYPE_Ft, 0 }, /* Ft */ + { NULL, TYPE_Ic, 0 }, /* Ic */ + { NULL, TYPE_In, 0 }, /* In */ + { NULL, TYPE_Li, 0 }, /* Li */ + { parse_mdoc_Nd, 0, 0 }, /* Nd */ + { parse_mdoc_Nm, 0, 0 }, /* Nm */ + { NULL, 0, 0 }, /* Op */ + { NULL, 0, 0 }, /* Ot */ + { NULL, TYPE_Pa, NODE_NOSRC }, /* Pa */ + { NULL, 0, 0 }, /* Rv */ + { NULL, TYPE_St, 0 }, /* St */ + { parse_mdoc_Va, TYPE_Va, 0 }, /* Va */ + { parse_mdoc_Va, TYPE_Vt, 0 }, /* Vt */ + { parse_mdoc_Xr, 0, 0 }, /* Xr */ + { NULL, 0, 0 }, /* %A */ + { NULL, 0, 0 }, /* %B */ + { NULL, 0, 0 }, /* %D */ + { NULL, 0, 0 }, /* %I */ + { NULL, 0, 0 }, /* %J */ + { NULL, 0, 0 }, /* %N */ + { NULL, 0, 0 }, /* %O */ + { NULL, 0, 0 }, /* %P */ + { NULL, 0, 0 }, /* %R */ + { NULL, 0, 0 }, /* %T */ + { NULL, 0, 0 }, /* %V */ + { NULL, 0, 0 }, /* Ac */ + { NULL, 0, 0 }, /* Ao */ + { NULL, 0, 0 }, /* Aq */ + { NULL, TYPE_At, 0 }, /* At */ + { NULL, 0, 0 }, /* Bc */ + { NULL, 0, 0 }, /* Bf */ + { NULL, 0, 0 }, /* Bo */ + { NULL, 0, 0 }, /* Bq */ + { NULL, TYPE_Bsx, NODE_NOSRC }, /* Bsx */ + { NULL, TYPE_Bx, NODE_NOSRC }, /* Bx */ + { NULL, 0, 0 }, /* Db */ + { NULL, 0, 0 }, /* Dc */ + { NULL, 0, 0 }, /* Do */ + { NULL, 0, 0 }, /* Dq */ + { NULL, 0, 0 }, /* Ec */ + { NULL, 0, 0 }, /* Ef */ + { NULL, TYPE_Em, 0 }, /* Em */ + { NULL, 0, 0 }, /* Eo */ + { NULL, TYPE_Fx, NODE_NOSRC }, /* Fx */ + { NULL, TYPE_Ms, 0 }, /* Ms */ + { NULL, 0, 0 }, /* No */ + { NULL, 0, 0 }, /* Ns */ + { NULL, TYPE_Nx, NODE_NOSRC }, /* Nx */ + { NULL, TYPE_Ox, NODE_NOSRC }, /* Ox */ + { NULL, 0, 0 }, /* Pc */ + { NULL, 0, 0 }, /* Pf */ + { NULL, 0, 0 }, /* Po */ + { NULL, 0, 0 }, /* Pq */ + { NULL, 0, 0 }, /* Qc */ + { NULL, 0, 0 }, /* Ql */ + { NULL, 0, 0 }, /* Qo */ + { NULL, 0, 0 }, /* Qq */ + { NULL, 0, 0 }, /* Re */ + { NULL, 0, 0 }, /* Rs */ + { NULL, 0, 0 }, /* Sc */ + { NULL, 0, 0 }, /* So */ + { NULL, 0, 0 }, /* Sq */ + { NULL, 0, 0 }, /* Sm */ + { NULL, 0, 0 }, /* Sx */ + { NULL, TYPE_Sy, 0 }, /* Sy */ + { NULL, TYPE_Tn, 0 }, /* Tn */ + { NULL, 0, NODE_NOSRC }, /* Ux */ + { NULL, 0, 0 }, /* Xc */ + { NULL, 0, 0 }, /* Xo */ + { parse_mdoc_Fo, 0, 0 }, /* Fo */ + { NULL, 0, 0 }, /* Fc */ + { NULL, 0, 0 }, /* Oo */ + { NULL, 0, 0 }, /* Oc */ + { NULL, 0, 0 }, /* Bk */ + { NULL, 0, 0 }, /* Ek */ + { NULL, 0, 0 }, /* Bt */ + { NULL, 0, 0 }, /* Hf */ + { NULL, 0, 0 }, /* Fr */ + { NULL, 0, 0 }, /* Ud */ + { NULL, TYPE_Lb, NODE_NOSRC }, /* Lb */ + { NULL, 0, 0 }, /* Lp */ + { NULL, TYPE_Lk, 0 }, /* Lk */ + { NULL, TYPE_Mt, NODE_NOSRC }, /* Mt */ + { NULL, 0, 0 }, /* Brq */ + { NULL, 0, 0 }, /* Bro */ + { NULL, 0, 0 }, /* Brc */ + { NULL, 0, 0 }, /* %C */ + { NULL, 0, 0 }, /* Es */ + { NULL, 0, 0 }, /* En */ + { NULL, TYPE_Dx, NODE_NOSRC }, /* Dx */ + { NULL, 0, 0 }, /* %Q */ + { NULL, 0, 0 }, /* br */ + { NULL, 0, 0 }, /* sp */ + { NULL, 0, 0 }, /* %U */ + { NULL, 0, 0 }, /* Ta */ + { NULL, 0, 0 }, /* ll */ }; int mandocdb(int argc, char *argv[]) { - int ch, i; - size_t j, sz; - const char *path_arg; - struct manpaths dirs; + struct manconf conf; struct mparse *mp; - struct ohash_info mpages_info, mlinks_info; + const char *path_arg, *progname; + size_t j, sz; + int ch, i; - memset(stmts, 0, STMT__MAX * sizeof(sqlite3_stmt *)); - memset(&dirs, 0, sizeof(struct manpaths)); +#if HAVE_PLEDGE + if (pledge("stdio rpath wpath cpath fattr flock proc exec", NULL) == -1) { + warn("pledge"); + return (int)MANDOCLEVEL_SYSERR; + } +#endif - mpages_info.alloc = mlinks_info.alloc = hash_alloc; - mpages_info.calloc = mlinks_info.calloc = hash_calloc; - mpages_info.free = mlinks_info.free = hash_free; - mpages_info.data = mlinks_info.data = NULL; +#if HAVE_SANDBOX_INIT + if (sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, NULL) == -1) { + warnx("sandbox_init"); + return (int)MANDOCLEVEL_SYSERR; + } +#endif - mpages_info.key_offset = offsetof(struct mpage, inodev); - mlinks_info.key_offset = offsetof(struct mlink, file); + memset(&conf, 0, sizeof(conf)); + memset(stmts, 0, STMT__MAX * sizeof(sqlite3_stmt *)); - progname = strrchr(argv[0], '/'); - if (progname == NULL) - progname = argv[0]; - else - ++progname; - /* * We accept a few different invocations. * The CHECKOP macro makes sure that invocation styles don't @@ -369,8 +378,7 @@ mandocdb(int argc, char *argv[]) */ #define CHECKOP(_op, _ch) do \ if (OP_DEFAULT != (_op)) { \ - fprintf(stderr, "%s: -%c: Conflicting option\n", \ - progname, (_ch)); \ + warnx("-%c: Conflicting option", (_ch)); \ goto usage; \ } while (/*CONSTCOND*/0) @@ -406,9 +414,8 @@ mandocdb(int argc, char *argv[]) break; case 'T': if (strcmp(optarg, "utf8")) { - fprintf(stderr, "%s: -T%s: " - "Unsupported output format\n", - progname, optarg); + warnx("-T%s: Unsupported output format", + optarg); goto usage; } write_utf8 = 1; @@ -434,18 +441,25 @@ mandocdb(int argc, char *argv[]) argc -= optind; argv += optind; +#if HAVE_PLEDGE + if (nodb) { + if (pledge("stdio rpath", NULL) == -1) { + warn("pledge"); + return (int)MANDOCLEVEL_SYSERR; + } + } +#endif + if (OP_CONFFILE == op && argc > 0) { - fprintf(stderr, "%s: -C: Too many arguments\n", - progname); + warnx("-C: Too many arguments"); goto usage; } exitcode = (int)MANDOCLEVEL_OK; - mchars = mchars_alloc(); - mp = mparse_alloc(mparse_options, MANDOCLEVEL_BADARG, NULL, - mchars, NULL); - ohash_init(&mpages, 6, &mpages_info); - ohash_init(&mlinks, 6, &mlinks_info); + mchars_alloc(); + mp = mparse_alloc(mparse_options, MANDOCLEVEL_BADARG, NULL, NULL); + mandoc_ohash_init(&mpages, 6, offsetof(struct mpage, inodev)); + mandoc_ohash_init(&mlinks, 6, offsetof(struct mlink, file)); if (OP_UPDATE == op || OP_DELETE == op || OP_TEST == op) { @@ -461,6 +475,15 @@ mandocdb(int argc, char *argv[]) * The existing database is usable. Process * all files specified on the command-line. */ +#if HAVE_PLEDGE + if (!nodb) { + if (pledge("stdio rpath wpath cpath fattr flock", NULL) == -1) { + warn("pledge"); + exitcode = (int)MANDOCLEVEL_SYSERR; + goto out; + } + } +#endif use_all = 1; for (i = 0; i < argc; i++) filescan(argv[i]); @@ -485,18 +508,18 @@ mandocdb(int argc, char *argv[]) /* * If we have arguments, use them as our manpaths. * If we don't, grok from manpath(1) or however else - * manpath_parse() wants to do it. + * manconf_parse() wants to do it. */ if (argc > 0) { - dirs.paths = mandoc_reallocarray(NULL, + conf.manpath.paths = mandoc_reallocarray(NULL, argc, sizeof(char *)); - dirs.sz = (size_t)argc; + conf.manpath.sz = (size_t)argc; for (i = 0; i < argc; i++) - dirs.paths[i] = mandoc_strdup(argv[i]); + conf.manpath.paths[i] = mandoc_strdup(argv[i]); } else - manpath_parse(&dirs, path_arg, NULL, NULL); + manconf_parse(&conf, path_arg, NULL, NULL); - if (0 == dirs.sz) { + if (conf.manpath.sz == 0) { exitcode = (int)MANDOCLEVEL_BADARG; say("", "Empty manpath"); } @@ -507,19 +530,21 @@ mandocdb(int argc, char *argv[]) * Ignore zero-length directories and strip trailing * slashes. */ - for (j = 0; j < dirs.sz; j++) { - sz = strlen(dirs.paths[j]); - if (sz && '/' == dirs.paths[j][sz - 1]) - dirs.paths[j][--sz] = '\0'; + for (j = 0; j < conf.manpath.sz; j++) { + sz = strlen(conf.manpath.paths[j]); + if (sz && conf.manpath.paths[j][sz - 1] == '/') + conf.manpath.paths[j][--sz] = '\0'; if (0 == sz) continue; if (j) { - ohash_init(&mpages, 6, &mpages_info); - ohash_init(&mlinks, 6, &mlinks_info); + mandoc_ohash_init(&mpages, 6, + offsetof(struct mpage, inodev)); + mandoc_ohash_init(&mlinks, 6, + offsetof(struct mlink, file)); } - if (0 == set_basedir(dirs.paths[j], argc > 0)) + if ( ! set_basedir(conf.manpath.paths[j], argc > 0)) continue; if (0 == treescan()) continue; @@ -532,7 +557,7 @@ mandocdb(int argc, char *argv[]) names_check(); dbclose(0); - if (j + 1 < dirs.sz) { + if (j + 1 < conf.manpath.sz) { mpages_free(); ohash_delete(&mpages); ohash_delete(&mlinks); @@ -540,26 +565,40 @@ mandocdb(int argc, char *argv[]) } } out: - manpath_free(&dirs); + manconf_free(&conf); mparse_free(mp); - mchars_free(mchars); + mchars_free(); mpages_free(); ohash_delete(&mpages); ohash_delete(&mlinks); - return(exitcode); + return exitcode; usage: + progname = getprogname(); fprintf(stderr, "usage: %s [-aDnpQ] [-C file] [-Tutf8]\n" " %s [-aDnpQ] [-Tutf8] dir ...\n" " %s [-DnpQ] [-Tutf8] -d dir [file ...]\n" " %s [-Dnp] -u dir [file ...]\n" " %s [-Q] -t file ...\n", - progname, progname, progname, - progname, progname); + progname, progname, progname, progname, progname); - return((int)MANDOCLEVEL_BADARG); + return (int)MANDOCLEVEL_BADARG; } /* + * To get a singly linked list in alpha order while inserting entries + * at the beginning, process directory entries in reverse alpha order. + */ +static int +#if HAVE_FTS_COMPARE_CONST +fts_compare(const FTSENT *const *a, const FTSENT *const *b) +#else +fts_compare(const FTSENT **a, const FTSENT **b) +#endif +{ + return -strcmp((*a)->fts_name, (*b)->fts_name); +} + +/* * Scan a directory tree rooted at "basedir" for manpages. * We use fts(), scanning directory parts along the way for clues to our * section and architecture. @@ -571,7 +610,7 @@ usage: * or * [./]cat
[/]/.0 * - * TODO: accomodate for multi-language directories. + * TODO: accommodate for multi-language directories. */ static int treescan(void) @@ -586,20 +625,20 @@ treescan(void) const char *argv[2]; argv[0] = "."; - argv[1] = (char *)NULL; + argv[1] = NULL; - f = fts_open((char * const *)argv, - FTS_PHYSICAL | FTS_NOCHDIR, NULL); - if (NULL == f) { + f = fts_open((char * const *)argv, FTS_PHYSICAL | FTS_NOCHDIR, + fts_compare); + if (f == NULL) { exitcode = (int)MANDOCLEVEL_SYSERR; say("", "&fts_open"); - return(0); + return 0; } dsec = arch = NULL; dform = FORM_NONE; - while (NULL != (ff = fts_read(f))) { + while ((ff = fts_read(f)) != NULL) { path = ff->fts_path + 2; switch (ff->fts_info) { @@ -608,7 +647,7 @@ treescan(void) * then get handled just like regular files. */ case FTS_SL: - if (NULL == realpath(path, buf)) { + if (realpath(path, buf) == NULL) { if (warnings) say(path, "&realpath"); continue; @@ -623,7 +662,7 @@ treescan(void) continue; } /* Use logical inode to avoid mpages dupe. */ - if (-1 == stat(path, ff->fts_statp)) { + if (stat(path, ff->fts_statp) == -1) { if (warnings) say(path, "&stat"); continue; @@ -635,7 +674,7 @@ treescan(void) * stored directory data and handling the filename. */ case FTS_F: - if (0 == strcmp(path, MANDOC_DB)) + if ( ! strcmp(path, MANDOC_DB)) continue; if ( ! use_all && ff->fts_level < 2) { if (warnings) @@ -644,37 +683,37 @@ treescan(void) } gzip = 0; fsec = NULL; - while (NULL == fsec) { + while (fsec == NULL) { fsec = strrchr(ff->fts_name, '.'); - if (NULL == fsec || strcmp(fsec+1, "gz")) + if (fsec == NULL || strcmp(fsec+1, "gz")) break; gzip = 1; *fsec = '\0'; fsec = NULL; } - if (NULL == fsec) { + if (fsec == NULL) { if ( ! use_all) { if (warnings) say(path, "No filename suffix"); continue; } - } else if (0 == strcmp(++fsec, "html")) { + } else if ( ! strcmp(++fsec, "html")) { if (warnings) say(path, "Skip html"); continue; - } else if (0 == strcmp(fsec, "ps")) { + } else if ( ! strcmp(fsec, "ps")) { if (warnings) say(path, "Skip ps"); continue; - } else if (0 == strcmp(fsec, "pdf")) { + } else if ( ! strcmp(fsec, "pdf")) { if (warnings) say(path, "Skip pdf"); continue; } else if ( ! use_all && - ((FORM_SRC == dform && + ((dform == FORM_SRC && strncmp(fsec, dsec, strlen(dsec))) || - (FORM_CAT == dform && strcmp(fsec, "0")))) { + (dform == FORM_CAT && strcmp(fsec, "0")))) { if (warnings) say(path, "Wrong filename suffix"); continue; @@ -699,7 +738,6 @@ treescan(void) continue; case FTS_D: - /* FALLTHROUGH */ case FTS_DP: break; @@ -720,13 +758,16 @@ treescan(void) * If we're not in use_all, enforce it. */ cp = ff->fts_name; - if (FTS_DP == ff->fts_info) + if (ff->fts_info == FTS_DP) { + dform = FORM_NONE; + dsec = NULL; break; + } - if (0 == strncmp(cp, "man", 3)) { + if ( ! strncmp(cp, "man", 3)) { dform = FORM_SRC; dsec = cp + 3; - } else if (0 == strncmp(cp, "cat", 3)) { + } else if ( ! strncmp(cp, "cat", 3)) { dform = FORM_CAT; dsec = cp + 3; } else { @@ -734,7 +775,7 @@ treescan(void) dsec = NULL; } - if (NULL != dsec || use_all) + if (dsec != NULL || use_all) break; if (warnings) @@ -746,13 +787,13 @@ treescan(void) * Possibly our architecture. * If we're descending, keep tabs on it. */ - if (FTS_DP != ff->fts_info && NULL != dsec) + if (ff->fts_info != FTS_DP && dsec != NULL) arch = ff->fts_name; else arch = NULL; break; default: - if (FTS_DP == ff->fts_info || use_all) + if (ff->fts_info == FTS_DP || use_all) break; if (warnings) say(path, "Extraneous directory part"); @@ -762,7 +803,7 @@ treescan(void) } fts_close(f); - return(1); + return 1; } /* @@ -867,6 +908,20 @@ filescan(const char *file) } /* + * In test mode or when the original name is absolute + * but outside our tree, guess the base directory. + */ + + if (op == OP_TEST || (start == buf && *start == '/')) { + if (strncmp(buf, "man/", 4) == 0) + start = buf + 4; + else if ((start = strstr(buf, "/man/")) != NULL) + start += 5; + else + start = buf; + } + + /* * First try to guess our directory structure. * If we find a separator, try to look for man* or cat*. * If we find one of these and what's underneath is a directory, @@ -952,6 +1007,8 @@ mlink_add(struct mlink *mlink, const struct stat *st) mpage = mandoc_calloc(1, sizeof(struct mpage)); mpage->inodev.st_ino = inodev.st_ino; mpage->inodev.st_dev = inodev.st_dev; + mpage->next = mpage_head; + mpage_head = mpage; ohash_insert(&mpages, slot, mpage); } else mlink->next = mpage->mlinks; @@ -975,20 +1032,18 @@ mpages_free(void) { struct mpage *mpage; struct mlink *mlink; - unsigned int slot; - mpage = ohash_first(&mpages, &slot); - while (NULL != mpage) { - while (NULL != (mlink = mpage->mlinks)) { + while ((mpage = mpage_head) != NULL) { + while ((mlink = mpage->mlinks) != NULL) { mpage->mlinks = mlink->next; mlink_free(mlink); } + mpage_head = mpage->next; free(mpage->sec); free(mpage->arch); free(mpage->title); free(mpage->desc); free(mpage); - mpage = ohash_next(&mpages, &slot); } } @@ -1103,43 +1158,29 @@ static void mpages_merge(struct mparse *mp) { char any[] = "any"; - struct ohash_info str_info; struct mpage *mpage, *mpage_dest; struct mlink *mlink, *mlink_dest; - struct mdoc *mdoc; - struct man *man; + struct roff_man *man; char *sodest; char *cp; int fd; - unsigned int pslot; - str_info.alloc = hash_alloc; - str_info.calloc = hash_calloc; - str_info.free = hash_free; - str_info.data = NULL; - str_info.key_offset = offsetof(struct str, key); - if ( ! nodb) SQL_EXEC("BEGIN TRANSACTION"); - mpage = ohash_first(&mpages, &pslot); - while (mpage != NULL) { + for (mpage = mpage_head; mpage != NULL; mpage = mpage->next) { mlinks_undupe(mpage); - if ((mlink = mpage->mlinks) == NULL) { - mpage = ohash_next(&mpages, &pslot); + if ((mlink = mpage->mlinks) == NULL) continue; - } name_mask = NAME_MASK; - ohash_init(&names, 4, &str_info); - ohash_init(&strings, 6, &str_info); + mandoc_ohash_init(&names, 4, offsetof(struct str, key)); + mandoc_ohash_init(&strings, 6, offsetof(struct str, key)); mparse_reset(mp); - mdoc = NULL; man = NULL; sodest = NULL; - mparse_open(mp, &fd, mlink->file); - if (fd == -1) { + if ((fd = mparse_open(mp, mlink->file)) == -1) { say(mlink->file, "&open"); goto nextpage; } @@ -1150,7 +1191,9 @@ mpages_merge(struct mparse *mp) */ if (mlink->dform != FORM_CAT || mlink->fform != FORM_CAT) { mparse_readfd(mp, fd, mlink->file); - mparse_result(mp, &mdoc, &man, &sodest); + close(fd); + fd = -1; + mparse_result(mp, &man, &sodest); } if (sodest != NULL) { @@ -1194,27 +1237,46 @@ mpages_merge(struct mparse *mp) mpage->mlinks = NULL; } goto nextpage; - } else if (mdoc != NULL) { + } else if (man != NULL && man->macroset == MACROSET_MDOC) { + mdoc_validate(man); mpage->form = FORM_SRC; - mpage->sec = mdoc_meta(mdoc)->msec; + mpage->sec = man->meta.msec; mpage->sec = mandoc_strdup( mpage->sec == NULL ? "" : mpage->sec); - mpage->arch = mdoc_meta(mdoc)->arch; + mpage->arch = man->meta.arch; mpage->arch = mandoc_strdup( mpage->arch == NULL ? "" : mpage->arch); - mpage->title = - mandoc_strdup(mdoc_meta(mdoc)->title); - } else if (man != NULL) { - mpage->form = FORM_SRC; - mpage->sec = mandoc_strdup(man_meta(man)->msec); - mpage->arch = mandoc_strdup(mlink->arch); - mpage->title = mandoc_strdup(man_meta(man)->title); - } else { + mpage->title = mandoc_strdup(man->meta.title); + } else if (man != NULL && man->macroset == MACROSET_MAN) { + man_validate(man); + if (*man->meta.msec != '\0' || + *man->meta.msec != '\0') { + mpage->form = FORM_SRC; + mpage->sec = mandoc_strdup(man->meta.msec); + mpage->arch = mandoc_strdup(mlink->arch); + mpage->title = mandoc_strdup(man->meta.title); + } else + man = NULL; + } + + assert(mpage->desc == NULL); + if (man == NULL) { mpage->form = FORM_CAT; mpage->sec = mandoc_strdup(mlink->dsec); mpage->arch = mandoc_strdup(mlink->arch); mpage->title = mandoc_strdup(mlink->name); + parse_cat(mpage, fd); + } else if (man->macroset == MACROSET_MDOC) + parse_mdoc(mpage, &man->meta, man->first); + else + parse_man(mpage, &man->meta, man->first); + if (mpage->desc == NULL) { + mpage->desc = mandoc_strdup(mlink->name); + if (warnings) + say(mlink->file, "No one-line description, " + "using filename \"%s\"", mlink->name); } + putkey(mpage, mpage->sec, TYPE_sec); if (*mpage->arch != '\0') putkey(mpage, mpage->arch, TYPE_arch); @@ -1229,32 +1291,16 @@ mpages_merge(struct mparse *mp) putkey(mpage, mlink->name, NAME_FILE); } - assert(mpage->desc == NULL); - if (mdoc != NULL) - parse_mdoc(mpage, mdoc_meta(mdoc), mdoc_node(mdoc)); - else if (man != NULL) - parse_man(mpage, man_meta(man), man_node(man)); - else - parse_cat(mpage, fd); - if (mpage->desc == NULL) - mpage->desc = mandoc_strdup(mpage->mlinks->name); - if (warnings && !use_all) for (mlink = mpage->mlinks; mlink; mlink = mlink->next) mlink_check(mpage, mlink); dbadd(mpage); - mlink = mpage->mlinks; nextpage: - if (mparse_wait(mp) != MANDOCLEVEL_OK) { - exitcode = (int)MANDOCLEVEL_SYSERR; - say(mlink->file, "&wait gunzip"); - } ohash_delete(&strings); ohash_delete(&names); - mpage = ohash_next(&mpages, &pslot); } if (0 == nodb) @@ -1266,7 +1312,6 @@ names_check(void) { sqlite3_stmt *stmt; const char *name, *sec, *arch, *key; - int irc; sqlite3_prepare_v2(db, "SELECT name, sec, arch, key FROM (" @@ -1282,10 +1327,10 @@ names_check(void) ") USING (pageid);", -1, &stmt, NULL); - if (SQLITE_OK != sqlite3_bind_int64(stmt, 1, NAME_TITLE)) + if (sqlite3_bind_int64(stmt, 1, NAME_TITLE) != SQLITE_OK) say("", "%s", sqlite3_errmsg(db)); - while (SQLITE_ROW == (irc = sqlite3_step(stmt))) { + while (sqlite3_step(stmt) == SQLITE_ROW) { name = (const char *)sqlite3_column_text(stmt, 0); sec = (const char *)sqlite3_column_text(stmt, 1); arch = (const char *)sqlite3_column_text(stmt, 2); @@ -1301,24 +1346,48 @@ static void parse_cat(struct mpage *mpage, int fd) { FILE *stream; - char *line, *p, *title; - size_t len, plen, titlesz; + struct mlink *mlink; + char *line, *p, *title, *sec; + size_t linesz, plen, titlesz; + ssize_t len; + int offs; - stream = (-1 == fd) ? - fopen(mpage->mlinks->file, "r") : - fdopen(fd, "r"); - if (NULL == stream) { - if (-1 != fd) + mlink = mpage->mlinks; + stream = fd == -1 ? fopen(mlink->file, "r") : fdopen(fd, "r"); + if (stream == NULL) { + if (fd != -1) close(fd); if (warnings) - say(mpage->mlinks->file, "&fopen"); + say(mlink->file, "&fopen"); return; } + line = NULL; + linesz = 0; + + /* Parse the section number from the header line. */ + + while (getline(&line, &linesz, stream) != -1) { + if (*line == '\n') + continue; + if ((sec = strchr(line, '(')) == NULL) + break; + if ((p = strchr(++sec, ')')) == NULL) + break; + free(mpage->sec); + mpage->sec = mandoc_strndup(sec, p - sec); + if (warnings && *mlink->dsec != '\0' && + strcasecmp(mpage->sec, mlink->dsec)) + say(mlink->file, + "Section \"%s\" manual in %s directory", + mpage->sec, mlink->dsec); + break; + } + /* Skip to first blank line. */ - while (NULL != (line = fgetln(stream, &len))) - if ('\n' == *line) + while (line == NULL || *line != '\n') + if (getline(&line, &linesz, stream) == -1) break; /* @@ -1326,8 +1395,8 @@ parse_cat(struct mpage *mpage, int fd) * is the first section header. Skip to it. */ - while (NULL != (line = fgetln(stream, &len))) - if ('\n' != *line && ' ' != *line) + while (getline(&line, &linesz, stream) != -1) + if (*line != '\n' && *line != ' ') break; /* @@ -1340,20 +1409,20 @@ parse_cat(struct mpage *mpage, int fd) titlesz = 0; title = NULL; - while (NULL != (line = fgetln(stream, &len))) { - if (' ' != *line || '\n' != line[len - 1]) + while ((len = getline(&line, &linesz, stream)) != -1) { + if (*line != ' ') break; - while (len > 0 && isspace((unsigned char)*line)) { - line++; - len--; - } - if (1 == len) + offs = 0; + while (isspace((unsigned char)line[offs])) + offs++; + if (line[offs] == '\0') continue; - title = mandoc_realloc(title, titlesz + len); - memcpy(title + titlesz, line, len); - titlesz += len; + title = mandoc_realloc(title, titlesz + len - offs); + memcpy(title + titlesz, line + offs, len - offs); + titlesz += len - offs; title[titlesz - 1] = ' '; } + free(line); /* * If no page content can be found, or the input line @@ -1364,15 +1433,13 @@ parse_cat(struct mpage *mpage, int fd) if (NULL == title || '\0' == *title) { if (warnings) - say(mpage->mlinks->file, - "Cannot find NAME section"); + say(mlink->file, "Cannot find NAME section"); fclose(stream); free(title); return; } - title = mandoc_realloc(title, titlesz + 1); - title[titlesz] = '\0'; + title[titlesz - 1] = '\0'; /* * Skip to the first dash. @@ -1385,8 +1452,8 @@ parse_cat(struct mpage *mpage, int fd) /* Skip to next word. */ ; } else { if (warnings) - say(mpage->mlinks->file, - "No dash in title line"); + say(mlink->file, "No dash in title line, " + "reusing \"%s\" as one-line description", title); p = title; } @@ -1430,27 +1497,29 @@ putkey(const struct mpage *mpage, char *value, uint64_ */ static void putmdockey(const struct mpage *mpage, - const struct mdoc_node *n, uint64_t m) + const struct roff_node *n, uint64_t m, int taboo) { for ( ; NULL != n; n = n->next) { + if (n->flags & taboo) + continue; if (NULL != n->child) - putmdockey(mpage, n->child, m); - if (MDOC_TEXT == n->type) + putmdockey(mpage, n->child, m, taboo); + if (n->type == ROFFT_TEXT) putkey(mpage, n->string, m); } } static void -parse_man(struct mpage *mpage, const struct man_meta *meta, - const struct man_node *n) +parse_man(struct mpage *mpage, const struct roff_meta *meta, + const struct roff_node *n) { - const struct man_node *head, *body; + const struct roff_node *head, *body; char *start, *title; char byte; size_t sz; - if (NULL == n) + if (n == NULL) return; /* @@ -1460,15 +1529,14 @@ parse_man(struct mpage *mpage, const struct man_meta * * the correct section or not. */ - if (MAN_BODY == n->type && MAN_SH == n->tok) { + if (n->type == ROFFT_BODY && n->tok == MAN_SH) { body = n; - assert(body->parent); - if (NULL != (head = body->parent->head) && - 1 == head->nchild && - NULL != (head = (head->child)) && - MAN_TEXT == head->type && - 0 == strcmp(head->string, "NAME") && - NULL != body->child) { + if ((head = body->parent->head) != NULL && + (head = head->child) != NULL && + head->next == NULL && + head->type == ROFFT_TEXT && + strcmp(head->string, "NAME") == 0 && + body->child != NULL) { /* * Suck the entire NAME section into memory. @@ -1478,7 +1546,7 @@ parse_man(struct mpage *mpage, const struct man_meta * */ title = NULL; - man_deroff(&title, body); + deroff(&title, body); if (NULL == title) return; @@ -1568,31 +1636,29 @@ parse_man(struct mpage *mpage, const struct man_meta * } static void -parse_mdoc(struct mpage *mpage, const struct mdoc_meta *meta, - const struct mdoc_node *n) +parse_mdoc(struct mpage *mpage, const struct roff_meta *meta, + const struct roff_node *n) { assert(NULL != n); for (n = n->child; NULL != n; n = n->next) { + if (n->flags & mdocs[n->tok].taboo) + continue; switch (n->type) { - case MDOC_ELEM: - /* FALLTHROUGH */ - case MDOC_BLOCK: - /* FALLTHROUGH */ - case MDOC_HEAD: - /* FALLTHROUGH */ - case MDOC_BODY: - /* FALLTHROUGH */ - case MDOC_TAIL: + case ROFFT_ELEM: + case ROFFT_BLOCK: + case ROFFT_HEAD: + case ROFFT_BODY: + case ROFFT_TAIL: if (NULL != mdocs[n->tok].fp) if (0 == (*mdocs[n->tok].fp)(mpage, meta, n)) break; if (mdocs[n->tok].mask) putmdockey(mpage, n->child, - mdocs[n->tok].mask); + mdocs[n->tok].mask, mdocs[n->tok].taboo); break; default: - assert(MDOC_ROOT != n->type); + assert(n->type != ROFFT_ROOT); continue; } if (NULL != n->child) @@ -1601,16 +1667,16 @@ parse_mdoc(struct mpage *mpage, const struct mdoc_meta } static int -parse_mdoc_Fd(struct mpage *mpage, const struct mdoc_meta *meta, - const struct mdoc_node *n) +parse_mdoc_Fd(struct mpage *mpage, const struct roff_meta *meta, + const struct roff_node *n) { char *start, *end; size_t sz; if (SEC_SYNOPSIS != n->sec || NULL == (n = n->child) || - MDOC_TEXT != n->type) - return(0); + n->type != ROFFT_TEXT) + return 0; /* * Only consider those `Fd' macro fields that begin with an @@ -1618,10 +1684,10 @@ parse_mdoc_Fd(struct mpage *mpage, const struct mdoc_m */ if (strcmp("#include", n->string)) - return(0); + return 0; - if (NULL == (n = n->next) || MDOC_TEXT != n->type) - return(0); + if ((n = n->next) == NULL || n->type != ROFFT_TEXT) + return 0; /* * Strip away the enclosing angle brackets and make sure we're @@ -1633,7 +1699,7 @@ parse_mdoc_Fd(struct mpage *mpage, const struct mdoc_m start++; if (0 == (sz = strlen(start))) - return(0); + return 0; end = &start[(int)sz - 1]; if ('>' == *end || '"' == *end) @@ -1641,16 +1707,16 @@ parse_mdoc_Fd(struct mpage *mpage, const struct mdoc_m if (end > start) putkeys(mpage, start, end - start + 1, TYPE_In); - return(0); + return 0; } static void -parse_mdoc_fname(struct mpage *mpage, const struct mdoc_node *n) +parse_mdoc_fname(struct mpage *mpage, const struct roff_node *n) { char *cp; size_t sz; - if (n->type != MDOC_TEXT) + if (n->type != ROFFT_TEXT) return; /* Skip function pointer punctuation. */ @@ -1666,78 +1732,103 @@ parse_mdoc_fname(struct mpage *mpage, const struct mdo } static int -parse_mdoc_Fn(struct mpage *mpage, const struct mdoc_meta *meta, - const struct mdoc_node *n) +parse_mdoc_Fn(struct mpage *mpage, const struct roff_meta *meta, + const struct roff_node *n) { if (n->child == NULL) - return(0); + return 0; parse_mdoc_fname(mpage, n->child); for (n = n->child->next; n != NULL; n = n->next) - if (n->type == MDOC_TEXT) + if (n->type == ROFFT_TEXT) putkey(mpage, n->string, TYPE_Fa); - return(0); + return 0; } static int -parse_mdoc_Fo(struct mpage *mpage, const struct mdoc_meta *meta, - const struct mdoc_node *n) +parse_mdoc_Fo(struct mpage *mpage, const struct roff_meta *meta, + const struct roff_node *n) { - if (n->type != MDOC_HEAD) - return(1); + if (n->type != ROFFT_HEAD) + return 1; if (n->child != NULL) parse_mdoc_fname(mpage, n->child); - return(0); + return 0; } static int -parse_mdoc_Xr(struct mpage *mpage, const struct mdoc_meta *meta, - const struct mdoc_node *n) +parse_mdoc_Va(struct mpage *mpage, const struct roff_meta *meta, + const struct roff_node *n) { + char *cp; + + if (n->type != ROFFT_ELEM && n->type != ROFFT_BODY) + return 0; + + if (n->child != NULL && + n->child->next == NULL && + n->child->type == ROFFT_TEXT) + return 1; + + cp = NULL; + deroff(&cp, n); + if (cp != NULL) { + putkey(mpage, cp, TYPE_Vt | (n->tok == MDOC_Va || + n->type == ROFFT_BODY ? TYPE_Va : 0)); + free(cp); + } + + return 0; +} + +static int +parse_mdoc_Xr(struct mpage *mpage, const struct roff_meta *meta, + const struct roff_node *n) +{ char *cp; if (NULL == (n = n->child)) - return(0); + return 0; if (NULL == n->next) { putkey(mpage, n->string, TYPE_Xr); - return(0); + return 0; } mandoc_asprintf(&cp, "%s(%s)", n->string, n->next->string); putkey(mpage, cp, TYPE_Xr); free(cp); - return(0); + return 0; } static int -parse_mdoc_Nd(struct mpage *mpage, const struct mdoc_meta *meta, - const struct mdoc_node *n) +parse_mdoc_Nd(struct mpage *mpage, const struct roff_meta *meta, + const struct roff_node *n) { - if (MDOC_BODY == n->type) - mdoc_deroff(&mpage->desc, n); - return(0); + if (n->type == ROFFT_BODY) + deroff(&mpage->desc, n); + return 0; } static int -parse_mdoc_Nm(struct mpage *mpage, const struct mdoc_meta *meta, - const struct mdoc_node *n) +parse_mdoc_Nm(struct mpage *mpage, const struct roff_meta *meta, + const struct roff_node *n) { if (SEC_NAME == n->sec) - putmdockey(mpage, n->child, NAME_TITLE); - else if (SEC_SYNOPSIS == n->sec && MDOC_HEAD == n->type) { + putmdockey(mpage, n->child, NAME_TITLE, 0); + else if (n->sec == SEC_SYNOPSIS && n->type == ROFFT_HEAD) { if (n->child == NULL) putkey(mpage, meta->name, NAME_SYN); else - putmdockey(mpage, n->child, NAME_SYN); + putmdockey(mpage, n->child, NAME_SYN, 0); } if ( ! (mpage->name_head_done || n->child == NULL || n->child->string == NULL || @@ -1745,33 +1836,25 @@ parse_mdoc_Nm(struct mpage *mpage, const struct mdoc_m putkey(mpage, n->child->string, NAME_HEAD); mpage->name_head_done = 1; } - return(0); + return 0; } static int -parse_mdoc_Sh(struct mpage *mpage, const struct mdoc_meta *meta, - const struct mdoc_node *n) +parse_mdoc_Sh(struct mpage *mpage, const struct roff_meta *meta, + const struct roff_node *n) { - return(SEC_CUSTOM == n->sec && MDOC_HEAD == n->type); + return n->sec == SEC_CUSTOM && n->type == ROFFT_HEAD; } static int -parse_mdoc_head(struct mpage *mpage, const struct mdoc_meta *meta, - const struct mdoc_node *n) +parse_mdoc_head(struct mpage *mpage, const struct roff_meta *meta, + const struct roff_node *n) { - return(MDOC_HEAD == n->type); + return n->type == ROFFT_HEAD; } -static int -parse_mdoc_body(struct mpage *mpage, const struct mdoc_meta *meta, - const struct mdoc_node *n) -{ - - return(MDOC_BODY == n->type); -} - /* * Add a string to the hash table for the current manual. * Each string has a bitmask telling which macros it belongs to. @@ -1798,7 +1881,8 @@ putkeys(const struct mpage *mpage, char *cp, size_t sz name_mask &= ~NAME_FIRST; if (debug > 1) say(mpage->mlinks->file, - "Adding name %*s, bits=%d", sz, cp, v); + "Adding name %*s, bits=0x%llx", (int)sz, cp, + (unsigned long long)v); } else { htab = &strings; if (debug > 1) @@ -1806,7 +1890,7 @@ putkeys(const struct mpage *mpage, char *cp, size_t sz if ((uint64_t)1 << i & v) say(mpage->mlinks->file, "Adding key %s=%*s", - mansearch_keynames[i], sz, cp); + mansearch_keynames[i], (int)sz, cp); } end = cp + sz; @@ -1874,10 +1958,10 @@ utf8(unsigned int cp, char out[7]) out[4] = (cp >> 6 & 63) | 128; out[5] = (cp & 63) | 128; } else - return(0); + return 0; out[rc] = '\0'; - return(rc); + return rc; } /* @@ -1935,7 +2019,6 @@ render_string(char **public, size_t *psz) case '\\': break; case '\t': - /* FALLTHROUGH */ case ASCII_NBRSP: dst[dsz++] = ' '; scp++; @@ -1966,7 +2049,7 @@ render_string(char **public, size_t *psz) */ if (write_utf8) { - unicode = mchars_spec2cp(mchars, seq, seqlen); + unicode = mchars_spec2cp(seq, seqlen); if (unicode <= 0) continue; addsz = utf8(unicode, utfbuf); @@ -1974,7 +2057,7 @@ render_string(char **public, size_t *psz) continue; addcp = utfbuf; } else { - addcp = mchars_spec2str(mchars, seq, seqlen, &addsz); + addcp = mchars_spec2str(seq, seqlen, &addsz); if (addcp == NULL) continue; if (*addcp == ASCII_NBRSP) { @@ -2001,9 +2084,9 @@ render_string(char **public, size_t *psz) --*psz; if (dst != NULL) { (*public)[*psz] = '\0'; - return(1); + return 1; } else - return(0); + return 0; } static void @@ -2214,7 +2297,7 @@ dbclose(int real) return; case 0: execlp("cmp", "cmp", "-s", - tempfilename, MANDOC_DB, NULL); + tempfilename, MANDOC_DB, (char *)NULL); say("", "&exec cmp"); exit(0); default: @@ -2239,7 +2322,7 @@ dbclose(int real) say("", "&fork rm"); return; case 0: - execlp("rm", "rm", "-rf", tempfilename, NULL); + execlp("rm", "rm", "-rf", tempfilename, (char *)NULL); say("", "&exec rm"); exit((int)MANDOCLEVEL_SYSERR); default: @@ -2270,7 +2353,7 @@ dbopen(int real) int rc, ofl; if (nodb) - return(1); + return 1; *tempfilename = '\0'; ofl = SQLITE_OPEN_READWRITE; @@ -2281,7 +2364,7 @@ dbopen(int real) exitcode = (int)MANDOCLEVEL_SYSERR; if (SQLITE_CANTOPEN != rc) say(MANDOC_DB, "%s", sqlite3_errstr(rc)); - return(0); + return 0; } goto prepare_statements; } @@ -2295,7 +2378,7 @@ dbopen(int real) if (MPARSE_QUICK & mparse_options) { exitcode = (int)MANDOCLEVEL_SYSERR; say(MANDOC_DB "~", "%s", sqlite3_errstr(rc)); - return(0); + return 0; } (void)strlcpy(tempfilename, "/tmp/mandocdb.XXXXXX", @@ -2303,7 +2386,7 @@ dbopen(int real) if (NULL == mkdtemp(tempfilename)) { exitcode = (int)MANDOCLEVEL_SYSERR; say("", "&%s", tempfilename); - return(0); + return 0; } (void)strlcat(tempfilename, "/" MANDOC_DB, sizeof(tempfilename)); @@ -2311,7 +2394,7 @@ dbopen(int real) if (SQLITE_OK != rc) { exitcode = (int)MANDOCLEVEL_SYSERR; say("", "%s: %s", tempfilename, sqlite3_errstr(rc)); - return(0); + return 0; } create_tables: @@ -2350,7 +2433,7 @@ create_tables: exitcode = (int)MANDOCLEVEL_SYSERR; say(MANDOC_DB, "%s", sqlite3_errmsg(db)); sqlite3_close(db); - return(0); + return 0; } prepare_statements: @@ -2360,7 +2443,7 @@ prepare_statements: say(MANDOC_DB, "PRAGMA foreign_keys: %s", sqlite3_errmsg(db)); sqlite3_close(db); - return(0); + return 0; } sql = "DELETE FROM mpages WHERE pageid IN " @@ -2394,34 +2477,13 @@ prepare_statements: say(MANDOC_DB, "PRAGMA synchronous: %s", sqlite3_errmsg(db)); sqlite3_close(db); - return(0); + return 0; } #endif - return(1); + return 1; } -static void * -hash_calloc(size_t n, size_t sz, void *arg) -{ - - return(mandoc_calloc(n, sz)); -} - -static void * -hash_alloc(size_t sz, void *arg) -{ - - return(mandoc_malloc(sz)); -} - -static void -hash_free(void *p, void *arg) -{ - - free(p); -} - static int set_basedir(const char *targetdir, int report_baddir) { @@ -2461,12 +2523,12 @@ set_basedir(const char *targetdir, int report_baddir) if (2 == getcwd_status) { exitcode = (int)MANDOCLEVEL_SYSERR; say("", "getcwd: %s", startdir); - return(0); + return 0; } if (-1 == chdir(startdir)) { exitcode = (int)MANDOCLEVEL_SYSERR; say("", "&chdir %s", startdir); - return(0); + return 0; } } @@ -2480,13 +2542,13 @@ set_basedir(const char *targetdir, int report_baddir) exitcode = (int)MANDOCLEVEL_BADARG; say("", "&%s: realpath", targetdir); } - return(0); + return 0; } else if (-1 == chdir(basedir)) { if (report_baddir || errno != ENOENT) { exitcode = (int)MANDOCLEVEL_BADARG; say("", "&chdir"); } - return(0); + return 0; } chdir_status = 1; cp = strchr(basedir, '\0'); @@ -2494,12 +2556,12 @@ set_basedir(const char *targetdir, int report_baddir) if (cp - basedir >= PATH_MAX - 1) { exitcode = (int)MANDOCLEVEL_SYSERR; say("", "Filename too long"); - return(0); + return 0; } *cp++ = '/'; *cp = '\0'; } - return(1); + return 1; } static void