-/* $Id: mandocdb.c,v 1.223 2016/07/29 15:23:57 schwarze Exp $ */
+/* $Id: mandocdb.c,v 1.232 2016/10/18 16:06:44 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* 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
* purpose with or without fee is hereby granted, provided that the above
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 name_head_done;
enum form form; /* format from file content */
static void dbprune(struct dba *);
static void dbwrite(struct dba *);
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_check(struct mpage *, struct mlink *);
static void mlink_free(struct mlink *);
static int exitcode; /* to be returned by main */
static enum op op; /* operational mode */
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 mlinks; /* table of directory entries */
static struct ohash names; /* table of all names */
if (OP_TEST != op && 0 == set_basedir(path_arg, 1))
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
* all files specified on the command-line.
use_all = 1;
for (i = 0; i < argc; i++)
filescan(argv[i]);
- if (OP_TEST != op)
+ if (nodb == 0)
dbprune(dba);
} else {
- /*
- * Database missing or corrupt.
- * Recreate from scratch.
- */
+ /* Database missing or corrupt. */
+ if (op != OP_UPDATE || errno != ENOENT)
+ say(MANDOC_DB, "%s: Automatically recreating"
+ " from scratch", strerror(errno));
exitcode = (int)MANDOCLEVEL_OK;
op = OP_DEFAULT;
if (0 == treescan())
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
argv[0] = ".";
argv[1] = (char *)NULL;
- f = fts_open((char * const *)argv,
- FTS_PHYSICAL | FTS_NOCHDIR, NULL);
+ f = fts_open((char * const *)argv, FTS_PHYSICAL | FTS_NOCHDIR,
+ fts_compare);
if (f == NULL) {
exitcode = (int)MANDOCLEVEL_SYSERR;
say("", "&fts_open");
mpage->inodev.st_ino = inodev.st_ino;
mpage->inodev.st_dev = inodev.st_dev;
mpage->form = FORM_NONE;
+ mpage->next = mpage_head;
+ mpage_head = mpage;
ohash_insert(&mpages, slot, mpage);
} else
mlink->next = mpage->mlinks;
{
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);
}
}
* architectures.
* A few manuals are even shared across completely
* different architectures, for example fdformat(1)
- * on amd64, i386, sparc, and sparc64.
+ * on amd64, i386, and sparc64.
*/
if (strcasecmp(mpage->arch, mlink->arch))
char *sodest;
char *cp;
int fd;
- unsigned int pslot;
- 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;
mandoc_ohash_init(&names, 4, offsetof(struct str, key));
nextpage:
ohash_delete(&strings);
ohash_delete(&names);
- mpage = ohash_next(&mpages, &pslot);
}
}
if ( ! (mpage->name_head_done ||
n->child == NULL || n->child->string == NULL ||
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;
}
return 0;
cp = mpage->desc;
i = strlen(cp);
mustfree = render_string(&cp, &i);
- mpage->dba = dba_page_new(dba->pages, mlink->name, mpage->sec,
+ mpage->dba = dba_page_new(dba->pages,
*mpage->arch == '\0' ? mlink->arch : mpage->arch,
cp, mlink->file, mpage->form);
if (mustfree)
free(cp);
+ dba_page_add(mpage->dba, DBP_SECT, mpage->sec);
while (mlink != NULL) {
dbadd_mlink(mlink);