=================================================================== RCS file: /cvs/mandoc/mandocdb.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -p -r1.11 -r1.12 --- mandoc/mandocdb.c 2011/11/24 12:54:19 1.11 +++ mandoc/mandocdb.c 2011/11/26 11:23:56 1.12 @@ -1,6 +1,7 @@ -/* $Id: mandocdb.c,v 1.11 2011/11/24 12:54:19 kristaps Exp $ */ +/* $Id: mandocdb.c,v 1.12 2011/11/26 11:23:56 schwarze Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons + * Copyright (c) 2011 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -48,6 +49,9 @@ struct of { char *fname; /* heap-allocated */ + char *sec; + char *arch; + char *title; struct of *next; /* NULL for last one */ struct of *first; /* first in list */ }; @@ -89,13 +93,15 @@ static void hash_reset(DB **); static void index_merge(const struct of *, struct mparse *, struct buf *, struct buf *, DB *, DB *, const char *, - DB *, const char *, int, + DB *, const char *, int, int, recno_t, const recno_t *, size_t); static void index_prune(const struct of *, DB *, const char *, DB *, const char *, int, recno_t *, recno_t **, size_t *); -static void ofile_argbuild(char *[], int, int, struct of **); -static int ofile_dirbuild(const char *, int, struct of **); +static void ofile_argbuild(char *[], int, int, int, + struct of **); +static int ofile_dirbuild(const char *, const char *, + const char *, int, int, struct of **); static void ofile_free(struct of *); static int pman_node(MAN_ARGS); static void pmdoc_node(MDOC_ARGS); @@ -254,16 +260,17 @@ main(int argc, char *argv[]) char ibuf[MAXPATHLEN], /* index fname */ fbuf[MAXPATHLEN]; /* btree fname */ int verb, /* output verbosity */ + use_all, /* use all directories and files */ ch, i, flags; DB *idx, /* index database */ *db, /* keyword database */ *hash; /* temporary keyword hashtable */ BTREEINFO info; /* btree configuration */ - recno_t maxrec; /* supremum of all records */ - recno_t *recs; /* buffer of empty records */ + recno_t maxrec; /* last record number in the index */ + recno_t *recs; /* the numbers of all empty records */ size_t sz1, sz2, - recsz, /* buffer size of recs */ - reccur; /* valid number of recs */ + recsz, /* number of allocated slots in recs */ + reccur; /* current number of empty records */ struct buf buf, /* keyword buffer */ dbuf; /* description buffer */ struct of *of; /* list of files for processing */ @@ -279,6 +286,7 @@ main(int argc, char *argv[]) memset(&dirs, 0, sizeof(struct manpaths)); verb = 0; + use_all = 0; of = NULL; db = idx = NULL; mp = NULL; @@ -289,8 +297,11 @@ main(int argc, char *argv[]) op = OP_NEW; dir = NULL; - while (-1 != (ch = getopt(argc, argv, "d:u:v"))) + while (-1 != (ch = getopt(argc, argv, "ad:u:v"))) switch (ch) { + case ('a'): + use_all = 1; + break; case ('d'): dir = optarg; op = OP_UPDATE; @@ -347,7 +358,7 @@ main(int argc, char *argv[]) if (NULL == db) { perror(fbuf); exit((int)MANDOCLEVEL_SYSERR); - } else if (NULL == db) { + } else if (NULL == idx) { perror(ibuf); exit((int)MANDOCLEVEL_SYSERR); } @@ -357,7 +368,7 @@ main(int argc, char *argv[]) printf("%s: Opened\n", ibuf); } - ofile_argbuild(argv, argc, verb, &of); + ofile_argbuild(argv, argc, use_all, verb, &of); if (NULL == of) goto out; @@ -368,8 +379,8 @@ main(int argc, char *argv[]) if (OP_UPDATE == op) index_merge(of, mp, &dbuf, &buf, hash, - db, fbuf, idx, ibuf, verb, - maxrec, recs, reccur); + db, fbuf, idx, ibuf, use_all, + verb, maxrec, recs, reccur); goto out; } @@ -411,7 +422,7 @@ main(int argc, char *argv[]) if (NULL == db) { perror(fbuf); exit((int)MANDOCLEVEL_SYSERR); - } else if (NULL == db) { + } else if (NULL == idx) { perror(ibuf); exit((int)MANDOCLEVEL_SYSERR); } @@ -424,7 +435,8 @@ main(int argc, char *argv[]) ofile_free(of); of = NULL; - if ( ! ofile_dirbuild(dirs.paths[i], verb, &of)) + if ( ! ofile_dirbuild(dirs.paths[i], NULL, NULL, + use_all, verb, &of)) exit((int)MANDOCLEVEL_SYSERR); if (NULL == of) @@ -433,7 +445,8 @@ main(int argc, char *argv[]) of = of->first; index_merge(of, mp, &dbuf, &buf, hash, db, fbuf, - idx, ibuf, verb, maxrec, recs, reccur); + idx, ibuf, use_all, verb, + maxrec, recs, reccur); } out: @@ -459,7 +472,7 @@ void index_merge(const struct of *of, struct mparse *mp, struct buf *dbuf, struct buf *buf, DB *hash, DB *db, const char *dbf, - DB *idx, const char *idxf, int verb, + DB *idx, const char *idxf, int use_all, int verb, recno_t maxrec, const recno_t *recs, size_t reccur) { recno_t rec; @@ -495,17 +508,53 @@ index_merge(const struct of *of, struct mparse *mp, if (NULL == mdoc && NULL == man) continue; + /* + * By default, skip a file if the manual section + * and architecture given in the file disagree + * with the directory where the file is located. + */ + msec = NULL != mdoc ? mdoc_meta(mdoc)->msec : man_meta(man)->msec; - mtitle = NULL != mdoc ? - mdoc_meta(mdoc)->title : man_meta(man)->title; arch = NULL != mdoc ? mdoc_meta(mdoc)->arch : NULL; + if (0 == use_all) { + assert(of->sec); + assert(msec); + if (strcmp(msec, of->sec)) + continue; + + if (NULL == arch) { + if (NULL != of->arch) + continue; + } else if (NULL == of->arch || + strcmp(arch, of->arch)) + continue; + } + if (NULL == arch) arch = ""; /* + * By default, skip a file if the title given + * in the file disagrees with the file name. + * If both agree, use the file name as the title, + * because the one in the file usually is all caps. + */ + + mtitle = NULL != mdoc ? + mdoc_meta(mdoc)->title : man_meta(man)->title; + + assert(of->title); + assert(mtitle); + + if (0 == strcasecmp(mtitle, of->title)) + mtitle = of->title; + else if (0 == use_all) + continue; + + /* * The index record value consists of a nil-terminated * filename, a nil-terminated manual section, and a * nil-terminated description. Since the description @@ -1179,14 +1228,64 @@ pman_node(MAN_ARGS) } static void -ofile_argbuild(char *argv[], int argc, int verb, struct of **of) +ofile_argbuild(char *argv[], int argc, int use_all, int verb, + struct of **of) { + char buf[MAXPATHLEN]; + char *sec, *arch, *title, *p; int i; struct of *nof; for (i = 0; i < argc; i++) { + + /* + * Try to infer the manual section, architecture and + * page title from the path, assuming it looks like + * man*[/]/.<section> + */ + + if (strlcpy(buf, argv[i], sizeof(buf)) >= sizeof(buf)) { + fprintf(stderr, "%s: Path too long\n", argv[i]); + continue; + } + sec = arch = title = NULL; + p = strrchr(buf, '\0'); + while (p-- > buf) { + if (NULL == sec && '.' == *p) { + sec = p + 1; + *p = '\0'; + continue; + } + if ('/' != *p) + continue; + if (NULL == title) { + title = p + 1; + *p = '\0'; + continue; + } + if (strncmp("man", p + 1, 3)) + arch = p + 1; + break; + } + if (NULL == title) + title = buf; + + /* + * Build the file structure. + */ + nof = mandoc_calloc(1, sizeof(struct of)); - nof->fname = strdup(argv[i]); + nof->fname = mandoc_strdup(argv[i]); + if (NULL != sec) + nof->sec = mandoc_strdup(sec); + if (NULL != arch) + nof->arch = mandoc_strdup(arch); + nof->title = mandoc_strdup(title); + + /* + * Add the structure to the list. + */ + if (verb > 2) printf("%s: Scheduling\n", argv[i]); if (NULL == *of) { @@ -1209,12 +1308,14 @@ ofile_argbuild(char *argv[], int argc, int verb, struc * Pass in a pointer to a NULL structure for the first invocation. */ static int -ofile_dirbuild(const char *dir, int verb, struct of **of) +ofile_dirbuild(const char *dir, const char* psec, const char *parch, + int use_all, int verb, struct of **of) { char buf[MAXPATHLEN]; size_t sz; DIR *d; - const char *fn; + const char *fn, *sec, *arch; + char *suffix; struct of *nof; struct dirent *dp; @@ -1225,34 +1326,69 @@ ofile_dirbuild(const char *dir, int verb, struct of ** while (NULL != (dp = readdir(d))) { fn = dp->d_name; + + if ('.' == *fn) + continue; + if (DT_DIR == dp->d_type) { - if (0 == strcmp(".", fn)) + sec = psec; + arch = parch; + + /* + * By default, only use directories called: + * man<section>/[<arch>/] + */ + + if (NULL == sec) { + if(0 == strncmp("man", fn, 3)) + sec = fn + 3; + else if (use_all) + sec = fn; + else + continue; + } else if (NULL == arch && (use_all || + NULL == strchr(fn, '.'))) + arch = fn; + else if (0 == use_all) continue; - if (0 == strcmp("..", fn)) - continue; buf[0] = '\0'; strlcat(buf, dir, MAXPATHLEN); strlcat(buf, "/", MAXPATHLEN); sz = strlcat(buf, fn, MAXPATHLEN); - if (sz < MAXPATHLEN) { - if ( ! ofile_dirbuild(buf, verb, of)) - return(0); - continue; - } else if (sz < MAXPATHLEN) - continue; + if (MAXPATHLEN <= sz) { + fprintf(stderr, "%s: Path too long\n", dir); + return(0); + } + + if (verb > 2) + printf("%s: Scanning\n", buf); - fprintf(stderr, "%s: Path too long\n", dir); - return(0); + if ( ! ofile_dirbuild(buf, sec, arch, + use_all, verb, of)) + return(0); } - if (DT_REG != dp->d_type) + if (DT_REG != dp->d_type || + (NULL == psec && !use_all) || + !strcmp(MANDOC_DB, fn) || + !strcmp(MANDOC_IDX, fn)) continue; - if (0 == strcmp(MANDOC_DB, fn) || - 0 == strcmp(MANDOC_IDX, fn)) - continue; + /* + * By default, skip files where the file name suffix + * does not agree with the section directory + * they are located in. + */ + suffix = strrchr(fn, '.'); + if (0 == use_all) { + if (NULL == suffix) + continue; + if (strcmp(suffix + 1, psec)) + continue; + } + buf[0] = '\0'; strlcat(buf, dir, MAXPATHLEN); strlcat(buf, "/", MAXPATHLEN); @@ -1264,7 +1400,20 @@ ofile_dirbuild(const char *dir, int verb, struct of ** nof = mandoc_calloc(1, sizeof(struct of)); nof->fname = mandoc_strdup(buf); + if (NULL != psec) + nof->sec = mandoc_strdup(psec); + if (NULL != parch) + nof->arch = mandoc_strdup(parch); + /* + * Remember the file name without the extension, + * to be used as the page title in the database. + */ + + if (NULL != suffix) + *suffix = '\0'; + nof->title = mandoc_strdup(fn); + if (verb > 2) printf("%s: Scheduling\n", buf); @@ -1290,6 +1439,9 @@ ofile_free(struct of *of) while (of) { nof = of->next; free(of->fname); + free(of->sec); + free(of->arch); + free(of->title); free(of); of = nof; }