|
|
1.1 root 1: /*
2: * troff4.c
3: *
4: * number registers, conversion, arithmetic
5: */
6:
7: #include "tdef.h"
8: #include "fns.h"
9: #include "ext.h"
10:
11:
12: int regcnt = NNAMES;
13: int falsef = 0; /* on if inside false branch of if */
14:
15: #define NHASHSIZE 128 /* must be 2**n */
16: #define NHASH(i) ((i>>6)^i) & (NHASHSIZE-1)
17: Numtab *nhash[NHASHSIZE];
18:
19: void setn(void)
20: {
21: int i, j, f;
22: Tchar ii;
23: char *p;
24: char buf[NTM]; /* for \n(.S */
25:
26: f = nform = 0;
27: if ((i = cbits(ii = getach())) == '+')
28: f = 1;
29: else if (i == '-')
30: f = -1;
31: else if (ii) /* don't put it back if it's already back (thanks to jaap) */
32: ch = ii;
33: if (falsef)
34: f = 0;
35: if ((i = getsn()) == 0)
36: return;
37: p = unpair(i);
38: if (p[0] == '.')
39: switch (p[1]) {
40: case 's':
41: i = pts;
42: break;
43: case 'v':
44: i = lss;
45: break;
46: case 'f':
47: i = font;
48: break;
49: case 'p':
50: i = pl;
51: break;
52: case 't':
53: i = findt1();
54: break;
55: case 'o':
56: i = po;
57: break;
58: case 'l':
59: i = ll;
60: break;
61: case 'i':
62: i = in;
63: break;
64: case '$':
65: i = frame->nargs;
66: break;
67: case 'A':
68: i = ascii;
69: break;
70: case 'c':
71: i = numtab[CD].val;
72: break;
73: case 'n':
74: i = lastl;
75: break;
76: case 'a':
77: i = ralss;
78: break;
79: case 'h':
80: i = dip->hnl;
81: break;
82: case 'd':
83: if (dip != d)
84: i = dip->dnl;
85: else
86: i = numtab[NL].val;
87: break;
88: case 'u':
89: i = fi;
90: break;
91: case 'j':
92: i = ad + 2 * admod;
93: break;
94: case 'w':
95: i = widthp;
96: break;
97: case 'x':
98: i = nel;
99: break;
100: case 'y':
101: i = un;
102: break;
103: case 'T':
104: i = dotT;
105: break; /* -Tterm used in nroff */
106: case 'V':
107: i = VERT;
108: break;
109: case 'H':
110: i = HOR;
111: break;
112: case 'k':
113: i = ne;
114: break;
115: case 'P':
116: i = print;
117: break;
118: case 'L':
119: i = ls;
120: break;
121: case 'R':
122: i = NN - regcnt;
123: break;
124: case 'z':
125: p = unpair(dip->curd);
126: *pbp++ = p[1]; /* watch order */
127: *pbp++ = p[0];
128: return;
129: case 'b':
130: i = bdtab[font];
131: break;
132: case 'F':
133: cpushback(cfname[ifi]);
134: return;
135: case 'S':
136: buf[0] = j = 0;
137: for( i = 0; tabtab[i] != 0 && i < NTAB; i++) {
138: if (i > 0)
139: buf[j++] = ' ';
140: sprintf(&buf[j], "%d", tabtab[i] & TABMASK);
141: j = strlen(buf);
142: if ( tabtab[i] & RTAB)
143: sprintf(&buf[j], "uR");
144: else if (tabtab[i] & CTAB)
145: sprintf(&buf[j], "uC");
146: else
147: sprintf(&buf[j], "uL");
148: j += 2;
149: }
150: cpushback(buf);
151: return;
152: default:
153: goto s0;
154: }
155: else {
156: s0:
157: if ((j = findr(i)) == -1)
158: i = 0;
159: else {
160: i = numtab[j].val = numtab[j].val + numtab[j].inc * f;
161: nform = numtab[j].fmt;
162: }
163: }
164: setn1(i, nform, (Tchar) 0);
165: }
166:
167: Tchar numbuf[25];
168: Tchar *numbufp;
169:
170: int wrc(Tchar i)
171: {
172: if (numbufp >= &numbuf[24])
173: return(0);
174: *numbufp++ = i;
175: return(1);
176: }
177:
178:
179:
180: /* insert into input number i, in format form, with size-font bits bits */
181: void setn1(int i, int form, Tchar bits)
182: {
183: numbufp = numbuf;
184: nrbits = bits;
185: nform = form;
186: fnumb(i, wrc);
187: *numbufp = 0;
188: pushback(numbuf);
189: }
190:
191:
192: void nrehash(void)
193: {
194: Numtab *p;
195: int i;
196:
197: for (i=0; i<NHASHSIZE; i++)
198: nhash[i] = 0;
199: for (p=numtab; p < &numtab[NN]; p++)
200: p->link = 0;
201: for (p=numtab; p < &numtab[NN]; p++) {
202: if (p->r == 0)
203: continue;
204: i = NHASH(p->r);
205: p->link = nhash[i];
206: nhash[i] = p;
207: }
208: }
209:
210: void nunhash(Numtab *rp)
211: {
212: Numtab *p;
213: Numtab **lp;
214:
215: if (rp->r == 0)
216: return;
217: lp = &nhash[NHASH(rp->r)];
218: p = *lp;
219: while (p) {
220: if (p == rp) {
221: *lp = p->link;
222: p->link = 0;
223: return;
224: }
225: lp = &p->link;
226: p = p->link;
227: }
228: }
229:
230: int findr(int i)
231: {
232: Numtab *p;
233: int h = NHASH(i);
234:
235: if (i == 0)
236: return(-1);
237: for (p = nhash[h]; p; p = p->link)
238: if (i == p->r)
239: return(p - numtab);
240: for (p = numtab; p < &numtab[NN]; p++) {
241: if (p->r == 0) {
242: p->r = i;
243: p->link = nhash[h];
244: nhash[h] = p;
245: regcnt++;
246: return(p - numtab);
247: }
248: }
249: ERROR "too many number registers (%d).", NN WARN;
250: done2(04);
251: /* NOTREACHED */
252: return -1;
253: }
254:
255: int usedr(int i) /* returns -1 if nr i has never been used */
256: {
257: Numtab *p;
258:
259: if (i == 0)
260: return(-1);
261: for (p = nhash[NHASH(i)]; p; p = p->link)
262: if (i == p->r)
263: return(p - numtab);
264: return -1;
265: }
266:
267:
268: int fnumb(int i, int (*f)(Tchar))
269: {
270: int j;
271:
272: j = 0;
273: if (i < 0) {
274: j = (*f)('-' | nrbits);
275: i = -i;
276: }
277: switch (nform) {
278: default:
279: case '1':
280: case 0:
281: return decml(i, f) + j;
282: case 'i':
283: case 'I':
284: return roman(i, f) + j;
285: case 'a':
286: case 'A':
287: return abc(i, f) + j;
288: }
289: }
290:
291:
292: int decml(int i, int (*f)(Tchar))
293: {
294: int j, k;
295:
296: k = 0;
297: nform--;
298: if ((j = i / 10) || (nform > 0))
299: k = decml(j, f);
300: return(k + (*f)((i % 10 + '0') | nrbits));
301: }
302:
303:
304: int roman(int i, int (*f)(Tchar))
305: {
306:
307: if (!i)
308: return((*f)('0' | nrbits));
309: if (nform == 'i')
310: return(roman0(i, f, "ixcmz", "vldw"));
311: else
312: return(roman0(i, f, "IXCMZ", "VLDW"));
313: }
314:
315:
316: int roman0(int i, int (*f)(Tchar), char *onesp, char *fivesp)
317: {
318: int q, rem, k;
319:
320: if (!i)
321: return(0);
322: k = roman0(i / 10, f, onesp + 1, fivesp + 1);
323: q = (i = i % 10) / 5;
324: rem = i % 5;
325: if (rem == 4) {
326: k += (*f)(*onesp | nrbits);
327: if (q)
328: i = *(onesp + 1);
329: else
330: i = *fivesp;
331: return(k += (*f)(i | nrbits));
332: }
333: if (q)
334: k += (*f)(*fivesp | nrbits);
335: while (--rem >= 0)
336: k += (*f)(*onesp | nrbits);
337: return(k);
338: }
339:
340:
341: int abc(int i, int (*f)(Tchar))
342: {
343: if (!i)
344: return((*f)('0' | nrbits));
345: else
346: return(abc0(i - 1, f));
347: }
348:
349:
350: int abc0(int i, int (*f)(Tchar))
351: {
352: int j, k;
353:
354: k = 0;
355: if (j = i / 26)
356: k = abc0(j - 1, f);
357: return(k + (*f)((i % 26 + nform) | nrbits));
358: }
359:
360: long atoi0(void)
361: {
362: int c, k, cnt;
363: Tchar ii;
364: long i, acc;
365:
366: acc = 0;
367: nonumb = 0;
368: cnt = -1;
369: a0:
370: cnt++;
371: ii = getch();
372: c = cbits(ii);
373: switch (c) {
374: default:
375: ch = ii;
376: if (cnt)
377: break;
378: case '+':
379: i = ckph();
380: if (nonumb)
381: break;
382: acc += i;
383: goto a0;
384: case '-':
385: i = ckph();
386: if (nonumb)
387: break;
388: acc -= i;
389: goto a0;
390: case '*':
391: i = ckph();
392: if (nonumb)
393: break;
394: acc *= i;
395: goto a0;
396: case '/':
397: i = ckph();
398: if (nonumb)
399: break;
400: if (i == 0) {
401: flusho();
402: ERROR "divide by zero." WARN;
403: acc = 0;
404: } else
405: acc /= i;
406: goto a0;
407: case '%':
408: i = ckph();
409: if (nonumb)
410: break;
411: acc %= i;
412: goto a0;
413: case '&': /*and*/
414: i = ckph();
415: if (nonumb)
416: break;
417: if ((acc > 0) && (i > 0))
418: acc = 1;
419: else
420: acc = 0;
421: goto a0;
422: case ':': /*or*/
423: i = ckph();
424: if (nonumb)
425: break;
426: if ((acc > 0) || (i > 0))
427: acc = 1;
428: else
429: acc = 0;
430: goto a0;
431: case '=':
432: if (cbits(ii = getch()) != '=')
433: ch = ii;
434: i = ckph();
435: if (nonumb) {
436: acc = 0;
437: break;
438: }
439: if (i == acc)
440: acc = 1;
441: else
442: acc = 0;
443: goto a0;
444: case '>':
445: k = 0;
446: if (cbits(ii = getch()) == '=')
447: k++;
448: else
449: ch = ii;
450: i = ckph();
451: if (nonumb) {
452: acc = 0;
453: break;
454: }
455: if (acc > (i - k))
456: acc = 1;
457: else
458: acc = 0;
459: goto a0;
460: case '<':
461: k = 0;
462: if (cbits(ii = getch()) == '=')
463: k++;
464: else
465: ch = ii;
466: i = ckph();
467: if (nonumb) {
468: acc = 0;
469: break;
470: }
471: if (acc < (i + k))
472: acc = 1;
473: else
474: acc = 0;
475: goto a0;
476: case ')':
477: break;
478: case '(':
479: acc = atoi0();
480: goto a0;
481: }
482: return(acc);
483: }
484:
485:
486: long ckph(void)
487: {
488: Tchar i;
489: long j;
490:
491: if (cbits(i = getch()) == '(')
492: j = atoi0();
493: else {
494: j = atoi1(i);
495: }
496: return(j);
497: }
498:
499:
500: long atoi1(Tchar ii)
501: {
502: int i, j, digits;
503: double acc; /* this is the only double in troff! */
504: int neg, abs, field;
505:
506: neg = abs = field = digits = 0;
507: acc = 0;
508: for (;;) {
509: i = cbits(ii);
510: switch (i) {
511: default:
512: break;
513: case '+':
514: ii = getch();
515: continue;
516: case '-':
517: neg = 1;
518: ii = getch();
519: continue;
520: case '|':
521: abs = 1 + neg;
522: neg = 0;
523: ii = getch();
524: continue;
525: }
526: break;
527: }
528: a1:
529: while (i >= '0' && i <= '9') {
530: field++;
531: digits++;
532: acc = 10 * acc + i - '0';
533: ii = getch();
534: i = cbits(ii);
535: }
536: if (i == '.') {
537: field++;
538: digits = 0;
539: ii = getch();
540: i = cbits(ii);
541: goto a1;
542: }
543: if (!field) {
544: ch = ii;
545: goto a2;
546: }
547: switch (i) {
548: case 'u':
549: i = j = 1; /* should this be related to HOR?? */
550: break;
551: case 'v': /*VSs - vert spacing*/
552: j = lss;
553: i = 1;
554: break;
555: case 'm': /*Ems*/
556: j = EM;
557: i = 1;
558: break;
559: case 'n': /*Ens*/
560: j = EM;
561: if (TROFF)
562: i = 2;
563: else
564: i = 1; /*Same as Ems in NROFF*/
565: break;
566: case 'p': /*Points*/
567: j = INCH;
568: i = 72;
569: break;
570: case 'i': /*Inches*/
571: j = INCH;
572: i = 1;
573: break;
574: case 'c': /*Centimeters*/
575: /* if INCH is too big, this will overflow */
576: j = INCH * 50;
577: i = 127;
578: break;
579: case 'P': /*Picas*/
580: j = INCH;
581: i = 6;
582: break;
583: default:
584: j = dfact;
585: ch = ii;
586: i = dfactd;
587: }
588: if (neg)
589: acc = -acc;
590: if (!noscale) {
591: acc = (acc * j) / i;
592: }
593: if (field != digits && digits > 0)
594: while (digits--)
595: acc /= 10;
596: if (abs) {
597: if (dip != d)
598: j = dip->dnl;
599: else
600: j = numtab[NL].val;
601: if (!vflag) {
602: j = numtab[HP].val;
603: }
604: if (abs == 2)
605: j = -j;
606: acc -= j;
607: }
608: a2:
609: nonumb = !field;
610: return(acc);
611: }
612:
613:
614: void caserr(void)
615: {
616: int i, j;
617: Numtab *p;
618:
619: lgf++;
620: while (!skip() && (i = getrq()) ) {
621: j = usedr(i);
622: if (j < 0)
623: continue;
624: p = &numtab[j];
625: nunhash(p);
626: p->r = p->val = p->inc = p->fmt = 0;
627: regcnt--;
628: }
629: }
630:
631:
632: void casenr(void)
633: {
634: int i, j;
635:
636: lgf++;
637: skip();
638: if ((i = findr(getrq())) == -1)
639: goto rtn;
640: skip();
641: j = inumb(&numtab[i].val);
642: if (nonumb)
643: goto rtn;
644: numtab[i].val = j;
645: skip();
646: j = atoi0(); /* BUG??? */
647: if (nonumb)
648: goto rtn;
649: numtab[i].inc = j;
650: rtn:
651: return;
652: }
653:
654: void caseaf(void)
655: {
656: int i, k;
657: Tchar j;
658:
659: lgf++;
660: if (skip() || !(i = getrq()) || skip())
661: return;
662: k = 0;
663: j = getch();
664: if (!isalpha(cbits(j))) {
665: ch = j;
666: while ((j = cbits(getch())) >= '0' && j <= '9')
667: k++;
668: }
669: if (!k)
670: k = j;
671: numtab[findr(i)].fmt = k; /* was k & BYTEMASK */
672: }
673:
674: void setaf(void) /* return format of number register */
675: {
676: int i, j;
677:
678: i = usedr(getsn());
679: if (i == -1)
680: return;
681: if (numtab[i].fmt > 20) /* it was probably a, A, i or I */
682: *pbp++ = numtab[i].fmt;
683: else
684: for (j = (numtab[i].fmt ? numtab[i].fmt : 1); j; j--)
685: *pbp++ = '0';
686: }
687:
688:
689: int vnumb(int *i)
690: {
691: vflag++;
692: dfact = lss;
693: res = VERT;
694: return(inumb(i));
695: }
696:
697:
698: int hnumb(int *i)
699: {
700: dfact = EM;
701: res = HOR;
702: return(inumb(i));
703: }
704:
705:
706: int inumb(int *n)
707: {
708: int i, j, f;
709: Tchar ii;
710:
711: f = 0;
712: if (n) {
713: if ((j = cbits(ii = getch())) == '+')
714: f = 1;
715: else if (j == '-')
716: f = -1;
717: else
718: ch = ii;
719: }
720: i = atoi0();
721: if (n && f)
722: i = *n + f * i;
723: i = quant(i, res);
724: vflag = 0;
725: res = dfactd = dfact = 1;
726: if (nonumb)
727: i = 0;
728: return(i);
729: }
730:
731:
732: int quant(int n, int m)
733: {
734: int i, neg;
735:
736: neg = 0;
737: if (n < 0) {
738: neg++;
739: n = -n;
740: }
741: /* better as i = ((n + m/2)/m)*m */
742: i = n / m;
743: if (n - m * i > m / 2)
744: i += 1;
745: i *= m;
746: if (neg)
747: i = -i;
748: return(i);
749: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.