xref: /csrg-svn/old/roff/common_source/n4.c (revision 48302)
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