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
setn()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
setn1(i)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
findr(i)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
usedr(i)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
wrc(i)318 wrc(i)
319 tchar i;
320 {
321 if (cp >= &cbuf[NC])
322 return(0);
323 *cp++ = i;
324 return(1);
325 }
326
327
atoi0()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
ckph()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
atoi1()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
caserr()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
casenr()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
caseaf()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
setaf()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
vnumb(i)662 vnumb(i)
663 int *i;
664 {
665 vflag++;
666 dfact = lss;
667 res = VERT;
668 return(inumb(i));
669 }
670
671
hnumb(i)672 hnumb(i)
673 int *i;
674 {
675 dfact = EM;
676 res = HOR;
677 return(inumb(i));
678 }
679
680
inumb(n)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
quant(n,m)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