tech@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: Ingo Schwarze <schwarze@usta.de>
To: tech@mdocml.bsd.lv
Subject: Re: roff.c question
Date: Wed, 8 Dec 2010 02:05:27 +0100	[thread overview]
Message-ID: <20101208010527.GA25360@iris.usta.de> (raw)
In-Reply-To: <4CFBAC80.1060004@bsd.lv>

Hi Kristaps,

Kristaps Dzonsons wrote on Sun, Dec 05, 2010 at 04:15:12PM +0100:
> Ingo wrote:

>> 1) roff_res() should not expand \\* or \\\\*,
>>    but it should expand \* and \\\*.
>>
>> OK for the following patch?

> That's fine by me,

Oh well, the patch was broken, fortunately i notived before
committing it.  The problem was that it didn't make sure that
the '*' immediately followed the '\\'.

> but let's please put some roff.7 documentation
> (and in-line) in place

Actually, that's what made me find the problem.
Documenting code is often a good debugging strategy.

> regarding this sort of chicanery.
> It confuses the hell out of me for one!

At some point, i guess we will have to implement proper
roff copy mode - but not right now, we still have more
elementary problems to deal with.  At that point, we
ought to improve roff(7) docs related to .ds and \*.

For now, i suggest to add just one sentence.


See below for an updated patch.
As it is quite different form the previous one,
i'm not committing it right away,
but sending it again for review.

It is not as long as it seems; that's just the comments!  ;-)
Actually, the code is more straightforward and easier than
my first try and uses one automatic variable less.

As my other patch depends on this one (not in the sense of
physical conflicts in the code, but logically), i need to
return to it when this has gone in.

Yours,
  Ingo


Index: usr.bin/mandoc/roff.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/roff.c,v
retrieving revision 1.22
diff -u -p -r1.22 roff.c
--- usr.bin/mandoc/roff.c	7 Dec 2010 00:08:52 -0000	1.22
+++ usr.bin/mandoc/roff.c	8 Dec 2010 00:49:53 -0000
@@ -337,15 +337,43 @@ roff_alloc(struct regset *regs, void *da
 static int
 roff_res(struct roff *r, char **bufp, size_t *szp, int pos)
 {
-	const char	*cp, *cpp, *st, *res;
+	const char	*stesc;	/* start of an escape sequence ('\\') */
+	const char	*stnam;	/* start of the name, after "[(*" */
+	const char	*cp;	/* end of the name, e.g. before ']' */
+	const char	*res;	/* the string to be substituted */
 	int		 i, maxl;
 	size_t		 nsz;
 	char		*n;
 
-	/* LINTED */
-	for (cp = &(*bufp)[pos]; (cpp = strstr(cp, "\\*")); cp++) {
-		cp = cpp + 2;
-		switch (*cp) {
+	/* String escape sequences have at least three characters. */
+
+	for (cp = *bufp + pos; cp[0] && cp[1] && cp[2]; cp++) {
+
+		/*
+		 * The first character must be a backslash.
+		 * Save a pointer to it.
+		 */
+
+		if ('\\' != *cp)
+			continue;
+		stesc = cp;
+
+		/*
+		 * The second character must be an asterisk.
+		 * If it isn't, skip it anyway:  It is escaped,
+		 * so it can't start another escape sequence.
+		 */
+
+		if ('*' != *(++cp))
+			continue;
+
+		/*
+		 * The third character decides the length
+		 * of the name of the string.
+		 * Save a pointer to the name.
+		 */
+
+		switch (*(++cp)) {
 		case ('('):
 			cp++;
 			maxl = 2;
@@ -358,8 +386,9 @@ roff_res(struct roff *r, char **bufp, si
 			maxl = 1;
 			break;
 		}
+		stnam = cp;
 
-		st = cp;
+		/* Advance to the end of the name. */
 
 		for (i = 0; 0 == maxl || i < maxl; i++, cp++) {
 			if ('\0' == *cp)
@@ -368,19 +397,24 @@ roff_res(struct roff *r, char **bufp, si
 				break;
 		}
 
-		res = roff_getstrn(r, st, (size_t)i);
+		/*
+		 * Retrieve the replacement string; if it is
+		 * undefined, resume searching for escapes.
+		 */
+
+		res = roff_getstrn(r, stnam, (size_t)i);
 
 		if (NULL == res) {
 			cp -= maxl ? 1 : 0;
 			continue;
 		}
 
+		/* Replace the escape sequence by the string. */
+
 		nsz = *szp + strlen(res) + 1;
 		n = mandoc_malloc(nsz);
 
-		*n = '\0';
-
-		strlcat(n, *bufp, (size_t)(cpp - *bufp + 1));
+		strlcpy(n, *bufp, (size_t)(stesc - *bufp + 1));
 		strlcat(n, res, nsz);
 		strlcat(n, cp + (maxl ? 0 : 1), nsz);
 
@@ -544,6 +578,7 @@ roff_cblock(ROFF_ARGS)
 	case (ROFF_am1):
 		/* FALLTHROUGH */
 	case (ROFF_de):
+		/* ROFF_de1 is remapped to ROFF_de in roff_block(). */
 		/* FALLTHROUGH */
 	case (ROFF_dei):
 		/* FALLTHROUGH */
Index: share/man/man7/roff.7
===================================================================
RCS file: /cvs/src/share/man/man7/roff.7,v
retrieving revision 1.5
diff -u -p -r1.5 roff.7
--- share/man/man7/roff.7	30 Nov 2010 22:40:13 -0000	1.5
+++ share/man/man7/roff.7	8 Dec 2010 00:49:53 -0000
@@ -269,6 +269,9 @@ for a
 of arbitrary length, or \e*(NN or \e*N if the length of
 .Ar name
 is two or one characters, respectively.
+Interpolation can be prevented by escaping the leading backslash;
+that is, an asterisk preceded by an even number of backslashes
+does not trigger string interpolation.
 .Pp
 Since user-defined strings and macros share a common string table,
 defining a string
--
 To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv

  reply	other threads:[~2010-12-08  1:05 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-01 16:33 exit_status persistence Kristaps Dzonsons
2010-12-01 16:41 ` Kristaps Dzonsons
2010-12-01 21:28 ` Ingo Schwarze
2010-12-02 10:51   ` exit_status persistence (now: roff.c question) Kristaps Dzonsons
2010-12-02 13:29     ` Kristaps Dzonsons
2010-12-02 22:50       ` roff.c question Ingo Schwarze
2010-12-03 21:49         ` Ingo Schwarze
2010-12-05 15:15           ` Kristaps Dzonsons
2010-12-08  1:05             ` Ingo Schwarze [this message]
2010-12-10  9:40               ` Kristaps Dzonsons
2010-12-10 20:45                 ` Ingo Schwarze
2010-12-10 20:52                   ` Joerg Sonnenberger
2010-12-10 21:10                     ` Ingo Schwarze
2010-12-10 21:17                       ` Joerg Sonnenberger
2010-12-10 23:12                       ` Ingo Schwarze
2010-12-03 23:31         ` Ingo Schwarze
2010-12-05 15:17           ` Kristaps Dzonsons
2010-12-09 23:45             ` Ingo Schwarze
2010-12-10  9:32               ` Kristaps Dzonsons
2010-12-02 20:54     ` Ingo Schwarze

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=20101208010527.GA25360@iris.usta.de \
    --to=schwarze@usta.de \
    --cc=tech@mdocml.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).