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