]> git.cameronkatri.com Git - mandoc.git/commitdiff
First step of making mandocdb a true makewhatis/mandb replacement:
authorKristaps Dzonsons <kristaps@bsd.lv>
Fri, 15 Jul 2011 10:15:24 +0000 (10:15 +0000)
committerKristaps Dzonsons <kristaps@bsd.lv>
Fri, 15 Jul 2011 10:15:24 +0000 (10:15 +0000)
accept a set of directories on the command line ("manpaths") that are
recursed for files.  The databases are created in each manpath root.
This temporarily removes OP_UPDATE and OP_DELETE functionality, which
will be added back in.

mandocdb.8
mandocdb.c

index 84f3abe771c3b2cf336a96880e80bfa732bbeeb9..f22466be4117bcf316db9d18b92ee9ec0ab67fd5 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: mandocdb.8,v 1.1 2011/07/14 14:36:37 schwarze Exp $
+.\"    $Id: mandocdb.8,v 1.2 2011/07/15 10:15:24 kristaps Exp $
 .\"
 .\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: July 14 2011 $
+.Dd $Mdocdate: July 15 2011 $
 .Dt MANDOCDB 8
 .Os
 .Sh NAME
@@ -22,9 +22,7 @@
 .Nd index UNIX manuals
 .Sh SYNOPSIS
 .Nm
-.Op Fl ruv
-.Op Fl d Ar dir
-.Ar
+.Ar dir...
 .Sh DESCRIPTION
 The
 .Nm
@@ -33,42 +31,33 @@ utility extracts keywords from
 manuals and indexes them for fast retrieval.
 The arguments are as follows:
 .Bl -tag -width Ds
-.It Fl d Ar dir
-The directory into which to write the keyword and index databases.
-.It Ar
-Read input from zero or more files in
+.It Ar dir...
+Recursively scan for
 .Xr mdoc 7
-or
+and
 .Xr man 7
 .Ux
-manual format.
-.It Fl r
-Remove entries.
-This will remove the index and keyword references.
-If the record is not found, it is ignored.
-.It Fl u
-Update the record.
-This will first remove the record (as in
-.Fl r )
-then re-add it.
-.It Fl v
-Verbose output.
-If specified once, prints the name of each indexed file.
-If twice, prints keywords for each file.
-.El
-.Pp
-By default,
-.Nm
-constructs a new
+manual files in each
+.Ar dir
+directory.
 .Sx Index Database
 and
 .Sx Keyword Database
-in the current working directory.
+files are installed in each
+.Ar dir
+directory.
 Existing databases are truncated.
+.El
+.Pp
+By default,
+.Nm
+does nothing: the
+.Ar dir...
+invocation must be used.
 .Pp
-If fatal parse errors are encountered, the offending file is printed to
-stderr, omitted from the index, and the parse continues with the next
-input file.
+If fatal parse errors are encountered while parsing, the offending file
+is printed to stderr, omitted from the index, and the parse continues
+with the next input file.
 .Ss Index Database
 The index database,
 .Pa mandoc.index ,
index cb2512bb0ec698d5757b1a28e39a7ef09c7e1a83..28dc43ca06b2a05853dfed260fb58c01a1c20759 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mandocdb.c,v 1.3 2011/07/15 09:06:23 kristaps Exp $ */
+/*     $Id: mandocdb.c,v 1.4 2011/07/15 10:15:24 kristaps Exp $ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -21,6 +21,7 @@
 #include <sys/param.h>
 
 #include <assert.h>
+#include <dirent.h>
 #include <fcntl.h>
 #include <getopt.h>
 #include <stdio.h>
@@ -63,6 +64,7 @@
 struct of {
        char             *fname;
        struct of        *next;
+       struct of        *first;
 };
 
 /* Buffer for storing growable data. */
@@ -107,6 +109,8 @@ static      void              index_merge(const struct of *, struct mparse *,
 static void              index_prune(const struct of *, DB *, 
                                const char *, DB *, const char *, 
                                recno_t *, recno_t **, size_t *);
+static int               ofile_build(const char *, struct of **);
+static void              ofile_free(struct of *);
 static int               pman_node(MAN_ARGS);
 static void              pmdoc_node(MDOC_ARGS);
 static void              pmdoc_An(MDOC_ARGS);
@@ -259,14 +263,12 @@ main(int argc, char *argv[])
 {
        struct mparse   *mp; /* parse sequence */
        enum op          op; /* current operation */
-       const char      *dir; /* result dir (default: cwd) */
        char             ibuf[MAXPATHLEN], /* index fname */
                         fbuf[MAXPATHLEN];  /* btree fname */
-       int              ch, verb, i;
+       int              ch, i, flags;
        DB              *idx, /* index database */
                        *db, /* keyword database */
                        *hash; /* temporary keyword hashtable */
-       enum mandoclevel ec; /* exit status */
        BTREEINFO        info; /* btree configuration */
        recno_t          maxrec; /* supremum of all records */
        recno_t         *recs; /* buffer of empty records */
@@ -274,7 +276,7 @@ main(int argc, char *argv[])
                         reccur; /* valid number of recs */
        struct buf       buf, /* keyword buffer */
                         dbuf; /* description buffer */
-       struct of       *ofile;
+       struct of       *of;
        extern int       optind;
        extern char     *optarg;
 
@@ -284,9 +286,7 @@ main(int argc, char *argv[])
        else
                ++progname;
 
-       ofile = NULL;
-       dir = "";
-       verb = 0;
+       of = NULL;
        db = idx = NULL;
        mp = NULL;
        hash = NULL;
@@ -294,25 +294,12 @@ main(int argc, char *argv[])
        recsz = reccur = 0;
        maxrec = 0;
        op = OP_NEW;
-       ec = MANDOCLEVEL_SYSERR;
 
        memset(&buf, 0, sizeof(struct buf));
        memset(&dbuf, 0, sizeof(struct buf));
 
-       while (-1 != (ch = getopt(argc, argv, "d:ruv")))
+       while (-1 != (ch = getopt(argc, argv, "")))
                switch (ch) {
-               case ('d'):
-                       dir = optarg;
-                       break;
-               case ('r'):
-                       op = OP_DELETE;
-                       break;
-               case ('u'):
-                       op = OP_UPDATE;
-                       break;
-               case ('v'):
-                       verb++;
-                       break;
                default:
                        usage();
                        return((int)MANDOCLEVEL_BADARG);
@@ -321,92 +308,63 @@ main(int argc, char *argv[])
        argc -= optind;
        argv += optind;
 
-       ibuf[0] = ibuf[MAXPATHLEN - 2] =
-               fbuf[0] = fbuf[MAXPATHLEN - 2] = '\0';
-
-       strlcat(fbuf, dir, MAXPATHLEN);
-       strlcat(fbuf, MANDOC_DB, MAXPATHLEN);
+       memset(&info, 0, sizeof(BTREEINFO));
+       info.flags = R_DUP;
 
-       strlcat(ibuf, dir, MAXPATHLEN);
-       strlcat(ibuf, MANDOC_IDX, MAXPATHLEN);
+       mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL);
 
-       if ('\0' != fbuf[MAXPATHLEN - 2] ||
-                       '\0' != ibuf[MAXPATHLEN - 2]) {
-               fprintf(stderr, "%s: Path too long\n", dir);
-               goto out;
-       }
+       flags = OP_NEW == op ? O_CREAT|O_TRUNC|O_RDWR : O_CREAT|O_RDWR;
 
-       /*
-        * For the keyword database, open a BTREE database that allows
-        * duplicates.  
-        * For the index database, use a standard RECNO database type.
-        * Truncate the database if we're creating a new one.
-        */
+       buf.size = dbuf.size = MANDOC_BUFSZ;
 
-       memset(&info, 0, sizeof(BTREEINFO));
-       info.flags = R_DUP;
+       buf.cp = mandoc_malloc(buf.size);
+       dbuf.cp = mandoc_malloc(dbuf.size);
 
-       if (OP_NEW == op) {
-               db = dbopen(fbuf, MANDOC_FLAGS, 0644, DB_BTREE, &info);
-               idx = dbopen(ibuf, MANDOC_FLAGS, 0644, DB_RECNO, NULL);
-       } else {
-               db = dbopen(fbuf, O_CREAT|O_RDWR, 0644, DB_BTREE, &info);
-               idx = dbopen(ibuf, O_CREAT|O_RDWR, 0644, DB_RECNO, NULL);
-       }
+       for (i = 0; i < argc; i++) {
+               ibuf[0] = ibuf[MAXPATHLEN - 2] =
+                       fbuf[0] = fbuf[MAXPATHLEN - 2] = '\0';
 
-       if (NULL == db) {
-               perror(fbuf);
-               goto out;
-       } else if (NULL == db) {
-               perror(ibuf);
-               goto out;
-       }
+               strlcat(fbuf, argv[i], MAXPATHLEN);
+               strlcat(fbuf, MANDOC_DB, MAXPATHLEN);
 
-       ofile = mandoc_calloc(argc, sizeof(struct of));
-       for (i = 0; i < argc; i++) {
-               ofile[i].next = &ofile[i + 1];
-               ofile[i].fname = argv[i];
-       }
+               strlcat(ibuf, argv[i], MAXPATHLEN);
+               strlcat(ibuf, MANDOC_IDX, MAXPATHLEN);
 
-       ofile[argc - 1].next = NULL;
+               if ('\0' != fbuf[MAXPATHLEN - 2] ||
+                               '\0' != ibuf[MAXPATHLEN - 2]) {
+                       fprintf(stderr, "%s: Path too long\n", argv[i]);
+                       break;
+               }
 
-       /*
-        * If we're going to delete or update a database, remove the
-        * entries now (both the index and all keywords pointing to it).
-        * This doesn't actually remove them: it only sets their record
-        * value lengths to zero.
-        * While doing so, add the empty records to a list we'll access
-        * later in re-adding entries to the database.
-        */
+               db = dbopen(fbuf, flags, 0644, DB_BTREE, &info);
+               idx = dbopen(ibuf, flags, 0644, DB_RECNO, NULL);
 
-       if (OP_DELETE == op || OP_UPDATE == op)
-               index_prune(ofile, db, fbuf, idx, ibuf, 
-                               &maxrec, &recs, &recsz);
+               if (NULL == db) {
+                       perror(fbuf);
+                       break;
+               } else if (NULL == db) {
+                       perror(ibuf);
+                       break;
+               }
 
-       if (OP_DELETE == op) {
-               ec = MANDOCLEVEL_OK;
-               goto out;
-       }
+               ofile_free(of);
+               of = NULL;
 
-       /*
-        * Add records to the database.
-        * Try parsing each manual given on the command line.  
-        * If we fail, then emit an error and keep on going.  
-        * Take resulting trees and push them down into the database code.
-        * Use the auto-parser and don't report any errors.
-        */
+               if ( ! ofile_build(argv[i], &of))
+                       break;
+               of = of->first;
 
-       mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL);
+               if (OP_DELETE == op || OP_UPDATE == op)
+                       index_prune(of, db, fbuf, idx, ibuf, 
+                                       &maxrec, &recs, &recsz);
 
-       buf.size = dbuf.size = MANDOC_BUFSZ;
-       buf.cp = mandoc_malloc(buf.size);
-       dbuf.cp = mandoc_malloc(dbuf.size);
+               if (OP_DELETE == op)
+                       continue;
 
-       index_merge(ofile, mp, &dbuf, &buf, hash, db, 
-                       fbuf, idx, ibuf, maxrec, recs, reccur);
+               index_merge(of, mp, &dbuf, &buf, hash, db, 
+                               fbuf, idx, ibuf, maxrec, recs, reccur);
+       }
 
-       ec = MANDOCLEVEL_OK;
-out:
        if (db)
                (*db->close)(db);
        if (idx)
@@ -416,12 +374,12 @@ out:
        if (mp)
                mparse_free(mp);
 
-       free(ofile);
+       ofile_free(of);
        free(buf.cp);
        free(dbuf.cp);
        free(recs);
 
-       return((int)ec);
+       return(i < argc ? MANDOCLEVEL_SYSERR : MANDOCLEVEL_OK);
 }
 
 void
@@ -1144,10 +1102,72 @@ pman_node(MAN_ARGS)
        return(0);
 }
 
+/*
+ * Recursively build up a list of files to parse.
+ * We use this instead of ftw() and so on because I don't want global
+ * variables hanging around.
+ * This ignores the mandoc.db and mandoc.index files, but assumes that
+ * everything else is a manual.
+ * Pass in a pointer to a NULL structure for the first invocation.
+ */
+static int
+ofile_build(const char *dir, struct of **of)
+{
+       DIR             *d;
+       const char      *fn;
+       struct of       *nof;
+       struct dirent   *dp;
+
+       if (NULL == (d = opendir(dir))) {
+               perror(dir);
+               return(0);
+       }
+
+       while (NULL != (dp = readdir(d))) {
+               fn = dp->d_name;
+               if (DT_DIR == dp->d_type) {
+                       if (strcmp(".", fn) && strcmp("..", fn))
+                               if ( ! ofile_build(dp->d_name, of))
+                                       return(0);
+                       continue;
+               } else if (DT_REG != dp->d_type)
+                       continue;
+
+               if (0 == strcmp(MANDOC_DB, fn) ||
+                               0 == strcmp(MANDOC_IDX, fn))
+                       continue;
+
+               nof = mandoc_calloc(1, sizeof(struct of));
+               nof->fname = mandoc_strdup(fn);
+
+               if (NULL == *of) {
+                       *of = nof;
+                       (*of)->first = nof;
+               } else {
+                       (*of)->next = nof;
+                       *of = nof;
+               }
+       }
+
+       return(1);
+}
+
+static void
+ofile_free(struct of *of)
+{
+       struct of       *nof;
+
+       while (of) {
+               nof = of->next;
+               free(of->fname);
+               free(of);
+               of = nof;
+       }
+}
+
 static void
 usage(void)
 {
 
-       fprintf(stderr, "usage: %s [-ruv] [-d path] [file...]\n", 
-                       progname);
+       fprintf(stderr, "usage: %s [dir...]\n", progname);
 }