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