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