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