1 #include "tdef.h" 2 extern 3 #include "d.h" 4 extern 5 #include "v.h" 6 #ifdef NROFF 7 extern 8 #include "tw.h" 9 #endif 10 #include "s.h" 11 12 /* 13 troff3.c 14 15 macro and string routines, storage allocation 16 */ 17 #define INCORE /* defines not using temp files */ 18 19 #include <sgtty.h> 20 #include "ext.h" 21 #define blisti(i) (((i)-NEV*EVS)/BLK) 22 filep blist[NBLIST]; 23 tchar *argtop; 24 int pagech = '%'; 25 int strflg; 26 extern struct contab { 27 int rq; 28 union { 29 int (*f)(); 30 unsigned mx; 31 } x; 32 } contab[NM]; 33 34 #ifdef INCORE 35 tchar *wbuf; 36 tchar *rbuf; 37 tchar corebuf[NBLIST*BLK + NEV*EVS]; 38 #else 39 tchar wbuf[BLK]; 40 tchar rbuf[BLK]; 41 #endif 42 43 caseig() 44 { 45 register i; 46 47 offset = 0; 48 if ((i = copyb()) != '.') 49 control(i, 1); 50 } 51 52 53 casern() 54 { 55 register i, j; 56 57 lgf++; 58 skip(); 59 if ((i = getrq()) == 0 || (oldmn = findmn(i)) < 0) 60 return; 61 skip(); 62 clrmn(findmn(j = getrq())); 63 if (j) 64 contab[oldmn].rq = (contab[oldmn].rq & MMASK) | j; 65 } 66 67 68 caserm() 69 { 70 lgf++; 71 while (!skip()) { 72 clrmn(findmn(getrq())); 73 } 74 } 75 76 77 caseas() 78 { 79 app++; 80 caseds(); 81 } 82 83 84 caseds() 85 { 86 ds++; 87 casede(); 88 } 89 90 91 caseam() 92 { 93 app++; 94 casede(); 95 } 96 97 98 casede() 99 { 100 register i, req; 101 register filep savoff; 102 extern filep finds(); 103 104 if (dip != d) 105 wbfl(); 106 req = '.'; 107 lgf++; 108 skip(); 109 if ((i = getrq()) == 0) 110 goto de1; 111 if ((offset = finds(i)) == 0) 112 goto de1; 113 if (ds) 114 copys(); 115 else 116 req = copyb(); 117 wbfl(); 118 clrmn(oldmn); 119 if (newmn) 120 contab[newmn].rq = i | MMASK; 121 if (apptr) { 122 savoff = offset; 123 offset = apptr; 124 wbt((tchar) IMP); 125 offset = savoff; 126 } 127 offset = dip->op; 128 if (req != '.') 129 control(req, 1); 130 de1: 131 ds = app = 0; 132 return; 133 } 134 135 136 findmn(i) 137 register int i; 138 { 139 register j; 140 register struct contab *p; 141 142 for (p = contab; p < &contab[NM]; p++) { 143 if (i == (p->rq & ~MMASK)) 144 break; 145 } 146 j = p - contab; 147 if (j == NM) 148 j = -1; 149 return(j); 150 } 151 152 153 clrmn(i) 154 register int i; 155 { 156 if (i >= 0) { 157 if (contab[i].rq & MMASK) 158 ffree((filep)contab[i].x.mx); 159 contab[i].rq = 0; 160 contab[i].x.mx = 0; 161 } 162 } 163 164 165 filep finds(mn) 166 register int mn; 167 { 168 register i; 169 register filep savip; 170 extern filep alloc(); 171 extern filep incoff(); 172 173 oldmn = findmn(mn); 174 newmn = 0; 175 apptr = (filep)0; 176 if (app && oldmn >= 0 && (contab[oldmn].rq & MMASK)) { 177 savip = ip; 178 ip = (filep)contab[oldmn].x.mx; 179 oldmn = -1; 180 while ((i = rbf()) != 0) 181 ; 182 apptr = ip; 183 if (!diflg) 184 ip = incoff(ip); 185 nextb = ip; 186 ip = savip; 187 } else { 188 for (i = 0; i < NM; i++) { 189 if (contab[i].rq == 0) 190 break; 191 } 192 if (i == NM || (nextb = alloc()) == 0) { 193 app = 0; 194 if (macerr++ > 1) 195 done2(02); 196 fprintf(stderr, "troff: Too many (%d) string/macro names.\n", NM); 197 edone(04); 198 return(offset = 0); 199 } 200 contab[i].x.mx = (unsigned) nextb; 201 if (!diflg) { 202 newmn = i; 203 if (oldmn == -1) 204 contab[i].rq = -1; 205 } else { 206 contab[i].rq = mn | MMASK; 207 } 208 } 209 app = 0; 210 return(offset = nextb); 211 } 212 213 214 skip() 215 { 216 tchar i; 217 218 while (cbits(i = getch()) == ' ') 219 ; 220 ch = i; 221 return(nlflg); 222 } 223 224 225 copyb() 226 { 227 register i, j, k; 228 int req, state; 229 tchar ii; 230 filep savoff; 231 232 if (skip() || !(j = getrq())) 233 j = '.'; 234 req = j; 235 k = j >> BYTE; 236 j &= BMASK; 237 copyf++; 238 flushi(); 239 nlflg = 0; 240 state = 1; 241 while (1) { 242 i = cbits(ii = getch()); 243 if (state == 3) { 244 if (i == k) 245 break; 246 if (!k) { 247 ch = ii; 248 i = getach(); 249 ch = ii; 250 if (!i) 251 break; 252 } 253 state = 0; 254 goto c0; 255 } 256 if (i == '\n') { 257 state = 1; 258 nlflg = 0; 259 goto c0; 260 } 261 if (state == 1 && i == '.') { 262 state++; 263 savoff = offset; 264 goto c0; 265 } 266 if ((state == 2) && (i == j)) { 267 state++; 268 goto c0; 269 } 270 state = 0; 271 c0: 272 if (offset) 273 wbf(ii); 274 } 275 if (offset) { 276 wbfl(); 277 offset = savoff; 278 wbt((tchar)0); 279 } 280 copyf--; 281 return(req); 282 } 283 284 285 copys() 286 { 287 tchar i; 288 289 copyf++; 290 if (skip()) 291 goto c0; 292 if (cbits(i = getch()) != '"') 293 wbf(i); 294 while (cbits(i = getch()) != '\n') 295 wbf(i); 296 c0: 297 wbt((tchar)0); 298 copyf--; 299 } 300 301 302 filep alloc() 303 { 304 register i; 305 filep j; 306 307 for (i = 0; i < NBLIST; i++) { 308 if (blist[i] == 0) 309 break; 310 } 311 if (i == NBLIST) { 312 j = 0; 313 } else { 314 blist[i] = -1; 315 if ((j = ((filep)i * BLK + NEV * EVS)) < NEV * EVS) 316 j = 0; 317 } 318 return(nextb = j); 319 } 320 321 322 ffree(i) 323 filep i; 324 { 325 register j; 326 327 while ((blist[j = blisti(i)]) != -1) { 328 i = ((filep)blist[j]); 329 blist[j] = 0; 330 } 331 blist[j] = 0; 332 } 333 334 335 wbt(i) 336 tchar i; 337 { 338 wbf(i); 339 wbfl(); 340 } 341 342 343 wbf(i) 344 tchar i; 345 { 346 register j; 347 348 if (!offset) 349 return; 350 if (!woff) { 351 woff = offset; 352 #ifdef INCORE 353 wbuf = &corebuf[woff]; /* INCORE only */ 354 #endif 355 wbfi = 0; 356 } 357 wbuf[wbfi++] = i; 358 if (!((++offset) & (BLK - 1))) { 359 wbfl(); 360 if (blist[j = blisti(--offset)] == -1) { 361 if (alloc() == 0) { 362 fprintf(stderr, "troff: Out of temp file space at %d.\n", v.cd); 363 done2(01); 364 } 365 blist[j] = (unsigned)(nextb); 366 } 367 offset = ((filep)blist[j]); 368 } 369 if (wbfi >= BLK) 370 wbfl(); 371 } 372 373 374 wbfl() 375 { 376 if (woff == 0) 377 return; 378 #ifndef INCORE 379 lseek(ibf, ((long)woff) * sizeof(tchar), 0); 380 write(ibf, (char *)wbuf, wbfi * sizeof(tchar)); 381 #endif 382 if ((woff & (~(BLK - 1))) == (roff & (~(BLK - 1)))) 383 roff = -1; 384 woff = 0; 385 } 386 387 388 tchar rbf() 389 { 390 tchar i; 391 register filep j, p; 392 extern filep incoff(); 393 394 /* this is an inline expansion of rbf0: dirty! */ 395 if ((j = ip & ~(BLK - 1)) != roff) { 396 roff = j; 397 #ifndef INCORE 398 lseek(ibf, (long)roff * sizeof(tchar), 0); 399 if (read(ibf, (char *)rbuf, BLK * sizeof(tchar)) == 0) 400 i = 0; 401 else 402 i = rbuf[ip & (BLK-1)]; 403 #else 404 rbuf = &corebuf[roff]; 405 i = rbuf[ip & (BLK-1)]; 406 #endif 407 } else 408 i = rbuf[ip & (BLK-1)]; 409 /* end of rbf0 */ 410 if (i == 0) { 411 if (!app) 412 i = popi(); 413 } else { 414 /* this is an inline expansion of incoff: also dirty */ 415 int i; 416 p = ip; 417 if (!((j = ++p) & (BLK - 1))) { 418 if ((i = blist[blisti(--p)]) == -1) { 419 fprintf(stderr, "troff: Bad storage allocation.\n"); 420 done2(-5); 421 } 422 j = ((filep)i); 423 } 424 ip = j; 425 } 426 return(i); 427 } 428 429 430 tchar rbf0(p) 431 register filep p; 432 { 433 register filep i; 434 435 if ((i = p & ~(BLK - 1)) != roff) { 436 roff = i; 437 #ifndef INCORE 438 lseek(ibf, (long)roff * sizeof(tchar), 0); 439 if (read(ibf, (char *)rbuf, BLK * sizeof(tchar)) == 0) 440 return(0); 441 #else 442 rbuf = &corebuf[roff]; 443 #endif 444 } 445 return(rbuf[p & (BLK-1)]); 446 } 447 448 449 filep incoff(p) 450 register filep p; 451 { 452 register i; 453 register filep j; 454 455 if (!((j = ++p) & (BLK - 1))) { 456 if ((i = blist[blisti(--p)]) == -1) { 457 fprintf(stderr, "troff: Bad storage allocation.\n"); 458 done2(-5); 459 } 460 j = (filep) i; 461 } 462 return(j); 463 } 464 465 466 tchar popi() 467 { 468 register struct s *p; 469 470 if (frame == stk) 471 return(0); 472 if (strflg) 473 strflg--; 474 p = nxf = frame; 475 p->nargs = 0; 476 frame = p->pframe; 477 ip = p->pip; 478 nchar = p->pnchar; 479 rchar = p->prchar; 480 pendt = p->ppendt; 481 ap = p->pap; 482 cp = p->pcp; 483 ch0 = p->pch0; 484 return(p->pch); 485 } 486 487 /* 488 * test that the end of the allocation is above a certain location 489 * in memory 490 */ 491 #define SPACETEST(base, size) while ((enda - (size)) <= (char *)(base)){setbrk(DELTA);} 492 493 pushi(newip) 494 filep newip; 495 { 496 register struct s *p; 497 extern char *setbrk(); 498 499 SPACETEST(nxf, sizeof(struct s)); 500 p = nxf; 501 p->pframe = frame; 502 p->pip = ip; 503 p->pnchar = nchar; 504 p->prchar = rchar; 505 p->ppendt = pendt; 506 p->pap = ap; 507 p->pcp = cp; 508 p->pch0 = ch0; 509 p->pch = ch; 510 cp = ap = 0; 511 nchar = rchar = pendt = ch0 = ch = 0; 512 frame = nxf; 513 if (nxf->nargs == 0) 514 nxf += 1; 515 else 516 nxf = (struct s *)argtop; 517 return(ip = newip); 518 } 519 520 521 char *setbrk(x) 522 int x; 523 { 524 register char *i; 525 char *sbrk(); 526 527 if (x % 2 == 1) 528 x++; 529 if ((i = sbrk(x)) == MAXPTR) { 530 fprintf(stderr, "troff: Core limit reached.\n"); 531 edone(0100); 532 } else { 533 enda = i + x; 534 } 535 return(i); 536 } 537 538 539 getsn() 540 { 541 register i; 542 543 if ((i = getach()) == 0) 544 return(0); 545 if (i == '(') 546 return(getrq()); 547 else 548 return(i); 549 } 550 551 552 setstr() 553 { 554 register i; 555 556 lgf++; 557 if (((i = getsn()) == 0) || ((i = findmn(i)) == -1) || !(contab[i].rq & MMASK)) { 558 lgf--; 559 return(0); 560 } else { 561 SPACETEST(nxf, sizeof(struct s)); 562 nxf->nargs = 0; 563 strflg++; 564 lgf--; 565 return(pushi(((filep)contab[i].x.mx))); 566 } 567 } 568 569 570 571 collect() 572 { 573 register j; 574 tchar i; 575 register tchar *strp; 576 tchar * lim; 577 tchar * *argpp, **argppend; 578 int quote; 579 struct s *savnxf; 580 581 copyf++; 582 nxf->nargs = 0; 583 savnxf = nxf; 584 if (skip()) 585 goto rtn; 586 587 { 588 char *memp; 589 memp = (char *)savnxf; 590 /* 591 * 1 s structure for the macro descriptor 592 * APERMAC tchar *'s for pointers into the strings 593 * space for the tchar's themselves 594 */ 595 memp += sizeof(struct s); 596 /* 597 * CPERMAC (the total # of characters for ALL arguments) 598 * to a macros, has been carefully chosen 599 * so that the distance between stack frames is < DELTA 600 */ 601 #define CPERMAC 200 602 #define APERMAC 9 603 memp += APERMAC * sizeof(tchar *); 604 memp += CPERMAC * sizeof(tchar); 605 nxf = (struct s*)memp; 606 } 607 lim = (tchar *)nxf; 608 argpp = (tchar **)(savnxf + 1); 609 argppend = &argpp[APERMAC]; 610 SPACETEST(argppend, sizeof(tchar *)); 611 strp = (tchar *)argppend; 612 /* 613 * Zero out all the string pointers before filling them in. 614 */ 615 for (j = 0; j < APERMAC; j++){ 616 argpp[j] = (tchar *)0; 617 } 618 #if 0 619 fprintf(stderr, "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x,lim=0x%x,enda=0x%x\n", 620 savnxf, nxf, argpp, strp, lim, enda); 621 #endif 0 622 strflg = 0; 623 while ((argpp != argppend) && (!skip())) { 624 *argpp++ = strp; 625 quote = 0; 626 if (cbits(i = getch()) == '"') 627 quote++; 628 else 629 ch = i; 630 while (1) { 631 i = getch(); 632 if ( nlflg || (!quote && cbits(i) == ' ')) 633 break; 634 if ( quote 635 && (cbits(i) == '"') 636 && (cbits(i = getch()) != '"')) { 637 ch = i; 638 break; 639 } 640 *strp++ = i; 641 if (strflg && (strp >= lim)) { 642 #if 0 643 fprintf(stderr, "strp=0x%x, lim = 0x%x\n", 644 strp, lim); 645 #endif 0 646 fprintf(stderr, 647 "troff: Macro argument too long.\n"); 648 copyf--; 649 edone(004); 650 } 651 SPACETEST(strp, 3 * sizeof(tchar)); 652 } 653 *strp++ = 0; 654 } 655 nxf = savnxf; 656 nxf->nargs = argpp - (tchar **)(savnxf + 1); 657 argtop = strp; 658 rtn: 659 copyf--; 660 } 661 662 663 seta() 664 { 665 register i; 666 667 i = cbits(getch()) - '0'; 668 if ( (i > 0) 669 && (i <= APERMAC) 670 && (i <= frame->nargs)){ 671 ap = *(((tchar **)(frame + 1)) + i - 1); 672 } 673 } 674 675 676 caseda() 677 { 678 app++; 679 casedi(); 680 } 681 682 683 casedi() 684 { 685 register i, j; 686 register *k; 687 688 lgf++; 689 if (skip() || ((i = getrq()) == 0)) { 690 if (dip != d) 691 wbt((tchar)0); 692 if (dilev > 0) { 693 v.dn = dip->dnl; 694 v.dl = dip->maxl; 695 dip = &d[--dilev]; 696 offset = dip->op; 697 } 698 goto rtn; 699 } 700 if (++dilev == NDI) { 701 --dilev; 702 fprintf(stderr, "troff: Diversions nested too deep.\n"); 703 edone(02); 704 } 705 if (dip != d) 706 wbt((tchar)0); 707 diflg++; 708 dip = &d[dilev]; 709 dip->op = finds(i); 710 dip->curd = i; 711 clrmn(oldmn); 712 k = (int *) & dip->dnl; 713 for (j = 0; j < 10; j++) 714 k[j] = 0; /*not op and curd*/ 715 rtn: 716 app = 0; 717 diflg = 0; 718 } 719 720 721 casedt() 722 { 723 lgf++; 724 dip->dimac = dip->ditrap = dip->ditf = 0; 725 skip(); 726 dip->ditrap = vnumb((int *)0); 727 if (nonumb) 728 return; 729 skip(); 730 dip->dimac = getrq(); 731 } 732 733 734 casetl() 735 { 736 register j; 737 int w1, w2, w3; 738 tchar i, delim; 739 filep begin; 740 extern width(), pchar(); 741 742 dip->nls = 0; 743 skip(); 744 if (dip != d) 745 wbfl(); 746 if ((offset = begin = alloc()) == 0) 747 return; 748 if (ismot(delim = getch())) { 749 ch = delim; 750 delim = '\''; 751 } else 752 delim = cbits(delim); 753 if (!nlflg) 754 while (cbits(i = getch()) != '\n') { 755 if (cbits(i) == cbits(delim)) 756 i = IMP; 757 wbf(i); 758 } 759 wbf((tchar)IMP); 760 wbf((tchar)IMP); 761 wbt((tchar)0); 762 763 w1 = hseg(width, begin); 764 w2 = hseg(width, (filep)0); 765 w3 = hseg(width, (filep)0); 766 offset = dip->op; 767 #ifdef NROFF 768 if (!offset) 769 horiz(po); 770 #endif 771 hseg(pchar, begin); 772 if (w2 || w3) 773 horiz(j = quant((lt - w2) / 2 - w1, HOR)); 774 hseg(pchar, (filep)0); 775 if (w3) { 776 horiz(lt - w1 - w2 - w3 - j); 777 hseg(pchar, (filep)0); 778 } 779 newline(0); 780 if (dip != d) { 781 if (dip->dnl > dip->hnl) 782 dip->hnl = dip->dnl; 783 } else { 784 if (v.nl > dip->hnl) 785 dip->hnl = v.nl; 786 } 787 ffree(begin); 788 } 789 790 791 casepc() 792 { 793 pagech = chget(IMP); 794 } 795 796 797 hseg(f, p) 798 int (*f)(); 799 filep p; 800 { 801 register acc; 802 tchar i; 803 static filep q; 804 805 acc = 0; 806 if (p) 807 q = p; 808 while (1) { 809 i = rbf0(q); 810 q = incoff(q); 811 if (!i || i == IMP) 812 return(acc); 813 if (cbits(i) == pagech) { 814 nrbits = i & SFMASK; 815 nform = fmt[findr('%')]; 816 acc += fnumb(v.pn, f); 817 } else 818 acc += (*f)(i); 819 } 820 } 821 822 823 casepm() 824 { 825 register i, k; 826 register char *p; 827 int xx, cnt, tcnt, kk, tot; 828 filep j; 829 char pmline[10]; 830 831 kk = cnt = tcnt = 0; 832 tot = !skip(); 833 for (i = 0; i < NM; i++) { 834 if (contab[i].rq) 835 tcnt++; 836 if (!((xx = contab[i].rq) & MMASK)) 837 continue; 838 p = pmline; 839 j = (filep) contab[i].x.mx; 840 k = 1; 841 while ((j = blist[blisti(j)]) != -1) { 842 k++; 843 } 844 cnt++; 845 kk += k; 846 if (!tot) { 847 *p++ = xx & 0177; 848 if (!(*p++ = (xx >> BYTE) & 0177)) 849 *(p - 1) = ' '; 850 *p++ = 0; 851 fprintf(stderr, "%s %d\n", pmline, k); 852 } 853 } 854 fprintf(stderr, "pm: total %d, macros %d, space %d\n", tcnt, cnt, kk); 855 } 856 857 858 dummy() 859 { 860 } 861