shithub: neatroff

Download patch

ref: 1eadad7e80537cbc584451767a35383c8a47f259
parent: ed1a68194ee61d0a6e2ee6a96189403c6daaea9b
author: Ali Gholami Rudi <[email protected]>
date: Mon Jul 20 04:22:43 EDT 2015

tr: handle long register names more gracefully

Also, the cost of large values of NMLEN is very small.  Thus, its
default value is changed to 128.

--- a/roff.h
+++ b/roff.h
@@ -27,8 +27,8 @@
 #define NFILES		16	/* number of input files */
 #define NFONTS		32	/* number of fonts */
 #define FNLEN		32	/* font name length */
-#define NMLEN		32	/* macro/register/environment/glyph name length */
-#define GNLEN		NMLEN	/* glyph name length */
+#define GNLEN		32	/* glyph name length */
+#define NMLEN		128	/* macro/register/environment name length */
 #define RNLEN		NMLEN	/* register/macro name */
 #define NREGS		8192	/* number of mapped names */
 #define ILNLEN		1000	/* line limit of input files */
--- a/tr.c
+++ b/tr.c
@@ -108,28 +108,55 @@
 	n_o = MAX(0, po);
 }
 
-static void read_regname(char *s)
+/* read a string argument of a macro */
+static char *read_string(void)
 {
+	struct sbuf sbuf;
+	int c;
+	sbuf_init(&sbuf);
+	cp_copymode(1);
+	while ((c = cp_next()) == ' ')
+		;
+	if (c == '"')
+		c = cp_next();
+	while (c > 0 && c != '\n') {
+		if (c != c_ni)
+			sbuf_add(&sbuf, c);
+		c = cp_next();
+	}
+	if (c >= 0)
+		cp_back(c);
+	cp_copymode(0);
+	return sbuf_out(&sbuf);
+}
+
+/* read a register name argument; if two, read at most two characters */
+static char *read_name(int two)
+{
+	struct sbuf sbuf;
 	int c = cp_next();
-	int n = n_cp ? 2 : NMLEN - 1;
+	int i = 0;
+	sbuf_init(&sbuf);
 	while (c == ' ' || c == '\t' || c == c_ni)
 		c = cp_next();
-	while (c >= 0 && c != ' ' && c != '\t' && c != '\n' && --n >= 0) {
-		*s++ = c;
-		do {
-			c = cp_next();
-		} while (n && c == c_ni);
+	while (c > 0 && c != ' ' && c != '\t' && c != '\n' && (!two || i < 2)) {
+		if (c != c_ni) {
+			sbuf_add(&sbuf, c);
+			i++;
+		}
+		c = cp_next();
 	}
 	if (c >= 0)
 		cp_back(c);
-	*s = '\0';
+	return sbuf_out(&sbuf);
 }
 
+
 static void macrobody(struct sbuf *sbuf, char *end)
 {
-	char buf[NMLEN];
-	int i, c;
 	int first = 1;
+	int c;
+	char *req = NULL;
 	cp_back('\n');
 	cp_copymode(1);
 	while ((c = cp_next()) >= 0) {
@@ -137,25 +164,25 @@
 			sbuf_add(sbuf, c);
 		first = 0;
 		if (c == '\n') {
-			if ((c = cp_next()) != '.') {
+			if ((c = cp_next()) != c_cc) {
 				cp_back(c);
 				continue;
 			}
-			read_regname(buf);
-			if ((n_cp && end[0] == buf[0] && end[1] == buf[1]) ||
-						!strcmp(end, buf)) {
-				for (i = strlen(buf) - 1; i >= 0; i--)
-					cp_back((unsigned char) buf[i]);
-				cp_back('.');
+			req = read_name(n_cp);
+			if (!strcmp(end, req)) {
+				in_push(end, NULL);
+				cp_back(c_cc);
 				break;
 			}
 			if (sbuf) {
-				sbuf_add(sbuf, '.');
-				for (i = 0; buf[i]; i++)
-					sbuf_add(sbuf, (unsigned char) buf[i]);
+				sbuf_add(sbuf, c_cc);
+				sbuf_append(sbuf, req);
 			}
+			free(req);
+			req = NULL;
 		}
 	}
+	free(req);
 	cp_copymode(0);
 }
 
@@ -790,48 +817,6 @@
 		font_map(fn, args[2], args[3]);
 }
 
-static void arg_regname(struct sbuf *sbuf)
-{
-	char reg[NMLEN];
-	read_regname(reg);
-	sbuf_append(sbuf, reg);
-	sbuf_add(sbuf, 0);
-}
-
-static void arg_string(struct sbuf *sbuf)
-{
-	int c;
-	cp_copymode(1);
-	while ((c = cp_next()) == ' ')
-		;
-	if (c == '"')
-		c = cp_next();
-	while (c > 0 && c != '\n') {
-		if (c != c_ni)
-			sbuf_add(sbuf, c);
-		c = cp_next();
-	}
-	sbuf_add(sbuf, 0);
-	if (c >= 0)
-		cp_back(c);
-	cp_copymode(0);
-}
-
-static void arg_name(struct sbuf *sbuf)
-{
-	int c;
-	while ((c = cp_next()) == ' ')
-		;
-	while (c > 0 && c != ' ' && c != '\t' && c != '\n') {
-		if (c != c_ni)
-			sbuf_add(sbuf, c);
-		c = cp_next();
-	}
-	sbuf_add(sbuf, 0);
-	if (c >= 0)
-		cp_back(c);
-}
-
 /* read a macro argument */
 static int tr_arg(struct sbuf *sbuf, int brk, int (*next)(void), void (*back)(int))
 {
@@ -933,8 +918,14 @@
 /* read arguments for .ds */
 static void mkargs_ds(struct sbuf *sbuf)
 {
-	arg_regname(sbuf);
-	arg_string(sbuf);
+	char *s = read_name(n_cp);
+	sbuf_append(sbuf, s);
+	sbuf_add(sbuf, 0);
+	free(s);
+	s = read_string();
+	sbuf_append(sbuf, s);
+	sbuf_add(sbuf, 0);
+	free(s);
 	jmp_eol();
 }
 
@@ -941,8 +932,14 @@
 /* read arguments for .char */
 static void mkargs_def(struct sbuf *sbuf)
 {
-	arg_name(sbuf);
-	arg_string(sbuf);
+	char *s = read_name(0);
+	sbuf_append(sbuf, s);
+	sbuf_add(sbuf, 0);
+	free(s);
+	s = read_string();
+	sbuf_append(sbuf, s);
+	sbuf_add(sbuf, 0);
+	free(s);
 	jmp_eol();
 }
 
@@ -949,7 +946,10 @@
 /* read arguments for .ochar */
 static void mkargs_def3(struct sbuf *sbuf)
 {
-	arg_name(sbuf);
+	char *s = read_name(0);
+	sbuf_append(sbuf, s);
+	sbuf_add(sbuf, 0);
+	free(s);
 	mkargs_def(sbuf);
 }
 
@@ -956,7 +956,10 @@
 /* read arguments for .nr */
 static void mkargs_reg1(struct sbuf *sbuf)
 {
-	arg_regname(sbuf);
+	char *s = read_name(n_cp);
+	sbuf_append(sbuf, s);
+	sbuf_add(sbuf, 0);
+	free(s);
 	mkargs_req(sbuf);
 }
 
@@ -1091,11 +1094,19 @@
 	{"wh", tr_wh},
 };
 
+static char *dotted(char *name, int dot)
+{
+	char *out = xmalloc(strlen(name) + 2);
+	out[0] = dot;
+	strcpy(out + 1, name);
+	return out;
+}
+
 /* read the next troff request; return zero if a request was executed. */
 int tr_nextreq(void)
 {
 	char *args[NARGS + 3] = {NULL};
-	char cmd[RNLEN + 1];
+	char *cmd;
 	struct cmd *req;
 	struct sbuf sbuf;
 	int c;
@@ -1121,12 +1132,10 @@
 		cp_back(c);
 		return 1;
 	}
-	args[0] = cmd;
-	cmd[0] = c;
-	req = NULL;
 	cp_reqbeg();
-	read_regname(cmd + 1);
-	req = str_dget(map(cmd + 1));
+	cmd = read_name(n_cp);
+	args[0] = dotted(cmd, c);
+	req = str_dget(map(cmd));
 	if (req) {
 		sbuf_init(&sbuf);
 		if (req->args)
@@ -1142,10 +1151,12 @@
 		buf = tr_args(args + 1, -1, cp_next, cp_back);
 		jmp_eol();
 		cp_copymode(0);
-		if (str_get(map(cmd + 1)))
-			in_push(str_get(map(cmd + 1)), args + 1);
+		if (str_get(map(cmd)))
+			in_push(str_get(map(cmd)), args + 1);
 		free(buf);
 	}
+	free(args[0]);
+	free(cmd);
 	return 0;
 }