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