shithub: neatroff

Download patch

ref: 18649e6f7e158970eb43d7b212c747ae1a46b633
parent: efed3e9037a152731d9f2ef9d51e4e9a8aa20edd
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sun Jun 7 12:27:52 EDT 2015

cp: quoted brackets as in \*[xyz "]"]

--- a/cp.c
+++ b/cp.c
@@ -17,7 +17,8 @@
 	return c;
 }
 
-static void cparg(char *d, int len)
+/* return 1 if \*[] includes a space */
+static int cparg(char *d, int len)
 {
 	int c = cp_noninext();
 	int i = 0;
@@ -26,15 +27,18 @@
 		i += utf8next(d + i, cp_noninext);
 	} else if (!n_cp && c == '[') {
 		c = cp_noninext();
-		while (i < len - 1 && c >= 0 && c != ']') {
-			d[i++] = c;
+		while (c >= 0 && c != ']' && c != ' ') {
+			if (i + 1 < len)
+				d[i++] = c;
 			c = cp_noninext();
 		}
 		d[i] = '\0';
+		return c == ' ';
 	} else {
 		cp_back(c);
 		utf8next(d, cp_noninext);
 	}
+	return 0;
 }
 
 static int regid(void)
@@ -61,23 +65,17 @@
 /* interpolate \*(xy */
 static void cp_str(void)
 {
-	char arg[ILNLEN];
-	struct sbuf sbuf;
+	char reg[NMLEN];
 	char *args[NARGS + 1] = {NULL};
-	cparg(arg, sizeof(arg));
-	if (strchr(arg, ' ')) {
-		sbuf_init(&sbuf);
-		sstr_push(strchr(arg, ' ') + 1);
-		tr_argsread(&sbuf, sstr_next, sstr_back);
-		tr_argschop(&sbuf, args);
-		sstr_pop();
-		*strchr(arg, ' ') = '\0';
-		if (str_get(map(arg)))
-			in_push(str_get(map(arg)), args);
-		sbuf_done(&sbuf);
+	if (cparg(reg, sizeof(reg))) {
+		char *buf = tr_args(args, ']', cp_noninext, cp_back);
+		cp_noninext();
+		if (str_get(map(reg)))
+			in_push(str_get(map(reg)), args);
+		free(buf);
 	} else {
-		if (str_get(map(arg)))
-			in_push(str_get(map(arg)), NULL);
+		if (str_get(map(reg)))
+			in_push(str_get(map(reg)), NULL);
 	}
 }
 
--- a/roff.h
+++ b/roff.h
@@ -378,8 +378,8 @@
 
 void tr_init(void);
 void tr_done(void);
-void tr_argsread(struct sbuf *sbuf, int (*next)(void), void (*back)(int));
-int tr_argschop(struct sbuf *sbuf, char **args);
+
+char *tr_args(char **args, int brk, int (*next)(void), void (*back)(int));
 
 /* helpers */
 void errmsg(char *msg, ...);
--- a/tr.c
+++ b/tr.c
@@ -832,7 +832,8 @@
 		cp_back(c);
 }
 
-static int mkargs_arg(struct sbuf *sbuf, int (*next)(void), void (*back)(int))
+/* read a macro argument */
+static int tr_arg(struct sbuf *sbuf, int brk, int (*next)(void), void (*back)(int))
 {
 	int quoted = 0;
 	int c;
@@ -839,15 +840,15 @@
 	c = next();
 	while (c == ' ')
 		c = next();
-	if (c == '\n')
+	if (c == '\n' || c == brk)
 		back(c);
-	if (c < 0 || c == '\n')
+	if (c < 0 || c == '\n' || c == brk)
 		return 1;
 	if (c == '"') {
 		quoted = 1;
 		c = next();
 	}
-	while (c >= 0 && c != '\n') {
+	while (c >= 0 && c != '\n' && c != brk) {
 		if (!quoted && c == ' ')
 			break;
 		if (quoted && c == '"') {
@@ -868,19 +869,27 @@
 	return 0;
 }
 
-/* read macro arguments */
-void tr_argsread(struct sbuf *sbuf, int (*next)(void), void (*back)(int))
+/* read macro arguments; free the returned pointer when done */
+char *tr_args(char **args, int brk, int (*next)(void), void (*back)(int))
 {
+	struct sbuf sbuf;
+	char *s, *e;
 	int n = 0;
-	while (n < NARGS) {
-		if (mkargs_arg(sbuf, next, back))
-			break;
-		n++;
+	sbuf_init(&sbuf);
+	while (!tr_arg(&sbuf, brk, next, back))
+		;
+	s = sbuf_buf(&sbuf);
+	e = s + sbuf_len(&sbuf);
+	while (n < NARGS && s && s < e) {
+		args[n++] = s;
+		if ((s = memchr(s, '\0', e - s)))
+			s++;
 	}
+	return sbuf_out(&sbuf);
 }
 
 /* split the arguments in sbuf */
-int tr_argschop(struct sbuf *sbuf, char **args)
+static int tr_argschop(struct sbuf *sbuf, char **args)
 {
 	char *s = sbuf_buf(sbuf);
 	char *e = s + sbuf_len(sbuf);
@@ -893,13 +902,6 @@
 	return n;
 }
 
-/* read macro arguments; trims tabs if rmtabs is nonzero */
-static void mkargs(struct sbuf *sbuf)
-{
-	tr_argsread(sbuf, cp_next, cp_back);
-	jmp_eol();
-}
-
 /* read request arguments; trims tabs too */
 static void mkargs_req(struct sbuf *sbuf)
 {
@@ -1124,9 +1126,9 @@
 	req = NULL;
 	cp_reqbeg();
 	read_regname(cmd + 1);
-	sbuf_init(&sbuf);
 	req = str_dget(map(cmd + 1));
 	if (req) {
+		sbuf_init(&sbuf);
 		if (req->args)
 			req->args(&sbuf);
 		else
@@ -1133,15 +1135,17 @@
 			mkargs_req(&sbuf);
 		tr_argschop(&sbuf, args + 1);
 		req->f(args);
+		sbuf_done(&sbuf);
 	} else {
+		char *buf;
 		cp_copymode(1);
-		mkargs(&sbuf);
+		buf = tr_args(args + 1, -1, cp_next, cp_back);
+		jmp_eol();
 		cp_copymode(0);
-		tr_argschop(&sbuf, args + 1);
 		if (str_get(map(cmd + 1)))
 			in_push(str_get(map(cmd + 1)), args + 1);
+		free(buf);
 	}
-	sbuf_done(&sbuf);
 	return 0;
 }