4 * number registers, conversion, arithmetic
13 int falsef = 0; /* on if inside false branch of if */
15 #define NHASHSIZE 128 /* must be 2**n */
16 #define NHASH(i) ((i>>6)^i) & (NHASHSIZE-1)
17 Numtab *nhash[NHASHSIZE];
19 Numtab *numtabp = NULL;
28 char buf[NTM]; /* for \n(.S */
31 if ((i = cbits(ii = getach())) == '+')
35 else if (ii) /* don't put it back if it's already back (thanks to jaap) */
39 if ((i = getsn()) == 0)
109 break; /* -Tterm used in nroff */
125 case 'R': /* maximal # of regs that can be addressed */
126 i = 255*256 - regcnt;
129 p = unpair(dip->curd);
130 *pbp++ = p[1]; /* watch order */
137 cpushback(cfname[ifi]);
141 for( i = 0; tabtab[i] != 0 && i < NTAB; i++) {
144 sprintf(&buf[j], "%d", tabtab[i] & TABMASK);
146 if ( tabtab[i] & RTAB)
147 sprintf(&buf[j], "uR");
148 else if (tabtab[i] & CTAB)
149 sprintf(&buf[j], "uC");
151 sprintf(&buf[j], "uL");
161 if ((j = findr(i)) == -1)
164 i = numtabp[j].val = numtabp[j].val + numtabp[j].inc * f;
165 nform = numtabp[j].fmt;
168 setn1(i, nform, (Tchar) 0);
176 if (numbufp >= &numbuf[24])
184 /* insert into input number i, in format form, with size-font bits bits */
185 void setn1(int i, int form, Tchar bits)
195 void prnumtab(Numtab *p)
198 for (i = 0; i < ncnt; i++)
201 fprintf(stderr, "slot %d, %s, val %d\n", i, unpair(p[i].r), p[i].val);
203 fprintf(stderr, "slot %d empty\n", i);
205 fprintf(stderr, "slot %d empty\n", i);
210 ncnt = sizeof(numtab)/sizeof(Numtab) + NDELTA;
211 numtabp = (Numtab *) grow((char *)numtabp, ncnt, sizeof(Numtab));
212 if (numtabp == NULL) {
213 ERROR "not enough memory for registers (%d)", ncnt WARN;
216 numtabp = (Numtab *) memcpy((char *)numtabp, (char *)numtab,
218 if (numtabp == NULL) {
219 ERROR "Cannot initialize registers" WARN;
224 void grownumtab(void)
227 numtabp = (Numtab *) grow((char *) numtabp, ncnt, sizeof(Numtab));
228 if (numtabp == NULL) {
229 ERROR "Too many number registers (%d)", ncnt WARN;
232 memset((char *)(numtabp) + (ncnt - NDELTA) * sizeof(Numtab),
233 0, NDELTA * sizeof(Numtab));
243 for (i=0; i<NHASHSIZE; i++)
245 for (p=numtabp; p < &numtabp[ncnt]; p++)
247 for (p=numtabp; p < &numtabp[ncnt]; p++) {
256 void nunhash(Numtab *rp)
263 lp = &nhash[NHASH(rp->r)];
284 for (p = nhash[h]; p; p = p->link)
287 for (p = numtabp; p < &numtabp[ncnt]; p++) {
300 int usedr(int i) /* returns -1 if nr i has never been used */
306 for (p = nhash[NHASH(i)]; p; p = p->link)
313 int fnumb(int i, int (*f)(Tchar))
319 j = (*f)('-' | nrbits);
326 return decml(i, f) + j;
329 return roman(i, f) + j;
332 return abc(i, f) + j;
337 int decml(int i, int (*f)(Tchar))
343 if ((j = i / 10) || (nform > 0))
345 return(k + (*f)((i % 10 + '0') | nrbits));
349 int roman(int i, int (*f)(Tchar))
353 return((*f)('0' | nrbits));
355 return(roman0(i, f, "ixcmz", "vldw"));
357 return(roman0(i, f, "IXCMZ", "VLDW"));
361 int roman0(int i, int (*f)(Tchar), char *onesp, char *fivesp)
367 k = roman0(i / 10, f, onesp + 1, fivesp + 1);
368 q = (i = i % 10) / 5;
371 k += (*f)(*onesp | nrbits);
376 return(k += (*f)(i | nrbits));
379 k += (*f)(*fivesp | nrbits);
381 k += (*f)(*onesp | nrbits);
386 int abc(int i, int (*f)(Tchar))
389 return((*f)('0' | nrbits));
391 return(abc0(i - 1, f));
395 int abc0(int i, int (*f)(Tchar))
402 return(k + (*f)((i % 26 + nform) | nrbits));
447 ERROR "divide by zero." WARN;
462 if ((acc > 0) && (i > 0))
471 if ((acc > 0) || (i > 0))
477 if (cbits(ii = getch()) != '=')
491 if (cbits(ii = getch()) == '=')
507 if (cbits(ii = getch()) == '=')
536 if (cbits(i = getch()) == '(')
546 * print error about illegal numeric argument;
551 static char warn[] = "Numeric argument expected";
552 int savcd = numtabp[CD].val;
554 if (numerr.type == RQERR)
555 sprintf(err_buf, "%c%s: %s", nb ? cbits(c2) : cbits(cc),
556 unpair(numerr.req), warn);
558 sprintf(err_buf, "\\%c'%s': %s", numerr.esc, &numerr.escarg,
560 if (frame != stk) /* uncertainty correction */
563 numtabp[CD].val = savcd;
570 double acc; /* this is the only double in troff! */
571 int neg, abs, field, decpnt;
575 neg = abs = field = decpnt = digits = 0;
598 while (i >= '0' && i <= '9') {
601 acc = 10 * acc + i - '0';
605 if (i == '.' && !decpnt++) {
618 i = j = 1; /* should this be related to HOR?? */
620 case 'v': /*VSs - vert spacing*/
633 i = 1; /*Same as Ems in NROFF*/
643 case 'c': /*Centimeters*/
644 /* if INCH is too big, this will overflow */
662 if (field != digits && digits > 0)
678 nonumb = (!field || field == decpnt);
679 if (nonumb && (trace & TRNARGS) && !ismot(ii) && !nlflg && !ifnum) {
680 if (cbits(ii) != RIGHT ) /* Too painful to do right */
693 while (!skip() && (i = getrq()) ) {
699 p->r = p->val = p->inc = p->fmt = 0;
705 * .nr request; if tracing, don't check optional
706 * 2nd argument because tbl generates .in 1.5n
715 if ((i = findr(getrq())) == -1)
718 j = inumb(&numtabp[i].val);
724 j = atoi0(); /* BUG??? */
739 if (skip() || !(i = getrq()) || skip())
743 if (!isalpha(cbits(j))) {
745 while ((j = cbits(getch())) >= '0' && j <= '9')
750 numtabp[findr(i)].fmt = k; /* was k & BYTEMASK */
753 void setaf(void) /* return format of number register */
760 if (numtabp[i].fmt > 20) /* it was probably a, A, i or I */
761 *pbp++ = numtabp[i].fmt;
763 for (j = (numtabp[i].fmt ? numtabp[i].fmt : 1); j; j--)
792 if ((j = cbits(ii = getch())) == '+')
804 res = dfactd = dfact = 1;
811 int quant(int n, int m)
820 /* better as i = ((n + m/2)/m)*m */
822 if (n - m * i > m / 2)