version 1.221, 2016/07/19 21:31:55 |
version 1.233, 2016/10/20 16:31:00 |
|
|
/* |
/* |
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2011-2016 Ingo Schwarze <schwarze@openbsd.org> |
* Copyright (c) 2011-2016 Ingo Schwarze <schwarze@openbsd.org> |
|
* Copyright (c) 2016 Ed Maste <emaste@freebsd.org> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
|
|
char *arch; /* architecture from file content */ |
char *arch; /* architecture from file content */ |
char *title; /* title from file content */ |
char *title; /* title from file content */ |
char *desc; /* description from file content */ |
char *desc; /* description from file content */ |
|
struct mpage *next; /* singly linked list */ |
struct mlink *mlinks; /* singly linked list */ |
struct mlink *mlinks; /* singly linked list */ |
int name_head_done; |
int name_head_done; |
enum form form; /* format from file content */ |
enum form form; /* format from file content */ |
Line 118 static void dbadd_mlink(const struct mlink *mlink); |
|
Line 120 static void dbadd_mlink(const struct mlink *mlink); |
|
static void dbprune(struct dba *); |
static void dbprune(struct dba *); |
static void dbwrite(struct dba *); |
static void dbwrite(struct dba *); |
static void filescan(const char *); |
static void filescan(const char *); |
|
#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_add(struct mlink *, const struct stat *); |
static void mlink_check(struct mpage *, struct mlink *); |
static void mlink_check(struct mpage *, struct mlink *); |
static void mlink_free(struct mlink *); |
static void mlink_free(struct mlink *); |
Line 168 static int write_utf8; /* write UTF-8 output; else A |
|
Line 175 static int write_utf8; /* write UTF-8 output; else A |
|
static int exitcode; /* to be returned by main */ |
static int exitcode; /* to be returned by main */ |
static enum op op; /* operational mode */ |
static enum op op; /* operational mode */ |
static char basedir[PATH_MAX]; /* current base directory */ |
static char basedir[PATH_MAX]; /* current base directory */ |
|
static struct mpage *mpage_head; /* list of distinct manual pages */ |
static struct ohash mpages; /* table of distinct manual pages */ |
static struct ohash mpages; /* table of distinct manual pages */ |
static struct ohash mlinks; /* table of directory entries */ |
static struct ohash mlinks; /* table of directory entries */ |
static struct ohash names; /* table of all names */ |
static struct ohash names; /* table of all names */ |
Line 426 mandocdb(int argc, char *argv[]) |
|
Line 434 mandocdb(int argc, char *argv[]) |
|
if (OP_TEST != op && 0 == set_basedir(path_arg, 1)) |
if (OP_TEST != op && 0 == set_basedir(path_arg, 1)) |
goto out; |
goto out; |
|
|
if ((dba = dba_read(MANDOC_DB)) != NULL) { |
dba = nodb ? dba_new(128) : dba_read(MANDOC_DB); |
|
if (dba != NULL) { |
/* |
/* |
* The existing database is usable. Process |
* The existing database is usable. Process |
* all files specified on the command-line. |
* all files specified on the command-line. |
Line 443 mandocdb(int argc, char *argv[]) |
|
Line 452 mandocdb(int argc, char *argv[]) |
|
use_all = 1; |
use_all = 1; |
for (i = 0; i < argc; i++) |
for (i = 0; i < argc; i++) |
filescan(argv[i]); |
filescan(argv[i]); |
if (OP_TEST != op) |
if (nodb == 0) |
dbprune(dba); |
dbprune(dba); |
} else { |
} else { |
/* |
/* Database missing or corrupt. */ |
* Database missing or corrupt. |
if (op != OP_UPDATE || errno != ENOENT) |
* Recreate from scratch. |
say(MANDOC_DB, "%s: Automatically recreating" |
*/ |
" from scratch", strerror(errno)); |
exitcode = (int)MANDOCLEVEL_OK; |
exitcode = (int)MANDOCLEVEL_OK; |
op = OP_DEFAULT; |
op = OP_DEFAULT; |
if (0 == treescan()) |
if (0 == treescan()) |
Line 464 mandocdb(int argc, char *argv[]) |
|
Line 473 mandocdb(int argc, char *argv[]) |
|
} else { |
} else { |
/* |
/* |
* If we have arguments, use them as our manpaths. |
* If we have arguments, use them as our manpaths. |
* If we don't, grok from manpath(1) or however else |
* If we don't, use man.conf(5). |
* manconf_parse() wants to do it. |
|
*/ |
*/ |
if (argc > 0) { |
if (argc > 0) { |
conf.manpath.paths = mandoc_reallocarray(NULL, |
conf.manpath.paths = mandoc_reallocarray(NULL, |
|
|
} |
} |
|
|
/* |
/* |
|
* 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. |
* Scan a directory tree rooted at "basedir" for manpages. |
* We use fts(), scanning directory parts along the way for clues to our |
* We use fts(), scanning directory parts along the way for clues to our |
* section and architecture. |
* section and architecture. |
|
|
argv[0] = "."; |
argv[0] = "."; |
argv[1] = (char *)NULL; |
argv[1] = (char *)NULL; |
|
|
f = fts_open((char * const *)argv, |
f = fts_open((char * const *)argv, FTS_PHYSICAL | FTS_NOCHDIR, |
FTS_PHYSICAL | FTS_NOCHDIR, NULL); |
fts_compare); |
if (f == NULL) { |
if (f == NULL) { |
exitcode = (int)MANDOCLEVEL_SYSERR; |
exitcode = (int)MANDOCLEVEL_SYSERR; |
say("", "&fts_open"); |
say("", "&fts_open"); |
Line 935 mlink_add(struct mlink *mlink, const struct stat *st) |
|
Line 957 mlink_add(struct mlink *mlink, const struct stat *st) |
|
mpage->inodev.st_ino = inodev.st_ino; |
mpage->inodev.st_ino = inodev.st_ino; |
mpage->inodev.st_dev = inodev.st_dev; |
mpage->inodev.st_dev = inodev.st_dev; |
mpage->form = FORM_NONE; |
mpage->form = FORM_NONE; |
|
mpage->next = mpage_head; |
|
mpage_head = mpage; |
ohash_insert(&mpages, slot, mpage); |
ohash_insert(&mpages, slot, mpage); |
} else |
} else |
mlink->next = mpage->mlinks; |
mlink->next = mpage->mlinks; |
Line 958 mpages_free(void) |
|
Line 982 mpages_free(void) |
|
{ |
{ |
struct mpage *mpage; |
struct mpage *mpage; |
struct mlink *mlink; |
struct mlink *mlink; |
unsigned int slot; |
|
|
|
mpage = ohash_first(&mpages, &slot); |
while ((mpage = mpage_head) != NULL) { |
while (NULL != mpage) { |
while ((mlink = mpage->mlinks) != NULL) { |
while (NULL != (mlink = mpage->mlinks)) { |
|
mpage->mlinks = mlink->next; |
mpage->mlinks = mlink->next; |
mlink_free(mlink); |
mlink_free(mlink); |
} |
} |
|
mpage_head = mpage->next; |
free(mpage->sec); |
free(mpage->sec); |
free(mpage->arch); |
free(mpage->arch); |
free(mpage->title); |
free(mpage->title); |
free(mpage->desc); |
free(mpage->desc); |
free(mpage); |
free(mpage); |
mpage = ohash_next(&mpages, &slot); |
|
} |
} |
} |
} |
|
|
Line 1048 mlink_check(struct mpage *mpage, struct mlink *mlink) |
|
Line 1070 mlink_check(struct mpage *mpage, struct mlink *mlink) |
|
* architectures. |
* architectures. |
* A few manuals are even shared across completely |
* A few manuals are even shared across completely |
* different architectures, for example fdformat(1) |
* different architectures, for example fdformat(1) |
* on amd64, i386, sparc, and sparc64. |
* on amd64, i386, and sparc64. |
*/ |
*/ |
|
|
if (strcasecmp(mpage->arch, mlink->arch)) |
if (strcasecmp(mpage->arch, mlink->arch)) |
Line 1085 mlink_check(struct mpage *mpage, struct mlink *mlink) |
|
Line 1107 mlink_check(struct mpage *mpage, struct mlink *mlink) |
|
static void |
static void |
mpages_merge(struct dba *dba, struct mparse *mp) |
mpages_merge(struct dba *dba, struct mparse *mp) |
{ |
{ |
char any[] = "any"; |
|
struct mpage *mpage, *mpage_dest; |
struct mpage *mpage, *mpage_dest; |
struct mlink *mlink, *mlink_dest; |
struct mlink *mlink, *mlink_dest; |
struct roff_man *man; |
struct roff_man *man; |
char *sodest; |
char *sodest; |
char *cp; |
char *cp; |
int fd; |
int fd; |
unsigned int pslot; |
|
|
|
mpage = ohash_first(&mpages, &pslot); |
for (mpage = mpage_head; mpage != NULL; mpage = mpage->next) { |
while (mpage != NULL) { |
|
mlinks_undupe(mpage); |
mlinks_undupe(mpage); |
if ((mlink = mpage->mlinks) == NULL) { |
if ((mlink = mpage->mlinks) == NULL) |
mpage = ohash_next(&mpages, &pslot); |
|
continue; |
continue; |
} |
|
|
|
name_mask = NAME_MASK; |
name_mask = NAME_MASK; |
mandoc_ohash_init(&names, 4, offsetof(struct str, key)); |
mandoc_ohash_init(&names, 4, offsetof(struct str, key)); |
Line 1187 mpages_merge(struct dba *dba, struct mparse *mp) |
|
Line 1204 mpages_merge(struct dba *dba, struct mparse *mp) |
|
mpage->arch = mandoc_strdup(mlink->arch); |
mpage->arch = mandoc_strdup(mlink->arch); |
mpage->title = mandoc_strdup(mlink->name); |
mpage->title = mandoc_strdup(mlink->name); |
} |
} |
putkey(mpage, mpage->sec, TYPE_sec); |
|
if (*mpage->arch != '\0') |
|
putkey(mpage, mpage->arch, TYPE_arch); |
|
|
|
for ( ; mlink != NULL; mlink = mlink->next) { |
|
if ('\0' != *mlink->dsec) |
|
putkey(mpage, mlink->dsec, TYPE_sec); |
|
if ('\0' != *mlink->fsec) |
|
putkey(mpage, mlink->fsec, TYPE_sec); |
|
putkey(mpage, '\0' == *mlink->arch ? |
|
any : mlink->arch, TYPE_arch); |
|
putkey(mpage, mlink->name, NAME_FILE); |
|
} |
|
|
|
assert(mpage->desc == NULL); |
assert(mpage->desc == NULL); |
if (man != NULL && man->macroset == MACROSET_MDOC) |
if (man != NULL && man->macroset == MACROSET_MDOC) |
parse_mdoc(mpage, &man->meta, man->first); |
parse_mdoc(mpage, &man->meta, man->first); |
Line 1222 mpages_merge(struct dba *dba, struct mparse *mp) |
|
Line 1226 mpages_merge(struct dba *dba, struct mparse *mp) |
|
nextpage: |
nextpage: |
ohash_delete(&strings); |
ohash_delete(&strings); |
ohash_delete(&names); |
ohash_delete(&names); |
mpage = ohash_next(&mpages, &pslot); |
|
} |
} |
} |
} |
|
|
Line 1348 parse_cat(struct mpage *mpage, int fd) |
|
Line 1351 parse_cat(struct mpage *mpage, int fd) |
|
static void |
static void |
putkey(const struct mpage *mpage, char *value, uint64_t type) |
putkey(const struct mpage *mpage, char *value, uint64_t type) |
{ |
{ |
char *cp; |
|
|
|
assert(NULL != value); |
|
if (TYPE_arch == type) |
|
for (cp = value; *cp; cp++) |
|
if (isupper((unsigned char)*cp)) |
|
*cp = _tolower((unsigned char)*cp); |
|
putkeys(mpage, value, strlen(value), type); |
putkeys(mpage, value, strlen(value), type); |
} |
} |
|
|
Line 1695 parse_mdoc_Nm(struct mpage *mpage, const struct roff_m |
|
Line 1691 parse_mdoc_Nm(struct mpage *mpage, const struct roff_m |
|
if ( ! (mpage->name_head_done || |
if ( ! (mpage->name_head_done || |
n->child == NULL || n->child->string == NULL || |
n->child == NULL || n->child->string == NULL || |
strcasecmp(n->child->string, meta->title))) { |
strcasecmp(n->child->string, meta->title))) { |
putkey(mpage, n->child->string, ROFFT_HEAD); |
putkey(mpage, n->child->string, NAME_HEAD); |
mpage->name_head_done = 1; |
mpage->name_head_done = 1; |
} |
} |
return 0; |
return 0; |
Line 1743 putkeys(const struct mpage *mpage, char *cp, size_t sz |
|
Line 1739 putkeys(const struct mpage *mpage, char *cp, size_t sz |
|
name_mask &= ~NAME_FIRST; |
name_mask &= ~NAME_FIRST; |
if (debug > 1) |
if (debug > 1) |
say(mpage->mlinks->file, |
say(mpage->mlinks->file, |
"Adding name %*s, bits=0x%llu", (int)sz, cp, v); |
"Adding name %*s, bits=0x%llx", (int)sz, cp, v); |
} else { |
} else { |
htab = &strings; |
htab = &strings; |
if (debug > 1) |
if (debug > 1) |
Line 1955 dbadd_mlink(const struct mlink *mlink) |
|
Line 1951 dbadd_mlink(const struct mlink *mlink) |
|
{ |
{ |
dba_page_alias(mlink->mpage->dba, mlink->name, NAME_FILE); |
dba_page_alias(mlink->mpage->dba, mlink->name, NAME_FILE); |
dba_page_add(mlink->mpage->dba, DBP_SECT, mlink->dsec); |
dba_page_add(mlink->mpage->dba, DBP_SECT, mlink->dsec); |
|
dba_page_add(mlink->mpage->dba, DBP_SECT, mlink->fsec); |
dba_page_add(mlink->mpage->dba, DBP_ARCH, mlink->arch); |
dba_page_add(mlink->mpage->dba, DBP_ARCH, mlink->arch); |
dba_page_add(mlink->mpage->dba, DBP_FILE, mlink->file); |
dba_page_add(mlink->mpage->dba, DBP_FILE, mlink->file); |
} |
} |
Line 2014 dbadd(struct dba *dba, struct mpage *mpage) |
|
Line 2011 dbadd(struct dba *dba, struct mpage *mpage) |
|
cp = mpage->desc; |
cp = mpage->desc; |
i = strlen(cp); |
i = strlen(cp); |
mustfree = render_string(&cp, &i); |
mustfree = render_string(&cp, &i); |
mpage->dba = dba_page_new(dba->pages, mlink->name, |
mpage->dba = dba_page_new(dba->pages, |
mlink->dsec, mlink->arch, cp, mlink->file, mpage->form); |
*mpage->arch == '\0' ? mlink->arch : mpage->arch, |
|
cp, mlink->file, mpage->form); |
if (mustfree) |
if (mustfree) |
free(cp); |
free(cp); |
|
dba_page_add(mpage->dba, DBP_SECT, mpage->sec); |
|
|
while ((mlink = mlink->next) != NULL) |
while (mlink != NULL) { |
dbadd_mlink(mlink); |
dbadd_mlink(mlink); |
|
mlink = mlink->next; |
|
} |
|
|
for (key = ohash_first(&names, &slot); NULL != key; |
for (key = ohash_first(&names, &slot); NULL != key; |
key = ohash_next(&names, &slot)) { |
key = ohash_next(&names, &slot)) { |