source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* docbook2mdoc: As usual, whitespace handling is the heart and soul of
@ 2019-03-24 16:46 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2019-03-24 16:46 UTC (permalink / raw)
  To: source

Log Message:
-----------
As usual, whitespace handling is the heart and soul of roff(7) 
processing, so overhaul it.  Keep output line state and provide a
set of output functions to open and close macro lines and to add
arguments to them.  Mostly avoid asserting output line state because
elements can occur in any order and we should just deal with whatever
comes in.

This diff shortens the code by 60 lines, improves robustness and 
readability, and fixes some bugs.

Modified Files:
--------------
    docbook2mdoc:
        docbook2mdoc.c

Revision Data
-------------
Index: docbook2mdoc.c
===================================================================
RCS file: /home/cvs/mdocml/docbook2mdoc/docbook2mdoc.c,v
retrieving revision 1.68
retrieving revision 1.69
diff -Ldocbook2mdoc.c -Ldocbook2mdoc.c -u -p -r1.68 -r1.69
--- docbook2mdoc.c
+++ docbook2mdoc.c
@@ -29,6 +29,12 @@
 
 #include "extern.h"
 
+enum	linestate {
+	LINE_NEW = 0,
+	LINE_TEXT,
+	LINE_MACRO
+};
+
 /*
  * Global parse state.
  * Keep this as simple and small as possible.
@@ -46,7 +52,7 @@ struct	parse {
 	size_t		 bsz; /* current length of b */
 	size_t		 mbsz; /* max bsz allocation */
 	int		 level; /* header level, starting at 1 */
-	int		 newln; /* output: are we on a fresh line */
+	enum linestate	 linestate;
 };
 
 struct	node {
@@ -587,34 +593,62 @@ pnode_findfirst(struct pnode *pn, enum n
 	return res;
 }
 
-#define MACROLINE_NORM	0
-#define MACROLINE_UPPER	1
-#define	MACROLINE_NOWS 2
-/*
- * Recursively print text presumably on a macro line.
- * Convert all whitespace to regular spaces.
- */
 static void
-pnode_printmacrolinetext(struct parse *p, struct pnode *pn, int fl)
+macro_open(struct parse *p, const char *name)
 {
-	char		*cp;
-
-	if (p->newln == 0 && (fl & MACROLINE_NOWS) == 0)
+	switch (p->linestate) {
+	case LINE_TEXT:
+		putchar('\n');
+		/* FALLTHROUGH */
+	case LINE_NEW:
+		putchar('.');
+		p->linestate = LINE_MACRO;
+		break;
+	case LINE_MACRO:
 		putchar(' ');
+		break;
+	}
+	fputs(name, stdout);
+}
 
-	bufclear(p);
-	bufappend_r(p, pn);
+static void
+macro_close(struct parse *p)
+{
+	assert(p->linestate == LINE_MACRO);
+	putchar('\n');
+	p->linestate = LINE_NEW;
+}
+
+static void
+macro_line(struct parse *p, const char *name)
+{
+	macro_open(p, name);
+	macro_close(p);
+}
+
+#define	MACROLINE_UPPER	1
+#define	MACROLINE_NOWS	2
+/*
+ * Print an argument string on a macro line, collapsing whitespace.
+ */
+static void
+macro_addarg(struct parse *p, const char *arg, int fl)
+{
+	const char	*cp;
+	int		 wantspace;
 
-	/* Convert all space to spaces. */
-	for (cp = p->b; *cp != '\0'; cp++)
-		if (isspace((unsigned char)*cp))
-			*cp = ' ';
-
-	for (cp = p->b; isspace((unsigned char)*cp); cp++)
-		/* Spin past whitespace (XXX: necessary?) */ ;
-	for ( ; *cp != '\0'; cp++) {
+	assert(p->linestate == LINE_MACRO);
+	wantspace = !(fl & MACROLINE_NOWS);
+	for (cp = arg; *cp != '\0'; cp++) {
+		if (isspace((unsigned char)*cp)) {
+			wantspace = 1;
+			continue;
+		} else if (wantspace) {
+			putchar(' ');
+			wantspace = 0;
+		}
 		/* Escape us if we look like a macro. */
-		if ((cp == p->b || cp[-1] == ' ') &&
+		if ((cp == arg || cp[-1] == ' ') &&
 		    isupper((unsigned char)cp[0]) &&
 		    islower((unsigned char)cp[1]) &&
 		    (cp[2] == '\0' || cp[2] == ' ' ||
@@ -625,75 +659,47 @@ pnode_printmacrolinetext(struct parse *p
 			putchar(toupper((unsigned char)*cp));
 		else
 			putchar(*cp);
-		/* If we're a character escape, escape us. */
 		if (*cp == '\\')
 			putchar('e');
 	}
 }
 
 static void
-pnode_printmacrolinepart(struct parse *p, struct pnode *pn)
+macro_argline(struct parse *p, const char *name, const char *arg)
 {
-
-	pnode_printmacrolinetext(p, pn, 0);
+	macro_open(p, name);
+	macro_addarg(p, arg, 0);
+	macro_close(p);
 }
 
 /*
- * Just pnode_printmacrolinepart() but with a newline.
- * If no text, just the newline.
+ * Recurse nodes to print arguments on a macro line.
  */
 static void
-pnode_printmacroline(struct parse *p, struct pnode *pn)
-{
-	assert(p->newln == 0);
-	pnode_printmacrolinetext(p, pn, 0);
-	putchar('\n');
-	p->newln = 1;
-}
-
-static void
-pnode_printmopen(struct parse *p)
+macro_addnode(struct parse *p, struct pnode *pn, int fl)
 {
-	if (p->newln) {
-		putchar('.');
-		p->newln = 0;
-	} else
-		putchar(' ');
+	bufclear(p);
+	bufappend_r(p, pn);
+	macro_addarg(p, p->b, fl);
 }
 
 static void
-pnode_printmclose(struct parse *p, int sv)
+macro_nodeline(struct parse *p, const char *name, struct pnode *pn)
 {
-
-	if (sv && ! p->newln) {
-		putchar('\n');
-		p->newln = 1;
-	}
+	macro_open(p, name);
+	macro_addnode(p, pn, 0);
+	macro_close(p);
 }
 
 /*
- * Like pnode_printmclose() except we look to the next node, and, if
- * found, see if it starts with punctuation.
- * If it does, then we print that punctuation before the newline.
+ * If the next node is a text node starting with closing punctuation,
+ * emit the closing punctuation as a trailing macro argument.
  */
 static void
-pnode_printmclosepunct(struct parse *p, struct pnode *pn, int sv)
+macro_closepunct(struct parse *p, struct pnode *pn)
 {
-	/* We wouldn't have done anything anyway. */
-	if ( ! (sv && ! p->newln))
-		return;
-
-	/* No next node or it's not text. */
-	if ((pn = TAILQ_NEXT(pn, child)) == NULL) {
-		pnode_printmclose(p, sv);
-		return;
-	} else if (pn->node != NODE_TEXT) {
-		pnode_printmclose(p, sv);
-		return;
-	}
-
-	/* Only do this for the comma/period. */
-	if (pn->bsz > 0 &&
+	if ((pn = TAILQ_NEXT(pn, child)) != NULL &&
+	    pn->node == NODE_TEXT && pn->bsz > 0 &&
 	    (pn->b[0] == ',' || pn->b[0] == '.') &&
 	    (pn->bsz == 1 || isspace((unsigned char)pn->b[1]))) {
 		putchar(' ');
@@ -701,9 +707,7 @@ pnode_printmclosepunct(struct parse *p, 
 		pn->b++;
 		pn->bsz--;
 	}
-
-	putchar('\n');
-	p->newln = 1;
+	macro_close(p);
 }
 
 static void
@@ -711,7 +715,6 @@ pnode_printpara(struct parse *p, struct 
 {
 	struct pnode	*pp;
 
-	assert(p->newln);
 	if ((pp = TAILQ_PREV(pn, pnodeq, child)) == NULL &&
 	    (pp = pn->parent) == NULL)
 		return;
@@ -728,7 +731,7 @@ pnode_printpara(struct parse *p, struct 
 	default:
 		break;
 	}
-	puts(".Pp");
+	macro_line(p, "Pp");
 }
 
 /*
@@ -803,24 +806,23 @@ pnode_printrefsect(struct parse *p, stru
 
 	switch (level) {
 	case 1:
-		fputs(".Sh", stdout);
+		macro_open(p, "Sh");
 		break;
 	case 2:
-		fputs(".Ss", stdout);
+		macro_open(p, "Ss");
 		break;
 	default:
 		pnode_printpara(p, pn);
-		fputs(".Sy", stdout);
+		macro_open(p, "Sy");
 		break;
 	}
 
 	if (pp != NULL) {
-		p->newln = 0;
-		pnode_printmacrolinetext(p, pp, flags);
-		pnode_printmclose(p, 1);
+		macro_addnode(p, pp, flags);
 		pnode_unlink(pp);
 	} else
-		printf(" %s\n", title);
+		macro_addarg(p, title, 0);
+	macro_close(p);
 }
 
 /*
@@ -832,22 +834,22 @@ pnode_printciterefentry(struct parse *p,
 	struct pnode	*pp, *title, *manvol;
 
 	title = manvol = NULL;
-	TAILQ_FOREACH(pp, &pn->childq, child)
+	TAILQ_FOREACH(pp, &pn->childq, child) {
 		if (pp->node == NODE_MANVOLNUM)
 			manvol = pp;
 		else if (pp->node == NODE_REFENTRYTITLE)
 			title = pp;
-
-	if (title != NULL)
-		pnode_printmacrolinepart(p, title);
+	}
+	macro_open(p, "Xr");
+	if (title == NULL)
+		macro_addarg(p, "unknown", 0);
 	else
-		fputs(" unknown ", stdout);
-
-	if (manvol == NULL) {
-		puts(" 1");
-		p->newln = 1;
-	} else
-		pnode_printmacrolinepart(p, manvol);
+		macro_addnode(p, title, 0);
+	if (manvol == NULL)
+		macro_addarg(p, "1", 0);
+	else
+		macro_addnode(p, manvol, 0);
+	macro_close(p);
 }
 
 static void
@@ -856,26 +858,22 @@ pnode_printrefmeta(struct parse *p, stru
 	struct pnode	*pp, *title, *manvol;
 
 	title = manvol = NULL;
-	assert(p->newln);
-	TAILQ_FOREACH(pp, &pn->childq, child)
+	TAILQ_FOREACH(pp, &pn->childq, child) {
 		if (pp->node == NODE_MANVOLNUM)
 			manvol = pp;
 		else if (pp->node == NODE_REFENTRYTITLE)
 			title = pp;
-
-	fputs(".Dt", stdout);
-	p->newln = 0;
-
-	if (title != NULL)
-		pnode_printmacrolinetext(p, title, MACROLINE_UPPER);
+	}
+	macro_open(p, "Dt");
+	if (title == NULL)
+		macro_addarg(p, "UNKNOWN", 0);
 	else
-		fputs(" UNKNOWN ", stdout);
-
-	if (manvol == NULL) {
-		puts(" 1");
-		p->newln = 1;
-	} else
-		pnode_printmacroline(p, manvol);
+		macro_addnode(p, title, MACROLINE_UPPER);
+	if (manvol == NULL)
+		macro_addarg(p, "1", 0);
+	else
+		macro_addnode(p, manvol, 0);
+	macro_close(p);
 }
 
 static void
@@ -883,55 +881,47 @@ pnode_printfuncdef(struct parse *p, stru
 {
 	struct pnode	*pp, *ftype, *func;
 
-	assert(p->newln);
 	ftype = func = NULL;
-	TAILQ_FOREACH(pp, &pn->childq, child)
+	TAILQ_FOREACH(pp, &pn->childq, child) {
 		if (pp->node == NODE_TEXT)
 			ftype = pp;
 		else if (pp->node == NODE_FUNCTION)
 			func = pp;
-
-	if (ftype != NULL) {
-		fputs(".Ft", stdout);
-		p->newln = 0;
-		pnode_printmacroline(p, ftype);
-	}
-
-	if (func != NULL) {
-		fputs(".Fo", stdout);
-		p->newln = 0;
-		pnode_printmacroline(p, func);
-	} else {
-		puts(".Fo UNKNOWN");
-		p->newln = 1;
 	}
+	if (ftype != NULL)
+		macro_nodeline(p, "Ft", ftype);
+	macro_open(p, "Fo");
+	if (func == NULL)
+		macro_addarg(p, "UNKNOWN", 0);
+	else
+		macro_addnode(p, func, 0);
+	macro_close(p);
 }
 
 static void
 pnode_printparamdef(struct parse *p, struct pnode *pn)
 {
 	struct pnode	*pp, *ptype, *param;
+	int		 flags;
 
-	assert(p->newln);
 	ptype = param = NULL;
-	TAILQ_FOREACH(pp, &pn->childq, child)
+	TAILQ_FOREACH(pp, &pn->childq, child) {
 		if (pp->node == NODE_TEXT)
 			ptype = pp;
 		else if (pp->node == NODE_PARAMETER)
 			param = pp;
-
-	fputs(".Fa \"", stdout);
-	p->newln = 0;
+	}
+	macro_open(p, "Fa \"");
+	flags = MACROLINE_NOWS;
 	if (ptype != NULL) {
-		pnode_printmacrolinetext(p, ptype, MACROLINE_NOWS);
-		putchar(' ');
+		macro_addnode(p, ptype, flags);
+		flags = 0;
 	}
-
 	if (param != NULL)
-		pnode_printmacrolinepart(p, param);
-
-	puts("\"");
-	p->newln = 1;
+		macro_addnode(p, param, flags);
+	flags = MACROLINE_NOWS;
+	macro_addarg(p, "\"", flags);
+	macro_close(p);
 }
 
 /*
@@ -995,7 +985,6 @@ pnode_printfuncprototype(struct parse *p
 {
 	struct pnode	*pp, *fdef;
 
-	assert(p->newln);
 	TAILQ_FOREACH(fdef, &pn->childq, child)
 		if (fdef->node == NODE_FUNCDEF)
 			break;
@@ -1003,14 +992,13 @@ pnode_printfuncprototype(struct parse *p
 	if (fdef != NULL)
 		pnode_printfuncdef(p, fdef);
 	else
-		puts(".Fo UNKNOWN");
+		macro_line(p, "Fo UNKNOWN");
 
 	TAILQ_FOREACH(pp, &pn->childq, child)
 		if (pp->node == NODE_PARAMDEF)
 			pnode_printparamdef(p, pp);
 
-	puts(".Fc");
-	p->newln = 1;
+	macro_line(p, "Fc");
 }
 
 /*
@@ -1029,26 +1017,22 @@ pnode_printarg(struct parse *p, struct p
 
 	isop = 1;
 	isrep = 0;
-	TAILQ_FOREACH(ap, &pn->attrq, child)
+	TAILQ_FOREACH(ap, &pn->attrq, child) {
 		if (ap->key == ATTRKEY_CHOICE &&
 		    (ap->val == ATTRVAL_PLAIN || ap->val == ATTRVAL_REQ))
 			isop = 0;
 		else if (ap->key == ATTRKEY_REP && ap->val == ATTRVAL_REPEAT)
 			isrep = 1;
-
-	if (isop) {
-		pnode_printmopen(p);
-		fputs("Op", stdout);
 	}
+	if (isop)
+		macro_open(p, "Op");
 
 	TAILQ_FOREACH(pp, &pn->childq, child) {
-		if (pp->node == NODE_TEXT) {
-			pnode_printmopen(p);
-			fputs("Ar", stdout);
-		}
+		if (pp->node == NODE_TEXT)
+			macro_open(p, "Ar");
 		pnode_print(p, pp);
 		if (isrep && pp->node == NODE_TEXT)
-			fputs("...", stdout);
+			macro_addarg(p, "...", 0);
 	}
 }
 
@@ -1072,12 +1056,11 @@ pnode_printgroup(struct parse *p, struct
 	 * This will prevent pnode_print() for putting us on a
 	 * subsequent line.
 	 */
-	sv = p->newln;
-	pnode_printmopen(p);
+	sv = p->linestate == LINE_NEW;
 	if (isop)
-		fputs("Op", stdout);
+		macro_open(p, "Op");
 	else if (sv)
-		fputs("No", stdout);
+		macro_open(p, "No");
 
 	/*
 	 * Keep on printing text separated by the vertical bar as long
@@ -1093,14 +1076,14 @@ pnode_printgroup(struct parse *p, struct
 		while (np != NULL) {
 			if (pp->node != np->node)
 				break;
-			fputs(" |", stdout);
-			pnode_printmacrolinepart(p, np);
+			macro_addarg(p, "|", 0);
+			macro_addnode(p, np, 0);
 			pp = np;
 			np = TAILQ_NEXT(np, child);
 		}
 	}
-
-	pnode_printmclose(p, sv);
+	if (sv)
+		macro_close(p);
 }
 
 static void
@@ -1111,19 +1094,23 @@ pnode_printprologue(struct parse *p, str
 	pp = p->root == NULL ? NULL :
 		pnode_findfirst(p->root, NODE_REFMETA);
 
-	puts(".Dd $Mdocdate" "$");
+	macro_line(p, "Dd $Mdocdate" "$");
 	if (pp != NULL) {
 		pnode_printrefmeta(p, pp);
 		pnode_unlink(pp);
-	} else
-		printf(".Dt %s 1\n",
-		    pnode_getattr_raw(p->root, ATTRKEY_ID, "UNKNOWN"));
-	puts(".Os");
+	} else {
+		macro_open(p, "Dt");
+		macro_addarg(p,
+		    pnode_getattr_raw(p->root, ATTRKEY_ID, "UNKNOWN"), 0);
+		macro_addarg(p, "1", 0);
+		macro_close(p);
+	}
+	macro_line(p, "Os");
 
 	if (p->flags & PARSE_EQN) {
-		puts(".EQ");
+		macro_line(p, "EQ");
 		puts("delim $$");
-		puts(".EN");
+		macro_line(p, "EN");
 	}
 }
 
@@ -1137,22 +1124,19 @@ pnode_printvarlistentry(struct parse *p,
 	struct pnode	*pp;
 	int		 first = 1;
 
-	assert(p->newln);
-	fputs(".It", stdout);
-	p->newln = 0;
-
+	macro_open(p, "It");
+	TAILQ_FOREACH(pp, &pn->childq, child) {
+		if (pp->node != NODE_TERM)
+			continue;
+		if ( ! first)
+			putchar(',');
+		pnode_print(p, pp);
+		first = 0;
+	}
+	macro_close(p);
 	TAILQ_FOREACH(pp, &pn->childq, child)
-		if (pp->node == NODE_TERM) {
-			if ( ! first)
-				putchar(',');
+		if (pp->node != NODE_TERM)
 			pnode_print(p, pp);
-			pnode_unlink(pp);
-			first = 0;
-		} else
-			break;
-
-	putchar('\n');
-	p->newln = 1;
 }
 
 static void
@@ -1160,16 +1144,12 @@ pnode_printrow(struct parse *p, struct p
 {
 	struct pnode	*pp;
 
-	puts(".Bl -dash -compact");
-
+	macro_line(p, "Bl -dash -compact");
 	TAILQ_FOREACH(pp, &pn->childq, child) {
-		assert(p->newln);
-		puts(".It");
+		macro_line(p, "It");
 		pnode_print(p, pp);
-		pnode_printmclose(p, 1);
 	}
-	assert(p->newln);
-	puts(".El");
+	macro_line(p, "El");
 }
 
 static void
@@ -1177,23 +1157,20 @@ pnode_printtable(struct parse *p, struct
 {
 	struct pnode	*pp;
 
-	assert(p->newln);
-	TAILQ_FOREACH(pp, &pn->childq, child)
+	TAILQ_FOREACH(pp, &pn->childq, child) {
 		if (pp->node == NODE_TITLE) {
 			pnode_printpara(p, pp);
 			pnode_print(p, pp);
 			pnode_unlink(pp);
 		}
-	assert(p->newln);
-	puts(".Bl -ohang");
+	}
+	macro_line(p, "Bl -ohang");
 	while ((pp = pnode_findfirst(pn, NODE_ROW)) != NULL) {
-		puts(".It Table Row");
+		macro_line(p, "It Table Row");
 		pnode_printrow(p, pp);
-		pnode_printmclose(p, 1);
 		pnode_unlink(pp);
 	}
-	assert(p->newln);
-	puts(".El");
+	macro_line(p, "El");
 }
 
 static void
@@ -1201,28 +1178,20 @@ pnode_printlist(struct parse *p, struct 
 {
 	struct pnode	*pp;
 
-	assert(p->newln);
-	TAILQ_FOREACH(pp, &pn->childq, child)
+	TAILQ_FOREACH(pp, &pn->childq, child) {
 		if (pp->node == NODE_TITLE) {
 			pnode_printpara(p, pp);
 			pnode_print(p, pp);
 			pnode_unlink(pp);
 		}
-	assert(p->newln);
-
-	if (pn->node == NODE_ORDEREDLIST)
-		puts(".Bl -enum");
-	else
-		puts(".Bl -bullet");
-
+	}
+	macro_argline(p, "Bl",
+	    pn->node == NODE_ORDEREDLIST ? "-enum" : "-bullet");
 	TAILQ_FOREACH(pp, &pn->childq, child) {
-		assert(p->newln);
-		puts(".It");
+		macro_line(p, "It");
 		pnode_print(p, pp);
-		pnode_printmclose(p, 1);
 	}
-	assert(p->newln);
-	puts(".El");
+	macro_line(p, "El");
 }
 
 static void
@@ -1230,27 +1199,21 @@ pnode_printvariablelist(struct parse *p,
 {
 	struct pnode	*pp;
 
-	assert(p->newln);
-	TAILQ_FOREACH(pp, &pn->childq, child)
+	TAILQ_FOREACH(pp, &pn->childq, child) {
 		if (pp->node == NODE_TITLE) {
 			pnode_printpara(p, pp);
 			pnode_print(p, pp);
 			pnode_unlink(pp);
 		}
-
-	assert(p->newln);
-	puts(".Bl -tag -width Ds");
-	TAILQ_FOREACH(pp, &pn->childq, child)
-		if (pp->node != NODE_VARLISTENTRY) {
-			assert(p->newln);
-			fputs(".It", stdout);
-			pnode_printmacroline(p, pp);
-		} else {
-			assert(p->newln);
+	}
+	macro_line(p, "Bl -tag -width Ds");
+	TAILQ_FOREACH(pp, &pn->childq, child) {
+		if (pp->node == NODE_VARLISTENTRY)
 			pnode_print(p, pp);
-		}
-	assert(p->newln);
-	puts(".El");
+		else
+			macro_nodeline(p, "It", pp);
+	}
+	macro_line(p, "El");
 }
 
 /*
@@ -1265,17 +1228,17 @@ pnode_print(struct parse *p, struct pnod
 	struct pnode	*pp;
 	const char	*ccp;
 	char		*cp;
-	int		 last, sv;
+	int		 last;
+	enum linestate	 sv;
 
 	if (pn == NULL)
 		return;
 
-	sv = p->newln;
+	sv = p->linestate;
 
 	switch (pn->node) {
 	case NODE_APPLICATION:
-		pnode_printmopen(p);
-		fputs("Nm", stdout);
+		macro_open(p, "Nm");
 		break;
 	case NODE_ANCHOR:
 		/* Don't print anything! */
@@ -1285,88 +1248,71 @@ pnode_print(struct parse *p, struct pnod
 		pnode_unlinksub(pn);
 		break;
 	case NODE_AUTHOR:
-		pnode_printmopen(p);
-		fputs("An", stdout);
+		macro_open(p, "An");
 		break;
 	case NODE_AUTHORGROUP:
-		assert(p->newln);
-		puts(".An -split");
+		macro_line(p, "An -split");
 		break;
 	case NODE_BOOKINFO:
-		assert(p->newln);
-		puts(".Sh NAME");
+		macro_line(p, "Sh NAME");
 		break;
 	case NODE_CITEREFENTRY:
-		pnode_printmopen(p);
-		fputs("Xr", stdout);
 		pnode_printciterefentry(p, pn);
 		pnode_unlinksub(pn);
 		break;
 	case NODE_CITETITLE:
-		pnode_printmopen(p);
-		fputs("%T", stdout);
+		macro_open(p, "%T");
 		break;
 	case NODE_CODE:
-		pnode_printmopen(p);
-		fputs("Li", stdout);
+		macro_open(p, "Li");
 		break;
 	case NODE_COMMAND:
-		pnode_printmopen(p);
-		fputs("Nm", stdout);
+		macro_open(p, "Nm");
 		break;
 	case NODE_CONSTANT:
-		pnode_printmopen(p);
-		fputs("Dv", stdout);
+		macro_open(p, "Dv");
 		break;
 	case NODE_EDITOR:
-		puts("editor: ");
-		pnode_printmopen(p);
-		fputs("An", stdout);
+		if (p->linestate != LINE_NEW)
+			putchar('\n');
+		puts("editor:");
+		p->linestate = LINE_TEXT;
+		macro_open(p, "An");
 		break;
 	case NODE_EMAIL:
-		pnode_printmopen(p);
-		fputs("Aq Mt", stdout);
+		macro_open(p, "Aq Mt");
 		break;
 	case NODE_EMPHASIS:
 	case NODE_FIRSTTERM:
-		pnode_printmopen(p);
-		fputs("Em", stdout);
+		macro_open(p, "Em");
 		break;
 	case NODE_ENVAR:
-		pnode_printmopen(p);
-		fputs("Ev", stdout);
+		macro_open(p, "Ev");
 		break;
 	case NODE_FILENAME:
-		pnode_printmopen(p);
-		fputs("Pa", stdout);
+		macro_open(p, "Pa");
 		break;
 	case NODE_FUNCTION:
-		pnode_printmopen(p);
-		fputs("Fn", stdout);
+		macro_open(p, "Fn");
 		break;
 	case NODE_FUNCPROTOTYPE:
-		assert(p->newln);
 		pnode_printfuncprototype(p, pn);
 		pnode_unlinksub(pn);
 		break;
 	case NODE_FUNCSYNOPSISINFO:
-		pnode_printmopen(p);
-		fputs("Fd", stdout);
+		macro_open(p, "Fd");
 		break;
 	case NODE_INDEXTERM:
 		return;
 	case NODE_INFORMALEQUATION:
-		if ( ! p->newln)
-			putchar('\n');
-		puts(".EQ");
-		p->newln = 0;
+		macro_line(p, "EQ");
 		break;
 	case NODE_INLINEEQUATION:
-		fputc('$', stdout);
-		p->newln = 0;
+		if (p->linestate == LINE_NEW)
+			p->linestate = LINE_TEXT;
+		putchar('$');
 		break;
 	case NODE_ITEMIZEDLIST:
-		assert(p->newln);
 		pnode_printlist(p, pn);
 		pnode_unlinksub(pn);
 		break;
@@ -1375,28 +1321,22 @@ pnode_print(struct parse *p, struct pnod
 		pnode_unlinksub(pn);
 		break;
 	case NODE_KEYSYM:
-		pnode_printmopen(p);
-		fputs("Sy", stdout);
+		macro_open(p, "Sy");
 		break;
 	case NODE_LEGALNOTICE:
-		assert(p->newln);
-		puts(".Sh LEGAL NOTICE");
+		macro_line(p, "Sh LEGAL NOTICE");
 		break;
 	case NODE_LINK:
 		ccp = pnode_getattr_raw(pn, ATTRKEY_LINKEND, NULL);
 		if (ccp == NULL)
 			break;
-		pnode_printmopen(p);
-		printf("Sx %s\n", ccp);
-		p->newln = 1;
+		macro_argline(p, "Sx", ccp);
 		return;
 	case NODE_LITERAL:
-		pnode_printmopen(p);
-		fputs("Li", stdout);
+		macro_open(p, "Li");
 		break;
 	case NODE_LITERALLAYOUT:
-		assert(p->newln);
-		printf(".Bd %s\n", pnode_getattr(pn, ATTRKEY_CLASS) ==
+		macro_argline(p, "Bd", pnode_getattr(pn, ATTRKEY_CLASS) ==
 		    ATTRVAL_MONOSPACED ? "-literal" : "-unfilled");
 		break;
 	case NODE_MML_MFENCED:
@@ -1418,11 +1358,9 @@ pnode_print(struct parse *p, struct pnod
 		pnode_unlinksub(pn);
 		break;
 	case NODE_OPTION:
-		pnode_printmopen(p);
-		fputs("Fl", stdout);
+		macro_open(p, "Fl");
 		break;
 	case NODE_ORDEREDLIST:
-		assert(p->newln);
 		pnode_printlist(p, pn);
 		pnode_unlinksub(pn);
 		break;
@@ -1431,20 +1369,18 @@ pnode_print(struct parse *p, struct pnod
 		break;
 	case NODE_PARAMETER:
 		/* Suppress non-text children... */
-		pnode_printmopen(p);
-		fputs("Fa \"", stdout);
-		pnode_printmacrolinetext(p, pn, MACROLINE_NOWS);
-		fputs("\"", stdout);
+		macro_open(p, "Fa \"");
+		macro_addnode(p, pn, MACROLINE_NOWS);
+		macro_addarg(p, "\"", MACROLINE_NOWS);
+		macro_close(p);
 		pnode_unlinksub(pn);
 		break;
 	case NODE_QUOTE:
-		pnode_printmopen(p);
-		fputs("Qo", stdout);
+		macro_open(p, "Qo");
 		break;
 	case NODE_PROGRAMLISTING:
 	case NODE_SCREEN:
-		assert(p->newln);
-		puts(".Bd -literal");
+		macro_line(p, "Bd -literal");
 		break;
 	case NODE_REFENTRYINFO:
 		/* Suppress. */
@@ -1455,25 +1391,18 @@ pnode_print(struct parse *p, struct pnod
 		break;
 	case NODE_REFNAME:
 		/* Suppress non-text children... */
-		pnode_printmopen(p);
-		fputs("Nm", stdout);
-		p->newln = 0;
-		pnode_printmacrolinepart(p, pn);
+		macro_nodeline(p, "Nm", pn);
 		pnode_unlinksub(pn);
 		break;
 	case NODE_REFNAMEDIV:
-		assert(p->newln);
-		puts(".Sh NAME");
+		macro_line(p, "Sh NAME");
 		break;
 	case NODE_REFPURPOSE:
-		assert(p->newln);
-		pnode_printmopen(p);
-		fputs("Nd", stdout);
+		macro_open(p, "Nd");
 		break;
 	case NODE_REFSYNOPSISDIV:
-		assert(p->newln);
 		pnode_printrefsynopsisdiv(p, pn);
-		puts(".Sh SYNOPSIS");
+		macro_line(p, "Sh SYNOPSIS");
 		break;
 	case NODE_PREFACE:
 	case NODE_SECTION:
@@ -1481,42 +1410,36 @@ pnode_print(struct parse *p, struct pnod
 	case NODE_TIP:
 	case NODE_CAUTION:
 	case NODE_WARNING:
-		assert(p->newln);
 		pnode_printrefsect(p, pn);
 		break;
 	case NODE_REPLACEABLE:
-		pnode_printmopen(p);
-		fputs("Ar", stdout);
+		macro_open(p, "Ar");
 		break;
 	case NODE_SBR:
-		assert(p->newln);
-		puts(".br");
+		macro_line(p, "br");
 		break;
 	case NODE_SGMLTAG:
-		pnode_printmopen(p);
-		fputs("Li", stdout);
+		macro_open(p, "Li");
 		break;
 	case NODE_STRUCTNAME:
-		pnode_printmopen(p);
-		fputs("Vt", stdout);
+		macro_open(p, "Vt");
 		break;
 	case NODE_TABLE:
 	case NODE_INFORMALTABLE:
-		assert(p->newln);
 		pnode_printtable(p, pn);
 		pnode_unlinksub(pn);
 		break;
 	case NODE_TEXT:
-		if (p->newln == 0)
-			putchar(' ');
-
 		bufclear(p);
 		bufappend(p, pn);
-
 		if (p->bsz == 0) {
 			assert(pn->real != pn->b);
 			break;
 		}
+		if (p->linestate == LINE_NEW)
+			p->linestate = LINE_TEXT;
+		else
+			putchar(' ');
 
 		/*
 		 * Output all characters, squeezing out whitespace
@@ -1524,7 +1447,6 @@ pnode_print(struct parse *p, struct pnod
 		 * XXX: all whitespace, including tabs (?).
 		 * Remember to escape control characters and escapes.
 		 */
-		assert(p->bsz);
 		cp = p->b;
 
 		/*
@@ -1551,34 +1473,27 @@ pnode_print(struct parse *p, struct pnod
 			if (last == '\\')
 				putchar('e');
 		}
-		p->newln = 0;
 		break;
 	case NODE_TITLE:
-		if (pn->parent->node == NODE_BOOKINFO) {
-			pnode_printmopen(p);
-			fputs("Nd", stdout);
-		}
+		if (pn->parent->node == NODE_BOOKINFO)
+			macro_open(p, "Nd");
 		break;
 	case NODE_TYPE:
-		pnode_printmopen(p);
-		fputs("Vt", stdout);
+		macro_open(p, "Vt");
 		break;
 	case NODE_USERINPUT:
-		pnode_printmopen(p);
-		fputs("Li", stdout);
+		macro_open(p, "Li");
 		break;
 	case NODE_VARIABLELIST:
-		assert(p->newln);
 		pnode_printvariablelist(p, pn);
 		pnode_unlinksub(pn);
 		break;
 	case NODE_VARLISTENTRY:
-		assert(p->newln);
 		pnode_printvarlistentry(p, pn);
+		pnode_unlinksub(pn);
 		break;
 	case NODE_VARNAME:
-		pnode_printmopen(p);
-		fputs("Va", stdout);
+		macro_open(p, "Va");
 		break;
 	default:
 		break;
@@ -1589,14 +1504,11 @@ pnode_print(struct parse *p, struct pnod
 
 	switch (pn->node) {
 	case NODE_INFORMALEQUATION:
-		if ( ! p->newln)
-			putchar('\n');
-		puts(".EN");
-		p->newln = 1;
+		macro_line(p, "EN");
 		break;
 	case NODE_INLINEEQUATION:
 		fputs("$ ", stdout);
-		p->newln = sv;
+		p->linestate = sv;
 		break;
 	case NODE_MML_MROW:
 	case NODE_MML_MI:
@@ -1630,18 +1542,19 @@ pnode_print(struct parse *p, struct pnod
 	case NODE_REFPURPOSE:
 	case NODE_SGMLTAG:
 	case NODE_STRUCTNAME:
-	case NODE_TEXT:
 	case NODE_TYPE:
 	case NODE_USERINPUT:
 	case NODE_VARNAME:
-		pnode_printmclosepunct(p, pn, sv);
+		if (sv != LINE_MACRO && p->linestate == LINE_MACRO)
+			macro_closepunct(p, pn);
 		break;
 	case NODE_QUOTE:
-		pnode_printmclose(p, sv);
-		sv = p->newln;
-		pnode_printmopen(p);
-		fputs("Qc", stdout);
-		pnode_printmclose(p, sv);
+		if (sv == LINE_NEW)
+			macro_close(p);
+		sv = p->linestate;
+		macro_open(p, "Qc");
+		if (sv == LINE_NEW)
+			macro_close(p);
 		break;
 	case NODE_REFNAME:
 		/*
@@ -1654,7 +1567,8 @@ pnode_print(struct parse *p, struct pnod
 		    TAILQ_NEXT(pn, child) != NULL &&
 		    TAILQ_NEXT(pn, child)->node == NODE_REFNAME)
 			fputs(" ,", stdout);
-		pnode_printmclose(p, sv);
+		if (sv == LINE_NEW)
+			macro_close(p);
 		break;
 	case NODE_PREFACE:
 	case NODE_SECTION:
@@ -1667,15 +1581,11 @@ pnode_print(struct parse *p, struct pnod
 	case NODE_LITERALLAYOUT:
 	case NODE_PROGRAMLISTING:
 	case NODE_SCREEN:
-		assert(p->newln);
-		puts(".Ed");
-		p->newln = 1;
+		macro_line(p, "Ed");
 		break;
 	case NODE_TITLE:
-		if (pn->parent->node == NODE_BOOKINFO) {
-			pnode_printmclose(p, 1);
-			puts(".Sh AUTHORS");
-		}
+		if (pn->parent->node == NODE_BOOKINFO)
+			macro_line(p, "Sh AUTHORS");
 		break;
 	default:
 		break;
@@ -1717,9 +1627,11 @@ readfile(XML_Parser xp, int fd,
 		 * Exit when we've read all or errors have occured
 		 * during the parse sequence.
 		 */
-		p.newln = 1;
+		p.linestate = LINE_NEW;
 		pnode_printprologue(&p, p.root);
 		pnode_print(&p, p.root);
+		if (p.linestate != LINE_NEW)
+			putchar('\n');
 		pnode_free(p.root);
 		free(p.b);
 		return rc != 0 && p.stop == 0;
--
 To unsubscribe send an email to source+unsubscribe@mandoc.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2019-03-24 16:46 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-24 16:46 docbook2mdoc: As usual, whitespace handling is the heart and soul of schwarze

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