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