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