version 1.18, 2011/07/11 09:36:15 |
version 1.19, 2011/07/11 21:56:06 |
|
|
size_t size; |
size_t size; |
}; |
}; |
|
|
|
/* Operation we're going to perform. */ |
|
|
|
enum op { |
|
OP_NEW = 0, /* new database */ |
|
OP_UPDATE, /* update entries in existing database */ |
|
OP_DELETE /* delete entries from existing database */ |
|
}; |
|
|
#define MAN_ARGS DB *hash, \ |
#define MAN_ARGS DB *hash, \ |
struct buf *buf, \ |
struct buf *buf, \ |
struct buf *dbuf, \ |
struct buf *dbuf, \ |
Line 85 static void buf_appendb(struct buf *, |
|
Line 93 static void buf_appendb(struct buf *, |
|
static void dbt_put(DB *, const char *, DBT *, DBT *); |
static void dbt_put(DB *, const char *, DBT *, DBT *); |
static void hash_put(DB *, const struct buf *, int); |
static void hash_put(DB *, const struct buf *, int); |
static void hash_reset(DB **); |
static void hash_reset(DB **); |
|
static void op_delete(const char *, int, DB *, |
|
const char *, DB *, const char *); |
static int pman_node(MAN_ARGS); |
static int pman_node(MAN_ARGS); |
static void pmdoc_node(MDOC_ARGS); |
static void pmdoc_node(MDOC_ARGS); |
static void pmdoc_An(MDOC_ARGS); |
static void pmdoc_An(MDOC_ARGS); |
Line 238 main(int argc, char *argv[]) |
|
Line 248 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 */ |
struct man *man; /* resulting man */ |
struct man *man; /* resulting man */ |
|
enum op op; |
char *fn; /* current file being parsed */ |
char *fn; /* current file being parsed */ |
const char *msec, /* manual section */ |
const char *msec, /* manual section */ |
*mtitle, /* manual title */ |
*mtitle, /* manual title */ |
Line 246 main(int argc, char *argv[]) |
|
Line 257 main(int argc, char *argv[]) |
|
char ibuf[MAXPATHLEN], /* index fname */ |
char ibuf[MAXPATHLEN], /* index fname */ |
fbuf[MAXPATHLEN], /* btree fname */ |
fbuf[MAXPATHLEN], /* btree fname */ |
vbuf[8]; /* stringified record number */ |
vbuf[8]; /* stringified record number */ |
int ch, seq, verb; |
int ch, seq, verb, i; |
DB *idx, /* index database */ |
DB *idx, /* index database */ |
*db, /* keyword database */ |
*db, /* keyword database */ |
*hash; /* temporary keyword hashtable */ |
*hash; /* temporary keyword hashtable */ |
Line 254 main(int argc, char *argv[]) |
|
Line 265 main(int argc, char *argv[]) |
|
enum mandocerr ec; |
enum mandocerr ec; |
size_t sv; |
size_t sv; |
BTREEINFO info; /* btree configuration */ |
BTREEINFO info; /* btree configuration */ |
recno_t rec; /* current record number */ |
recno_t rec, /* current record number */ |
|
maxrec; |
|
recno_t *recs; |
|
size_t recsz; |
struct buf buf, /* keyword buffer */ |
struct buf buf, /* keyword buffer */ |
dbuf; /* description buffer */ |
dbuf; /* description buffer */ |
extern int optind; |
extern int optind; |
Line 271 main(int argc, char *argv[]) |
|
Line 285 main(int argc, char *argv[]) |
|
db = idx = NULL; |
db = idx = NULL; |
mp = NULL; |
mp = NULL; |
hash = NULL; |
hash = NULL; |
|
recs = NULL; |
|
recsz = 0; |
|
op = OP_NEW; |
ec = MANDOCLEVEL_SYSERR; |
ec = MANDOCLEVEL_SYSERR; |
|
|
memset(&buf, 0, sizeof(struct buf)); |
memset(&buf, 0, sizeof(struct buf)); |
memset(&dbuf, 0, sizeof(struct buf)); |
memset(&dbuf, 0, sizeof(struct buf)); |
|
|
while (-1 != (ch = getopt(argc, argv, "d:v"))) |
while (-1 != (ch = getopt(argc, argv, "d:ruv"))) |
switch (ch) { |
switch (ch) { |
case ('d'): |
case ('d'): |
dir = optarg; |
dir = optarg; |
break; |
break; |
|
case ('r'): |
|
op = OP_DELETE; |
|
break; |
|
case ('u'): |
|
op = OP_UPDATE; |
|
break; |
case ('v'): |
case ('v'): |
verb++; |
verb++; |
break; |
break; |
Line 311 main(int argc, char *argv[]) |
|
Line 334 main(int argc, char *argv[]) |
|
* For the keyword database, open a BTREE database that allows |
* For the keyword database, open a BTREE database that allows |
* duplicates. |
* duplicates. |
* For the index database, use a standard RECNO database type. |
* For the index database, use a standard RECNO database type. |
|
* Truncate the database if we're creating a new one. |
*/ |
*/ |
|
|
memset(&info, 0, sizeof(BTREEINFO)); |
memset(&info, 0, sizeof(BTREEINFO)); |
info.flags = R_DUP; |
info.flags = R_DUP; |
|
|
db = dbopen(fbuf, MANDOC_FLAGS, 0644, DB_BTREE, &info); |
if (OP_NEW == op) { |
idx = dbopen(ibuf, MANDOC_FLAGS, 0644, DB_RECNO, NULL); |
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); |
|
} |
|
|
if (NULL == db) { |
if (NULL == db) { |
perror(fbuf); |
perror(fbuf); |
Line 328 main(int argc, char *argv[]) |
|
Line 357 main(int argc, char *argv[]) |
|
} |
} |
|
|
/* |
/* |
|
* If we're going to delete or update a database, remove the |
|
* entries now. This doesn't actually remove them; it only sets |
|
* their record value lengths to zero. |
|
*/ |
|
|
|
if (OP_DELETE == op || OP_UPDATE == op) |
|
for (i = 0; i < argc; i++) |
|
op_delete(argv[i], verb, idx, ibuf, db, fbuf); |
|
|
|
if (OP_DELETE == op) { |
|
ec = MANDOCLEVEL_OK; |
|
goto out; |
|
} |
|
|
|
/* |
|
* Compile a list of all available "empty" records to use. This |
|
* keeps the size of the database small. |
|
*/ |
|
|
|
if (OP_UPDATE == op) { |
|
i = 0; |
|
seq = R_FIRST; |
|
while (0 == (ch = (*idx->seq)(idx, &key, &val, seq))) { |
|
seq = R_NEXT; |
|
maxrec = *(recno_t *)key.data; |
|
if (val.size > 0) |
|
continue; |
|
if ((size_t)i >= recsz) { |
|
recsz += 1024; |
|
recs = mandoc_realloc |
|
(recs, recsz * sizeof(recno_t)); |
|
} |
|
recs[i++] = maxrec; |
|
} |
|
if (ch < 0) { |
|
perror(ibuf); |
|
exit((int)MANDOCLEVEL_SYSERR); |
|
} |
|
recsz = (size_t)i; |
|
maxrec++; |
|
assert(recsz < maxrec); |
|
} else |
|
maxrec = 0; |
|
|
|
/* |
|
* Add records to the database. |
* Try parsing each manual given on the command line. |
* Try parsing each manual given on the command line. |
* If we fail, then emit an error and keep on going. |
* If we fail, then emit an error and keep on going. |
* Take resulting trees and push them down into the database code. |
* Take resulting trees and push them down into the database code. |
Line 340 main(int argc, char *argv[]) |
|
Line 415 main(int argc, char *argv[]) |
|
buf.cp = mandoc_malloc(buf.size); |
buf.cp = mandoc_malloc(buf.size); |
dbuf.cp = mandoc_malloc(dbuf.size); |
dbuf.cp = mandoc_malloc(dbuf.size); |
|
|
rec = 1; |
for (rec = 0, i = 0; i < argc; i++) { |
|
fn = argv[i]; |
|
if (OP_UPDATE == op) { |
|
if (recsz > 0) { |
|
--recsz; |
|
rec = recs[(int)recsz]; |
|
} else if (maxrec > 0) { |
|
rec = maxrec; |
|
maxrec = 0; |
|
} else |
|
rec++; |
|
} else |
|
rec++; |
|
|
while (NULL != (fn = *argv++)) { |
|
mparse_reset(mp); |
mparse_reset(mp); |
hash_reset(&hash); |
hash_reset(&hash); |
|
|
Line 359 main(int argc, char *argv[]) |
|
Line 445 main(int argc, char *argv[]) |
|
mdoc_meta(mdoc)->msec : man_meta(man)->msec; |
mdoc_meta(mdoc)->msec : man_meta(man)->msec; |
mtitle = NULL != mdoc ? |
mtitle = NULL != mdoc ? |
mdoc_meta(mdoc)->title : man_meta(man)->title; |
mdoc_meta(mdoc)->title : man_meta(man)->title; |
arch = NULL != mdoc ? |
arch = NULL != mdoc ? mdoc_meta(mdoc)->arch : NULL; |
mdoc_meta(mdoc)->arch : ""; |
|
|
|
|
if (NULL == arch) |
|
arch = ""; |
|
|
/* |
/* |
* The index record value consists of a nil-terminated |
* The index record value consists of a nil-terminated |
* filename, a nil-terminated manual section, and a |
* filename, a nil-terminated manual section, and a |
Line 403 main(int argc, char *argv[]) |
|
Line 491 main(int argc, char *argv[]) |
|
val.data = vbuf; |
val.data = vbuf; |
|
|
if (verb > 1) |
if (verb > 1) |
printf("%s: Keyword %s: 0x%x\n", |
printf("Indexed: %s, %s, 0x%x\n", |
fn, (char *)key.data, |
fn, (char *)key.data, |
*(int *)val.data); |
*(int *)val.data); |
|
|
dbt_put(db, fbuf, &key, &val); |
dbt_put(db, fbuf, &key, &val); |
|
|
} |
} |
if (ch < 0) { |
if (ch < 0) { |
perror("hash"); |
perror("hash"); |
Line 430 main(int argc, char *argv[]) |
|
Line 516 main(int argc, char *argv[]) |
|
val.size = dbuf.len; |
val.size = dbuf.len; |
|
|
if (verb > 0) |
if (verb > 0) |
printf("%s: Indexed\n", fn); |
printf("Indexed: %s\n", fn); |
|
|
dbt_put(idx, ibuf, &key, &val); |
dbt_put(idx, ibuf, &key, &val); |
rec++; |
|
} |
} |
|
|
ec = MANDOCLEVEL_OK; |
ec = MANDOCLEVEL_OK; |
|
|
out: |
out: |
if (db) |
if (db) |
(*db->close)(db); |
(*db->close)(db); |
|
|
|
|
free(buf.cp); |
free(buf.cp); |
free(dbuf.cp); |
free(dbuf.cp); |
|
free(recs); |
|
|
return((int)ec); |
return((int)ec); |
} |
} |
|
|
|
static void |
|
op_delete(const char *fn, int verb, DB *idx, |
|
const char *ibuf, DB *db, const char *fbuf) |
|
{ |
|
int ch; |
|
DBT key, val; |
|
recno_t rec; |
|
unsigned int seq, sseq; |
|
|
|
seq = R_FIRST; |
|
while (0 == (ch = (*idx->seq)(idx, &key, &val, seq))) { |
|
seq = R_NEXT; |
|
if (0 == val.size) |
|
continue; |
|
if (strcmp((char *)val.data, fn)) |
|
continue; |
|
|
|
rec = *(recno_t *)key.data; |
|
|
|
sseq = R_FIRST; |
|
while (0 == (ch = (*db->seq)(db, &key, &val, sseq))) { |
|
sseq = R_NEXT; |
|
assert(8 == val.size); |
|
if (rec != *(recno_t *)(val.data + 4)) |
|
continue; |
|
if (verb > 1) |
|
printf("Deleted: %s, %s\n", |
|
fn, (char *)key.data); |
|
ch = (*db->del)(db, &key, R_CURSOR); |
|
if (ch < 0) |
|
break; |
|
} |
|
if (ch < 0) { |
|
perror(fbuf); |
|
exit((int)MANDOCLEVEL_SYSERR); |
|
} |
|
|
|
val.size = 0; |
|
if (verb) |
|
printf("Deleted: %s\n", fn); |
|
ch = (*idx->put) |
|
(idx, &key, &val, R_CURSOR); |
|
if (ch < 0) |
|
break; |
|
} |
|
if (ch < 0) { |
|
perror(ibuf); |
|
exit((int)MANDOCLEVEL_SYSERR); |
|
} |
|
} |
|
|
/* |
/* |
* Grow the buffer (if necessary) and copy in a binary string. |
* Grow the buffer (if necessary) and copy in a binary string. |
*/ |
*/ |
|
|
usage(void) |
usage(void) |
{ |
{ |
|
|
fprintf(stderr, "usage: %s [-v] [-d path] [file...]\n", |
fprintf(stderr, "usage: %s [-ruv] [-d path] [file...]\n", |
progname); |
progname); |
} |
} |