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