source@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: schwarze@mdocml.bsd.lv
To: source@mdocml.bsd.lv
Subject: mdocml: We already supported (outer) user-defined strings containing
Date: Mon, 7 Apr 2014 17:00:08 -0400 (EDT)	[thread overview]
Message-ID: <201404072100.s37L08ek001955@krisdoz.my.domain> (raw)

Log Message:
-----------
We already supported (outer) user-defined strings containing references 
to other (inner) user-defined strings in their values, such that the inner
ones get expanded at expansion time of the outer ones (delayed evaluation).
Now we also support specifying the name of an (outer) user-defined
string to expand using the expanded values of some other (inner)  
user-defined strings (indirect reference).

Modified Files:
--------------
    mdocml:
        roff.c

Revision Data
-------------
Index: roff.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/roff.c,v
retrieving revision 1.204
retrieving revision 1.205
diff -Lroff.c -Lroff.c -u -p -r1.204 -r1.205
--- roff.c
+++ roff.c
@@ -493,32 +493,44 @@ static enum rofferr
 roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
 {
 	char		 ubuf[12]; /* buffer to print the number */
+	const char	*start;	/* start of the string to process */
 	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 */
 	char		*nbuf;	/* new buffer to copy bufp to */
-	size_t		 nsz;	/* size of the new buffer */
 	size_t		 maxl;  /* expected length of the escape name */
 	size_t		 naml;	/* actual length of the escape name */
+	size_t		 ressz;	/* size of the replacement string */
 	int		 expand_count;	/* to avoid infinite loops */
 
 	expand_count = 0;
+	start = *bufp + pos;
+	stesc = strchr(start, '\0') - 1;
+	while (stesc-- > start) {
 
-again:
-	cp = *bufp + pos;
-	while (NULL != (cp = strchr(cp, '\\'))) {
-		stesc = cp++;
+		/* Search backwards for the next backslash. */
+
+		if ('\\' != *stesc)
+			continue;
+
+		/* If it is escaped, skip it. */
+
+		for (cp = stesc - 1; cp >= start; cp--)
+			if ('\\' != *cp)
+				break;
+
+		if (0 == (stesc - cp) % 2) {
+			stesc = cp;
+			continue;
+		}
 
 		/*
-		 * The second character must be an asterisk or an n.
-		 * If it isn't, skip it anyway:  It is escaped,
-		 * so it can't start another escape sequence.
+		 * Everything except user-defined strings and number
+		 * registers is only checked, not expanded.
 		 */
 
-		if ('\0' == *cp)
-			return(ROFF_CONT);
-
+		cp = stesc + 1;
 		switch (*cp) {
 		case ('*'):
 			res = NULL;
@@ -527,15 +539,17 @@ again:
 			res = ubuf;
 			break;
 		default:
-			if (ESCAPE_ERROR != mandoc_escape(&cp, NULL, NULL))
-				continue;
-			mandoc_msg
-				(MANDOCERR_BADESCAPE, r->parse, 
-				 ln, (int)(stesc - *bufp), NULL);
-			return(ROFF_CONT);
+			if (ESCAPE_ERROR == mandoc_escape(&cp, NULL, NULL))
+				mandoc_msg(MANDOCERR_BADESCAPE, r->parse,
+				    ln, (int)(stesc - *bufp), NULL);
+			continue;
 		}
 
-		cp++;
+		if (EXPAND_LIMIT < ++expand_count) {
+			mandoc_msg(MANDOCERR_ROFFLOOP, r->parse,
+			    ln, (int)(stesc - *bufp), NULL);
+			return(ROFF_IGN);
+		}
 
 		/*
 		 * The third character decides the length
@@ -543,9 +557,9 @@ again:
 		 * Save a pointer to the name.
 		 */
 
-		switch (*cp) {
+		switch (*++cp) {
 		case ('\0'):
-			return(ROFF_CONT);
+			continue;
 		case ('('):
 			cp++;
 			maxl = 2;
@@ -568,7 +582,7 @@ again:
 					(MANDOCERR_BADESCAPE, 
 					 r->parse, ln, 
 					 (int)(stesc - *bufp), NULL);
-				return(ROFF_CONT);
+				continue;
 			}
 			if (0 == maxl && ']' == *cp)
 				break;
@@ -591,29 +605,23 @@ again:
 				 ln, (int)(stesc - *bufp), NULL);
 			res = "";
 		}
+		ressz = strlen(res);
 
 		/* Replace the escape sequence by the string. */
 
-		pos = stesc - *bufp;
-
-		nsz = *szp + strlen(res) + 1;
-		nbuf = mandoc_malloc(nsz);
+		*szp += ressz + 1;
+		nbuf = mandoc_malloc(*szp);
 
 		strlcpy(nbuf, *bufp, (size_t)(stesc - *bufp + 1));
-		strlcat(nbuf, res, nsz);
-		strlcat(nbuf, cp + (maxl ? 0 : 1), nsz);
+		strlcat(nbuf, res, *szp);
+		strlcat(nbuf, cp + (maxl ? 0 : 1), *szp);
 
-		free(*bufp);
+		/* Prepare for the next replacement. */
 
+		start = nbuf + pos;
+		stesc = nbuf + (stesc - *bufp) + ressz;
+		free(*bufp);
 		*bufp = nbuf;
-		*szp = nsz;
-
-		if (EXPAND_LIMIT >= ++expand_count)
-			goto again;
-
-		/* Just leave the string unexpanded. */
-		mandoc_msg(MANDOCERR_ROFFLOOP, r->parse, ln, pos, NULL);
-		return(ROFF_IGN);
 	}
 	return(ROFF_CONT);
 }
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

                 reply	other threads:[~2014-04-07 21:00 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=201404072100.s37L08ek001955@krisdoz.my.domain \
    --to=schwarze@mdocml.bsd.lv \
    --cc=source@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).