]> git.cameronkatri.com Git - mandoc.git/blobdiff - mandocdb.c
Support .St -p1003.1-2013, "IEEE Std 1003.1-2008/Cor 1-2013".
[mandoc.git] / mandocdb.c
index 959dbfcefe29f9c5b2d93c6ccc0b5bc5d5501b80..31d168265a2be2e1e9dbab3becb49deb9e469468 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mandocdb.c,v 1.84 2013/12/27 15:39:03 schwarze Exp $ */
+/*     $Id: mandocdb.c,v 1.92 2013/12/31 19:40:20 schwarze Exp $ */
 /*
  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
 /*
  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
@@ -111,6 +111,7 @@ struct      mlink {
        char            *arch;    /* architecture from directory */
        char            *name;    /* name from file name (not empty) */
        char            *fsec;    /* section from file name suffix */
        char            *arch;    /* architecture from directory */
        char            *name;    /* name from file name (not empty) */
        char            *fsec;    /* section from file name suffix */
+       struct mlink    *next;    /* singly linked list */
 };
 
 struct title {
 };
 
 struct title {
@@ -141,9 +142,9 @@ static      void     filescan(const char *);
 static void    *hash_alloc(size_t, void *);
 static void     hash_free(void *, size_t, void *);
 static void    *hash_halloc(size_t, void *);
 static void    *hash_alloc(size_t, void *);
 static void     hash_free(void *, size_t, void *);
 static void    *hash_halloc(size_t, void *);
-static int      inocheck(const struct stat *);
 static void     mlink_add(struct mlink *, const struct stat *);
 static void     mlink_free(struct mlink *);
 static void     mlink_add(struct mlink *, const struct stat *);
 static void     mlink_free(struct mlink *);
+static void     mlinks_undupe(struct mpage *);
 static void     mpages_free(void);
 static void     mpages_merge(struct mchars *, struct mparse *, int);
 static void     parse_cat(struct mpage *);
 static void     mpages_free(void);
 static void     mpages_merge(struct mchars *, struct mparse *, int);
 static void     parse_cat(struct mpage *);
@@ -153,11 +154,9 @@ static     int      parse_mdoc_body(struct mpage *, const struct mdoc_node *);
 static int      parse_mdoc_head(struct mpage *, const struct mdoc_node *);
 static int      parse_mdoc_Fd(struct mpage *, const struct mdoc_node *);
 static int      parse_mdoc_Fn(struct mpage *, const struct mdoc_node *);
 static int      parse_mdoc_head(struct mpage *, const struct mdoc_node *);
 static int      parse_mdoc_Fd(struct mpage *, const struct mdoc_node *);
 static int      parse_mdoc_Fn(struct mpage *, const struct mdoc_node *);
-static int      parse_mdoc_In(struct mpage *, const struct mdoc_node *);
 static int      parse_mdoc_Nd(struct mpage *, const struct mdoc_node *);
 static int      parse_mdoc_Nm(struct mpage *, const struct mdoc_node *);
 static int      parse_mdoc_Sh(struct mpage *, const struct mdoc_node *);
 static int      parse_mdoc_Nd(struct mpage *, const struct mdoc_node *);
 static int      parse_mdoc_Nm(struct mpage *, const struct mdoc_node *);
 static int      parse_mdoc_Sh(struct mpage *, const struct mdoc_node *);
-static int      parse_mdoc_St(struct mpage *, const struct mdoc_node *);
 static int      parse_mdoc_Xr(struct mpage *, const struct mdoc_node *);
 static void     putkey(const struct mpage *,
                        const char *, uint64_t);
 static int      parse_mdoc_Xr(struct mpage *, const struct mdoc_node *);
 static void     putkey(const struct mpage *,
                        const char *, uint64_t);
@@ -215,7 +214,7 @@ static      const struct mdoc_handler mdocs[MDOC_MAX] = {
        { parse_mdoc_Fn, 0 },  /* Fn */
        { NULL, TYPE_Ft },  /* Ft */
        { NULL, TYPE_Ic },  /* Ic */
        { parse_mdoc_Fn, 0 },  /* Fn */
        { NULL, TYPE_Ft },  /* Ft */
        { NULL, TYPE_Ic },  /* Ic */
-       { parse_mdoc_In, TYPE_In },  /* In */
+       { NULL, TYPE_In },  /* In */
        { NULL, TYPE_Li },  /* Li */
        { parse_mdoc_Nd, TYPE_Nd },  /* Nd */
        { parse_mdoc_Nm, TYPE_Nm },  /* Nm */
        { NULL, TYPE_Li },  /* Li */
        { parse_mdoc_Nd, TYPE_Nd },  /* Nd */
        { parse_mdoc_Nm, TYPE_Nm },  /* Nm */
@@ -223,7 +222,7 @@ static      const struct mdoc_handler mdocs[MDOC_MAX] = {
        { NULL, 0 },  /* Ot */
        { NULL, TYPE_Pa },  /* Pa */
        { NULL, 0 },  /* Rv */
        { NULL, 0 },  /* Ot */
        { NULL, TYPE_Pa },  /* Pa */
        { NULL, 0 },  /* Rv */
-       { parse_mdoc_St, 0 },  /* St */
+       { NULL, TYPE_St },  /* St */
        { NULL, TYPE_Va },  /* Va */
        { parse_mdoc_body, TYPE_Va },  /* Vt */
        { parse_mdoc_Xr, 0 },  /* Xr */
        { NULL, TYPE_Va },  /* Va */
        { parse_mdoc_body, TYPE_Va },  /* Vt */
        { parse_mdoc_Xr, 0 },  /* Xr */
@@ -548,7 +547,6 @@ treescan(void)
                /*
                 * If we're a regular file, add an mlink by using the
                 * stored directory data and handling the filename.
                /*
                 * If we're a regular file, add an mlink by using the
                 * stored directory data and handling the filename.
-                * Disallow duplicate (hard-linked) files.
                 */
                if (FTS_F == ff->fts_info) {
                        if (0 == strcmp(path, MANDOC_DB))
                 */
                if (FTS_F == ff->fts_info) {
                        if (0 == strcmp(path, MANDOC_DB))
@@ -557,10 +555,6 @@ treescan(void)
                                if (warnings)
                                        say(path, "Extraneous file");
                                continue;
                                if (warnings)
                                        say(path, "Extraneous file");
                                continue;
-                       } else if (inocheck(ff->fts_statp)) {
-                               if (warnings)
-                                       say(path, "Duplicate file");
-                               continue;
                        } else if (NULL == (fsec =
                                        strrchr(ff->fts_name, '.'))) {
                                if ( ! use_all) {
                        } else if (NULL == (fsec =
                                        strrchr(ff->fts_name, '.'))) {
                                if ( ! use_all) {
@@ -667,7 +661,7 @@ treescan(void)
 }
 
 /*
 }
 
 /*
- * Add a file to the file vector.
+ * Add a file to the mlinks table.
  * Do not verify that it's a "valid" looking manpage (we'll do that
  * later).
  *
  * Do not verify that it's a "valid" looking manpage (we'll do that
  * later).
  *
@@ -678,7 +672,6 @@ treescan(void)
  *   or
  *   [./]cat<section>[/<arch>]/<name>.0
  *
  *   or
  *   [./]cat<section>[/<arch>]/<name>.0
  *
- * Stuff this information directly into the mlink vector.
  * See treescan() for the fts(3) version of this.
  */
 static void
  * See treescan() for the fts(3) version of this.
  */
 static void
@@ -710,10 +703,6 @@ filescan(const char *file)
                exitcode = (int)MANDOCLEVEL_BADARG;
                say(file, "Not a regular file");
                return;
                exitcode = (int)MANDOCLEVEL_BADARG;
                say(file, "Not a regular file");
                return;
-       } else if (inocheck(&st)) {
-               if (warnings)
-                       say(file, "Duplicate file");
-               return;
        }
        start = buf + strlen(basedir);
        mlink = mandoc_calloc(1, sizeof(struct mlink));
        }
        start = buf + strlen(basedir);
        mlink = mandoc_calloc(1, sizeof(struct mlink));
@@ -770,20 +759,6 @@ filescan(const char *file)
        mlink_add(mlink, &st);
 }
 
        mlink_add(mlink, &st);
 }
 
-static int
-inocheck(const struct stat *st)
-{
-       struct inodev    inodev;
-       uint32_t         hash;
-
-       memset(&inodev, 0, sizeof(inodev));
-       inodev.st_ino = hash = st->st_ino;
-       inodev.st_dev = st->st_dev;
-
-       return(NULL != ohash_find(&mpages, ohash_lookup_memory(
-                       &mpages, (char *)&inodev, sizeof(inodev), hash)));
-}
-
 static void
 mlink_add(struct mlink *mlink, const struct stat *st)
 {
 static void
 mlink_add(struct mlink *mlink, const struct stat *st)
 {
@@ -826,7 +801,7 @@ mlink_add(struct mlink *mlink, const struct stat *st)
                mpage->inodev.st_dev = inodev.st_dev;
                ohash_insert(&mpages, slot, mpage);
        } else
                mpage->inodev.st_dev = inodev.st_dev;
                ohash_insert(&mpages, slot, mpage);
        } else
-               abort();
+               mlink->next = mpage->mlinks;
        mpage->mlinks = mlink;
 }
 
        mpage->mlinks = mlink;
 }
 
@@ -851,7 +826,7 @@ mpages_free(void)
        mpage = ohash_first(&mpages, &slot);
        while (NULL != mpage) {
                while (NULL != (mlink = mpage->mlinks)) {
        mpage = ohash_first(&mpages, &slot);
        while (NULL != mpage) {
                while (NULL != (mlink = mpage->mlinks)) {
-                       mpage->mlinks = NULL;
+                       mpage->mlinks = mlink->next;
                        mlink_free(mlink);
                }
                free(mpage->sec);
                        mlink_free(mlink);
                }
                free(mpage->sec);
@@ -863,6 +838,53 @@ mpages_free(void)
        }
 }
 
        }
 }
 
+/*
+ * For each mlink to the mpage, check whether the path looks like
+ * it is formatted, and if it does, check whether a source manual
+ * exists by the same name, ignoring the suffix.
+ * If both conditions hold, drop the mlink.
+ */
+static void
+mlinks_undupe(struct mpage *mpage)
+{
+       char              buf[PATH_MAX];
+       struct mlink    **prev;
+       struct mlink     *mlink;
+       char             *bufp;
+
+       mpage->form = FORM_CAT;
+       prev = &mpage->mlinks;
+       while (NULL != (mlink = *prev)) {
+               if (FORM_CAT != mlink->dform) {
+                       mpage->form = FORM_NONE;
+                       goto nextlink;
+               }
+               if (strlcpy(buf, mlink->file, PATH_MAX) >= PATH_MAX) {
+                       if (warnings)
+                               say(mlink->file, "Filename too long");
+                       goto nextlink;
+               }
+               bufp = strstr(buf, "cat");
+               assert(NULL != bufp);
+               memcpy(bufp, "man", 3);
+               if (NULL != (bufp = strrchr(buf, '.')))
+                       *++bufp = '\0';
+               strlcat(buf, mlink->dsec, PATH_MAX);
+               if (NULL == ohash_find(&mlinks,
+                               ohash_qlookup(&mlinks, buf)))
+                       goto nextlink;
+               if (warnings)
+                       say(mlink->file, "Man source exists: %s", buf);
+               if (use_all)
+                       goto nextlink;
+               *prev = mlink->next;
+               mlink_free(mlink);
+               continue;
+nextlink:
+               prev = &(*prev)->next;
+       }
+}
+
 /*
  * Run through the files in the global vector "mpages"
  * and add them to the database specified in "basedir".
 /*
  * Run through the files in the global vector "mpages"
  * and add them to the database specified in "basedir".
@@ -875,14 +897,12 @@ mpages_merge(struct mchars *mc, struct mparse *mp, int check_reachable)
 {
        struct ohash             title_table;
        struct ohash_info        title_info, str_info;
 {
        struct ohash             title_table;
        struct ohash_info        title_info, str_info;
-       char                     buf[PATH_MAX];
        struct mpage            *mpage;
        struct mdoc             *mdoc;
        struct man              *man;
        struct title            *title_entry;
        struct mpage            *mpage;
        struct mdoc             *mdoc;
        struct man              *man;
        struct title            *title_entry;
-       char                    *bufp, *title_str;
+       char                    *title_str;
        const char              *cp;
        const char              *cp;
-       size_t                   sz;
        int                      match;
        unsigned int             pslot, tslot;
        enum mandoclevel         lvl;
        int                      match;
        unsigned int             pslot, tslot;
        enum mandoclevel         lvl;
@@ -902,36 +922,10 @@ mpages_merge(struct mchars *mc, struct mparse *mp, int check_reachable)
 
        mpage = ohash_first(&mpages, &pslot);
        while (NULL != mpage) {
 
        mpage = ohash_first(&mpages, &pslot);
        while (NULL != mpage) {
-               /*
-                * If we're a catpage (as defined by our path), then see
-                * if a manpage exists by the same name (ignoring the
-                * suffix).
-                * If it does, then we want to use it instead of our
-                * own.
-                */
-               if ( ! use_all && FORM_CAT == mpage->mlinks->dform) {
-                       sz = strlcpy(buf, mpage->mlinks->file, PATH_MAX);
-                       if (sz >= PATH_MAX) {
-                               if (warnings)
-                                       say(mpage->mlinks->file,
-                                           "Filename too long");
-                               mpage = ohash_next(&mpages, &pslot);
-                               continue;
-                       }
-                       bufp = strstr(buf, "cat");
-                       assert(NULL != bufp);
-                       memcpy(bufp, "man", 3);
-                       if (NULL != (bufp = strrchr(buf, '.')))
-                               *++bufp = '\0';
-                       strlcat(buf, mpage->mlinks->dsec, PATH_MAX);
-                       if (NULL != ohash_find(&mlinks,
-                                       ohash_qlookup(&mlinks, buf))) {
-                               if (warnings)
-                                       say(mpage->mlinks->file, "Man "
-                                           "source exists: %s", buf);
-                               mpage = ohash_next(&mpages, &pslot);
-                               continue;
-                       }
+               mlinks_undupe(mpage);
+               if (NULL == mpage->mlinks) {
+                       mpage = ohash_next(&mpages, &pslot);
+                       continue;
                }
 
                ohash_init(&strings, 6, &str_info);
                }
 
                ohash_init(&strings, 6, &str_info);
@@ -1445,18 +1439,7 @@ parse_mdoc_Fd(struct mpage *mpage, const struct mdoc_node *n)
 
        if (end > start)
                putkeys(mpage, start, end - start + 1, TYPE_In);
 
        if (end > start)
                putkeys(mpage, start, end - start + 1, TYPE_In);
-       return(1);
-}
-
-static int
-parse_mdoc_In(struct mpage *mpage, const struct mdoc_node *n)
-{
-
-       if (NULL != n->child && MDOC_TEXT == n->child->type)
-               return(0);
-
-       putkey(mpage, n->child->string, TYPE_In);
-       return(1);
+       return(0);
 }
 
 static int
 }
 
 static int
@@ -1492,17 +1475,6 @@ parse_mdoc_Fn(struct mpage *mpage, const struct mdoc_node *n)
        return(0);
 }
 
        return(0);
 }
 
-static int
-parse_mdoc_St(struct mpage *mpage, const struct mdoc_node *n)
-{
-
-       if (NULL == n->child || MDOC_TEXT != n->child->type)
-               return(0);
-
-       putkey(mpage, n->child->string, TYPE_St);
-       return(1);
-}
-
 static int
 parse_mdoc_Xr(struct mpage *mpage, const struct mdoc_node *n)
 {
 static int
 parse_mdoc_Xr(struct mpage *mpage, const struct mdoc_node *n)
 {
@@ -1560,12 +1532,8 @@ static int
 parse_mdoc_Nm(struct mpage *mpage, const struct mdoc_node *n)
 {
 
 parse_mdoc_Nm(struct mpage *mpage, const struct mdoc_node *n)
 {
 
-       if (SEC_NAME == n->sec)
-               return(1);
-       else if (SEC_SYNOPSIS != n->sec || MDOC_HEAD != n->type)
-               return(0);
-
-       return(1);
+       return(SEC_NAME == n->sec ||
+           (SEC_SYNOPSIS == n->sec && MDOC_HEAD == n->type));
 }
 
 static int
 }
 
 static int
@@ -1738,7 +1706,6 @@ utf8key(struct mchars *mc, struct str *key)
                /* Read past the slash. */
 
                val++;
                /* Read past the slash. */
 
                val++;
-               u = 0;
 
                /*
                 * Parse the escape sequence and see if it's a
 
                /*
                 * Parse the escape sequence and see if it's a
@@ -1786,6 +1753,7 @@ utf8key(struct mchars *mc, struct str *key)
 static void
 dbindex(const struct mpage *mpage, struct mchars *mc)
 {
 static void
 dbindex(const struct mpage *mpage, struct mchars *mc)
 {
+       struct mlink    *mlink;
        struct str      *key;
        const char      *desc;
        int64_t          recno;
        struct str      *key;
        const char      *desc;
        int64_t          recno;
@@ -1825,13 +1793,16 @@ dbindex(const struct mpage *mpage, struct mchars *mc)
        recno = sqlite3_last_insert_rowid(db);
        sqlite3_reset(stmts[STMT_INSERT_PAGE]);
 
        recno = sqlite3_last_insert_rowid(db);
        sqlite3_reset(stmts[STMT_INSERT_PAGE]);
 
-       i = 1;
-       SQL_BIND_TEXT(stmts[STMT_INSERT_LINK], i, mpage->mlinks->dsec);
-       SQL_BIND_TEXT(stmts[STMT_INSERT_LINK], i, mpage->mlinks->arch);
-       SQL_BIND_TEXT(stmts[STMT_INSERT_LINK], i, mpage->mlinks->file);
-       SQL_BIND_INT64(stmts[STMT_INSERT_LINK], i, recno);
-       SQL_STEP(stmts[STMT_INSERT_LINK]);
-       sqlite3_reset(stmts[STMT_INSERT_LINK]);
+       for (mlink = mpage->mlinks; mlink; mlink = mlink->next) {
+               i = 1;
+               SQL_BIND_TEXT(stmts[STMT_INSERT_LINK], i, mlink->file);
+               SQL_BIND_TEXT(stmts[STMT_INSERT_LINK], i, mlink->dsec);
+               SQL_BIND_TEXT(stmts[STMT_INSERT_LINK], i, mlink->arch);
+               SQL_BIND_TEXT(stmts[STMT_INSERT_LINK], i, mlink->name);
+               SQL_BIND_INT64(stmts[STMT_INSERT_LINK], i, recno);
+               SQL_STEP(stmts[STMT_INSERT_LINK]);
+               sqlite3_reset(stmts[STMT_INSERT_LINK]);
+       }
 
        for (key = ohash_first(&strings, &slot); NULL != key;
             key = ohash_next(&strings, &slot)) {
 
        for (key = ohash_first(&strings, &slot); NULL != key;
             key = ohash_next(&strings, &slot)) {
@@ -1967,6 +1938,7 @@ dbopen(int real)
              ");\n"
              "\n"
              "CREATE TABLE \"mlinks\" (\n"
              ");\n"
              "\n"
              "CREATE TABLE \"mlinks\" (\n"
+             " \"file\" TEXT NOT NULL,\n"
              " \"sec\" TEXT NOT NULL,\n"
              " \"arch\" TEXT NOT NULL,\n"
              " \"name\" TEXT NOT NULL,\n"
              " \"sec\" TEXT NOT NULL,\n"
              " \"arch\" TEXT NOT NULL,\n"
              " \"name\" TEXT NOT NULL,\n"
@@ -1999,7 +1971,7 @@ prepare_statements:
                "(file,sec,arch,desc,form) VALUES (?,?,?,?,?)";
        sqlite3_prepare_v2(db, sql, -1, &stmts[STMT_INSERT_PAGE], NULL);
        sql = "INSERT INTO mlinks "
                "(file,sec,arch,desc,form) VALUES (?,?,?,?,?)";
        sqlite3_prepare_v2(db, sql, -1, &stmts[STMT_INSERT_PAGE], NULL);
        sql = "INSERT INTO mlinks "
-               "(sec,arch,name,pageid) VALUES (?,?,?,?)";
+               "(file,sec,arch,name,pageid) VALUES (?,?,?,?,?)";
        sqlite3_prepare_v2(db, sql, -1, &stmts[STMT_INSERT_LINK], NULL);
        sql = "INSERT INTO keys "
                "(bits,key,pageid) VALUES (?,?,?)";
        sqlite3_prepare_v2(db, sql, -1, &stmts[STMT_INSERT_LINK], NULL);
        sql = "INSERT INTO keys "
                "(bits,key,pageid) VALUES (?,?,?)";