1 #include	<ctype.h>
2 #include "tdef.h"
3 extern
4 #include "d.h"
5 extern
6 #include "v.h"
7 #ifdef NROFF
8 extern
9 #include "tw.h"
10 #endif
11 #include "s.h"
12 /*
13 troff4.c
14 
15 number registers, conversion, arithmetic
16 */
17 
18 #include <sgtty.h>
19 #include "ext.h"
20 
21 int	regcnt = NNAMES;
22 int	falsef	= 0;	/* on if inside false branch of if */
23 
24 setn()
25 {
26 	register i, j;
27 	tchar ii;
28 	int	f;
29 
30 	f = nform = 0;
31 	lgf++;					/* don't catch ligatures */
32 	if ((i = cbits(ii = getch())) == '+')
33 		f = 1;
34 	else if (i == '-')
35 		f = -1;
36 	else
37 		ch = ii;
38 	lgf--;					/* ok, catch `em again */
39 	if (falsef)
40 		f = 0;
41 	if ((i = getsn()) == 0)
42 		return;
43 	if ((i & 0177) == '.')
44 		switch (i >> BYTE) {
45 		case 's':
46 			i = pts;
47 			break;
48 		case 'v':
49 			i = lss;
50 			break;
51 		case 'f':
52 			i = font;
53 			break;
54 		case 'p':
55 			i = pl;
56 			break;
57 		case 't':
58 			i = findt1();
59 			break;
60 		case 'o':
61 			i = po;
62 			break;
63 		case 'l':
64 			i = ll;
65 			break;
66 		case 'i':
67 			i = in;
68 			break;
69 		case '$':
70 			i = frame->nargs;
71 			break;
72 		case 'A':
73 			i = ascii;
74 			break;
75 		case 'c':
76 			i = v.cd;
77 			break;
78 		case 'n':
79 			i = lastl;
80 			break;
81 		case 'a':
82 			i = ralss;
83 			break;
84 		case 'h':
85 			i = dip->hnl;
86 			break;
87 		case 'd':
88 			if (dip != d)
89 				i = dip->dnl;
90 			else
91 				i = v.nl;
92 			break;
93 		case 'u':
94 			i = fi;
95 			break;
96 		case 'j':
97 			i = ad + 2 * admod;
98 			break;
99 		case 'w':
100 			i = width(*(pinchar-1));	/* XXX */
101 			break;
102 		case 'x':
103 			i = nel;
104 			break;
105 		case 'y':
106 			i = un;
107 			break;
108 		case 'T':
109 			i = dotT;
110 			break; /*-Tterm used in nroff*/
111 		case 'V':
112 			i = VERT;
113 			break;
114 		case 'H':
115 			i = HOR;
116 			break;
117 		case 'k':
118 			i = ne;
119 			break;
120 		case 'P':
121 			i = print;
122 			break;
123 		case 'L':
124 			i = ls;
125 			break;
126 		case 'R':
127 			i = NN - regcnt;
128 			break;
129 		case 'z':
130 			i = dip->curd;
131 			cbuf[0] = i & BMASK;
132 			cbuf[1] = (i >> BYTE) & BMASK;
133 			cbuf[2] = 0;
134 			cp = cbuf;
135 			return;
136 		case 'b':
137 			i = bdtab[font];
138 			break;
139 
140 		default:
141 			goto s0;
142 		}
143 	else {
144 s0:
145 		if ((j = findr(i)) == -1)
146 			i = 0;
147 		else {
148 			i = (vlist[j] = (vlist[j] + inc[j] * f));
149 			nform = fmt[j];
150 		}
151 	}
152 	setn1(i);
153 	cp = cbuf;
154 }
155 
156 
157 setn1(i)
158 int	i;
159 {
160 	extern int	wrc();
161 
162 	cp = cbuf;
163 	nrbits = 0;
164 	fnumb(i, wrc);
165 	*cp = 0;
166 	cp = cbuf;
167 }
168 
169 
170 findr(i)
171 register int	i;
172 {
173 	register j;
174 	register int *p;
175 
176 	if (i == 0)
177 		return(-1);
178 	for (p = r; p < &r[NN]; p++) {
179 		if (i == *p)
180 			break;
181 	}
182 	if (p != &r[NN])
183 		return(p - r);
184 	for (p = r; p < &r[NN]; p++) {
185 		if (*p == 0) {
186 			*p = i;
187 			regcnt++;
188 			break;
189 		}
190 	}
191 	if (p == &r[NN]) {
192 		fprintf(stderr, "troff: too many number registers (%d).\n", NN);
193 		done2(04);
194 	}
195 	return(p - r);
196 }
197 
198 usedr(i)	/* returns -1 if nr i has never been used */
199 register int	i;
200 {
201 	register j;
202 	register int *p;
203 
204 	if (i == 0)
205 		return(-1);
206 	for (p = r; p < &r[NN]; p++) {
207 		if (i == *p)
208 			break;
209 	}
210 	if (p != &r[NN])
211 		return(p - r);
212 	else
213 		return -1;
214 }
215 
216 
217 fnumb(i, f)
218 int	i, (*f)();
219 {
220 	register j;
221 
222 	j = 0;
223 	if (i < 0) {
224 		j = (*f)('-' | nrbits);
225 		i = -i;
226 	}
227 	switch (nform) {
228 	default:
229 	case '1':
230 	case 0:
231 		return(decml(i, f) + j);
232 	case 'i':
233 	case 'I':
234 		return(roman(i, f) + j);
235 	case 'a':
236 	case 'A':
237 		return(abc(i, f) + j);
238 	}
239 }
240 
241 
242 decml(i, f)
243 int	i, (*f)();
244 {
245 	register j, k;
246 
247 	k = 0;
248 	nform--;
249 	if ((j = i / 10) || (nform > 0))
250 		k = decml(j, f);
251 	return(k + (*f)((i % 10 + '0') | nrbits));
252 }
253 
254 
255 roman(i, f)
256 int	i, (*f)();
257 {
258 
259 	if (!i)
260 		return((*f)('0' | nrbits));
261 	if (nform == 'i')
262 		return(roman0(i, f, "ixcmz", "vldw"));
263 	else
264 		return(roman0(i, f, "IXCMZ", "VLDW"));
265 }
266 
267 
268 roman0(i, f, onesp, fivesp)
269 int	i, (*f)();
270 char	*onesp, *fivesp;
271 {
272 	register q, rem, k;
273 
274 	k = 0;
275 	if (!i)
276 		return(0);
277 	k = roman0(i / 10, f, onesp + 1, fivesp + 1);
278 	q = (i = i % 10) / 5;
279 	rem = i % 5;
280 	if (rem == 4) {
281 		k += (*f)(*onesp | nrbits);
282 		if (q)
283 			i = *(onesp + 1);
284 		else
285 			i = *fivesp;
286 		return(k += (*f)(i | nrbits));
287 	}
288 	if (q)
289 		k += (*f)(*fivesp | nrbits);
290 	while (--rem >= 0)
291 		k += (*f)(*onesp | nrbits);
292 	return(k);
293 }
294 
295 
296 abc(i, f)
297 int	i, (*f)();
298 {
299 	if (!i)
300 		return((*f)('0' | nrbits));
301 	else
302 		return(abc0(i - 1, f));
303 }
304 
305 
306 abc0(i, f)
307 int	i, (*f)();
308 {
309 	register j, k;
310 
311 	k = 0;
312 	if (j = i / 26)
313 		k = abc0(j - 1, f);
314 	return(k + (*f)((i % 26 + nform) | nrbits));
315 }
316 
317 
318 wrc(i)
319 tchar i;
320 {
321 	if (cp >= &cbuf[NC])
322 		return(0);
323 	*cp++ = i;
324 	return(1);
325 }
326 
327 
328 long	atoi0()
329 {
330 	register c, k, cnt;
331 	tchar ii;
332 	long	i, acc;
333 	extern long	ckph();
334 
335 	i = 0;
336 	acc = 0;
337 	nonumb = 0;
338 	cnt = -1;
339 a0:
340 	cnt++;
341 	ii = getch();
342 	c = cbits(ii);
343 	switch (c) {
344 	default:
345 		ch = ii;
346 		if (cnt)
347 			break;
348 	case '+':
349 		i = ckph();
350 		if (nonumb)
351 			break;
352 		acc += i;
353 		goto a0;
354 	case '-':
355 		i = ckph();
356 		if (nonumb)
357 			break;
358 		acc -= i;
359 		goto a0;
360 	case '*':
361 		i = ckph();
362 		if (nonumb)
363 			break;
364 		acc *= i;
365 		goto a0;
366 	case '/':
367 		i = ckph();
368 		if (nonumb)
369 			break;
370 		if (i == 0) {
371 			flusho();
372 			fprintf(stderr, "troff: divide by zero.\n");
373 			acc = 0;
374 		} else
375 			acc /= i;
376 		goto a0;
377 	case '%':
378 		i = ckph();
379 		if (nonumb)
380 			break;
381 		acc %= i;
382 		goto a0;
383 	case '&':	/*and*/
384 		i = ckph();
385 		if (nonumb)
386 			break;
387 		if ((acc > 0) && (i > 0))
388 			acc = 1;
389 		else
390 			acc = 0;
391 		goto a0;
392 	case ':':	/*or*/
393 		i = ckph();
394 		if (nonumb)
395 			break;
396 		if ((acc > 0) || (i > 0))
397 			acc = 1;
398 		else
399 			acc = 0;
400 		goto a0;
401 	case '=':
402 		if (cbits(ii = getch()) != '=')
403 			ch = ii;
404 		i = ckph();
405 		if (nonumb) {
406 			acc = 0;
407 			break;
408 		}
409 		if (i == acc)
410 			acc = 1;
411 		else
412 			acc = 0;
413 		goto a0;
414 	case '>':
415 		k = 0;
416 		if (cbits(ii = getch()) == '=')
417 			k++;
418 		else
419 			ch = ii;
420 		i = ckph();
421 		if (nonumb) {
422 			acc = 0;
423 			break;
424 		}
425 		if (acc > (i - k))
426 			acc = 1;
427 		else
428 			acc = 0;
429 		goto a0;
430 	case '<':
431 		k = 0;
432 		if (cbits(ii = getch()) == '=')
433 			k++;
434 		else
435 			ch = ii;
436 		i = ckph();
437 		if (nonumb) {
438 			acc = 0;
439 			break;
440 		}
441 		if (acc < (i + k))
442 			acc = 1;
443 		else
444 			acc = 0;
445 		goto a0;
446 	case ')':
447 		break;
448 	case '(':
449 		acc = atoi0();
450 		goto a0;
451 	}
452 	return(acc);
453 }
454 
455 
456 long	ckph()
457 {
458 	tchar i;
459 	long	j;
460 	extern long	atoi0();
461 	extern long	atoi1();
462 
463 	if (cbits(i = getch()) == '(')
464 		j = atoi0();
465 	else {
466 		ch = i;
467 		j = atoi1();
468 	}
469 	return(j);
470 }
471 
472 
473 long	atoi1()
474 {
475 	register i, j, digits;
476 	tchar ii;
477 	long	acc;
478 	int	neg, abs, field;
479 
480 	neg = abs = field = digits = 0;
481 	acc = 0;
482 a0:
483 	ii = getch();
484 	i = cbits(ii);
485 	switch (i) {
486 	default:
487 		ch = ii;
488 		break;
489 	case '+':
490 		goto a0;
491 	case '-':
492 		neg = 1;
493 		goto a0;
494 	case '|':
495 		abs = 1 + neg;
496 		neg = 0;
497 		goto a0;
498 	}
499 a1:
500 	while (((j = (cbits(ii = getch())) - '0') >= 0) && (j <= 9)) {
501 		field++;
502 		digits++;
503 		acc = 10 * acc + j;
504 	}
505 	if (cbits(ii) == '.') {
506 		field++;
507 		digits = 0;
508 		goto a1;
509 	}
510 	ch = ii;
511 	if (!field)
512 		goto a2;
513 	ii = getch();
514 	switch (i = cbits(ii)) {
515 	case 'u':
516 		i = j = 1;	/* should this be related to HOR?? */
517 		break;
518 	case 'v':	/*VSs - vert spacing*/
519 		j = lss;
520 		i = 1;
521 		break;
522 	case 'm':	/*Ems*/
523 		j = EM;
524 		i = 1;
525 		break;
526 	case 'n':	/*Ens*/
527 		j = EM;
528 #ifndef NROFF
529 		i = 2;
530 #endif
531 #ifdef NROFF
532 		i = 1;	/*Same as Ems in NROFF*/
533 #endif
534 		break;
535 	case 'p':	/*Points*/
536 		j = INCH;
537 		i = 72;
538 		break;
539 	case 'i':	/*Inches*/
540 		j = INCH;
541 		i = 1;
542 		break;
543 	case 'c':	/*Centimeters*/
544 		/* if INCH is too big, this will overflow */
545 		j = INCH * 50;
546 		i = 127;
547 		break;
548 	case 'P':	/*Picas*/
549 		j = INCH;
550 		i = 6;
551 		break;
552 	default:
553 		j = dfact;
554 		ch = ii;
555 		i = dfactd;
556 	}
557 	if (neg)
558 		acc = -acc;
559 	if (!noscale) {
560 		acc = (acc * j) / i;
561 	}
562 	if ((field != digits) && (digits > 0))
563 		while (digits--)
564 			acc /= 10;
565 	if (abs) {
566 		if (dip != d)
567 			j = dip->dnl;
568 		else
569 			j = v.nl;
570 		if (!vflag) {
571 			j = v.hp = sumhp();	/* XXX */
572 		}
573 		if (abs == 2)
574 			j = -j;
575 		acc -= j;
576 	}
577 a2:
578 	nonumb = !field;
579 	return(acc);
580 }
581 
582 
583 caserr()
584 {
585 	register i, j;
586 
587 	lgf++;
588 	while (!skip() && (i = getrq()) ) {
589 		for (j = NNAMES; j < NN; j++) {  /*NNAMES predefined names*/
590 			if (i == r[j])
591 				break;
592 		}
593 		if (j != NN) {
594 			r[j] = vlist[j] = inc[j] = fmt[j] = 0;
595 			regcnt--;
596 		}
597 	}
598 }
599 
600 
601 casenr()
602 {
603 	register i, j;
604 
605 	lgf++;
606 	skip();
607 	if ((i = findr(getrq())) == -1)
608 		goto rtn;
609 	skip();
610 	j = inumb(&vlist[i]);
611 	if (nonumb)
612 		goto rtn;
613 	vlist[i] = j;
614 	skip();
615 	j = atoi();
616 	if (nonumb)
617 		goto rtn;
618 	inc[i] = j;
619 rtn:
620 	return;
621 }
622 
623 
624 caseaf()
625 {
626 	register i, k;
627 	tchar j;
628 
629 	lgf++;
630 	if (skip() || !(i = getrq()) || skip())
631 		return;
632 	k = 0;
633 	j = getch();
634 	if (!isalpha(cbits(j))) {
635 		ch = j;
636 		while ((j = cbits(getch())) >= '0' &&  j <= '9')
637 			k++;
638 	}
639 	if (!k)
640 		k = j;
641 	fmt[findr(i)] = k & BMASK;
642 }
643 
644 setaf()	/* return format of number register */
645 {
646 	register int i, j;
647 
648 	i = usedr(getsn());
649 	if (i == -1)
650 		return;
651 	cp = cbuf;
652 	if (fmt[i] > 20)	/* it was probably a, A, i or I */
653 		*cp++ = fmt[i];
654 	else
655 		for (j = (fmt[i] ? fmt[i] : 1); j; j--)
656 			*cp++ = '0';
657 	*cp = 0;
658 	cp = cbuf;
659 }
660 
661 
662 vnumb(i)
663 int	*i;
664 {
665 	vflag++;
666 	dfact = lss;
667 	res = VERT;
668 	return(inumb(i));
669 }
670 
671 
672 hnumb(i)
673 int	*i;
674 {
675 	dfact = EM;
676 	res = HOR;
677 	return(inumb(i));
678 }
679 
680 
681 inumb(n)
682 int	*n;
683 {
684 	register i, j, f;
685 	tchar ii;
686 
687 	f = 0;
688 	if (n) {
689 		if ((j = cbits(ii = getch())) == '+')
690 			f = 1;
691 		else if (j == '-')
692 			f = -1;
693 		else
694 			ch = ii;
695 	}
696 	i = atoi();
697 	if (n && f)
698 		i = *n + f * i;
699 	i = quant(i, res);
700 	vflag = 0;
701 	res = dfactd = dfact = 1;
702 	if (nonumb)
703 		i = 0;
704 	return(i);
705 }
706 
707 
708 quant(n, m)
709 int	n, m;
710 {
711 	register i, neg;
712 
713 	neg = 0;
714 	if (n < 0) {
715 		neg++;
716 		n = -n;
717 	}
718 	/* better as i = ((n + (m/2))/m)*m */
719 	i = n / m;
720 	if ((n - m * i) > (m / 2))
721 		i += 1;
722 	i *= m;
723 	if (neg)
724 		i = -i;
725 	return(i);
726 }
727 
728 
729