]> git.cameronkatri.com Git - mandoc.git/blobdiff - mandocdb.c
The termination condition of the iteration logic in page_bymacro()
[mandoc.git] / mandocdb.c
index 652ff159b03de442cd0ccd163d77cf9e74271aba..16bb4c9af8412ce23909afafe713e789388f5fec 100644 (file)
@@ -1,7 +1,8 @@
-/*     $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
@@ -84,6 +85,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              name_head_done;
        enum form        form;    /* format from file content */
@@ -118,6 +120,11 @@ static     void     dbadd_mlink(const struct mlink *mlink);
 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 *);
@@ -168,6 +175,7 @@ static      int              write_utf8; /* write UTF-8 output; else ASCII */
 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 */
@@ -426,7 +434,8 @@ mandocdb(int argc, char *argv[])
                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.
@@ -443,13 +452,13 @@ mandocdb(int argc, char *argv[])
                        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())
@@ -537,6 +546,20 @@ usage:
        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
@@ -567,8 +590,8 @@ treescan(void)
        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");
@@ -934,6 +957,8 @@ mlink_add(struct mlink *mlink, const struct stat *st)
                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;
@@ -957,20 +982,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);
        }
 }
 
@@ -1047,7 +1070,7 @@ mlink_check(struct mpage *mpage, struct mlink *mlink)
         * 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))
@@ -1090,15 +1113,11 @@ mpages_merge(struct dba *dba, struct mparse *mp)
        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));
@@ -1207,7 +1226,6 @@ mpages_merge(struct dba *dba, struct mparse *mp)
 nextpage:
                ohash_delete(&strings);
                ohash_delete(&names);
-               mpage = ohash_next(&mpages, &pslot);
        }
 }
 
@@ -1673,7 +1691,7 @@ parse_mdoc_Nm(struct mpage *mpage, const struct roff_meta *meta,
        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;
@@ -1993,11 +2011,12 @@ dbadd(struct dba *dba, struct mpage *mpage)
        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);