From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp1.rz.uni-karlsruhe.de (Debian-exim@smtp1.rz.uni-karlsruhe.de [129.13.185.217]) by krisdoz.my.domain (8.14.3/8.14.3) with ESMTP id oB815TtY025893 for ; Tue, 7 Dec 2010 20:05:30 -0500 (EST) Received: from hekate.usta.de (asta-nat.asta.uni-karlsruhe.de [172.22.63.82]) by smtp1.rz.uni-karlsruhe.de with esmtp (Exim 4.63 #1) id 1PQ8TH-0006IJ-9d; Wed, 08 Dec 2010 02:05:27 +0100 Received: from donnerwolke.usta.de ([172.24.96.3]) by hekate.usta.de with esmtp (Exim 4.72) (envelope-from ) id 1PQ8TH-0006TA-7k for tech@mdocml.bsd.lv; Wed, 08 Dec 2010 02:05:27 +0100 Received: from iris.usta.de ([172.24.96.5] helo=usta.de) by donnerwolke.usta.de with esmtp (Exim 4.69) (envelope-from ) id 1PQ8TH-0005Zn-6N for tech@mdocml.bsd.lv; Wed, 08 Dec 2010 02:05:27 +0100 Received: from schwarze by usta.de with local (Exim 4.72) (envelope-from ) id 1PQ8TH-0007AC-5e for tech@mdocml.bsd.lv; Wed, 08 Dec 2010 02:05:27 +0100 Date: Wed, 8 Dec 2010 02:05:27 +0100 From: Ingo Schwarze To: tech@mdocml.bsd.lv Subject: Re: roff.c question Message-ID: <20101208010527.GA25360@iris.usta.de> References: <4CF678F0.6020304@bsd.lv> <20101201212834.GA22990@iris.usta.de> <4CF77A2B.6020702@bsd.lv> <4CF79F45.6080105@bsd.lv> <20101202225019.GD12188@iris.usta.de> <20101203214929.GB28384@iris.usta.de> <4CFBAC80.1060004@bsd.lv> X-Mailinglist: mdocml-tech Reply-To: tech@mdocml.bsd.lv MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <4CFBAC80.1060004@bsd.lv> User-Agent: Mutt/1.5.21 (2010-09-15) 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