ref: e09893889703797eb671aa56f59e109da1caa569
parent: cb39077a4a8e2be1b11b02c0f3f93730f8de4658
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sun Oct 13 13:08:11 EDT 2013
map: more compact mapping of register names Now only ".x" built-in style names have predefined indices.
--- a/map.c
+++ b/map.c
@@ -2,7 +2,9 @@
#include <string.h>
#include "roff.h"
-/* register, macro, or environments names with more than two characters */
+#define MAPBEG 256 /* the entries reserved for .x names */
+
+/* register, macro, or environments names */
static char keys[NREGS][GNLEN];
static int nkeys = 1;
/* per starting character name lists */
@@ -14,11 +16,15 @@
{
int head = (unsigned char) s[0];
int i = key_head[head];
+ if (*s == '\0')
+ return 0;
while (i > 0) {
- if (!strcmp(keys[i], s))
+ if (keys[i][1] == s[1] && !strcmp(keys[i], s))
return i;
i = key_next[i];
}
+ if (nkeys >= NREGS - MAPBEG)
+ errdie("neatroff: out of register names (NREGS)\n");
i = nkeys++;
strcpy(keys[i], s);
key_next[i] = key_head[head];
@@ -26,22 +32,22 @@
return i;
}
-/* map register names to [0..NREGS * 2) */
+/* map register names to [0..NREGS] */
int map(char *s)
{
- if (n_cp || !s[1] || !s[2])
- return REG(s[0], s[1]);
- return NREGS + key_get(s);
+ if (s[0] == '.' && s[1] && !s[2]) /* ".x" is mapped to 'x' */
+ return (unsigned char) s[1];
+ return MAPBEG + key_get(s);
}
-/* returns a static buffer */
+/* return the name mapped to id; 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;
+ if (id >= MAPBEG)
+ return keys[id - MAPBEG];
+ map_buf[0] = '.';
+ map_buf[1] = id;
map_buf[2] = '\0';
return map_buf;
}
--- a/reg.c
+++ b/reg.c
@@ -19,15 +19,15 @@
char mc[GNLEN]; /* margin character (.mc) */
};
-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 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[NREGS];/* environments */
static struct env *env; /* current enviroment */
static int env_id; /* current environment id */
-static int eregs_idx[NREGS2]; /* register environment index in eregs[] */
+static int eregs_idx[NREGS]; /* register environment index in eregs[] */
static char *eregs[] = { /* environment-specific number registers */
"ln", ".f", ".i", ".j", ".l",
@@ -34,9 +34,9 @@
".L", ".nI", ".nm", ".nM", ".nn",
".nS", ".m", ".s", ".u", ".v",
".it", ".itn", ".mc", ".mcn",
- "\0c", "\0f", "\0h", "\0i", "\0l",
- "\0L", "\0n", "\0m", "\0p", "\0s",
- "\0t", "\0T", "\0v",
+ ".ce", ".f0", ".hy", ".i0", ".l0",
+ ".L0", ".m0", ".n0", ".s0", ".ss",
+ ".lt", ".lt0", ".v0",
};
/* return the address of a number register */
@@ -53,40 +53,43 @@
char *num_str(int id)
{
static char numbuf[128];
+ char *s = map_name(id);
numbuf[0] = '\0';
- switch (id) {
- case REG('.', 'b'):
- sprintf(numbuf, "%d", dev_getbd(n_f));
- break;
- case REG('.', 'c'):
- sprintf(numbuf, "%d", in_lnum());
- break;
- case REG('.', 'k'):
- sprintf(numbuf, "%d", f_hpos());
- break;
- case REG('.', 'm'):
- sprintf(numbuf, "#%02x%02x%02x", CLR_R(n_m), CLR_G(n_m), CLR_B(n_m));
- break;
- case REG('.', 't'):
- sprintf(numbuf, "%d", f_nexttrap());
- break;
- case REG('.', 'z'):
- if (f_divreg() >= 0)
- sprintf(numbuf, "%s", map_name(f_divreg()));
- break;
- case REG('.', 'F'):
- sprintf(numbuf, "%s", in_filename());
- break;
- case REG('.', '$'):
- sprintf(numbuf, "%d", in_nargs());
- break;
- case REG('y', 'r'):
+ if (s[0] == '.' && !s[2]) {
+ switch (s[1]) {
+ case 'b':
+ sprintf(numbuf, "%d", dev_getbd(n_f));
+ return numbuf;
+ case 'c':
+ sprintf(numbuf, "%d", in_lnum());
+ return numbuf;
+ case 'k':
+ sprintf(numbuf, "%d", f_hpos());
+ return numbuf;
+ case 'm':
+ sprintf(numbuf, "#%02x%02x%02x", CLR_R(n_m), CLR_G(n_m), CLR_B(n_m));
+ return numbuf;
+ case 't':
+ sprintf(numbuf, "%d", f_nexttrap());
+ return numbuf;
+ case 'z':
+ if (f_divreg() >= 0)
+ sprintf(numbuf, "%s", map_name(f_divreg()));
+ return numbuf;
+ case 'F':
+ sprintf(numbuf, "%s", in_filename());
+ return numbuf;
+ case '$':
+ sprintf(numbuf, "%d", in_nargs());
+ return numbuf;
+ }
+ }
+ if (id == map("yr")) {
sprintf(numbuf, "%02d", nregs[id]);
- break;
- default:
- if (!nregs_fmt[id] || num_fmt(numbuf, *nreg(id), nregs_fmt[id]))
- sprintf(numbuf, "%d", *nreg(id));
+ return numbuf;
}
+ if (!nregs_fmt[id] || num_fmt(numbuf, *nreg(id), nregs_fmt[id]))
+ sprintf(numbuf, "%d", *nreg(id));
return numbuf;
}
@@ -207,10 +210,10 @@
{
time_t t = time(NULL);
struct tm *tm = localtime(&t);
- nregs[REG('d', 'w')] = tm->tm_wday + 1;
- nregs[REG('d', 'y')] = tm->tm_mday;
- nregs[REG('m', 'o')] = tm->tm_mon + 1;
- nregs[REG('y', 'r')] = tm->tm_year % 100;
+ nregs[map("dw")] = tm->tm_wday + 1;
+ nregs[map("dy")] = tm->tm_mday;
+ nregs[map("mo")] = tm->tm_mon + 1;
+ nregs[map("yr")] = tm->tm_year % 100;
}
void env_init(void)
--- a/ren.c
+++ b/ren.c
@@ -306,7 +306,7 @@
wb_done(&wb);
}
-/* return 1 if triggered a trap */
+/* output current line; returns 1 if triggered a trap */
static int ren_bradj(struct adj *adj, int fill, int ad, int body)
{
char cmd[16];
@@ -356,7 +356,7 @@
return 0;
}
-/* return 1 if triggered a trap */
+/* output current line; returns 1 if triggered a trap */
static int ren_br(int force)
{
int ad = n_j;
@@ -900,7 +900,6 @@
int render(void)
{
struct wb *wb = &ren_wb;
- int fillreq;
int c;
n_nl = -1;
wb_init(wb);
@@ -925,14 +924,11 @@
continue;
}
ren_cnl = c == '\n';
- fillreq = 0;
/* add wb (the current word) to cadj */
if (c == ' ' || c == '\n') {
adj_swid(cadj, spacewid(n_f, n_s));
if (!wb_part(wb)) { /* not after a \c */
adj_wb(cadj, wb);
- fillreq = ren_fillreq;
- ren_fillreq = 0;
if (c == '\n')
adj_nl(cadj);
else
@@ -939,9 +935,13 @@
adj_sp(cadj);
}
}
- while ((fillreq && !n_ce && n_u) || adj_full(cadj, !n_ce && n_u)) {
- ren_br(0);
- fillreq = 0;
+ /* flush the line if necessary */
+ if (c == ' ' || c == '\n') {
+ while ((ren_fillreq && !wb_part(wb) && !n_ce && n_u) ||
+ adj_full(cadj, !n_ce && n_u)) {
+ ren_br(0);
+ ren_fillreq = 0;
+ }
}
if (c == '\n' || ren_nl) /* end or start of input line */
n_lb = f_hpos();
--- a/roff.c
+++ b/roff.c
@@ -8,6 +8,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include "roff.h"
static void g_init(void)
@@ -26,6 +27,12 @@
va_end(ap);
}
+void errdie(char *msg)
+{
+ fprintf(stderr, msg);
+ exit(1);
+}
+
static char *usage =
"Usage: neatcc [options] input\n"
"Options:\n"
@@ -79,7 +86,7 @@
in_queue(NULL); /* reading from standard input */
for (; i < argc; i++)
in_queue(!strcmp("-", argv[i]) ? NULL : argv[i]);
- str_set(REG('.', 'P'), macrodir);
+ str_set(map(".P"), macrodir);
out("s%d\n", n_s);
out("f%d\n", n_f);
ret = render();
--- a/roff.h
+++ b/roff.h
@@ -325,6 +325,7 @@
/* helpers */
void errmsg(char *msg, ...);
+void errdie(char *msg);
int utf8len(int c);
int utf8next(char *s, int (*next)(void));
int utf8read(char **s, char *d);
@@ -347,13 +348,12 @@
#define TR_DIVEND "\07>" /* diversion ends */
#define TR_EJECT "\07P" /* page eject */
-/* mapping register, macro and environment names to numbers */
-#define NREGS (1 << 16)
-#define NREGS2 (NREGS * 2)
-#define REG(c1, c2) ((c1) * 256 + (c2))
+/* mapping register, macro and environment names to indices */
+#define NREGS 4096 /* maximum number of mapped names */
+#define DOTMAP(c2) (c2) /* optimized mapping for ".x" names */
-int map(char *s);
-char *map_name(int id);
+int map(char *s); /* map name s to an index */
+char *map_name(int id); /* return the name mapped to id */
/* colors */
#define CLR_R(c) (((c) >> 16) & 0xff)
@@ -365,59 +365,59 @@
int clr_get(char *s);
/* 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')))
-#define n_i (*nreg(REG('.', 'i')))
+#define n_a (*nreg(DOTMAP('a')))
+#define n_cp (*nreg(DOTMAP('C')))
+#define n_d (*nreg(DOTMAP('d')))
+#define n_f (*nreg(DOTMAP('f')))
+#define n_h (*nreg(DOTMAP('h')))
+#define n_i (*nreg(DOTMAP('i')))
#define n_it (*nreg(map(".it"))) /* .it trap macro */
#define n_itn (*nreg(map(".itn"))) /* .it lines left */
-#define n_j (*nreg(REG('.', 'j')))
-#define n_l (*nreg(REG('.', 'l')))
-#define n_L (*nreg(REG('.', 'L')))
-#define n_n (*nreg(REG('.', 'n')))
+#define n_j (*nreg(DOTMAP('j')))
+#define n_l (*nreg(DOTMAP('l')))
+#define n_L (*nreg(DOTMAP('L')))
+#define n_n (*nreg(DOTMAP('n')))
#define n_nI (*nreg(map(".nI"))) /* i for .nm */
#define n_nm (*nreg(map(".nm"))) /* .nm enabled */
#define n_nM (*nreg(map(".nM"))) /* m for .nm */
#define n_nn (*nreg(map(".nn"))) /* remaining .nn */
#define n_nS (*nreg(map(".nS"))) /* s for .nm */
-#define n_m (*nreg(REG('.', 'm')))
+#define n_m (*nreg(DOTMAP('m')))
#define n_mc (*nreg(map(".mc"))) /* .mc enabled */
#define n_mcn (*nreg(map(".mcn"))) /* .mc distance */
-#define n_o (*nreg(REG('.', 'o')))
-#define n_p (*nreg(REG('.', 'p')))
-#define n_s (*nreg(REG('.', 's')))
-#define n_u (*nreg(REG('.', 'u')))
-#define n_v (*nreg(REG('.', 'v')))
-#define n_ct (*nreg(REG('c', 't')))
-#define n_dl (*nreg(REG('d', 'l')))
-#define n_dn (*nreg(REG('d', 'n')))
-#define n_ln (*nreg(REG('l', 'n')))
-#define n_nl (*nreg(REG('n', 'l')))
-#define n_sb (*nreg(REG('s', 'b')))
-#define n_st (*nreg(REG('s', 't')))
-#define n_pg (*nreg(REG('%', '\0'))) /* % */
-#define n_lb (*nreg(REG(0, 'b'))) /* input line beg */
-#define n_ce (*nreg(REG(0, 'c'))) /* .ce remaining */
-#define n_f0 (*nreg(REG(0, 'f'))) /* last .f */
-#define n_lg (*nreg(REG(0, 'g'))) /* .lg mode */
-#define n_hy (*nreg(REG(0, 'h'))) /* .hy mode */
-#define n_i0 (*nreg(REG(0, 'i'))) /* last .i */
-#define n_kn (*nreg(REG(0, 'k'))) /* .kn mode */
-#define n_l0 (*nreg(REG(0, 'l'))) /* last .l */
-#define n_L0 (*nreg(REG(0, 'L'))) /* last .L */
-#define n_m0 (*nreg(REG(0, 'm'))) /* last .m */
-#define n_mk (*nreg(REG(0, 'M'))) /* .mk internal register */
-#define n_na (*nreg(REG(0, 'n'))) /* .na mode */
-#define n_ns (*nreg(REG(0, 'N'))) /* .ns mode */
-#define n_o0 (*nreg(REG(0, 'o'))) /* last .o */
-#define n_ss (*nreg(REG(0, 'p'))) /* .ss value */
-#define n_s0 (*nreg(REG(0, 's'))) /* last .s */
-#define n_sv (*nreg(REG(0, 'S'))) /* .sv value */
-#define n_lt (*nreg(REG(0, 't'))) /* .lt value */
-#define n_t0 (*nreg(REG(0, 'T'))) /* previous .lt value */
-#define n_v0 (*nreg(REG(0, 'v'))) /* last .v */
+#define n_o (*nreg(DOTMAP('o')))
+#define n_p (*nreg(DOTMAP('p')))
+#define n_s (*nreg(DOTMAP('s')))
+#define n_u (*nreg(DOTMAP('u')))
+#define n_v (*nreg(DOTMAP('v')))
+#define n_ct (*nreg(map("ct")))
+#define n_dl (*nreg(map("dl")))
+#define n_dn (*nreg(map("dn")))
+#define n_ln (*nreg(map("ln")))
+#define n_nl (*nreg(map("nl")))
+#define n_sb (*nreg(map("sb")))
+#define n_st (*nreg(map("st")))
+#define n_pg (*nreg(map("%"))) /* % */
+#define n_lb (*nreg(map(".b0"))) /* input line beg */
+#define n_ce (*nreg(map(".ce"))) /* .ce remaining */
+#define n_f0 (*nreg(map(".f0"))) /* last .f */
+#define n_lg (*nreg(map(".lg"))) /* .lg mode */
+#define n_hy (*nreg(map(".hy"))) /* .hy mode */
+#define n_i0 (*nreg(map(".i0"))) /* last .i */
+#define n_kn (*nreg(map(".kern"))) /* .kn mode */
+#define n_l0 (*nreg(map(".l0"))) /* last .l */
+#define n_L0 (*nreg(map(".L0"))) /* last .L */
+#define n_m0 (*nreg(map(".m0"))) /* last .m */
+#define n_mk (*nreg(map(".mk"))) /* .mk internal register */
+#define n_na (*nreg(map(".na"))) /* .na mode */
+#define n_ns (*nreg(map(".ns"))) /* .ns mode */
+#define n_o0 (*nreg(map(".o0"))) /* last .o */
+#define n_ss (*nreg(map(".ss"))) /* .ss value */
+#define n_s0 (*nreg(map(".s0"))) /* last .s */
+#define n_sv (*nreg(map(".sv"))) /* .sv value */
+#define n_lt (*nreg(map(".lt"))) /* .lt value */
+#define n_t0 (*nreg(map(".lt0"))) /* previous .lt value */
+#define n_v0 (*nreg(map(".v0"))) /* last .v */
/* functions for implementing read-only registers */
int f_nexttrap(void); /* .t */
--- a/tr.c
+++ b/tr.c
@@ -336,7 +336,7 @@
{
int c = cp_next();
if (c >= 0 && c == c_pc) {
- in_push(num_str(REG('%', '\0')), NULL);
+ in_push(num_str(map("%")), NULL);
c = cp_next();
}
return c;