ref: 7e51746ad98afe340fb62e9ea196d77414401fd7
parent: 8b5fcf6aa4de48b8d5f2e75da580a4556277c1cf
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Jul 6 21:01:29 EDT 2013
tr: long register/macro names and named environments
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@
all: roff
%.o: %.c roff.h
$(CC) -c $(CFLAGS) $<
-roff: roff.o dev.o font.o in.o cp.o tr.o ren.o out.o reg.o sbuf.o adj.o eval.o draw.o wb.o hyph.o
+roff: roff.o dev.o font.o in.o cp.o tr.o ren.o out.o reg.o sbuf.o adj.o eval.o draw.o wb.o hyph.o map.o
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -f *.o roff
--- a/cp.c
+++ b/cp.c
@@ -10,6 +10,8 @@
static int regid(void)
{
+ char key[NMLEN];
+ int i = 0;
int c1;
int c2 = 0;
c1 = cp_next();
@@ -16,6 +18,14 @@
if (c1 == '(') {
c1 = cp_next();
c2 = cp_next();
+ } else if (!n_cp && c1 == '[') {
+ c1 = cp_next();
+ while (i < NMLEN - 1 && c1 >= 0 && c1 != ']') {
+ key[i++] = c1;
+ c1 = cp_next();
+ }
+ key[i] = '\0';
+ return map(key);
}
return REG(c1, c2);
}
--- /dev/null
+++ b/map.c
@@ -1,0 +1,31 @@
+#include <stdio.h>
+#include <string.h>
+#include "roff.h"
+
+static char keys[NREGS][GNLEN];
+static int nkeys;
+
+/* map register names to [0..NREGS * 2) */
+int map(char *s)
+{
+ int i;
+ if (n_cp || !s[1] || !s[2])
+ return REG(s[0], s[1]);
+ for (i = 0; i < nkeys; i++)
+ if (keys[i][0] == s[0] && !strcmp(keys[i], s))
+ return NREGS + i;
+ strcpy(keys[nkeys++], s);
+ return NREGS + nkeys - 1;
+}
+
+/* returns a static buffer */
+char *map_name(int id)
+{
+ static char map_buf[NMLEN];
+ if (id >= NREGS)
+ return keys[id - NREGS];
+ map_buf[0] = (id >> 8) & 0xff;
+ map_buf[1] = id & 0xff;
+ map_buf[2] = '\0';
+ return map_buf;
+}
--- a/out.c
+++ b/out.c
@@ -92,6 +92,12 @@
s++;
*d++ = *s++;
*d++ = *s++;
+ } else if (!n_cp && *s == '[') {
+ s++;
+ while (*s && *s != ']')
+ *d++ = *s++;
+ if (*s == ']')
+ s++;
} else {
*d++ = *s++;
if (cmd == 's' && s[-1] >= '1' && s[-1] <= '3')
@@ -170,6 +176,7 @@
*/
int out_readc(char **s, char *d)
{
+ char *r = d;
if (!**s)
return -1;
utf8read(s, d);
@@ -178,6 +185,11 @@
if (d[1] == '(') {
utf8read(s, d);
utf8read(s, d + strlen(d));
+ } else if (!n_cp && d[1] == '[') {
+ while (**s && **s != ']')
+ *r++ = *(*s)++;
+ if (**s == ']')
+ (*s)++;
} else if (strchr("CDfhsvXx", d[1])) {
int c = d[1];
escarg(s, d, d[1]);
--- a/reg.c
+++ b/reg.c
@@ -6,8 +6,7 @@
#include <time.h>
#include "roff.h"
-#define NREGS (1 << 16)
-#define NENVS (1 << 5)
+#define NENVS 32 /* number of environment registers */
struct env {
int eregs[NENVS]; /* environment-specific number registers */
@@ -16,13 +15,14 @@
char hc[GNLEN]; /* hyphenation character */
};
-static int nregs[NREGS]; /* global number registers */
-static int nregs_inc[NREGS]; /* number register auto-increment size */
-static int nregs_fmt[NREGS]; /* number register format */
-static char *sregs[NREGS]; /* global string registers */
-static void *sregs_dat[NREGS]; /* builtin function data */
-static struct env envs[3]; /* environments */
+static int nregs[NREGS2]; /* global number registers */
+static int nregs_inc[NREGS2]; /* number register auto-increment size */
+static int nregs_fmt[NREGS2]; /* number register format */
+static char *sregs[NREGS2]; /* global string registers */
+static void *sregs_dat[NREGS2]; /* builtin function data */
+static struct env *envs[NREGS2];/* environments */
static struct env *env; /* current enviroment */
+static int env_id; /* current environment id */
static int eregs_idx[NREGS]; /* register environment index in eregs[] */
static int eregs[] = { /* environment-specific number registers */
@@ -55,13 +55,6 @@
return &nregs[id];
}
-static void reg_name(char *s, int id)
-{
- s[0] = (id >> 8) & 0xff;
- s[1] = id & 0xff;
- s[3] = '\0';
-}
-
static int num_fmt(char *s, int n, int fmt);
/* the contents of a number register (returns a static buffer) */
@@ -78,7 +71,7 @@
break;
case REG('.', 'z'):
if (f_divreg() >= 0)
- reg_name(numbuf, f_divreg());
+ sprintf(numbuf, "%s", map_name(f_divreg()));
break;
case REG('.', 'F'):
sprintf(numbuf, "%s", in_filename());
@@ -162,12 +155,28 @@
sregs_dat[src] = NULL;
}
+static struct env *env_alloc(void)
+{
+ struct env *env = malloc(sizeof(*env));
+ memset(env, 0, sizeof(*env));
+ env->adj = adj_alloc();
+ return env;
+}
+
+static void env_free(struct env *env)
+{
+ adj_free(env->adj);
+ free(env);
+}
+
static void env_set(int id)
{
int i;
- env = &envs[id];
- if (!env->adj) {
- env->adj = adj_alloc();
+ env = envs[id];
+ env_id = id;
+ if (!env) {
+ envs[id] = env_alloc();
+ env = envs[id];
n_f = 1;
n_i = 0;
n_j = AD_B;
@@ -208,12 +217,12 @@
env_set(0);
}
-void env_free(void)
+void env_done(void)
{
int i;
for (i = 0; i < LEN(envs); i++)
- if (envs[i].adj)
- adj_free(envs[i].adj);
+ if (envs[i])
+ env_free(envs[i]);
}
static int oenv[NPREV]; /* environment stack */
@@ -221,13 +230,15 @@
void tr_ev(char **args)
{
- int id = args[1] ? atoi(args[1]) : -1;
- if (id < 0 && nenv)
- id = oenv[--nenv];
- if (id >= LEN(envs) || id < 0)
+ int id = -1;
+ if (args[1])
+ id = map(args[1]);
+ else
+ id = nenv ? oenv[--nenv] : -1;
+ if (id < 0)
return;
if (args[1] && env && nenv < NPREV)
- oenv[nenv++] = env - envs;
+ oenv[nenv++] = env_id;
env_set(id);
}
--- a/ren.c
+++ b/ren.c
@@ -56,7 +56,7 @@
cdiv = cdiv ? cdiv + 1 : divs;
memset(cdiv, 0, sizeof(*cdiv));
sbuf_init(&cdiv->sbuf);
- cdiv->reg = REG(args[1][0], args[1][1]);
+ cdiv->reg = map(args[1]);
cdiv->treg = -1;
if (args[0][2] == 'a' && str_get(cdiv->reg)) /* .da */
sbuf_append(&cdiv->sbuf, str_get(cdiv->reg));
@@ -323,7 +323,7 @@
void tr_mk(char **args)
{
if (args[1])
- num_set(REG(args[1][0], args[1][1]), n_d);
+ num_set(map(args[1]), n_d);
else
n_mk = n_d;
}
@@ -498,6 +498,12 @@
if (c == '(') {
*d++ = next();
*d++ = next();
+ } else if (!n_cp && c == '[') {
+ c = next();
+ while (c > 0 && c != '\n' && c != ']') {
+ *d++ = c;
+ c = next();
+ }
} else {
*d++ = c;
if (cmd == 's' && c >= '1' && c <= '3') {
@@ -560,8 +566,7 @@
wb_hmov(wb, eval(arg, 'm'));
break;
case 'k':
- num_set(REG(arg[0], arg[1]),
- RENWB(wb) ? f_hpos() - n_lb : wb_wid(wb));
+ num_set(map(arg), RENWB(wb) ? f_hpos() - n_lb : wb_wid(wb));
break;
case 'L':
ren_vline(wb, arg);
@@ -621,7 +626,7 @@
char c[GNLEN * 4];
char arg[ILNLEN];
char *s;
- int w, n;
+ int w, n, l;
nextchar(c, next);
if (c[0] == ' ' || c[0] == '\n') {
wb_put(wb, c);
@@ -639,9 +644,17 @@
if (c[0] == c_ec) {
nextchar(c + 1, next);
if (c[1] == '(') {
- int l = nextchar(c + 2, next);
+ l = nextchar(c + 2, next);
l += nextchar(c + 2 + l, next);
c[2 + l] = '\0';
+ } else if (!n_cp && c[1] == '[') {
+ l = 0;
+ n = next();
+ while (n >= 0 && n != '\n' && n != ']' && l < GNLEN - 1) {
+ c[l++] = n;
+ n = next();
+ }
+ c[l] = '\0';
} else if (c[1] == 'z') {
w = wb_wid(wb);
ren_char(wb, next, back);
@@ -898,7 +911,7 @@
treg[id] = -1;
return;
}
- reg = REG(args[2][0], args[2][1]);
+ reg = map(args[2]);
if (id < 0)
id = trap_byreg(-1);
if (id < 0)
@@ -913,7 +926,7 @@
int id;
if (!args[1])
return;
- reg = REG(args[1][0], args[1][1]);
+ reg = map(args[1]);
id = trap_byreg(reg);
if (id >= 0)
tpos[id] = args[2] ? eval(args[2], 'v') : -1;
@@ -925,7 +938,7 @@
return;
if (args[2]) {
cdiv->tpos = eval(args[1], 'v');
- cdiv->treg = REG(args[2][0], args[2][1]);
+ cdiv->treg = map(args[2]);
} else {
cdiv->treg = -1;
}
@@ -933,7 +946,7 @@
void tr_em(char **args)
{
- trap_em = args[1] ? REG(args[1][0], args[1][1]) : -1;
+ trap_em = args[1] ? map(args[1]) : -1;
}
static int trap_pos(int pos)
--- a/roff.c
+++ b/roff.c
@@ -45,6 +45,8 @@
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-' || !argv[i][0])
break;
+ if (argv[i][1] == 'C')
+ n_cp = 1;
if (argv[i][1] == 'm') {
sprintf(path, TROFFROOT "/tmac/tmac.%s", argv[i] + 2);
in_queue(path);
@@ -56,7 +58,7 @@
in_queue(!strcmp("-", argv[i]) ? NULL : argv[i]);
str_set(REG('.', 'P'), TROFFROOT);
compile();
- env_free();
+ env_done();
dev_close();
return 0;
}
--- a/roff.h
+++ b/roff.h
@@ -13,12 +13,13 @@
#define NKERNS 128 /* number of font pairwise kerning pairs */
#define FNLEN 32 /* font name length */
#define NGLYPHS 512 /* glyphs in fonts */
-#define GNLEN 32 /* glyph name length */
+#define NMLEN 32 /* macro/register/environment/glyph name length */
+#define GNLEN NMLEN /* glyph name length */
+#define RNLEN NMLEN /* register/macro name */
#define ILNLEN 1000 /* line limit of input files */
#define LNLEN 4000 /* line buffer length (ren.c/out.c) */
#define NWORDS 256 /* number of words in line buffer */
#define NARGS 9 /* number of macro arguments */
-#define RLEN 4 /* register/macro name */
#define NPREV 16 /* environment stack depth */
#define NTRAPS 1024 /* number of traps per page */
#define NIES 128 /* number of nested .ie commands */
@@ -54,6 +55,10 @@
int eval_up(char **s, int unit);
int eval_re(char *s, int orig, int unit);
+/* mapping register, macro and environment names to numbers */
+int map(char *s);
+char *map_name(int id);
+
/* string registers */
void str_set(int id, char *s);
void str_dset(int id, void *d);
@@ -68,7 +73,7 @@
/* enviroments */
void env_init(void);
-void env_free(void);
+void env_done(void);
struct adj *env_adj(void);
char *env_hc(void);
int tab_next(int pos);
@@ -298,9 +303,14 @@
#define TR_DIVEND "\07>" /* diversion ends */
#define TR_EJECT "\07P" /* page eject */
-/* builtin number registers; n_X for .X register */
+/* register mapping */
+#define NREGS (1 << 16)
+#define NREGS2 (NREGS * 2)
#define REG(c1, c2) ((c1) * 256 + (c2))
+
+/* builtin number registers; n_X for .X register */
#define n_a (*nreg(REG('.', 'a')))
+#define n_cp (*nreg(REG('.', 'C')))
#define n_d (*nreg(REG('.', 'd')))
#define n_f (*nreg(REG('.', 'f')))
#define n_h (*nreg(REG('.', 'h')))
--- a/tr.c
+++ b/tr.c
@@ -44,7 +44,7 @@
int id;
if (!args[2])
return;
- id = REG(args[1][0], args[1][1]);
+ id = map(args[1]);
num_set(id, eval_re(args[2], num_get(id, 0), 'u'));
num_inc(id, args[3] ? eval(args[3], 'u') : 0);
}
@@ -54,19 +54,19 @@
int i;
for (i = 1; i <= NARGS; i++)
if (args[i])
- num_del(REG(args[i][0], args[i][1]));
+ num_del(map(args[i]));
}
static void tr_af(char **args)
{
if (args[2])
- num_setfmt(REG(args[1][0], args[1][1]), args[2]);
+ num_setfmt(map(args[1]), args[2]);
}
static void tr_ds(char **args)
{
if (args[2])
- str_set(REG(args[1][0], args[1][1]), args[2]);
+ str_set(map(args[1]), args[2]);
}
static void tr_as(char **args)
@@ -75,7 +75,7 @@
char *s1, *s2, *s;
if (!args[2])
return;
- reg = REG(args[1][0], args[1][1]);
+ reg = map(args[1]);
s1 = str_get(reg) ? str_get(reg) : "";
s2 = args[2];
s = malloc(strlen(s1) + strlen(s2) + 1);
@@ -90,7 +90,7 @@
int i;
for (i = 1; i <= NARGS; i++)
if (args[i])
- str_rm(REG(args[i][0], args[i][1]));
+ str_rm(map(args[i]));
}
static void tr_rn(char **args)
@@ -97,7 +97,7 @@
{
if (!args[2])
return;
- str_rn(REG(args[1][0], args[1][1]), REG(args[2][0], args[2][1]));
+ str_rn(map(args[1]), map(args[2]));
}
static void tr_po(char **args)
@@ -111,7 +111,7 @@
static void macrobody(struct sbuf *sbuf, char *end)
{
- char buf[4];
+ char buf[NMLEN];
int i, c;
int first = 1;
cp_back('\n');
@@ -123,8 +123,9 @@
if (c == '\n') {
c = cp_next();
if (c == '.') {
- arg_regname(buf, 4);
- if (buf[0] == end[0] && buf[1] == end[1]) {
+ arg_regname(buf, sizeof(buf));
+ if ((n_cp && end[0] == buf[0] && end[1] == buf[1]) ||
+ !strcmp(end, buf)) {
jmp_eol();
break;
}
@@ -148,7 +149,7 @@
int id;
if (!args[1])
return;
- id = REG(args[1][0], args[1][1]);
+ id = map(args[1]);
sbuf_init(&sbuf);
if (args[0][1] == 'a' && args[0][2] == 'm' && str_get(id))
sbuf_append(&sbuf, str_get(id));
@@ -428,9 +429,15 @@
n_kn = atoi(args[1]);
}
+static void tr_cp(char **args)
+{
+ if (args[1])
+ n_cp = atoi(args[1]);
+}
+
static char *arg_regname(char *s, int len)
{
- char *e = s + 2;
+ char *e = n_cp ? s + 2 : s + len;
int c = cp_next();
while (c == ' ' || c == '\t')
c = cp_next();
@@ -608,6 +615,7 @@
{"cc", tr_cc},
{"ce", tr_ce},
{"ch", tr_ch},
+ {"cp", tr_cp},
{"da", tr_di},
{"de", tr_de, mkargs_reg1},
{"di", tr_di},
@@ -670,7 +678,7 @@
int c = cp_next();
int nl = c == '\n';
char *args[NARGS + 3] = {NULL};
- char cmd[RLEN];
+ char cmd[RNLEN];
char buf[LNLEN];
struct cmd *req;
while (tr_nl && c >= 0 && (c == c_cc || c == c_c2)) {
@@ -680,7 +688,7 @@
cmd[0] = c;
req = NULL;
arg_regname(cmd + 1, sizeof(cmd) - 1);
- req = str_dget(REG(cmd[1], cmd[2]));
+ req = str_dget(map(cmd + 1));
if (req) {
if (req->args)
req->args(args + 1, buf, sizeof(buf));
@@ -691,8 +699,8 @@
cp_wid(0);
mkargs(args + 1, buf, sizeof(buf));
cp_wid(1);
- if (str_get(REG(cmd[1], cmd[2])))
- in_push(str_get(REG(cmd[1], cmd[2])), args + 1);
+ if (str_get(map(cmd + 1)))
+ in_push(str_get(map(cmd + 1)), args + 1);
}
c = cp_next();
nl = c == '\n';
@@ -705,7 +713,7 @@
{
int i;
for (i = 0; i < LEN(cmds); i++)
- str_dset(REG(cmds[i].id[0], cmds[i].id[1]), &cmds[i]);
+ str_dset(map(cmds[i].id), &cmds[i]);
}
void tr_first(void)