shithub: neatroff

Download patch

ref: 88b3d68dce91f41a988bf90e1eec7b10bd25dd61
parent: 82a5163b8e7a1e6abb8bbe4cceeca68899460aa0
author: Ali Gholami Rudi <ali@rudi.ir>
date: Fri Apr 19 09:00:39 EDT 2013

cp: do not remove \{ and \} in copy mode, unless asked to

--- a/cp.c
+++ b/cp.c
@@ -6,7 +6,8 @@
 
 static int cp_buf[CPBUF];	/* pushed character stack */
 static int cp_backed;		/* number of pushed characters */
-static int cp_blk;		/* input block depth (text in \{ and \}) */
+static int cp_nblk;		/* input block depth (text in \{ and \}) */
+static int cp_sblk[NIES];	/* skip \} escape at this depth, if set */
 
 static int regid(void)
 {
@@ -63,14 +64,11 @@
 			return in_next();
 		if (c == '.')
 			return '.';
-		if (c == '{') {
-			cp_blk++;
-			return cp_raw();
-		}
-		if (c == '}') {
-			cp_blk--;
-			return cp_raw();
-		}
+		if (c == '{' && cp_nblk < LEN(cp_sblk))
+			cp_sblk[cp_nblk++] = 0;
+		if (c == '}' && cp_nblk > 0)
+			if (cp_sblk[--cp_nblk])
+				return cp_raw();
 		cp_back(c);
 		return '\\';
 	}
@@ -111,15 +109,30 @@
 		cp_buf[cp_backed++] = c;
 }
 
-void cp_skip(void)
+static int cp_top(void)
 {
+	return cp_backed ? cp_buf[cp_backed - 1] : -1;
+}
+
+void cp_blk(int skip)
+{
 	int c;
-	int old_blk = cp_blk;
+	int nblk = cp_nblk;
 	do {
 		c = cp_raw();
 	} while (c == ' ' || c == '\t');
-	while (cp_blk > old_blk && c >= 0)
-		c = cp_raw();
-	while (c != '\n')
+	if (c == '\\' && cp_top() == '{') {	/* a troff \{ \} block */
+		if (skip) {
+			while (skip && cp_nblk > nblk && c >= 0)
+				c = cp_raw();
+		} else {
+			cp_sblk[nblk] = 1;
+			cp_raw();
+		}
+	} else {
+		if (!skip)
+			cp_back(c);
+	}
+	while (skip && c != '\n')	/* skip until the end of the line */
 		c = cp_raw();
 }
--- a/in.c
+++ b/in.c
@@ -18,6 +18,7 @@
 static char files[NFILES][PATHLEN];
 static int nfiles;
 static int cfile;
+static int in_last;
 
 static char **args_init(char **args);
 static void args_free(char **args);
@@ -41,6 +42,12 @@
 	buf->args = args ? args_init(args) : NULL;
 }
 
+void in_pushnl(void)
+{
+	if (buf && buf->backed < 0 && in_last != '\n')
+		cp_back('\n');
+}
+
 void in_source(char *path)
 {
 	FILE *fin = path && path[0] ? fopen(path, "r") : stdin;
@@ -77,16 +84,9 @@
 	return !buf;
 }
 
-int in_next(void)
+static int in_read(void)
 {
 	int c;
-	if (!buf && in_nextfile())
-		return -1;
-	if (buf->backed >= 0) {
-		c = buf->backed;
-		buf->backed = -1;
-		return c;
-	}
 	while (buf || !in_nextfile()) {
 		if (buf->buf && buf->pos < buf->len)
 			break;
@@ -100,6 +100,20 @@
 	if (buf->buf[buf->pos] == '\\' && buf->buf[buf->pos + 1] == '\\')
 		buf->pos++;
 	return buf->buf[buf->pos++];
+}
+
+int in_next(void)
+{
+	int c;
+	if (!buf && in_nextfile())
+		return -1;
+	c = buf->backed;
+	if (c >= 0)
+		buf->backed = -1;
+	else
+		c = in_read();
+	in_last = c;
+	return c;
 }
 
 void in_back(int c)
--- a/ren.c
+++ b/ren.c
@@ -169,6 +169,7 @@
 		push_ne(0);
 	if (str_get(reg))
 		in_push(str_get(reg), NULL);
+	in_pushnl();
 }
 
 /* return 1 if executed a trap */
@@ -472,7 +473,7 @@
 			int l = nextchar(c);
 			l += nextchar(c + l);
 			c[l] = '\0';
-		} else if (strchr("DfhksvwXx", c[0])) {
+		} else if (strchr("DfhksvwXx{}", c[0])) {
 			if (c[0] == 'w') {
 				render_wid();
 				return 0;
@@ -498,6 +499,8 @@
 				adj_put(adj, 0, "\\X'%s'", arg);
 			if (c[0] == 'x')
 				adj_els(adj, eval(arg, 0, 'v'));
+			if (c[0] == '{' || c[0] == '}')
+				;
 			return 0;
 		}
 	}
--- a/tr.c
+++ b/tr.c
@@ -200,20 +200,6 @@
 	return ret;
 }
 
-/* execute or skip the line or block following .if */
-static void if_blk(int doexec)
-{
-	int c;
-	if (doexec) {
-		do {
-			c = cp_next();
-		} while (c == ' ');
-		cp_back(c);
-	} else {
-		cp_skip();
-	}
-}
-
 static int ie_cond[NIES];	/* .ie condition stack */
 static int ie_depth;
 
@@ -238,12 +224,12 @@
 	if (args[0][1] == 'i' && args[0][2] == 'e')	/* .ie command */
 		if (ie_depth < NIES)
 			ie_cond[ie_depth++] = ret != neg;
-	if_blk(ret != neg);
+	cp_blk(ret == neg);
 }
 
 static void tr_el(char **args)
 {
-	if_blk(ie_depth > 0 ? !ie_cond[--ie_depth] : 0);
+	cp_blk(ie_depth > 0 ? ie_cond[--ie_depth] : 1);
 }
 
 static void tr_na(char **args)
--- a/xroff.h
+++ b/xroff.h
@@ -103,9 +103,10 @@
 void in_queue(char *path);	/* next input file */
 char *in_arg(int i);		/* look up argument */
 void in_back(int c);		/* push back input character */
+void in_pushnl(void);		/* push a \n, if the last char was not */
 char *in_filename(void);	/* current filename */
 void cp_back(int c);		/* push back copy-mode character */
-void cp_skip(void);		/* skip current input line or block */
+void cp_blk(int skip);		/* skip or read the next line or block */
 
 /* rendering */
 void render(void);	/* read from in.c and print the output */