wb: add wb struct as a word buffer
[neatroff.git] / reg.c
blobcec464e1a8ee996c3beef69f2286e2ee439a4f23
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "xroff.h"
7 #define NREGS (1 << 16)
8 #define NENVS (1 << 5)
10 struct env {
11 int eregs[NENVS]; /* environment-specific number registers */
12 struct adj *adj; /* per environment line buffer */
15 static int nregs[NREGS]; /* global number registers */
16 static int nregs_inc[NREGS]; /* number register auto-increment size */
17 static char *sregs[NREGS]; /* global string registers */
18 static void *sregs_dat[NREGS]; /* builtin function data */
19 static struct env envs[3]; /* environments */
20 static struct env *env; /* current enviroment */
21 static int eregs_idx[NREGS]; /* register environment index in eregs[] */
23 static int eregs[] = { /* environment-specific number registers */
24 REG('.', 'f'),
25 REG('.', 'i'),
26 REG('.', 'j'),
27 REG('.', 'l'),
28 REG('.', 'L'),
29 REG('.', 's'),
30 REG('.', 'u'),
31 REG('.', 'v'),
32 REG(0, 'c'),
33 REG(0, 'f'),
34 REG(0, 'i'),
35 REG(0, 'l'),
36 REG(0, 'L'),
37 REG(0, 'n'),
38 REG(0, 's'),
39 REG(0, 't'),
40 REG(0, 'T'),
41 REG(0, 'v'),
44 /* return the address of a number register */
45 int *nreg(int id)
47 if (eregs_idx[id])
48 return &env->eregs[eregs_idx[id]];
49 return &nregs[id];
52 static void reg_name(char *s, int id)
54 s[0] = (id >> 8) & 0xff;
55 s[1] = id & 0xff;
56 s[3] = '\0';
59 /* the contents of a number register (returns a static buffer) */
60 char *num_str(int id)
62 static char numbuf[128];
63 numbuf[0] = '\0';
64 switch (id) {
65 case REG('.', 'k'):
66 sprintf(numbuf, "%d", f_hpos());
67 break;
68 case REG('.', 't'):
69 sprintf(numbuf, "%d", f_nexttrap());
70 break;
71 case REG('.', 'z'):
72 if (f_divreg() >= 0)
73 reg_name(numbuf, f_divreg());
74 break;
75 case REG('.', 'F'):
76 sprintf(numbuf, "%s", in_filename());
77 break;
78 case REG('.', '$'):
79 sprintf(numbuf, "%d", in_nargs());
80 break;
81 default:
82 sprintf(numbuf, "%d", *nreg(id));
84 return numbuf;
87 void num_set(int id, int val)
89 *nreg(id) = val;
92 void num_inc(int id, int val)
94 nregs_inc[id] = val;
97 void num_del(int id)
99 *nreg(id) = 0;
100 nregs_inc[id] = 0;
103 int num_get(int id, int inc)
105 if (inc)
106 *nreg(id) += inc > 0 ? nregs_inc[id] : -nregs_inc[id];
107 return *nreg(id);
110 void str_set(int id, char *s)
112 int len = strlen(s) + 1;
113 if (sregs[id])
114 free(sregs[id]);
115 sregs[id] = malloc(len);
116 memcpy(sregs[id], s, len);
117 sregs_dat[id] = NULL;
120 char *str_get(int id)
122 return sregs[id];
125 void *str_dget(int id)
127 return sregs_dat[id];
130 void str_dset(int id, void *d)
132 sregs_dat[id] = d;
135 void str_rm(int id)
137 if (sregs[id])
138 free(sregs[id]);
139 sregs[id] = NULL;
140 sregs_dat[id] = NULL;
143 void str_rn(int src, int dst)
145 str_rm(dst);
146 sregs[dst] = sregs[src];
147 sregs_dat[dst] = sregs_dat[src];
148 sregs[src] = NULL;
149 sregs_dat[src] = NULL;
152 static void env_set(int id)
154 env = &envs[id];
155 if (!env->adj) {
156 env->adj = adj_alloc();
157 n_f = 1;
158 n_i = 0;
159 n_j = AD_B;
160 n_l = SC_IN * 65 / 10;
161 n_s = 10;
162 n_u = 1;
163 n_v = 12 * SC_PT;
164 n_s0 = n_s;
165 n_f0 = n_f;
166 n_na = 0;
167 n_lt = SC_IN * 65 / 10;
168 adj_ll(env->adj, n_l);
169 adj_in(env->adj, n_i);
173 void env_init(void)
175 int i;
176 for (i = 0; i < LEN(eregs); i++)
177 eregs_idx[eregs[i]] = i + 1;
178 env_set(0);
181 void env_free(void)
183 int i;
184 for (i = 0; i < LEN(envs); i++)
185 if (envs[i].adj)
186 adj_free(envs[i].adj);
189 static int oenv[NPREV]; /* environment stack */
190 static int nenv;
192 void tr_ev(char **args)
194 int id = args[1] ? atoi(args[1]) : -1;
195 if (id < 0 && nenv)
196 id = oenv[--nenv];
197 if (id >= LEN(envs) || id < 0)
198 return;
199 if (args[1] && env && nenv < NPREV)
200 oenv[nenv++] = env - envs;
201 env_set(id);
204 struct adj *env_adj(void)
206 return env->adj;
209 /* saving and restoring registers around diverted lines */
210 struct odiv {
211 int f, s, f0, s0;
214 static struct odiv odivs[NPREV]; /* state before diverted text */
215 static int nodivs;
217 /* begin outputting diverted line */
218 void odiv_beg(void)
220 struct odiv *o = &odivs[nodivs++];
221 o->f = n_f;
222 o->s = n_s;
223 o->f0 = n_f0;
224 o->s0 = n_s0;
227 /* end outputting diverted line */
228 void odiv_end(void)
230 struct odiv *o = &odivs[--nodivs];
231 n_f = o->f;
232 n_s = o->s;
233 n_f0 = o->f0;
234 n_s0 = o->s0;