BSD 4 development
[unix-history] / usr / src / cmd / troff / n4.c
CommitLineData
d6ded25b
BJ
1#include "tdef.h"
2extern
3#include "d.h"
4extern
5#include "v.h"
6#ifdef NROFF
7extern
8#include "tw.h"
9#endif
10#include "s.h"
11/*
12troff4.c
13
14number registers, conversion, arithmetic
15*/
16
17extern int inchar[LNSIZE], *pinchar; /* XXX */
18extern struct s *frame;
19
20extern int ascii;
21extern int cbuf[NC];
22extern int *cp;
23extern int r[NN];
24extern int *vlist;
25extern int inc[NN];
26extern int fmt[NN];
27extern int ch;
28extern int lgf;
29extern int pl;
30extern int lastl;
31extern int ralss;
32extern int totout;
33extern int nrbits;
34extern int nonumb;
35extern int vflag;
36extern int noscale;
37extern int dfact;
38extern int dfactd;
39extern int po;
40extern int nform;
41extern int ll;
42extern int in;
43extern int font;
44extern int bdtab[];
45extern int lss;
46extern int pts;
47extern int fi;
48extern int res;
49extern int cwidth;
50extern int dotT;
51extern int ev;
52extern int ne;
53extern int ad, admod;
54extern int print;
55extern int ls;
56extern int nel, un;
57extern int xxx;
58int regcnt = NNAMES;
59
60setn()
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{
114s0:
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}
124setn1(i)
125int i;
126{
127 extern int wrc();
128
129 cp = cbuf;
130 nrbits = 0;
131 fnumb(i,wrc);
132 *cp = 0;
133 cp = cbuf;
134}
135findr(i)
136int 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}
159fnumb(i,f)
160int 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}
179decml(i,f)
180int 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}
189roman(i,f)
190int 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}
197roman0(i,f,onesp,fivesp)
198int i, (*f)();
199char *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}
219abc(i,f)
220int i, (*f)();
221{
222 if(!i)return((*f)('0' | nrbits));
223 else return(abc0(i-1,f));
224}
225abc0(i,f)
226int 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}
234wrc(i)
235int i;
236{
237 if(cp >= &cbuf[NC])return(0);
238 *cp++ = i;
239 return(1);
240}
241atoi(){
242 extern long atoi0();
243
244 return((int)atoi0());
245}
246long 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;
255a0:
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}
327long 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}
340long 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;
348a0:
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 }
363a1:
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 }
429a2:
430 nonumb = !field;
431 return(acc);
432}
433caserr(){
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}
447casenr(){
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;
461rtn:
462 return;
463}
464caseaf(){
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}
478vnumb(i)
479int *i;
480{
481 vflag++;
482 dfact = lss;
483 res = VERT;
484 return(inumb(i));
485}
486hnumb(i)
487int *i;
488{
489 dfact = EM;
490 res = HOR;
491 return(inumb(i));
492}
493inumb(n)
494int *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}
512quant(n,m)
513int 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}