X-Git-Url: https://git.cameronkatri.com/mandoc.git/blobdiff_plain/80ea5fba77843cbf9564d787b2c04144de97fed3..861b32f0c650c391f020df039714a7370b28c40f:/demandoc.c

diff --git a/demandoc.c b/demandoc.c
index d1aa9496..57d0cc5f 100644
--- a/demandoc.c
+++ b/demandoc.c
@@ -1,4 +1,4 @@
-/*	$Id: demandoc.c,v 1.2 2011/09/01 10:47:47 kristaps Exp $ */
+/*	$Id: demandoc.c,v 1.33 2019/03/03 11:01:15 schwarze Exp $ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -14,26 +14,28 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-#ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
+
+#include <sys/types.h>
 
 #include <assert.h>
-#include <getopt.h>
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
+#include "mandoc.h"
+#include "roff.h"
 #include "man.h"
 #include "mdoc.h"
-#include "mandoc.h"
+#include "mandoc_parse.h"
 
-static	void	 pline(int, int *, int *);
-static	void	 pman(const struct man_node *, int *, int *);
-static	void	 pmandoc(struct mparse *, int, const char *);
-static	void	 pmdoc(const struct mdoc_node *, int *, int *);
-static	void	 pstring(const char *, int, int *);
+static	void	 pline(int, int *, int *, int);
+static	void	 pman(const struct roff_node *, int *, int *, int);
+static	void	 pmandoc(struct mparse *, int, const char *, int);
+static	void	 pmdoc(const struct roff_node *, int *, int *, int);
+static	void	 pstring(const char *, int, int *, int);
 static	void	 usage(void);
 
 static	const char	 *progname;
@@ -42,140 +44,217 @@ int
 main(int argc, char *argv[])
 {
 	struct mparse	*mp;
-	int		 ch, i;
+	int		 ch, fd, i, list;
 	extern int	 optind;
-	extern char	*optarg;
 
-	progname = strrchr(argv[0], '/');
-	if (progname == NULL)
+	if (argc < 1)
+		progname = "demandoc";
+	else if ((progname = strrchr(argv[0], '/')) == NULL)
 		progname = argv[0];
 	else
 		++progname;
 
 	mp = NULL;
+	list = 0;
 
-	while (-1 != (ch = getopt(argc, argv, "")))
+	while (-1 != (ch = getopt(argc, argv, "ikm:pw")))
 		switch (ch) {
+		case ('i'):
+			/* FALLTHROUGH */
+		case ('k'):
+			/* FALLTHROUGH */
+		case ('m'):
+			/* FALLTHROUGH */
+		case ('p'):
+			break;
+		case ('w'):
+			list = 1;
+			break;
 		default:
 			usage();
-			return((int)MANDOCLEVEL_BADARG);
+			return (int)MANDOCLEVEL_BADARG;
 		}
 
 	argc -= optind;
 	argv += optind;
 
-	mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL);
+	mchars_alloc();
+	mp = mparse_alloc(MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1 |
+	    MPARSE_VALIDATE, MANDOC_OS_OTHER, NULL);
 	assert(mp);
 
-	if (0 == argc)
-		pmandoc(mp, STDIN_FILENO, "<stdin>");
+	if (argc < 1)
+		pmandoc(mp, STDIN_FILENO, "<stdin>", list);
 
 	for (i = 0; i < argc; i++) {
 		mparse_reset(mp);
-		pmandoc(mp, -1, argv[i]);
+		if ((fd = mparse_open(mp, argv[i])) == -1) {
+			perror(argv[i]);
+			continue;
+		}
+		pmandoc(mp, fd, argv[i], list);
 	}
 
 	mparse_free(mp);
-	return(MANDOCLEVEL_OK);
+	mchars_free();
+	return (int)MANDOCLEVEL_OK;
 }
 
 static void
 usage(void)
 {
 
-	fprintf(stderr, "usage: %s [files...]\n", progname);
+	fprintf(stderr, "usage: %s [-w] [files...]\n", progname);
 }
 
 static void
-pmandoc(struct mparse *mp, int fd, const char *fn)
+pmandoc(struct mparse *mp, int fd, const char *fn, int list)
 {
-	struct mdoc	*mdoc;
-	struct man	*man;
+	struct roff_meta	*meta;
 	int		 line, col;
 
-	if (mparse_readfd(mp, fd, fn) >= MANDOCLEVEL_FATAL) {
-		fprintf(stderr, "%s: Parse failure\n", fn);
-		return;
-	}
-
-	mparse_result(mp, &mdoc, &man);
+	mparse_readfd(mp, fd, fn);
+	close(fd);
+	meta = mparse_result(mp);
 	line = 1;
 	col = 0;
 
-	if (mdoc) 
-		pmdoc(mdoc_node(mdoc), &line, &col);
-	else if (man)
-		pman(man_node(man), &line, &col);
+	if (meta->macroset == MACROSET_MDOC)
+		pmdoc(meta->first->child, &line, &col, list);
 	else
-		return;
+		pman(meta->first->child, &line, &col, list);
 
-	putchar('\n');
+	if ( ! list)
+		putchar('\n');
 }
 
 /*
  * Strip the escapes out of a string, emitting the results.
  */
 static void
-pstring(const char *p, int col, int *colp)
+pstring(const char *p, int col, int *colp, int list)
 {
 	enum mandoc_esc	 esc;
+	const char	*start, *end;
+	int		 emit;
+
+	/*
+	 * Print as many column spaces til we achieve parity with the
+	 * input document.
+	 */
+
+again:
+	if (list && '\0' != *p) {
+		while (isspace((unsigned char)*p))
+			p++;
+
+		while ('\'' == *p || '(' == *p || '"' == *p)
+			p++;
+
+		emit = isalpha((unsigned char)p[0]) &&
+			isalpha((unsigned char)p[1]);
+
+		for (start = p; '\0' != *p; p++)
+			if ('\\' == *p) {
+				p++;
+				esc = mandoc_escape(&p, NULL, NULL);
+				if (ESCAPE_ERROR == esc)
+					return;
+				emit = 0;
+			} else if (isspace((unsigned char)*p))
+				break;
+
+		end = p - 1;
+
+		while (end > start)
+			if ('.' == *end || ',' == *end ||
+					'\'' == *end || '"' == *end ||
+					')' == *end || '!' == *end ||
+					'?' == *end || ':' == *end ||
+					';' == *end)
+				end--;
+			else
+				break;
+
+		if (emit && end - start >= 1) {
+			for ( ; start <= end; start++)
+				if (ASCII_HYPH == *start)
+					putchar('-');
+				else
+					putchar((unsigned char)*start);
+			putchar('\n');
+		}
+
+		if (isspace((unsigned char)*p))
+			goto again;
+
+		return;
+	}
 
 	while (*colp < col) {
 		putchar(' ');
 		(*colp)++;
 	}
 
-	while ('\0' != *p) {
+	/*
+	 * Print the input word, skipping any special characters.
+	 */
+	while ('\0' != *p)
 		if ('\\' == *p) {
 			p++;
 			esc = mandoc_escape(&p, NULL, NULL);
 			if (ESCAPE_ERROR == esc)
-				return;
+				break;
 		} else {
-			putchar(*p++);
+			putchar((unsigned char )*p++);
 			(*colp)++;
 		}
-	}
 }
 
-/*
- * Emit lines until we're in sync with our input.
- */
 static void
-pline(int line, int *linep, int *col)
+pline(int line, int *linep, int *col, int list)
 {
 
+	if (list)
+		return;
+
+	/*
+	 * Print out as many lines as needed to reach parity with the
+	 * original input.
+	 */
+
 	while (*linep < line) {
 		putchar('\n');
 		(*linep)++;
 	}
+
 	*col = 0;
 }
 
 static void
-pmdoc(const struct mdoc_node *p, int *line, int *col)
+pmdoc(const struct roff_node *p, int *line, int *col, int list)
 {
 
 	for ( ; p; p = p->next) {
-		if (MDOC_LINE & p->flags)
-			pline(p->line, line, col);
-		if (MDOC_TEXT == p->type)
-			pstring(p->string, p->pos, col);
-		if (p->child) 
-			pmdoc(p->child, line, col);
+		if (NODE_LINE & p->flags)
+			pline(p->line, line, col, list);
+		if (ROFFT_TEXT == p->type)
+			pstring(p->string, p->pos, col, list);
+		if (p->child)
+			pmdoc(p->child, line, col, list);
 	}
 }
 
 static void
-pman(const struct man_node *p, int *line, int *col)
+pman(const struct roff_node *p, int *line, int *col, int list)
 {
 
 	for ( ; p; p = p->next) {
-		if (MAN_LINE & p->flags)
-			pline(p->line, line, col);
-		if (MAN_TEXT == p->type)
-			pstring(p->string, p->pos, col);
-		if (p->child) 
-			pman(p->child, line, col);
+		if (NODE_LINE & p->flags)
+			pline(p->line, line, col, list);
+		if (ROFFT_TEXT == p->type)
+			pstring(p->string, p->pos, col, list);
+		if (p->child)
+			pman(p->child, line, col, list);
 	}
 }