new copyright; att/bsd/shared
[unix-history] / usr / src / old / roff / common_source / n4.c
CommitLineData
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
9static char sccsid[] = "@(#)n4.c 4.2 (Berkeley) %G%";
10#endif /* not lint */
c8721856
RH
11
12#include "tdef.h"
13extern
14#include "d.h"
15extern
16#include "v.h"
17#ifdef NROFF
18extern
19#include "tw.h"
20#endif
21#include "sdef.h"
22/*
23troff4.c
24
25number registers, conversion, arithmetic
26*/
27
28extern int inchar[LNSIZE], *pinchar; /* XXX */
29extern struct s *frame;
30
31extern int ascii;
32extern int cbuf[NC];
33extern int *cp;
34extern int r[NN];
35extern int *vlist;
36extern int inc[NN];
37extern int fmt[NN];
38extern int ch;
39extern int lgf;
40extern int pl;
41extern int lastl;
42extern int ralss;
43extern int totout;
44extern int nrbits;
45extern int nonumb;
46extern int vflag;
47extern int noscale;
48extern int dfact;
49extern int dfactd;
50extern int po;
51extern int nform;
52extern int ll;
53extern int in;
54extern int font;
55extern int bdtab[];
56extern int lss;
57extern int pts;
58extern int fi;
59extern int res;
60extern int cwidth;
61extern int dotT;
62extern int ev;
63extern int ne;
64extern int ad, admod;
65extern int print;
66extern int ls;
67extern int nel, un;
68extern int xxx;
69int regcnt = NNAMES;
70
71setn()
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{
125s0:
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}
135setn1(i)
136int i;
137{
138 extern int wrc();
139
140 cp = cbuf;
141 nrbits = 0;
142 fnumb(i,wrc);
143 *cp = 0;
144 cp = cbuf;
145}
146findr(i)
147int 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}
170fnumb(i,f)
171int 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}
190decml(i,f)
191int 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}
200roman(i,f)
201int 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}
208roman0(i,f,onesp,fivesp)
209int i, (*f)();
210char *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}
230abc(i,f)
231int i, (*f)();
232{
233 if(!i)return((*f)('0' | nrbits));
234 else return(abc0(i-1,f));
235}
236abc0(i,f)
237int 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}
245wrc(i)
246int i;
247{
248 if(cp >= &cbuf[NC])return(0);
249 *cp++ = i;
250 return(1);
251}
252atoi(){
253 extern long atoi0();
254
255 return((int)atoi0());
256}
257long 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;
266a0:
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}
338long 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}
351long 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;
359a0:
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 }
374a1:
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 }
440a2:
441 nonumb = !field;
442 return(acc);
443}
444caserr(){
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}
458casenr(){
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;
472rtn:
473 return;
474}
475caseaf(){
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}
489vnumb(i)
490int *i;
491{
492 vflag++;
493 dfact = lss;
494 res = VERT;
495 return(inumb(i));
496}
497hnumb(i)
498int *i;
499{
500 dfact = EM;
501 res = HOR;
502 return(inumb(i));
503}
504inumb(n)
505int *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}
523quant(n,m)
524int 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}