1 /* $MirOS: src/usr.bin/oldroff/nroff/n4.c,v 1.3 2008/11/08 23:04:41 tg Exp $ */
2
3 /*-
4 * Copyright (c) 1979, 1980, 1981, 1986, 1988, 1990, 1991, 1992
5 * The Regents of the University of California.
6 * Copyright (C) Caldera International Inc. 2001-2002.
7 * Copyright (c) 2003, 2004
8 * Thorsten "mirabilos" Glaser <tg@mirbsd.org>
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms,
12 * with or without modification, are permitted provided
13 * that the following conditions are met:
14 *
15 * Redistributions of source code and documentation must retain
16 * the above copyright notice, this list of conditions and the
17 * following disclaimer. Redistributions in binary form must
18 * reproduce the above copyright notice, this list of conditions
19 * and the following disclaimer in the documentation and/or other
20 * materials provided with the distribution.
21 *
22 * All advertising materials mentioning features or use of this
23 * software must display the following acknowledgement:
24 * This product includes software developed or owned by
25 * Caldera International, Inc.
26 *
27 * Neither the name of Caldera International, Inc. nor the names
28 * of other contributors may be used to endorse or promote products
29 * derived from this software without specific prior written permission.
30 *
31 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
32 * INTERNATIONAL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
33 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
36 * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
39 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
41 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
42 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 */
44
45 #include <sys/cdefs.h>
46 __SCCSID("@(#)n4.c 4.2 (Berkeley) 4/18/91");
47 __RCSID("$MirOS: src/usr.bin/oldroff/nroff/n4.c,v 1.3 2008/11/08 23:04:41 tg Exp $");
48
49 #include "tdef.h"
50 extern
51 #include "d.h"
52 extern
53 #include "v.h"
54 #ifdef NROFF
55 extern
56 #include "tw.h"
57 #endif
58 #include "sdef.h"
59 /*
60 troff4.c
61
62 number registers, conversion, arithmetic
63 */
64
65 extern int inchar[LNSIZE], *pinchar; /* XXX */
66 extern struct s *frame;
67
68 extern int ascii;
69 extern int cbuf[NC];
70 extern int *cp;
71 extern int r[NN];
72 extern int *vlist;
73 extern int inc[NN];
74 extern int fmt[NN];
75 extern int ch;
76 extern int lgf;
77 extern int pl;
78 extern int lastl;
79 extern int ralss;
80 extern int totout;
81 extern int nrbits;
82 extern int nonumb;
83 extern int vflag;
84 extern int noscale;
85 extern int dfact;
86 extern int dfactd;
87 extern int po;
88 extern int nform;
89 extern int ll;
90 extern int in;
91 extern int font;
92 extern int bdtab[];
93 extern int lss;
94 extern int pts;
95 extern int fi;
96 extern int res;
97 extern int cwidth;
98 extern int dotT;
99 extern int ev;
100 extern int ne;
101 extern int ad, admod;
102 extern int print;
103 extern int ls;
104 extern int nel, un;
105 extern int xxx;
106 int regcnt = NNAMES;
107
setn()108 setn()
109 {
110 register i,j;
111 int f;
112
113 f = nform = 0;
114 if((i=getch() & CMASK) == '+')f = 1;
115 else if(i == '-')f = -1;
116 else ch = i;
117 if((i=getsn()) == 0)return;
118 if((i & 0177) == '.')switch(i>>BYTE){
119 case 's': i = pts & 077; break;
120 case 'v': i = lss; break;
121 case 'f': i = font + 1; break;
122 case 'p': i = pl; break;
123 case 't': i = findt1(); break;
124 case 'o': i = po; break;
125 case 'l': i = ll; break;
126 case 'i': i = in; break;
127 case '$': i = frame->nargs; break;
128 case 'A': i = ascii; break;
129 case 'c': i = v.cd; break;
130 case 'n': i = lastl; break;
131 case 'a': i = ralss; break;
132 case 'h': i = dip->hnl; break;
133 case 'd':
134 if(dip != d)i = dip->dnl; else i = v.nl;
135 break;
136 case 'u': i = fi; break;
137 case 'j': i = ad + 2*admod; break;
138 case 'w': i = width(*(pinchar-1)); break; /* XXX */
139 case 'x': i = nel; break;
140 case 'y': i = un; break;
141 case 'T': i = dotT; break; /*-Tterm used in nroff*/
142 case 'V': i = VERT; break;
143 case 'H': i = HOR; break;
144 case 'k': i = ne; break;
145 case 'P': i = print; break;
146 case 'L': i = ls; break;
147 case 'R': i = NN - regcnt; break;
148 case 'z': i = dip->curd;
149 cbuf[0] = i & BMASK;
150 cbuf[1] = (i >> BYTE) & BMASK;
151 cbuf[2] = 0;
152 cp = cbuf;
153 return;
154 #ifndef NROFF
155 case 'b': i = bdtab[font]; break;
156 #endif
157
158 default:
159 goto s0;
160 }
161 else{
162 s0:
163 if((j=findr(i)) == -1)i = 0;
164 else{
165 i = (vlist[j] = (vlist[j] + inc[j]*f));
166 nform = fmt[j];
167 }
168 }
169 setn1(i);
170 cp = cbuf;
171 }
setn1(i)172 setn1(i)
173 int i;
174 {
175 extern int wrc();
176
177 cp = cbuf;
178 nrbits = 0;
179 fnumb(i,wrc);
180 *cp = 0;
181 cp = cbuf;
182 }
findr(i)183 findr(i)
184 int i;
185 {
186 register j;
187 static int numerr;
188
189 if(i == 0)return(-1);
190 for(j=0;j<NN;j++){
191 if(i == r[j])break;
192 }
193 if(j != NN)return(j);
194 for(j=0; j<NN; j++){
195 if(r[j] == 0){
196 r[j] = i;
197 regcnt++;
198 break;
199 }
200 }
201 if(j==NN){
202 if(!numerr)prstrfl("Too many number registers.\n");
203 if(++numerr > 1)done2(04); else edone(04);
204 }
205 return(j);
206 }
207 fnumb(i,f)
208 int i, (*f)();
209 {
210 register j;
211
212 j = 0;
213 if(i < 0){
214 j = (*f)('-' | nrbits);
215 i = -i;
216 }
217 switch(nform){
218 default:
219 case '1':
220 case 0: return(decml(i,f) + j);
221 case 'i':
222 case 'I': return(roman(i,f) + j);
223 case 'a':
224 case 'A': return(abc(i,f) + j);
225 }
226 }
227 decml(i,f)
228 int i, (*f)();
229 {
230 register j,k;
231
232 k = 0;
233 nform--;
234 if((j=i/10) || (nform > 0))k = decml(j,f);
235 return(k + (*f)((i%10 + '0') | nrbits));
236 }
237 roman(i,f)
238 int i, (*f)();
239 {
240
241 if(!i)return((*f)('0' | nrbits));
242 if(nform == 'i')return(roman0(i,f,"ixcmz","vldw"));
243 else return(roman0(i,f,"IXCMZ","VLDW"));
244 }
245 roman0(i,f,onesp,fivesp)
246 int i, (*f)();
247 char *onesp, *fivesp;
248 {
249 register q, rem, k;
250
251 k = 0;
252 if(!i)return(0);
253 k = roman0(i/10,f,onesp+1,fivesp+1);
254 q = (i=i%10)/5;
255 rem = i%5;
256 if(rem == 4){
257 k += (*f)(*onesp | nrbits);
258 if(q)i = *(onesp+1);
259 else i = *fivesp;
260 return(k += (*f)(i | nrbits));
261 }
262 if(q)k += (*f)(*fivesp | nrbits);
263 while(--rem >= 0)
264 k += (*f)(*onesp | nrbits);
265 return(k);
266 }
267 abc(i,f)
268 int i, (*f)();
269 {
270 if(!i)return((*f)('0' | nrbits));
271 else return(abc0(i-1,f));
272 }
273 abc0(i,f)
274 int i, (*f)();
275 {
276 register j, k;
277
278 k = 0;
279 if(j=i/26)k = abc0(j-1,f);
280 return(k + (*f)((i%26 + nform) | nrbits));
281 }
wrc(i)282 wrc(i)
283 int i;
284 {
285 if(cp >= &cbuf[NC])return(0);
286 *cp++ = i;
287 return(1);
288 }
nr_atoi()289 nr_atoi(){
290 extern long atoi0();
291
292 return((int)atoi0());
293 }
atoi0()294 long atoi0()
295 {
296 register ii, k, cnt;
297 long i, acc;
298 extern long ckph();
299
300 i = 0; acc = 0;
301 nonumb = 0;
302 cnt = -1;
303 a0:
304 cnt++;
305 switch((ii=getch()) & CMASK){
306 default:
307 ch = ii;
308 if(cnt)break;
309 case '+':
310 i = ckph();
311 if(nonumb)break;
312 acc += i;
313 goto a0;
314 case '-':
315 i = ckph();
316 if(nonumb)break;
317 acc -= i;
318 goto a0;
319 case '*':
320 i = ckph();
321 if(nonumb)break;
322 acc *= i;
323 goto a0;
324 case '/':
325 i = ckph();
326 if(nonumb)break;
327 if(i == 0){
328 prstrfl("Divide by zero.\n");
329 acc = 0;
330 }else acc /= i;
331 goto a0;
332 case '%':
333 i = ckph();
334 if(nonumb)break;
335 acc %= i;
336 goto a0;
337 case '&': /*and*/
338 i = ckph();
339 if(nonumb)break;
340 if((acc > 0) && (i > 0))acc = 1; else acc = 0;
341 goto a0;
342 case ':': /*or*/
343 i = ckph();
344 if(nonumb)break;
345 if((acc > 0) || (i > 0))acc = 1; else acc = 0;
346 goto a0;
347 case '=':
348 if(((ii=getch()) & CMASK) != '=')ch = ii;
349 i = ckph();
350 if(nonumb){acc = 0; break;}
351 if(i == acc)acc = 1;
352 else acc = 0;
353 goto a0;
354 case '>':
355 k = 0;
356 if(((ii=getch()) & CMASK) == '=')k++; else ch =ii;
357 i = ckph();
358 if(nonumb){acc = 0; break;}
359 if(acc > (i - k))acc = 1; else acc = 0;
360 goto a0;
361 case '<':
362 k = 0;
363 if(((ii=getch()) & CMASK) == '=')k++; else ch =ii;
364 i = ckph();
365 if(nonumb){acc = 0; break;}
366 if(acc < (i + k))acc = 1; else acc = 0;
367 goto a0;
368 case ')': break;
369 case '(':
370 acc = atoi0();
371 goto a0;
372 }
373 return(acc);
374 }
ckph()375 long ckph(){
376 register i;
377 long j;
378 extern long atoi0();
379 extern long atoi1();
380
381 if(((i = getch()) & CMASK) == '(')j = atoi0();
382 else{
383 ch = i;
384 j = atoi1();
385 }
386 return(j);
387 }
atoi1()388 long atoi1()
389 {
390 register i, j, digits;
391 long acc;
392 int neg, abs, field;
393
394 neg = abs = field = digits = 0;
395 acc = 0;
396 a0:
397 switch((i = getch()) & CMASK){
398 default:
399 ch = i;
400 break;
401 case '+':
402 goto a0;
403 case '-':
404 neg = 1;
405 goto a0;
406 case '|':
407 abs = 1 + neg;
408 neg = 0;
409 goto a0;
410 }
411 a1:
412 while(((j = ((i = getch()) & CMASK) - '0') >= 0) && (j <= 9)){
413 field++;
414 digits++;
415 acc = 10*acc + j;
416 }
417 if((i & CMASK) == '.'){
418 field++;
419 digits = 0;
420 goto a1;
421 }
422 ch = i;
423 if(!field)goto a2;
424 switch((i = getch()) & CMASK){
425 case 'u':
426 i = j = 1;
427 break;
428 case 'v': /*VSs - vert spacing*/
429 j = lss;
430 i = 1;
431 break;
432 case 'm': /*Ems*/
433 j = EM;
434 i = 1;
435 break;
436 case 'n': /*Ens*/
437 j = EM;
438 #ifndef NROFF
439 i = 2;
440 #endif
441 #ifdef NROFF
442 i = 1; /*Same as Ems in NROFF*/
443 #endif
444 break;
445 case 'p': /*Points*/
446 j = INCH;
447 i = 72;
448 break;
449 case 'i': /*Inches*/
450 j = INCH;
451 i = 1;
452 break;
453 case 'c': /*Centimeters*/
454 j = INCH*50;
455 i = 127;
456 break;
457 case 'P': /*Picas*/
458 j = INCH;
459 i = 6;
460 break;
461 default:
462 j = dfact;
463 ch = i;
464 i = dfactd;
465 }
466 if(neg) acc = -acc;
467 if(!noscale){
468 acc = (acc*j)/i;
469 }
470 if((field != digits) && (digits > 0))while(digits--)acc /= 10;
471 if(abs){
472 if(dip != d)j = dip->dnl; else j = v.nl;
473 if(!vflag)j = v.hp = sumhp(); /* XXX */
474 if(abs == 2)j = -j;
475 acc -= j;
476 }
477 a2:
478 nonumb = !field;
479 return(acc);
480 }
caserr()481 caserr(){
482 register i,j;
483
484 lgf++;
485 while(!skip() && (i=getrq()) ){
486 for(j=NNAMES; j<NN; j++){ /*NNAMES predefined names*/
487 if(i == r[j])break;
488 }
489 if(j!=NN){
490 r[j]=vlist[j]=inc[j]=fmt[j]=0;
491 regcnt--;
492 }
493 }
494 }
casenr()495 casenr(){
496 register i, j;
497
498 lgf++;
499 skip();
500 if((i = findr(getrq())) == -1)goto rtn;
501 skip();
502 j = inumb(&vlist[i]);
503 if(nonumb)goto rtn;
504 vlist[i] = j;
505 skip();
506 j = nr_atoi();
507 if(nonumb)goto rtn;
508 inc[i] = j;
509 rtn:
510 return;
511 }
caseaf()512 caseaf(){
513 register i, j, k;
514
515 lgf++;
516 if(skip() || !(i = getrq()) || skip())return;
517 k = 0;
518 if(!alph(j=getch())){
519 ch = j;
520 while(((j = getch() & CMASK) >= '0') &&
521 (j <= '9'))k++;
522 }
523 if(!k)k=j;
524 fmt[findr(i)] = k & BMASK;
525 }
vnumb(i)526 vnumb(i)
527 int *i;
528 {
529 vflag++;
530 dfact = lss;
531 res = VERT;
532 return(inumb(i));
533 }
hnumb(i)534 hnumb(i)
535 int *i;
536 {
537 dfact = EM;
538 res = HOR;
539 return(inumb(i));
540 }
inumb(n)541 inumb(n)
542 int *n;
543 {
544 register i, j, f;
545
546 f = 0;
547 if(n){
548 if((j = (i = getch()) & CMASK) == '+')f = 1;
549 else if(j == '-')f = -1;
550 else ch = i;
551 }
552 i = nr_atoi();
553 if(n && f)i = *n + f*i;
554 i = quant(i,res);
555 vflag = 0;
556 res = dfactd = dfact = 1;
557 if(nonumb)i = 0;
558 return(i);
559 }
quant(n,m)560 quant(n,m)
561 int n, m;
562 {
563 register i, neg;
564
565 neg = 0;
566 if(n<0){
567 neg++;
568 n = -n;
569 }
570 i = n/m;
571 if((n - m*i) > (m/2))i += 1;
572 i *= m;
573 if(neg)i = -i;
574 return(i);
575 }
576