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