1 static char *sccsid = "@(#)tc.c 4.3 (Berkeley) 05/11/89"; 2 /* 3 * Simulate typesetter on 4014 4 */ 5 6 #include <sys/signal.h> 7 #include <paths.h> 8 #include <stdio.h> 9 10 #define oput(c) if (pgskip==0) putchar(c); else (c); 11 #define MAXY 3071 12 #define US 037 13 #define GS 035 14 #define ESC 033 15 #define FF 014 16 #define DBL 0200 17 18 int pl = 11*144; 19 int mpy = 1; 20 int div = 1; 21 char *ap; 22 int ch; 23 int nonumb; 24 int psize = 10; 25 int dfact = 1; 26 int esc; 27 int escd; 28 int verd; 29 int esct; 30 int osize = 02; 31 int size = 02; 32 int rx; 33 int xx; 34 int yy = MAXY+62+48; 35 int leadtot = -31; 36 int ohy = -1; 37 int ohx = -1; 38 int oxb = -1; 39 int oly = -1; 40 int olx = -1; 41 int tflag; 42 int railmag; 43 int lead; 44 int skip; 45 int pgskip; 46 int ksize = ';'; 47 int mcase; 48 int stab[] = {010,0,01,07,02,03,04,05,0211,06,0212,0213,0214,0215,0216,0217}; 49 int rtab[] = {6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 28, 36, 18}; 50 int ktab[] = {';',';',';',';',';',';',':',':','9','9','9','9','8','8','8','9'}; 51 int first = 1; 52 int alpha; 53 extern char *asctab[128]; 54 extern char *spectab[128]; 55 int erase = 1; 56 int (*sigint)(); 57 int (*sigquit)(); 58 59 main(argc,argv) 60 int argc; 61 char **argv; 62 { 63 register i, j; 64 register char *k; 65 extern ex(); 66 67 while((--argc > 0) && ((++argv)[0][0]=='-')){ 68 switch(argv[0][1]){ 69 case 'p': 70 ap = &argv[0][2]; 71 dfact = 72; 72 if(i = atoi())pl = i/3; 73 continue; 74 case 't': 75 tflag++; 76 continue; 77 case 's': 78 ap = &argv[0][2]; 79 dfact = 1; 80 pgskip = atoi(); 81 continue; 82 default: 83 dfact = 1; 84 ap = &argv[0][1]; 85 if(i = atoi())mpy = i; 86 if(i = atoi())div = i; 87 continue; 88 } 89 } 90 if(argc){ 91 if (freopen(argv[0], "r", stdin) == NULL) { 92 fprintf(stderr, "tc: cannot open %s\n", argv[0]); 93 exit(1); 94 } 95 } 96 sigint = signal(SIGINT, ex); 97 sigquit = signal(SIGQUIT, SIG_IGN); 98 while((i = getchar()) != EOF){ 99 if(!i)continue; 100 if(i & 0200){ 101 esc += (~i) & 0177; 102 continue; 103 } 104 if(esc){ 105 if(escd)esc = -esc; 106 esct += esc; 107 xx += (esc*mpy + rx)/div; 108 rx = (esc*mpy + rx)%div; 109 sendpt(); 110 esc = 0; 111 } 112 switch(i){ 113 case 0100: /*init*/ 114 escd = verd = mcase = railmag = xx = 0; 115 yy = MAXY + 48; 116 leadtot = -31; 117 ohy = oxb = oly = ohx = olx = -1; 118 oput(US); 119 fflush(stdout); 120 if(!first && !tflag)kwait(); 121 if(first){ 122 first = 0; 123 yy += 62; 124 } 125 init(); 126 continue; 127 case 0101: /*lower rail*/ 128 railmag &= ~01; 129 continue; 130 case 0102: /*upper rail*/ 131 railmag |= 01; 132 continue; 133 case 0103: /*upper mag*/ 134 railmag |= 02; 135 continue; 136 case 0104: /*lower mag*/ 137 railmag &= ~02; 138 continue; 139 case 0105: /*lower case*/ 140 mcase = 0; 141 continue; 142 case 0106: /*upper case*/ 143 mcase = 0100; 144 continue; 145 case 0107: /*escape forward*/ 146 escd = 0; 147 continue; 148 case 0110: /*escape backward*/ 149 escd = 1; 150 continue; 151 case 0111: /*stop*/ 152 continue; 153 case 0112: /*lead forward*/ 154 verd = 0; 155 continue; 156 case 0113: /*undefined*/ 157 continue; 158 case 0114: /*lead backward*/ 159 verd = 1; 160 continue; 161 case 0115: /*undefined*/ 162 case 0116: 163 case 0117: 164 continue; 165 } 166 if((i & 0340) == 0140){ /*leading*/ 167 lead = (~i) & 037; 168 if(verd)lead = -lead; 169 if((leadtot += lead) > pl){ 170 leadtot = lead; 171 oput(US); 172 fflush(stdout); 173 if(!tflag)kwait(); 174 yy = MAXY; 175 if(pgskip)--pgskip; 176 init(); 177 continue; 178 } 179 if(skip)continue; 180 if((yy -= (lead<<1)) < 0){ 181 skip++; 182 yy = 0; 183 }else sendpt(); 184 continue; 185 } 186 if((i & 0360) == 0120){ /*size change*/ 187 i &= 017; 188 for(j = 0; i != (stab[j] & 017); j++); 189 osize = size; 190 size = stab[j]; 191 psize = rtab[j]; 192 ksize = ktab[j]; 193 oput(ESC); 194 oput(ksize); 195 i = 0; 196 if(!(osize & DBL) && (size & DBL))i = -55; 197 else if((osize & DBL) && !(size & DBL))i = 55; 198 if(escd)i = -i; 199 esc += i; 200 continue; 201 } 202 if(i & 0300)continue; 203 i = (i & 077) | mcase; 204 if(railmag != 03)k = asctab[i]; 205 else k = spectab[i]; 206 if(alpha)sendpt(); 207 if(*k!='\0'){ 208 oput(US); 209 while(*k & 0377)oput(*k++); 210 alpha++; 211 continue; 212 }else{ 213 if(railmag != 03){ 214 switch(i){ 215 case 0124: lig("fi"); break; 216 case 0125: lig("fl"); break; 217 case 0126: lig("ff"); break; 218 case 0130: lig("ffl"); break; 219 case 0131: lig("ffi"); break; 220 default: continue; 221 } 222 } 223 continue; 224 } 225 } 226 ex(); 227 } 228 lig(x) 229 char *x; 230 { 231 register i, j; 232 register char *k; 233 234 j = 0; 235 k = x; 236 oput(US); 237 oput(*k++); 238 i = psize * 8 * mpy / (div * 6); /* 8/36 em */ 239 while(*k){ 240 xx += i; 241 j += i; 242 sendpt(); 243 oput(US); 244 oput(*k++); 245 } 246 xx -= j; 247 sendpt(); 248 } 249 init(){ 250 251 fflush(stdout); 252 if(erase){ 253 oput(ESC); 254 oput(FF); 255 }else erase = 1; 256 oput(ESC); 257 oput(ksize); 258 /*delay about a second*/ 259 /* let the system do it... 260 for(i = 960; i > 0; i--)oput(GS); 261 */ 262 skip = 0; 263 sendpt(); 264 } 265 ex(){ 266 yy = MAXY; 267 xx = 0; 268 sendpt(); 269 oput(ESC); 270 oput(';'); 271 oput(US); 272 fflush(stdout); 273 exit(0); 274 } 275 kwait(){ 276 char buf[128]; char *bptr; char c; 277 if(pgskip) return; 278 next: 279 bptr=buf; 280 while((c=readch())&&(c!='\n')) *bptr++=c; 281 *bptr=0; 282 if(bptr!=buf){ 283 bptr = buf; 284 if(*bptr == '!'){callunix(&buf[1]); fputs("!\n", stderr); goto next;} 285 else switch(*bptr++){ 286 case 'e': 287 erase = 0; 288 goto next; 289 case 's': 290 ap = &buf[1]; 291 dfact = 1; 292 pgskip = atoi() + 1; 293 goto next; 294 default: 295 fputs("?\n", stderr); 296 goto next; 297 } 298 } 299 else if (c==0) ex(); 300 else return; 301 } 302 callunix(line) 303 char line[]; 304 { 305 int rc, status, unixpid; 306 if( (unixpid=fork())==0 ) { 307 signal(SIGINT,sigint); signal(SIGQUIT,sigquit); 308 close(0); dup(2); 309 execl(_PATH_BSHELL, "-sh", "-c", line, 0); 310 exit(255); 311 } 312 else if(unixpid == -1) 313 return; 314 else{ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); 315 while( (rc = wait(&status)) != unixpid && rc != -1 ) ; 316 signal(SIGINT,ex); signal(SIGQUIT,sigquit); 317 } 318 } 319 readch(){ 320 char c; 321 if (read(2,&c,1)<1) c=0; 322 return(c); 323 } 324 sendpt(){ 325 int hy,xb,ly,hx,lx; 326 327 oput(GS); 328 hy = ((yy>>7) & 037); 329 xb = ((xx & 03) + ((yy<<2) & 014) & 017); 330 ly = ((yy>>2) & 037); 331 hx = ((xx>>7) & 037); 332 lx = ((xx>>2) & 037); 333 if(hy != ohy)oput(hy | 040); 334 if(xb != oxb)oput(xb | 0140); 335 if((ly != oly) || (hx != ohx) || (xb != oxb)) 336 oput(ly | 0140); 337 if(hx != ohx)oput(hx | 040); 338 oput(lx | 0100); 339 ohy = hy; 340 oxb = xb; 341 oly = ly; 342 ohx = hx; 343 olx = lx; 344 alpha = 0; 345 return; 346 } 347 atoi() 348 { 349 register i, j, acc; 350 int field, digits; 351 long dd; 352 long tscale(); 353 354 field = digits = acc = 0; 355 a1: 356 while(((j = (i = getch()) - '0') >= 0) && (j <= 9)){ 357 field++; 358 digits++; 359 acc = 10*acc + j; 360 } 361 if(i == '.'){ 362 field++; 363 digits = 0; 364 goto a1; 365 } 366 if(!(ch = i))ch = 'x'; 367 dd = tscale(acc); 368 acc = dd; 369 if((field != digits) && (digits > 0)){ 370 j = 1; 371 while(digits--)j *= 10; 372 acc = dd/j; 373 } 374 nonumb = !field; 375 ch = 0; 376 return(acc); 377 } 378 long tscale(n) 379 int n; 380 { 381 register i, j; 382 383 switch(i = getch()){ 384 case 'u': 385 j = 1; 386 break; 387 case 'p': /*Points*/ 388 j = 6; 389 break; 390 case 'i': /*Inches*/ 391 j = 432; 392 break; 393 case 'c': /*Centimeters; should be 170.0787*/ 394 j = 170; 395 break; 396 case 'P': /*Picas*/ 397 j = 72; 398 break; 399 default: 400 j = dfact; 401 ch = i; 402 } 403 return((long)n*j); 404 } 405 getch(){ 406 register i; 407 408 if(ch){ 409 i = ch; 410 ch = 0; 411 return(i); 412 } 413 return(*ap++); 414 } 415 416 char *asctab[128] = { 417 "\0", /*blank*/ 418 "h", /*h*/ 419 "t", /*t*/ 420 "n", /*n*/ 421 "m", /*m*/ 422 "l", /*l*/ 423 "i", /*i*/ 424 "z", /*z*/ 425 "s", /*s*/ 426 "d", /*d*/ 427 "b", /*b*/ 428 "x", /*x*/ 429 "f", /*f*/ 430 "j", /*j*/ 431 "u", /*u*/ 432 "k", /*k*/ 433 "\0", /*blank*/ 434 "p", /*p*/ 435 "-", /*_ 3/4 em dash*/ 436 ";", /*;*/ 437 "\0", /*blank*/ 438 "a", /*a*/ 439 "_", /*rule*/ 440 "c", /*c*/ 441 "`", /*` open*/ 442 "e", /*e*/ 443 "\'", /*' close*/ 444 "o", /*o*/ 445 "\0", /*1/4*/ 446 "r", /*r*/ 447 "\0", /*1/2*/ 448 "v", /*v*/ 449 "-", /*- hyphen*/ 450 "w", /*w*/ 451 "q", /*q*/ 452 "/", /*/*/ 453 ".", /*.*/ 454 "g", /*g*/ 455 "\0", /*3/4*/ 456 ",", /*,*/ 457 "&", /*&*/ 458 "y", /*y*/ 459 "\0", /*blank*/ 460 "%", /*%*/ 461 "\0", /*blank*/ 462 "Q", /*Q*/ 463 "T", /*T*/ 464 "O", /*O*/ 465 "H", /*H*/ 466 "N", /*N*/ 467 "M", /*M*/ 468 "L", /*L*/ 469 "R", /*R*/ 470 "G", /*G*/ 471 "I", /*I*/ 472 "P", /*P*/ 473 "C", /*C*/ 474 "V", /*V*/ 475 "E", /*E*/ 476 "Z", /*Z*/ 477 "D", /*D*/ 478 "B", /*B*/ 479 "S", /*S*/ 480 "Y", /*Y*/ 481 "\0", /*blank*/ 482 "F", /*F*/ 483 "X", /*X*/ 484 "A", /*A*/ 485 "W", /*W*/ 486 "J", /*J*/ 487 "U", /*U*/ 488 "K", /*K*/ 489 "0", /*0*/ 490 "1", /*1*/ 491 "2", /*2*/ 492 "3", /*3*/ 493 "4", /*4*/ 494 "5", /*5*/ 495 "6", /*6*/ 496 "7", /*7*/ 497 "8", /*8*/ 498 "9", /*9*/ 499 "*", /***/ 500 "-", /*minus*/ 501 "", /*fi*/ 502 "", /*fl*/ 503 "", /*ff*/ 504 "\033\016Z\bM\033\017", /*cent sign*/ 505 "", /*ffl*/ 506 "", /*ffi*/ 507 "(", /*(*/ 508 ")", /*)*/ 509 "[", /*[*/ 510 "]", /*]*/ 511 "\033\016J\033\017", /*degree*/ 512 "\033\016M\b_\033\017", /*dagger*/ 513 "=", /*=*/ 514 "\033\016O\b&\033\017", /*registered*/ 515 ":", /*:*/ 516 "+", /*+*/ 517 "\0", /*blank*/ 518 "!", /*!*/ 519 "\033\016O\b~\033\017", /*bullet*/ 520 "?", /*?*/ 521 "\'", /*foot mark*/ 522 "|", /*|*/ 523 "\0", /*blank*/ 524 "\033\016O\b#\033\017", /*copyright*/ 525 "\033\016L\033\017", /*square*/ 526 "$" }; /*$*/ 527 528 char *spectab[128] = { 529 "\0", /*blank*/ 530 "\033\016(\bM\033\017", /*psi*/ 531 "\033\016o\b_\033\017", /*theta*/ 532 "v\b)", /*nu*/ 533 "\033\016V\b,\033\017", /*mu*/ 534 "\033\016)\b?\033\017", /*lambda*/ 535 "\033\016I\033\017", /*iota*/ 536 "S\b\033\016Z\033\017", /*zeta*/ 537 "o\b\'", /*sigma*/ 538 "o\b\033\0165\033\017", /*delta*/ 539 "\033\016b\033\017", /*beta*/ 540 "\033\016e\bc\033\017", /*xi*/ 541 "j\b\033\016C\033\017", /*eta*/ 542 "\033\016O\bM\033\017", /*phi*/ 543 "\033\016(\033\017", /*upsilon*/ 544 "\033\016k\033\017", /*kappa*/ 545 "\0", /*blank*/ 546 "T\b\033\016S\033\017", /*pi*/ 547 "@", /*at-sign*/ 548 "\033\016U\033\017", /*down arrow*/ 549 "\0", /*blank*/ 550 "\033\016A\033\017", /*alpha*/ 551 "|", /*or*/ 552 "l\b/", /*chi*/ 553 "\"", /*"*/ 554 "\033\016E\033\017", /*epsilon*/ 555 "=", /*=*/ 556 "\033\016O\033\017", /*omicron*/ 557 "\033\016[\033\017", /*left arrow*/ 558 "\033\016R\033\017", /*rho*/ 559 "\033\016Y\033\017", /*up arrow*/ 560 "\033\016N\033\017", /*tau*/ 561 "_", /*underrule*/ 562 "\\", /*\*/ 563 "I\b\033\016(\033\017", /*Psi*/ 564 "\033\016O\bJ\033\017", /*bell system sign*/ 565 "\033\016W\bX\033\017", /*infinity*/ 566 "`\b/", /*gamma*/ 567 "\033\016X\bF\033\017", /*improper superset*/ 568 "\033\016A\033\017", /*proportional to*/ 569 "\033\016\\\b]\033\017", /*right hand*/ 570 "\033\016W\033\017", /*omega*/ 571 "\0", /*blank*/ 572 "\033\016G\033\017", /*gradient*/ 573 "\0", /*blank*/ 574 "I\033\016\bO\033\017", /*Phi*/ 575 "O\b=", /*Theta*/ 576 "O\b_", /*Omega*/ 577 "\033\016V\033\017", /*cup (union)*/ 578 "\033\016@\033\017", /*root en*/ 579 "s", /*terminal sigma*/ 580 "\033\016)\bK\033\017", /*Lambda*/ 581 "-", /*minus*/ 582 "\033\016S\bK\033\017", /*Gamma*/ 583 "\033\016i\033\017", /*integral sign*/ 584 "\033\016t\b'\033\017", /*Pi*/ 585 "\033\016Z\033\017", /*subset of*/ 586 "\033\016X\033\017", /*superset of*/ 587 "\033\016T\033\017", /*approximates*/ 588 "o\b`", /*partial derivative*/ 589 "\033\016H\033\017", /*Delta*/ 590 "\033\016I\b'\033\017", /*square root*/ 591 ">\b\033\016F\b@\033\017", /*Sigma*/ 592 "\033\016T\bF\033\017", /*approx =*/ 593 "\0", /*blank*/ 594 ">", /*>*/ 595 "\033\016_\bF\b@\033\017", /*Xi*/ 596 "<", /*<*/ 597 "/", /*slash (longer)*/ 598 "\033\016C\033\017", /*cap (intersection)*/ 599 "\033\016y\033\017", /*Upsilon*/ 600 "\033\016|\033\017", /*not*/ 601 "|", /*right ceiling (rt of ")*/ 602 "|", /*left top (of big curly)*/ 603 "|", /*bold vertical*/ 604 "|", /*left center of big curly bracket*/ 605 "|", /*left bottom*/ 606 "|", /*right top*/ 607 "|", /*right center of big curly bracket*/ 608 "|", /*right bot*/ 609 "|", /*right floor (rb of ")*/ 610 "|", /*left floor (left bot of big sq bract)*/ 611 "|", /*left ceiling (lt of ")*/ 612 "\033\016=\033\017", /*multiply*/ 613 "\033\016+\033\017", /*divide*/ 614 "+\b_", /*plus-minus*/ 615 "\033\016$\033\017", /*<=*/ 616 "\033\016^\033\017", /*>=*/ 617 "=\b_", /*identically equal*/ 618 "\033\016*\033\017", /*not equal*/ 619 "{", /*{*/ 620 "}", /*}*/ 621 "\'", /*' acute accent*/ 622 "`", /*` grave accent*/ 623 "^", /*^*/ 624 "#", /*sharp*/ 625 "\033\016|\b[\033\017", /*left hand*/ 626 "\033\016c\b_\033\017", /*member of*/ 627 "~", /*~*/ 628 "\033\016O\b/\033\017", /*empty set*/ 629 "\0", /*blank*/ 630 "\033\016%\bM\033\017", /*dbl dagger*/ 631 "|", /*box rule*/ 632 "*", /*asterisk*/ 633 "\033\016Z\bF\033\017", /*improper subset*/ 634 "\033\016O\033\017", /*circle*/ 635 "\0", /*blank*/ 636 "+", /*eqn plus*/ 637 "\033\016]\033\017", /*right arrow*/ 638 "g\b\033\016C\033\017" }; /*section mark*/ 639