Example #1
0
static void
pmandoc(struct mparse *mp, int fd, const char *fn, int list)
{
	struct mdoc	*mdoc;
	struct man	*man;
	int		 line, col;

	if (mparse_readfd(mp, fd, fn) >= MANDOCLEVEL_FATAL) {
		fprintf(stderr, "%s: Parse failure\n", fn);
		return;
	}

	mparse_result(mp, &mdoc, &man, NULL);
	line = 1;
	col = 0;

	if (mdoc) 
		pmdoc(mdoc_node(mdoc), &line, &col, list);
	else if (man)
		pman(man_node(man), &line, &col, list);
	else
		return;

	if ( ! list)
		putchar('\n');
}
Example #2
0
void
html_man(void *arg, const struct man *man)
{
	struct mhtml	 mh;

	memset(&mh, 0, sizeof(struct mhtml));
	print_man(man_meta(man), man_node(man), &mh, (struct html *)arg);
	putchar('\n');
}
Example #3
0
void
terminal_man(void *arg, const struct man *man)
{
	struct termp		*p;
	const struct man_meta	*meta;
	struct man_node		*n;
	struct mtermp		 mt;

	p = (struct termp *)arg;

	p->overstep = 0;
	p->rmargin = p->maxrmargin = p->defrmargin;
	p->tabwidth = term_len(p, 5);

	n = man_node(man)->child;
	meta = man_meta(man);

	memset(&mt, 0, sizeof(struct mtermp));

	mt.lmargin[mt.lmargincur] = term_len(p, p->defindent);
	mt.offset = term_len(p, p->defindent);
	mt.pardist = 1;

	if (p->synopsisonly) {
		while (n != NULL) {
			if (n->tok == MAN_SH &&
			    n->child->child->type == MAN_TEXT &&
			    !strcmp(n->child->child->string, "SYNOPSIS")) {
				if (n->child->next->child != NULL)
					print_man_nodelist(p, &mt,
					    n->child->next->child, meta);
				term_newln(p);
				break;
			}
			n = n->next;
		}
	} else {
		if (p->defindent == 0)
			p->defindent = 7;
		term_begin(p, print_man_head, print_man_foot, meta);
		p->flags |= TERMP_NOSPACE;
		if (n != NULL)
			print_man_nodelist(p, &mt, n, meta);
		term_end(p);
	}
}
Example #4
0
void
terminal_man(void *arg, const struct man *man)
{
	struct termp		*p;
	const struct man_node	*n;
	const struct man_meta	*m;
	struct mtermp		 mt;

	p = (struct termp *)arg;

	p->overstep = 0;
	p->maxrmargin = p->defrmargin;
	p->tabwidth = term_len(p, 5);

	if (NULL == p->symtab)
		switch (p->enc) {
		case (TERMENC_ASCII):
			p->symtab = chars_init(CHARS_ASCII);
			break;
		default:
			abort();
			/* NOTREACHED */
		}

	n = man_node(man);
	m = man_meta(man);

	term_begin(p, print_man_head, print_man_foot, m);
	p->flags |= TERMP_NOSPACE;

	mt.fl = 0;
	mt.lmargin = term_len(p, INDENT);
	mt.offset = term_len(p, INDENT);

	if (n->child)
		print_man_nodelist(p, &mt, n->child, m);

	term_end(p);
}
Example #5
0
static void
pmandoc(struct mparse *mp, int fd, const char *fn, int list)
{
	struct mdoc	*mdoc;
	struct man	*man;
	int		 line, col;

	mparse_readfd(mp, fd, fn);
	mparse_result(mp, &mdoc, &man, NULL);
	line = 1;
	col = 0;

	if (mdoc)
		pmdoc(mdoc_node(mdoc), &line, &col, list);
	else if (man)
		pman(man_node(man), &line, &col, list);
	else
		return;

	if ( ! list)
		putchar('\n');
}
Example #6
0
void
terminal_man(void *arg, const struct man *man)
{
	struct termp		*p;
	const struct man_node	*n;
	const struct man_meta	*meta;
	struct mtermp		 mt;

	p = (struct termp *)arg;

	if (0 == p->defindent)
		p->defindent = 7;

	p->overstep = 0;
	p->maxrmargin = p->defrmargin;
	p->tabwidth = term_len(p, 5);

	if (NULL == p->symtab)
		p->symtab = mchars_alloc();

	n = man_node(man);
	meta = man_meta(man);

	term_begin(p, print_man_head, print_man_foot, meta);
	p->flags |= TERMP_NOSPACE;

	memset(&mt, 0, sizeof(struct mtermp));

	mt.lmargin[mt.lmargincur] = term_len(p, p->defindent);
	mt.offset = term_len(p, p->defindent);
	mt.pardist = 1;

	if (n->child)
		print_man_nodelist(p, &mt, n->child, meta);

	term_end(p);
}
Example #7
0
void
index_merge(const struct of *of, struct mparse *mp,
		struct buf *dbuf, struct buf *buf, DB *hash,
		struct mdb *mdb, struct recs *recs,
		const char *basedir)
{
	recno_t		 rec;
	int		 ch, skip;
	DBT		 key, val;
	DB		*files;  /* temporary file name table */
	char	 	 emptystring[1] = {'\0'};
	struct mdoc	*mdoc;
	struct man	*man;
	char		*p;
	const char	*fn, *msec, *march, *mtitle;
	uint64_t	 mask;
	size_t		 sv;
	unsigned	 seq;
	uint64_t	 vbuf[2];
	char		 type;

	if (warnings) {
		files = NULL;
		hash_reset(&files);
	}

	rec = 0;
	for (of = of->first; of; of = of->next) {
		fn = of->fname;

		/*
		 * Try interpreting the file as mdoc(7) or man(7)
		 * source code, unless it is already known to be
		 * formatted.  Fall back to formatted mode.
		 */

		mparse_reset(mp);
		mdoc = NULL;
		man = NULL;

		if ((MANDOC_SRC & of->src_form ||
		    ! (MANDOC_FORM & of->src_form)) &&
		    MANDOCLEVEL_FATAL > mparse_readfd(mp, -1, fn))
			mparse_result(mp, &mdoc, &man);

		if (NULL != mdoc) {
			msec = mdoc_meta(mdoc)->msec;
			march = mdoc_meta(mdoc)->arch;
			if (NULL == march)
				march = "";
			mtitle = mdoc_meta(mdoc)->title;
		} else if (NULL != man) {
			msec = man_meta(man)->msec;
			march = "";
			mtitle = man_meta(man)->title;
		} else {
			msec = of->sec;
			march = of->arch;
			mtitle = of->title;
		}

		/*
		 * Check whether the manual section given in a file
		 * agrees with the directory where the file is located.
		 * Some manuals have suffixes like (3p) on their
		 * section number either inside the file or in the
		 * directory name, some are linked into more than one
		 * section, like encrypt(1) = makekey(8).  Do not skip
		 * manuals for such reasons.
		 */

		skip = 0;
		assert(of->sec);
		assert(msec);
		if (strcasecmp(msec, of->sec))
			WARNING(fn, basedir, "Section \"%s\" manual "
				"in \"%s\" directory", msec, of->sec);
		/*
		 * Manual page directories exist for each kernel
		 * architecture as returned by machine(1).
		 * However, many manuals only depend on the
		 * application architecture as returned by arch(1).
		 * For example, some (2/ARM) manuals are shared
		 * across the "armish" and "zaurus" kernel
		 * architectures.
		 * A few manuals are even shared across completely
		 * different architectures, for example fdformat(1)
		 * on amd64, i386, sparc, and sparc64.
		 * Thus, warn about architecture mismatches,
		 * but don't skip manuals for this reason.
		 */

		assert(of->arch);
		assert(march);
		if (strcasecmp(march, of->arch))
			WARNING(fn, basedir, "Architecture \"%s\" "
				"manual in \"%s\" directory", 
				march, of->arch);

		/*
		 * By default, skip a file if the title given
		 * in the file disagrees with the file name.
		 * Do not warn, this happens for all MLINKs.
		 */

		assert(of->title);
		assert(mtitle);
		if (strcasecmp(mtitle, of->title))
			skip = 1;

		/*
		 * Build a title string for the file.  If it matches
		 * the location of the file, remember the title as
		 * found; else, remember it as missing.
		 */

		if (warnings) {
			buf->len = 0;
			buf_appendb(buf, mtitle, strlen(mtitle));
			buf_appendb(buf, "(", 1);
			buf_appendb(buf, msec, strlen(msec));
			if ('\0' != *march) {
				buf_appendb(buf, "/", 1);
				buf_appendb(buf, march, strlen(march));
			}
			buf_appendb(buf, ")", 2);
			for (p = buf->cp; '\0' != *p; p++)
				*p = tolower(*p);
			key.data = buf->cp;
			key.size = buf->len;
			val.data = NULL;
			val.size = 0;
			if (0 == skip)
				val.data = emptystring;
			else {
				ch = (*files->get)(files, &key, &val, 0);
				if (ch < 0) {
					perror("hash");
					exit((int)MANDOCLEVEL_SYSERR);
				} else if (ch > 0) {
					val.data = (void *)fn;
					val.size = strlen(fn) + 1;
				} else
					val.data = NULL;
			}
			if (NULL != val.data &&
			    (*files->put)(files, &key, &val, 0) < 0) {
				perror("hash");
				exit((int)MANDOCLEVEL_SYSERR);
			}
		}

		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.  Use the actual
		 * location of the file, such that the user can find
		 * it with man(1).  Since the description may not be
		 * set, we set a sentinel to see if we're going to
		 * write a nil byte in its place.
		 */

		dbuf->len = 0;
		type = mdoc ? 'd' : (man ? 'a' : 'c');
		buf_appendb(dbuf, &type, 1);
		buf_appendb(dbuf, fn, strlen(fn) + 1);
		buf_appendb(dbuf, of->sec, strlen(of->sec) + 1);
		buf_appendb(dbuf, of->title, strlen(of->title) + 1);
		buf_appendb(dbuf, of->arch, strlen(of->arch) + 1);

		sv = dbuf->len;

		/*
		 * Collect keyword/mask pairs.
		 * Each pair will become a new btree node.
		 */

		hash_reset(&hash);
		if (mdoc)
			pmdoc_node(hash, buf, dbuf,
				mdoc_node(mdoc), mdoc_meta(mdoc));
		else if (man)
			pman_node(hash, buf, dbuf, man_node(man));
		else
			pformatted(hash, buf, dbuf, of, basedir);

		/* Test mode, do not access any database. */

		if (NULL == mdb->db || NULL == mdb->idx)
			continue;

		/*
		 * Make sure the file name is always registered
		 * as an .Nm search key.
		 */
		buf->len = 0;
		buf_append(buf, of->title);
		hash_put(hash, buf, TYPE_Nm);

		/*
		 * Reclaim an empty index record, if available.
		 * Use its record number for all new btree nodes.
		 */

		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[1] = htobe64(rec);

		/*
		 * Copy from the in-memory hashtable of pending
		 * keyword/mask pairs into the database.
		 */

		seq = R_FIRST;
		while (0 == (ch = (*hash->seq)(hash, &key, &val, seq))) {
			seq = R_NEXT;
			assert(sizeof(uint64_t) == val.size);
			memcpy(&mask, val.data, val.size);
			vbuf[0] = htobe64(mask);
			val.size = sizeof(vbuf);
			val.data = &vbuf;
			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.
		 */

		if (dbuf->len == sv)
			buf_appendb(dbuf, "", 1);

		key.data = &rec;
		key.size = sizeof(recno_t);

		val.data = dbuf->cp;
		val.size = dbuf->len;

		if (verb)
			printf("%s: Adding to index: %s\n", basedir, fn);

		dbt_put(mdb->idx, mdb->idxn, &key, &val);
	}

	/*
	 * Iterate the remembered file titles and check that
	 * all files can be found by their main title.
	 */

	if (warnings) {
		seq = R_FIRST;
		while (0 == (*files->seq)(files, &key, &val, seq)) {
			seq = R_NEXT;
			if (val.size)
				WARNING((char *)val.data, basedir, 
					"Probably unreachable, title "
					"is %s", (char *)key.data);
		}
		(*files->close)(files);
	}
}
Example #8
0
/* ARGSUSED */
void
tree_man(void *arg, const struct man *man)
{

	print_man(man_node(man), 0);
}