|
|
1.1 ! root 1: /* ! 2: * troff4.c ! 3: * ! 4: * number registers, conversion, arithmetic ! 5: */ ! 6: ! 7: #include "tdef.h" ! 8: #include "fns.h" ! 9: #include "ext.h" ! 10: ! 11: ! 12: int regcnt = NNAMES; ! 13: int falsef = 0; /* on if inside false branch of if */ ! 14: ! 15: #define NHASHSIZE 128 /* must be 2**n */ ! 16: #define NHASH(i) ((i>>6)^i) & (NHASHSIZE-1) ! 17: Numtab *nhash[NHASHSIZE]; ! 18: ! 19: void setn(void) ! 20: { ! 21: int i, j, f; ! 22: Tchar ii; ! 23: char *p; ! 24: char buf[NTM]; /* for \n(.S */ ! 25: ! 26: f = nform = 0; ! 27: if ((i = cbits(ii = getach())) == '+') ! 28: f = 1; ! 29: else if (i == '-') ! 30: f = -1; ! 31: else if (ii) /* don't put it back if it's already back (thanks to jaap) */ ! 32: ch = ii; ! 33: if (falsef) ! 34: f = 0; ! 35: if ((i = getsn()) == 0) ! 36: return; ! 37: p = unpair(i); ! 38: if (p[0] == '.') ! 39: switch (p[1]) { ! 40: case 's': ! 41: i = pts; ! 42: break; ! 43: case 'v': ! 44: i = lss; ! 45: break; ! 46: case 'f': ! 47: i = font; ! 48: break; ! 49: case 'p': ! 50: i = pl; ! 51: break; ! 52: case 't': ! 53: i = findt1(); ! 54: break; ! 55: case 'o': ! 56: i = po; ! 57: break; ! 58: case 'l': ! 59: i = ll; ! 60: break; ! 61: case 'i': ! 62: i = in; ! 63: break; ! 64: case '$': ! 65: i = frame->nargs; ! 66: break; ! 67: case 'A': ! 68: i = ascii; ! 69: break; ! 70: case 'c': ! 71: i = numtab[CD].val; ! 72: break; ! 73: case 'n': ! 74: i = lastl; ! 75: break; ! 76: case 'a': ! 77: i = ralss; ! 78: break; ! 79: case 'h': ! 80: i = dip->hnl; ! 81: break; ! 82: case 'd': ! 83: if (dip != d) ! 84: i = dip->dnl; ! 85: else ! 86: i = numtab[NL].val; ! 87: break; ! 88: case 'u': ! 89: i = fi; ! 90: break; ! 91: case 'j': ! 92: i = ad + 2 * admod; ! 93: break; ! 94: case 'w': ! 95: i = widthp; ! 96: break; ! 97: case 'x': ! 98: i = nel; ! 99: break; ! 100: case 'y': ! 101: i = un; ! 102: break; ! 103: case 'T': ! 104: i = dotT; ! 105: break; /* -Tterm used in nroff */ ! 106: case 'V': ! 107: i = VERT; ! 108: break; ! 109: case 'H': ! 110: i = HOR; ! 111: break; ! 112: case 'k': ! 113: i = ne; ! 114: break; ! 115: case 'P': ! 116: i = print; ! 117: break; ! 118: case 'L': ! 119: i = ls; ! 120: break; ! 121: case 'R': ! 122: i = NN - regcnt; ! 123: break; ! 124: case 'z': ! 125: p = unpair(dip->curd); ! 126: *pbp++ = p[1]; /* watch order */ ! 127: *pbp++ = p[0]; ! 128: return; ! 129: case 'b': ! 130: i = bdtab[font]; ! 131: break; ! 132: case 'F': ! 133: cpushback(cfname[ifi]); ! 134: return; ! 135: case 'S': ! 136: buf[0] = j = 0; ! 137: for( i = 0; tabtab[i] != 0 && i < NTAB; i++) { ! 138: if (i > 0) ! 139: buf[j++] = ' '; ! 140: sprintf(&buf[j], "%d", tabtab[i] & TABMASK); ! 141: j = strlen(buf); ! 142: if ( tabtab[i] & RTAB) ! 143: sprintf(&buf[j], "uR"); ! 144: else if (tabtab[i] & CTAB) ! 145: sprintf(&buf[j], "uC"); ! 146: else ! 147: sprintf(&buf[j], "uL"); ! 148: j += 2; ! 149: } ! 150: cpushback(buf); ! 151: return; ! 152: default: ! 153: goto s0; ! 154: } ! 155: else { ! 156: s0: ! 157: if ((j = findr(i)) == -1) ! 158: i = 0; ! 159: else { ! 160: i = numtab[j].val = numtab[j].val + numtab[j].inc * f; ! 161: nform = numtab[j].fmt; ! 162: } ! 163: } ! 164: setn1(i, nform, (Tchar) 0); ! 165: } ! 166: ! 167: Tchar numbuf[25]; ! 168: Tchar *numbufp; ! 169: ! 170: int wrc(Tchar i) ! 171: { ! 172: if (numbufp >= &numbuf[24]) ! 173: return(0); ! 174: *numbufp++ = i; ! 175: return(1); ! 176: } ! 177: ! 178: ! 179: ! 180: /* insert into input number i, in format form, with size-font bits bits */ ! 181: void setn1(int i, int form, Tchar bits) ! 182: { ! 183: numbufp = numbuf; ! 184: nrbits = bits; ! 185: nform = form; ! 186: fnumb(i, wrc); ! 187: *numbufp = 0; ! 188: pushback(numbuf); ! 189: } ! 190: ! 191: ! 192: void nrehash(void) ! 193: { ! 194: Numtab *p; ! 195: int i; ! 196: ! 197: for (i=0; i<NHASHSIZE; i++) ! 198: nhash[i] = 0; ! 199: for (p=numtab; p < &numtab[NN]; p++) ! 200: p->link = 0; ! 201: for (p=numtab; p < &numtab[NN]; p++) { ! 202: if (p->r == 0) ! 203: continue; ! 204: i = NHASH(p->r); ! 205: p->link = nhash[i]; ! 206: nhash[i] = p; ! 207: } ! 208: } ! 209: ! 210: void nunhash(Numtab *rp) ! 211: { ! 212: Numtab *p; ! 213: Numtab **lp; ! 214: ! 215: if (rp->r == 0) ! 216: return; ! 217: lp = &nhash[NHASH(rp->r)]; ! 218: p = *lp; ! 219: while (p) { ! 220: if (p == rp) { ! 221: *lp = p->link; ! 222: p->link = 0; ! 223: return; ! 224: } ! 225: lp = &p->link; ! 226: p = p->link; ! 227: } ! 228: } ! 229: ! 230: int findr(int i) ! 231: { ! 232: Numtab *p; ! 233: int h = NHASH(i); ! 234: ! 235: if (i == 0) ! 236: return(-1); ! 237: for (p = nhash[h]; p; p = p->link) ! 238: if (i == p->r) ! 239: return(p - numtab); ! 240: for (p = numtab; p < &numtab[NN]; p++) { ! 241: if (p->r == 0) { ! 242: p->r = i; ! 243: p->link = nhash[h]; ! 244: nhash[h] = p; ! 245: regcnt++; ! 246: return(p - numtab); ! 247: } ! 248: } ! 249: ERROR "too many number registers (%d).", NN WARN; ! 250: done2(04); ! 251: /* NOTREACHED */ ! 252: return -1; ! 253: } ! 254: ! 255: int usedr(int i) /* returns -1 if nr i has never been used */ ! 256: { ! 257: Numtab *p; ! 258: ! 259: if (i == 0) ! 260: return(-1); ! 261: for (p = nhash[NHASH(i)]; p; p = p->link) ! 262: if (i == p->r) ! 263: return(p - numtab); ! 264: return -1; ! 265: } ! 266: ! 267: ! 268: int fnumb(int i, int (*f)(Tchar)) ! 269: { ! 270: int j; ! 271: ! 272: j = 0; ! 273: if (i < 0) { ! 274: j = (*f)('-' | nrbits); ! 275: i = -i; ! 276: } ! 277: switch (nform) { ! 278: default: ! 279: case '1': ! 280: case 0: ! 281: return decml(i, f) + j; ! 282: case 'i': ! 283: case 'I': ! 284: return roman(i, f) + j; ! 285: case 'a': ! 286: case 'A': ! 287: return abc(i, f) + j; ! 288: } ! 289: } ! 290: ! 291: ! 292: int decml(int i, int (*f)(Tchar)) ! 293: { ! 294: int j, k; ! 295: ! 296: k = 0; ! 297: nform--; ! 298: if ((j = i / 10) || (nform > 0)) ! 299: k = decml(j, f); ! 300: return(k + (*f)((i % 10 + '0') | nrbits)); ! 301: } ! 302: ! 303: ! 304: int roman(int i, int (*f)(Tchar)) ! 305: { ! 306: ! 307: if (!i) ! 308: return((*f)('0' | nrbits)); ! 309: if (nform == 'i') ! 310: return(roman0(i, f, "ixcmz", "vldw")); ! 311: else ! 312: return(roman0(i, f, "IXCMZ", "VLDW")); ! 313: } ! 314: ! 315: ! 316: int roman0(int i, int (*f)(Tchar), char *onesp, char *fivesp) ! 317: { ! 318: int q, rem, k; ! 319: ! 320: if (!i) ! 321: return(0); ! 322: k = roman0(i / 10, f, onesp + 1, fivesp + 1); ! 323: q = (i = i % 10) / 5; ! 324: rem = i % 5; ! 325: if (rem == 4) { ! 326: k += (*f)(*onesp | nrbits); ! 327: if (q) ! 328: i = *(onesp + 1); ! 329: else ! 330: i = *fivesp; ! 331: return(k += (*f)(i | nrbits)); ! 332: } ! 333: if (q) ! 334: k += (*f)(*fivesp | nrbits); ! 335: while (--rem >= 0) ! 336: k += (*f)(*onesp | nrbits); ! 337: return(k); ! 338: } ! 339: ! 340: ! 341: int abc(int i, int (*f)(Tchar)) ! 342: { ! 343: if (!i) ! 344: return((*f)('0' | nrbits)); ! 345: else ! 346: return(abc0(i - 1, f)); ! 347: } ! 348: ! 349: ! 350: int abc0(int i, int (*f)(Tchar)) ! 351: { ! 352: int j, k; ! 353: ! 354: k = 0; ! 355: if (j = i / 26) ! 356: k = abc0(j - 1, f); ! 357: return(k + (*f)((i % 26 + nform) | nrbits)); ! 358: } ! 359: ! 360: long atoi0(void) ! 361: { ! 362: int c, k, cnt; ! 363: Tchar ii; ! 364: long i, acc; ! 365: ! 366: acc = 0; ! 367: nonumb = 0; ! 368: cnt = -1; ! 369: a0: ! 370: cnt++; ! 371: ii = getch(); ! 372: c = cbits(ii); ! 373: switch (c) { ! 374: default: ! 375: ch = ii; ! 376: if (cnt) ! 377: break; ! 378: case '+': ! 379: i = ckph(); ! 380: if (nonumb) ! 381: break; ! 382: acc += i; ! 383: goto a0; ! 384: case '-': ! 385: i = ckph(); ! 386: if (nonumb) ! 387: break; ! 388: acc -= i; ! 389: goto a0; ! 390: case '*': ! 391: i = ckph(); ! 392: if (nonumb) ! 393: break; ! 394: acc *= i; ! 395: goto a0; ! 396: case '/': ! 397: i = ckph(); ! 398: if (nonumb) ! 399: break; ! 400: if (i == 0) { ! 401: flusho(); ! 402: ERROR "divide by zero." WARN; ! 403: acc = 0; ! 404: } else ! 405: acc /= i; ! 406: goto a0; ! 407: case '%': ! 408: i = ckph(); ! 409: if (nonumb) ! 410: break; ! 411: acc %= i; ! 412: goto a0; ! 413: case '&': /*and*/ ! 414: i = ckph(); ! 415: if (nonumb) ! 416: break; ! 417: if ((acc > 0) && (i > 0)) ! 418: acc = 1; ! 419: else ! 420: acc = 0; ! 421: goto a0; ! 422: case ':': /*or*/ ! 423: i = ckph(); ! 424: if (nonumb) ! 425: break; ! 426: if ((acc > 0) || (i > 0)) ! 427: acc = 1; ! 428: else ! 429: acc = 0; ! 430: goto a0; ! 431: case '=': ! 432: if (cbits(ii = getch()) != '=') ! 433: ch = ii; ! 434: i = ckph(); ! 435: if (nonumb) { ! 436: acc = 0; ! 437: break; ! 438: } ! 439: if (i == acc) ! 440: acc = 1; ! 441: else ! 442: acc = 0; ! 443: goto a0; ! 444: case '>': ! 445: k = 0; ! 446: if (cbits(ii = getch()) == '=') ! 447: k++; ! 448: else ! 449: ch = ii; ! 450: i = ckph(); ! 451: if (nonumb) { ! 452: acc = 0; ! 453: break; ! 454: } ! 455: if (acc > (i - k)) ! 456: acc = 1; ! 457: else ! 458: acc = 0; ! 459: goto a0; ! 460: case '<': ! 461: k = 0; ! 462: if (cbits(ii = getch()) == '=') ! 463: k++; ! 464: else ! 465: ch = ii; ! 466: i = ckph(); ! 467: if (nonumb) { ! 468: acc = 0; ! 469: break; ! 470: } ! 471: if (acc < (i + k)) ! 472: acc = 1; ! 473: else ! 474: acc = 0; ! 475: goto a0; ! 476: case ')': ! 477: break; ! 478: case '(': ! 479: acc = atoi0(); ! 480: goto a0; ! 481: } ! 482: return(acc); ! 483: } ! 484: ! 485: ! 486: long ckph(void) ! 487: { ! 488: Tchar i; ! 489: long j; ! 490: ! 491: if (cbits(i = getch()) == '(') ! 492: j = atoi0(); ! 493: else { ! 494: j = atoi1(i); ! 495: } ! 496: return(j); ! 497: } ! 498: ! 499: ! 500: long atoi1(Tchar ii) ! 501: { ! 502: int i, j, digits; ! 503: double acc; /* this is the only double in troff! */ ! 504: int neg, abs, field; ! 505: ! 506: neg = abs = field = digits = 0; ! 507: acc = 0; ! 508: for (;;) { ! 509: i = cbits(ii); ! 510: switch (i) { ! 511: default: ! 512: break; ! 513: case '+': ! 514: ii = getch(); ! 515: continue; ! 516: case '-': ! 517: neg = 1; ! 518: ii = getch(); ! 519: continue; ! 520: case '|': ! 521: abs = 1 + neg; ! 522: neg = 0; ! 523: ii = getch(); ! 524: continue; ! 525: } ! 526: break; ! 527: } ! 528: a1: ! 529: while (i >= '0' && i <= '9') { ! 530: field++; ! 531: digits++; ! 532: acc = 10 * acc + i - '0'; ! 533: ii = getch(); ! 534: i = cbits(ii); ! 535: } ! 536: if (i == '.') { ! 537: field++; ! 538: digits = 0; ! 539: ii = getch(); ! 540: i = cbits(ii); ! 541: goto a1; ! 542: } ! 543: if (!field) { ! 544: ch = ii; ! 545: goto a2; ! 546: } ! 547: switch (i) { ! 548: case 'u': ! 549: i = j = 1; /* should this be related to HOR?? */ ! 550: break; ! 551: case 'v': /*VSs - vert spacing*/ ! 552: j = lss; ! 553: i = 1; ! 554: break; ! 555: case 'm': /*Ems*/ ! 556: j = EM; ! 557: i = 1; ! 558: break; ! 559: case 'n': /*Ens*/ ! 560: j = EM; ! 561: if (TROFF) ! 562: i = 2; ! 563: else ! 564: i = 1; /*Same as Ems in NROFF*/ ! 565: break; ! 566: case 'p': /*Points*/ ! 567: j = INCH; ! 568: i = 72; ! 569: break; ! 570: case 'i': /*Inches*/ ! 571: j = INCH; ! 572: i = 1; ! 573: break; ! 574: case 'c': /*Centimeters*/ ! 575: /* if INCH is too big, this will overflow */ ! 576: j = INCH * 50; ! 577: i = 127; ! 578: break; ! 579: case 'P': /*Picas*/ ! 580: j = INCH; ! 581: i = 6; ! 582: break; ! 583: default: ! 584: j = dfact; ! 585: ch = ii; ! 586: i = dfactd; ! 587: } ! 588: if (neg) ! 589: acc = -acc; ! 590: if (!noscale) { ! 591: acc = (acc * j) / i; ! 592: } ! 593: if (field != digits && digits > 0) ! 594: while (digits--) ! 595: acc /= 10; ! 596: if (abs) { ! 597: if (dip != d) ! 598: j = dip->dnl; ! 599: else ! 600: j = numtab[NL].val; ! 601: if (!vflag) { ! 602: j = numtab[HP].val; ! 603: } ! 604: if (abs == 2) ! 605: j = -j; ! 606: acc -= j; ! 607: } ! 608: a2: ! 609: nonumb = !field; ! 610: return(acc); ! 611: } ! 612: ! 613: ! 614: void caserr(void) ! 615: { ! 616: int i, j; ! 617: Numtab *p; ! 618: ! 619: lgf++; ! 620: while (!skip() && (i = getrq()) ) { ! 621: j = usedr(i); ! 622: if (j < 0) ! 623: continue; ! 624: p = &numtab[j]; ! 625: nunhash(p); ! 626: p->r = p->val = p->inc = p->fmt = 0; ! 627: regcnt--; ! 628: } ! 629: } ! 630: ! 631: ! 632: void casenr(void) ! 633: { ! 634: int i, j; ! 635: ! 636: lgf++; ! 637: skip(); ! 638: if ((i = findr(getrq())) == -1) ! 639: goto rtn; ! 640: skip(); ! 641: j = inumb(&numtab[i].val); ! 642: if (nonumb) ! 643: goto rtn; ! 644: numtab[i].val = j; ! 645: skip(); ! 646: j = atoi0(); /* BUG??? */ ! 647: if (nonumb) ! 648: goto rtn; ! 649: numtab[i].inc = j; ! 650: rtn: ! 651: return; ! 652: } ! 653: ! 654: void caseaf(void) ! 655: { ! 656: int i, k; ! 657: Tchar j; ! 658: ! 659: lgf++; ! 660: if (skip() || !(i = getrq()) || skip()) ! 661: return; ! 662: k = 0; ! 663: j = getch(); ! 664: if (!isalpha(cbits(j))) { ! 665: ch = j; ! 666: while ((j = cbits(getch())) >= '0' && j <= '9') ! 667: k++; ! 668: } ! 669: if (!k) ! 670: k = j; ! 671: numtab[findr(i)].fmt = k; /* was k & BYTEMASK */ ! 672: } ! 673: ! 674: void setaf(void) /* return format of number register */ ! 675: { ! 676: int i, j; ! 677: ! 678: i = usedr(getsn()); ! 679: if (i == -1) ! 680: return; ! 681: if (numtab[i].fmt > 20) /* it was probably a, A, i or I */ ! 682: *pbp++ = numtab[i].fmt; ! 683: else ! 684: for (j = (numtab[i].fmt ? numtab[i].fmt : 1); j; j--) ! 685: *pbp++ = '0'; ! 686: } ! 687: ! 688: ! 689: int vnumb(int *i) ! 690: { ! 691: vflag++; ! 692: dfact = lss; ! 693: res = VERT; ! 694: return(inumb(i)); ! 695: } ! 696: ! 697: ! 698: int hnumb(int *i) ! 699: { ! 700: dfact = EM; ! 701: res = HOR; ! 702: return(inumb(i)); ! 703: } ! 704: ! 705: ! 706: int inumb(int *n) ! 707: { ! 708: int i, j, f; ! 709: Tchar ii; ! 710: ! 711: f = 0; ! 712: if (n) { ! 713: if ((j = cbits(ii = getch())) == '+') ! 714: f = 1; ! 715: else if (j == '-') ! 716: f = -1; ! 717: else ! 718: ch = ii; ! 719: } ! 720: i = atoi0(); ! 721: if (n && f) ! 722: i = *n + f * i; ! 723: i = quant(i, res); ! 724: vflag = 0; ! 725: res = dfactd = dfact = 1; ! 726: if (nonumb) ! 727: i = 0; ! 728: return(i); ! 729: } ! 730: ! 731: ! 732: int quant(int n, int m) ! 733: { ! 734: int i, neg; ! 735: ! 736: neg = 0; ! 737: if (n < 0) { ! 738: neg++; ! 739: n = -n; ! 740: } ! 741: /* better as i = ((n + m/2)/m)*m */ ! 742: i = n / m; ! 743: if (n - m * i > m / 2) ! 744: i += 1; ! 745: i *= m; ! 746: if (neg) ! 747: i = -i; ! 748: return(i); ! 749: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.