ref: d3d6cc88b2ccbe251436b60dd37af3915ee0c420
parent: 03c073b4ef687a6aa5a5d66f58a9c2ed467db19d
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Feb 7 05:24:25 EST 2015
tr: read macro arguments into an sbuf struct
--- a/cp.c
+++ b/cp.c
@@ -63,12 +63,13 @@
{
char arg[ILNLEN];
struct sbuf sbuf;
- char *args[NARGS] = {NULL};
+ char *args[NARGS + 1] = {NULL};
cparg(arg, sizeof(arg));
if (strchr(arg, ' ')) {
sbuf_init(&sbuf);
sstr_push(strchr(arg, ' ') + 1);
- tr_readargs(args, &sbuf, sstr_next, sstr_back);
+ tr_argsread(&sbuf, sstr_next, sstr_back);
+ tr_argschop(&sbuf, args);
sstr_pop();
*strchr(arg, ' ') = '\0';
if (str_get(map(arg)))
--- a/roff.h
+++ b/roff.h
@@ -376,8 +376,8 @@
void tr_init(void);
void tr_done(void);
-int tr_readargs(char **args, struct sbuf *sbuf,
- int (*next)(void), void (*back)(int));
+void tr_argsread(struct sbuf *sbuf, int (*next)(void), void (*back)(int));
+int tr_argschop(struct sbuf *sbuf, char **args);
/* helpers */
void errmsg(char *msg, ...);
--- a/tr.c
+++ b/tr.c
@@ -801,6 +801,7 @@
static void arg_string(struct sbuf *sbuf)
{
int c;
+ cp_copymode(1);
while ((c = cp_next()) == ' ')
;
if (c == '"')
@@ -813,8 +814,24 @@
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);
+}
+
static int mkargs_arg(struct sbuf *sbuf, int (*next)(void), void (*back)(int))
{
int quoted = 0;
@@ -852,38 +869,45 @@
}
/* read macro arguments */
-int tr_readargs(char **args, struct sbuf *sbuf, int (*next)(void), void (*back)(int))
+void tr_argsread(struct sbuf *sbuf, int (*next)(void), void (*back)(int))
{
- int idx[NARGS];
- int i, n = 0;
+ int n = 0;
while (n < NARGS) {
- idx[n] = sbuf_len(sbuf);
if (mkargs_arg(sbuf, next, back))
break;
n++;
}
- for (i = 0; i < n; i++)
- args[i] = sbuf_buf(sbuf) + idx[i];
+}
+
+/* split the arguments in sbuf */
+int tr_argschop(struct sbuf *sbuf, char **args)
+{
+ char *s = sbuf_buf(sbuf);
+ char *e = s + sbuf_len(sbuf);
+ int n = 0;
+ while (n < NARGS && s && s < e) {
+ args[n++] = s;
+ if ((s = memchr(s, '\0', e - s)))
+ s++;
+ }
return n;
}
/* read macro arguments; trims tabs if rmtabs is nonzero */
-static int mkargs(char **args, struct sbuf *sbuf)
+static void mkargs(struct sbuf *sbuf)
{
- int n = tr_readargs(args, sbuf, cp_next, cp_back);
+ tr_argsread(sbuf, cp_next, cp_back);
jmp_eol();
- return n;
}
/* read request arguments; trims tabs too */
-static int mkargs_req(char **args, struct sbuf *sbuf)
+static void mkargs_req(struct sbuf *sbuf)
{
- int idx[NARGS];
- int i, n = 0;
+ int n = 0;
int c;
c = cp_next();
while (n < NARGS) {
- idx[n] = sbuf_len(sbuf);
+ int ok = 0;
while (c == ' ' || c == '\t')
c = cp_next();
while (c >= 0 && c != '\n' && c != ' ' && c != '\t') {
@@ -890,59 +914,58 @@
if (c != c_ni)
sbuf_add(sbuf, c);
c = cp_next();
+ ok = 1;
}
- if (sbuf_len(sbuf) > idx[n])
+ if (ok) {
n++;
- sbuf_add(sbuf, 0);
+ sbuf_add(sbuf, 0);
+ }
if (c == '\n')
cp_back(c);
if (c < 0 || c == '\n')
break;
}
- for (i = 0; i < n; i++)
- args[i] = sbuf_buf(sbuf) + idx[i];
jmp_eol();
- return n;
}
/* read arguments for .ds */
-static int mkargs_ds(char **args, struct sbuf *sbuf)
+static void mkargs_ds(struct sbuf *sbuf)
{
- int idx[NARGS];
- int i, n = 0;
- idx[n++] = sbuf_len(sbuf);
arg_regname(sbuf);
- idx[n++] = sbuf_len(sbuf);
- cp_copymode(1);
arg_string(sbuf);
- cp_copymode(0);
jmp_eol();
- for (i = 0; i < n; i++)
- args[i] = sbuf_buf(sbuf) + idx[i];
- return n;
}
-/* read arguments for commands .nr that expect a register name */
-static int mkargs_reg1(char **args, struct sbuf *sbuf)
+/* read arguments for .char */
+static void mkargs_def(struct sbuf *sbuf)
{
- int n;
- int idx0 = sbuf_len(sbuf);
+ arg_name(sbuf);
+ arg_string(sbuf);
+ jmp_eol();
+}
+
+/* read arguments for .ochar */
+static void mkargs_def3(struct sbuf *sbuf)
+{
+ arg_name(sbuf);
+ mkargs_def(sbuf);
+}
+
+/* read arguments for .nr */
+static void mkargs_reg1(struct sbuf *sbuf)
+{
arg_regname(sbuf);
- n = mkargs_req(args + 1, sbuf) + 1;
- args[0] = sbuf_buf(sbuf) + idx0;
- return n;
+ mkargs_req(sbuf);
}
-/* do not read arguments; for .if, .ie and .el */
-static int mkargs_null(char **args, struct sbuf *sbuf)
+/* do not read any arguments; for .if, .ie and .el */
+static void mkargs_null(struct sbuf *sbuf)
{
- return 0;
}
/* read the whole line for .tm */
-static int mkargs_eol(char **args, struct sbuf *sbuf)
+static void mkargs_eol(struct sbuf *sbuf)
{
- int idx0 = sbuf_len(sbuf);
int c;
cp_copymode(1);
c = cp_next();
@@ -954,14 +977,12 @@
c = cp_next();
}
cp_copymode(0);
- args[0] = sbuf_buf(sbuf) + idx0;
- return 1;
}
static struct cmd {
char *id;
void (*f)(char **args);
- int (*args)(char **args, struct sbuf *sbuf);
+ void (*args)(struct sbuf *sbuf);
} cmds[] = {
{TR_DIVBEG, tr_divbeg},
{TR_DIVEND, tr_divend},
@@ -977,10 +998,10 @@
{"br", tr_br},
{"c2", tr_c2},
{"cc", tr_cc},
- {"ochar", tr_ochar},
+ {"ochar", tr_ochar, mkargs_def3},
{"ce", tr_ce},
{"ch", tr_ch},
- {"char", tr_char, mkargs_ds},
+ {"char", tr_char, mkargs_def},
{"chop", tr_chop, mkargs_reg1},
{"cl", tr_cl},
{"cp", tr_cp},
@@ -1046,7 +1067,7 @@
{"pn", tr_pn},
{"po", tr_po},
{"ps", tr_ps},
- {"rchar", tr_rchar, mkargs_ds},
+ {"rchar", tr_rchar},
{"rm", tr_rm},
{"rn", tr_rn},
{"rr", tr_rr},
@@ -1085,8 +1106,9 @@
args[0] = "\\!";
sbuf_init(&sbuf);
cp_copymode(1);
- mkargs_eol(args + 1, &sbuf);
+ mkargs_eol(&sbuf);
cp_copymode(0);
+ tr_argschop(&sbuf, args + 1);
tr_transparent(args);
sbuf_done(&sbuf);
return 0;
@@ -1097,7 +1119,6 @@
cp_back(c);
return 1;
}
- memset(args, 0, sizeof(args));
args[0] = cmd;
cmd[0] = c;
req = NULL;
@@ -1107,14 +1128,16 @@
req = str_dget(map(cmd + 1));
if (req) {
if (req->args)
- req->args(args + 1, &sbuf);
+ req->args(&sbuf);
else
- mkargs_req(args + 1, &sbuf);
+ mkargs_req(&sbuf);
+ tr_argschop(&sbuf, args + 1);
req->f(args);
} else {
cp_copymode(1);
- mkargs(args + 1, &sbuf);
+ mkargs(&sbuf);
cp_copymode(0);
+ tr_argschop(&sbuf, args + 1);
if (str_get(map(cmd + 1)))
in_push(str_get(map(cmd + 1)), args + 1);
}