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 */