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