xref: /csrg-svn/old/roff/common_source/n4.c (revision 7068)
1*7068Srrh #ifndef lint
2*7068Srrh static char sccsid[] = "@(#)n4.c	4.1 06/07/82";
3*7068Srrh #endif lint
4*7068Srrh 
5*7068Srrh #include "tdef.h"
6*7068Srrh extern
7*7068Srrh #include "d.h"
8*7068Srrh extern
9*7068Srrh #include "v.h"
10*7068Srrh #ifdef NROFF
11*7068Srrh extern
12*7068Srrh #include "tw.h"
13*7068Srrh #endif
14*7068Srrh #include "sdef.h"
15*7068Srrh /*
16*7068Srrh troff4.c
17*7068Srrh 
18*7068Srrh number registers, conversion, arithmetic
19*7068Srrh */
20*7068Srrh 
21*7068Srrh extern	int	inchar[LNSIZE], *pinchar;	/* XXX */
22*7068Srrh extern struct s *frame;
23*7068Srrh 
24*7068Srrh extern int ascii;
25*7068Srrh extern int cbuf[NC];
26*7068Srrh extern int *cp;
27*7068Srrh extern int r[NN];
28*7068Srrh extern int *vlist;
29*7068Srrh extern int inc[NN];
30*7068Srrh extern int fmt[NN];
31*7068Srrh extern int ch;
32*7068Srrh extern int lgf;
33*7068Srrh extern int pl;
34*7068Srrh extern int lastl;
35*7068Srrh extern int ralss;
36*7068Srrh extern int totout;
37*7068Srrh extern int nrbits;
38*7068Srrh extern int nonumb;
39*7068Srrh extern int vflag;
40*7068Srrh extern int noscale;
41*7068Srrh extern int dfact;
42*7068Srrh extern int dfactd;
43*7068Srrh extern int po;
44*7068Srrh extern int nform;
45*7068Srrh extern int ll;
46*7068Srrh extern int in;
47*7068Srrh extern int font;
48*7068Srrh extern int bdtab[];
49*7068Srrh extern int lss;
50*7068Srrh extern int pts;
51*7068Srrh extern int fi;
52*7068Srrh extern int res;
53*7068Srrh extern int cwidth;
54*7068Srrh extern int dotT;
55*7068Srrh extern int ev;
56*7068Srrh extern int ne;
57*7068Srrh extern int ad, admod;
58*7068Srrh extern int print;
59*7068Srrh extern int ls;
60*7068Srrh extern int nel, un;
61*7068Srrh extern int xxx;
62*7068Srrh int regcnt = NNAMES;
63*7068Srrh 
64*7068Srrh setn()
65*7068Srrh {
66*7068Srrh 	register i,j;
67*7068Srrh 	int f;
68*7068Srrh 
69*7068Srrh 	f = nform = 0;
70*7068Srrh 	if((i=getch() & CMASK) == '+')f = 1;
71*7068Srrh 		else if(i == '-')f = -1;
72*7068Srrh 			else ch = i;
73*7068Srrh 	if((i=getsn()) == 0)return;
74*7068Srrh 	if((i & 0177) == '.')switch(i>>BYTE){
75*7068Srrh 		case 's': i = pts & 077;	break;
76*7068Srrh 		case 'v': i = lss;		break;
77*7068Srrh 		case 'f': i = font + 1;	break;
78*7068Srrh 		case 'p': i = pl;		break;
79*7068Srrh 		case 't':  i = findt1();	break;
80*7068Srrh 		case 'o': i = po;		break;
81*7068Srrh 		case 'l': i = ll;		break;
82*7068Srrh 		case 'i': i = in;		break;
83*7068Srrh 		case '$': i = frame->nargs;		break;
84*7068Srrh 		case 'A': i = ascii;		break;
85*7068Srrh 		case 'c': i = v.cd;		break;
86*7068Srrh 		case 'n': i = lastl;		break;
87*7068Srrh 		case 'a': i = ralss;		break;
88*7068Srrh 		case 'h': i = dip->hnl;	break;
89*7068Srrh 		case 'd':
90*7068Srrh 			if(dip != d)i = dip->dnl; else i = v.nl;
91*7068Srrh 			break;
92*7068Srrh 		case 'u': i = fi;		break;
93*7068Srrh 		case 'j': i = ad + 2*admod;	break;
94*7068Srrh 		case 'w': i = width(*(pinchar-1));		break;	/* XXX */
95*7068Srrh 		case 'x': i = nel;	break;
96*7068Srrh 		case 'y': i = un;		break;
97*7068Srrh 		case 'T': i = dotT;		break; /*-Tterm used in nroff*/
98*7068Srrh 		case 'V': i = VERT;		break;
99*7068Srrh 		case 'H': i = HOR;		break;
100*7068Srrh 		case 'k': i = ne;		break;
101*7068Srrh 		case 'P': i = print;		break;
102*7068Srrh 		case 'L': i = ls;		break;
103*7068Srrh 		case 'R': i = NN - regcnt;	break;
104*7068Srrh 		case 'z': i = dip->curd;
105*7068Srrh 			cbuf[0] = i & BMASK;
106*7068Srrh 			cbuf[1] = (i >> BYTE) & BMASK;
107*7068Srrh 			cbuf[2] = 0;
108*7068Srrh 			cp = cbuf;
109*7068Srrh 			return;
110*7068Srrh #ifndef NROFF
111*7068Srrh 		case 'b': i = bdtab[font];		break;
112*7068Srrh #endif
113*7068Srrh 
114*7068Srrh 		default:
115*7068Srrh 			goto s0;
116*7068Srrh 	}
117*7068Srrh 	else{
118*7068Srrh s0:
119*7068Srrh 		if((j=findr(i)) == -1)i = 0;
120*7068Srrh 		else{
121*7068Srrh 			i = (vlist[j] = (vlist[j] + inc[j]*f));
122*7068Srrh 			nform = fmt[j];
123*7068Srrh 		}
124*7068Srrh 	}
125*7068Srrh 	setn1(i);
126*7068Srrh 	cp = cbuf;
127*7068Srrh }
128*7068Srrh setn1(i)
129*7068Srrh int i;
130*7068Srrh {
131*7068Srrh 	extern int wrc();
132*7068Srrh 
133*7068Srrh 	cp = cbuf;
134*7068Srrh 	nrbits = 0;
135*7068Srrh 	fnumb(i,wrc);
136*7068Srrh 	*cp = 0;
137*7068Srrh 	cp = cbuf;
138*7068Srrh }
139*7068Srrh findr(i)
140*7068Srrh int i;
141*7068Srrh {
142*7068Srrh 	register j;
143*7068Srrh 	static int numerr;
144*7068Srrh 
145*7068Srrh 	if(i == 0)return(-1);
146*7068Srrh 	for(j=0;j<NN;j++){
147*7068Srrh 		if(i == r[j])break;
148*7068Srrh 	}
149*7068Srrh 	if(j != NN)return(j);
150*7068Srrh 	for(j=0; j<NN; j++){
151*7068Srrh 		if(r[j] == 0){
152*7068Srrh 			r[j] = i;
153*7068Srrh 			regcnt++;
154*7068Srrh 			break;
155*7068Srrh 		}
156*7068Srrh 	}
157*7068Srrh 	if(j==NN){
158*7068Srrh 		if(!numerr)prstrfl("Too many number registers.\n");
159*7068Srrh 		if(++numerr > 1)done2(04); else edone(04);
160*7068Srrh 	}
161*7068Srrh 	return(j);
162*7068Srrh }
163*7068Srrh fnumb(i,f)
164*7068Srrh int i, (*f)();
165*7068Srrh {
166*7068Srrh 	register j;
167*7068Srrh 
168*7068Srrh 	j = 0;
169*7068Srrh 	if(i < 0){
170*7068Srrh 		j = (*f)('-' | nrbits);
171*7068Srrh 		i = -i;
172*7068Srrh 	}
173*7068Srrh 	switch(nform){
174*7068Srrh 		default:
175*7068Srrh 		case '1':
176*7068Srrh 		case 0: return(decml(i,f) + j);
177*7068Srrh 		case 'i':
178*7068Srrh 		case 'I': return(roman(i,f) + j);
179*7068Srrh 		case 'a':
180*7068Srrh 		case 'A': return(abc(i,f) + j);
181*7068Srrh 	}
182*7068Srrh }
183*7068Srrh decml(i,f)
184*7068Srrh int i, (*f)();
185*7068Srrh {
186*7068Srrh 	register j,k;
187*7068Srrh 
188*7068Srrh 	k = 0;
189*7068Srrh 	nform--;
190*7068Srrh 	if((j=i/10) || (nform > 0))k = decml(j,f);
191*7068Srrh 	return(k + (*f)((i%10 + '0') | nrbits));
192*7068Srrh }
193*7068Srrh roman(i,f)
194*7068Srrh int i, (*f)();
195*7068Srrh {
196*7068Srrh 
197*7068Srrh 	if(!i)return((*f)('0' | nrbits));
198*7068Srrh 	if(nform == 'i')return(roman0(i,f,"ixcmz","vldw"));
199*7068Srrh 	else return(roman0(i,f,"IXCMZ","VLDW"));
200*7068Srrh }
201*7068Srrh roman0(i,f,onesp,fivesp)
202*7068Srrh int i, (*f)();
203*7068Srrh char *onesp, *fivesp;
204*7068Srrh {
205*7068Srrh 	register q, rem, k;
206*7068Srrh 
207*7068Srrh 	k = 0;
208*7068Srrh 	if(!i)return(0);
209*7068Srrh 	k = roman0(i/10,f,onesp+1,fivesp+1);
210*7068Srrh 	q = (i=i%10)/5;
211*7068Srrh 	rem = i%5;
212*7068Srrh 	if(rem == 4){
213*7068Srrh 		k += (*f)(*onesp | nrbits);
214*7068Srrh 		if(q)i = *(onesp+1);
215*7068Srrh 			else i = *fivesp;
216*7068Srrh 		return(k += (*f)(i | nrbits));
217*7068Srrh 	}
218*7068Srrh 	if(q)k += (*f)(*fivesp | nrbits);
219*7068Srrh 	while(--rem >= 0)
220*7068Srrh 		k += (*f)(*onesp | nrbits);
221*7068Srrh 	return(k);
222*7068Srrh }
223*7068Srrh abc(i,f)
224*7068Srrh int i, (*f)();
225*7068Srrh {
226*7068Srrh 	if(!i)return((*f)('0' | nrbits));
227*7068Srrh 	else return(abc0(i-1,f));
228*7068Srrh }
229*7068Srrh abc0(i,f)
230*7068Srrh int i, (*f)();
231*7068Srrh {
232*7068Srrh 	register j, k;
233*7068Srrh 
234*7068Srrh 	k = 0;
235*7068Srrh 	if(j=i/26)k = abc0(j-1,f);
236*7068Srrh 	return(k + (*f)((i%26 + nform) | nrbits));
237*7068Srrh }
238*7068Srrh wrc(i)
239*7068Srrh int i;
240*7068Srrh {
241*7068Srrh 	if(cp >= &cbuf[NC])return(0);
242*7068Srrh 	*cp++ = i;
243*7068Srrh 	return(1);
244*7068Srrh }
245*7068Srrh atoi(){
246*7068Srrh 	extern long atoi0();
247*7068Srrh 
248*7068Srrh 	return((int)atoi0());
249*7068Srrh }
250*7068Srrh long atoi0()
251*7068Srrh {
252*7068Srrh 	register ii, k, cnt;
253*7068Srrh 	long i, acc;
254*7068Srrh 	extern long ckph();
255*7068Srrh 
256*7068Srrh 	i = 0; acc = 0;
257*7068Srrh 	nonumb = 0;
258*7068Srrh 	cnt = -1;
259*7068Srrh a0:
260*7068Srrh 	cnt++;
261*7068Srrh 	switch((ii=getch()) & CMASK){
262*7068Srrh 		default:
263*7068Srrh 			ch = ii;
264*7068Srrh 			if(cnt)break;
265*7068Srrh 		case '+':
266*7068Srrh 			i = ckph();
267*7068Srrh 			if(nonumb)break;
268*7068Srrh 			acc += i;
269*7068Srrh 			goto a0;
270*7068Srrh 		case '-':
271*7068Srrh 			i = ckph();
272*7068Srrh 			if(nonumb)break;
273*7068Srrh 			acc -= i;
274*7068Srrh 			goto a0;
275*7068Srrh 		case '*':
276*7068Srrh 			i = ckph();
277*7068Srrh 			if(nonumb)break;
278*7068Srrh 			acc *= i;
279*7068Srrh 			goto a0;
280*7068Srrh 		case '/':
281*7068Srrh 			i = ckph();
282*7068Srrh 			if(nonumb)break;
283*7068Srrh 			if(i == 0){
284*7068Srrh 				prstrfl("Divide by zero.\n");
285*7068Srrh 				acc = 0;
286*7068Srrh 			}else acc /= i;
287*7068Srrh 			goto a0;
288*7068Srrh 		case '%':
289*7068Srrh 			i = ckph();
290*7068Srrh 			if(nonumb)break;
291*7068Srrh 			acc %= i;
292*7068Srrh 			goto a0;
293*7068Srrh 		case '&':	/*and*/
294*7068Srrh 			i = ckph();
295*7068Srrh 			if(nonumb)break;
296*7068Srrh 			if((acc > 0) && (i > 0))acc = 1; else acc = 0;
297*7068Srrh 			goto a0;
298*7068Srrh 		case ':':	/*or*/
299*7068Srrh 			i = ckph();
300*7068Srrh 			if(nonumb)break;
301*7068Srrh 			if((acc > 0) || (i > 0))acc = 1; else acc = 0;
302*7068Srrh 			goto a0;
303*7068Srrh 		case '=':
304*7068Srrh 			if(((ii=getch()) & CMASK) != '=')ch = ii;
305*7068Srrh 			i = ckph();
306*7068Srrh 			if(nonumb){acc = 0; break;}
307*7068Srrh 			if(i == acc)acc = 1;
308*7068Srrh 			else acc = 0;
309*7068Srrh 			goto a0;
310*7068Srrh 		case '>':
311*7068Srrh 			k = 0;
312*7068Srrh 			if(((ii=getch()) & CMASK) == '=')k++; else ch =ii;
313*7068Srrh 			i = ckph();
314*7068Srrh 			if(nonumb){acc = 0; break;}
315*7068Srrh 			if(acc > (i - k))acc = 1; else acc = 0;
316*7068Srrh 			goto a0;
317*7068Srrh 		case '<':
318*7068Srrh 			k = 0;
319*7068Srrh 			if(((ii=getch()) & CMASK) == '=')k++; else ch =ii;
320*7068Srrh 			i = ckph();
321*7068Srrh 			if(nonumb){acc = 0; break;}
322*7068Srrh 			if(acc < (i + k))acc = 1; else acc = 0;
323*7068Srrh 			goto a0;
324*7068Srrh 		case ')': break;
325*7068Srrh 		case '(':
326*7068Srrh 			acc = atoi0();
327*7068Srrh 			goto a0;
328*7068Srrh 	}
329*7068Srrh 	return(acc);
330*7068Srrh }
331*7068Srrh long ckph(){
332*7068Srrh 	register i;
333*7068Srrh 	long j;
334*7068Srrh 	extern long atoi0();
335*7068Srrh 	extern long atoi1();
336*7068Srrh 
337*7068Srrh 	if(((i = getch()) & CMASK) == '(')j = atoi0();
338*7068Srrh 	else{
339*7068Srrh 		ch = i;
340*7068Srrh 		j = atoi1();
341*7068Srrh 	}
342*7068Srrh 	return(j);
343*7068Srrh }
344*7068Srrh long atoi1()
345*7068Srrh {
346*7068Srrh 	register i, j, digits;
347*7068Srrh 	long acc;
348*7068Srrh 	int neg, abs, field;
349*7068Srrh 
350*7068Srrh 	neg = abs = field = digits = 0;
351*7068Srrh 	acc = 0;
352*7068Srrh a0:
353*7068Srrh 	switch((i = getch()) & CMASK){
354*7068Srrh 		default:
355*7068Srrh 			ch = i;
356*7068Srrh 			break;
357*7068Srrh 		case '+':
358*7068Srrh 			goto a0;
359*7068Srrh 		case '-':
360*7068Srrh 			neg = 1;
361*7068Srrh 			goto a0;
362*7068Srrh 		case '|':
363*7068Srrh 			abs = 1 + neg;
364*7068Srrh 			neg = 0;
365*7068Srrh 			goto a0;
366*7068Srrh 	}
367*7068Srrh a1:
368*7068Srrh 	while(((j = ((i = getch()) & CMASK) - '0') >= 0) && (j <= 9)){
369*7068Srrh 		field++;
370*7068Srrh 		digits++;
371*7068Srrh 		acc = 10*acc + j;
372*7068Srrh 	}
373*7068Srrh 	if((i & CMASK) == '.'){
374*7068Srrh 		field++;
375*7068Srrh 		digits = 0;
376*7068Srrh 		goto a1;
377*7068Srrh 	}
378*7068Srrh 	ch = i;
379*7068Srrh 	if(!field)goto a2;
380*7068Srrh 	switch((i = getch()) & CMASK){
381*7068Srrh 		case 'u':
382*7068Srrh 			i = j = 1;
383*7068Srrh 			break;
384*7068Srrh 		case 'v':	/*VSs - vert spacing*/
385*7068Srrh 			j = lss;
386*7068Srrh 			i = 1;
387*7068Srrh 			break;
388*7068Srrh 		case 'm':	/*Ems*/
389*7068Srrh 			j = EM;
390*7068Srrh 			i = 1;
391*7068Srrh 			break;
392*7068Srrh 		case 'n':	/*Ens*/
393*7068Srrh 			j = EM;
394*7068Srrh #ifndef NROFF
395*7068Srrh 			i = 2;
396*7068Srrh #endif
397*7068Srrh #ifdef NROFF
398*7068Srrh 			i = 1;	/*Same as Ems in NROFF*/
399*7068Srrh #endif
400*7068Srrh 			break;
401*7068Srrh 		case 'p':	/*Points*/
402*7068Srrh 			j = INCH;
403*7068Srrh 			i = 72;
404*7068Srrh 			break;
405*7068Srrh 		case 'i':	/*Inches*/
406*7068Srrh 			j = INCH;
407*7068Srrh 			i = 1;
408*7068Srrh 			break;
409*7068Srrh 		case 'c':	/*Centimeters*/
410*7068Srrh 			j = INCH*50;
411*7068Srrh 			i = 127;
412*7068Srrh 			break;
413*7068Srrh 		case 'P':	/*Picas*/
414*7068Srrh 			j = INCH;
415*7068Srrh 			i = 6;
416*7068Srrh 			break;
417*7068Srrh 		default:
418*7068Srrh 			j = dfact;
419*7068Srrh 			ch = i;
420*7068Srrh 			i = dfactd;
421*7068Srrh 	}
422*7068Srrh 	if(neg) acc = -acc;
423*7068Srrh 	if(!noscale){
424*7068Srrh 		acc = (acc*j)/i;
425*7068Srrh 	}
426*7068Srrh 	if((field != digits) && (digits > 0))while(digits--)acc /= 10;
427*7068Srrh 	if(abs){
428*7068Srrh 		if(dip != d)j = dip->dnl; else j = v.nl;
429*7068Srrh 		if(!vflag)j = v.hp = sumhp();	/* XXX */
430*7068Srrh 		if(abs == 2)j = -j;
431*7068Srrh 		acc -= j;
432*7068Srrh 	}
433*7068Srrh a2:
434*7068Srrh 	nonumb = !field;
435*7068Srrh 	return(acc);
436*7068Srrh }
437*7068Srrh caserr(){
438*7068Srrh 	register i,j;
439*7068Srrh 
440*7068Srrh 	lgf++;
441*7068Srrh 	while(!skip() && (i=getrq()) ){
442*7068Srrh 		for(j=NNAMES; j<NN; j++){  /*NNAMES predefined names*/
443*7068Srrh 			if(i == r[j])break;
444*7068Srrh 		}
445*7068Srrh 		if(j!=NN){
446*7068Srrh 			r[j]=vlist[j]=inc[j]=fmt[j]=0;
447*7068Srrh 			regcnt--;
448*7068Srrh 		}
449*7068Srrh 	}
450*7068Srrh }
451*7068Srrh casenr(){
452*7068Srrh 	register i, j;
453*7068Srrh 
454*7068Srrh 	lgf++;
455*7068Srrh 	skip();
456*7068Srrh 	if((i = findr(getrq())) == -1)goto rtn;
457*7068Srrh 	skip();
458*7068Srrh 	j = inumb(&vlist[i]);
459*7068Srrh 	if(nonumb)goto rtn;
460*7068Srrh 	vlist[i] = j;
461*7068Srrh 	skip();
462*7068Srrh 	j = atoi();
463*7068Srrh 	if(nonumb)goto rtn;
464*7068Srrh 	inc[i] = j;
465*7068Srrh rtn:
466*7068Srrh 	return;
467*7068Srrh }
468*7068Srrh caseaf(){
469*7068Srrh 	register i, j, k;
470*7068Srrh 
471*7068Srrh 	lgf++;
472*7068Srrh 	if(skip() || !(i = getrq()) || skip())return;
473*7068Srrh 	k = 0;
474*7068Srrh 	if(!alph(j=getch())){
475*7068Srrh 		ch = j;
476*7068Srrh 		while(((j = getch() & CMASK) >= '0') &&
477*7068Srrh 			(j <= '9'))k++;
478*7068Srrh 	}
479*7068Srrh 	if(!k)k=j;
480*7068Srrh 	fmt[findr(i)] = k & BMASK;
481*7068Srrh }
482*7068Srrh vnumb(i)
483*7068Srrh int *i;
484*7068Srrh {
485*7068Srrh 	vflag++;
486*7068Srrh 	dfact = lss;
487*7068Srrh 	res = VERT;
488*7068Srrh 	return(inumb(i));
489*7068Srrh }
490*7068Srrh hnumb(i)
491*7068Srrh int *i;
492*7068Srrh {
493*7068Srrh 	dfact = EM;
494*7068Srrh 	res = HOR;
495*7068Srrh 	return(inumb(i));
496*7068Srrh }
497*7068Srrh inumb(n)
498*7068Srrh int *n;
499*7068Srrh {
500*7068Srrh 	register i, j, f;
501*7068Srrh 
502*7068Srrh 	f = 0;
503*7068Srrh 	if(n){
504*7068Srrh 	if((j = (i = getch()) & CMASK) == '+')f = 1;
505*7068Srrh 		else if(j == '-')f = -1;
506*7068Srrh 			else ch = i;
507*7068Srrh 	}
508*7068Srrh 	i = atoi();
509*7068Srrh 	if(n && f)i = *n + f*i;
510*7068Srrh 	i = quant(i,res);
511*7068Srrh 	vflag = 0;
512*7068Srrh 	res = dfactd = dfact = 1;
513*7068Srrh 	if(nonumb)i = 0;
514*7068Srrh 	return(i);
515*7068Srrh }
516*7068Srrh quant(n,m)
517*7068Srrh int n, m;
518*7068Srrh {
519*7068Srrh 	register i, neg;
520*7068Srrh 
521*7068Srrh 	neg = 0;
522*7068Srrh 	if(n<0){
523*7068Srrh 		neg++;
524*7068Srrh 		n = -n;
525*7068Srrh 	}
526*7068Srrh 	i = n/m;
527*7068Srrh 	if((n - m*i) > (m/2))i += 1;
528*7068Srrh 	i *= m;
529*7068Srrh 	if(neg)i = -i;
530*7068Srrh 	return(i);
531*7068Srrh }
532