source@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: schwarze@mandoc.bsd.lv
To: source@mandoc.bsd.lv
Subject: mandoc: Provide a new function roff_req_or_macro() to parse and handle a
Date: Sat, 30 Apr 2022 13:52:08 -0500 (EST)	[thread overview]
Message-ID: <33651b1982b367dd@mandoc.bsd.lv> (raw)

Log Message:
-----------
Provide a new function roff_req_or_macro() to parse and handle a request
or macro, including context-dependent error handling inside tbl(7) code
and inside .ce/.rj blocks.  Use it both in the top level roff(7) parser
and inside conditional blocks.

This fixes an assertion failure triggered by ".if 1 .ce" inside tbl(7)
code, found by tb@ using afl(1).

As a side benefit for readability, only one place remains in the
code that calls the main handler functions for the various roff(7)
requests.  This patch also improves column numbers in some error
messages and various comments.

Modified Files:
--------------
    mandoc:
        roff.c
    mandoc/regress/roff/ce:
        Makefile
    mandoc/regress/tbl/macro:
        Makefile
        nested.out_lint

Added Files:
-----------
    mandoc/regress/roff/ce:
        break.in
        break.out_ascii
    mandoc/regress/tbl/macro:
        req.in
        req.out_ascii
        req.out_lint

Revision Data
-------------
--- /dev/null
+++ regress/roff/ce/break.out_ascii
@@ -0,0 +1,24 @@
+CE-BREAK(1)                 General Commands Manual                CE-BREAK(1)
+
+N\bNA\bAM\bME\bE
+       ce-break - centering requests broken by high-level macros
+
+D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
+       initial text
+                        Text centered with the .ce request is
+       _\bn_\bo_\bt filled.
+                                             Text adjusted to the right margin
+                                             works in just the same way and is
+       _\bn_\bo_\bt filled either.
+                     High-level macros break centering even in a
+       _\bc_\bo_\bn_\bd_\bi_\bt_\bi_\bo_\bn_\ba_\bl block.
+
+       Now entering
+       explicit no-fill mode.
+                                    Text is still
+       _\bn_\bo_\bt
+       filled.
+
+       final text in fill mode
+
+OpenBSD                         April 30, 2022                     CE-BREAK(1)
Index: Makefile
===================================================================
RCS file: /home/cvs/mandoc/mandoc/regress/roff/ce/Makefile,v
retrieving revision 1.1
retrieving revision 1.2
diff -Lregress/roff/ce/Makefile -Lregress/roff/ce/Makefile -u -p -r1.1 -r1.2
--- regress/roff/ce/Makefile
+++ regress/roff/ce/Makefile
@@ -1,5 +1,10 @@
-# $OpenBSD: Makefile,v 1.1 2019/01/04 01:06:44 schwarze Exp $
+# $OpenBSD: Makefile,v 1.2 2022/04/30 18:46:16 schwarze Exp $
 
-REGRESS_TARGETS	 = basic
+REGRESS_TARGETS	 = basic break
+
+# mandoc defect:
+# - For now, high level macros break .ce and .rj blocks.
+
+SKIP_GROFF	 = break
 
 .include <bsd.regress.mk>
--- /dev/null
+++ regress/roff/ce/break.in
@@ -0,0 +1,33 @@
+.\" $OpenBSD: break.in,v 1.1 2022/04/30 18:46:16 schwarze Exp $
+.TH CE-BREAK 1 "April 30, 2022"
+.SH NAME
+ce-break \- centering requests broken by high-level macros
+.SH DESCRIPTION
+initial
+text
+.ce 3
+Text centered with the .ce request is
+.I not
+filled.
+.rj 4
+Text adjusted to the right margin
+works in just the same way and is
+.I not
+filled either.
+.ce
+High-level macros break centering even in a
+.if 1 .I conditional
+block.
+.PP
+.nf
+Now entering
+explicit no-fill mode.
+.ce 3
+Text is still
+.I not
+filled.
+.PP
+.fi
+final
+text
+in fill mode
Index: roff.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/roff.c,v
retrieving revision 1.385
retrieving revision 1.386
diff -Lroff.c -Lroff.c -u -p -r1.385 -r1.386
--- roff.c
+++ roff.c
@@ -237,6 +237,7 @@ static	enum roff_tok	 roff_parse(struct 
 static	int		 roff_parsetext(struct roff *, struct buf *,
 				int, int *);
 static	int		 roff_renamed(ROFF_ARGS);
+static	int		 roff_req_or_macro(ROFF_ARGS);
 static	int		 roff_return(ROFF_ARGS);
 static	int		 roff_rm(ROFF_ARGS);
 static	int		 roff_rn(ROFF_ARGS);
@@ -1905,7 +1906,6 @@ roff_parseln(struct roff *r, int ln, str
 	/*
 	 * If a scope is open, go to the child handler for that macro,
 	 * as it may want to preprocess before doing anything with it.
-	 * Don't do so if an equation is open.
 	 */
 
 	if (r->last) {
@@ -1913,19 +1913,27 @@ roff_parseln(struct roff *r, int ln, str
 		return (*roffs[t].sub)(r, t, buf, ln, ppos, pos, offs);
 	}
 
-	/* No scope is open.  This is a new request or macro. */
-
 	r->options &= ~MPARSE_COMMENT;
 	spos = pos;
 	t = roff_parse(r, buf->buf, &pos, ln, ppos);
+	return roff_req_or_macro(r, t, buf, ln, spos, pos, offs);
+}
+
+/*
+ * Handle a new request or macro.
+ * May be called outside any scope or from inside a conditional scope.
+ */
+static int
+roff_req_or_macro(ROFF_ARGS) {
 
-	/* Tables ignore most macros. */
+	/* For now, tables ignore most macros and some request. */
 
-	if (r->tbl != NULL && (t == TOKEN_NONE || t == ROFF_TS ||
-	    t == ROFF_br || t == ROFF_ce || t == ROFF_rj || t == ROFF_sp)) {
+	if (r->tbl != NULL && (tok == TOKEN_NONE || tok == ROFF_TS ||
+	    tok == ROFF_br || tok == ROFF_ce || tok == ROFF_rj ||
+	    tok == ROFF_sp)) {
 		mandoc_msg(MANDOCERR_TBLMACRO,
-		    ln, pos, "%s", buf->buf + spos);
-		if (t != TOKEN_NONE)
+		    ln, ppos, "%s", buf->buf + ppos);
+		if (tok != TOKEN_NONE)
 			return ROFF_IGN;
 		while (buf->buf[pos] != '\0' && buf->buf[pos] != ' ')
 			pos++;
@@ -1938,9 +1946,9 @@ roff_parseln(struct roff *r, int ln, str
 
 	/* For now, let high level macros abort .ce mode. */
 
-	if (ctl && roffce_node != NULL &&
-	    (t == TOKEN_NONE || t == ROFF_Dd || t == ROFF_EQ ||
-	     t == ROFF_TH || t == ROFF_TS)) {
+	if (roffce_node != NULL &&
+	    (tok == TOKEN_NONE || tok == ROFF_Dd || tok == ROFF_EQ ||
+	     tok == ROFF_TH || tok == ROFF_TS)) {
 		r->man->last = roffce_node;
 		r->man->next = ROFF_NEXT_SIBLING;
 		roffce_lines = 0;
@@ -1952,12 +1960,12 @@ roff_parseln(struct roff *r, int ln, str
 	 * Let the standard macro set parsers handle it.
 	 */
 
-	if (t == TOKEN_NONE)
+	if (tok == TOKEN_NONE)
 		return ROFF_CONT;
 
-	/* Execute a roff request or a user defined macro. */
+	/* Execute a roff request or a user-defined macro. */
 
-	return (*roffs[t].proc)(r, t, buf, ln, spos, pos, offs);
+	return (*roffs[tok].proc)(r, tok, buf, ln, ppos, pos, offs);
 }
 
 /*
@@ -2000,8 +2008,10 @@ roff_endparse(struct roff *r)
 }
 
 /*
- * Parse a roff node's type from the input buffer.  This must be in the
- * form of ".foo xxx" in the usual way.
+ * Parse the request or macro name at buf[*pos].
+ * Return ROFF_RENAMED, ROFF_USERDEF, or a ROFF_* token value.
+ * For empty, undefined, mdoc(7), and man(7) macros, return TOKEN_NONE.
+ * As a side effect, set r->current_string to the definition or to NULL.
  */
 static enum roff_tok
 roff_parse(struct roff *r, char *buf, int *pos, int ln, int ppos)
@@ -2393,27 +2403,18 @@ static int
 roff_cond_sub(ROFF_ARGS)
 {
 	struct roffnode	*bl;
-	int		 irc, rr;
+	int		 irc, rr, spos;
 	enum roff_tok	 t;
 
 	rr = 0;  /* If arguments follow "\}", skip them. */
 	irc = roff_cond_checkend(r, tok, buf, ln, ppos, pos, &rr);
+	spos = pos;
 	t = roff_parse(r, buf->buf, &pos, ln, ppos);
 
-	/* For now, let high level macros abort .ce mode. */
-
-	if (roffce_node != NULL &&
-	    (t == TOKEN_NONE || t == ROFF_Dd || t == ROFF_EQ ||
-             t == ROFF_TH || t == ROFF_TS)) {
-		r->man->last = roffce_node;
-		r->man->next = ROFF_NEXT_SIBLING;
-		roffce_lines = 0;
-		roffce_node = NULL;
-	}
-
 	/*
-	 * Fully handle known macros when they are structurally
-	 * required or when the conditional evaluated to true.
+	 * Handle requests and macros if the conditional evaluated
+	 * to true or if they are structurally required.
+	 * The .break request is always handled specially.
 	 */
 
 	if (t == ROFF_break) {
@@ -2426,13 +2427,11 @@ roff_cond_sub(ROFF_ARGS)
 					break;
 			}
 		}
-	} else if (t != TOKEN_NONE &&
-	    (rr || roffs[t].flags & ROFFMAC_STRUCT)) {
-		irc |= (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs);
+	} else if (rr || (t < TOKEN_NONE && roffs[t].flags & ROFFMAC_STRUCT)) {
+		irc |= roff_req_or_macro(r, t, buf, ln, spos, pos, offs);
 		if (irc & ROFF_WHILE)
 			irc &= ~(ROFF_LOOPCONT | ROFF_LOOPEXIT);
-	} else
-		irc |= rr ? ROFF_CONT : ROFF_IGN;
+	}
 	return irc;
 }
 
--- /dev/null
+++ regress/tbl/macro/req.out_ascii
@@ -0,0 +1,18 @@
+TBL-MACRO-REQ(1)            General Commands Manual           TBL-MACRO-REQ(1)
+
+N\bNA\bAM\bME\bE
+       tbl-macro-req - requests generating nodes in a table
+
+D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
+       initial text
+
+       +--+-----+
+       |a | b   |
+       +--+-----+
+       |c | d e |
+       |f | g h |
+       |i | j k |
+       +--+-----+
+       final text
+
+OpenBSD                         April 30, 2022                TBL-MACRO-REQ(1)
--- /dev/null
+++ regress/tbl/macro/req.out_lint
@@ -0,0 +1,5 @@
+mandoc: req.in:10:5: ERROR: ignoring extra tbl data cells: stray
+mandoc: req.in:16:2: UNSUPP: ignoring macro in table: ce
+mandoc: req.in:19:2: UNSUPP: ignoring macro in table: br
+mandoc: req.in:22:8: UNSUPP: ignoring macro in table: ce
+mandoc: req.in:25:8: UNSUPP: ignoring macro in table: br
--- /dev/null
+++ regress/tbl/macro/req.in
@@ -0,0 +1,30 @@
+.\" $OpenBSD: req.in,v 1.1 2022/04/30 18:46:16 schwarze Exp $
+.TH TBL-MACRO-REQ 1 "April 30, 2022"
+.SH NAME
+tbl-macro-req \- requests generating nodes in a table
+.SH DESCRIPTION
+initial text
+.TS
+box tab(:);
+l | l .
+a:b:stray
+_
+c:T{
+d
+e
+T}
+.ce
+f:T{
+g
+.br
+h
+T}
+.if 1 .ce
+i:T{
+j
+.if 1 .br
+k
+T}
+.TE
+.PP
+final text
Index: Makefile
===================================================================
RCS file: /home/cvs/mandoc/mandoc/regress/tbl/macro/Makefile,v
retrieving revision 1.1
retrieving revision 1.2
diff -Lregress/tbl/macro/Makefile -Lregress/tbl/macro/Makefile -u -p -r1.1 -r1.2
--- regress/tbl/macro/Makefile
+++ regress/tbl/macro/Makefile
@@ -1,12 +1,15 @@
-# $OpenBSD: Makefile,v 1.2 2016/08/20 14:43:40 schwarze Exp $
+# $OpenBSD: Makefile,v 1.3 2022/04/30 18:46:16 schwarze Exp $
 
-REGRESS_TARGETS	 = man nested column
-LINT_TARGETS	 = man nested
+REGRESS_TARGETS	 = column man nested req
+LINT_TARGETS	 = man nested req
 
-# trivial differences to groff-1.22.3:
+# mandoc defect:
+# mandoc(1) ignores .br inside tbl(7) code.
+
+# trivial differences to groff-1.23.0:
 # .TS in a table causes a blank table line in GNU tbl(1), but not in mandoc.
 # .TS in a column list causes a blank line in mandoc, but not in GNU tbl(1).
 
-SKIP_GROFF	 = nested column
+SKIP_GROFF	 = column nested req
 
 .include <bsd.regress.mk>
Index: nested.out_lint
===================================================================
RCS file: /home/cvs/mandoc/mandoc/regress/tbl/macro/nested.out_lint,v
retrieving revision 1.4
retrieving revision 1.5
diff -Lregress/tbl/macro/nested.out_lint -Lregress/tbl/macro/nested.out_lint -u -p -r1.4 -r1.5
--- regress/tbl/macro/nested.out_lint
+++ regress/tbl/macro/nested.out_lint
@@ -1 +1 @@
-mandoc: nested.in:13:4: UNSUPP: ignoring macro in table: TS
+mandoc: nested.in:13:2: UNSUPP: ignoring macro in table: TS
--
 To unsubscribe send an email to source+unsubscribe@mandoc.bsd.lv


                 reply	other threads:[~2022-04-30 18:52 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=33651b1982b367dd@mandoc.bsd.lv \
    --to=schwarze@mandoc.bsd.lv \
    --cc=source@mandoc.bsd.lv \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).