version 1.44, 2012/03/23 05:07:35 |
version 1.46, 2012/03/23 06:52:17 |
|
|
#include <assert.h> |
#include <assert.h> |
#include <ctype.h> |
#include <ctype.h> |
#include <dirent.h> |
#include <dirent.h> |
|
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
#include <getopt.h> |
#include <getopt.h> |
#include <stdio.h> |
#include <stdio.h> |
|
|
#define MANDOC_SRC 0x1 |
#define MANDOC_SRC 0x1 |
#define MANDOC_FORM 0x2 |
#define MANDOC_FORM 0x2 |
|
|
|
#define WARNING(_f, _b, _fmt, _args...) \ |
|
do if (warnings) { \ |
|
fprintf(stderr, "%s: ", (_b)); \ |
|
fprintf(stderr, (_fmt), ##_args); \ |
|
if ('\0' != *(_f)) \ |
|
fprintf(stderr, ": %s", (_f)); \ |
|
fprintf(stderr, "\n"); \ |
|
} while (/* CONSTCOND */ 0) |
|
|
/* Access to the mandoc database on disk. */ |
/* Access to the mandoc database on disk. */ |
|
|
struct mdb { |
struct mdb { |
Line 130 static void index_prune(const struct of *, struct m |
|
Line 140 static void index_prune(const struct of *, struct m |
|
static void ofile_argbuild(int, char *[], |
static void ofile_argbuild(int, char *[], |
struct of **, const char *); |
struct of **, const char *); |
static void ofile_dirbuild(const char *, const char *, |
static void ofile_dirbuild(const char *, const char *, |
const char *, int, struct of **); |
const char *, int, struct of **, char *); |
static void ofile_free(struct of *); |
static void ofile_free(struct of *); |
static void pformatted(DB *, struct buf *, struct buf *, |
static void pformatted(DB *, struct buf *, struct buf *, |
const struct of *, const char *); |
const struct of *, const char *); |
Line 295 main(int argc, char *argv[]) |
|
Line 305 main(int argc, char *argv[]) |
|
enum op op; /* current operation */ |
enum op op; /* current operation */ |
const char *dir; |
const char *dir; |
int ch, i, flags; |
int ch, i, flags; |
|
char dirbuf[MAXPATHLEN]; |
DB *hash; /* temporary keyword hashtable */ |
DB *hash; /* temporary keyword hashtable */ |
BTREEINFO info; /* btree configuration */ |
BTREEINFO info; /* btree configuration */ |
size_t sz1, sz2; |
size_t sz1, sz2; |
Line 500 main(int argc, char *argv[]) |
|
Line 511 main(int argc, char *argv[]) |
|
* Search for manuals and fill the new database. |
* Search for manuals and fill the new database. |
*/ |
*/ |
|
|
ofile_dirbuild(".", "", "", 0, &of); |
strlcpy(dirbuf, dirs.paths[i], MAXPATHLEN); |
|
ofile_dirbuild(".", "", "", 0, &of, dirbuf); |
|
|
if (NULL != of) { |
if (NULL != of) { |
index_merge(of, mp, &dbuf, &buf, hash, |
index_merge(of, mp, &dbuf, &buf, hash, |
|
|
|
|
usage: |
usage: |
fprintf(stderr, |
fprintf(stderr, |
"usage: %s [-avvv] [-C file] | dir ... | -t file ...\n" |
"usage: %s [-av] [-C file] | dir ... | -t file ...\n" |
" -d dir [file ...] | " |
" -d dir [file ...] | " |
"-u dir [file ...]\n", |
"-u dir [file ...]\n", |
progname); |
progname); |
Line 617 index_merge(const struct of *of, struct mparse *mp, |
|
Line 629 index_merge(const struct of *of, struct mparse *mp, |
|
skip = 0; |
skip = 0; |
assert(of->sec); |
assert(of->sec); |
assert(msec); |
assert(msec); |
if (warnings && strcasecmp(msec, of->sec)) |
if (strcasecmp(msec, of->sec)) |
fprintf(stderr, "%s: section \"%s\" manual " |
WARNING(fn, basedir, "Section \"%s\" manual " |
"in \"%s\" directory\n", |
"in \"%s\" directory", msec, of->sec); |
fn, msec, of->sec); |
|
|
|
|
|
/* |
/* |
* Manual page directories exist for each kernel |
* Manual page directories exist for each kernel |
* architecture as returned by machine(1). |
* architecture as returned by machine(1). |
Line 640 index_merge(const struct of *of, struct mparse *mp, |
|
Line 649 index_merge(const struct of *of, struct mparse *mp, |
|
|
|
assert(of->arch); |
assert(of->arch); |
assert(march); |
assert(march); |
if (warnings && strcasecmp(march, of->arch)) |
if (strcasecmp(march, of->arch)) |
fprintf(stderr, "%s: architecture \"%s\" manual " |
WARNING(fn, basedir, "Architecture \"%s\" " |
"in \"%s\" directory\n", |
"manual in \"%s\" directory", |
fn, march, of->arch); |
march, of->arch); |
|
|
/* |
/* |
* By default, skip a file if the title given |
* By default, skip a file if the title given |
Line 813 index_merge(const struct of *of, struct mparse *mp, |
|
Line 822 index_merge(const struct of *of, struct mparse *mp, |
|
while (0 == (*files->seq)(files, &key, &val, seq)) { |
while (0 == (*files->seq)(files, &key, &val, seq)) { |
seq = R_NEXT; |
seq = R_NEXT; |
if (val.size) |
if (val.size) |
fprintf(stderr, "%s: probably " |
WARNING((char *)val.data, basedir, |
"unreachable, title is %s\n", |
"Probably unreachable, title " |
(char *)val.data, (char *)key.data); |
"is %s", (char *)key.data); |
} |
} |
(*files->close)(files); |
(*files->close)(files); |
} |
} |
|
|
pman_node(MAN_ARGS) |
pman_node(MAN_ARGS) |
{ |
{ |
const struct man_node *head, *body; |
const struct man_node *head, *body; |
const char *start, *sv; |
char *start, *sv, *title; |
size_t sz; |
size_t sz, titlesz; |
|
|
if (NULL == n) |
if (NULL == n) |
return(0); |
return(0); |
Line 1338 pman_node(MAN_ARGS) |
|
Line 1347 pman_node(MAN_ARGS) |
|
NULL != (body = body->child) && |
NULL != (body = body->child) && |
MAN_TEXT == body->type) { |
MAN_TEXT == body->type) { |
|
|
assert(body->string); |
title = NULL; |
start = sv = body->string; |
titlesz = 0; |
|
/* |
|
* Suck the entire NAME section into memory. |
|
* Yes, we might run away. |
|
* But too many manuals have big, spread-out |
|
* NAME sections over many lines. |
|
*/ |
|
for ( ; NULL != body; body = body->next) { |
|
if (MAN_TEXT != body->type) |
|
break; |
|
if (0 == (sz = strlen(body->string))) |
|
continue; |
|
title = mandoc_realloc |
|
(title, titlesz + sz + 1); |
|
memcpy(title + titlesz, body->string, sz); |
|
titlesz += sz + 1; |
|
title[(int)titlesz - 1] = ' '; |
|
} |
|
if (NULL == title) |
|
return(0); |
|
|
|
title = mandoc_realloc(title, titlesz + 1); |
|
title[(int)titlesz] = '\0'; |
|
|
|
/* Skip leading space. */ |
|
|
|
sv = title; |
|
while (isspace((unsigned char)*sv)) |
|
sv++; |
|
|
|
if (0 == (sz = strlen(sv))) { |
|
free(title); |
|
return(0); |
|
} |
|
|
|
/* Erase trailing space. */ |
|
|
|
start = &sv[sz - 1]; |
|
while (start > sv && isspace((unsigned char)*start)) |
|
*start-- = '\0'; |
|
|
|
if (start == sv) { |
|
free(title); |
|
return(0); |
|
} |
|
|
|
start = sv; |
|
|
/* |
/* |
* Go through a special heuristic dance here. |
* Go through a special heuristic dance here. |
* This is why -man manuals are great! |
* This is why -man manuals are great! |
Line 1377 pman_node(MAN_ARGS) |
|
Line 1432 pman_node(MAN_ARGS) |
|
|
|
if (sv == start) { |
if (sv == start) { |
buf_append(buf, start); |
buf_append(buf, start); |
|
free(title); |
return(1); |
return(1); |
} |
} |
|
|
while (' ' == *start) |
while (isspace((unsigned char)*start)) |
start++; |
start++; |
|
|
if (0 == strncmp(start, "-", 1)) |
if (0 == strncmp(start, "-", 1)) |
Line 1402 pman_node(MAN_ARGS) |
|
Line 1458 pman_node(MAN_ARGS) |
|
buf_appendb(buf, start, sz); |
buf_appendb(buf, start, sz); |
|
|
hash_put(hash, buf, TYPE_Nd); |
hash_put(hash, buf, TYPE_Nd); |
|
free(title); |
} |
} |
} |
} |
|
|
Line 1425 pformatted(DB *hash, struct buf *buf, struct buf *dbuf |
|
Line 1482 pformatted(DB *hash, struct buf *buf, struct buf *dbuf |
|
size_t len, plen, titlesz; |
size_t len, plen, titlesz; |
|
|
if (NULL == (stream = fopen(of->fname, "r"))) { |
if (NULL == (stream = fopen(of->fname, "r"))) { |
if (warnings) |
WARNING(of->fname, basedir, "%s", strerror(errno)); |
perror(of->fname); |
|
return; |
return; |
} |
} |
|
|
Line 1481 pformatted(DB *hash, struct buf *buf, struct buf *dbuf |
|
Line 1537 pformatted(DB *hash, struct buf *buf, struct buf *dbuf |
|
title[(int)titlesz - 1] = ' '; |
title[(int)titlesz - 1] = ' '; |
} |
} |
|
|
|
|
/* |
/* |
* If no page content can be found, or the input line |
* If no page content can be found, or the input line |
* is already the next section header, or there is no |
* is already the next section header, or there is no |
Line 1490 pformatted(DB *hash, struct buf *buf, struct buf *dbuf |
|
Line 1545 pformatted(DB *hash, struct buf *buf, struct buf *dbuf |
|
*/ |
*/ |
|
|
if (NULL == title || '\0' == *title) { |
if (NULL == title || '\0' == *title) { |
if (warnings) |
WARNING(of->fname, basedir, |
fprintf(stderr, "%s: Cannot find NAME " |
"Cannot find NAME section"); |
"section: %s\n", basedir, of->fname); |
|
buf_appendb(dbuf, buf->cp, buf->size); |
buf_appendb(dbuf, buf->cp, buf->size); |
hash_put(hash, buf, TYPE_Nd); |
hash_put(hash, buf, TYPE_Nd); |
fclose(stream); |
fclose(stream); |
Line 1513 pformatted(DB *hash, struct buf *buf, struct buf *dbuf |
|
Line 1567 pformatted(DB *hash, struct buf *buf, struct buf *dbuf |
|
for (p += 2; ' ' == *p || '\b' == *p; p++) |
for (p += 2; ' ' == *p || '\b' == *p; p++) |
/* Skip to next word. */ ; |
/* Skip to next word. */ ; |
} else { |
} else { |
if (warnings) |
WARNING(of->fname, basedir, |
fprintf(stderr, "%s/%s: No dash in " |
"No dash in title line"); |
"title line\n", basedir, of->fname); |
|
p = title; |
p = title; |
} |
} |
|
|
Line 1593 ofile_argbuild(int argc, char *argv[], |
|
Line 1646 ofile_argbuild(int argc, char *argv[], |
|
break; |
break; |
} |
} |
if ('\0' == *title) { |
if ('\0' == *title) { |
if (warnings) |
WARNING(argv[i], basedir, |
fprintf(stderr, "%s/%s: Cannot deduce " |
"Cannot deduce title from filename"); |
"title from filename\n", |
|
basedir, argv[i]); |
|
title = buf; |
title = buf; |
} |
} |
|
|
Line 1636 ofile_argbuild(int argc, char *argv[], |
|
Line 1687 ofile_argbuild(int argc, char *argv[], |
|
*/ |
*/ |
static void |
static void |
ofile_dirbuild(const char *dir, const char* psec, const char *parch, |
ofile_dirbuild(const char *dir, const char* psec, const char *parch, |
int p_src_form, struct of **of) |
int p_src_form, struct of **of, char *basedir) |
{ |
{ |
char buf[MAXPATHLEN]; |
char buf[MAXPATHLEN]; |
size_t sz; |
size_t sz; |
Line 1648 ofile_dirbuild(const char *dir, const char* psec, cons |
|
Line 1699 ofile_dirbuild(const char *dir, const char* psec, cons |
|
int src_form; |
int src_form; |
|
|
if (NULL == (d = opendir(dir))) { |
if (NULL == (d = opendir(dir))) { |
if (warnings) |
WARNING("", dir, "%s", strerror(errno)); |
perror(dir); |
|
return; |
return; |
} |
} |
|
|
Line 1679 ofile_dirbuild(const char *dir, const char* psec, cons |
|
Line 1729 ofile_dirbuild(const char *dir, const char* psec, cons |
|
src_form |= MANDOC_FORM; |
src_form |= MANDOC_FORM; |
sec = fn + 3; |
sec = fn + 3; |
} else { |
} else { |
if (warnings) fprintf(stderr, |
WARNING(fn, basedir, "Bad section"); |
"%s/%s: bad section\n", |
|
dir, fn); |
|
if (use_all) |
if (use_all) |
sec = fn; |
sec = fn; |
else |
else |
Line 1689 ofile_dirbuild(const char *dir, const char* psec, cons |
|
Line 1737 ofile_dirbuild(const char *dir, const char* psec, cons |
|
} |
} |
} else if ('\0' == *arch) { |
} else if ('\0' == *arch) { |
if (NULL != strchr(fn, '.')) { |
if (NULL != strchr(fn, '.')) { |
if (warnings) fprintf(stderr, |
WARNING(fn, basedir, "Bad architecture"); |
"%s/%s: bad architecture\n", |
|
dir, fn); |
|
if (0 == use_all) |
if (0 == use_all) |
continue; |
continue; |
} |
} |
arch = fn; |
arch = fn; |
} else { |
} else { |
if (warnings) fprintf(stderr, "%s/%s: " |
WARNING(fn, basedir, "Excessive subdirectory"); |
"excessive subdirectory\n", dir, fn); |
|
if (0 == use_all) |
if (0 == use_all) |
continue; |
continue; |
} |
} |
Line 1706 ofile_dirbuild(const char *dir, const char* psec, cons |
|
Line 1751 ofile_dirbuild(const char *dir, const char* psec, cons |
|
buf[0] = '\0'; |
buf[0] = '\0'; |
strlcat(buf, dir, MAXPATHLEN); |
strlcat(buf, dir, MAXPATHLEN); |
strlcat(buf, "/", MAXPATHLEN); |
strlcat(buf, "/", MAXPATHLEN); |
|
strlcat(basedir, "/", MAXPATHLEN); |
|
strlcat(basedir, fn, MAXPATHLEN); |
sz = strlcat(buf, fn, MAXPATHLEN); |
sz = strlcat(buf, fn, MAXPATHLEN); |
|
|
if (MAXPATHLEN <= sz) { |
if (MAXPATHLEN <= sz) { |
if (warnings) fprintf(stderr, "%s/%s: " |
WARNING(fn, basedir, "Path too long"); |
"path too long\n", dir, fn); |
|
continue; |
continue; |
} |
} |
|
|
ofile_dirbuild(buf, sec, arch, src_form, of); |
ofile_dirbuild(buf, sec, arch, |
|
src_form, of, basedir); |
|
|
|
p = strrchr(basedir, '/'); |
|
*p = '\0'; |
continue; |
continue; |
} |
} |
|
|
if (DT_REG != dp->d_type) { |
if (DT_REG != dp->d_type) { |
if (warnings) |
WARNING(fn, basedir, "Not a regular file"); |
fprintf(stderr, |
|
"%s/%s: not a regular file\n", |
|
dir, fn); |
|
continue; |
continue; |
} |
} |
if (!strcmp(MANDOC_DB, fn) || !strcmp(MANDOC_IDX, fn)) |
if (!strcmp(MANDOC_DB, fn) || !strcmp(MANDOC_IDX, fn)) |
continue; |
continue; |
if ('\0' == *psec) { |
if ('\0' == *psec) { |
if (warnings) |
WARNING(fn, basedir, "File outside section"); |
fprintf(stderr, |
|
"%s/%s: file outside section\n", |
|
dir, fn); |
|
if (0 == use_all) |
if (0 == use_all) |
continue; |
continue; |
} |
} |
Line 1744 ofile_dirbuild(const char *dir, const char* psec, cons |
|
Line 1788 ofile_dirbuild(const char *dir, const char* psec, cons |
|
|
|
suffix = strrchr(fn, '.'); |
suffix = strrchr(fn, '.'); |
if (NULL == suffix) { |
if (NULL == suffix) { |
if (warnings) |
WARNING(fn, basedir, "No filename suffix"); |
fprintf(stderr, |
|
"%s/%s: no filename suffix\n", |
|
dir, fn); |
|
if (0 == use_all) |
if (0 == use_all) |
continue; |
continue; |
} else if ((MANDOC_SRC & src_form && |
} else if ((MANDOC_SRC & src_form && |
strcmp(suffix + 1, psec)) || |
strcmp(suffix + 1, psec)) || |
(MANDOC_FORM & src_form && |
(MANDOC_FORM & src_form && |
strcmp(suffix + 1, "0"))) { |
strcmp(suffix + 1, "0"))) { |
if (warnings) |
WARNING(fn, basedir, "Wrong filename suffix"); |
fprintf(stderr, |
|
"%s/%s: wrong filename suffix\n", |
|
dir, fn); |
|
if (0 == use_all) |
if (0 == use_all) |
continue; |
continue; |
if ('0' == suffix[1]) |
if ('0' == suffix[1]) |
Line 1791 ofile_dirbuild(const char *dir, const char* psec, cons |
|
Line 1829 ofile_dirbuild(const char *dir, const char* psec, cons |
|
strlcat(buf, "/", MAXPATHLEN); |
strlcat(buf, "/", MAXPATHLEN); |
sz = strlcat(buf, fn, MAXPATHLEN); |
sz = strlcat(buf, fn, MAXPATHLEN); |
if (sz >= MAXPATHLEN) { |
if (sz >= MAXPATHLEN) { |
if (warnings) fprintf(stderr, |
WARNING(fn, basedir, "Path too long"); |
"%s/%s: path too long\n", |
|
dir, fn); |
|
continue; |
continue; |
} |
} |
q = strrchr(buf, '.'); |
q = strrchr(buf, '.'); |
Line 1801 ofile_dirbuild(const char *dir, const char* psec, cons |
|
Line 1837 ofile_dirbuild(const char *dir, const char* psec, cons |
|
*q = '\0'; |
*q = '\0'; |
sz = strlcat(buf, psec, MAXPATHLEN); |
sz = strlcat(buf, psec, MAXPATHLEN); |
if (sz >= MAXPATHLEN) { |
if (sz >= MAXPATHLEN) { |
if (warnings) fprintf(stderr, |
WARNING(fn, basedir, "Path too long"); |
"%s/%s: path too long\n", |
|
dir, fn); |
|
continue; |
continue; |
} |
} |
if (0 == access(buf, R_OK)) |
if (0 == access(buf, R_OK)) |
Line 1819 ofile_dirbuild(const char *dir, const char* psec, cons |
|
Line 1853 ofile_dirbuild(const char *dir, const char* psec, cons |
|
} |
} |
sz = strlcat(buf, fn, MAXPATHLEN); |
sz = strlcat(buf, fn, MAXPATHLEN); |
if (sz >= MAXPATHLEN) { |
if (sz >= MAXPATHLEN) { |
if (warnings) fprintf(stderr, |
WARNING(fn, basedir, "Path too long"); |
"%s/%s: path too long\n", dir, fn); |
|
continue; |
continue; |
} |
} |
|
|