version 1.255, 2017/08/26 15:55:46 |
version 1.263, 2019/05/03 18:17:12 |
|
|
/* $Id$ */ |
/* $Id$ */ |
/* |
/* |
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2011-2017 Ingo Schwarze <schwarze@openbsd.org> |
* Copyright (c) 2011-2019 Ingo Schwarze <schwarze@openbsd.org> |
* Copyright (c) 2016 Ed Maste <emaste@freebsd.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 |
|
|
#include "roff.h" |
#include "roff.h" |
#include "mdoc.h" |
#include "mdoc.h" |
#include "man.h" |
#include "man.h" |
|
#include "mandoc_parse.h" |
#include "manconf.h" |
#include "manconf.h" |
#include "mansearch.h" |
#include "mansearch.h" |
#include "dba_array.h" |
#include "dba_array.h" |
Line 139 static void parse_mdoc(struct mpage *, const struct r |
|
Line 140 static void parse_mdoc(struct mpage *, const struct r |
|
const struct roff_node *); |
const struct roff_node *); |
static int parse_mdoc_head(struct mpage *, const struct roff_meta *, |
static int parse_mdoc_head(struct mpage *, const struct roff_meta *, |
const struct roff_node *); |
const struct roff_node *); |
|
static int parse_mdoc_Fa(struct mpage *, const struct roff_meta *, |
|
const struct roff_node *); |
static int parse_mdoc_Fd(struct mpage *, const struct roff_meta *, |
static int parse_mdoc_Fd(struct mpage *, const struct roff_meta *, |
const struct roff_node *); |
const struct roff_node *); |
static void parse_mdoc_fname(struct mpage *, const struct roff_node *); |
static void parse_mdoc_fname(struct mpage *, const struct roff_node *); |
Line 183 static struct ohash names; /* table of all names */ |
|
Line 186 static struct ohash names; /* table of all names */ |
|
static struct ohash strings; /* table of all strings */ |
static struct ohash strings; /* table of all strings */ |
static uint64_t name_mask; |
static uint64_t name_mask; |
|
|
static const struct mdoc_handler __mdocs[MDOC_MAX - MDOC_Dd] = { |
static const struct mdoc_handler mdoc_handlers[MDOC_MAX - MDOC_Dd] = { |
{ NULL, 0, NODE_NOPRT }, /* Dd */ |
{ NULL, 0, NODE_NOPRT }, /* Dd */ |
{ NULL, 0, NODE_NOPRT }, /* Dt */ |
{ NULL, 0, NODE_NOPRT }, /* Dt */ |
{ NULL, 0, NODE_NOPRT }, /* Os */ |
{ NULL, 0, NODE_NOPRT }, /* Os */ |
Line 207 static const struct mdoc_handler __mdocs[MDOC_MAX - MD |
|
Line 210 static const struct mdoc_handler __mdocs[MDOC_MAX - MD |
|
{ NULL, TYPE_Er, 0 }, /* Er */ |
{ NULL, TYPE_Er, 0 }, /* Er */ |
{ NULL, TYPE_Ev, 0 }, /* Ev */ |
{ NULL, TYPE_Ev, 0 }, /* Ev */ |
{ NULL, 0, 0 }, /* Ex */ |
{ NULL, 0, 0 }, /* Ex */ |
{ NULL, TYPE_Fa, 0 }, /* Fa */ |
{ parse_mdoc_Fa, 0, 0 }, /* Fa */ |
{ parse_mdoc_Fd, 0, 0 }, /* Fd */ |
{ parse_mdoc_Fd, 0, 0 }, /* Fd */ |
{ NULL, TYPE_Fl, 0 }, /* Fl */ |
{ NULL, TYPE_Fl, 0 }, /* Fl */ |
{ parse_mdoc_Fn, 0, 0 }, /* Fn */ |
{ parse_mdoc_Fn, 0, 0 }, /* Fn */ |
{ NULL, TYPE_Ft, 0 }, /* Ft */ |
{ NULL, TYPE_Ft | TYPE_Vt, 0 }, /* Ft */ |
{ NULL, TYPE_Ic, 0 }, /* Ic */ |
{ NULL, TYPE_Ic, 0 }, /* Ic */ |
{ NULL, TYPE_In, 0 }, /* In */ |
{ NULL, TYPE_In, 0 }, /* In */ |
{ NULL, TYPE_Li, 0 }, /* Li */ |
{ NULL, TYPE_Li, 0 }, /* Li */ |
Line 305 static const struct mdoc_handler __mdocs[MDOC_MAX - MD |
|
Line 308 static const struct mdoc_handler __mdocs[MDOC_MAX - MD |
|
{ NULL, 0, 0 }, /* %U */ |
{ NULL, 0, 0 }, /* %U */ |
{ NULL, 0, 0 }, /* Ta */ |
{ NULL, 0, 0 }, /* Ta */ |
}; |
}; |
static const struct mdoc_handler *const mdocs = __mdocs - MDOC_Dd; |
|
|
|
|
|
int |
int |
Line 345 mandocdb(int argc, char *argv[]) |
|
Line 347 mandocdb(int argc, char *argv[]) |
|
goto usage; \ |
goto usage; \ |
} while (/*CONSTCOND*/0) |
} while (/*CONSTCOND*/0) |
|
|
|
mparse_options = MPARSE_VALIDATE; |
path_arg = NULL; |
path_arg = NULL; |
op = OP_DEFAULT; |
op = OP_DEFAULT; |
|
|
Line 420 mandocdb(int argc, char *argv[]) |
|
Line 423 mandocdb(int argc, char *argv[]) |
|
|
|
exitcode = (int)MANDOCLEVEL_OK; |
exitcode = (int)MANDOCLEVEL_OK; |
mchars_alloc(); |
mchars_alloc(); |
mp = mparse_alloc(mparse_options, MANDOCERR_MAX, NULL, |
mp = mparse_alloc(mparse_options, MANDOC_OS_OTHER, NULL); |
MANDOC_OS_OTHER, NULL); |
|
mandoc_ohash_init(&mpages, 6, offsetof(struct mpage, inodev)); |
mandoc_ohash_init(&mpages, 6, offsetof(struct mpage, inodev)); |
mandoc_ohash_init(&mlinks, 6, offsetof(struct mlink, file)); |
mandoc_ohash_init(&mlinks, 6, offsetof(struct mlink, file)); |
|
|
Line 1114 mpages_merge(struct dba *dba, struct mparse *mp) |
|
Line 1116 mpages_merge(struct dba *dba, struct mparse *mp) |
|
{ |
{ |
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_meta *meta; |
char *sodest; |
|
char *cp; |
char *cp; |
int fd; |
int fd; |
|
|
Line 1128 mpages_merge(struct dba *dba, struct mparse *mp) |
|
Line 1129 mpages_merge(struct dba *dba, struct mparse *mp) |
|
mandoc_ohash_init(&names, 4, offsetof(struct str, key)); |
mandoc_ohash_init(&names, 4, offsetof(struct str, key)); |
mandoc_ohash_init(&strings, 6, offsetof(struct str, key)); |
mandoc_ohash_init(&strings, 6, offsetof(struct str, key)); |
mparse_reset(mp); |
mparse_reset(mp); |
man = NULL; |
meta = NULL; |
sodest = NULL; |
|
|
|
if ((fd = mparse_open(mp, mlink->file)) == -1) { |
if ((fd = mparse_open(mp, mlink->file)) == -1) { |
say(mlink->file, "&open"); |
say(mlink->file, "&open"); |
Line 1144 mpages_merge(struct dba *dba, struct mparse *mp) |
|
Line 1144 mpages_merge(struct dba *dba, struct mparse *mp) |
|
mparse_readfd(mp, fd, mlink->file); |
mparse_readfd(mp, fd, mlink->file); |
close(fd); |
close(fd); |
fd = -1; |
fd = -1; |
mparse_result(mp, &man, &sodest); |
meta = mparse_result(mp); |
} |
} |
|
|
if (sodest != NULL) { |
if (meta != NULL && meta->sodest != NULL) { |
mlink_dest = ohash_find(&mlinks, |
mlink_dest = ohash_find(&mlinks, |
ohash_qlookup(&mlinks, sodest)); |
ohash_qlookup(&mlinks, meta->sodest)); |
if (mlink_dest == NULL) { |
if (mlink_dest == NULL) { |
mandoc_asprintf(&cp, "%s.gz", sodest); |
mandoc_asprintf(&cp, "%s.gz", meta->sodest); |
mlink_dest = ohash_find(&mlinks, |
mlink_dest = ohash_find(&mlinks, |
ohash_qlookup(&mlinks, cp)); |
ohash_qlookup(&mlinks, cp)); |
free(cp); |
free(cp); |
Line 1186 mpages_merge(struct dba *dba, struct mparse *mp) |
|
Line 1186 mpages_merge(struct dba *dba, struct mparse *mp) |
|
mlink->next = mlink_dest->next; |
mlink->next = mlink_dest->next; |
mlink_dest->next = mpage->mlinks; |
mlink_dest->next = mpage->mlinks; |
mpage->mlinks = NULL; |
mpage->mlinks = NULL; |
|
goto nextpage; |
} |
} |
goto nextpage; |
meta->macroset = MACROSET_NONE; |
} else if (man != NULL && man->macroset == MACROSET_MDOC) { |
} |
mdoc_validate(man); |
if (meta != NULL && meta->macroset == MACROSET_MDOC) { |
mpage->form = FORM_SRC; |
mpage->form = FORM_SRC; |
mpage->sec = man->meta.msec; |
mpage->sec = meta->msec; |
mpage->sec = mandoc_strdup( |
mpage->sec = mandoc_strdup( |
mpage->sec == NULL ? "" : mpage->sec); |
mpage->sec == NULL ? "" : mpage->sec); |
mpage->arch = man->meta.arch; |
mpage->arch = meta->arch; |
mpage->arch = mandoc_strdup( |
mpage->arch = mandoc_strdup( |
mpage->arch == NULL ? "" : mpage->arch); |
mpage->arch == NULL ? "" : mpage->arch); |
mpage->title = mandoc_strdup(man->meta.title); |
mpage->title = mandoc_strdup(meta->title); |
} else if (man != NULL && man->macroset == MACROSET_MAN) { |
} else if (meta != NULL && meta->macroset == MACROSET_MAN) { |
man_validate(man); |
if (*meta->msec != '\0' || *meta->title != '\0') { |
if (*man->meta.msec != '\0' || |
|
*man->meta.title != '\0') { |
|
mpage->form = FORM_SRC; |
mpage->form = FORM_SRC; |
mpage->sec = mandoc_strdup(man->meta.msec); |
mpage->sec = mandoc_strdup(meta->msec); |
mpage->arch = mandoc_strdup(mlink->arch); |
mpage->arch = mandoc_strdup(mlink->arch); |
mpage->title = mandoc_strdup(man->meta.title); |
mpage->title = mandoc_strdup(meta->title); |
} else |
} else |
man = NULL; |
meta = NULL; |
} |
} |
|
|
assert(mpage->desc == NULL); |
assert(mpage->desc == NULL); |
if (man == NULL) { |
if (meta == NULL || meta->sodest != NULL) { |
mpage->form = FORM_CAT; |
|
mpage->sec = mandoc_strdup(mlink->dsec); |
mpage->sec = mandoc_strdup(mlink->dsec); |
mpage->arch = mandoc_strdup(mlink->arch); |
mpage->arch = mandoc_strdup(mlink->arch); |
mpage->title = mandoc_strdup(mlink->name); |
mpage->title = mandoc_strdup(mlink->name); |
parse_cat(mpage, fd); |
if (meta == NULL) { |
} else if (man->macroset == MACROSET_MDOC) |
mpage->form = FORM_CAT; |
parse_mdoc(mpage, &man->meta, man->first); |
parse_cat(mpage, fd); |
|
} else |
|
mpage->form = FORM_SRC; |
|
} else if (meta->macroset == MACROSET_MDOC) |
|
parse_mdoc(mpage, meta, meta->first); |
else |
else |
parse_man(mpage, &man->meta, man->first); |
parse_man(mpage, meta, meta->first); |
if (mpage->desc == NULL) { |
if (mpage->desc == NULL) { |
mpage->desc = mandoc_strdup(mlink->name); |
mpage->desc = mandoc_strdup(mlink->name); |
if (warnings) |
if (warnings) |
Line 1373 parse_cat(struct mpage *mpage, int fd) |
|
Line 1375 parse_cat(struct mpage *mpage, int fd) |
|
plen -= 2; |
plen -= 2; |
} |
} |
|
|
mpage->desc = mandoc_strdup(p); |
/* |
|
* Cut off excessive one-line descriptions. |
|
* Bad pages are not worth better heuristics. |
|
*/ |
|
|
|
mpage->desc = mandoc_strndup(p, 150); |
fclose(stream); |
fclose(stream); |
free(title); |
free(title); |
} |
} |
Line 1517 parse_man(struct mpage *mpage, const struct roff_meta |
|
Line 1524 parse_man(struct mpage *mpage, const struct roff_meta |
|
while (' ' == *start) |
while (' ' == *start) |
start++; |
start++; |
|
|
mpage->desc = mandoc_strdup(start); |
/* |
|
* Cut off excessive one-line descriptions. |
|
* Bad pages are not worth better heuristics. |
|
*/ |
|
|
|
mpage->desc = mandoc_strndup(start, 150); |
free(title); |
free(title); |
return; |
return; |
} |
} |
|
|
parse_mdoc(struct mpage *mpage, const struct roff_meta *meta, |
parse_mdoc(struct mpage *mpage, const struct roff_meta *meta, |
const struct roff_node *n) |
const struct roff_node *n) |
{ |
{ |
|
const struct mdoc_handler *handler; |
|
|
for (n = n->child; n != NULL; n = n->next) { |
for (n = n->child; n != NULL; n = n->next) { |
if (n->tok == TOKEN_NONE || |
if (n->tok == TOKEN_NONE || n->tok < ROFF_MAX) |
n->tok < ROFF_MAX || |
|
n->flags & mdocs[n->tok].taboo) |
|
continue; |
continue; |
assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX); |
assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX); |
|
handler = mdoc_handlers + (n->tok - MDOC_Dd); |
|
if (n->flags & handler->taboo) |
|
continue; |
|
|
switch (n->type) { |
switch (n->type) { |
case ROFFT_ELEM: |
case ROFFT_ELEM: |
case ROFFT_BLOCK: |
case ROFFT_BLOCK: |
case ROFFT_HEAD: |
case ROFFT_HEAD: |
case ROFFT_BODY: |
case ROFFT_BODY: |
case ROFFT_TAIL: |
case ROFFT_TAIL: |
if (mdocs[n->tok].fp != NULL && |
if (handler->fp != NULL && |
(*mdocs[n->tok].fp)(mpage, meta, n) == 0) |
(*handler->fp)(mpage, meta, n) == 0) |
break; |
break; |
if (mdocs[n->tok].mask) |
if (handler->mask) |
putmdockey(mpage, n->child, |
putmdockey(mpage, n->child, |
mdocs[n->tok].mask, mdocs[n->tok].taboo); |
handler->mask, handler->taboo); |
break; |
break; |
default: |
default: |
continue; |
continue; |
Line 1563 parse_mdoc(struct mpage *mpage, const struct roff_meta |
|
Line 1578 parse_mdoc(struct mpage *mpage, const struct roff_meta |
|
} |
} |
|
|
static int |
static int |
|
parse_mdoc_Fa(struct mpage *mpage, const struct roff_meta *meta, |
|
const struct roff_node *n) |
|
{ |
|
uint64_t mask; |
|
|
|
mask = TYPE_Fa; |
|
if (n->sec == SEC_SYNOPSIS) |
|
mask |= TYPE_Vt; |
|
|
|
putmdockey(mpage, n->child, mask, 0); |
|
return 0; |
|
} |
|
|
|
static int |
parse_mdoc_Fd(struct mpage *mpage, const struct roff_meta *meta, |
parse_mdoc_Fd(struct mpage *mpage, const struct roff_meta *meta, |
const struct roff_node *n) |
const struct roff_node *n) |
{ |
{ |
|
|
parse_mdoc_Fn(struct mpage *mpage, const struct roff_meta *meta, |
parse_mdoc_Fn(struct mpage *mpage, const struct roff_meta *meta, |
const struct roff_node *n) |
const struct roff_node *n) |
{ |
{ |
|
uint64_t mask; |
|
|
if (n->child == NULL) |
if (n->child == NULL) |
return 0; |
return 0; |
|
|
parse_mdoc_fname(mpage, n->child); |
parse_mdoc_fname(mpage, n->child); |
|
|
for (n = n->child->next; n != NULL; n = n->next) |
n = n->child->next; |
if (n->type == ROFFT_TEXT) |
if (n != NULL && n->type == ROFFT_TEXT) { |
putkey(mpage, n->string, TYPE_Fa); |
mask = TYPE_Fa; |
|
if (n->sec == SEC_SYNOPSIS) |
|
mask |= TYPE_Vt; |
|
putmdockey(mpage, n, mask, 0); |
|
} |
|
|
return 0; |
return 0; |
} |
} |
Line 2152 dbwrite(struct dba *dba) |
|
Line 2186 dbwrite(struct dba *dba) |
|
say("", "&%s", tfn); |
say("", "&%s", tfn); |
return; |
return; |
} |
} |
cp1 = cp2 = NULL; |
cp1 = cp2 = MAP_FAILED; |
fd1 = fd2 = -1; |
fd1 = fd2 = -1; |
(void)strlcat(tfn, "/" MANDOC_DB, sizeof(tfn)); |
(void)strlcat(tfn, "/" MANDOC_DB, sizeof(tfn)); |
if (dba_write(tfn, dba) == -1) { |
if (dba_write(tfn, dba) == -1) { |
Line 2178 dbwrite(struct dba *dba) |
|
Line 2212 dbwrite(struct dba *dba) |
|
if (sb1.st_size != sb2.st_size) |
if (sb1.st_size != sb2.st_size) |
goto err; |
goto err; |
if ((cp1 = mmap(NULL, sb1.st_size, PROT_READ, MAP_PRIVATE, |
if ((cp1 = mmap(NULL, sb1.st_size, PROT_READ, MAP_PRIVATE, |
fd1, 0)) == NULL) { |
fd1, 0)) == MAP_FAILED) { |
say(MANDOC_DB, "&mmap"); |
say(MANDOC_DB, "&mmap"); |
goto err; |
goto err; |
} |
} |
if ((cp2 = mmap(NULL, sb2.st_size, PROT_READ, MAP_PRIVATE, |
if ((cp2 = mmap(NULL, sb2.st_size, PROT_READ, MAP_PRIVATE, |
fd2, 0)) == NULL) { |
fd2, 0)) == MAP_FAILED) { |
say(tfn, "&mmap"); |
say(tfn, "&mmap"); |
goto err; |
goto err; |
} |
} |
|
|
say(MANDOC_DB, "Data changed, but cannot replace database"); |
say(MANDOC_DB, "Data changed, but cannot replace database"); |
|
|
out: |
out: |
if (cp1 != NULL) |
if (cp1 != MAP_FAILED) |
munmap(cp1, sb1.st_size); |
munmap(cp1, sb1.st_size); |
if (cp2 != NULL) |
if (cp2 != MAP_FAILED) |
munmap(cp2, sb2.st_size); |
munmap(cp2, sb2.st_size); |
if (fd1 != -1) |
if (fd1 != -1) |
close(fd1); |
close(fd1); |