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