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