version 1.197, 2015/10/06 18:32:19 |
version 1.202, 2015/10/13 15:53:05 |
|
|
|
|
#include <assert.h> |
#include <assert.h> |
#include <ctype.h> |
#include <ctype.h> |
|
#include <err.h> |
#include <errno.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
#if HAVE_FTS |
#if HAVE_FTS |
|
|
#include <string.h> |
#include <string.h> |
#include <unistd.h> |
#include <unistd.h> |
|
|
#if HAVE_OHASH |
|
#include <ohash.h> |
|
#else |
|
#include "compat_ohash.h" |
|
#endif |
|
#include <sqlite3.h> |
#include <sqlite3.h> |
|
|
#include "mandoc_aux.h" |
#include "mandoc_aux.h" |
|
#include "mandoc_ohash.h" |
#include "mandoc.h" |
#include "mandoc.h" |
#include "roff.h" |
#include "roff.h" |
#include "mdoc.h" |
#include "mdoc.h" |
Line 145 static void dbadd_mlink_name(const struct mlink *mlin |
|
Line 142 static void dbadd_mlink_name(const struct mlink *mlin |
|
static int dbopen(int); |
static int dbopen(int); |
static void dbprune(void); |
static void dbprune(void); |
static void filescan(const char *); |
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 *); |
|
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 189 static int set_basedir(const char *, int); |
|
Line 183 static int set_basedir(const char *, int); |
|
static int treescan(void); |
static int treescan(void); |
static size_t utf8(unsigned int, char [7]); |
static size_t utf8(unsigned int, char [7]); |
|
|
|
extern char *__progname; |
|
|
static char tempfilename[32]; |
static char tempfilename[32]; |
static char *progname; |
|
static int nodb; /* no database changes */ |
static int nodb; /* no database changes */ |
static int mparse_options; /* abort the parse early */ |
static int mparse_options; /* abort the parse early */ |
static int use_all; /* use all found files */ |
static int use_all; /* use all found files */ |
|
|
mandocdb(int argc, char *argv[]) |
mandocdb(int argc, char *argv[]) |
{ |
{ |
struct manconf conf; |
struct manconf conf; |
struct ohash_info mpages_info, mlinks_info; |
|
struct mparse *mp; |
struct mparse *mp; |
const char *path_arg; |
const char *path_arg; |
size_t j, sz; |
size_t j, sz; |
Line 349 mandocdb(int argc, char *argv[]) |
|
Line 343 mandocdb(int argc, char *argv[]) |
|
memset(&conf, 0, sizeof(conf)); |
memset(&conf, 0, sizeof(conf)); |
memset(stmts, 0, STMT__MAX * sizeof(sqlite3_stmt *)); |
memset(stmts, 0, STMT__MAX * sizeof(sqlite3_stmt *)); |
|
|
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; |
|
|
|
mpages_info.key_offset = offsetof(struct mpage, inodev); |
|
mlinks_info.key_offset = offsetof(struct mlink, file); |
|
|
|
progname = strrchr(argv[0], '/'); |
|
if (progname == NULL) |
|
progname = argv[0]; |
|
else |
|
++progname; |
|
|
|
/* |
/* |
* We accept a few different invocations. |
* We accept a few different invocations. |
* The CHECKOP macro makes sure that invocation styles don't |
* The CHECKOP macro makes sure that invocation styles don't |
Line 370 mandocdb(int argc, char *argv[]) |
|
Line 350 mandocdb(int argc, char *argv[]) |
|
*/ |
*/ |
#define CHECKOP(_op, _ch) do \ |
#define CHECKOP(_op, _ch) do \ |
if (OP_DEFAULT != (_op)) { \ |
if (OP_DEFAULT != (_op)) { \ |
fprintf(stderr, "%s: -%c: Conflicting option\n", \ |
warnx("-%c: Conflicting option", (_ch)); \ |
progname, (_ch)); \ |
|
goto usage; \ |
goto usage; \ |
} while (/*CONSTCOND*/0) |
} while (/*CONSTCOND*/0) |
|
|
Line 407 mandocdb(int argc, char *argv[]) |
|
Line 386 mandocdb(int argc, char *argv[]) |
|
break; |
break; |
case 'T': |
case 'T': |
if (strcmp(optarg, "utf8")) { |
if (strcmp(optarg, "utf8")) { |
fprintf(stderr, "%s: -T%s: " |
warnx("-T%s: Unsupported output format", |
"Unsupported output format\n", |
optarg); |
progname, optarg); |
|
goto usage; |
goto usage; |
} |
} |
write_utf8 = 1; |
write_utf8 = 1; |
Line 436 mandocdb(int argc, char *argv[]) |
|
Line 414 mandocdb(int argc, char *argv[]) |
|
argv += optind; |
argv += optind; |
|
|
if (OP_CONFFILE == op && argc > 0) { |
if (OP_CONFFILE == op && argc > 0) { |
fprintf(stderr, "%s: -C: Too many arguments\n", |
warnx("-C: Too many arguments"); |
progname); |
|
goto usage; |
goto usage; |
} |
} |
|
|
Line 445 mandocdb(int argc, char *argv[]) |
|
Line 422 mandocdb(int argc, char *argv[]) |
|
mchars = mchars_alloc(); |
mchars = mchars_alloc(); |
mp = mparse_alloc(mparse_options, MANDOCLEVEL_BADARG, NULL, |
mp = mparse_alloc(mparse_options, MANDOCLEVEL_BADARG, NULL, |
mchars, NULL); |
mchars, NULL); |
ohash_init(&mpages, 6, &mpages_info); |
mandoc_ohash_init(&mpages, 6, offsetof(struct mpage, inodev)); |
ohash_init(&mlinks, 6, &mlinks_info); |
mandoc_ohash_init(&mlinks, 6, offsetof(struct mlink, file)); |
|
|
if (OP_UPDATE == op || OP_DELETE == op || OP_TEST == op) { |
if (OP_UPDATE == op || OP_DELETE == op || OP_TEST == op) { |
|
|
Line 516 mandocdb(int argc, char *argv[]) |
|
Line 493 mandocdb(int argc, char *argv[]) |
|
continue; |
continue; |
|
|
if (j) { |
if (j) { |
ohash_init(&mpages, 6, &mpages_info); |
mandoc_ohash_init(&mpages, 6, |
ohash_init(&mlinks, 6, &mlinks_info); |
offsetof(struct mpage, inodev)); |
|
mandoc_ohash_init(&mlinks, 6, |
|
offsetof(struct mlink, file)); |
} |
} |
|
|
if ( ! set_basedir(conf.manpath.paths[j], argc > 0)) |
if ( ! set_basedir(conf.manpath.paths[j], argc > 0)) |
|
|
" %s [-DnpQ] [-Tutf8] -d dir [file ...]\n" |
" %s [-DnpQ] [-Tutf8] -d dir [file ...]\n" |
" %s [-Dnp] -u dir [file ...]\n" |
" %s [-Dnp] -u dir [file ...]\n" |
" %s [-Q] -t 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; |
} |
} |
|
|
|
|
f = fts_open((char * const *)argv, |
f = fts_open((char * const *)argv, |
FTS_PHYSICAL | FTS_NOCHDIR, NULL); |
FTS_PHYSICAL | FTS_NOCHDIR, NULL); |
if (NULL == f) { |
if (f == NULL) { |
exitcode = (int)MANDOCLEVEL_SYSERR; |
exitcode = (int)MANDOCLEVEL_SYSERR; |
say("", "&fts_open"); |
say("", "&fts_open"); |
return 0; |
return 0; |
|
|
dsec = arch = NULL; |
dsec = arch = NULL; |
dform = FORM_NONE; |
dform = FORM_NONE; |
|
|
while (NULL != (ff = fts_read(f))) { |
while ((ff = fts_read(f)) != NULL) { |
path = ff->fts_path + 2; |
path = ff->fts_path + 2; |
switch (ff->fts_info) { |
switch (ff->fts_info) { |
|
|
|
|
* then get handled just like regular files. |
* then get handled just like regular files. |
*/ |
*/ |
case FTS_SL: |
case FTS_SL: |
if (NULL == realpath(path, buf)) { |
if (realpath(path, buf) == NULL) { |
if (warnings) |
if (warnings) |
say(path, "&realpath"); |
say(path, "&realpath"); |
continue; |
continue; |
|
|
continue; |
continue; |
} |
} |
/* Use logical inode to avoid mpages dupe. */ |
/* Use logical inode to avoid mpages dupe. */ |
if (-1 == stat(path, ff->fts_statp)) { |
if (stat(path, ff->fts_statp) == -1) { |
if (warnings) |
if (warnings) |
say(path, "&stat"); |
say(path, "&stat"); |
continue; |
continue; |
|
|
* stored directory data and handling the filename. |
* stored directory data and handling the filename. |
*/ |
*/ |
case FTS_F: |
case FTS_F: |
if (0 == strcmp(path, MANDOC_DB)) |
if ( ! strcmp(path, MANDOC_DB)) |
continue; |
continue; |
if ( ! use_all && ff->fts_level < 2) { |
if ( ! use_all && ff->fts_level < 2) { |
if (warnings) |
if (warnings) |
|
|
} |
} |
gzip = 0; |
gzip = 0; |
fsec = NULL; |
fsec = NULL; |
while (NULL == fsec) { |
while (fsec == NULL) { |
fsec = strrchr(ff->fts_name, '.'); |
fsec = strrchr(ff->fts_name, '.'); |
if (NULL == fsec || strcmp(fsec+1, "gz")) |
if (fsec == NULL || strcmp(fsec+1, "gz")) |
break; |
break; |
gzip = 1; |
gzip = 1; |
*fsec = '\0'; |
*fsec = '\0'; |
fsec = NULL; |
fsec = NULL; |
} |
} |
if (NULL == fsec) { |
if (fsec == NULL) { |
if ( ! use_all) { |
if ( ! use_all) { |
if (warnings) |
if (warnings) |
say(path, |
say(path, |
"No filename suffix"); |
"No filename suffix"); |
continue; |
continue; |
} |
} |
} else if (0 == strcmp(++fsec, "html")) { |
} else if ( ! strcmp(++fsec, "html")) { |
if (warnings) |
if (warnings) |
say(path, "Skip html"); |
say(path, "Skip html"); |
continue; |
continue; |
} else if (0 == strcmp(fsec, "ps")) { |
} else if ( ! strcmp(fsec, "ps")) { |
if (warnings) |
if (warnings) |
say(path, "Skip ps"); |
say(path, "Skip ps"); |
continue; |
continue; |
} else if (0 == strcmp(fsec, "pdf")) { |
} else if ( ! strcmp(fsec, "pdf")) { |
if (warnings) |
if (warnings) |
say(path, "Skip pdf"); |
say(path, "Skip pdf"); |
continue; |
continue; |
} else if ( ! use_all && |
} else if ( ! use_all && |
((FORM_SRC == dform && |
((dform == FORM_SRC && |
strncmp(fsec, dsec, strlen(dsec))) || |
strncmp(fsec, dsec, strlen(dsec))) || |
(FORM_CAT == dform && strcmp(fsec, "0")))) { |
(dform == FORM_CAT && strcmp(fsec, "0")))) { |
if (warnings) |
if (warnings) |
say(path, "Wrong filename suffix"); |
say(path, "Wrong filename suffix"); |
continue; |
continue; |
|
|
continue; |
continue; |
|
|
case FTS_D: |
case FTS_D: |
/* FALLTHROUGH */ |
|
case FTS_DP: |
case FTS_DP: |
break; |
break; |
|
|
|
|
* If we're not in use_all, enforce it. |
* If we're not in use_all, enforce it. |
*/ |
*/ |
cp = ff->fts_name; |
cp = ff->fts_name; |
if (FTS_DP == ff->fts_info) |
if (ff->fts_info == FTS_DP) { |
|
dform = FORM_NONE; |
|
dsec = NULL; |
break; |
break; |
|
} |
|
|
if (0 == strncmp(cp, "man", 3)) { |
if ( ! strncmp(cp, "man", 3)) { |
dform = FORM_SRC; |
dform = FORM_SRC; |
dsec = cp + 3; |
dsec = cp + 3; |
} else if (0 == strncmp(cp, "cat", 3)) { |
} else if ( ! strncmp(cp, "cat", 3)) { |
dform = FORM_CAT; |
dform = FORM_CAT; |
dsec = cp + 3; |
dsec = cp + 3; |
} else { |
} else { |
|
|
dsec = NULL; |
dsec = NULL; |
} |
} |
|
|
if (NULL != dsec || use_all) |
if (dsec != NULL || use_all) |
break; |
break; |
|
|
if (warnings) |
if (warnings) |
|
|
* Possibly our architecture. |
* Possibly our architecture. |
* If we're descending, keep tabs on it. |
* 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; |
arch = ff->fts_name; |
else |
else |
arch = NULL; |
arch = NULL; |
break; |
break; |
default: |
default: |
if (FTS_DP == ff->fts_info || use_all) |
if (ff->fts_info == FTS_DP || use_all) |
break; |
break; |
if (warnings) |
if (warnings) |
say(path, "Extraneous directory part"); |
say(path, "Extraneous directory part"); |
|
|
mpages_merge(struct mparse *mp) |
mpages_merge(struct mparse *mp) |
{ |
{ |
char any[] = "any"; |
char any[] = "any"; |
struct ohash_info str_info; |
|
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; |
Line 1113 mpages_merge(struct mparse *mp) |
|
Line 1093 mpages_merge(struct mparse *mp) |
|
int fd; |
int fd; |
unsigned int pslot; |
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) |
if ( ! nodb) |
SQL_EXEC("BEGIN TRANSACTION"); |
SQL_EXEC("BEGIN TRANSACTION"); |
|
|
Line 1131 mpages_merge(struct mparse *mp) |
|
Line 1105 mpages_merge(struct mparse *mp) |
|
} |
} |
|
|
name_mask = NAME_MASK; |
name_mask = NAME_MASK; |
ohash_init(&names, 4, &str_info); |
mandoc_ohash_init(&names, 4, offsetof(struct str, key)); |
ohash_init(&strings, 6, &str_info); |
mandoc_ohash_init(&strings, 6, offsetof(struct str, key)); |
mparse_reset(mp); |
mparse_reset(mp); |
man = NULL; |
man = NULL; |
sodest = NULL; |
sodest = NULL; |
Line 1260 names_check(void) |
|
Line 1234 names_check(void) |
|
{ |
{ |
sqlite3_stmt *stmt; |
sqlite3_stmt *stmt; |
const char *name, *sec, *arch, *key; |
const char *name, *sec, *arch, *key; |
int irc; |
|
|
|
sqlite3_prepare_v2(db, |
sqlite3_prepare_v2(db, |
"SELECT name, sec, arch, key FROM (" |
"SELECT name, sec, arch, key FROM (" |
Line 1276 names_check(void) |
|
Line 1249 names_check(void) |
|
") USING (pageid);", |
") USING (pageid);", |
-1, &stmt, NULL); |
-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)); |
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); |
name = (const char *)sqlite3_column_text(stmt, 0); |
sec = (const char *)sqlite3_column_text(stmt, 1); |
sec = (const char *)sqlite3_column_text(stmt, 1); |
arch = (const char *)sqlite3_column_text(stmt, 2); |
arch = (const char *)sqlite3_column_text(stmt, 2); |
Line 1570 parse_mdoc(struct mpage *mpage, const struct roff_meta |
|
Line 1543 parse_mdoc(struct mpage *mpage, const struct roff_meta |
|
for (n = n->child; NULL != n; n = n->next) { |
for (n = n->child; NULL != n; n = n->next) { |
switch (n->type) { |
switch (n->type) { |
case ROFFT_ELEM: |
case ROFFT_ELEM: |
/* FALLTHROUGH */ |
|
case ROFFT_BLOCK: |
case ROFFT_BLOCK: |
/* FALLTHROUGH */ |
|
case ROFFT_HEAD: |
case ROFFT_HEAD: |
/* FALLTHROUGH */ |
|
case ROFFT_BODY: |
case ROFFT_BODY: |
/* FALLTHROUGH */ |
|
case ROFFT_TAIL: |
case ROFFT_TAIL: |
if (NULL != mdocs[n->tok].fp) |
if (NULL != mdocs[n->tok].fp) |
if (0 == (*mdocs[n->tok].fp)(mpage, meta, n)) |
if (0 == (*mdocs[n->tok].fp)(mpage, meta, n)) |
Line 1929 render_string(char **public, size_t *psz) |
|
Line 1898 render_string(char **public, size_t *psz) |
|
case '\\': |
case '\\': |
break; |
break; |
case '\t': |
case '\t': |
/* FALLTHROUGH */ |
|
case ASCII_NBRSP: |
case ASCII_NBRSP: |
dst[dsz++] = ' '; |
dst[dsz++] = ' '; |
scp++; |
scp++; |
Line 2393 prepare_statements: |
|
Line 2361 prepare_statements: |
|
#endif |
#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 |
static int |