xref: /minix3/external/bsd/mdocml/dist/demandoc.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	Id: demandoc.c,v 1.7 2012/05/31 22:27:14 schwarze Exp  */
292395e9cSLionel Sambuc /*
392395e9cSLionel Sambuc  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
492395e9cSLionel Sambuc  *
592395e9cSLionel Sambuc  * Permission to use, copy, modify, and distribute this software for any
692395e9cSLionel Sambuc  * purpose with or without fee is hereby granted, provided that the above
792395e9cSLionel Sambuc  * copyright notice and this permission notice appear in all copies.
892395e9cSLionel Sambuc  *
992395e9cSLionel Sambuc  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1092395e9cSLionel Sambuc  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1192395e9cSLionel Sambuc  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1292395e9cSLionel Sambuc  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1392395e9cSLionel Sambuc  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1492395e9cSLionel Sambuc  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1592395e9cSLionel Sambuc  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1692395e9cSLionel Sambuc  */
1792395e9cSLionel Sambuc #ifdef HAVE_CONFIG_H
1892395e9cSLionel Sambuc #include "config.h"
1992395e9cSLionel Sambuc #endif
2092395e9cSLionel Sambuc 
2192395e9cSLionel Sambuc #include <assert.h>
2292395e9cSLionel Sambuc #include <ctype.h>
2392395e9cSLionel Sambuc #include <getopt.h>
2492395e9cSLionel Sambuc #include <stdio.h>
2592395e9cSLionel Sambuc #include <stdlib.h>
2692395e9cSLionel Sambuc #include <string.h>
2792395e9cSLionel Sambuc #include <unistd.h>
2892395e9cSLionel Sambuc 
2992395e9cSLionel Sambuc #include "man.h"
3092395e9cSLionel Sambuc #include "mdoc.h"
3192395e9cSLionel Sambuc #include "mandoc.h"
3292395e9cSLionel Sambuc 
3392395e9cSLionel Sambuc static	void	 pline(int, int *, int *, int);
3492395e9cSLionel Sambuc static	void	 pman(const struct man_node *, int *, int *, int);
3592395e9cSLionel Sambuc static	void	 pmandoc(struct mparse *, int, const char *, int);
3692395e9cSLionel Sambuc static	void	 pmdoc(const struct mdoc_node *, int *, int *, int);
3792395e9cSLionel Sambuc static	void	 pstring(const char *, int, int *, int);
3892395e9cSLionel Sambuc static	void	 usage(void);
3992395e9cSLionel Sambuc 
4092395e9cSLionel Sambuc static	const char	 *progname;
4192395e9cSLionel Sambuc 
4292395e9cSLionel Sambuc int
main(int argc,char * argv[])4392395e9cSLionel Sambuc main(int argc, char *argv[])
4492395e9cSLionel Sambuc {
4592395e9cSLionel Sambuc 	struct mparse	*mp;
4692395e9cSLionel Sambuc 	int		 ch, i, list;
4792395e9cSLionel Sambuc 	extern int	 optind;
4892395e9cSLionel Sambuc 
4992395e9cSLionel Sambuc 	progname = strrchr(argv[0], '/');
5092395e9cSLionel Sambuc 	if (progname == NULL)
5192395e9cSLionel Sambuc 		progname = argv[0];
5292395e9cSLionel Sambuc 	else
5392395e9cSLionel Sambuc 		++progname;
5492395e9cSLionel Sambuc 
5592395e9cSLionel Sambuc 	mp = NULL;
5692395e9cSLionel Sambuc 	list = 0;
5792395e9cSLionel Sambuc 
5892395e9cSLionel Sambuc 	while (-1 != (ch = getopt(argc, argv, "ikm:pw")))
5992395e9cSLionel Sambuc 		switch (ch) {
6092395e9cSLionel Sambuc 		case ('i'):
6192395e9cSLionel Sambuc 			/* FALLTHROUGH */
6292395e9cSLionel Sambuc 		case ('k'):
6392395e9cSLionel Sambuc 			/* FALLTHROUGH */
6492395e9cSLionel Sambuc 		case ('m'):
6592395e9cSLionel Sambuc 			/* FALLTHROUGH */
6692395e9cSLionel Sambuc 		case ('p'):
6792395e9cSLionel Sambuc 			break;
6892395e9cSLionel Sambuc 		case ('w'):
6992395e9cSLionel Sambuc 			list = 1;
7092395e9cSLionel Sambuc 			break;
7192395e9cSLionel Sambuc 		default:
7292395e9cSLionel Sambuc 			usage();
7392395e9cSLionel Sambuc 			return((int)MANDOCLEVEL_BADARG);
7492395e9cSLionel Sambuc 		}
7592395e9cSLionel Sambuc 
7692395e9cSLionel Sambuc 	argc -= optind;
7792395e9cSLionel Sambuc 	argv += optind;
7892395e9cSLionel Sambuc 
79*0a6a1f1dSLionel Sambuc 	mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL, NULL);
8092395e9cSLionel Sambuc 	assert(mp);
8192395e9cSLionel Sambuc 
8292395e9cSLionel Sambuc 	if (0 == argc)
8392395e9cSLionel Sambuc 		pmandoc(mp, STDIN_FILENO, "<stdin>", list);
8492395e9cSLionel Sambuc 
8592395e9cSLionel Sambuc 	for (i = 0; i < argc; i++) {
8692395e9cSLionel Sambuc 		mparse_reset(mp);
8792395e9cSLionel Sambuc 		pmandoc(mp, -1, argv[i], list);
8892395e9cSLionel Sambuc 	}
8992395e9cSLionel Sambuc 
9092395e9cSLionel Sambuc 	mparse_free(mp);
9192395e9cSLionel Sambuc 	return((int)MANDOCLEVEL_OK);
9292395e9cSLionel Sambuc }
9392395e9cSLionel Sambuc 
9492395e9cSLionel Sambuc static void
usage(void)9592395e9cSLionel Sambuc usage(void)
9692395e9cSLionel Sambuc {
9792395e9cSLionel Sambuc 
9892395e9cSLionel Sambuc 	fprintf(stderr, "usage: %s [-w] [files...]\n", progname);
9992395e9cSLionel Sambuc }
10092395e9cSLionel Sambuc 
10192395e9cSLionel Sambuc static void
pmandoc(struct mparse * mp,int fd,const char * fn,int list)10292395e9cSLionel Sambuc pmandoc(struct mparse *mp, int fd, const char *fn, int list)
10392395e9cSLionel Sambuc {
10492395e9cSLionel Sambuc 	struct mdoc	*mdoc;
10592395e9cSLionel Sambuc 	struct man	*man;
10692395e9cSLionel Sambuc 	int		 line, col;
10792395e9cSLionel Sambuc 
10892395e9cSLionel Sambuc 	if (mparse_readfd(mp, fd, fn) >= MANDOCLEVEL_FATAL) {
10992395e9cSLionel Sambuc 		fprintf(stderr, "%s: Parse failure\n", fn);
11092395e9cSLionel Sambuc 		return;
11192395e9cSLionel Sambuc 	}
11292395e9cSLionel Sambuc 
11392395e9cSLionel Sambuc 	mparse_result(mp, &mdoc, &man);
11492395e9cSLionel Sambuc 	line = 1;
11592395e9cSLionel Sambuc 	col = 0;
11692395e9cSLionel Sambuc 
11792395e9cSLionel Sambuc 	if (mdoc)
11892395e9cSLionel Sambuc 		pmdoc(mdoc_node(mdoc), &line, &col, list);
11992395e9cSLionel Sambuc 	else if (man)
12092395e9cSLionel Sambuc 		pman(man_node(man), &line, &col, list);
12192395e9cSLionel Sambuc 	else
12292395e9cSLionel Sambuc 		return;
12392395e9cSLionel Sambuc 
12492395e9cSLionel Sambuc 	if ( ! list)
12592395e9cSLionel Sambuc 		putchar('\n');
12692395e9cSLionel Sambuc }
12792395e9cSLionel Sambuc 
12892395e9cSLionel Sambuc /*
12992395e9cSLionel Sambuc  * Strip the escapes out of a string, emitting the results.
13092395e9cSLionel Sambuc  */
13192395e9cSLionel Sambuc static void
pstring(const char * p,int col,int * colp,int list)13292395e9cSLionel Sambuc pstring(const char *p, int col, int *colp, int list)
13392395e9cSLionel Sambuc {
13492395e9cSLionel Sambuc 	enum mandoc_esc	 esc;
13592395e9cSLionel Sambuc 	const char	*start, *end;
13692395e9cSLionel Sambuc 	int		 emit;
13792395e9cSLionel Sambuc 
13892395e9cSLionel Sambuc 	/*
13992395e9cSLionel Sambuc 	 * Print as many column spaces til we achieve parity with the
14092395e9cSLionel Sambuc 	 * input document.
14192395e9cSLionel Sambuc 	 */
14292395e9cSLionel Sambuc 
14392395e9cSLionel Sambuc again:
14492395e9cSLionel Sambuc 	if (list && '\0' != *p) {
14592395e9cSLionel Sambuc 		while (isspace((unsigned char)*p))
14692395e9cSLionel Sambuc 			p++;
14792395e9cSLionel Sambuc 
14892395e9cSLionel Sambuc 		while ('\'' == *p || '(' == *p || '"' == *p)
14992395e9cSLionel Sambuc 			p++;
15092395e9cSLionel Sambuc 
15192395e9cSLionel Sambuc 		emit = isalpha((unsigned char)p[0]) &&
15292395e9cSLionel Sambuc 			isalpha((unsigned char)p[1]);
15392395e9cSLionel Sambuc 
15492395e9cSLionel Sambuc 		for (start = p; '\0' != *p; p++)
15592395e9cSLionel Sambuc 			if ('\\' == *p) {
15692395e9cSLionel Sambuc 				p++;
15792395e9cSLionel Sambuc 				esc = mandoc_escape(&p, NULL, NULL);
15892395e9cSLionel Sambuc 				if (ESCAPE_ERROR == esc)
15992395e9cSLionel Sambuc 					return;
16092395e9cSLionel Sambuc 				emit = 0;
16192395e9cSLionel Sambuc 			} else if (isspace((unsigned char)*p))
16292395e9cSLionel Sambuc 				break;
16392395e9cSLionel Sambuc 
16492395e9cSLionel Sambuc 		end = p - 1;
16592395e9cSLionel Sambuc 
16692395e9cSLionel Sambuc 		while (end > start)
16792395e9cSLionel Sambuc 			if ('.' == *end || ',' == *end ||
16892395e9cSLionel Sambuc 					'\'' == *end || '"' == *end ||
16992395e9cSLionel Sambuc 					')' == *end || '!' == *end ||
17092395e9cSLionel Sambuc 					'?' == *end || ':' == *end ||
17192395e9cSLionel Sambuc 					';' == *end)
17292395e9cSLionel Sambuc 				end--;
17392395e9cSLionel Sambuc 			else
17492395e9cSLionel Sambuc 				break;
17592395e9cSLionel Sambuc 
17692395e9cSLionel Sambuc 		if (emit && end - start >= 1) {
17792395e9cSLionel Sambuc 			for ( ; start <= end; start++)
17892395e9cSLionel Sambuc 				if (ASCII_HYPH == *start)
17992395e9cSLionel Sambuc 					putchar('-');
18092395e9cSLionel Sambuc 				else
18192395e9cSLionel Sambuc 					putchar((unsigned char)*start);
18292395e9cSLionel Sambuc 			putchar('\n');
18392395e9cSLionel Sambuc 		}
18492395e9cSLionel Sambuc 
18592395e9cSLionel Sambuc 		if (isspace((unsigned char)*p))
18692395e9cSLionel Sambuc 			goto again;
18792395e9cSLionel Sambuc 
18892395e9cSLionel Sambuc 		return;
18992395e9cSLionel Sambuc 	}
19092395e9cSLionel Sambuc 
19192395e9cSLionel Sambuc 	while (*colp < col) {
19292395e9cSLionel Sambuc 		putchar(' ');
19392395e9cSLionel Sambuc 		(*colp)++;
19492395e9cSLionel Sambuc 	}
19592395e9cSLionel Sambuc 
19692395e9cSLionel Sambuc 	/*
19792395e9cSLionel Sambuc 	 * Print the input word, skipping any special characters.
19892395e9cSLionel Sambuc 	 */
19992395e9cSLionel Sambuc 	while ('\0' != *p)
20092395e9cSLionel Sambuc 		if ('\\' == *p) {
20192395e9cSLionel Sambuc 			p++;
20292395e9cSLionel Sambuc 			esc = mandoc_escape(&p, NULL, NULL);
20392395e9cSLionel Sambuc 			if (ESCAPE_ERROR == esc)
20492395e9cSLionel Sambuc 				break;
20592395e9cSLionel Sambuc 		} else {
20692395e9cSLionel Sambuc 			putchar((unsigned char )*p++);
20792395e9cSLionel Sambuc 			(*colp)++;
20892395e9cSLionel Sambuc 		}
20992395e9cSLionel Sambuc }
21092395e9cSLionel Sambuc 
21192395e9cSLionel Sambuc static void
pline(int line,int * linep,int * col,int list)21292395e9cSLionel Sambuc pline(int line, int *linep, int *col, int list)
21392395e9cSLionel Sambuc {
21492395e9cSLionel Sambuc 
21592395e9cSLionel Sambuc 	if (list)
21692395e9cSLionel Sambuc 		return;
21792395e9cSLionel Sambuc 
21892395e9cSLionel Sambuc 	/*
21992395e9cSLionel Sambuc 	 * Print out as many lines as needed to reach parity with the
22092395e9cSLionel Sambuc 	 * original input.
22192395e9cSLionel Sambuc 	 */
22292395e9cSLionel Sambuc 
22392395e9cSLionel Sambuc 	while (*linep < line) {
22492395e9cSLionel Sambuc 		putchar('\n');
22592395e9cSLionel Sambuc 		(*linep)++;
22692395e9cSLionel Sambuc 	}
22792395e9cSLionel Sambuc 
22892395e9cSLionel Sambuc 	*col = 0;
22992395e9cSLionel Sambuc }
23092395e9cSLionel Sambuc 
23192395e9cSLionel Sambuc static void
pmdoc(const struct mdoc_node * p,int * line,int * col,int list)23292395e9cSLionel Sambuc pmdoc(const struct mdoc_node *p, int *line, int *col, int list)
23392395e9cSLionel Sambuc {
23492395e9cSLionel Sambuc 
23592395e9cSLionel Sambuc 	for ( ; p; p = p->next) {
23692395e9cSLionel Sambuc 		if (MDOC_LINE & p->flags)
23792395e9cSLionel Sambuc 			pline(p->line, line, col, list);
23892395e9cSLionel Sambuc 		if (MDOC_TEXT == p->type)
23992395e9cSLionel Sambuc 			pstring(p->string, p->pos, col, list);
24092395e9cSLionel Sambuc 		if (p->child)
24192395e9cSLionel Sambuc 			pmdoc(p->child, line, col, list);
24292395e9cSLionel Sambuc 	}
24392395e9cSLionel Sambuc }
24492395e9cSLionel Sambuc 
24592395e9cSLionel Sambuc static void
pman(const struct man_node * p,int * line,int * col,int list)24692395e9cSLionel Sambuc pman(const struct man_node *p, int *line, int *col, int list)
24792395e9cSLionel Sambuc {
24892395e9cSLionel Sambuc 
24992395e9cSLionel Sambuc 	for ( ; p; p = p->next) {
25092395e9cSLionel Sambuc 		if (MAN_LINE & p->flags)
25192395e9cSLionel Sambuc 			pline(p->line, line, col, list);
25292395e9cSLionel Sambuc 		if (MAN_TEXT == p->type)
25392395e9cSLionel Sambuc 			pstring(p->string, p->pos, col, list);
25492395e9cSLionel Sambuc 		if (p->child)
25592395e9cSLionel Sambuc 			pman(p->child, line, col, list);
25692395e9cSLionel Sambuc 	}
25792395e9cSLionel Sambuc }
258