shithub: neatroff

Download patch

ref: fa227033810da058e4b76ed18ccf36a9c04fa9d5
parent: 72b10b4403a811e2e95c9b7dbbc5098af022f669
author: Ali Gholami Rudi <ali@rudi.ir>
date: Wed Apr 24 15:02:40 EDT 2013

ren: execute the 0 trap just after the initial troff requests

Now cp.c and tr.c are stateless and unread characters are saved
in in.c.

--- a/cp.c
+++ b/cp.c
@@ -4,8 +4,6 @@
 
 #define CPBUF		4
 
-static int cp_buf[CPBUF];	/* pushed character stack */
-static int cp_backed;		/* number of pushed characters */
 static int cp_nblk;		/* input block depth (text in \{ and \}) */
 static int cp_sblk[NIES];	/* skip \} escape at this depth, if set */
 static int cp_widreq = 1;	/* inline \w requests */
@@ -63,8 +61,8 @@
 static int cp_raw(void)
 {
 	int c;
-	if (cp_backed)
-		return cp_buf[--cp_backed];
+	if (in_top() >= 0)
+		return in_next();
 	c = in_next();
 	if (c == '\\') {
 		c = in_next();
@@ -86,8 +84,8 @@
 int cp_next(void)
 {
 	int c;
-	if (cp_backed)
-		return cp_buf[--cp_backed];
+	if (in_top() >= 0)
+		return in_next();
 	c = cp_raw();
 	if (c == '\\') {
 		c = cp_raw();
@@ -114,17 +112,6 @@
 	return c;
 }
 
-void cp_back(int c)
-{
-	if (cp_backed < CPBUF)
-		cp_buf[cp_backed++] = c;
-}
-
-static int cp_top(void)
-{
-	return cp_backed ? cp_buf[cp_backed - 1] : -1;
-}
-
 void cp_blk(int skip)
 {
 	int c;
@@ -132,7 +119,7 @@
 	do {
 		c = cp_raw();
 	} while (c == ' ' || c == '\t');
-	if (c == '\\' && cp_top() == '{') {	/* a troff \{ \} block */
+	if (c == '\\' && in_top() == '{') {	/* a troff \{ \} block */
 		if (skip) {
 			while (skip && cp_nblk > nblk && c >= 0)
 				c = cp_raw();
--- a/in.c
+++ b/in.c
@@ -8,9 +8,10 @@
 	FILE *fin;
 	char *buf;		/* for string buffers */
 	char **args;
+	int unbuf[8];		/* unread characters */
+	int un;			/* number of unread characters */
 	int pos;
 	int len;
-	int backed;
 	int nl;			/* read \n, if the previous char was not */
 	struct inbuf *prev;
 };
@@ -19,7 +20,7 @@
 static char files[NFILES][PATHLEN];
 static int nfiles;
 static int cfile;
-static int in_last;
+static int in_last[2];		/* the last chars returned from in_next() */
 
 static char **args_init(char **args);
 static void args_free(char **args);
@@ -28,7 +29,6 @@
 {
 	struct inbuf *next = malloc(sizeof(*next));
 	memset(next, 0, sizeof(*next));
-	next->backed = -1;
 	next->prev = buf;
 	buf = next;
 }
@@ -89,7 +89,9 @@
 {
 	int c;
 	while (buf || !in_nextfile()) {
-		if (buf->nl-- > 0 && in_last != '\n')
+		if (buf->un)
+			return buf->unbuf[--buf->un];
+		if (buf->nl-- > 0 && in_last[0] != '\n')
 			return '\n';
 		if (buf->buf && buf->pos < buf->len)
 			break;
@@ -107,22 +109,21 @@
 
 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;
+	in_last[1] = in_last[0];
+	in_last[0] = in_read();
+	return in_last[0];
 }
 
 void in_back(int c)
 {
+	in_last[0] = in_last[1];
 	if (buf)
-		buf->backed = c;
+		buf->unbuf[buf->un++] = c;
+}
+
+int in_top(void)
+{
+	return buf && buf->un ? buf->unbuf[buf->un - 1] : -1;
 }
 
 char *in_arg(int i)
--- a/ren.c
+++ b/ren.c
@@ -605,6 +605,8 @@
 {
 	int c;
 	n_nl = -1;
+	tr_first();
+	ren_first();			/* transition to the first page */
 	c = ren_next();
 	while (c >= 0) {
 		if (c == ' ' || c == '\n') {
--- a/tr.c
+++ b/tr.c
@@ -534,3 +534,8 @@
 	for (i = 0; i < LEN(cmds); i++)
 		str_dset(REG(cmds[i].id[0], cmds[i].id[1]), &cmds[i]);
 }
+
+void tr_first(void)
+{
+	cp_back(tr_next());
+}
--- a/xroff.h
+++ b/xroff.h
@@ -106,20 +106,21 @@
 char *in_arg(int i);		/* look up argument */
 int in_nargs(void);		/* number of arguments */
 void in_back(int c);		/* push back input character */
+int in_top(void);		/* the first pushed-back character */
 char *in_filename(void);	/* current filename */
-void cp_back(int c);		/* push back copy-mode character */
 void cp_blk(int skip);		/* skip or read the next line or block */
 void cp_wid(int enable);	/* control inlining \w requests */
+void tr_first(void);		/* read until the first non-command line */
+#define cp_back		in_back	/* cp.c is stateless */
 
 /* rendering */
-void render(void);	/* read from in.c and print the output */
+void render(void);		/* read from in.c and print the output */
 int ren_wid(int (*next)(void), void (*back)(int));
-void out_line(char *s);	/* output the given rendered line */
+void out_line(char *s);		/* output the given rendered line */
 int out_draw(char *s, char *cc);
-void out(char *s, ...);	/* output troff cmd */
-/* drawing lines */
-void ren_hline(struct adj *adj, char *arg);
-void ren_vline(struct adj *adj, char *arg);
+void out(char *s, ...);				/* output troff cmd */
+void ren_hline(struct adj *adj, char *arg);	/* horizontal line */
+void ren_vline(struct adj *adj, char *arg);	/* vertical line */
 
 /* troff commands */
 void tr_bp(char **args);