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;
}