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

* Re: implement mandocdb -t
  2011-12-24 16:46 implement mandocdb -t Ingo Schwarze
@ 2011-12-24 23:20 ` Kristaps Dzonsons
  2011-12-25  0:38   ` Ingo Schwarze
  0 siblings, 1 reply; 4+ messages in thread
From: Kristaps Dzonsons @ 2011-12-24 23:20 UTC (permalink / raw)
  To: tech

Hi Ingo,

I have a few issues with this patch -- not the intent or code, but 
rather with the consistency of the verbosity and warnings.

First, for consistency, all warnings/errors should follow "CAUSE: 
REASON" -- including those in the getopt() switch.  Thus, "conflicting 
options" messages should be prefixed by the offending switch case and 
"Too many arguments" should begin with "-C".

Second, verbosity.  I think we should settle this now.  BSD.lv only has 
a single `-v' and I think this should stay as such ("%s: added to index" 
or "%s: removed from index" (or whatever the message is)).  This is 
completely clear and is also valuable to the user.  Noting keywords 
added or removed is unnecessary when you consider that mandocdb(8) isn't 
there to debug the keywords of individual manuals: it's there to index them.

Regarding errors, the existences of (and not reasons for) mandoc(3) 
parse errors are printed to stderr ("parse failed").  For catpages, I 
think it's unnecessary to print anything more than the same.  After all, 
it's not like the operator can do anything about the page, no?  Just 
give the same error regardless the reason.  Maybe an extra kick like 
"%s: parse failed (not a manpage?)".

Moving on to the warnings (wrong sections, architectures, etc.).  This 
shouldn't be a `-v', as this isn't a verbose message, it's a warning. 
Maybe we can pull in `-W' from mandoc(1)?  I don't think these should be 
printed by default, as they don't affect parse status.  An extra 
"warning" flag is both consistent with other utilities and doesn't 
confuse the utility of `-v'.

Another option is to print the warnings by default, but use `-q' to 
silence them.  But that's also confusing because one `-q' silences 
warnings, but `-qq' silences parse errors also?  Ugh...

If we follow this logic, then `-t' is much clearer, as it does nothing 
but run in `add' mode without changing the database.  (Isn't this 
usually termed `-n', as with make(1)?  Sigh.)  However, the `-W' flag 
(or whatever it becomes) could be turned on by default just like 
`-Tlint' turns on `-Wall' in mandoc(1).  `-v' would be unaffected and 
meaningless as no files are actually added or removed.

Thoughts?

Kristaps
--
 To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv

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

* Re: implement mandocdb -t
  2011-12-24 23:20 ` Kristaps Dzonsons
@ 2011-12-25  0:38   ` Ingo Schwarze
  2011-12-25  0:56     ` Kristaps Dzonsons
  0 siblings, 1 reply; 4+ messages in thread
From: Ingo Schwarze @ 2011-12-25  0:38 UTC (permalink / raw)
  To: tech

Hi Kristaps,

thanks for the quick review!

Kristaps Dzonsons wrote on Sun, Dec 25, 2011 at 01:20:15AM +0200:

> I have a few issues with this patch -- not the intent or code, but
> rather with the consistency of the verbosity and warnings.
> 
> First, for consistency, all warnings/errors should follow "CAUSE:
> REASON" -- including those in the getopt() switch.  Thus,
> "conflicting options" messages should be prefixed by the offending
> switch case and "Too many arguments" should begin with "-C".

Makes sense to me; fixed.

> Second, verbosity.  I think we should settle this now.  BSD.lv only
> has a single `-v' and I think this should stay as such ("%s: added
> to index" or "%s: removed from index" (or whatever the message is)).
> This is completely clear and is also valuable to the user.  Noting
> keywords added or removed is unnecessary when you consider that
> mandocdb(8) isn't there to debug the keywords of individual manuals:
> it's there to index them.

Indeed, i didn't put dumping of keywords back.

I'm ok with having only a single -v, both in the documentation and
in the long term.  For now, i'd like to keep the "scanning" and
"scheduling" messages around, they help tremendously for
debugging, but can be removed when the dust has settled.

> Regarding errors, the existences of (and not reasons for) mandoc(3)
> parse errors are printed to stderr ("parse failed").  For catpages,
> I think it's unnecessary to print anything more than the same.
> After all, it's not like the operator can do anything about the
> page, no?  Just give the same error regardless the reason.  Maybe an
> extra kick like "%s: parse failed (not a manpage?)".

Well, mandocdb -t is not for the operator, but for the porter,
and for the porter, the message should be as specific as possible,
because a diligent porter may wish to fix the manuals and send
patches upstream.

> Moving on to the warnings (wrong sections, architectures, etc.).
> This shouldn't be a `-v', as this isn't a verbose message, it's a
> warning. Maybe we can pull in `-W' from mandoc(1)?  I don't think
> these should be printed by default, as they don't affect parse
> status.

Definitely, because printing them by default would clobber
the output of pkg_add(1), and espie@ would not be amused.

> An extra "warning" flag is both consistent with other
> utilities and doesn't confuse the utility of `-v'.

Interesting idea.
Right now, makewhatis(8) doesn't have a -W flag.

The only use of -W i can find is in Linux man(1):
   -W [Linux man] list the pathnames of matching formatted pages
which is similar to man -w, just for formatted manuals.
I don't think we have to respect that.

> Another option is to print the warnings by default, but use `-q' to
> silence them.

No way: pkg_add(1)!

> But that's also confusing because one `-q' silences
> warnings, but `-qq' silences parse errors also?  Ugh...

Ugh indeed.

> If we follow this logic, then `-t' is much clearer, as it does
> nothing but run in `add' mode without changing the database.  (Isn't
> this usually termed `-n', as with make(1)?  Sigh.)

Well, both OpenBSD makewhatis(8) and Linux mandb(8) call it -t,
so i'd like to stick with that.

> However, the  `-W' flag (or whatever it becomes) could be turned on
> by default just like `-Tlint' turns on `-Wall' in mandoc(1).

Indeed, -t without -W doesn't make much sense.
Besides, -t has to imply -W because otherwise,
we would break established behaviour of makewhatis -t.

> `-v' would be unaffected and meaningless as no files are actually
> added or removed.
> 
> Thoughts?

Lots of useful input, see below for a patch to be applied
on top of the previous one, for easier review.

OK in that revised form?
  Ingo


--- mandocdb.8.orig
+++ mandocdb.8
@@ -22,21 +22,20 @@
 .Nd index UNIX manuals
 .Sh SYNOPSIS
 .Nm
-.Op Fl avvv
+.Op Fl avW
 .Op Fl C Ar file
 .Nm
-.Op Fl avvv
+.Op Fl avW
 .Ar dir ...
 .Nm
-.Op Fl vvv
+.Op Fl vW
 .Fl d Ar dir
 .Op Ar
 .Nm
-.Op Fl vvv
+.Op Fl vW
 .Fl u Ar dir
 .Op Ar
 .Nm
-.Op Fl vv
 .Fl t Ar
 .Sh DESCRIPTION
 The
@@ -98,8 +97,8 @@ for potential problems.
 No databases are modified.
 Implies
 .Fl a
-and one
-.Fl v .
+and
+.Fl W .
 All diagnostic messages are printed to the standard output;
 the standard error output is not used.
 .It Fl u Ar dir
@@ -109,19 +108,10 @@ from the database in
 .Ar dir
 without truncating it.
 .It Fl v
-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.
+Display all files added or removed to the index.
+.It Fl W
+Print warnings about potential problems with manual pages
+to the standard error output.
 .El
 .Pp
 If fatal parse errors are encountered while parsing, the offending file
--- mandocdb.c.orig
+++ mandocdb.c
@@ -267,6 +267,7 @@ static	const struct mdoc_handler mdocs[MDOC_MAX] = {
 static	const char	 *progname;
 static	int		  use_all;  /* Use all directories and files. */
 static	int		  verb;  /* Output verbosity level. */
+static	int		  warnings;  /* Potential problems in manuals. */
 
 int
 mandocdb(int argc, char *argv[])
@@ -299,22 +300,24 @@ mandocdb(int argc, char *argv[])
 	memset(&mdb, 0, sizeof(struct mdb));
 	memset(&recs, 0, sizeof(struct recs));
 
-	verb = 0;
 	use_all = 0;
+	verb = 0;
+	warnings = 0;
 	of = NULL;
 	mp = NULL;
 	hash = NULL;
 	op = OP_DEFAULT;
 	dir = NULL;
 
-	while (-1 != (ch = getopt(argc, argv, "aC:d:tu:v")))
+	while (-1 != (ch = getopt(argc, argv, "aC:d:tu:vW")))
 		switch (ch) {
 		case ('a'):
 			use_all = 1;
 			break;
 		case ('C'):
 			if (op) {
-				fprintf(stderr, "conflicting options\n");
+				fprintf(stderr,
+				    "-C: conflicting options\n");
 				goto usage;
 			}
 			dir = optarg;
@@ -322,7 +325,8 @@ mandocdb(int argc, char *argv[])
 			break;
 		case ('d'):
 			if (op) {
-				fprintf(stderr, "conflicting options\n");
+				fprintf(stderr,
+				    "-d: conflicting options\n");
 				goto usage;
 			}
 			dir = optarg;
@@ -331,16 +335,18 @@ mandocdb(int argc, char *argv[])
 		case ('t'):
 			dup2(STDOUT_FILENO, STDERR_FILENO);
 			if (op) {
-				fprintf(stderr, "conflicting options\n");
+				fprintf(stderr,
+				    "-t: conflicting options\n");
 				goto usage;
 			}
 			op = OP_TEST;
 			use_all = 1;
-			verb++;
+			warnings = 1;
 			break;
 		case ('u'):
 			if (op) {
-				fprintf(stderr, "conflicting options\n");
+				fprintf(stderr,
+				    "-u: conflicting options\n");
 				goto usage;
 			}
 			dir = optarg;
@@ -349,6 +355,9 @@ mandocdb(int argc, char *argv[])
 		case ('v'):
 			verb++;
 			break;
+		case ('W'):
+			warnings = 1;
+			break;
 		default:
 			goto usage;
 		}
@@ -357,7 +366,7 @@ mandocdb(int argc, char *argv[])
 	argv += optind;
 
 	if (OP_CONFFILE == op && argc > 0) {
-		fprintf(stderr, "too many arguments for -C\n");
+		fprintf(stderr, "-C: too many arguments\n");
 		goto usage;
 	}
 
@@ -489,11 +498,6 @@ mandocdb(int argc, char *argv[])
 			exit((int)MANDOCLEVEL_SYSERR);
 		}
 
-		if (verb > 2) {
-			printf("%s: truncated\n", mdb.dbn);
-			printf("%s: truncated\n", mdb.idxn);
-		}
-
 		ofile_free(of);
 		of = NULL;
 
@@ -610,7 +614,7 @@ index_merge(const struct of *of, struct mparse *mp,
 		assert(of->sec);
 		assert(msec);
 		if (strcasecmp(msec, of->sec)) {
-			if (verb)
+			if (warnings)
 				fprintf(stderr, "%s: "
 					"section \"%s\" manual "
 					"in \"%s\" directory\n",
@@ -621,7 +625,7 @@ index_merge(const struct of *of, struct mparse *mp,
 		assert(of->arch);
 		assert(march);
 		if (strcasecmp(march, of->arch)) {
-			if (verb)
+			if (warnings)
 				fprintf(stderr, "%s: "
 					"architecture \"%s\" manual "
 					"in \"%s\" directory\n",
@@ -639,7 +643,7 @@ index_merge(const struct of *of, struct mparse *mp,
 		assert(of->title);
 		assert(mtitle);
 		if (strcasecmp(mtitle, of->title)) {
-			if (verb)
+			if (warnings)
 				fprintf(stderr, "%s: "
 					"title \"%s\" in file "
 					"but \"%s\" in filename\n",
@@ -737,7 +741,7 @@ index_merge(const struct of *of, struct mparse *mp,
 		val.data = dbuf->cp;
 		val.size = dbuf->len;
 
-		if (verb > 1)
+		if (verb)
 			printf("%s: adding to index\n", fn);
 
 		dbt_put(mdb->idx, mdb->idxn, &key, &val);
@@ -825,7 +829,7 @@ index_prune(const struct of *ofile, struct mdb *mdb, struct recs *recs)
 			exit((int)MANDOCLEVEL_SYSERR);
 		}
 
-		if (verb > 1)
+		if (verb)
 			printf("%s: deleting from index\n", fn);
 
 		val.size = 0;
@@ -1344,7 +1348,7 @@ pformatted(DB *hash, struct buf *buf, struct buf *dbuf,
 	size_t		 len, plen;
 
 	if (NULL == (stream = fopen(of->fname, "r"))) {
-		if (verb)
+		if (warnings)
 			perror(of->fname);
 		return;
 	}
@@ -1384,7 +1388,7 @@ pformatted(DB *hash, struct buf *buf, struct buf *dbuf,
 
 	line = fgetln(stream, &len);
 	if (NULL == line || ' ' != *line || '\n' != line[(int)len - 1]) {
-		if (verb)
+		if (warnings)
 			fprintf(stderr, "%s: cannot find NAME section\n",
 					of->fname);
 		buf_appendb(dbuf, buf->cp, buf->size);
@@ -1405,7 +1409,7 @@ pformatted(DB *hash, struct buf *buf, struct buf *dbuf,
 		for (p += 2; ' ' == *p || '\b' == *p; p++)
 			/* Skip to next word. */ ;
 	} else {
-		if (verb)
+		if (warnings)
 			fprintf(stderr, "%s: no dash in title line\n",
 					of->fname);
 		p = line;
@@ -1485,7 +1489,7 @@ ofile_argbuild(int argc, char *argv[], struct of **of)
 			break;
 		}
 		if ('\0' == *title) {
-			if (verb)
+			if (warnings)
 				fprintf(stderr,
 				    "%s: cannot deduce title "
 				    "from filename\n",
@@ -1508,7 +1512,7 @@ ofile_argbuild(int argc, char *argv[], struct of **of)
 		 * Add the structure to the list.
 		 */
 
-		if (verb > 2)
+		if (verb > 1)
 			printf("%s: scheduling\n", argv[i]);
 		if (NULL == *of) {
 			*of = nof;
@@ -1543,7 +1547,7 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
 	int		 src_form;
 
 	if (NULL == (d = opendir(dir))) {
-		if (verb)
+		if (warnings)
 			perror(dir);
 		return;
 	}
@@ -1574,8 +1578,9 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
 					src_form |= MANDOC_FORM;
 					sec = fn + 3;
 				} else {
-					if (verb) fprintf(stderr, "%s/%s: "
-					    "bad section\n", dir, fn);
+					if (warnings) fprintf(stderr,
+					    "%s/%s: bad section\n",
+					    dir, fn);
 					if (use_all)
 						sec = fn;
 					else
@@ -1583,14 +1588,15 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
 				}
 			} else if ('\0' == *arch) {
 				if (NULL != strchr(fn, '.')) {
-					if (verb) fprintf(stderr, "%s/%s: "
-					    "bad architecture\n", dir, fn);
+					if (warnings) fprintf(stderr,
+					    "%s/%s: bad architecture\n",
+					    dir, fn);
 					if (0 == use_all)
 						continue;
 				}
 				arch = fn;
 			} else {
-				if (verb) fprintf(stderr, "%s/%s: "
+				if (warnings) fprintf(stderr, "%s/%s: "
 				    "excessive subdirectory\n", dir, fn);
 				if (0 == use_all)
 					continue;
@@ -1602,12 +1608,12 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
 			sz = strlcat(buf, fn, MAXPATHLEN);
 
 			if (MAXPATHLEN <= sz) {
-				if (verb) fprintf(stderr, "%s/%s: "
+				if (warnings) fprintf(stderr, "%s/%s: "
 				    "path too long\n", dir, fn);
 				continue;
 			}
 
-			if (verb > 2)
+			if (verb > 1)
 				printf("%s: scanning\n", buf);
 
 			ofile_dirbuild(buf, sec, arch, src_form, of);
@@ -1615,7 +1621,7 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
 		}
 
 		if (DT_REG != dp->d_type) {
-			if (verb)
+			if (warnings)
 				fprintf(stderr,
 				    "%s/%s: not a regular file\n",
 				    dir, fn);
@@ -1624,7 +1630,7 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
 		if (!strcmp(MANDOC_DB, fn) || !strcmp(MANDOC_IDX, fn))
 			continue;
 		if ('\0' == *psec) {
-			if (verb)
+			if (warnings)
 				fprintf(stderr,
 				    "%s/%s: file outside section\n",
 				    dir, fn);
@@ -1640,7 +1646,7 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
 
 		suffix = strrchr(fn, '.');
 		if (NULL == suffix) {
-			if (verb)
+			if (warnings)
 				fprintf(stderr,
 				    "%s/%s: no filename suffix\n",
 				    dir, fn);
@@ -1650,7 +1656,7 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
 				strcmp(suffix + 1, psec)) ||
 			    (MANDOC_FORM & src_form &&
 				strcmp(suffix + 1, "0"))) {
-			if (verb)
+			if (warnings)
 				fprintf(stderr,
 				    "%s/%s: wrong filename suffix\n",
 				    dir, fn);
@@ -1687,8 +1693,9 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
 			strlcat(buf, "/", MAXPATHLEN);
 			sz = strlcat(buf, fn, MAXPATHLEN);
 			if (sz >= MAXPATHLEN) {
-				if (verb) fprintf(stderr, "%s/%s: "
-				    "path too long\n", dir, fn);
+				if (warnings) fprintf(stderr,
+				    "%s/%s: path too long\n",
+				    dir, fn);
 				continue;
 			}
 			q = strrchr(buf, '.');
@@ -1696,8 +1703,9 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
 				*q = '\0';
 				sz = strlcat(buf, psec, MAXPATHLEN);
 				if (sz >= MAXPATHLEN) {
-					if (verb) fprintf(stderr, "%s/%s: "
-					    "path too long\n", dir, fn);
+					if (warnings) fprintf(stderr,
+					    "%s/%s: path too long\n",
+					    dir, fn);
 					continue;
 				}
 				if (0 == access(buf, R_OK))
@@ -1713,7 +1721,8 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
 		}
 		sz = strlcat(buf, fn, MAXPATHLEN);
 		if (sz >= MAXPATHLEN) {
-			fprintf(stderr, "%s/%s: path too long\n", dir, fn);
+			if (warnings) fprintf(stderr,
+			    "%s/%s: path too long\n", dir, fn);
 			continue;
 		}
 
@@ -1736,7 +1745,7 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
 		 * Add the structure to the list.
 		 */
 
-		if (verb > 2)
+		if (verb > 1)
 			printf("%s: scheduling\n", buf);
 		if (NULL == *of) {
 			*of = nof;



--
 To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv

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

* Re: implement mandocdb -t
  2011-12-25  0:38   ` Ingo Schwarze
@ 2011-12-25  0:56     ` Kristaps Dzonsons
  0 siblings, 0 replies; 4+ messages in thread
From: Kristaps Dzonsons @ 2011-12-25  0:56 UTC (permalink / raw)
  To: tech

On 25/12/2011 02:38, Ingo Schwarze wrote:
> Hi Kristaps,
>
> thanks for the quick review!
>
> Kristaps Dzonsons wrote on Sun, Dec 25, 2011 at 01:20:15AM +0200:
>
>> I have a few issues with this patch -- not the intent or code, but
>> rather with the consistency of the verbosity and warnings.
>>
>> First, for consistency, all warnings/errors should follow "CAUSE:
>> REASON" -- including those in the getopt() switch.  Thus,
>> "conflicting options" messages should be prefixed by the offending
>> switch case and "Too many arguments" should begin with "-C".
>
> Makes sense to me; fixed.
>
>> Second, verbosity.  I think we should settle this now.  BSD.lv only
>> has a single `-v' and I think this should stay as such ("%s: added
>> to index" or "%s: removed from index" (or whatever the message is)).
>> This is completely clear and is also valuable to the user.  Noting
>> keywords added or removed is unnecessary when you consider that
>> mandocdb(8) isn't there to debug the keywords of individual manuals:
>> it's there to index them.
>
> Indeed, i didn't put dumping of keywords back.
>
> I'm ok with having only a single -v, both in the documentation and
> in the long term.  For now, i'd like to keep the "scanning" and
> "scheduling" messages around, they help tremendously for
> debugging, but can be removed when the dust has settled.
>
>> Regarding errors, the existences of (and not reasons for) mandoc(3)
>> parse errors are printed to stderr ("parse failed").  For catpages,
>> I think it's unnecessary to print anything more than the same.
>> After all, it's not like the operator can do anything about the
>> page, no?  Just give the same error regardless the reason.  Maybe an
>> extra kick like "%s: parse failed (not a manpage?)".
>

>
>> Moving on to the warnings (wrong sections, architectures, etc.).
>> This shouldn't be a `-v', as this isn't a verbose message, it's a
>> warning. Maybe we can pull in `-W' from mandoc(1)?  I don't think
>> these should be printed by default, as they don't affect parse
>> status.
>
> Definitely, because printing them by default would clobber
> the output of pkg_add(1), and espie@ would not be amused.
>
>> An extra "warning" flag is both consistent with other
>> utilities and doesn't confuse the utility of `-v'.
>
> Interesting idea.
> Right now, makewhatis(8) doesn't have a -W flag.
>
> The only use of -W i can find is in Linux man(1):
>     -W [Linux man] list the pathnames of matching formatted pages
> which is similar to man -w, just for formatted manuals.
> I don't think we have to respect that.
>
>> Another option is to print the warnings by default, but use `-q' to
>> silence them.
>
> No way: pkg_add(1)!
>
>> But that's also confusing because one `-q' silences
>> warnings, but `-qq' silences parse errors also?  Ugh...
>
> Ugh indeed.
>
>> If we follow this logic, then `-t' is much clearer, as it does
>> nothing but run in `add' mode without changing the database.  (Isn't
>> this usually termed `-n', as with make(1)?  Sigh.)
>
> Well, both OpenBSD makewhatis(8) and Linux mandb(8) call it -t,
> so i'd like to stick with that.
>
>> However, the  `-W' flag (or whatever it becomes) could be turned on
>> by default just like `-Tlint' turns on `-Wall' in mandoc(1).
>
> Indeed, -t without -W doesn't make much sense.
> Besides, -t has to imply -W because otherwise,
> we would break established behaviour of makewhatis -t.
>
>> `-v' would be unaffected and meaningless as no files are actually
>> added or removed.
>>
>> Thoughts?
>
> Lots of useful input, see below for a patch to be applied
> on top of the previous one, for easier review.
>
> OK in that revised form?

Ingo,

Thanks for making these changes so quickly!  I like what I see, so 
please commit.  You don't, by the way, need to initialise the static 
variables to zero.

 > Well, mandocdb -t is not for the operator, but for the porter,
 > and for the porter, the message should be as specific as possible,
 > because a diligent porter may wish to fix the manuals and send
 > patches upstream.

I agree with this logic.

When you've checked everything in, by the way, I've a local patch that 
groks everything between NAME and the next section instead of just the 
first line.  This catches full descriptions and all names.  I'll convert 
that to a function reading into a string buffer, then fit it into your 
checks.

Thanks again,

Kristaps
--
 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).