|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.