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