1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 /*	from OpenSolaris "n4.c	1.8	05/06/08 SMI"	*/
32 
33 /*
34  * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
35  *
36  * Sccsid @(#)n4.c	1.102 (gritter) 10/23/09
37  */
38 
39 /*
40  * University Copyright- Copyright (c) 1982, 1986, 1988
41  * The Regents of the University of California
42  * All Rights Reserved
43  *
44  * University Acknowledgment- Portions of this document are derived from
45  * software developed by the University of California, Berkeley, and its
46  * contributors.
47  */
48 
49 #include	<stddef.h>
50 #include	<stdio.h>
51 #include	<stdlib.h>
52 #include	<string.h>
53 #include	<ctype.h>
54 #include	<locale.h>
55 #include	<limits.h>
56 #include	<float.h>
57 #include "tdef.h"
58 #ifdef NROFF
59 #include "tw.h"
60 #endif
61 #include "pt.h"
62 #include "ext.h"
63 /*
64  * troff4.c
65  *
66  * number registers, conversion, arithmetic
67  */
68 
69 
70 int	regcnt = NNAMES;
71 int	falsef	= 0;	/* on if inside false branch of if */
72 #define	NHASH(i)	((i>>6)^i)&0177
73 struct	numtab	**nhash;	/* size must be 128 == the 0177 on line above */
74 
75 static void	nrehash(struct numtab *, int, struct numtab **);
76 static struct numtab	*_findr(register int i, int, int, int, int *);
77 static struct acc	_atoi(int);
78 static struct acc	_atoi0(int);
79 static struct acc	ckph(int);
80 static struct acc	atoi1(tchar, int);
81 static struct acc	_inumb(int *, float *, int, int *);
82 static void	print_tab_setting(char *, size_t);
83 
84 static void *
_grownumtab(struct numtab ** numtp,int * NNp,struct numtab *** hashp)85 _grownumtab(struct numtab **numtp, int *NNp, struct numtab ***hashp)
86 {
87 	int	i, inc = 20;
88 	ptrdiff_t	j;
89 	struct numtab	*onc;
90 
91 	onc = *numtp;
92 	if ((*numtp = realloc(*numtp, (*NNp+inc) * sizeof *numtab)) == NULL)
93 		return NULL;
94 	memset(&(*numtp)[*NNp], 0, inc * sizeof *numtab);
95 	if (*NNp == 0) {
96 		if (numtp == &numtab)
97 			for (i = 0; initnumtab[i].r; i++)
98 				(*numtp)[i] = initnumtab[i];
99 		if (*hashp == NULL)
100 			*hashp = calloc(128, sizeof *hashp);
101 		nrehash(*numtp, *NNp + inc, *hashp);
102 	} else {
103 		j = (char *)(*numtp) - (char *)onc;
104 		for (i = 0; i < 128; i++)
105 			if ((*hashp)[i])
106 				(*hashp)[i] = (struct numtab *)
107 					((char *)((*hashp)[i]) + j);
108 		for (i = 0; i < *NNp; i++)
109 			if ((*numtp)[i].link)
110 				(*numtp)[i].link = (struct numtab *)
111 					((char *)((*numtp)[i].link) + j);
112 	}
113 	*NNp += inc;
114 	return *numtp;
115 }
116 
117 void *
grownumtab(void)118 grownumtab(void)
119 {
120 	return _grownumtab(&numtab, &NN, &nhash);
121 }
122 
123 static void
print_tab_setting(char * tb,size_t siz)124 print_tab_setting(char *tb, size_t siz) {
125 	char *cp;
126 	int i;
127 	for (i = 0; tabtab[i]; i++);
128 	while (--i >= 0) {
129 		cp = tb;
130 		if (i)
131 			*cp++ = ' ';
132 		cp = roff_sprintf(cp, siz - (cp - tb), "%d", tabtab[i]&TABMASK);
133 		*cp++ = 'u';
134 		switch (tabtab[i] & ~TABMASK) {
135 		case RTAB:
136 			*cp++ = 'R';
137 			break;
138 		case CTAB:
139 			*cp++ = 'C';
140 			break;
141 		}
142 		*cp = 0;
143 		cpushback(tb);
144 	}
145 }
146 
147 #define	TMYES	if (tm) return(1)
148 #define	TMNO	if (tm) return(0)
149 
150 static int
_setn(int tm)151 _setn(int tm)	/* tm: test for presence of readonly register */
152 {
153 	extern const char	revision[];
154 	struct numtab	*numtp;
155 	char	tb[30], *cp;
156 	const char	*name;
157 	struct s	*s;
158 	register int i;
159 	register tchar ii;
160 	int	f, j;
161 	float	fl;
162 
163 	f = nform = 0;
164 	if (tm) {
165 		i = tm;
166 		goto sl;
167 	}
168 	noschr++;
169 	if ((i = cbits(ii = getach())) == '+')
170 		f = 1;
171 	else if (i == '-')
172 		f = -1;
173 	else
174 		ch = ii;
175 	if (noschr) noschr--;
176 	if (falsef)
177 		f = 0;
178 	if ((i = getsn(1)) == 0)
179 		return(0);
180 sl:
181 	name = macname(i);
182 	if (i < 65536 && (i & 0177) == '.')
183 		switch (i >> BYTE) {
184 		case 's':
185 			i = fl = u2pts(pts);
186 			if (i != fl)
187 				goto flt;
188 			break;
189 		case 'v':
190 			i = lss;
191 			break;
192 		case 'f':
193 			i = font;
194 			break;
195 		case 'p':
196 			i = pl;
197 			break;
198 		case 't':
199 			i = findt1();
200 			break;
201 		case 'o':
202 			i = po;
203 			break;
204 		case 'l':
205 			i = ll;
206 			break;
207 		case 'i':
208 			i = in;
209 			break;
210 		case '$':
211 			for (s = frame; s->loopf && s != stk; s = s->pframe);
212 			i = s->nargs;
213 			break;
214 		case 'A':
215 			i = ascii;
216 			break;
217 		case 'c':
218 			i = numtab[CD].val;
219 			break;
220 		case 'n':
221 			i = lastl;
222 			break;
223 		case 'a':
224 			i = ralss;
225 			break;
226 		case 'h':
227 			i = dip->hnl;
228 			break;
229 		case 'd':
230 			if (dip != d)
231 				i = dip->dnl;
232 			else
233 				i = numtab[NL].val;
234 			break;
235 		case 'u':
236 			i = fi;
237 			break;
238 		case 'j':
239 			i = ad + 2 * admod + pa * 70;
240 			break;
241 		case 'w':
242 			i = widthp;
243 			break;
244 		case 'x':
245 			if (gflag)
246 				goto s0;
247 			i = nel - adspc;
248 			break;
249 		case 'y':
250 			if (gflag)
251 				goto s0;
252 			i = un;
253 			break;
254 		case 'T':
255 			i = dotT;
256 			break; /*-Tterm used in nroff*/
257 		case 'V':
258 			i = VERT;
259 			break;
260 		case 'H':
261 			i = HOR;
262 			break;
263 		case 'k':
264 			if ((pa || padj) && pglines == 0) {
265 				/* fake a value to make -mm work */
266 				i = pgne % (ll - in);
267 				if (i == 0 && pgne != 0)
268 					i = 1;
269 			} else
270 				i = ne + adspc;
271 			if (gflag) {
272 				if (ce || rj || !fi ? pendnf : pendw != NULL)
273 					i += wne - wsp;
274 				else if (nwd || pgchars) {
275 					i += sps;
276 					if (seflg || spflg)
277 						i += ses;
278 				}
279 			}
280 			break;
281 		case 'P':
282 			i = print;
283 			break;
284 		case 'L':
285 			i = ls;
286 			break;
287 		case 'R':
288 			i = NN - regcnt;
289 			break;
290 		case 'z':
291 			TMYES;
292 			cpushback(macname(dip->curd));
293 			return(0);
294 		case 'b':
295 			i = bdtab[font];
296 			break;
297 		case 'F':
298 			TMYES;
299 			cpushback(cfname[ifi] ? cfname[ifi] : "");
300 			return(0);
301 		case 'S':
302 			TMYES;
303 			print_tab_setting(tb, sizeof(tb));
304 			return(0);
305 		case 'X':
306 			if (xflag) {
307 				i = xflag;
308 				break;
309 			}
310 			/*FALLTHRU*/
311 		case 'Y':
312 			if (xflag) {
313 				TMYES;
314 				cpushback((char *)revision);
315 				return(0);
316 			}
317 			/*FALLTHRU*/
318 
319 		default:
320 			goto s0;
321 		}
322 	else if (name[0] == '.') {
323 		if (strcmp(&name[1], "warn") == 0)
324 			i = warn;
325 		else if (strcmp(&name[1], "vpt") == 0)
326 			i = vpt;
327 		else if (strcmp(&name[1], "ascender") == 0)
328 			i = getascender();
329 		else if (strcmp(&name[1], "descender") == 0)
330 			i = getdescender();
331 		else if (strcmp(&name[1], "fp") == 0)
332 			i = nextfp();
333 		else if (strcmp(&name[1], "ss") == 0)
334 			i = spacesz;
335 		else if (strcmp(&name[1], "sss") == 0)
336 			i = sesspsz;
337 		else if (strcmp(&name[1], "minss") == 0)
338 			i = minspsz ? minspsz : spacesz;
339 		else if (strcmp(&name[1], "lshmin") == 0) {
340 			i = fl = 100 - lshmin / (LAFACT/100.0);
341 			if (i != fl)
342 				goto flt;
343 		} else if (strcmp(&name[1], "lshmax") == 0) {
344 			i = fl = 100 + lshmax / (LAFACT/100.0);
345 			if (i != fl)
346 				goto flt;
347 		} else if (strcmp(&name[1], "lspmin") == 0) {
348 			i = fl = 100 - lspmin / (LAFACT/100.0);
349 			if (i != fl)
350 				goto flt;
351 		} else if (strcmp(&name[1], "lspmax") == 0) {
352 			i = fl = 100 + lspmax / (LAFACT/100.0);
353 			if (i != fl)
354 				goto flt;
355 		} else if (strcmp(&name[1], "letss") == 0)
356 			i = letspsz;
357 		else if (strcmp(&name[1], "hlm") == 0)
358 			i = hlm;
359 		else if (strcmp(&name[1], "hlc") == 0)
360 			i = hlc;
361 		else if (strcmp(&name[1], "lc_ctype") == 0) {
362 			if ((cp = setlocale(LC_CTYPE, NULL)) == NULL)
363 				cp = "C";
364 			TMYES;
365 			cpushback(cp);
366 			return(0);
367 		} else if (strcmp(&name[1], "hylang") == 0) {
368 			TMYES;
369 			if (hylang)
370 				cpushback(hylang);
371 			return(0);
372 		} else if (strcmp(&name[1], "fzoom") == 0) {
373 			i = fl = getfzoom();
374 			if (i != fl)
375 				goto flt;
376 		} else if (strcmp(&name[1], "sentchar") == 0) {
377 			TMYES;
378 			if (sentch[0] == IMP)
379 				/*EMPTY*/;
380 			else if (sentch[0] == 0)
381 				cpushback(".?!:");
382 			else {
383 				tchar	tc[NSENT+1];
384 				for (i = 0; sentch[i] && i < NSENT; i++)
385 					tc[i] = sentch[i];
386 				tc[i] = 0;
387 				pushback(tc);
388 			}
389 			return(0);
390 		} else if (strcmp(&name[1], "transchar") == 0) {
391 			tchar	tc[NSENT+1];
392 			TMYES;
393 			if (transch[0] == IMP)
394 				/*EMPTY*/;
395 			else if (transch[0] == 0) {
396 				cpushback("\"')]*");
397 				tc[0] = DAGGER;
398 				tc[1] = 0;
399 				pushback(tc);
400 			} else {
401 				for (i = 0; transch[i] && i < NSENT; i++)
402 					tc[i] = transch[i];
403 				tc[i] = 0;
404 				pushback(tc);
405 			}
406 			return(0);
407 		} else if (strcmp(&name[1], "breakchar") == 0) {
408 			tchar	tc[NSENT+1];
409 			TMYES;
410 			if (breakch[0] == IMP)
411 				/*EMPTY*/;
412 			else if (breakch[0] == 0) {
413 				tc[0] = EMDASH;
414 				tc[1] = '-';
415 				tc[2] = 0;
416 				pushback(tc);
417 			} else {
418 				for (i = 0; breakch[i] && i < NSENT; i++)
419 					tc[i] = breakch[i];
420 				tc[i] = 0;
421 				pushback(tc);
422 			}
423 			return(0);
424 		} else if (strcmp(&name[1], "nhychar") == 0) {
425 			tchar	tc[NSENT+1];
426 			TMYES;
427 			if (nhych[0] == IMP)
428 				/*EMPTY*/;
429 			else if (nhych[0] == 0) {
430 				if (!hyext) {
431 					tc[0] = EMDASH;
432 					tc[1] = '-';
433 					tc[2] = 0;
434 					pushback(tc);
435 				}
436 			} else {
437 				for (i = 0; nhych[i] && i < NSENT; i++)
438 					tc[i] = nhych[i];
439 				tc[i] = 0;
440 				pushback(tc);
441 			}
442 			return(0);
443 		} else if (strcmp(&name[1], "connectchar") == 0) {
444 			tchar	tc[NSENT+1];
445 			TMYES;
446 			if (connectch[0] == IMP)
447 				/*EMPTY*/;
448 			else if (connectch[0] == 0) {
449 				cpushback("\"\\(ru\\(ul\\(rn");
450 			} else {
451 				for (i = 0; connectch[i] && i < NSENT; i++)
452 					tc[i] = connectch[i];
453 				tc[i] = 0;
454 				pushback(tc);
455 			}
456 			return(0);
457 		} else if (strcmp(&name[1], "shc") == 0) {
458 			tchar	tc[2];
459 			TMYES;
460 			tc[0] = shc ? shc : HYPHEN;
461 			tc[1] = 0;
462 			pushback(tc);
463 			return(0);
464 		} else if (strcmp(&name[1], "hylen") == 0) {
465 			i = hylen;
466 		} else if (strcmp(&name[1], "hypp") == 0) {
467 			i = hypp;
468 		} else if (strcmp(&name[1], "hypp2") == 0) {
469 			i = hypp2;
470 		} else if (strcmp(&name[1], "hypp3") == 0) {
471 			i = hypp3;
472 		} else if (strcmp(&name[1], "padj") == 0) {
473 			i = padj;
474 		} else if (strcmp(&name[1], "ev") == 0) {
475 			TMYES;
476 			cpushback(evname ? evname : "0");
477 			return(0);
478 		} else if (strcmp(&name[1], "ps") == 0) {
479 			i = pts;
480 #ifdef	NROFF
481 			i *= INCH / 72;
482 #endif	/* NROFF */
483 		} else if (strcmp(&name[1], "tabs") == 0) {
484 			TMYES;
485 			print_tab_setting(tb, sizeof(tb));
486 			return(0);
487 		} else if (strcmp(&name[1], "lpfx") == 0) {
488 			TMYES;
489 			if (lpfx)
490 				pushback(lpfx);
491 			return(0);
492 		} else if (strcmp(&name[1], "ce") == 0)
493 			i = ce;
494 		else if (strcmp(&name[1], "rj") == 0)
495 			i = rj;
496 		else if (strcmp(&name[1], "brnl") == 0)
497 			i = brnl;
498 		else if (strcmp(&name[1], "brpnl") == 0)
499 			i = brpnl;
500 		else if (strcmp(&name[1], "cht") == 0)
501 			i = cht;
502 		else if (strcmp(&name[1], "cdp") == 0)
503 			i = cdp;
504 		else if (strcmp(&name[1], "in") == 0)
505 			i = un;
506 		else if (strcmp(&name[1], "hy") == 0)
507 			i = hyf;
508 		else if (strcmp(&name[1], "int") == 0)
509 			i = ce || rj || !fi ? pendnf : pendw != NULL;
510 		else if (strcmp(&name[1], "lt") == 0)
511 			i = lt;
512 		else if (strcmp(&name[1], "pn") == 0)
513 			i = npnflg ? npn : numtab[PN].val + 1;
514 		else if (strcmp(&name[1], "psr") == 0) {
515 			i = apts;
516 #ifdef	NROFF
517 			i *= INCH / 72;
518 #endif	/* NROFF */
519 		} else if (strcmp(&name[1], "sr") == 0) {
520 			i = fl = u2pts(apts);
521 			if (i != fl)
522 				goto flt;
523 		} else if (strcmp(&name[1], "kc") == 0)
524 			i = wne - wsp;
525 		else if (strcmp(&name[1], "dilev") == 0)
526 			i = dilev;
527 		else if (strcmp(&name[1], "defpenalty") == 0)
528 			i = dpenal ? dpenal - INFPENALTY0 - 1 : 0;
529 		else if (strcmp(&name[1], "ns") == 0)
530 			i = dip->nls;
531 		else
532 			goto s0;
533 	} else if (strcmp(name, "lss") == 0)
534 		i = glss;
535 	else if (strcmp(name, "lsn") == 0)
536 		i = lsn;
537 	else {
538 s0:
539 		TMNO;
540 		if ((numtp = _findr(i, 1, 2, 0, &j)) == NULL) {
541 			if (j < 0) {
542 				i = -j;
543 				goto sl;
544 			}
545 			i = 0;
546 		} else if (numtp->fmt == -1) {
547 			fl = numtp->fval = numtp->fval + numtp->finc*f;
548 			if (numtp->finc)
549 				prwatchn(numtp);
550 			goto flt;
551 		} else {
552 			i = numtp->val = numtp->val + numtp->inc*f;
553 			if (numtp->inc)
554 				prwatchn(numtp);
555 			nform = numtp->fmt;
556 		}
557 	}
558 	TMYES;
559 	setn1(i, nform, (tchar) 0);
560 	return(0);
561 flt:
562 	TMYES;
563 	roff_sprintf(tb, sizeof(tb), "%g", fl);
564 	cpushback(tb);
565 	return(0);
566 }
567 
568 void
setn(void)569 setn(void)
570 {
571 	_setn(0);
572 }
573 
574 tchar	numbuf[17];
575 tchar	*numbufp;
576 
577 int
wrc(tchar i)578 wrc(tchar i)
579 {
580 	if (numbufp >= &numbuf[16])
581 		return(0);
582 	*numbufp++ = i;
583 	return(1);
584 }
585 
586 
587 
588 /* insert into input number i, in format form, with size-font bits bits */
589 void
setn1(int i,int form,tchar bits)590 setn1(int i, int form, tchar bits)
591 {
592 	numbufp = numbuf;
593 	nrbits = bits;
594 	nform = form;
595 	fnumb(i, wrc);
596 	*numbufp = 0;
597 	pushback(numbuf);
598 }
599 
600 
601 static void
nrehash(struct numtab * numtp,int n,struct numtab ** hashp)602 nrehash(struct numtab *numtp, int n, struct numtab **hashp)
603 {
604 	register struct numtab *p;
605 	register int i;
606 
607 	for (i=0; i<128; i++)
608 		hashp[i] = 0;
609 	for (p=numtp; p < &numtp[n]; p++)
610 		p->link = 0;
611 	for (p=numtp; p < &numtp[n]; p++) {
612 		if (p->r == 0)
613 			continue;
614 		i = NHASH(p->r);
615 		p->link = hashp[i];
616 		hashp[i] = p;
617 	}
618 }
619 
620 void
nunhash(register struct numtab * rp)621 nunhash(register struct numtab *rp)
622 {
623 	register struct numtab *p;
624 	register struct numtab **lp;
625 	struct numtab	**hashp;
626 	struct s	*sp;
627 
628 	if (rp->r == 0)
629 		return;
630 	if (rp >= numtab && rp < &numtab[NN])
631 		hashp = nhash;
632 	else {
633 		sp = macframe();
634 		if (rp >= sp->numtab && rp < &sp->numtab[sp->NN])
635 			hashp = sp->nhash;
636 		else
637 			return;
638 	}
639 	lp = &hashp[NHASH(rp->r)];
640 	p = *lp;
641 	while (p) {
642 		if (p == rp) {
643 			*lp = p->link;
644 			p->link = 0;
645 			return;
646 		}
647 		lp = &p->link;
648 		p = p->link;
649 	}
650 }
651 
652 
653 /*
654  * Note: Pointers returned by findr(), usedr(), etc. may
655  * become invalid after a following call to getch() or another
656  * call to findr() since these may result in a number register
657  * creation and following grownumtab().
658  */
659 struct numtab *
findr(int i)660 findr(int i)
661 {
662 	return _findr(i, 0, 1, 0, NULL);
663 }
664 
665 static struct numtab *
findr1(struct numtab ** numtp,int * NNp,struct numtab *** hashp,register int i,int rd,int aln,int create,int * rop)666 findr1(struct numtab **numtp, int *NNp, struct numtab ***hashp,
667 		register int i, int rd, int aln, int create, int *rop)
668 {
669 	register struct numtab *p;
670 	register int h = NHASH(i);
671 
672 	if (rop)
673 		*rop = 0;
674 	if (i == 0 || i == -2)
675 		return(NULL);
676 	if (*hashp != NULL) {
677 		for (p = (*hashp)[h]; p; p = p->link)
678 			if (i == p->r) {
679 				if (p->aln < 0) {
680 					if (aln > 1) {
681 						if (rop)
682 							*rop = p->aln;
683 						return(NULL);
684 					} else if (aln)
685 						continue;
686 				}
687 				if (aln && p->aln > 0)
688 					return(&(*numtp)[p->aln - 1]);
689 				return(p);
690 			}
691 	}
692 	if (create) {
693 		if (rd && warn & WARN_REG)
694 			errprint("no such register %s", macname(i));
695 		do {
696 			for (p = *numtp; p < &(*numtp)[*NNp]; p++) {
697 				if (p->r == 0) {
698 					p->r = i;
699 					p->link = (*hashp)[h];
700 					(*hashp)[h] = p;
701 					regcnt++;
702 					if (*numtp != numtab)
703 						p->flags |= FLAG_LOCAL;
704 					return(p);
705 				}
706 			}
707 		} while (p == &(*numtp)[*NNp] &&
708 				_grownumtab(numtp, NNp, hashp) != NULL);
709 		errprint("too many number registers (%d).", *NNp);
710 		done2(04);
711 	}
712 	return(NULL);
713 }
714 
715 static struct numtab *
_findr(register int i,int rd,int aln,int forcecreate,int * rop)716 _findr(register int i, int rd, int aln, int forcecreate, int *rop)
717 {
718 	struct s	*sp;
719 	struct numtab	*numtp;
720 
721 	if ((sp = macframe()) != stk) {
722 		if ((numtp = findr1(&sp->numtab, &sp->NN, &sp->nhash,
723 				i, rd, aln, forcecreate == 1, rop)) != NULL)
724 			return numtp;
725 	}
726 	return findr1(&numtab, &NN, &nhash, i, rd, aln, forcecreate >= 0, rop);
727 }
728 
729 
730 static struct numtab *
_usedr(register int i,int aln,int * rop)731 _usedr (	/* returns NULL if nr i has never been used */
732     register int i, int aln, int *rop
733 )
734 {
735 	return _findr(i, 0, aln, -1, rop);
736 }
737 
738 
739 struct numtab *
usedr(int i)740 usedr(int i)
741 {
742 	return _usedr(i, 1, NULL);
743 }
744 
745 
746 int
fnumb(register int i,register int (* f)(tchar))747 fnumb(register int i, register int (*f)(tchar))
748 {
749 	register int j;
750 
751 	j = 0;
752 	if (i < 0) {
753 		j = (*f)('-' | nrbits);
754 		i = -i;
755 	}
756 	switch (nform) {
757 	default:
758 	case '1':
759 	case 0:
760 		return decml(i, f) + j;
761 		break;
762 	case 'i':
763 	case 'I':
764 		return roman(i, f) + j;
765 		break;
766 	case 'a':
767 	case 'A':
768 		return abc(i, f) + j;
769 		break;
770 	}
771 }
772 
773 
774 int
decml(register int i,register int (* f)(tchar))775 decml(register int i, register int (*f)(tchar))
776 {
777 	register int j, k;
778 
779 	k = 0;
780 	nform--;
781 	if ((j = i / 10) || (nform > 0))
782 		k = decml(j, f);
783 	return(k + (*f)((i % 10 + '0') | nrbits));
784 }
785 
786 
787 int
roman(int i,int (* f)(tchar))788 roman(int i, int (*f)(tchar))
789 {
790 
791 	if (!i)
792 		return((*f)('0' | nrbits));
793 	if (nform == 'i')
794 		return(roman0(i, f, "ixcmz", "vldw"));
795 	else
796 		return(roman0(i, f, "IXCMZ", "VLDW"));
797 }
798 
799 
800 int
roman0(int i,int (* f)(tchar),char * onesp,char * fivesp)801 roman0(int i, int (*f)(tchar), char *onesp, char *fivesp)
802 {
803 	register int q, rem, k;
804 
805 	k = 0;
806 	if (!i)
807 		return(0);
808 	k = roman0(i / 10, f, onesp + 1, fivesp + 1);
809 	q = (i = i % 10) / 5;
810 	rem = i % 5;
811 	if (rem == 4) {
812 		k += (*f)(*onesp | nrbits);
813 		if (q)
814 			i = *(onesp + 1);
815 		else
816 			i = *fivesp;
817 		return(k += (*f)(i | nrbits));
818 	}
819 	if (q)
820 		k += (*f)(*fivesp | nrbits);
821 	while (--rem >= 0)
822 		k += (*f)(*onesp | nrbits);
823 	return(k);
824 }
825 
826 
827 int
abc(int i,int (* f)(tchar))828 abc(int i, int (*f)(tchar))
829 {
830 	if (!i)
831 		return((*f)('0' | nrbits));
832 	else
833 		return(abc0(i - 1, f));
834 }
835 
836 
837 int
abc0(int i,int (* f)(tchar))838 abc0(int i, int (*f)(tchar))
839 {
840 	register int j, k;
841 
842 	k = 0;
843 	if ((j = i / 26))
844 		k = abc0(j - 1, f);
845 	return(k + (*f)((i % 26 + nform) | nrbits));
846 }
847 
848 static int	illscale;
849 static int	parlevel;
850 static int	whitexpr;
851 static int	empty;
852 
853 static tchar
agetch(void)854 agetch(void)
855 {
856 	tchar	c;
857 
858 	for (;;) {
859 		c = getch();
860 		if (xflag == 0 || parlevel == 0 || cbits(c) != ' ')
861 			break;
862 		whitexpr++;
863 	}
864 	return c;
865 }
866 
867 int
hatoi(void)868 hatoi(void)
869 {
870 	struct acc	a;
871 
872 	lgf++;
873 	a = _atoi(0);
874 	lgf--;
875 	return a.n;
876 }
877 
878 float
atof(void)879 atof(void)
880 {
881 	struct acc	a;
882 
883 	lgf++;
884 	a = _atoi(1);
885 	lgf--;
886 	return a.f;
887 }
888 
889 static struct acc
_atoi(int flt)890 _atoi(int flt)
891 {
892 	struct acc	n;
893 	int	c;
894 
895 	illscale = 0;
896 	whitexpr = parlevel = 0;
897 	empty = 1;
898 	n = _atoi0(flt);
899 	c = cbits(ch);
900 	if (c == RIGHT) {
901 		if (!empty && (nonumb || parlevel) && warn & WARN_RIGHT_BRACE)
902 			errprint("\\} terminates numerical expression");
903 	} else if (nonumb && c && c != ' ' && c != '\n' &&
904 			warn & WARN_NUMBER && illscale == 0) {
905 		if (c == 'T' && Tflg)
906 			/*EMPTY*/;
907 		else if ((c & ~0177) == 0 && isprint(c))
908 			errprint("illegal number, char %c", c);
909 		else
910 			errprint("illegal number");
911 	} else if (warn & WARN_SYNTAX) {
912 		if (parlevel > 0)
913 			errprint("missing ')'");
914 		if (parlevel < 0)
915 			errprint("excess ')'");
916 		if (xflag && whitexpr && parlevel)
917 			nonumb = 1;
918 	}
919 	if (flt) {
920 		if (!nonumb && ((n.f<0 && n.f<-FLT_MAX) || (n.f>0 && n.f>FLT_MAX))) {
921 			if (warn & WARN_NUMBER)
922 				errprint("floating-point arithmetic overflow");
923 			if (xflag)
924 				nonumb = 1;
925 		}
926 	} else {
927 		if (!nonumb && ((n.n<0 && n.n <INT_MIN) || (n.n>0 && n.n>INT_MAX))) {
928 			if (warn & WARN_NUMBER)
929 				errprint("arithmetic overflow");
930 			if (xflag)
931 				nonumb = 1;
932 		}
933 	}
934 	return n;
935 }
936 
937 long long
atoi0(void)938 atoi0(void)
939 {
940 	struct acc	a;
941 
942 	whitexpr = parlevel = 0;
943 	lgf++;
944 	a = _atoi0(0);
945 	lgf--;
946 	return a.n;
947 }
948 
949 double
atof0(void)950 atof0(void)
951 {
952 	struct acc	a;
953 
954 	whitexpr = parlevel = 0;
955 	lgf++;
956 	a = _atoi0(0);
957 	lgf--;
958 	return a.f;
959 }
960 
961 static struct acc
_atoi0(int flt)962 _atoi0(int flt)
963 {
964 	register int c, k, cnt;
965 	register tchar ii;
966 	struct acc	i, acc;
967 
968 	noschr++;
969 	i.f = i.n = 0;
970 	acc.f = acc.n = 0;
971 	nonumb = 0;
972 	cnt = -1;
973 a0:
974 	cnt++;
975 	ii = agetch();
976 	c = cbits(ii);
977 	switch (c) {
978 	default:
979 		ch = ii;
980 		if (cnt)
981 			break;
982 	case '+':
983 		i = ckph(flt);
984 		if (nonumb)
985 			break;
986 		acc.n += i.n;
987 		if (flt) acc.f += i.f;
988 		goto a0;
989 	case '-':
990 		i = ckph(flt);
991 		if (nonumb)
992 			break;
993 		acc.n -= i.n;
994 		if (flt) acc.f -= i.f;
995 		goto a0;
996 	case '*':
997 		i = ckph(flt);
998 		if (nonumb)
999 			break;
1000 		if (!flt) acc.n *= i.n;
1001 		if (flt) acc.f *= i.f;
1002 		goto a0;
1003 	case '/':
1004 		i = ckph(flt);
1005 		if (nonumb)
1006 			break;
1007 		if ((!flt && i.n == 0) || (flt && i.f == 0)) {
1008 			flusho();
1009 			errprint("divide by zero.");
1010 			acc.n = 0;
1011 			if (flt) acc.f = 0;
1012 		} else  {
1013 			if (!flt) acc.n /= i.n;
1014 			if (flt) acc.f /= i.f;
1015 		}
1016 		goto a0;
1017 	case '%':
1018 		i = ckph(flt);
1019 		if (nonumb)
1020 			break;
1021 		if (flt) acc.n = acc.f, i.n = i.f;
1022 		if (i.n != 0)
1023 			acc.n %= i.n;
1024 		else if (warn & WARN_RANGE)
1025 			errprint("modulo by zero.");
1026 		if (flt) acc.f = acc.n;
1027 		goto a0;
1028 	case '&':	/*and*/
1029 		i = ckph(flt);
1030 		if (nonumb)
1031 			break;
1032 		if ((acc.n > 0) && (i.n > 0))
1033 			acc.n = 1;
1034 		else
1035 			acc.n = 0;
1036 		if (flt) acc.f = acc.n;
1037 		goto a0;
1038 	case ':':	/*or*/
1039 		i = ckph(flt);
1040 		if (nonumb)
1041 			break;
1042 		if ((acc.n > 0) || (i.n > 0))
1043 			acc.n = 1;
1044 		else
1045 			acc.n = 0;
1046 		if (flt) acc.f = acc.n;
1047 		goto a0;
1048 	case '=':
1049 		if (cbits(ii = getch()) != '=')
1050 			ch = ii;
1051 		i = ckph(flt);
1052 		if (nonumb) {
1053 			acc.n = 0;
1054 			if (flt) acc.f = 0;
1055 			break;
1056 		}
1057 		acc.n = i.n == acc.n;
1058 		if (flt) acc.f = i.f == acc.f;
1059 		goto a0;
1060 	case '>':
1061 		k = 0;
1062 		if (cbits(ii = getch()) == '=')
1063 			k++;
1064 		else if (xflag && cbits(ii) == '?')
1065 			goto maximum;
1066 		else
1067 			ch = ii;
1068 		i = ckph(flt);
1069 		if (nonumb) {
1070 			acc.n = 0;
1071 			if (flt) acc.f = 0;
1072 			break;
1073 		}
1074 		if (!flt) {
1075 			if (acc.n > (i.n - k))
1076 				acc.n = 1;
1077 			else
1078 				acc.n = 0;
1079 		} else
1080 			acc.f = k ? acc.f >= i.f : acc.f > i.f;
1081 		goto a0;
1082 	maximum:
1083 		i = ckph(flt);
1084 		if (nonumb) {
1085 			acc.n = 0;
1086 			if (flt) acc.f = 0;
1087 			break;
1088 		}
1089 		if (i.n > acc.n)
1090 			acc.n = i.n;
1091 		if (flt && i.f > acc.f)
1092 			acc.f = i.f;
1093 		goto a0;
1094 	case '<':
1095 		k = 0;
1096 		if (cbits(ii = getch()) == '=')
1097 			k++;
1098 		else if (xflag && cbits(ii) == '?')
1099 			goto minimum;
1100 		else if (xflag && cbits(ii) == '>')
1101 			goto notequal;
1102 		else
1103 			ch = ii;
1104 		i = ckph(flt);
1105 		if (nonumb) {
1106 			acc.n = 0;
1107 			if (flt) acc.f = 0;
1108 			break;
1109 		}
1110 		if (!flt) {
1111 			if (acc.n < (i.n + k))
1112 				acc.n = 1;
1113 			else
1114 				acc.n = 0;
1115 		} else
1116 			acc.f = k ? acc.f <= i.f : acc.f < i.f;
1117 		goto a0;
1118 	minimum:
1119 		i = ckph(flt);
1120 		if (nonumb) {
1121 			acc.n = 0;
1122 			if (flt) acc.f = 0;
1123 			break;
1124 		}
1125 		if (i.n < acc.n)
1126 			acc.n = i.n;
1127 		if (flt && i.f < acc.f)
1128 			acc.f = i.f;
1129 		goto a0;
1130 	notequal:
1131 		i = ckph(flt);
1132 		if (nonumb) {
1133 			acc.n = 0;
1134 			if (flt) acc.f = 0;
1135 			break;
1136 		}
1137 		acc.n = i.n != acc.n;
1138 		if (flt) acc.f = i.f != acc.f;
1139 		goto a0;
1140 	case ')':
1141 		parlevel--;
1142 		break;
1143 	case '(':
1144 		parlevel++;
1145 		acc = _atoi0(flt);
1146 		goto a0;
1147 	}
1148 	if (noschr) noschr--;
1149 	return(acc);
1150 }
1151 
1152 
1153 static struct acc
ckph(int flt)1154 ckph(int flt)
1155 {
1156 	register tchar i;
1157 	struct acc	j;
1158 
1159 	if (cbits(i = agetch()) == '(') {
1160 		parlevel++;
1161 		j = _atoi0(flt);
1162 	} else {
1163 		j = atoi1(i, flt);
1164 	}
1165 	return(j);
1166 }
1167 
1168 
1169 static struct acc
atoi1(register tchar ii,int flt)1170 atoi1(register tchar ii, int flt)
1171 {
1172 	register int i, j, digits;
1173 	int	digit = 0;
1174 	struct acc	acc;
1175 	int	neg, abs, field;
1176 	int	_noscale = 0, scale;
1177 	double	e, f;
1178 
1179 	neg = abs = field = digits = 0;
1180 	acc.f = acc.n = 0;
1181 	for (;;) {
1182 		i = cbits(ii);
1183 		switch (i) {
1184 		default:
1185 			break;
1186 		case '+':
1187 			ii = agetch();
1188 			continue;
1189 		case '-':
1190 			neg = 1;
1191 			ii = agetch();
1192 			continue;
1193 		case '|':
1194 			abs = 1 + neg;
1195 			neg = 0;
1196 			ii = agetch();
1197 			continue;
1198 		}
1199 		break;
1200 	}
1201 	if (xflag && i == '(') {
1202 		parlevel++;
1203 		acc = _atoi0(flt);
1204 		e = 1;
1205 		i = j = 1;
1206 		field = -1;
1207 		goto aa;
1208 	}
1209 a1:
1210 	while (i >= '0' && i <= '9') {
1211 		field++;
1212 		digits++;
1213 		digit = 1;
1214 		if (!flt)
1215 			acc.n = 10 * acc.n + i - '0';
1216 		else if (field == digits)
1217 			acc.f = 10 * acc.f + i - '0';
1218 		else {
1219 			f = i - '0';
1220 			for (j = 0; j < digits; j++)
1221 				f /= 10;
1222 			acc.f += f;
1223 		}
1224 		ii = getch();
1225 		i = cbits(ii);
1226 	}
1227 	if (i == '.') {
1228 		field++;
1229 		digits = 0;
1230 		ii = getch();
1231 		i = cbits(ii);
1232 		goto a1;
1233 	}
1234 	e = 1;
1235 	if (xflag && digits && (i == 'e' || i == 'E')) {
1236 		if ((i = cbits(ii = getch())) == '+')
1237 			j = 1;
1238 		else if (i == '-')
1239 			j = -1;
1240 		else if (i >= '0' && i <= '9') {
1241 			j = 1;
1242 			ch = ii;
1243 		} else {
1244 			ch = ii;
1245 			field = 0;
1246 			goto a2;
1247 		}
1248 		f = 0;
1249 		while ((i = cbits(ii = getch())) >= '0' && i <= '9')
1250 			f = f * 10 + i - '0';
1251 		while (f-- > 0)
1252 			e *= 10;
1253 		if (j < 0)
1254 			e = 1/e;
1255 	}
1256 	if ((!xflag || !parlevel) && !field) {
1257 		ch = ii;
1258 		goto a2;
1259 	}
1260 	switch (scale = i) {
1261 	case 's':
1262 		if (!xflag)
1263 			goto dfl;
1264 		/*FALLTHRU*/
1265 	case 'u':
1266 		i = j = 1;	/* should this be related to HOR?? */
1267 		break;
1268 	case 'v':	/*VSs - vert spacing*/
1269 		j = lss;
1270 		i = 1;
1271 		break;
1272 	case 'm':	/*Ems*/
1273 		j = EM;
1274 		i = 1;
1275 		break;
1276 	case 'n':	/*Ens*/
1277 		j = EM;
1278 #ifndef NROFF
1279 		i = 2;
1280 #endif
1281 #ifdef NROFF
1282 		i = 1;	/*Same as Ems in NROFF*/
1283 #endif
1284 		break;
1285 	case 'z':
1286 		if (!xflag)
1287 			goto dfl;
1288 		/*FALLTHRU*/
1289 	case 'p':	/*Points*/
1290 		j = INCH;
1291 		i = 72;
1292 		break;
1293 	case 'i':	/*Inches*/
1294 		j = INCH;
1295 		i = 1;
1296 		break;
1297 	case 'c':	/*Centimeters*/
1298 		/* if INCH is too big, this will overflow */
1299 		j = INCH * 50;
1300 		i = 127;
1301 		break;
1302 	case 'P':	/*Picas*/
1303 		j = INCH;
1304 		i = 6;
1305 		break;
1306 	case 'D':	/* Didot points */
1307 		if (!xflag)
1308 			goto dfl;
1309 		j = INCH * 24;	/* following H. R. Bosshard, */
1310 		i = 1621;	/* Technische Grundlagen zur */
1311 		break;		/* Satzherstellung, Berne 1980, p. 17 */
1312 	case 'C':	/* Cicero */
1313 		if (!xflag)
1314 			goto dfl;
1315 		j = INCH * 24 * 12;
1316 		i = 1621;
1317 		break;
1318 	case 't':	/* printer's points */
1319 		if (!xflag)
1320 			goto dfl;
1321 		j = INCH * 100;	/* following Knuth */
1322 		i = 7227;
1323 		break;
1324 	case 'T':	/* printer's picas */
1325 		if (!xflag)
1326 			goto dfl;
1327 		j = INCH * 100 * 4;
1328 		i = 2409;
1329 		break;
1330 	case 'M':	/*Ems/100*/
1331 		if (!xflag)
1332 			goto dfl;
1333 		j = EM;
1334 		i = 100;
1335 		break;
1336 	case ';':
1337 		if (!xflag)
1338 			goto dfl;
1339 		i = j = 1;
1340 		_noscale = 1;
1341 		goto newscale;
1342 	default:
1343 	dfl:	if (!field) {
1344 			ch = ii;
1345 			goto a2;
1346 		}
1347 		if (((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z')) &&
1348 				warn & WARN_SCALE) {
1349 			errprint("undefined scale indicator %c", i);
1350 			illscale = 1;
1351 		} else
1352 			scale = 0;
1353 		j = dfact;
1354 		ch = ii;
1355 		i = dfactd;
1356 	}
1357 	if (!field) {
1358 		tchar	t, tp[2];
1359 		int	f, d, n;
1360 		t = getch();
1361 		if (cbits(t) != ';') {
1362 			tp[0] = t;
1363 			tp[1] = 0;
1364 			pushback(tp);
1365 			ch = ii;
1366 			goto a2;
1367 		}
1368 	newscale:
1369 		/* (c;e) */
1370 		f = dfact;
1371 		d = dfactd;
1372 		n = noscale;
1373 		dfact = j;
1374 		dfactd = i;
1375 		noscale = _noscale;
1376 		acc = _atoi0(flt);
1377 		dfact = f;
1378 		dfactd = d;
1379 		noscale = n;
1380 		return(acc);
1381 	}
1382 	if (noscale && scale && warn & WARN_SYNTAX)
1383 		errprint("ignoring scale indicator %c", scale);
1384 aa:
1385 	if (neg) {
1386 		acc.n = -acc.n;
1387 		if (flt) acc.f = -acc.f;
1388 	}
1389 	if (!noscale) {
1390 		if (!flt) acc.n = (acc.n * j) / i;
1391 		if (flt) acc.f = (acc.f * j) / i;
1392 	}
1393 	if (!flt && (field != digits) && (digits > 0)) {
1394 		if (e != 1) acc.n = e * acc.n;
1395 		while (digits--)
1396 			acc.n /= 10;
1397 	} else if (e != 1) {
1398 		if (!flt) acc.n = (int)(e * acc.n);
1399 		if (flt) acc.f *= e;
1400 	}
1401 	if (abs) {
1402 		if (dip != d)
1403 			j = dip->dnl;
1404 		else
1405 			j = numtab[NL].val;
1406 		if (!vflag) {
1407 			j = numtab[HP].val;
1408 		}
1409 		if (abs == 2)
1410 			j = -j;
1411 		acc.n -= j;
1412 		if (flt) acc.f -= j;
1413 	}
1414 a2:
1415 	nonumb = !field || !digit;
1416 	if (empty)
1417 		empty = !field;
1418 	return(acc);
1419 }
1420 
1421 
1422 void
setnr(const char * name,int val,int inc)1423 setnr(const char *name, int val, int inc)
1424 {
1425 	int	j;
1426 	struct numtab	*numtp;
1427 
1428 	if ((j = makerq(name)) < 0)
1429 		return;
1430 	if ((numtp = findr(j)) == NULL)
1431 		return;
1432 	numtp->val = val;
1433 	numtp->inc = inc;
1434 	if (numtp->fmt == -1)
1435 		numtp->fmt = 0;
1436 	prwatchn(numtp);
1437 }
1438 
1439 void
setnrf(const char * name,float val,float inc)1440 setnrf(const char *name, float val, float inc)
1441 {
1442 	int	j;
1443 	struct numtab	*numtp;
1444 
1445 	if ((j = makerq(name)) < 0)
1446 		return;
1447 	if ((numtp = findr(j)) == NULL)
1448 		return;
1449 	numtp->val = numtp->fval = val;
1450 	numtp->inc = numtp->finc = inc;
1451 	numtp->fmt = -1;
1452 	prwatchn(numtp);
1453 }
1454 
1455 
1456 static void
clrnr(struct numtab * p)1457 clrnr(struct numtab *p)
1458 {
1459 	if (p != NULL) {
1460 		memset(p, 0, sizeof *p);
1461 		regcnt--;
1462 	}
1463 }
1464 
1465 void
caserr(void)1466 caserr(void)
1467 {
1468 	register int i;
1469 	struct numtab	*p, *kp;
1470 	int cnt = 0;
1471 
1472 	lgf++;
1473 	while (!skip(!cnt++) && (i = getrq(2)) ) {
1474 		p = _usedr(i, 0, NULL);
1475 		if (p == NULL)
1476 			continue;
1477 		nunhash(p);
1478 		if (p->aln && (kp = _usedr(i, 1, NULL)) != NULL) {
1479 			if (--kp->nlink <= 0)
1480 				clrnr(kp);
1481 		}
1482 		if (p->flags & FLAG_WATCH)
1483 			errprint("%s: removing %sregister %s", macname(lastrq),
1484 					p->flags & FLAG_LOCAL ? "local " : "",
1485 					macname(i));
1486 		if (p->nlink > 0)
1487 			p->nlink--;
1488 		if (p->nlink == 0)
1489 			clrnr(p);
1490 		else
1491 			p->r = -1;
1492 	}
1493 }
1494 
1495 
1496 void
casernn(void)1497 casernn(void)
1498 {
1499 	int	i, j, flags;
1500 	struct numtab	*kp, *numtp;
1501 
1502 	lgf++;
1503 	skip(1);
1504 	if ((i = getrq(0)) == 0)
1505 		return;
1506 	skip(1);
1507 	j = getrq(1);
1508 	if ((kp = _usedr(i, 0, NULL)) == NULL) {
1509 		if (warn & WARN_REG)
1510 			errprint("no such register %s", macname(i));
1511 		return;
1512 	}
1513 	flags = kp->flags;
1514 	numtp = _findr(j, 0, 0, flags & FLAG_LOCAL, NULL);
1515 	if (numtp != NULL) {
1516 		if (numtp->nlink) {
1517 			numtp->nlink--;
1518 			numtp->r = -1;
1519 		}
1520 		numtp = _findr(j, 0, 0, flags & FLAG_LOCAL, NULL);
1521 	}
1522 	kp = _usedr(i, 0, NULL);
1523 	if (numtp != NULL) {
1524 		*numtp = *kp;
1525 		numtp->r = j;
1526 	}
1527 	clrnr(kp);
1528 	if (numtp->flags & FLAG_WATCH)
1529 		errprint("%s: renaming %sregister %s to %s", macname(lastrq),
1530 				numtp->flags & FLAG_LOCAL ? "local " : "",
1531 				macname(i), macname(j));
1532 }
1533 
1534 
1535 void
setr(void)1536 setr(void)
1537 {
1538 	int	termc, j, rq;
1539 	struct numtab	*numtp;
1540 
1541 	lgf++;
1542 	termc = getach();
1543 	rq = getrq(3);
1544 	lgf--;
1545 	if (skip(1) || (numtp = findr(rq)) == NULL)
1546 		return;
1547 	j = inumb(&numtp->val);
1548 	if (nonumb)
1549 		return;
1550 	if (getach() != termc) {
1551 		nodelim(termc);
1552 		return;
1553 	}
1554 	numtp = findr(rq);	/* twice because of getch() before */
1555 	numtp->val = j;
1556 	if (numtp->fmt == -1)
1557 		numtp->fmt = 0;
1558 	prwatchn(numtp);
1559 }
1560 
1561 static void
casnr1(int flt,int local)1562 casnr1(int flt, int local)
1563 {
1564 	register int j, rq;
1565 	struct acc	a;
1566 	struct numtab	*numtp;
1567 
1568 	lgf++;
1569 	skip(1);
1570 	rq = getrq(3);
1571 	skip(!local);
1572 	if ((numtp = _findr(rq, 0, 1, local, NULL)) == NULL)
1573 		goto rtn;
1574 	a = _inumb(&numtp->val, flt ? &numtp->fval : NULL, flt, NULL);
1575 	if (nonumb)
1576 		goto rtn;
1577 	if (rq == PAIR('.', 'g')) gemu = xflag && a.n == 1 ? 1 : 0;
1578 	numtp->val = a.n;
1579 	if (flt) {
1580 		numtp->fval = a.f;
1581 		numtp->fmt = -1;
1582 	} else if (numtp->fmt == -1)
1583 		numtp->fmt = 0;
1584 	/*
1585 	 * It is common use in pre-processors and macro packages
1586 	 * to append a unit definition to a user-supplied number
1587 	 * in order to achieve a default scale. Catch this case
1588 	 * now to avoid a warning because of an illegal number.
1589 	 */
1590 	j = cbits(ch);
1591 	if (((j >= 'a' && j <= 'z') || (j >= 'A' && j <= 'Z')) &&
1592 			warn & WARN_SCALE)
1593 		goto rtns;
1594 	skip(0);
1595 	a = _atoi(flt);
1596 	if (nonumb)
1597 		goto rtns;
1598 	numtp = _findr(rq, 0, 1, local, NULL);
1599 	numtp->inc = a.n;
1600 	if (flt)
1601 		numtp->finc = a.f;
1602 rtns:
1603 	prwatchn(numtp);
1604 rtn:
1605 	return;
1606 }
1607 
1608 void
casenr(void)1609 casenr(void)
1610 {
1611 	casnr1(0, 0);
1612 }
1613 
1614 void
casenrf(void)1615 casenrf(void)
1616 {
1617 	casnr1(1, 0);
1618 }
1619 
1620 void
caselnr(void)1621 caselnr(void)
1622 {
1623 	casnr1(0, macframe() != stk);
1624 }
1625 
1626 void
caselnrf(void)1627 caselnrf(void)
1628 {
1629 	casnr1(1, macframe() != stk);
1630 }
1631 
1632 
1633 void
caseaf(void)1634 caseaf(void)
1635 {
1636 	register int i, k;
1637 	register tchar j, jj;
1638 	struct numtab	*numtp;
1639 
1640 	lgf++;
1641 	if (skip(1) || !(i = getrq(3)))
1642 		return;
1643 	if (skip(1))
1644 		return;
1645 	k = 0;
1646 	j = getch();
1647 	if (!ischar(jj = cbits(j)) || !isalpha(jj)) {
1648 		ch = j;
1649 		while ((j = cbits(getch())) >= '0' &&  j <= '9')
1650 			k++;
1651 	}
1652 	if (!k)
1653 		k = j;
1654 	numtp = findr(i);
1655 	if (numtp->fmt == -1) {
1656 		if (warn & WARN_RANGE)
1657 			errprint("cannot change format of floating-point register");
1658 		return;
1659 	}
1660 	numtp->fmt = k & BYTEMASK;
1661 	if (numtp->flags & FLAG_WATCH) {
1662 		char	b[40];
1663 		int	x;
1664 		if ((k & BYTEMASK) > ' ') {
1665 			b[0] = k & BYTEMASK;
1666 			b[1] = 0;
1667 		} else {
1668 			for (x = 0; x < k; x++)
1669 				b[x] = '0';
1670 			b[x] = 0;
1671 		}
1672 		errprint("%s: format of %sregister %s set to %s",
1673 				macname(lastrq),
1674 				numtp->flags & FLAG_LOCAL ? "local " : "",
1675 				macname(i), b);
1676 	}
1677 }
1678 
1679 void
setaf(void)1680 setaf (void)	/* return format of number register */
1681 {
1682 	register int j;
1683 	struct numtab	*numtp;
1684 
1685 	numtp = usedr(getsn(0));
1686 	if (numtp == NULL)
1687 		return;
1688 	if (numtp->fmt > 20)	/* it was probably a, A, i or I */
1689 		pbbuf[pbp++] = numtp->fmt;
1690 	else if (numtp->fmt == -1)
1691 		pbbuf[pbp++] = '0';
1692 	else {
1693 		for (j = (numtp->fmt ? numtp->fmt : 1); j; j--) {
1694 			if (pbp >= pbsize-3)
1695 				if (growpbbuf() == NULL) {
1696 					errprint("no space for .af");
1697 					done(2);
1698 				}
1699 			pbbuf[pbp++] = '0';
1700 		}
1701 	}
1702 }
1703 
1704 
1705 void
casealn(void)1706 casealn(void)
1707 {
1708 	int	c, i, j, k;
1709 	int	flags, local = 0;
1710 	struct numtab	*op, *rp = NULL;
1711 
1712 	if (skip(1))
1713 		return;
1714 	i = getrq(1);
1715 	if (skip(1))
1716 		return;
1717 	j = getrq(1);
1718 	for (c = 0; ; c++) {
1719 		if (((op = _usedr(j, 2, &k)) == NULL)) {
1720 			if (k < -1)
1721 				/*EMPTY*/;
1722 			else if (_setn(j))
1723 				k = -j;
1724 			else {
1725 				if (warn & WARN_REG)
1726 					errprint("no such register %s",
1727 							macname(j));
1728 				return;
1729 			}
1730 		}
1731 		if (c)
1732 			break;
1733 		local = op != NULL && op->flags & FLAG_LOCAL;
1734 		if ((rp = _findr(i, 0, 0, local, NULL)) == NULL)
1735 			return;
1736 	}
1737 	if (op != NULL) {
1738 		rp->aln = op - (local ? macframe()->numtab : numtab) + 1;
1739 		if (op->nlink == 0)
1740 			op->nlink = 1;
1741 		op->nlink++;
1742 	} else
1743 		rp->aln = k;
1744 	flags = rp->flags;
1745 	if (op != NULL)
1746 		flags |= op->flags;
1747 	if (flags & FLAG_WATCH)
1748 		errprint("%s: creating alias %s to %sregister %s",
1749 				macname(lastrq), macname(i),
1750 				op->flags & FLAG_LOCAL ? "local " : "",
1751 				macname(j));
1752 }
1753 
1754 
1755 void
casewatchn(int unwatch)1756 casewatchn(int unwatch)
1757 {
1758 	int	j;
1759 	struct numtab	*numtp;
1760 
1761 	lgf++;
1762 	if (skip(1))
1763 		return;
1764 	do {
1765 		if (!(j = getrq(1)) || (numtp = findr(j)) == NULL)
1766 			break;
1767 		if (unwatch)
1768 			numtp->flags &= ~FLAG_WATCH;
1769 		else
1770 			numtp->flags |= FLAG_WATCH;
1771 	} while (!skip(0));
1772 }
1773 
1774 
1775 void
caseunwatchn(void)1776 caseunwatchn(void)
1777 {
1778 	casewatchn(1);
1779 }
1780 
1781 
1782 void
prwatchn(struct numtab * numtp)1783 prwatchn(struct numtab *numtp)
1784 {
1785 	char	*local;
1786 
1787 	if (numtp == NULL)
1788 		return;
1789 	local = numtp->flags & FLAG_LOCAL ? "local " : "";
1790 	if (numtp->flags & FLAG_WATCH) {
1791 		if (numtp->fmt == -1)
1792 			errprint("%s: %sfloating-point register %s set to %g, increment %g",
1793 					macname(lastrq), local,
1794 					macname(numtp->r),
1795 					numtp->fval, numtp->finc);
1796 		else
1797 			errprint("%s: %sregister %s set to %d, increment %d",
1798 					macname(lastrq), local,
1799 					macname(numtp->r),
1800 					numtp->val, numtp->inc);
1801 	}
1802 }
1803 
1804 
1805 int
vnumb(int * i)1806 vnumb(int *i)
1807 {
1808 	vflag++;
1809 	dfact = lss;
1810 	res = VERT;
1811 	return(inumb(i));
1812 }
1813 
1814 
1815 int
hnumb(int * i)1816 hnumb(int *i)
1817 {
1818 	dfact = EM;
1819 	res = HOR;
1820 	return(inumb(i));
1821 }
1822 
1823 
1824 int
inumb(int * n)1825 inumb(int *n)
1826 {
1827 	struct acc	a;
1828 
1829 	a = _inumb(n, NULL, 0, NULL);
1830 	return a.n;
1831 }
1832 
1833 
1834 int
inumb2(int * n,int * relative)1835 inumb2(int *n, int *relative)
1836 {
1837 	struct acc	a;
1838 
1839 	a = _inumb(n, NULL, 0, relative);
1840 	return a.n;
1841 }
1842 
1843 static struct acc
_inumb(int * n,float * fp,int flt,int * relative)1844 _inumb(int *n, float *fp, int flt, int *relative)
1845 {
1846 	struct acc	i;
1847 	register int j, f;
1848 	register tchar ii;
1849 	int	nv = 0;
1850 	float	fv = 0;
1851 
1852 	f = 0;
1853 	lgf++;
1854 	if (n) {
1855 		nv = *n;
1856 		if (fp)
1857 			fv = *fp;
1858 		noschr++;
1859 		if ((j = cbits(ii = getch())) == '+')
1860 			f = 1;
1861 		else if (j == '-')
1862 			f = -1;
1863 		else
1864 			ch = ii;
1865 		if (noschr) noschr--;
1866 	}
1867 	i = _atoi(flt);
1868 	lgf--;
1869 	if (n && f && !flt)
1870 		i.n = nv + f * i.n;
1871 	if (fp && f && flt)
1872 		i.f = fv + f * i.f;
1873 	if (!flt) i.n = quant(i.n, res);
1874 	vflag = 0;
1875 	res = dfactd = dfact = 1;
1876 	if (nonumb) {
1877 		i.n = 0;
1878 		if (flt) i.f = 0;
1879 	}
1880 	if (relative)
1881 		*relative = f;
1882 	return(i);
1883 }
1884 
1885 
1886 float
atop(void)1887 atop(void)
1888 {
1889 	float	t;
1890 
1891 	noscale++;
1892 	t = atof();
1893 	noscale--;
1894 	if (t < -INFPENALTY)
1895 		t = -INFPENALTY;
1896 	else if (t > INFPENALTY)
1897 		t = INFPENALTY;
1898 	else
1899 		t *= PENALSCALE;
1900 	return t;
1901 }
1902 
1903 
1904 int
quant(int n,int m)1905 quant(int n, int m)
1906 {
1907 	register int i, neg;
1908 
1909 	neg = 0;
1910 	if (n < 0) {
1911 		neg++;
1912 		n = -n;
1913 	}
1914 	/* better as i = ((n + (m/2))/m)*m */
1915 	i = n / m;
1916 	if ((n - m * i) > (m / 2))
1917 		i += 1;
1918 	i *= m;
1919 	if (neg)
1920 		i = -i;
1921 	return(i);
1922 }
1923 
1924 
1925 tchar
moflo(int n)1926 moflo(int n)
1927 {
1928 	if (warn & WARN_RANGE)
1929 		errprint("value too large for motion");
1930 	return sabsmot(MAXMOT);
1931 }
1932