]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/htmlroff/t8.c
usb lib: add maxpkt and ntds to Altc struct
[plan9front.git] / sys / src / cmd / htmlroff / t8.c
1 #include "a.h"
2 /*
3  * 8. Number Registers
4  * (Reg register implementation is also here.)
5  */
6
7 /*
8  *      \nx             N
9  *      \n(xx   N
10  *      \n+x            N+=M
11  *      \n-x            N-=M
12  *
13  *      .nr R ±N M
14  *      .af R c
15  *
16  *      formats
17  *              1       0, 1, 2, 3, ...
18  *              001     001, 002, 003, ...
19  *              i       0, i, ii, iii, iv, v, ...
20  *              I       0, I, II, III, IV, V, ...
21  *              a       0, a, b, ..., aa, ab, ..., zz, aaa, ...
22  *              A       0, A, B, ..., AA, AB, ..., ZZ, AAA, ...
23  *
24  *      \gx \g(xx return format of number register
25  *
26  *      .rr R
27  */
28
29 typedef struct Reg Reg;
30 struct Reg
31 {
32         Reg *next;
33         Rune *name;
34         Rune *val;
35         Rune *fmt;
36         int inc;
37 };
38
39 Reg *dslist;
40 Reg *nrlist;
41
42 /*
43  * Define strings and numbers.
44  */
45 void
46 dsnr(Rune *name, Rune *val, Reg **l)
47 {
48         Reg *s;
49
50         for(s = *l; s != nil; s = *l){
51                 if(runestrcmp(s->name, name) == 0)
52                         break;
53                 l = &s->next;
54         }
55         if(val == nil){
56                 if(s){
57                         *l = s->next;
58                         free(s->val);
59                         free(s->fmt);
60                         free(s);
61                 }
62                 return;
63         }
64         if(s == nil){
65                 s = emalloc(sizeof(Reg));
66                 *l = s;
67                 s->name = erunestrdup(name);
68         }else
69                 free(s->val);
70         s->val = erunestrdup(val);
71 }
72
73 Rune*
74 getdsnr(Rune *name, Reg *list)
75 {
76         Reg *s;
77         
78         for(s=list; s; s=s->next)
79                 if(runestrcmp(name, s->name) == 0)
80                         return s->val;
81         return nil;
82 }
83
84 void
85 ds(Rune *name, Rune *val)
86 {
87         dsnr(name, val, &dslist);
88 }
89
90 void
91 as(Rune *name, Rune *val)
92 {
93         Rune *p, *q;
94         
95         p = getds(name);
96         if(p == nil)
97                 p = L("");
98         q = runemalloc(runestrlen(p)+runestrlen(val)+1);
99         runestrcpy(q, p);
100         runestrcat(q, val);
101         ds(name, q);
102         free(q);
103 }
104
105 Rune*
106 getds(Rune *name)
107 {
108         return getdsnr(name, dslist);
109 }
110
111 void
112 printds(int t)
113 {
114         int n, total;
115         Reg *s;
116         
117         total = 0;
118         for(s=dslist; s; s=s->next){
119                 if(s->val)
120                         n = runestrlen(s->val);
121                 else
122                         n = 0;
123                 total += n;
124                 if(!t)
125                         fprint(2, "%S\t%d\n", s->name, n);
126         }
127         fprint(2, "total\t%d\n", total);
128 }
129
130 void
131 nr(Rune *name, int val)
132 {
133         Rune buf[20];
134         
135         runesnprint(buf, nelem(buf), "%d", val);
136         _nr(name, buf);
137 }
138
139 void
140 af(Rune *name, Rune *fmt)
141 {
142         Reg *s;
143
144         if(_getnr(name) == nil)
145                 _nr(name, L("0"));
146         for(s=nrlist; s; s=s->next)
147                 if(runestrcmp(s->name, name) == 0)
148                         s->fmt = erunestrdup(fmt);
149 }
150
151 Rune*
152 getaf(Rune *name)
153 {
154         Reg *s;
155         
156         for(s=nrlist; s; s=s->next)
157                 if(runestrcmp(s->name, name) == 0)
158                         return s->fmt;
159         return nil;
160 }
161
162 void
163 printnr(void)
164 {
165         Reg *r;
166         
167         for(r=nrlist; r; r=r->next)
168                 fprint(2, "%S %S %d\n", r->name, r->val, r->inc);
169 }
170
171 /*
172  * Some internal number registers are actually strings,
173  * so provide _ versions to get at them.
174  */
175 void
176 _nr(Rune *name, Rune *val)
177 {
178         dsnr(name, val, &nrlist);
179 }
180
181 Rune*
182 _getnr(Rune *name)
183 {
184         return getdsnr(name, nrlist);
185 }
186
187 int
188 getnr(Rune *name)
189 {
190         Rune *p;
191
192         p = _getnr(name);
193         if(p == nil)
194                 return 0;
195         return eval(p);
196 }
197
198 /* new register */
199 void
200 r_nr(int argc, Rune **argv)
201 {
202         Reg *s;
203
204         if(argc < 2)
205                 return;
206         if(argc < 3)
207                 nr(argv[1], 0);
208         else{
209                 if(argv[2][0] == '+')
210                         nr(argv[1], getnr(argv[1])+eval(argv[2]+1));
211                 else if(argv[2][0] == '-')
212                         nr(argv[1], getnr(argv[1])-eval(argv[2]+1));
213                 else
214                         nr(argv[1], eval(argv[2]));
215         }
216         if(argc > 3){
217                 for(s=nrlist; s; s=s->next)
218                         if(runestrcmp(s->name, argv[1]) == 0)
219                                 s->inc = eval(argv[3]);
220         }
221 }
222
223 /* assign format */
224 void
225 r_af(int argc, Rune **argv)
226 {
227         USED(argc);
228         
229         af(argv[1], argv[2]);
230 }
231
232 /* remove register */
233 void
234 r_rr(int argc, Rune **argv)
235 {
236         int i;
237         
238         for(i=1; i<argc; i++)
239                 _nr(argv[i], nil);
240 }
241
242 /* fmt integer in base 26 */
243 void
244 alpha(Rune *buf, int n, int a)
245 {
246         int i, v;
247         
248         i = 1;
249         for(v=n; v>0; v/=26)
250                 i++;
251         if(i == 0)
252                 i = 1;
253         buf[i] = 0;
254         while(i > 0){
255                 buf[--i] = a+n%26;
256                 n /= 26;
257         }
258 }
259
260 struct romanv {
261         char *s;
262         int v;
263 } romanv[] =
264 {
265         "m",    1000,
266         "cm", 900,
267         "d", 500,
268         "cd", 400,
269         "c", 100,
270         "xc", 90,
271         "l", 50,
272         "xl", 40,
273         "x", 10,
274         "ix", 9,
275         "v", 5,
276         "iv", 4,
277         "i", 1
278 };
279
280 /* fmt integer in roman numerals! */
281 void
282 roman(Rune *buf, int n, int upper)
283 {
284         Rune *p;
285         char *q;
286         struct romanv *r;
287         
288         if(upper)
289                 upper = 'A' - 'a';
290         if(n >= 5000 || n <= 0){
291                 runestrcpy(buf, L("-"));
292                 return;
293         }
294         p = buf;
295         r = romanv;
296         while(n > 0){
297                 while(n >= r->v){
298                         for(q=r->s; *q; q++)
299                                 *p++ = *q + upper;
300                         n -= r->v;
301                 }
302                 r++;
303         }
304         *p = 0;
305 }
306
307 Rune*
308 getname(void)
309 {
310         int i, c, cc;
311         static Rune buf[100];
312         
313         /* XXX add [name] syntax as in groff */
314         c = getnext();
315         if(c < 0)
316                 return L("");
317         if(c == '\n'){
318                 warn("newline in name\n");
319                 ungetnext(c);
320                 return L("");
321         }
322         if(c == '['){
323                 for(i=0; i<nelem(buf)-1; i++){
324                         if((c = getrune()) < 0)
325                                 return L("");
326                         if(c == ']'){
327                                 buf[i] = 0;
328                                 return buf;
329                         }
330                         buf[i] = c;
331                 }
332                 return L("");
333         }
334         if(c != '('){
335                 buf[0] = c;
336                 buf[1] = 0;
337                 return buf;
338         }
339         c = getnext();
340         cc = getnext();
341         if(c < 0 || cc < 0)
342                 return L("");
343         if(c == '\n' || cc == '\n'){
344                 warn("newline in \\n");
345                 ungetnext(cc);
346                 if(c == '\n')
347                         ungetnext(c);
348         }
349         buf[0] = c;
350         buf[1] = cc;
351         buf[2] = 0;
352         return buf;
353 }
354
355 /* \n - return number register */
356 int
357 e_n(void)
358 {
359         int inc, v, l;
360         Rune *name, *fmt, buf[100];
361         Reg *s;
362         
363         inc = getnext();
364         if(inc < 0)
365                 return -1;
366         if(inc != '+' && inc != '-'){
367                 ungetnext(inc);
368                 inc = 0;
369         }
370         name = getname();
371         if(_getnr(name) == nil)
372                 _nr(name, L("0"));
373         for(s=nrlist; s; s=s->next){
374                 if(runestrcmp(s->name, name) == 0){
375                         if(s->fmt == nil && !inc && s->val[0]){
376                                 /* might be a string! */
377                                 pushinputstring(s->val);
378                                 return 0;
379                         }
380                         v = eval(s->val);
381                         if(inc){
382                                 if(inc == '+')
383                                         v += s->inc;
384                                 else
385                                         v -= s->inc;
386                                 runesnprint(buf, nelem(buf), "%d", v);
387                                 free(s->val);
388                                 s->val = erunestrdup(buf);
389                         }
390                         fmt = s->fmt;
391                         if(fmt == nil)
392                                 fmt = L("1");
393                         switch(fmt[0]){
394                         case 'i':
395                         case 'I':
396                                 roman(buf, v, fmt[0]=='I');
397                                 break;
398                         case 'a':
399                         case 'A':
400                                 alpha(buf, v, fmt[0]);
401                                 break;
402                         default:
403                                 l = runestrlen(fmt);
404                                 if(l == 0)
405                                         l = 1;
406                                 runesnprint(buf, sizeof buf, "%0*d", l, v);
407                                 break;
408                         }
409                         pushinputstring(buf);
410                         return 0;
411                 }
412         }
413         pushinputstring(L(""));
414         return 0;
415 }
416
417 /* \g - number register format */
418 int
419 e_g(void)
420 {
421         Rune *p;
422
423         p = getaf(getname());
424         if(p == nil)
425                 p = L("1");
426         pushinputstring(p);
427         return 0;
428 }
429
430 void
431 r_pnr(int argc, Rune **argv)
432 {
433         USED(argc);
434         USED(argv);
435         printnr();
436 }
437
438 void
439 t8init(void)
440 {
441         addreq(L("nr"), r_nr, -1);
442         addreq(L("af"), r_af, 2);
443         addreq(L("rr"), r_rr, -1);
444         addreq(L("pnr"), r_pnr, 0);
445         
446         addesc('n', e_n, CopyMode|ArgMode|HtmlMode);
447         addesc('g', e_g, 0);
448 }
449