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