151162Scael #ifndef lint
251162Scael static char sccsid[] = "@(#)n4.c 2.1 (CWI) 85/07/18";
351162Scael #endif lint
451162Scael /* @(#)n4.c 1.1 */
551162Scael #include <ctype.h>
651162Scael #include "tdef.h"
751162Scael #ifdef NROFF
851162Scael #include "tw.h"
951162Scael #endif
1051162Scael #include "ext.h"
1151162Scael #include <sgtty.h>
1251162Scael /*
1351162Scael * troff4.c
1451162Scael *
1551162Scael * number registers, conversion, arithmetic
1651162Scael */
1751162Scael
1851162Scael
1951162Scael int regcnt = NNAMES;
2051162Scael int falsef = 0; /* on if inside false branch of if */
2151162Scael #define NHASH(i) ((i>>6)^i)&0177
2251162Scael struct numtab *nhash[128]; /* 128 == the 0177 on line above */
2351162Scael
setn()2451162Scael setn()
2551162Scael {
2651162Scael register i, j;
2751162Scael register tchar ii;
2851162Scael int f;
2951162Scael
3051162Scael f = nform = 0;
3151162Scael if ((i = cbits(ii = getach())) == '+')
3251162Scael f = 1;
3351162Scael else if (i == '-')
3451162Scael f = -1;
3551162Scael else
3651162Scael ch = ii;
3751162Scael if (falsef)
3851162Scael f = 0;
3951162Scael if ((i = getsn()) == 0)
4051162Scael return;
4151162Scael if ((i & 0177) == '.')
4251162Scael switch (i >> BYTE) {
4351162Scael case 's':
4451162Scael i = pts;
4551162Scael break;
4651162Scael case 'v':
4751162Scael i = lss;
4851162Scael break;
4951162Scael case 'f':
5051162Scael i = font;
5151162Scael break;
5251162Scael case 'p':
5351162Scael i = pl;
5451162Scael break;
5551162Scael case 't':
5651162Scael i = findt1();
5751162Scael break;
5851162Scael case 'o':
5951162Scael i = po;
6051162Scael break;
6151162Scael case 'l':
6251162Scael i = ll;
6351162Scael break;
6451162Scael case 'i':
6551162Scael i = in;
6651162Scael break;
6751162Scael case '$':
6851162Scael i = frame->nargs;
6951162Scael break;
7051162Scael case 'A':
7151162Scael i = ascii;
7251162Scael break;
7351162Scael case 'c':
7451162Scael i = numtab[CD].val;
7551162Scael break;
7651162Scael case 'n':
7751162Scael i = lastl;
7851162Scael break;
7951162Scael case 'a':
8051162Scael i = ralss;
8151162Scael break;
8251162Scael case 'h':
8351162Scael i = dip->hnl;
8451162Scael break;
8551162Scael case 'd':
8651162Scael if (dip != d)
8751162Scael i = dip->dnl;
8851162Scael else
8951162Scael i = numtab[NL].val;
9051162Scael break;
9151162Scael case 'u':
9251162Scael i = fi;
9351162Scael break;
9451162Scael case 'j':
9551162Scael i = ad + 2 * admod;
9651162Scael break;
9751162Scael case 'w':
9851162Scael i = widthp;
9951162Scael break;
10051162Scael case 'x':
10151162Scael i = nel;
10251162Scael break;
10351162Scael case 'y':
10451162Scael i = un;
10551162Scael break;
10651162Scael case 'T':
10751162Scael i = dotT;
10851162Scael break; /*-Tterm used in nroff*/
10951162Scael case 'V':
11051162Scael i = VERT;
11151162Scael break;
11251162Scael case 'H':
11351162Scael i = HOR;
11451162Scael break;
11551162Scael case 'k':
11651162Scael i = ne;
11751162Scael break;
11851162Scael case 'P':
11951162Scael i = print;
12051162Scael break;
12151162Scael case 'L':
12251162Scael i = ls;
12351162Scael break;
12451162Scael case 'R':
12551162Scael i = NN - regcnt;
12651162Scael break;
12751162Scael case 'z':
12851162Scael i = dip->curd;
12951162Scael *pbp++ = (i >> BYTE) & BYTEMASK;
13051162Scael *pbp++ = i & BYTEMASK;
13151162Scael return;
13251162Scael case 'b':
13351162Scael i = bdtab[font];
13451162Scael break;
13551162Scael case 'F':
13651162Scael cpushback(cfname[ifi]);
13751162Scael return;
13851162Scael case 'D':
13951162Scael i = hyalg; /* "Dialect" register (jaap) */
14051162Scael break;
14151162Scael case 'e':
14251162Scael i = thresh; /* (jaap) */
14351162Scael break;
14451162Scael
14551162Scael default:
14651162Scael goto s0;
14751162Scael }
14851162Scael else {
14951162Scael s0:
15051162Scael if ((j = findr(i)) == -1)
15151162Scael i = 0;
15251162Scael else {
15351162Scael i = numtab[j].val = (numtab[j].val+numtab[j].inc*f);
15451162Scael nform = numtab[j].fmt;
15551162Scael }
15651162Scael }
15751162Scael setn1(i, nform, (tchar) 0);
15851162Scael }
15951162Scael
16051162Scael tchar numbuf[17];
16151162Scael tchar *numbufp;
16251162Scael
wrc(i)16351162Scael wrc(i)
16451162Scael tchar i;
16551162Scael {
16651162Scael if (numbufp >= &numbuf[16])
16751162Scael return(0);
16851162Scael *numbufp++ = i;
16951162Scael return(1);
17051162Scael }
17151162Scael
17251162Scael
17351162Scael
17451162Scael /* insert into input number i, in format form, with size-font bits bits */
setn1(i,form,bits)17551162Scael setn1(i, form, bits)
17651162Scael int i;
17751162Scael tchar bits;
17851162Scael {
17951162Scael extern int wrc();
18051162Scael
18151162Scael numbufp = numbuf;
18251162Scael nrbits = bits;
18351162Scael nform = form;
18451162Scael fnumb(i, wrc);
18551162Scael *numbufp = 0;
18651162Scael pushback(numbuf);
18751162Scael }
18851162Scael
18951162Scael
nrehash()19051162Scael nrehash()
19151162Scael {
19251162Scael register struct numtab *p;
19351162Scael register i;
19451162Scael
19551162Scael for (i=0; i<128; i++)
19651162Scael nhash[i] = 0;
19751162Scael for (p=numtab; p < &numtab[NN]; p++)
19851162Scael p->link = 0;
19951162Scael for (p=numtab; p < &numtab[NN]; p++) {
20051162Scael if (p->r == 0)
20151162Scael continue;
20251162Scael i = NHASH(p->r);
20351162Scael p->link = nhash[i];
20451162Scael nhash[i] = p;
20551162Scael }
20651162Scael }
20751162Scael
nunhash(rp)20851162Scael nunhash(rp)
20951162Scael register struct numtab *rp;
21051162Scael {
21151162Scael register struct numtab *p;
21251162Scael register struct numtab **lp;
21351162Scael
21451162Scael if (rp->r == 0)
21551162Scael return;
21651162Scael lp = &nhash[NHASH(rp->r)];
21751162Scael p = *lp;
21851162Scael while (p) {
21951162Scael if (p == rp) {
22051162Scael *lp = p->link;
22151162Scael p->link = 0;
22251162Scael return;
22351162Scael }
22451162Scael lp = &p->link;
22551162Scael p = p->link;
22651162Scael }
22751162Scael }
22851162Scael
findr(i)22951162Scael findr(i)
23051162Scael register int i;
23151162Scael {
23251162Scael register struct numtab *p;
23351162Scael register h = NHASH(i);
23451162Scael
23551162Scael if (i == 0)
23651162Scael return(-1);
23751162Scael for (p = nhash[h]; p; p = p->link)
23851162Scael if (i == p->r)
23951162Scael return(p - numtab);
24051162Scael for (p = numtab; p < &numtab[NN]; p++) {
24151162Scael if (p->r == 0) {
24251162Scael p->r = i;
24351162Scael p->link = nhash[h];
24451162Scael nhash[h] = p;
24551162Scael regcnt++;
24651162Scael return(p - numtab);
24751162Scael }
24851162Scael }
24951162Scael errprint("too many number registers (%d).", NN);
25051162Scael done2(04);
25151162Scael /* NOTREACHED */
25251162Scael }
25351162Scael
usedr(i)25451162Scael usedr(i) /* returns -1 if nr i has never been used */
25551162Scael register int i;
25651162Scael {
25751162Scael register struct numtab *p;
25851162Scael
25951162Scael if (i == 0)
26051162Scael return(-1);
26151162Scael for (p = nhash[NHASH(i)]; p; p = p->link)
26251162Scael if (i == p->r)
26351162Scael return(p - numtab);
26451162Scael return -1;
26551162Scael }
26651162Scael
26751162Scael
26851162Scael fnumb(i, f)
26951162Scael register int i, (*f)();
27051162Scael {
27151162Scael register j;
27251162Scael
27351162Scael j = 0;
27451162Scael if (i < 0) {
27551162Scael j = (*f)('-' | nrbits);
27651162Scael i = -i;
27751162Scael }
27851162Scael switch (nform) {
27951162Scael default:
28051162Scael case '1':
28151162Scael case 0:
28251162Scael return decml(i, f) + j;
28351162Scael break;
28451162Scael case 'i':
28551162Scael case 'I':
28651162Scael return roman(i, f) + j;
28751162Scael break;
28851162Scael case 'a':
28951162Scael case 'A':
29051162Scael return abc(i, f) + j;
29151162Scael break;
29251162Scael }
29351162Scael }
29451162Scael
29551162Scael
29651162Scael decml(i, f)
29751162Scael register int i, (*f)();
29851162Scael {
29951162Scael register j, k;
30051162Scael
30151162Scael k = 0;
30251162Scael nform--;
30351162Scael if ((j = i / 10) || (nform > 0))
30451162Scael k = decml(j, f);
30551162Scael return(k + (*f)((i % 10 + '0') | nrbits));
30651162Scael }
30751162Scael
30851162Scael
30951162Scael roman(i, f)
31051162Scael int i, (*f)();
31151162Scael {
31251162Scael
31351162Scael if (!i)
31451162Scael return((*f)('0' | nrbits));
31551162Scael if (nform == 'i')
31651162Scael return(roman0(i, f, "ixcmz", "vldw"));
31751162Scael else
31851162Scael return(roman0(i, f, "IXCMZ", "VLDW"));
31951162Scael }
32051162Scael
32151162Scael
32251162Scael roman0(i, f, onesp, fivesp)
32351162Scael int i, (*f)();
32451162Scael char *onesp, *fivesp;
32551162Scael {
32651162Scael register q, rem, k;
32751162Scael
32851162Scael k = 0;
32951162Scael if (!i)
33051162Scael return(0);
33151162Scael k = roman0(i / 10, f, onesp + 1, fivesp + 1);
33251162Scael q = (i = i % 10) / 5;
33351162Scael rem = i % 5;
33451162Scael if (rem == 4) {
33551162Scael k += (*f)(*onesp | nrbits);
33651162Scael if (q)
33751162Scael i = *(onesp + 1);
33851162Scael else
33951162Scael i = *fivesp;
34051162Scael return(k += (*f)(i | nrbits));
34151162Scael }
34251162Scael if (q)
34351162Scael k += (*f)(*fivesp | nrbits);
34451162Scael while (--rem >= 0)
34551162Scael k += (*f)(*onesp | nrbits);
34651162Scael return(k);
34751162Scael }
34851162Scael
34951162Scael
35051162Scael abc(i, f)
35151162Scael int i, (*f)();
35251162Scael {
35351162Scael if (!i)
35451162Scael return((*f)('0' | nrbits));
35551162Scael else
35651162Scael return(abc0(i - 1, f));
35751162Scael }
35851162Scael
35951162Scael
36051162Scael abc0(i, f)
36151162Scael int i, (*f)();
36251162Scael {
36351162Scael register j, k;
36451162Scael
36551162Scael k = 0;
36651162Scael if (j = i / 26)
36751162Scael k = abc0(j - 1, f);
36851162Scael return(k + (*f)((i % 26 + nform) | nrbits));
36951162Scael }
37051162Scael
atoi0()37151162Scael long atoi0()
37251162Scael {
37351162Scael register c, k, cnt;
37451162Scael register tchar ii;
37551162Scael long i, acc;
37651162Scael extern long ckph();
37751162Scael
37851162Scael i = 0;
37951162Scael acc = 0;
38051162Scael nonumb = 0;
38151162Scael cnt = -1;
38251162Scael a0:
38351162Scael cnt++;
38451162Scael ii = getch();
38551162Scael c = cbits(ii);
38651162Scael switch (c) {
38751162Scael default:
38851162Scael ch = ii;
38951162Scael if (cnt)
39051162Scael break;
39151162Scael case '+':
39251162Scael i = ckph();
39351162Scael if (nonumb)
39451162Scael break;
39551162Scael acc += i;
39651162Scael goto a0;
39751162Scael case '-':
39851162Scael i = ckph();
39951162Scael if (nonumb)
40051162Scael break;
40151162Scael acc -= i;
40251162Scael goto a0;
40351162Scael case '*':
40451162Scael i = ckph();
40551162Scael if (nonumb)
40651162Scael break;
40751162Scael acc *= i;
40851162Scael goto a0;
40951162Scael case '/':
41051162Scael i = ckph();
41151162Scael if (nonumb)
41251162Scael break;
41351162Scael if (i == 0) {
41451162Scael flusho();
41551162Scael errprint("divide by zero.");
41651162Scael acc = 0;
41751162Scael } else
41851162Scael acc /= i;
41951162Scael goto a0;
42051162Scael case '%':
42151162Scael i = ckph();
42251162Scael if (nonumb)
42351162Scael break;
42451162Scael acc %= i;
42551162Scael goto a0;
42651162Scael case '&': /*and*/
42751162Scael i = ckph();
42851162Scael if (nonumb)
42951162Scael break;
43051162Scael if ((acc > 0) && (i > 0))
43151162Scael acc = 1;
43251162Scael else
43351162Scael acc = 0;
43451162Scael goto a0;
43551162Scael case ':': /*or*/
43651162Scael i = ckph();
43751162Scael if (nonumb)
43851162Scael break;
43951162Scael if ((acc > 0) || (i > 0))
44051162Scael acc = 1;
44151162Scael else
44251162Scael acc = 0;
44351162Scael goto a0;
44451162Scael case '=':
44551162Scael if (cbits(ii = getch()) != '=')
44651162Scael ch = ii;
44751162Scael i = ckph();
44851162Scael if (nonumb) {
44951162Scael acc = 0;
45051162Scael break;
45151162Scael }
45251162Scael if (i == acc)
45351162Scael acc = 1;
45451162Scael else
45551162Scael acc = 0;
45651162Scael goto a0;
45751162Scael case '>':
45851162Scael k = 0;
45951162Scael if (cbits(ii = getch()) == '=')
46051162Scael k++;
46151162Scael else
46251162Scael ch = ii;
46351162Scael i = ckph();
46451162Scael if (nonumb) {
46551162Scael acc = 0;
46651162Scael break;
46751162Scael }
46851162Scael if (acc > (i - k))
46951162Scael acc = 1;
47051162Scael else
47151162Scael acc = 0;
47251162Scael goto a0;
47351162Scael case '<':
47451162Scael k = 0;
47551162Scael if (cbits(ii = getch()) == '=')
47651162Scael k++;
47751162Scael else
47851162Scael ch = ii;
47951162Scael i = ckph();
48051162Scael if (nonumb) {
48151162Scael acc = 0;
48251162Scael break;
48351162Scael }
48451162Scael if (acc < (i + k))
48551162Scael acc = 1;
48651162Scael else
48751162Scael acc = 0;
48851162Scael goto a0;
48951162Scael case ')':
49051162Scael break;
49151162Scael case '(':
49251162Scael acc = atoi0();
49351162Scael goto a0;
49451162Scael }
49551162Scael return(acc);
49651162Scael }
49751162Scael
49851162Scael
ckph()49951162Scael long ckph()
50051162Scael {
50151162Scael register tchar i;
50251162Scael register long j;
50351162Scael extern long atoi0();
50451162Scael extern long atoi1();
50551162Scael
50651162Scael if (cbits(i = getch()) == '(')
50751162Scael j = atoi0();
50851162Scael else {
50951162Scael j = atoi1(i);
51051162Scael }
51151162Scael return(j);
51251162Scael }
51351162Scael
51451162Scael
atoi1(ii)51551162Scael long atoi1(ii)
51651162Scael register tchar ii;
51751162Scael {
51851162Scael register i, j, digits;
51951162Scael register long acc;
52051162Scael int neg, abs, field;
52151162Scael
52251162Scael neg = abs = field = digits = 0;
52351162Scael acc = 0;
52451162Scael for (;;) {
52551162Scael i = cbits(ii);
52651162Scael switch (i) {
52751162Scael default:
52851162Scael break;
52951162Scael case '+':
53051162Scael ii = getch();
53151162Scael continue;
53251162Scael case '-':
53351162Scael neg = 1;
53451162Scael ii = getch();
53551162Scael continue;
53651162Scael case '|':
53751162Scael abs = 1 + neg;
53851162Scael neg = 0;
53951162Scael ii = getch();
54051162Scael continue;
54151162Scael }
54251162Scael break;
54351162Scael }
54451162Scael a1:
54551162Scael while (i >= '0' && i <= '9') {
54651162Scael field++;
54751162Scael digits++;
54851162Scael acc = 10 * acc + i - '0';
54951162Scael ii = getch();
55051162Scael i = cbits(ii);
55151162Scael }
55251162Scael if (i == '.') {
55351162Scael field++;
55451162Scael digits = 0;
55551162Scael ii = getch();
55651162Scael i = cbits(ii);
55751162Scael goto a1;
55851162Scael }
55951162Scael if (!field) {
56051162Scael ch = ii;
56151162Scael goto a2;
56251162Scael }
56351162Scael switch (i) {
56451162Scael case 'u':
56551162Scael i = j = 1; /* should this be related to HOR?? */
56651162Scael break;
56751162Scael case 'v': /*VSs - vert spacing*/
56851162Scael j = lss;
56951162Scael i = 1;
57051162Scael break;
57151162Scael case 'm': /*Ems*/
57251162Scael j = EM;
57351162Scael i = 1;
57451162Scael break;
57551162Scael case 'n': /*Ens*/
57651162Scael j = EM;
57751162Scael #ifndef NROFF
57851162Scael i = 2;
57951162Scael #endif
58051162Scael #ifdef NROFF
58151162Scael i = 1; /*Same as Ems in NROFF*/
58251162Scael #endif
58351162Scael break;
58451162Scael case 'p': /*Points*/
58551162Scael j = INCH;
58651162Scael i = 72;
58751162Scael break;
58851162Scael case 'i': /*Inches*/
58951162Scael j = INCH;
59051162Scael i = 1;
59151162Scael break;
59251162Scael case 'c': /*Centimeters*/
59351162Scael /* if INCH is too big, this will overflow */
59451162Scael j = INCH * 50;
59551162Scael i = 127;
59651162Scael break;
59751162Scael case 'P': /*Picas*/
59851162Scael j = INCH;
59951162Scael i = 6;
60051162Scael break;
60151162Scael default:
60251162Scael j = dfact;
60351162Scael ch = ii;
60451162Scael i = dfactd;
60551162Scael }
60651162Scael if (neg)
60751162Scael acc = -acc;
60851162Scael if (!noscale) {
60951162Scael acc = (acc * j) / i;
61051162Scael }
61151162Scael if ((field != digits) && (digits > 0))
61251162Scael while (digits--)
61351162Scael acc /= 10;
61451162Scael if (abs) {
61551162Scael if (dip != d)
61651162Scael j = dip->dnl;
61751162Scael else
61851162Scael j = numtab[NL].val;
61951162Scael if (!vflag) {
62051162Scael j = numtab[HP].val;
62151162Scael }
62251162Scael if (abs == 2)
62351162Scael j = -j;
62451162Scael acc -= j;
62551162Scael }
62651162Scael a2:
62751162Scael nonumb = !field;
62851162Scael return(acc);
62951162Scael }
63051162Scael
63151162Scael
caserr()63251162Scael caserr()
63351162Scael {
63451162Scael register i, j;
63551162Scael register struct numtab *p;
63651162Scael
63751162Scael lgf++;
63851162Scael while (!skip() && (i = getrq()) ) {
63951162Scael j = usedr(i);
64051162Scael if (j < 0)
64151162Scael continue;
64251162Scael p = &numtab[j];
64351162Scael nunhash(p);
64451162Scael p->r = p->val = p->inc = p->fmt = 0;
64551162Scael regcnt--;
64651162Scael }
64751162Scael }
64851162Scael
64951162Scael
casenr()65051162Scael casenr()
65151162Scael {
65251162Scael register i, j;
65351162Scael
65451162Scael lgf++;
65551162Scael skip();
65651162Scael if ((i = findr(getrq())) == -1)
65751162Scael goto rtn;
65851162Scael skip();
65951162Scael j = inumb(&numtab[i].val);
66051162Scael if (nonumb)
66151162Scael goto rtn;
66251162Scael numtab[i].val = j;
66351162Scael skip();
664*54111Scael j = (int)atoi0();
66551162Scael if (nonumb)
66651162Scael goto rtn;
66751162Scael numtab[i].inc = j;
66851162Scael rtn:
66951162Scael return;
67051162Scael }
67151162Scael
67251162Scael
caseaf()67351162Scael caseaf()
67451162Scael {
67551162Scael register i, k;
67651162Scael register tchar j;
67751162Scael
67851162Scael lgf++;
67951162Scael if (skip() || !(i = getrq()) || skip())
68051162Scael return;
68151162Scael k = 0;
68251162Scael j = getch();
68351162Scael if (!isalpha(cbits(j))) {
68451162Scael ch = j;
68551162Scael while ((j = cbits(getch())) >= '0' && j <= '9')
68651162Scael k++;
68751162Scael }
68851162Scael if (!k)
68951162Scael k = j;
69051162Scael numtab[findr(i)].fmt = k & BYTEMASK;
69151162Scael }
69251162Scael
setaf()69351162Scael setaf() /* return format of number register */
69451162Scael {
69551162Scael register int i, j;
69651162Scael
69751162Scael i = usedr(getsn());
69851162Scael if (i == -1)
69951162Scael return;
70051162Scael if (numtab[i].fmt > 20) /* it was probably a, A, i or I */
70151162Scael *pbp++ = numtab[i].fmt;
70251162Scael else
70351162Scael for (j = (numtab[i].fmt ? numtab[i].fmt : 1); j; j--)
70451162Scael *pbp++ = '0';
70551162Scael }
70651162Scael
70751162Scael
vnumb(i)70851162Scael vnumb(i)
70951162Scael int *i;
71051162Scael {
71151162Scael vflag++;
71251162Scael dfact = lss;
71351162Scael res = VERT;
71451162Scael return(inumb(i));
71551162Scael }
71651162Scael
71751162Scael
hnumb(i)71851162Scael hnumb(i)
71951162Scael int *i;
72051162Scael {
72151162Scael dfact = EM;
72251162Scael res = HOR;
72351162Scael return(inumb(i));
72451162Scael }
72551162Scael
72651162Scael
inumb(n)72751162Scael inumb(n)
72851162Scael int *n;
72951162Scael {
73051162Scael register i, j, f;
73151162Scael register tchar ii;
73251162Scael
73351162Scael f = 0;
73451162Scael if (n) {
73551162Scael if ((j = cbits(ii = getch())) == '+')
73651162Scael f = 1;
73751162Scael else if (j == '-')
73851162Scael f = -1;
73951162Scael else
74051162Scael ch = ii;
74151162Scael }
742*54111Scael i = (int)atoi0();
74351162Scael if (n && f)
74451162Scael i = *n + f * i;
74551162Scael i = quant(i, res);
74651162Scael vflag = 0;
74751162Scael res = dfactd = dfact = 1;
74851162Scael if (nonumb)
74951162Scael i = 0;
75051162Scael return(i);
75151162Scael }
75251162Scael
75351162Scael
quant(n,m)75451162Scael quant(n, m)
75551162Scael int n, m;
75651162Scael {
75751162Scael register i, neg;
75851162Scael
75951162Scael neg = 0;
76051162Scael if (n < 0) {
76151162Scael neg++;
76251162Scael n = -n;
76351162Scael }
76451162Scael /* better as i = ((n + (m/2))/m)*m */
76551162Scael i = n / m;
76651162Scael if ((n - m * i) > (m / 2))
76751162Scael i += 1;
76851162Scael i *= m;
76951162Scael if (neg)
77051162Scael i = -i;
77151162Scael return(i);
77251162Scael }
77351162Scael
77451162Scael
775