[BACK]Return to mandoc-db.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/Attic/mandoc-db.c between version 1.2 and 1.6

version 1.2, 2011/04/03 10:14:45 version 1.6, 2011/04/05 13:09:33
Line 38 
Line 38 
 #include "mandoc.h"  #include "mandoc.h"
   
 #define MANDOC_DB        "mandoc.db"  #define MANDOC_DB        "mandoc.db"
   #define MANDOC_IDX       "mandoc.index"
 #define MANDOC_BUFSZ      BUFSIZ  #define MANDOC_BUFSZ      BUFSIZ
   #define MANDOC_FLAGS      O_CREAT|O_TRUNC|O_RDWR
   
 enum    type {  enum    type {
         MANDOC_NONE = 0,          MANDOC_NONE = 0,
Line 49  enum type {
Line 51  enum type {
         MANDOC_VARIABLE          MANDOC_VARIABLE
 };  };
   
   #define MAN_ARGS          DB *db, \
                             const char *dbn, \
                             DBT *key, size_t *ksz, \
                             DBT *val, \
                             const struct man_node *n
 #define MDOC_ARGS         DB *db, \  #define MDOC_ARGS         DB *db, \
                           const char *dbn, \                            const char *dbn, \
                           DBT *key, size_t *ksz, \                            DBT *key, size_t *ksz, \
Line 59  static void    dbt_append(DBT *, size_t *, const char 
Line 66  static void    dbt_append(DBT *, size_t *, const char 
 static  void              dbt_appendb(DBT *, size_t *,  static  void              dbt_appendb(DBT *, size_t *,
                                 const void *, size_t);                                  const void *, size_t);
 static  void              dbt_init(DBT *, size_t *);  static  void              dbt_init(DBT *, size_t *);
 static  void              version(void);  
 static  void              usage(void);  static  void              usage(void);
   static  void              pman(DB *, const char *,
                                   DBT *, size_t *, DBT *,
                                   const char *, struct man *);
   static  int               pman_node(MAN_ARGS);
 static  void              pmdoc(DB *, const char *,  static  void              pmdoc(DB *, const char *,
                                 DBT *, size_t *,                                  DBT *, size_t *, DBT *,
                                 DBT *, size_t *,  
                                 const char *, struct mdoc *);                                  const char *, struct mdoc *);
 static  void              pmdoc_node(MDOC_ARGS);  static  void              pmdoc_node(MDOC_ARGS);
 static  void              pmdoc_Fd(MDOC_ARGS);  static  void              pmdoc_Fd(MDOC_ARGS);
Line 207  main(int argc, char *argv[])
Line 216  main(int argc, char *argv[])
 {  {
         struct mparse   *mp; /* parse sequence */          struct mparse   *mp; /* parse sequence */
         struct mdoc     *mdoc; /* resulting mdoc */          struct mdoc     *mdoc; /* resulting mdoc */
         const char      *fn,          struct man      *man; /* resulting man */
                         *dir; /* result dir (default: cwd) */          char            *fn;
         char             fbuf[MAXPATHLEN],  /* btree fname */          const char      *dir; /* result dir (default: cwd) */
           char             ibuf[MAXPATHLEN], /* index fname */
                            ibbuf[MAXPATHLEN], /* index backup fname */
                            fbuf[MAXPATHLEN],  /* btree fname */
                          fbbuf[MAXPATHLEN]; /* btree backup fname */                           fbbuf[MAXPATHLEN]; /* btree backup fname */
         int              c;          int              c;
         DB              *db; /* open database */          DB              *index, /* index database */
         DBT              key, val; /* persistent entries */                          *db; /* keyword database */
         size_t           ksz, vsz; /* entry buffer sizes */          DBT              rkey, rval, /* recno entries */
                            key, val; /* persistent keyword entries */
           size_t           ksz; /* entry buffer size */
           char             vbuf[8];
         BTREEINFO        info; /* btree configuration */          BTREEINFO        info; /* btree configuration */
           recno_t          rec;
         extern int       optind;          extern int       optind;
         extern char     *optarg;          extern char     *optarg;
   
Line 225  main(int argc, char *argv[])
Line 241  main(int argc, char *argv[])
         else          else
                 ++progname;                  ++progname;
   
         dir = "./";          dir = "";
   
         while (-1 != (c = getopt(argc, argv, "d:V")))          while (-1 != (c = getopt(argc, argv, "d:")))
                 switch (c) {                  switch (c) {
                 case ('d'):                  case ('d'):
                         dir = optarg;                          dir = optarg;
                         break;                          break;
                 case ('V'):  
                         version();  
                         return((int)MANDOCLEVEL_OK);  
                 default:                  default:
                         usage();                          usage();
                         return((int)MANDOCLEVEL_BADARG);                          return((int)MANDOCLEVEL_BADARG);
Line 244  main(int argc, char *argv[])
Line 257  main(int argc, char *argv[])
         argv += optind;          argv += optind;
   
         /*          /*
          * Set up a temporary file-name into which we're going to write           * Set up temporary file-names into which we're going to write
          * all of our data.  This is securely renamed to the real           * all of our data (both for the index and database).  These
          * file-name after we've written all of our data.           * will be securely renamed to the real file-names after we've
            * written all of our data.
          */           */
   
         fbuf[0] = fbuf[MAXPATHLEN - 2] =          ibuf[0] = ibuf[MAXPATHLEN - 2] =
                 fbbuf[0] = fbbuf[MAXPATHLEN - 1] = '\0';                  ibbuf[0] = ibbuf[MAXPATHLEN - 2] =
                   fbuf[0] = fbuf[MAXPATHLEN - 2] =
                   fbbuf[0] = fbbuf[MAXPATHLEN - 2] = '\0';
   
         strlcat(fbuf, dir, MAXPATHLEN);          strlcat(fbuf, dir, MAXPATHLEN);
         strlcat(fbuf, MANDOC_DB, MAXPATHLEN);          strlcat(fbuf, MANDOC_DB, MAXPATHLEN);
   
         strlcat(fbbuf, fbuf, MAXPATHLEN);          strlcat(fbbuf, fbuf, MAXPATHLEN);
         strlcat(fbbuf, "~", MAXPATHLEN);          strlcat(fbbuf, "~", MAXPATHLEN);
   
           strlcat(ibuf, dir, MAXPATHLEN);
           strlcat(ibuf, MANDOC_IDX, MAXPATHLEN);
   
           strlcat(ibbuf, ibuf, MAXPATHLEN);
           strlcat(ibbuf, "~", MAXPATHLEN);
   
         if ('\0' != fbuf[MAXPATHLEN - 2] ||          if ('\0' != fbuf[MAXPATHLEN - 2] ||
                         '\0' != fbbuf[MAXPATHLEN - 2]) {                          '\0' != fbbuf[MAXPATHLEN - 2] ||
                 fprintf(stderr, "%s: Bad filename\n", progname);                          '\0' != ibuf[MAXPATHLEN - 2] ||
                           '\0' != ibbuf[MAXPATHLEN - 2]) {
                   fprintf(stderr, "%s: Path too long\n", progname);
                 exit((int)MANDOCLEVEL_SYSERR);                  exit((int)MANDOCLEVEL_SYSERR);
         }          }
   
         /*          /*
          * Open a BTREE database that allows duplicates.  If the           * For the keyword database, open a BTREE database that allows
          * database already exists (it's a backup anyway), then blow it           * duplicates.  For the index database, use a standard RECNO
          * away with O_TRUNC.           * database type.
          */           */
   
         memset(&info, 0, sizeof(BTREEINFO));          memset(&info, 0, sizeof(BTREEINFO));
         info.flags = R_DUP;          info.flags = R_DUP;
           db = dbopen(fbbuf, MANDOC_FLAGS, 0644, DB_BTREE, &info);
   
         db = dbopen(fbbuf, O_CREAT|O_TRUNC|O_RDWR,  
                         0644, DB_BTREE, &info);  
   
         if (NULL == db) {          if (NULL == db) {
                 perror(fbbuf);                  perror(fbbuf);
                 exit((int)MANDOCLEVEL_SYSERR);                  exit((int)MANDOCLEVEL_SYSERR);
         }          }
   
         /* Use the auto-parser and don't report any errors. */          index = dbopen(ibbuf, MANDOC_FLAGS, 0644, DB_RECNO, NULL);
   
         mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL);          if (NULL == db) {
                   perror(ibbuf);
                   (*db->close)(db);
                   exit((int)MANDOCLEVEL_SYSERR);
           }
   
         /*          /*
          * Try parsing the manuals given on the command line.  If we           * Try parsing the manuals given on the command line.  If we
          * totally fail, then just keep on going.  Take resulting trees           * totally fail, then just keep on going.  Take resulting trees
          * and push them down into the database code.           * and push them down into the database code.
            * Use the auto-parser and don't report any errors.
          */           */
   
           mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL);
   
         memset(&key, 0, sizeof(DBT));          memset(&key, 0, sizeof(DBT));
         memset(&val, 0, sizeof(DBT));          memset(&val, 0, sizeof(DBT));
         ksz = vsz = 0;          memset(&rkey, 0, sizeof(DBT));
           memset(&rval, 0, sizeof(DBT));
   
           val.size = sizeof(vbuf);
           val.data = vbuf;
           rkey.size = sizeof(recno_t);
   
           rec = 1;
           ksz = 0;
   
         while (NULL != (fn = *argv++)) {          while (NULL != (fn = *argv++)) {
                 mparse_reset(mp);                  mparse_reset(mp);
                 if (mparse_readfd(mp, -1, fn) >= MANDOCLEVEL_FATAL)  
                   if (mparse_readfd(mp, -1, fn) >= MANDOCLEVEL_FATAL) {
                           fprintf(stderr, "%s: Parse failure\n", fn);
                         continue;                          continue;
                 mparse_result(mp, &mdoc, NULL);                  }
   
                   mparse_result(mp, &mdoc, &man);
                   if (NULL == mdoc && NULL == man)
                           continue;
   
                   rkey.data = &rec;
                   rval.data = fn;
                   rval.size = strlen(fn) + 1;
   
                   if (-1 == (*index->put)(index, &rkey, &rval, 0)) {
                           perror(ibbuf);
                           break;
                   }
   
                   memset(val.data, 0, sizeof(uint32_t));
                   memcpy(val.data + 4, &rec, sizeof(uint32_t));
   
                 if (mdoc)                  if (mdoc)
                         pmdoc(db, fbbuf, &key, &ksz,                          pmdoc(db, fbbuf, &key, &ksz, &val, fn, mdoc);
                                 &val, &vsz, fn, mdoc);                  else
                           pman(db, fbbuf, &key, &ksz, &val, fn, man);
                   rec++;
         }          }
   
         (*db->close)(db);          (*db->close)(db);
           (*index->close)(index);
   
         mparse_free(mp);          mparse_free(mp);
   
         free(key.data);          free(key.data);
         free(val.data);  
   
         /* Atomically replace the file with our temporary one. */          /* Atomically replace the file with our temporary one. */
   
         if (-1 == rename(fbbuf, fbuf))          if (-1 == rename(fbbuf, fbuf))
                 perror(fbuf);                  perror(fbuf);
           if (-1 == rename(ibbuf, ibuf))
                   perror(fbuf);
   
         return((int)MANDOCLEVEL_OK);          return((int)MANDOCLEVEL_OK);
 }  }
Line 351  dbt_appendb(DBT *key, size_t *ksz, const void *cp, siz
Line 413  dbt_appendb(DBT *key, size_t *ksz, const void *cp, siz
   
         while (key->size + sz >= *ksz) {          while (key->size + sz >= *ksz) {
                 *ksz = key->size + sz + MANDOC_BUFSZ;                  *ksz = key->size + sz + MANDOC_BUFSZ;
                 *ksz = *ksz + (4 - (*ksz % 4));  
                 key->data = mandoc_realloc(key->data, *ksz);                  key->data = mandoc_realloc(key->data, *ksz);
         }          }
   
Line 369  dbt_append(DBT *key, size_t *ksz, const char *cp)
Line 430  dbt_append(DBT *key, size_t *ksz, const char *cp)
 {  {
         size_t           sz;          size_t           sz;
   
         assert(key->data);  
         assert(key->size <= *ksz);  
   
         if (0 == (sz = strlen(cp)))          if (0 == (sz = strlen(cp)))
                 return;                  return;
   
         /* Overshoot by MANDOC_BUFSZ (and nil terminator). */          assert(key->data);
   
         while (key->size + sz + 1 >= *ksz) {  
                 *ksz = key->size + sz + 1 + MANDOC_BUFSZ;  
                 *ksz = *ksz + (4 - (*ksz % 4));  
                 key->data = mandoc_realloc(key->data, *ksz);  
         }  
   
         /* Space-separate appended tokens. */  
   
         if (key->size)          if (key->size)
                 ((char *)key->data)[(int)key->size - 1] = ' ';                  ((char *)key->data)[(int)key->size - 1] = ' ';
   
         memcpy(key->data + (int)key->size, cp, sz + 1);          dbt_appendb(key, ksz, cp, sz + 1);
         key->size += sz + 1;  
 }  }
   
 /* ARGSUSED */  /* ARGSUSED */
Line 405  pmdoc_Fd(MDOC_ARGS)
Line 454  pmdoc_Fd(MDOC_ARGS)
                 return;                  return;
         if (NULL == (n = n->child) || MDOC_TEXT != n->type)          if (NULL == (n = n->child) || MDOC_TEXT != n->type)
                 return;                  return;
   
           /*
            * Only consider those `Fd' macro fields that begin with an
            * "inclusion" token (versus, e.g., #define).
            */
         if (strcmp("#include", n->string))          if (strcmp("#include", n->string))
                 return;                  return;
   
         if (NULL == (n = n->next) || MDOC_TEXT != n->type)          if (NULL == (n = n->next) || MDOC_TEXT != n->type)
                 return;                  return;
   
           /*
            * Strip away the enclosing angle brackets and make sure we're
            * not zero-length.
            */
   
         start = n->string;          start = n->string;
         if ('<' == *start)          if ('<' == *start || '"' == *start)
                 start++;                  start++;
   
         if (0 == (sz = strlen(start)))          if (0 == (sz = strlen(start)))
                 return;                  return;
   
         end = &start[(int)sz - 1];          end = &start[(int)sz - 1];
         if ('>' == *end)          if ('>' == *end || '"' == *end)
                 end--;                  end--;
   
         nil = '\0';          nil = '\0';
Line 463  pmdoc_Fn(MDOC_ARGS)
Line 523  pmdoc_Fn(MDOC_ARGS)
         if (NULL == cp)          if (NULL == cp)
                 cp = n->child->string;                  cp = n->child->string;
   
         /* Ignore pointers. */          /* Strip away pointer symbol. */
   
         while ('*' == *cp)          while ('*' == *cp)
                 cp++;                  cp++;
Line 490  pmdoc_Vt(MDOC_ARGS)
Line 550  pmdoc_Vt(MDOC_ARGS)
                 return;                  return;
   
         /*          /*
          * Strip away leading '*' and trailing ';'.           * Strip away leading pointer symbol '*' and trailing ';'.
          */           */
   
         start = n->last->string;          start = n->last->string;
Line 602  pmdoc_node(MDOC_ARGS)
Line 662  pmdoc_node(MDOC_ARGS)
         pmdoc_node(db, dbn, key, ksz, val, n->next);          pmdoc_node(db, dbn, key, ksz, val, n->next);
 }  }
   
 static void  static int
 pmdoc(DB *db, const char *dbn,  pman_node(MAN_ARGS)
                 DBT *key, size_t *ksz,  
                 DBT *val, size_t *valsz,  
                 const char *path, struct mdoc *m)  
 {  {
         uint32_t         flag;          const struct man_node *head, *body;
           const char      *end, *start;
           char             nil;
           uint32_t         fl;
   
         flag = MANDOC_NONE;          if (NULL == n)
                   return(0);
   
         /*          /*
          * Database values are a 4-byte bit-field followed by the path           * We're only searching for one thing: the first text child in
          * of the manual.  Allocate all the space we'll need now; we           * the BODY of a NAME section.  Since we don't keep track of
          * change the bit-field depending on the key type.           * sections in -man, run some hoops to find out whether we're in
            * the correct section or not.
          */           */
   
         dbt_init(val, valsz);          if (MAN_BODY == n->type && MAN_SH == n->tok) {
         dbt_appendb(val, valsz, &flag, 4);                  body = n;
         dbt_append(val, valsz, path);                  assert(body->parent);
                   if (NULL != (head = body->parent->head) &&
                                   1 == head->nchild &&
                                   NULL != (head = (head->child)) &&
                                   MAN_TEXT == head->type &&
                                   0 == strcmp(head->string, "NAME") &&
                                   NULL != (body = body->child) &&
                                   MAN_TEXT == body->type) {
                           nil = '\0';
   
         pmdoc_node(db, dbn, key, ksz, val, mdoc_node(m));                          start = body->string;
                           if (NULL == (end = strchr(start, ' ')))
                                   end = start + strlen(start);
   
                           dbt_init(key, ksz);
                           dbt_appendb(key, ksz, start, end - start + 1);
                           dbt_appendb(key, ksz, &nil, 1);
                           fl = MANDOC_NAME;
                           memcpy(val->data, &fl, 4);
                           return(1);
                   }
           }
   
           if (pman_node(db, dbn, key, ksz, val, n->child))
                   return(1);
           if (pman_node(db, dbn, key, ksz, val, n->next))
                   return(1);
   
           return(0);
 }  }
   
 static void  static void
 version(void)  pman(DB *db, const char *dbn,
                   DBT *key, size_t *ksz, DBT *val,
                   const char *path, struct man *m)
 {  {
   
         printf("%s %s\n", progname, VERSION);          pman_node(db, dbn, key, ksz, val, man_node(m));
 }  }
   
   
 static void  static void
   pmdoc(DB *db, const char *dbn,
                   DBT *key, size_t *ksz, DBT *val,
                   const char *path, struct mdoc *m)
   {
   
           pmdoc_node(db, dbn, key, ksz, val, mdoc_node(m));
   }
   
   static void
 usage(void)  usage(void)
 {  {
   
         fprintf(stderr, "usage: %s "          fprintf(stderr, "usage: %s "
                         "[-V] "  
                         "[-d path] "                          "[-d path] "
                         "[file...]\n",                          "[file...]\n",
                         progname);                          progname);

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.6

CVSweb