source@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: schwarze@mandoc.bsd.lv
To: source@mandoc.bsd.lv
Subject: mandoc: Expand \n(.$ (the number of macro arguments) right in
Date: Mon, 20 Aug 2018 12:25:39 -0500 (EST)	[thread overview]
Message-ID: <c89f1d47038f47a0@fantadrom.bsd.lv> (raw)

Log Message:
-----------
Expand \n(.$ (the number of macro arguments) right in roff_userdef(),
before even reparsing the expanded macro.
That is the least dirty way to fix the bug that \(.$ remained set
after execution of the user-defined macro ended.  Any other way
to fix it would probably require changes to read.c, which really
shouldn't be bothered with such roff(7) internals.

Modified Files:
--------------
    mandoc:
        roff.c

Revision Data
-------------
Index: roff.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/roff.c,v
retrieving revision 1.336
retrieving revision 1.337
diff -Lroff.c -Lroff.c -u -p -r1.336 -r1.337
--- roff.c
+++ roff.c
@@ -107,7 +107,6 @@ struct	roff {
 	int		 rstacksz; /* current size limit of rstack */
 	int		 rstackpos; /* position in rstack */
 	int		 format; /* current file in mdoc or man format */
-	int		 argc; /* number of args of the last macro */
 	char		 control; /* control character */
 	char		 escape; /* escape character */
 };
@@ -2663,7 +2662,7 @@ roff_getregro(const struct roff *r, cons
 
 	switch (*name) {
 	case '$':  /* Number of arguments of the last macro evaluated. */
-		return r->argc;
+		return 0;
 	case 'A':  /* ASCII approximation mode is always off. */
 		return 0;
 	case 'g':  /* Groff compatibility mode is always on. */
@@ -3381,22 +3380,22 @@ roff_userdef(ROFF_ARGS)
 {
 	const char	 *arg[16], *ap;
 	char		 *cp, *n1, *n2;
-	int		  expand_count, i, ib, ie;
-	size_t		  asz, rsz;
+	int		  argc, expand_count, i, ib, ie;
+	size_t		  asz, esz, rsz;
 
 	/*
 	 * Collect pointers to macro argument strings
 	 * and NUL-terminate them.
 	 */
 
-	r->argc = 0;
+	argc = 0;
 	cp = buf->buf + pos;
 	for (i = 0; i < 16; i++) {
 		if (*cp == '\0')
 			arg[i] = "";
 		else {
 			arg[i] = mandoc_getarg(r->parse, &cp, ln, &pos);
-			r->argc = i + 1;
+			argc = i + 1;
 		}
 	}
 
@@ -3418,7 +3417,7 @@ roff_userdef(ROFF_ARGS)
 			continue;
 		if (*cp == '*') {  /* \\$* inserts all arguments */
 			ib = 0;
-			ie = r->argc - 1;
+			ie = argc - 1;
 		} else {  /* \\$1 .. \\$9 insert one argument */
 			ib = ie = *cp - '1';
 			if (ib < 0 || ib > 8)
@@ -3504,6 +3503,34 @@ roff_userdef(ROFF_ARGS)
 			if (i < ie)
 				*n2++ = ' ';
 		}
+	}
+
+	/*
+	 * Expand the number of arguments, if it is used.
+	 * This never makes the expanded macro longer.
+	 */
+
+	for (cp = n1; *cp != '\0'; cp++) {
+		if (cp[0] != '\\')
+			continue;
+		if (cp[1] == '\\') {
+			cp++;
+			continue;
+		}
+		if (strncmp(cp + 1, "n(.$", 4) == 0)
+			esz = 5;
+		else if (strncmp(cp + 1, "n[.$]", 5) == 0)
+			esz = 6;
+		else
+			continue;
+		asz = snprintf(cp, esz, "%d", argc);
+		assert(asz < esz);
+		rsz = buf->sz - (cp - n1) - esz;
+		memmove(cp + asz, cp + esz, rsz);
+		buf->sz -= esz - asz;
+		n2 = mandoc_realloc(n1, buf->sz);
+		cp = n2 + (cp - n1) + asz;
+		n1 = n2;
 	}
 
 	/*
--
 To unsubscribe send an email to source+unsubscribe@mandoc.bsd.lv

                 reply	other threads:[~2018-08-20 17:25 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=c89f1d47038f47a0@fantadrom.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).