1*48302Sbostic /*-
2*48302Sbostic * Copyright (c) 1991 The Regents of the University of California.
3*48302Sbostic * All rights reserved.
4*48302Sbostic *
5*48302Sbostic * %sccs.include.proprietary.c%
6*48302Sbostic */
7*48302Sbostic
87068Srrh #ifndef lint
9*48302Sbostic static char sccsid[] = "@(#)n4.c 4.2 (Berkeley) 04/18/91";
10*48302Sbostic #endif /* not lint */
117068Srrh
127068Srrh #include "tdef.h"
137068Srrh extern
147068Srrh #include "d.h"
157068Srrh extern
167068Srrh #include "v.h"
177068Srrh #ifdef NROFF
187068Srrh extern
197068Srrh #include "tw.h"
207068Srrh #endif
217068Srrh #include "sdef.h"
227068Srrh /*
237068Srrh troff4.c
247068Srrh
257068Srrh number registers, conversion, arithmetic
267068Srrh */
277068Srrh
287068Srrh extern int inchar[LNSIZE], *pinchar; /* XXX */
297068Srrh extern struct s *frame;
307068Srrh
317068Srrh extern int ascii;
327068Srrh extern int cbuf[NC];
337068Srrh extern int *cp;
347068Srrh extern int r[NN];
357068Srrh extern int *vlist;
367068Srrh extern int inc[NN];
377068Srrh extern int fmt[NN];
387068Srrh extern int ch;
397068Srrh extern int lgf;
407068Srrh extern int pl;
417068Srrh extern int lastl;
427068Srrh extern int ralss;
437068Srrh extern int totout;
447068Srrh extern int nrbits;
457068Srrh extern int nonumb;
467068Srrh extern int vflag;
477068Srrh extern int noscale;
487068Srrh extern int dfact;
497068Srrh extern int dfactd;
507068Srrh extern int po;
517068Srrh extern int nform;
527068Srrh extern int ll;
537068Srrh extern int in;
547068Srrh extern int font;
557068Srrh extern int bdtab[];
567068Srrh extern int lss;
577068Srrh extern int pts;
587068Srrh extern int fi;
597068Srrh extern int res;
607068Srrh extern int cwidth;
617068Srrh extern int dotT;
627068Srrh extern int ev;
637068Srrh extern int ne;
647068Srrh extern int ad, admod;
657068Srrh extern int print;
667068Srrh extern int ls;
677068Srrh extern int nel, un;
687068Srrh extern int xxx;
697068Srrh int regcnt = NNAMES;
707068Srrh
setn()717068Srrh setn()
727068Srrh {
737068Srrh register i,j;
747068Srrh int f;
757068Srrh
767068Srrh f = nform = 0;
777068Srrh if((i=getch() & CMASK) == '+')f = 1;
787068Srrh else if(i == '-')f = -1;
797068Srrh else ch = i;
807068Srrh if((i=getsn()) == 0)return;
817068Srrh if((i & 0177) == '.')switch(i>>BYTE){
827068Srrh case 's': i = pts & 077; break;
837068Srrh case 'v': i = lss; break;
847068Srrh case 'f': i = font + 1; break;
857068Srrh case 'p': i = pl; break;
867068Srrh case 't': i = findt1(); break;
877068Srrh case 'o': i = po; break;
887068Srrh case 'l': i = ll; break;
897068Srrh case 'i': i = in; break;
907068Srrh case '$': i = frame->nargs; break;
917068Srrh case 'A': i = ascii; break;
927068Srrh case 'c': i = v.cd; break;
937068Srrh case 'n': i = lastl; break;
947068Srrh case 'a': i = ralss; break;
957068Srrh case 'h': i = dip->hnl; break;
967068Srrh case 'd':
977068Srrh if(dip != d)i = dip->dnl; else i = v.nl;
987068Srrh break;
997068Srrh case 'u': i = fi; break;
1007068Srrh case 'j': i = ad + 2*admod; break;
1017068Srrh case 'w': i = width(*(pinchar-1)); break; /* XXX */
1027068Srrh case 'x': i = nel; break;
1037068Srrh case 'y': i = un; break;
1047068Srrh case 'T': i = dotT; break; /*-Tterm used in nroff*/
1057068Srrh case 'V': i = VERT; break;
1067068Srrh case 'H': i = HOR; break;
1077068Srrh case 'k': i = ne; break;
1087068Srrh case 'P': i = print; break;
1097068Srrh case 'L': i = ls; break;
1107068Srrh case 'R': i = NN - regcnt; break;
1117068Srrh case 'z': i = dip->curd;
1127068Srrh cbuf[0] = i & BMASK;
1137068Srrh cbuf[1] = (i >> BYTE) & BMASK;
1147068Srrh cbuf[2] = 0;
1157068Srrh cp = cbuf;
1167068Srrh return;
1177068Srrh #ifndef NROFF
1187068Srrh case 'b': i = bdtab[font]; break;
1197068Srrh #endif
1207068Srrh
1217068Srrh default:
1227068Srrh goto s0;
1237068Srrh }
1247068Srrh else{
1257068Srrh s0:
1267068Srrh if((j=findr(i)) == -1)i = 0;
1277068Srrh else{
1287068Srrh i = (vlist[j] = (vlist[j] + inc[j]*f));
1297068Srrh nform = fmt[j];
1307068Srrh }
1317068Srrh }
1327068Srrh setn1(i);
1337068Srrh cp = cbuf;
1347068Srrh }
setn1(i)1357068Srrh setn1(i)
1367068Srrh int i;
1377068Srrh {
1387068Srrh extern int wrc();
1397068Srrh
1407068Srrh cp = cbuf;
1417068Srrh nrbits = 0;
1427068Srrh fnumb(i,wrc);
1437068Srrh *cp = 0;
1447068Srrh cp = cbuf;
1457068Srrh }
findr(i)1467068Srrh findr(i)
1477068Srrh int i;
1487068Srrh {
1497068Srrh register j;
1507068Srrh static int numerr;
1517068Srrh
1527068Srrh if(i == 0)return(-1);
1537068Srrh for(j=0;j<NN;j++){
1547068Srrh if(i == r[j])break;
1557068Srrh }
1567068Srrh if(j != NN)return(j);
1577068Srrh for(j=0; j<NN; j++){
1587068Srrh if(r[j] == 0){
1597068Srrh r[j] = i;
1607068Srrh regcnt++;
1617068Srrh break;
1627068Srrh }
1637068Srrh }
1647068Srrh if(j==NN){
1657068Srrh if(!numerr)prstrfl("Too many number registers.\n");
1667068Srrh if(++numerr > 1)done2(04); else edone(04);
1677068Srrh }
1687068Srrh return(j);
1697068Srrh }
1707068Srrh fnumb(i,f)
1717068Srrh int i, (*f)();
1727068Srrh {
1737068Srrh register j;
1747068Srrh
1757068Srrh j = 0;
1767068Srrh if(i < 0){
1777068Srrh j = (*f)('-' | nrbits);
1787068Srrh i = -i;
1797068Srrh }
1807068Srrh switch(nform){
1817068Srrh default:
1827068Srrh case '1':
1837068Srrh case 0: return(decml(i,f) + j);
1847068Srrh case 'i':
1857068Srrh case 'I': return(roman(i,f) + j);
1867068Srrh case 'a':
1877068Srrh case 'A': return(abc(i,f) + j);
1887068Srrh }
1897068Srrh }
1907068Srrh decml(i,f)
1917068Srrh int i, (*f)();
1927068Srrh {
1937068Srrh register j,k;
1947068Srrh
1957068Srrh k = 0;
1967068Srrh nform--;
1977068Srrh if((j=i/10) || (nform > 0))k = decml(j,f);
1987068Srrh return(k + (*f)((i%10 + '0') | nrbits));
1997068Srrh }
2007068Srrh roman(i,f)
2017068Srrh int i, (*f)();
2027068Srrh {
2037068Srrh
2047068Srrh if(!i)return((*f)('0' | nrbits));
2057068Srrh if(nform == 'i')return(roman0(i,f,"ixcmz","vldw"));
2067068Srrh else return(roman0(i,f,"IXCMZ","VLDW"));
2077068Srrh }
2087068Srrh roman0(i,f,onesp,fivesp)
2097068Srrh int i, (*f)();
2107068Srrh char *onesp, *fivesp;
2117068Srrh {
2127068Srrh register q, rem, k;
2137068Srrh
2147068Srrh k = 0;
2157068Srrh if(!i)return(0);
2167068Srrh k = roman0(i/10,f,onesp+1,fivesp+1);
2177068Srrh q = (i=i%10)/5;
2187068Srrh rem = i%5;
2197068Srrh if(rem == 4){
2207068Srrh k += (*f)(*onesp | nrbits);
2217068Srrh if(q)i = *(onesp+1);
2227068Srrh else i = *fivesp;
2237068Srrh return(k += (*f)(i | nrbits));
2247068Srrh }
2257068Srrh if(q)k += (*f)(*fivesp | nrbits);
2267068Srrh while(--rem >= 0)
2277068Srrh k += (*f)(*onesp | nrbits);
2287068Srrh return(k);
2297068Srrh }
2307068Srrh abc(i,f)
2317068Srrh int i, (*f)();
2327068Srrh {
2337068Srrh if(!i)return((*f)('0' | nrbits));
2347068Srrh else return(abc0(i-1,f));
2357068Srrh }
2367068Srrh abc0(i,f)
2377068Srrh int i, (*f)();
2387068Srrh {
2397068Srrh register j, k;
2407068Srrh
2417068Srrh k = 0;
2427068Srrh if(j=i/26)k = abc0(j-1,f);
2437068Srrh return(k + (*f)((i%26 + nform) | nrbits));
2447068Srrh }
wrc(i)2457068Srrh wrc(i)
2467068Srrh int i;
2477068Srrh {
2487068Srrh if(cp >= &cbuf[NC])return(0);
2497068Srrh *cp++ = i;
2507068Srrh return(1);
2517068Srrh }
atoi()2527068Srrh atoi(){
2537068Srrh extern long atoi0();
2547068Srrh
2557068Srrh return((int)atoi0());
2567068Srrh }
atoi0()2577068Srrh long atoi0()
2587068Srrh {
2597068Srrh register ii, k, cnt;
2607068Srrh long i, acc;
2617068Srrh extern long ckph();
2627068Srrh
2637068Srrh i = 0; acc = 0;
2647068Srrh nonumb = 0;
2657068Srrh cnt = -1;
2667068Srrh a0:
2677068Srrh cnt++;
2687068Srrh switch((ii=getch()) & CMASK){
2697068Srrh default:
2707068Srrh ch = ii;
2717068Srrh if(cnt)break;
2727068Srrh case '+':
2737068Srrh i = ckph();
2747068Srrh if(nonumb)break;
2757068Srrh acc += i;
2767068Srrh goto a0;
2777068Srrh case '-':
2787068Srrh i = ckph();
2797068Srrh if(nonumb)break;
2807068Srrh acc -= i;
2817068Srrh goto a0;
2827068Srrh case '*':
2837068Srrh i = ckph();
2847068Srrh if(nonumb)break;
2857068Srrh acc *= i;
2867068Srrh goto a0;
2877068Srrh case '/':
2887068Srrh i = ckph();
2897068Srrh if(nonumb)break;
2907068Srrh if(i == 0){
2917068Srrh prstrfl("Divide by zero.\n");
2927068Srrh acc = 0;
2937068Srrh }else acc /= i;
2947068Srrh goto a0;
2957068Srrh case '%':
2967068Srrh i = ckph();
2977068Srrh if(nonumb)break;
2987068Srrh acc %= i;
2997068Srrh goto a0;
3007068Srrh case '&': /*and*/
3017068Srrh i = ckph();
3027068Srrh if(nonumb)break;
3037068Srrh if((acc > 0) && (i > 0))acc = 1; else acc = 0;
3047068Srrh goto a0;
3057068Srrh case ':': /*or*/
3067068Srrh i = ckph();
3077068Srrh if(nonumb)break;
3087068Srrh if((acc > 0) || (i > 0))acc = 1; else acc = 0;
3097068Srrh goto a0;
3107068Srrh case '=':
3117068Srrh if(((ii=getch()) & CMASK) != '=')ch = ii;
3127068Srrh i = ckph();
3137068Srrh if(nonumb){acc = 0; break;}
3147068Srrh if(i == acc)acc = 1;
3157068Srrh else acc = 0;
3167068Srrh goto a0;
3177068Srrh case '>':
3187068Srrh k = 0;
3197068Srrh if(((ii=getch()) & CMASK) == '=')k++; else ch =ii;
3207068Srrh i = ckph();
3217068Srrh if(nonumb){acc = 0; break;}
3227068Srrh if(acc > (i - k))acc = 1; else acc = 0;
3237068Srrh goto a0;
3247068Srrh case '<':
3257068Srrh k = 0;
3267068Srrh if(((ii=getch()) & CMASK) == '=')k++; else ch =ii;
3277068Srrh i = ckph();
3287068Srrh if(nonumb){acc = 0; break;}
3297068Srrh if(acc < (i + k))acc = 1; else acc = 0;
3307068Srrh goto a0;
3317068Srrh case ')': break;
3327068Srrh case '(':
3337068Srrh acc = atoi0();
3347068Srrh goto a0;
3357068Srrh }
3367068Srrh return(acc);
3377068Srrh }
ckph()3387068Srrh long ckph(){
3397068Srrh register i;
3407068Srrh long j;
3417068Srrh extern long atoi0();
3427068Srrh extern long atoi1();
3437068Srrh
3447068Srrh if(((i = getch()) & CMASK) == '(')j = atoi0();
3457068Srrh else{
3467068Srrh ch = i;
3477068Srrh j = atoi1();
3487068Srrh }
3497068Srrh return(j);
3507068Srrh }
atoi1()3517068Srrh long atoi1()
3527068Srrh {
3537068Srrh register i, j, digits;
3547068Srrh long acc;
3557068Srrh int neg, abs, field;
3567068Srrh
3577068Srrh neg = abs = field = digits = 0;
3587068Srrh acc = 0;
3597068Srrh a0:
3607068Srrh switch((i = getch()) & CMASK){
3617068Srrh default:
3627068Srrh ch = i;
3637068Srrh break;
3647068Srrh case '+':
3657068Srrh goto a0;
3667068Srrh case '-':
3677068Srrh neg = 1;
3687068Srrh goto a0;
3697068Srrh case '|':
3707068Srrh abs = 1 + neg;
3717068Srrh neg = 0;
3727068Srrh goto a0;
3737068Srrh }
3747068Srrh a1:
3757068Srrh while(((j = ((i = getch()) & CMASK) - '0') >= 0) && (j <= 9)){
3767068Srrh field++;
3777068Srrh digits++;
3787068Srrh acc = 10*acc + j;
3797068Srrh }
3807068Srrh if((i & CMASK) == '.'){
3817068Srrh field++;
3827068Srrh digits = 0;
3837068Srrh goto a1;
3847068Srrh }
3857068Srrh ch = i;
3867068Srrh if(!field)goto a2;
3877068Srrh switch((i = getch()) & CMASK){
3887068Srrh case 'u':
3897068Srrh i = j = 1;
3907068Srrh break;
3917068Srrh case 'v': /*VSs - vert spacing*/
3927068Srrh j = lss;
3937068Srrh i = 1;
3947068Srrh break;
3957068Srrh case 'm': /*Ems*/
3967068Srrh j = EM;
3977068Srrh i = 1;
3987068Srrh break;
3997068Srrh case 'n': /*Ens*/
4007068Srrh j = EM;
4017068Srrh #ifndef NROFF
4027068Srrh i = 2;
4037068Srrh #endif
4047068Srrh #ifdef NROFF
4057068Srrh i = 1; /*Same as Ems in NROFF*/
4067068Srrh #endif
4077068Srrh break;
4087068Srrh case 'p': /*Points*/
4097068Srrh j = INCH;
4107068Srrh i = 72;
4117068Srrh break;
4127068Srrh case 'i': /*Inches*/
4137068Srrh j = INCH;
4147068Srrh i = 1;
4157068Srrh break;
4167068Srrh case 'c': /*Centimeters*/
4177068Srrh j = INCH*50;
4187068Srrh i = 127;
4197068Srrh break;
4207068Srrh case 'P': /*Picas*/
4217068Srrh j = INCH;
4227068Srrh i = 6;
4237068Srrh break;
4247068Srrh default:
4257068Srrh j = dfact;
4267068Srrh ch = i;
4277068Srrh i = dfactd;
4287068Srrh }
4297068Srrh if(neg) acc = -acc;
4307068Srrh if(!noscale){
4317068Srrh acc = (acc*j)/i;
4327068Srrh }
4337068Srrh if((field != digits) && (digits > 0))while(digits--)acc /= 10;
4347068Srrh if(abs){
4357068Srrh if(dip != d)j = dip->dnl; else j = v.nl;
4367068Srrh if(!vflag)j = v.hp = sumhp(); /* XXX */
4377068Srrh if(abs == 2)j = -j;
4387068Srrh acc -= j;
4397068Srrh }
4407068Srrh a2:
4417068Srrh nonumb = !field;
4427068Srrh return(acc);
4437068Srrh }
caserr()4447068Srrh caserr(){
4457068Srrh register i,j;
4467068Srrh
4477068Srrh lgf++;
4487068Srrh while(!skip() && (i=getrq()) ){
4497068Srrh for(j=NNAMES; j<NN; j++){ /*NNAMES predefined names*/
4507068Srrh if(i == r[j])break;
4517068Srrh }
4527068Srrh if(j!=NN){
4537068Srrh r[j]=vlist[j]=inc[j]=fmt[j]=0;
4547068Srrh regcnt--;
4557068Srrh }
4567068Srrh }
4577068Srrh }
casenr()4587068Srrh casenr(){
4597068Srrh register i, j;
4607068Srrh
4617068Srrh lgf++;
4627068Srrh skip();
4637068Srrh if((i = findr(getrq())) == -1)goto rtn;
4647068Srrh skip();
4657068Srrh j = inumb(&vlist[i]);
4667068Srrh if(nonumb)goto rtn;
4677068Srrh vlist[i] = j;
4687068Srrh skip();
4697068Srrh j = atoi();
4707068Srrh if(nonumb)goto rtn;
4717068Srrh inc[i] = j;
4727068Srrh rtn:
4737068Srrh return;
4747068Srrh }
caseaf()4757068Srrh caseaf(){
4767068Srrh register i, j, k;
4777068Srrh
4787068Srrh lgf++;
4797068Srrh if(skip() || !(i = getrq()) || skip())return;
4807068Srrh k = 0;
4817068Srrh if(!alph(j=getch())){
4827068Srrh ch = j;
4837068Srrh while(((j = getch() & CMASK) >= '0') &&
4847068Srrh (j <= '9'))k++;
4857068Srrh }
4867068Srrh if(!k)k=j;
4877068Srrh fmt[findr(i)] = k & BMASK;
4887068Srrh }
vnumb(i)4897068Srrh vnumb(i)
4907068Srrh int *i;
4917068Srrh {
4927068Srrh vflag++;
4937068Srrh dfact = lss;
4947068Srrh res = VERT;
4957068Srrh return(inumb(i));
4967068Srrh }
hnumb(i)4977068Srrh hnumb(i)
4987068Srrh int *i;
4997068Srrh {
5007068Srrh dfact = EM;
5017068Srrh res = HOR;
5027068Srrh return(inumb(i));
5037068Srrh }
inumb(n)5047068Srrh inumb(n)
5057068Srrh int *n;
5067068Srrh {
5077068Srrh register i, j, f;
5087068Srrh
5097068Srrh f = 0;
5107068Srrh if(n){
5117068Srrh if((j = (i = getch()) & CMASK) == '+')f = 1;
5127068Srrh else if(j == '-')f = -1;
5137068Srrh else ch = i;
5147068Srrh }
5157068Srrh i = atoi();
5167068Srrh if(n && f)i = *n + f*i;
5177068Srrh i = quant(i,res);
5187068Srrh vflag = 0;
5197068Srrh res = dfactd = dfact = 1;
5207068Srrh if(nonumb)i = 0;
5217068Srrh return(i);
5227068Srrh }
quant(n,m)5237068Srrh quant(n,m)
5247068Srrh int n, m;
5257068Srrh {
5267068Srrh register i, neg;
5277068Srrh
5287068Srrh neg = 0;
5297068Srrh if(n<0){
5307068Srrh neg++;
5317068Srrh n = -n;
5327068Srrh }
5337068Srrh i = n/m;
5347068Srrh if((n - m*i) > (m/2))i += 1;
5357068Srrh i *= m;
5367068Srrh if(neg)i = -i;
5377068Srrh return(i);
5387068Srrh }
539