tech@mandoc.bsd.lv
 help / color / mirror / Atom feed
* implement mandocdb -t
@ 2011-12-24 16:46 Ingo Schwarze
  2011-12-24 23:20 ` Kristaps Dzonsons
  0 siblings, 1 reply; 4+ messages in thread
From: Ingo Schwarze @ 2011-12-24 16:46 UTC (permalink / raw)
  To: tech

Hi,

finally, here is my implementation of a test mode (-t file ...)
for mandocdb(8).  This is the main missing part for pkg_create(8),
so i'd like to get it in quickly.

It involves a few cleanups:

 * Bail out on conflicting options.
   Distinguish default and config file operation mode.

 * Collect some related variables into structs.
   Useful because -t calls ofile_argbuild from yet another place.

 * Slightly simpler and safer handling of the "of" variable:
   Keep the pointer to the tail around, such that stuff could be appended,
   and explicitly start at the head whenever starting an iteration.

 * Always do all consistency checks.
   When any one fails, decide whether to print a message,
   or skip the file, or both, or none.

 * Do not crash with -a in ofile_dirbuild if there are plain files
   in the manual tree root.

This patch is against OpenBSD.
I'm well aware there are a few conflicts, both regarding minor
differences to bsd.lv and with the alignment-neutral database
format, so i'll do a resync afterwards.

Any objections?
  Ingo


Index: mandocdb.8
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/mandocdb.8,v
retrieving revision 1.13
diff -u -p -r1.13 mandocdb.8
--- mandocdb.8	19 Dec 2011 02:26:33 -0000	1.13
+++ mandocdb.8	24 Dec 2011 16:37:43 -0000
@@ -22,19 +22,22 @@
 .Nd index UNIX manuals
 .Sh SYNOPSIS
 .Nm
-.Op Fl av
+.Op Fl avvv
 .Op Fl C Ar file
 .Nm
-.Op Fl av
+.Op Fl avvv
 .Ar dir ...
 .Nm
-.Op Fl v
+.Op Fl vvv
 .Fl d Ar dir
 .Op Ar
 .Nm
-.Op Fl v
+.Op Fl vvv
 .Fl u Ar dir
 .Op Ar
+.Nm
+.Op Fl vv
+.Fl t Ar
 .Sh DESCRIPTION
 The
 .Nm
@@ -88,6 +91,17 @@ Merge (remove and re-add)
 to the database in
 .Ar dir
 without truncating it.
+.It Fl t Ar
+Check the given
+.Ar files
+for potential problems.
+No databases are modified.
+Implies
+.Fl a
+and one
+.Fl v .
+All diagnostic messages are printed to the standard output;
+the standard error output is not used.
 .It Fl u Ar dir
 Remove
 .Ar
@@ -95,7 +109,19 @@ from the database in
 .Ar dir
 without truncating it.
 .It Fl v
-Display all files added or removed to the index.
+Verbose operation; can be specified multiple times.
+By default,
+.Nm
+operates silently.
+One
+.Fl v
+warns about potential problems.
+A second
+.Fl v
+displays all files added to or removed from the index.
+A third
+.Fl v
+displays additional debugging information.
 .El
 .Pp
 If fatal parse errors are encountered while parsing, the offending file
Index: mandocdb.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/mandocdb.c,v
retrieving revision 1.27
diff -u -p -r1.27 mandocdb.c
--- mandocdb.c	20 Dec 2011 00:41:24 -0000	1.27
+++ mandocdb.c	24 Dec 2011 16:37:44 -0000
@@ -41,6 +41,24 @@
 #define	MANDOC_SRC	  0x1
 #define	MANDOC_FORM	  0x2
 
+/* Access to the mandoc database on disk. */
+
+struct	mdb {
+	char		  idxn[MAXPATHLEN]; /* index db filename */
+	char		  dbn[MAXPATHLEN]; /* keyword db filename */
+	DB		 *idx; /* index recno database */
+	DB		 *db; /* keyword btree database */
+};
+
+/* Stack of temporarily unused index records. */
+
+struct	recs {
+	recno_t		 *stack; /* pointer to a malloc'ed array */
+	size_t		  size; /* number of allocated slots */
+	size_t		  cur; /* current number of empty records */
+	recno_t		  last; /* last record number in the index */
+};
+
 /* Tiny list for files.  No need to bring in QUEUE. */
 
 struct	of {
@@ -64,9 +82,11 @@ struct	buf {
 /* Operation we're going to perform. */
 
 enum	op {
-	OP_NEW = 0, /* new database */
+	OP_DEFAULT = 0, /* new dbs from dir list or default config */
+	OP_CONFFILE, /* new databases from custom config file */
 	OP_UPDATE, /* delete/add entries in existing database */
-	OP_DELETE /* delete entries from existing database */
+	OP_DELETE, /* delete entries from existing database */
+	OP_TEST /* change no databases, report potential problems */
 };
 
 #define	MAN_ARGS	  DB *hash, \
@@ -89,12 +109,9 @@ static	void		  hash_put(DB *, const stru
 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 *,
-				recno_t, const recno_t *, size_t);
-static	void		  index_prune(const struct of *, DB *, 
-				const char *, DB *, const char *, 
-				recno_t *, recno_t **, size_t *,
-				size_t *);
+				struct mdb *, struct recs *);
+static	void		  index_prune(const struct of *, struct mdb *,
+				struct recs *);
 static	void		  ofile_argbuild(int, char *[], struct of **);
 static	void		  ofile_dirbuild(const char *, const char *,
 				const char *, int, struct of **);
@@ -113,7 +130,6 @@ static	int		  pmdoc_Nm(MDOC_ARGS);
 static	int		  pmdoc_Sh(MDOC_ARGS);
 static	int		  pmdoc_St(MDOC_ARGS);
 static	int		  pmdoc_Xr(MDOC_ARGS);
-static	void		  usage(void);
 
 #define	MDOCF_CHILD	  0x01  /* Automatically index child nodes. */
 
@@ -257,23 +273,16 @@ mandocdb(int argc, char *argv[])
 {
 	struct mparse	*mp; /* parse sequence */
 	struct manpaths	 dirs;
+	struct mdb	 mdb;
+	struct recs	 recs;
 	enum op		 op; /* current operation */
 	const char	*dir;
-	char		*conf_file;
 	char		*cp;
-	char		 pbuf[PATH_MAX],
-			 ibuf[MAXPATHLEN], /* index fname */
-			 fbuf[MAXPATHLEN];  /* btree fname */
+	char		 pbuf[PATH_MAX];
 	int		 ch, i, flags;
-	DB		*idx, /* index database */
-			*db, /* keyword database */
-			*hash; /* temporary keyword hashtable */
+	DB		*hash; /* temporary keyword hashtable */
 	BTREEINFO	 info; /* btree configuration */
-	recno_t		 maxrec; /* last record number in the index */
-	recno_t		*recs; /* the numbers of all empty records */
-	size_t		 sz1, sz2,
-			 recsz, /* number of allocated slots in recs */
-			 reccur; /* current number of empty records */
+	size_t		 sz1, sz2;
 	struct buf	 buf, /* keyword buffer */
 			 dbuf; /* description buffer */
 	struct of	*of; /* list of files for processing */
@@ -287,33 +296,53 @@ mandocdb(int argc, char *argv[])
 		++progname;
 
 	memset(&dirs, 0, sizeof(struct manpaths));
+	memset(&mdb, 0, sizeof(struct mdb));
+	memset(&recs, 0, sizeof(struct recs));
 
 	verb = 0;
 	use_all = 0;
 	of = NULL;
-	db = idx = NULL;
 	mp = NULL;
 	hash = NULL;
-	recs = NULL;
-	recsz = reccur = 0;
-	maxrec = 0;
-	op = OP_NEW;
+	op = OP_DEFAULT;
 	dir = NULL;
-	conf_file = NULL;
 
-	while (-1 != (ch = getopt(argc, argv, "aC:d:u:v")))
+	while (-1 != (ch = getopt(argc, argv, "aC:d:tu:v")))
 		switch (ch) {
 		case ('a'):
 			use_all = 1;
 			break;
 		case ('C'):
-			conf_file = optarg;
+			if (op) {
+				fprintf(stderr, "conflicting options\n");
+				goto usage;
+			}
+			dir = optarg;
+			op = OP_CONFFILE;
 			break;
 		case ('d'):
+			if (op) {
+				fprintf(stderr, "conflicting options\n");
+				goto usage;
+			}
 			dir = optarg;
 			op = OP_UPDATE;
 			break;
+		case ('t'):
+			dup2(STDOUT_FILENO, STDERR_FILENO);
+			if (op) {
+				fprintf(stderr, "conflicting options\n");
+				goto usage;
+			}
+			op = OP_TEST;
+			use_all = 1;
+			verb++;
+			break;
 		case ('u'):
+			if (op) {
+				fprintf(stderr, "conflicting options\n");
+				goto usage;
+			}
 			dir = optarg;
 			op = OP_DELETE;
 			break;
@@ -321,13 +350,17 @@ mandocdb(int argc, char *argv[])
 			verb++;
 			break;
 		default:
-			usage();
-			return((int)MANDOCLEVEL_BADARG);
+			goto usage;
 		}
 
 	argc -= optind;
 	argv += optind;
 
+	if (OP_CONFFILE == op && argc > 0) {
+		fprintf(stderr, "too many arguments for -C\n");
+		goto usage;
+	}
+
 	memset(&info, 0, sizeof(BTREEINFO));
 	info.lorder = 4321;
 	info.flags = R_DUP;
@@ -342,32 +375,40 @@ mandocdb(int argc, char *argv[])
 	buf.cp = mandoc_malloc(buf.size);
 	dbuf.cp = mandoc_malloc(dbuf.size);
 
-	flags = OP_NEW == op ? O_CREAT|O_TRUNC|O_RDWR : O_CREAT|O_RDWR;
+	flags = O_CREAT | O_RDWR;
+	if (OP_DEFAULT == op || OP_CONFFILE == op)
+		flags |= O_TRUNC;
 
-	if (OP_UPDATE == op || OP_DELETE == op) {
-		ibuf[0] = fbuf[0] = '\0';
+	if (OP_TEST == op) {
+		ofile_argbuild(argc, argv, &of);
+		if (NULL == of)
+			goto out;
+		index_merge(of, mp, &dbuf, &buf, hash, &mdb, &recs);
+		goto out;
+	}
 
-		strlcat(fbuf, dir, MAXPATHLEN);
-		strlcat(fbuf, "/", MAXPATHLEN);
-		sz1 = strlcat(fbuf, MANDOC_DB, MAXPATHLEN);
-
-		strlcat(ibuf, dir, MAXPATHLEN);
-		strlcat(ibuf, "/", MAXPATHLEN);
-		sz2 = strlcat(ibuf, MANDOC_IDX, MAXPATHLEN);
+	if (OP_UPDATE == op || OP_DELETE == op) {
+		strlcat(mdb.dbn, dir, MAXPATHLEN);
+		strlcat(mdb.dbn, "/", MAXPATHLEN);
+		sz1 = strlcat(mdb.dbn, MANDOC_DB, MAXPATHLEN);
+
+		strlcat(mdb.idxn, dir, MAXPATHLEN);
+		strlcat(mdb.idxn, "/", MAXPATHLEN);
+		sz2 = strlcat(mdb.idxn, MANDOC_IDX, MAXPATHLEN);
 
 		if (sz1 >= MAXPATHLEN || sz2 >= MAXPATHLEN) {
-			fprintf(stderr, "%s: Path too long\n", dir);
+			fprintf(stderr, "%s: path too long\n", dir);
 			exit((int)MANDOCLEVEL_BADARG);
 		}
 
-		db = dbopen(fbuf, flags, 0644, DB_BTREE, &info);
-		idx = dbopen(ibuf, flags, 0644, DB_RECNO, NULL);
+		mdb.db = dbopen(mdb.dbn, flags, 0644, DB_BTREE, &info);
+		mdb.idx = dbopen(mdb.idxn, flags, 0644, DB_RECNO, NULL);
 
-		if (NULL == db) {
-			perror(fbuf);
+		if (NULL == mdb.db) {
+			perror(mdb.dbn);
 			exit((int)MANDOCLEVEL_SYSERR);
-		} else if (NULL == idx) {
-			perror(ibuf);
+		} else if (NULL == mdb.idx) {
+			perror(mdb.idxn);
 			exit((int)MANDOCLEVEL_SYSERR);
 		}
 
@@ -376,10 +417,7 @@ mandocdb(int argc, char *argv[])
 		if (NULL == of)
 			goto out;
 
-		of = of->first;
-
-		index_prune(of, db, fbuf, idx, ibuf,
-				&maxrec, &recs, &recsz, &reccur);
+		index_prune(of, &mdb, &recs);
 
 		/*
 		 * Go to the root of the respective manual tree.
@@ -393,8 +431,7 @@ mandocdb(int argc, char *argv[])
 				exit((int)MANDOCLEVEL_SYSERR);
 			}
 			index_merge(of, mp, &dbuf, &buf, hash,
-					db, fbuf, idx, ibuf,
-					maxrec, recs, reccur);
+					&mdb, &recs);
 		}
 
 		goto out;
@@ -417,44 +454,44 @@ mandocdb(int argc, char *argv[])
 			dirs.paths[i] = mandoc_strdup(cp);
 		}
 	} else
-		manpath_parse(&dirs, conf_file, NULL, NULL);
+		manpath_parse(&dirs, dir, NULL, NULL);
 
 	for (i = 0; i < dirs.sz; i++) {
-		ibuf[0] = fbuf[0] = '\0';
+		mdb.idxn[0] = mdb.dbn[0] = '\0';
 
-		strlcat(fbuf, dirs.paths[i], MAXPATHLEN);
-		strlcat(fbuf, "/", MAXPATHLEN);
-		sz1 = strlcat(fbuf, MANDOC_DB, MAXPATHLEN);
-
-		strlcat(ibuf, dirs.paths[i], MAXPATHLEN);
-		strlcat(ibuf, "/", MAXPATHLEN);
-		sz2 = strlcat(ibuf, MANDOC_IDX, MAXPATHLEN);
+		strlcat(mdb.dbn, dirs.paths[i], MAXPATHLEN);
+		strlcat(mdb.dbn, "/", MAXPATHLEN);
+		sz1 = strlcat(mdb.dbn, MANDOC_DB, MAXPATHLEN);
+
+		strlcat(mdb.idxn, dirs.paths[i], MAXPATHLEN);
+		strlcat(mdb.idxn, "/", MAXPATHLEN);
+		sz2 = strlcat(mdb.idxn, MANDOC_IDX, MAXPATHLEN);
 
 		if (sz1 >= MAXPATHLEN || sz2 >= MAXPATHLEN) {
-			fprintf(stderr, "%s: Path too long\n",
+			fprintf(stderr, "%s: path too long\n",
 					dirs.paths[i]);
 			exit((int)MANDOCLEVEL_BADARG);
 		}
 
-		if (db)
-			(*db->close)(db);
-		if (idx)
-			(*idx->close)(idx);
+		if (mdb.db)
+			(*mdb.db->close)(mdb.db);
+		if (mdb.idx)
+			(*mdb.idx->close)(mdb.idx);
 
-		db = dbopen(fbuf, flags, 0644, DB_BTREE, &info);
-		idx = dbopen(ibuf, flags, 0644, DB_RECNO, NULL);
+		mdb.db = dbopen(mdb.dbn, flags, 0644, DB_BTREE, &info);
+		mdb.idx = dbopen(mdb.idxn, flags, 0644, DB_RECNO, NULL);
 
-		if (NULL == db) {
-			perror(fbuf);
+		if (NULL == mdb.db) {
+			perror(mdb.dbn);
 			exit((int)MANDOCLEVEL_SYSERR);
-		} else if (NULL == idx) {
-			perror(ibuf);
+		} else if (NULL == mdb.idx) {
+			perror(mdb.idxn);
 			exit((int)MANDOCLEVEL_SYSERR);
 		}
 
 		if (verb > 2) {
-			printf("%s: Truncated\n", fbuf);
-			printf("%s: Truncated\n", ibuf);
+			printf("%s: truncated\n", mdb.dbn);
+			printf("%s: truncated\n", mdb.idxn);
 		}
 
 		ofile_free(of);
@@ -463,17 +500,14 @@ mandocdb(int argc, char *argv[])
 		if (-1 == chdir(dirs.paths[i])) {
 			perror(dirs.paths[i]);
 			exit((int)MANDOCLEVEL_SYSERR);
-		} 
-
-	       	ofile_dirbuild(".", NULL, NULL, 0, &of);
+		}
 
+	       	ofile_dirbuild(".", "", "", 0, &of);
 		if (NULL == of)
 			continue;
 
-		of = of->first;
-
 		/*
-		 * Go to the root of the respective manual tree.  
+		 * Go to the root of the respective manual tree.
 		 * This must work or no manuals may be found (they're
 		 * indexed relative to the root).
 		 */
@@ -483,15 +517,14 @@ mandocdb(int argc, char *argv[])
 			exit((int)MANDOCLEVEL_SYSERR);
 		}
 
-		index_merge(of, mp, &dbuf, &buf, hash, db, fbuf,
-				idx, ibuf, maxrec, recs, reccur);
+		index_merge(of, mp, &dbuf, &buf, hash, &mdb, &recs);
 	}
 
 out:
-	if (db)
-		(*db->close)(db);
-	if (idx)
-		(*idx->close)(idx);
+	if (mdb.db)
+		(*mdb.db->close)(mdb.db);
+	if (mdb.idx)
+		(*mdb.idx->close)(mdb.idx);
 	if (hash)
 		(*hash->close)(hash);
 	if (mp)
@@ -501,30 +534,39 @@ out:
 	ofile_free(of);
 	free(buf.cp);
 	free(dbuf.cp);
-	free(recs);
+	free(recs.stack);
 
 	return(MANDOCLEVEL_OK);
+
+usage:
+	fprintf(stderr,
+		"usage: %s [-avvv] [-C file] | dir ... | -t file ...\n"
+		"                        -d dir [file ...] | "
+		"-u dir [file ...]\n",
+		progname);
+
+	return((int)MANDOCLEVEL_BADARG);
 }
 
 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,
-		recno_t maxrec, const recno_t *recs, size_t reccur)
+		struct mdb *mdb, struct recs *recs)
 {
 	recno_t		 rec;
-	int		 ch;
+	int		 ch, skip;
 	DBT		 key, val;
 	struct mdoc	*mdoc;
 	struct man	*man;
-	const char	*fn, *msec, *mtitle, *arch;
+	const char	*fn, *msec, *march, *mtitle;
 	uint64_t	 mask;
 	size_t		 sv;
 	unsigned	 seq;
 	struct db_val	 vbuf;
 	char		 type;
 
-	for (rec = 0; of; of = of->next) {
+	rec = 0;
+	for (of = of->first; of; of = of->next) {
 		fn = of->fname;
 
 		/*
@@ -544,15 +586,17 @@ index_merge(const struct of *of, struct 
 
 		if (NULL != mdoc) {
 			msec = mdoc_meta(mdoc)->msec;
-			arch = mdoc_meta(mdoc)->arch;
+			march = mdoc_meta(mdoc)->arch;
+			if (NULL == march)
+				march = "";
 			mtitle = mdoc_meta(mdoc)->title;
 		} else if (NULL != man) {
 			msec = man_meta(man)->msec;
-			arch = NULL;
+			march = "";
 			mtitle = man_meta(man)->title;
 		} else {
 			msec = of->sec;
-			arch = of->arch;
+			march = of->arch;
 			mtitle = of->title;
 		}
 
@@ -562,24 +606,30 @@ index_merge(const struct of *of, struct 
 		 * with the directory where the file is located.
 		 */
 
-		if (0 == use_all) {
-			assert(of->sec);
-			assert(msec);
-			if (strcasecmp(msec, of->sec))
-				continue;
-
-			if (NULL == arch) {
-				if (NULL != of->arch)
-					continue;
-			} else if (NULL == of->arch ||
-					strcasecmp(arch, of->arch))
-				continue;
+		skip = 0;
+		assert(of->sec);
+		assert(msec);
+		if (strcasecmp(msec, of->sec)) {
+			if (verb)
+				fprintf(stderr, "%s: "
+					"section \"%s\" manual "
+					"in \"%s\" directory\n",
+					fn, msec, of->sec);
+			skip = 1;
+		}
+
+		assert(of->arch);
+		assert(march);
+		if (strcasecmp(march, of->arch)) {
+			if (verb)
+				fprintf(stderr, "%s: "
+					"architecture \"%s\" manual "
+					"in \"%s\" directory\n",
+					fn, march, of->arch);
+			skip = 1;
 		}
 
-		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,
@@ -588,13 +638,20 @@ index_merge(const struct of *of, struct 
 
 		assert(of->title);
 		assert(mtitle);
-
-		if (0 == strcasecmp(mtitle, of->title))
+		if (strcasecmp(mtitle, of->title)) {
+			if (verb)
+				fprintf(stderr, "%s: "
+					"title \"%s\" in file "
+					"but \"%s\" in filename\n",
+					fn, mtitle, of->title);
+			skip = 1;
+		} else
 			mtitle = of->title;
-		else if (0 == use_all)
+
+		if (skip && !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
@@ -608,7 +665,7 @@ index_merge(const struct of *of, struct 
 		buf_appendb(dbuf, fn, strlen(fn) + 1);
 		buf_appendb(dbuf, msec, strlen(msec) + 1);
 		buf_appendb(dbuf, mtitle, strlen(mtitle) + 1);
-		buf_appendb(dbuf, arch, strlen(arch) + 1);
+		buf_appendb(dbuf, march, strlen(march) + 1);
 
 		sv = dbuf->len;
 
@@ -626,17 +683,22 @@ index_merge(const struct of *of, struct 
 		else
 			pformatted(hash, buf, dbuf, of);
 
+		/* Test mode, do not access any database. */
+
+		if (NULL == mdb->db || NULL == mdb->idx)
+			continue;
+
 		/*
 		 * Reclaim an empty index record, if available.
 		 * Use its record number for all new btree nodes.
 		 */
 
-		if (reccur > 0) {
-			--reccur;
-			rec = recs[(int)reccur];
-		} else if (maxrec > 0) {
-			rec = maxrec;
-			maxrec = 0;
+		if (recs->cur > 0) {
+			recs->cur--;
+			rec = recs->stack[(int)recs->cur];
+		} else if (recs->last > 0) {
+			rec = recs->last;
+			recs->last = 0;
 		} else
 			rec++;
 		vbuf.rec = htobe32(rec);
@@ -654,13 +716,13 @@ index_merge(const struct of *of, struct 
 			vbuf.mask = htobe64(mask);
 			val.size = sizeof(struct db_val);
 			val.data = &vbuf;
-			dbt_put(db, dbf, &key, &val);
+			dbt_put(mdb->db, mdb->dbn, &key, &val);
 		}
 		if (ch < 0) {
 			perror("hash");
 			exit((int)MANDOCLEVEL_SYSERR);
 		}
-		
+
 		/*
 		 * Apply to the index.  If we haven't had a description
 		 * set, put an empty one in now.
@@ -675,10 +737,10 @@ index_merge(const struct of *of, struct 
 		val.data = dbuf->cp;
 		val.size = dbuf->len;
 
-		if (verb)
-			printf("%s: Added index\n", fn);
+		if (verb > 1)
+			printf("%s: adding to index\n", fn);
 
-		dbt_put(idx, idxf, &key, &val);
+		dbt_put(mdb->idx, mdb->idxn, &key, &val);
 	}
 }
 
@@ -689,9 +751,7 @@ index_merge(const struct of *of, struct 
  * in `idx' (zeroing its value size).
  */
 static void
-index_prune(const struct of *ofile, DB *db, const char *dbf, 
-		DB *idx, const char *idxf, recno_t *maxrec,
-		recno_t **recs, size_t *recsz, size_t *reccur)
+index_prune(const struct of *ofile, struct mdb *mdb, struct recs *recs)
 {
 	const struct of	*of;
 	const char	*fn;
@@ -700,12 +760,12 @@ index_prune(const struct of *ofile, DB *
 	DBT		 key, val;
 	int		 ch;
 
-	*reccur = 0;
+	recs->cur = 0;
 	seq = R_FIRST;
-	while (0 == (ch = (*idx->seq)(idx, &key, &val, seq))) {
+	while (0 == (ch = (*mdb->idx->seq)(mdb->idx, &key, &val, seq))) {
 		seq = R_NEXT;
 		assert(sizeof(recno_t) == key.size);
-		memcpy(maxrec, key.data, key.size);
+		memcpy(&recs->last, key.data, key.size);
 
 		/* Deleted records are zero-sized.  Skip them. */
 
@@ -723,12 +783,12 @@ index_prune(const struct of *ofile, DB *
 		if (NULL == memchr(fn, '\0', val.size - 1))
 			break;
 
-		/* 
+		/*
 		 * Search for the file in those we care about.
 		 * XXX: build this into a tree.  Too slow.
 		 */
 
-		for (of = ofile; of; of = of->next)
+		for (of = ofile->first; of; of = of->next)
 			if (0 == strcmp(fn, of->fname))
 				break;
 
@@ -741,55 +801,58 @@ index_prune(const struct of *ofile, DB *
 		 */
 
 		sseq = R_FIRST;
-		while (0 == (ch = (*db->seq)(db, &key, &val, sseq))) {
+		while (0 == (ch = (*mdb->db->seq)(mdb->db,
+					&key, &val, sseq))) {
 			sseq = R_NEXT;
 			if (sizeof(struct db_val) != val.size)
 				break;
 
 			vbuf = val.data;
-			if (*maxrec != betoh32(vbuf->rec))
+			if (recs->last != betoh32(vbuf->rec))
 				continue;
 
-			if ((ch = (*db->del)(db, &key, R_CURSOR)) < 0)
+			if ((ch = (*mdb->db->del)(mdb->db,
+					&key, R_CURSOR)) < 0)
 				break;
 		}
 
 		if (ch < 0) {
-			perror(dbf);
+			perror(mdb->dbn);
 			exit((int)MANDOCLEVEL_SYSERR);
 		} else if (1 != ch) {
-			fprintf(stderr, "%s: Corrupt database\n", dbf);
+			fprintf(stderr, "%s: corrupt database\n",
+					mdb->dbn);
 			exit((int)MANDOCLEVEL_SYSERR);
 		}
 
-		if (verb)
-			printf("%s: Deleted index\n", fn);
+		if (verb > 1)
+			printf("%s: deleting from index\n", fn);
 
 		val.size = 0;
-		ch = (*idx->put)(idx, &key, &val, R_CURSOR);
+		ch = (*mdb->idx->put)(mdb->idx, &key, &val, R_CURSOR);
 
 		if (ch < 0)
 			break;
 cont:
-		if (*reccur >= *recsz) {
-			*recsz += MANDOC_SLOP;
-			*recs = mandoc_realloc
-				(*recs, *recsz * sizeof(recno_t));
+		if (recs->cur >= recs->size) {
+			recs->size += MANDOC_SLOP;
+			recs->stack = mandoc_realloc(recs->stack,
+					recs->size * sizeof(recno_t));
 		}
 
-		(*recs)[(int)*reccur] = *maxrec;
-		(*reccur)++;
+		recs->stack[(int)recs->cur] = recs->last;
+		recs->cur++;
 	}
 
 	if (ch < 0) {
-		perror(idxf);
+		perror(mdb->idxn);
 		exit((int)MANDOCLEVEL_SYSERR);
 	} else if (1 != ch) {
-		fprintf(stderr, "%s: Corrupt index\n", idxf);
+		fprintf(stderr, "%s: corrupt index\n", mdb->idxn);
 		exit((int)MANDOCLEVEL_SYSERR);
 	}
 
-	(*maxrec)++;
+	recs->last++;
 }
 
 /*
@@ -1281,7 +1344,8 @@ pformatted(DB *hash, struct buf *buf, st
 	size_t		 len, plen;
 
 	if (NULL == (stream = fopen(of->fname, "r"))) {
-		perror(of->fname);
+		if (verb)
+			perror(of->fname);
 		return;
 	}
 
@@ -1320,6 +1384,9 @@ pformatted(DB *hash, struct buf *buf, st
 
 	line = fgetln(stream, &len);
 	if (NULL == line || ' ' != *line || '\n' != line[(int)len - 1]) {
+		if (verb)
+			fprintf(stderr, "%s: cannot find NAME section\n",
+					of->fname);
 		buf_appendb(dbuf, buf->cp, buf->size);
 		hash_put(hash, buf, TYPE_Nd);
 		fclose(stream);
@@ -1337,8 +1404,12 @@ pformatted(DB *hash, struct buf *buf, st
 	if (NULL != (p = strstr(line, "- "))) {
 		for (p += 2; ' ' == *p || '\b' == *p; p++)
 			/* Skip to next word. */ ;
-	} else
+	} else {
+		if (verb)
+			fprintf(stderr, "%s: no dash in title line\n",
+					of->fname);
 		p = line;
+	}
 
 	if ((plen = strlen(p)) > 70) {
 		plen = 70;
@@ -1382,14 +1453,14 @@ ofile_argbuild(int argc, char *argv[], s
 		 */
 
 		if (strlcpy(buf, argv[i], sizeof(buf)) >= sizeof(buf)) {
-			fprintf(stderr, "%s: Path too long\n", argv[i]);
+			fprintf(stderr, "%s: path too long\n", argv[i]);
 			continue;
 		}
-		sec = arch = title = NULL;
+		sec = arch = title = "";
 		src_form = 0;
 		p = strrchr(buf, '\0');
 		while (p-- > buf) {
-			if (NULL == sec && '.' == *p) {
+			if ('\0' == *sec && '.' == *p) {
 				sec = p + 1;
 				*p = '\0';
 				if ('0' == *sec)
@@ -1400,7 +1471,7 @@ ofile_argbuild(int argc, char *argv[], s
 			}
 			if ('/' != *p)
 				continue;
-			if (NULL == title) {
+			if ('\0' == *title) {
 				title = p + 1;
 				*p = '\0';
 				continue;
@@ -1413,8 +1484,14 @@ ofile_argbuild(int argc, char *argv[], s
 				arch = p + 1;
 			break;
 		}
-		if (NULL == title)
+		if ('\0' == *title) {
+			if (verb)
+				fprintf(stderr,
+				    "%s: cannot deduce title "
+				    "from filename\n",
+				    argv[i]);
 			title = buf;
+		}
 
 		/*
 		 * Build the file structure.
@@ -1422,10 +1499,8 @@ ofile_argbuild(int argc, char *argv[], s
 
 		nof = mandoc_calloc(1, sizeof(struct of));
 		nof->fname = mandoc_strdup(argv[i]);
-		if (NULL != sec)
-			nof->sec = mandoc_strdup(sec);
-		if (NULL != arch)
-			nof->arch = mandoc_strdup(arch);
+		nof->sec = mandoc_strdup(sec);
+		nof->arch = mandoc_strdup(arch);
 		nof->title = mandoc_strdup(title);
 		nof->src_form = src_form;
 
@@ -1433,8 +1508,8 @@ ofile_argbuild(int argc, char *argv[], s
 		 * Add the structure to the list.
 		 */
 
-		if (verb > 2) 
-			printf("%s: Scheduling\n", argv[i]);
+		if (verb > 2)
+			printf("%s: scheduling\n", argv[i]);
 		if (NULL == *of) {
 			*of = nof;
 			(*of)->first = nof;
@@ -1468,8 +1543,9 @@ ofile_dirbuild(const char *dir, const ch
 	int		 src_form;
 
 	if (NULL == (d = opendir(dir))) {
-		perror(dir);
-		return(0);
+		if (verb)
+			perror(dir);
+		return;
 	}
 
 	while (NULL != (dp = readdir(d))) {
@@ -1490,22 +1566,35 @@ ofile_dirbuild(const char *dir, const ch
 			 *   cat<section>/[<arch>/]
 			 */
 
-			if (NULL == sec) {
+			if ('\0' == *sec) {
 				if(0 == strncmp("man", fn, 3)) {
 					src_form |= MANDOC_SRC;
 					sec = fn + 3;
 				} else if (0 == strncmp("cat", fn, 3)) {
 					src_form |= MANDOC_FORM;
 					sec = fn + 3;
-				} else if (use_all)
-					sec = fn;
-				else
-					continue;
-			} else if (NULL == arch && (use_all ||
-					NULL == strchr(fn, '.')))
+				} else {
+					if (verb) fprintf(stderr, "%s/%s: "
+					    "bad section\n", dir, fn);
+					if (use_all)
+						sec = fn;
+					else
+						continue;
+				}
+			} else if ('\0' == *arch) {
+				if (NULL != strchr(fn, '.')) {
+					if (verb) fprintf(stderr, "%s/%s: "
+					    "bad architecture\n", dir, fn);
+					if (0 == use_all)
+						continue;
+				}
 				arch = fn;
-			else if (0 == use_all)
-				continue;
+			} else {
+				if (verb) fprintf(stderr, "%s/%s: "
+				    "excessive subdirectory\n", dir, fn);
+				if (0 == use_all)
+					continue;
+			}
 
 			buf[0] = '\0';
 			strlcat(buf, dir, MAXPATHLEN);
@@ -1513,21 +1602,35 @@ ofile_dirbuild(const char *dir, const ch
 			sz = strlcat(buf, fn, MAXPATHLEN);
 
 			if (MAXPATHLEN <= sz) {
-				fprintf(stderr, "%s: Path too long\n", dir);
-				return(0);
+				if (verb) fprintf(stderr, "%s/%s: "
+				    "path too long\n", dir, fn);
+				continue;
 			}
- 
+
 			if (verb > 2)
-				printf("%s: Scanning\n", buf);
+				printf("%s: scanning\n", buf);
 
 			ofile_dirbuild(buf, sec, arch, src_form, of);
+			continue;
 		}
 
-		if (DT_REG != dp->d_type ||
-				(NULL == psec && !use_all) ||
-				! strcmp(MANDOC_DB, fn) ||
-				! strcmp(MANDOC_IDX, fn))
+		if (DT_REG != dp->d_type) {
+			if (verb)
+				fprintf(stderr,
+				    "%s/%s: not a regular file\n",
+				    dir, fn);
+			continue;
+		}
+		if (!strcmp(MANDOC_DB, fn) || !strcmp(MANDOC_IDX, fn))
 			continue;
+		if ('\0' == *psec) {
+			if (verb)
+				fprintf(stderr,
+				    "%s/%s: file outside section\n",
+				    dir, fn);
+			if (0 == use_all)
+				continue;
+		}
 
 		/*
 		 * By default, skip files where the file name suffix
@@ -1536,23 +1639,29 @@ ofile_dirbuild(const char *dir, const ch
 		 */
 
 		suffix = strrchr(fn, '.');
-		if (0 == use_all) {
-			if (NULL == suffix)
+		if (NULL == suffix) {
+			if (verb)
+				fprintf(stderr,
+				    "%s/%s: no filename suffix\n",
+				    dir, fn);
+			if (0 == use_all)
 				continue;
-			if ((MANDOC_SRC & src_form &&
-					 strcmp(suffix + 1, psec)) ||
+		} else if ((MANDOC_SRC & src_form &&
+				strcmp(suffix + 1, psec)) ||
 			    (MANDOC_FORM & src_form &&
-					 strcmp(suffix + 1, "0")))
-					continue;
-		}
-		if (NULL != suffix) {
+				strcmp(suffix + 1, "0"))) {
+			if (verb)
+				fprintf(stderr,
+				    "%s/%s: wrong filename suffix\n",
+				    dir, fn);
+			if (0 == use_all)
+				continue;
 			if ('0' == suffix[1])
 				src_form |= MANDOC_FORM;
 			else if ('1' <= suffix[1] && '9' >= suffix[1])
 				src_form |= MANDOC_SRC;
 		}
 
-
 		/*
 		 * Skip formatted manuals if a source version is
 		 * available.  Ignore the age: it is very unlikely
@@ -1561,11 +1670,11 @@ ofile_dirbuild(const char *dir, const ch
 		 * and in ports, old manuals get removed on update.
 		 */
 		if (0 == use_all && MANDOC_FORM & src_form &&
-				NULL != psec) {
+				'\0' != *psec) {
 			buf[0] = '\0';
 			strlcat(buf, dir, MAXPATHLEN);
 			p = strrchr(buf, '/');
-			if (NULL != parch && NULL != p)
+			if ('\0' != *parch && NULL != p)
 				for (p--; p > buf; p--)
 					if ('/' == *p)
 						break;
@@ -1578,7 +1687,8 @@ ofile_dirbuild(const char *dir, const ch
 			strlcat(buf, "/", MAXPATHLEN);
 			sz = strlcat(buf, fn, MAXPATHLEN);
 			if (sz >= MAXPATHLEN) {
-				fprintf(stderr, "%s: Path too long\n", buf);
+				if (verb) fprintf(stderr, "%s/%s: "
+				    "path too long\n", dir, fn);
 				continue;
 			}
 			q = strrchr(buf, '.');
@@ -1586,8 +1696,8 @@ ofile_dirbuild(const char *dir, const ch
 				*q = '\0';
 				sz = strlcat(buf, psec, MAXPATHLEN);
 				if (sz >= MAXPATHLEN) {
-					fprintf(stderr,
-					    "%s: Path too long\n", buf);
+					if (verb) fprintf(stderr, "%s/%s: "
+					    "path too long\n", dir, fn);
 					continue;
 				}
 				if (0 == access(buf, R_OK))
@@ -1595,23 +1705,22 @@ ofile_dirbuild(const char *dir, const ch
 			}
 		}
 
-		assert('.' == dir[0]);
-		assert('/' == dir[1]);
 		buf[0] = '\0';
-		strlcat(buf, dir + 2, MAXPATHLEN);
-		strlcat(buf, "/", MAXPATHLEN);
+		assert('.' == dir[0]);
+		if ('/' == dir[1]) {
+			strlcat(buf, dir + 2, MAXPATHLEN);
+			strlcat(buf, "/", MAXPATHLEN);
+		}
 		sz = strlcat(buf, fn, MAXPATHLEN);
 		if (sz >= MAXPATHLEN) {
-			fprintf(stderr, "%s: Path too long\n", dir);
+			fprintf(stderr, "%s/%s: path too long\n", dir, fn);
 			continue;
 		}
 
 		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);
+		nof->sec = mandoc_strdup(psec);
+		nof->arch = mandoc_strdup(parch);
 		nof->src_form = src_form;
 
 		/*
@@ -1628,7 +1737,7 @@ ofile_dirbuild(const char *dir, const ch
 		 */
 
 		if (verb > 2)
-			printf("%s: Scheduling\n", buf);
+			printf("%s: scheduling\n", buf);
 		if (NULL == *of) {
 			*of = nof;
 			(*of)->first = nof;
@@ -1656,15 +1765,4 @@ ofile_free(struct of *of)
 		free(of);
 		of = nof;
 	}
-}
-
-static void
-usage(void)
-{
-
-	fprintf(stderr, "usage: %s [-v] "
-			"[-C file] |"
-			" dir ... |"
-			" -d dir [file ...] |"
-			" -u dir [file ...]\n", progname);
 }
--
 To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-12-25  0:57 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-24 16:46 implement mandocdb -t Ingo Schwarze
2011-12-24 23:20 ` Kristaps Dzonsons
2011-12-25  0:38   ` Ingo Schwarze
2011-12-25  0:56     ` Kristaps Dzonsons

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).