Commit | Line | Data |
---|---|---|
a860ef9e KB |
1 | /*- |
2 | * Copyright (c) 1991 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.proprietary.c% | |
6 | */ | |
7 | ||
c8721856 | 8 | #ifndef lint |
a860ef9e KB |
9 | static char sccsid[] = "@(#)n4.c 4.2 (Berkeley) %G%"; |
10 | #endif /* not lint */ | |
c8721856 RH |
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 | ||
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 | } | |
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 | } | |
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 | } | |
245 | wrc(i) | |
246 | int i; | |
247 | { | |
248 | if(cp >= &cbuf[NC])return(0); | |
249 | *cp++ = i; | |
250 | return(1); | |
251 | } | |
252 | atoi(){ | |
253 | extern long atoi0(); | |
254 | ||
255 | return((int)atoi0()); | |
256 | } | |
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 | } | |
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 | } | |
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 | } | |
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 | } | |
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 | } | |
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 | } | |
489 | vnumb(i) | |
490 | int *i; | |
491 | { | |
492 | vflag++; | |
493 | dfact = lss; | |
494 | res = VERT; | |
495 | return(inumb(i)); | |
496 | } | |
497 | hnumb(i) | |
498 | int *i; | |
499 | { | |
500 | dfact = EM; | |
501 | res = HOR; | |
502 | return(inumb(i)); | |
503 | } | |
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 | } | |
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 | } |