1 # include <stdio.h> 2 /* 3 * vsort - Sort troff output for versatec to reduce amount of reverse leading 4 */ 5 6 #define NULL 0 7 8 double atof(); 9 char *calloc(); 10 11 FILE *in,*out; 12 13 int skipfirst = 1; /* skip the first leading so start at top of page */ 14 int cpsize = 02; /* Funny sizes */ 15 struct point_sizes 16 { 17 int stupid_code; 18 int real_code; 19 } point_sizes[] = 20 { 21 010, 6, 22 0, 7, 23 01, 8, 24 07, 9, 25 02, 10, 26 03, 11, 27 04, 12, 28 05, 14, 29 0211, 16, 30 06, 18, 31 0212, 20, 32 0213, 22, 33 0214, 24, 34 0215, 28, 35 0216, 36, 36 0, 0 37 }; 38 39 int pagelength = 144 * 11; /* in Leading units */ 40 int pagemod; /* horizontal page number (for versatec) */ 41 #define MODOFF 3672 /* 432 * 8.5 */ 42 43 int esc, lead, back, verd, mcase, railmag; 44 int col, row; 45 int pstart = 0; /* Means a startline is pending */ 46 47 int oback, omcase, orailmag, ocol, orow; 48 int opsize = 02; 49 50 struct lstate 51 { 52 int col; 53 int psize; 54 char railmag; 55 char verd; 56 char back; 57 char mcase; 58 }; 59 60 struct line 61 { 62 struct line *nextp; 63 struct line *lastp; 64 int len; 65 int row; 66 struct lstate start; 67 struct lstate end; 68 char *codep; 69 }; 70 71 struct line *head; 72 struct line *tail; 73 struct line cline; 74 75 #define TBUFLEN 1024 76 char *codep; 77 char tbuf[TBUFLEN]; 78 79 char wide = 0; 80 char nocutmarks = 0; /* Remove lines that seem to be cut marks. */ 81 82 #define iscutmark(ch) (ch == 023 || ch == 040 || ch == 061) 83 main(argc, argv) 84 int argc; 85 char *argv[]; 86 { 87 register i; 88 89 for(i = 3; i < 15; i++) 90 close(i); 91 while (argc > 1 && argv[1][0] == '-') { 92 switch (argv[1][1]) { 93 case 'l': { 94 float f = 144 * atof(argv[1] + 2); 95 if (f < 144) { 96 error("bad length"); 97 exit(1); 98 } 99 pagelength = f; 100 break; 101 } 102 103 case 'W': 104 wide++; 105 break; 106 107 case 'c': 108 nocutmarks++; 109 break; 110 } 111 argc--; argv++; 112 } 113 out = stdout; 114 if(argc > 1) 115 { 116 while(--argc) 117 { 118 argv++; 119 if((in=fopen(argv[0], "r")) == NULL) 120 perror("vsort"); 121 else { 122 ofile(); 123 fclose(in); 124 } 125 } 126 } 127 else 128 { 129 in = stdin; 130 ofile(); 131 } 132 exit(0); 133 } 134 135 ofile() 136 { 137 register int c; 138 static int initialized; 139 140 while((c = getch()) != -1) { 141 if(!c) 142 continue; 143 if(c & 0200) /* escape (left/right) */ 144 { 145 if(!pstart) 146 stuffc(c); 147 esc += (~c) & 0177; 148 continue; 149 } 150 if(esc) 151 { 152 if(back) 153 esc = -esc; 154 col += esc; 155 esc = 0; 156 } 157 if((c & 0377) < 0100) /* Purely for efficiency */ 158 goto normal_char; 159 switch(c) { 160 case 0100: 161 if(initialized++) { 162 termline(); 163 linesflush(); /* Omit trailing leading. */ 164 return; 165 } 166 row = 0; 167 col = 0; esc = 0; 168 lead = 0; 169 verd = 0; back = 0; mcase = 0; 170 railmag = 0; 171 ocol = 0; 172 orow = 0; 173 oback = 0; omcase = 0; 174 orailmag = 0; 175 if(loadfont(railmag, cpsize) < 0) 176 error("init"); 177 startline(); 178 putc(0100, out); /* Dont stuff it guys */ 179 break; 180 case 0101: /* lower rail */ 181 crail(railmag &= ~01); 182 if(!pstart) 183 stuffc(c); 184 break; 185 case 0102: /* upper rail */ 186 crail(railmag |= 01); 187 if(!pstart) 188 stuffc(c); 189 break; 190 case 0103: /* upper mag */ 191 crail(railmag |= 02); 192 if(!pstart) 193 stuffc(c); 194 break; 195 case 0104: /* lower mag */ 196 crail(railmag &= ~02); 197 if(!pstart) 198 stuffc(c); 199 break; 200 case 0105: /* lower case */ 201 mcase = 0; 202 if(!pstart) 203 stuffc(c); 204 break; 205 case 0106: /* upper case */ 206 mcase = 1; 207 if(!pstart) 208 stuffc(c); 209 break; 210 case 0107: /* escape forward */ 211 back = 0; 212 if(!pstart) 213 stuffc(c); 214 break; 215 case 0110: /* escape backwards */ 216 back = 1; 217 if(!pstart) 218 stuffc(c); 219 break; 220 case 0111: /* stop */ 221 stuffc(c); 222 break; 223 case 0112: /* lead forward */ 224 verd = 0; 225 break; 226 case 0113: /* undefined */ 227 break; 228 case 0114: /* lead backward */ 229 verd = 1; 230 break; 231 case 0115: /* undefined */ 232 case 0116: 233 case 0117: 234 break; 235 default: 236 if((c & 0340) == 0140) /* leading */ 237 { 238 termline(); 239 lead = (~c) & 037; 240 if(verd) 241 lead = -lead; 242 if (skipfirst > 0) { 243 skipfirst--; 244 continue; 245 } 246 row += lead; 247 if (row >= pagelength) { 248 if (wide) { 249 if (pagemod == 3) { 250 allflush(); 251 col %= MODOFF; 252 pagemod = 0; 253 } else { 254 pagemod++; 255 col += MODOFF; 256 row -= pagelength; 257 } 258 } else { 259 allflush(); 260 } 261 } 262 if (wide && row < 0 && pagemod) { 263 pagemod--; 264 col -= MODOFF; 265 row += pagelength; 266 } 267 pstart++; 268 continue; 269 } 270 if((c & 0360) == 0120) /* size change */ 271 { 272 if(!pstart) 273 stuffc(c); 274 col += stupidadj(c & 017, cpsize); 275 loadfont(railmag, c & 017); 276 continue; 277 } 278 if(c & 0300) 279 continue; 280 normal_char: 281 c = (c & 077); 282 stuffc(c); 283 } 284 } /* End of while loop reading chars. */ 285 termline(); 286 linesflush(); /* don't put out trailing leading. */ 287 } 288 289 290 int peekc; 291 getch() { 292 register c; 293 if(peekc) { 294 c = peekc; 295 peekc = 0; 296 return(c); 297 } 298 return(getc(in)); 299 } 300 301 ungetc(c) { 302 peekc = c; 303 } 304 305 306 error(s) 307 char *s; 308 { 309 310 fflush(out); 311 fprintf(stderr, stderr, "vsort: %s\n", s); 312 } 313 314 crail(nrail) 315 register int nrail; 316 { 317 register int psize; 318 319 psize = cpsize; 320 loadfont(nrail, psize); 321 } 322 323 loadfont(fnum, size) 324 register int fnum; 325 register int size; 326 { 327 328 cpsize = size; 329 return(0); 330 } 331 332 startline() 333 { 334 335 if(pstart != 0) { 336 cline.row = row; 337 return; 338 } 339 cline.len = 0; 340 cline.row = row; 341 cline.start.col = col; 342 cline.start.psize = cpsize; 343 cline.start.mcase = mcase; 344 cline.start.back = back; 345 cline.start.verd = verd; 346 cline.start.railmag = railmag; 347 codep = tbuf; 348 } 349 350 termline() 351 { 352 register struct line *linep; 353 register char *allp; 354 register char *cp; 355 int i; 356 357 if(pstart != 0) 358 return; 359 if((allp = calloc(sizeof *linep,1)) == ((char *)-1)) 360 error("alloc"); 361 linep = (struct line *)allp; 362 linep->end.col = col; 363 linep->end.psize = cpsize; 364 linep->end.mcase = mcase; 365 linep->end.back = back; 366 linep->end.verd = verd; 367 linep->end.railmag = railmag; 368 linep->start.col = cline.start.col; 369 linep->start.psize = cline.start.psize; 370 linep->start.mcase = cline.start.mcase; 371 linep->start.back = cline.start.back; 372 linep->start.verd = cline.start.verd; 373 linep->start.railmag = cline.start.railmag; 374 linep->len = cline.len; 375 linep->row = row; 376 if((allp = calloc(cline.len,1)) == ((char *)-1)) 377 error("alloc"); 378 linep->codep = allp; 379 cp = tbuf; 380 for(i = 0; i < cline.len; i++) 381 *allp++ = *cp++; 382 sortin(linep); 383 } 384 385 sortin(linep) 386 register struct line *linep; 387 { 388 register struct line *clp; 389 390 if((clp = tail) == NULL) { 391 head = tail = linep; 392 linep->lastp = linep->nextp = NULL; 393 return; 394 } 395 while(clp != NULL && clp->row > linep->row) 396 clp = clp->lastp; 397 if(clp == tail) { 398 linep->lastp = tail; 399 linep->nextp = NULL; 400 tail->nextp = linep; 401 tail = linep; 402 } else 403 if(clp == NULL) /* goes at head of list */ { 404 linep->lastp = NULL; 405 linep->nextp = head; 406 head->lastp = linep; 407 head = linep; 408 } else { 409 linep->lastp = clp; 410 linep->nextp = clp->nextp; 411 clp->nextp->lastp = linep; 412 clp->nextp = linep; 413 } 414 } 415 416 stuffc(code) 417 register int code; 418 { 419 420 if(pstart != 0) { 421 pstart = 0; 422 startline(); 423 } 424 if(cline.len > TBUFLEN) { 425 termline(); 426 startline(); 427 } 428 *codep++ = code; 429 cline.len++; 430 } 431 432 433 allflush() /* Flush all lines, then put out trailing leading. */ 434 { 435 436 linesflush(); 437 if (row > orow) { 438 ptlead(row - orow); 439 } 440 row -= pagelength; 441 orow = row; 442 } 443 444 linesflush() 445 { 446 while(head != NULL) 447 sendline(); 448 } 449 450 sendline() 451 { 452 register char *cp; 453 register struct line *linep; 454 register int i; 455 register int remcutmark; 456 457 if ((linep = head) == NULL) 458 return; 459 460 /* Heuristic: if cut marks are present, they are on lines whose 461 * row numbers are <= 24 or >= pagelength-4. 462 * Cut marks are formed from 023's, 040's, or 061's. 463 * There are 2 or 4 of them on a line, and no other characters 464 * are present. cutmark(...) checks this. 465 * Cutmark lines are removed if nocutmarks is true. 466 * Three leading units are removed, too, to compensate for 467 * varian output not being exactly 1584 leading units long. 468 */ 469 #ifdef DUMPLINE 470 dumpline(linep); 471 #endif 472 remcutmark = 0; 473 if (nocutmarks 474 && (linep->row <= 24 || linep->row >= pagelength-4) 475 && cutmark(linep)) { 476 remcutmark++; 477 orow = orow + 3; 478 } 479 if(linep->start.railmag != orailmag) 480 ptrail(linep->start.railmag); 481 if(linep->start.psize != opsize) 482 ptsize(linep->start.psize); 483 if(linep->start.mcase != omcase) 484 ptmcase(); 485 if(linep->row > orow) /* lead forward */ 486 ptlead(linep->row - orow); 487 if(linep->start.col != ocol) 488 ptesc(linep->start.col-ocol); 489 if(linep->start.back != oback) 490 ptback(); 491 cp = linep->codep; 492 if (remcutmark) { 493 for(i = 0; i < linep->len; i++) { 494 if (!iscutmark(*cp)) /* iscutmark is a macro. */ 495 putc(*cp++, out); 496 else 497 cp++; 498 } 499 } else { 500 for(i = 0; i < linep->len; i++) 501 putc(*cp++, out); 502 } 503 504 orow = linep->row; 505 orailmag = linep->end.railmag; 506 opsize = linep->end.psize; 507 omcase = linep->end.mcase; 508 ocol = linep->end.col; 509 oback = linep->end.back; 510 head = linep->nextp; 511 512 cfree(linep->codep); 513 cfree(linep); 514 if(head == NULL) 515 tail = NULL; 516 else 517 head->lastp = NULL; 518 } 519 520 int 521 cutmark(linep) 522 register struct line *linep; 523 { 524 register int i; 525 register int ch; 526 register int dashcount = 0; 527 register int firstdash = 0; 528 529 for (i = 0; i < linep->len; i++) { 530 ch = linep->codep[i] & 0377; 531 if (ch < 0100) { 532 if (iscutmark(ch)) { 533 if (firstdash == 0) 534 firstdash = ch; 535 if (ch != firstdash) 536 return (0); 537 dashcount++; 538 } else 539 return(0); 540 } 541 } 542 /* Must have 2 or 4 dashes on a line. */ 543 return (dashcount == 4 || dashcount == 2); 544 } 545 546 ptrail(rlmg) 547 register int rlmg; 548 { 549 550 if((rlmg & 01) != (orailmag & 01)) 551 putc((rlmg & 01) ? 0102:0101, out); /* rail */ 552 if((rlmg & 02) != (orailmag & 02)) 553 putc((rlmg & 02) ? 0103:0104, out); /* mag */ 554 } 555 556 ptback() 557 { 558 559 putc(oback ? 0107:0110, out); 560 oback = !oback; 561 } 562 563 ptsize(size) 564 register int size; 565 { 566 567 putc(0120 | (size & 017), out); 568 ptesc(-stupidadj(size, opsize)); 569 } 570 571 stupidadj(code, lcode) 572 register int code; 573 int lcode; 574 { 575 register struct point_sizes *psp; 576 register struct point_sizes *lpsp; 577 578 psp = point_sizes; 579 while(psp->real_code != 0) { 580 if((psp->stupid_code & 017) == code) 581 break; 582 psp++; 583 } 584 lpsp = point_sizes; 585 while(lpsp->real_code != 0) { 586 if((lpsp->stupid_code & 017) == lcode) 587 break; 588 lpsp++; 589 } 590 code = 0; 591 if(!(lpsp->stupid_code & 0200) && (psp->stupid_code & 0200)) 592 code = -55; 593 else 594 if((lpsp->stupid_code & 0200) && !(psp->stupid_code & 0200)) 595 code = 55; 596 return(code); 597 } 598 599 ptmcase() 600 { 601 602 putc(omcase ? 0105:0106, out); 603 } 604 605 ptesc(escc) 606 register int escc; 607 { 608 609 if((escc < 0 && !oback ) || (escc >= 0 && oback)) 610 ptback(); 611 escc = abs(escc); 612 while(escc > 0177) { 613 putc(0200, out); 614 escc -= 0177; 615 } 616 if(escc) 617 putc(0200 | ((~escc) & 0177), out); 618 } 619 620 ptlead(leadd) 621 register int leadd; 622 { 623 624 while(leadd > 037) { 625 putc(0140, out); 626 leadd -= 037; 627 } 628 if(leadd) 629 putc(0140 | ((~leadd) & 037), out); 630 } 631 632 #ifdef DUMPLINE 633 dumpline(linep) 634 register struct line *linep; 635 { 636 int i; 637 638 fprintf(stderr, "row: %d\n", linep->row); 639 fprintf(stderr, "start.col: %o ", linep->start.col & 0377); 640 fprintf(stderr, ".psize: %o ", linep->start.psize); 641 fprintf(stderr, ".railmag: %o ", linep->start.railmag); 642 fprintf(stderr, ".verd: %o ", linep->start.verd); 643 fprintf(stderr, ".back: %o ", linep->start.back); 644 fprintf(stderr, ".mcase: %o\n", linep->start.mcase); 645 fprintf(stderr, " end.col: %o ", linep->end.col); 646 fprintf(stderr, ".psize: %o ", linep->end.psize); 647 fprintf(stderr, ".railmag: %o ", linep->end.railmag); 648 fprintf(stderr, ".verd: %o ", linep->end.verd); 649 fprintf(stderr, ".back: %o ", linep->end.back); 650 fprintf(stderr, ".mcase: %o\n", linep->end.mcase); 651 fprintf(stderr, "len: %d\t", linep->len); 652 fprintf(stderr, "codep: "); 653 for (i = 0; i < linep->len; i++) 654 fprintf(stderr, "%o ", linep->codep[i] & 0377); 655 fprintf(stderr, "\n\n"); 656 } 657 #endif 658