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.4 (Berkeley) 03/02/91"; 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 error(s) 319 char *s; 320 { 321 322 fflush(out); 323 fprintf(stderr, "vsort: %s\n", s); 324 } 325 326 crail(nrail) 327 register int nrail; 328 { 329 register int psize; 330 331 psize = cpsize; 332 loadfont(nrail, psize); 333 } 334 335 loadfont(fnum, size) 336 register int fnum; 337 register int size; 338 { 339 340 cpsize = size; 341 return(0); 342 } 343 344 startline() 345 { 346 347 if(pstart != 0) { 348 cline.row = row; 349 return; 350 } 351 cline.len = 0; 352 cline.row = row; 353 cline.start.col = col; 354 cline.start.psize = cpsize; 355 cline.start.mcase = mcase; 356 cline.start.back = back; 357 cline.start.verd = verd; 358 cline.start.railmag = railmag; 359 codep = tbuf; 360 } 361 362 termline() 363 { 364 register struct line *linep; 365 register char *allp; 366 register char *cp; 367 int i; 368 369 if(pstart != 0) 370 return; 371 if((allp = calloc(sizeof *linep,1)) == ((char *)-1)) 372 error("alloc"); 373 linep = (struct line *)allp; 374 linep->end.col = col; 375 linep->end.psize = cpsize; 376 linep->end.mcase = mcase; 377 linep->end.back = back; 378 linep->end.verd = verd; 379 linep->end.railmag = railmag; 380 linep->start.col = cline.start.col; 381 linep->start.psize = cline.start.psize; 382 linep->start.mcase = cline.start.mcase; 383 linep->start.back = cline.start.back; 384 linep->start.verd = cline.start.verd; 385 linep->start.railmag = cline.start.railmag; 386 linep->len = cline.len; 387 linep->row = row; 388 if((allp = calloc(cline.len,1)) == ((char *)-1)) 389 error("alloc"); 390 linep->codep = allp; 391 cp = tbuf; 392 for(i = 0; i < cline.len; i++) 393 *allp++ = *cp++; 394 sortin(linep); 395 } 396 397 sortin(linep) 398 register struct line *linep; 399 { 400 register struct line *clp; 401 402 if((clp = tail) == NULL) { 403 head = tail = linep; 404 linep->lastp = linep->nextp = NULL; 405 return; 406 } 407 while(clp != NULL && clp->row > linep->row) 408 clp = clp->lastp; 409 if(clp == tail) { 410 linep->lastp = tail; 411 linep->nextp = NULL; 412 tail->nextp = linep; 413 tail = linep; 414 } else 415 if(clp == NULL) /* goes at head of list */ { 416 linep->lastp = NULL; 417 linep->nextp = head; 418 head->lastp = linep; 419 head = linep; 420 } else { 421 linep->lastp = clp; 422 linep->nextp = clp->nextp; 423 clp->nextp->lastp = linep; 424 clp->nextp = linep; 425 } 426 } 427 428 stuffc(code) 429 register int code; 430 { 431 432 if(pstart != 0) { 433 pstart = 0; 434 startline(); 435 } 436 if(cline.len > TBUFLEN) { 437 termline(); 438 startline(); 439 } 440 *codep++ = code; 441 cline.len++; 442 } 443 444 445 allflush() /* Flush all lines, then put out trailing leading. */ 446 { 447 448 linesflush(); 449 if (row > orow) { 450 ptlead(row - orow); 451 } 452 row -= pagelength; 453 orow = row; 454 } 455 456 linesflush() 457 { 458 while(head != NULL) 459 sendline(); 460 } 461 462 sendline() 463 { 464 register char *cp; 465 register struct line *linep; 466 register int i; 467 register int remcutmark; 468 469 if ((linep = head) == NULL) 470 return; 471 472 /* Heuristic: if cut marks are present, they are on lines whose 473 * row numbers are <= 24 or >= pagelength-4. 474 * Cut marks are formed from 023's, 040's, or 061's. 475 * There are 2 or 4 of them on a line, and no other characters 476 * are present. cutmark(...) checks this. 477 * Cutmark lines are removed if nocutmarks is true. 478 * Three leading units are removed, too, to compensate for 479 * varian output not being exactly 1584 leading units long. 480 */ 481 #ifdef DUMPLINE 482 dumpline(linep); 483 #endif 484 remcutmark = 0; 485 if (nocutmarks 486 && (linep->row <= 24 || linep->row >= pagelength-4) 487 && cutmark(linep)) { 488 remcutmark++; 489 orow = orow + 3; 490 } 491 if(linep->start.railmag != orailmag) 492 ptrail(linep->start.railmag); 493 if(linep->start.psize != opsize) 494 ptsize(linep->start.psize); 495 if(linep->start.mcase != omcase) 496 ptmcase(); 497 if(linep->row > orow) /* lead forward */ 498 ptlead(linep->row - orow); 499 if(linep->start.col != ocol) 500 ptesc(linep->start.col-ocol); 501 if(linep->start.back != oback) 502 ptback(); 503 cp = linep->codep; 504 if (remcutmark) { 505 for(i = 0; i < linep->len; i++) { 506 if (!iscutmark(*cp)) /* iscutmark is a macro. */ 507 putc(*cp++, out); 508 else 509 cp++; 510 } 511 } else { 512 for(i = 0; i < linep->len; i++) 513 putc(*cp++, out); 514 } 515 516 orow = linep->row; 517 orailmag = linep->end.railmag; 518 opsize = linep->end.psize; 519 omcase = linep->end.mcase; 520 ocol = linep->end.col; 521 oback = linep->end.back; 522 head = linep->nextp; 523 524 cfree(linep->codep); 525 cfree(linep); 526 if(head == NULL) 527 tail = NULL; 528 else 529 head->lastp = NULL; 530 } 531 532 int 533 cutmark(linep) 534 register struct line *linep; 535 { 536 register int i; 537 register int ch; 538 register int dashcount = 0; 539 register int firstdash = 0; 540 541 for (i = 0; i < linep->len; i++) { 542 ch = linep->codep[i] & 0377; 543 if (ch < 0100) { 544 if (iscutmark(ch)) { 545 if (firstdash == 0) 546 firstdash = ch; 547 if (ch != firstdash) 548 return (0); 549 dashcount++; 550 } else 551 return(0); 552 } 553 } 554 /* Must have 2 or 4 dashes on a line. */ 555 return (dashcount == 4 || dashcount == 2); 556 } 557 558 ptrail(rlmg) 559 register int rlmg; 560 { 561 562 if((rlmg & 01) != (orailmag & 01)) 563 putc((rlmg & 01) ? 0102:0101, out); /* rail */ 564 if((rlmg & 02) != (orailmag & 02)) 565 putc((rlmg & 02) ? 0103:0104, out); /* mag */ 566 } 567 568 ptback() 569 { 570 571 putc(oback ? 0107:0110, out); 572 oback = !oback; 573 } 574 575 ptsize(size) 576 register int size; 577 { 578 579 putc(0120 | (size & 017), out); 580 ptesc(-stupidadj(size, opsize)); 581 } 582 583 stupidadj(code, lcode) 584 register int code; 585 int lcode; 586 { 587 register struct point_sizes *psp; 588 register struct point_sizes *lpsp; 589 590 psp = point_sizes; 591 while(psp->real_code != 0) { 592 if((psp->stupid_code & 017) == code) 593 break; 594 psp++; 595 } 596 lpsp = point_sizes; 597 while(lpsp->real_code != 0) { 598 if((lpsp->stupid_code & 017) == lcode) 599 break; 600 lpsp++; 601 } 602 code = 0; 603 if(!(lpsp->stupid_code & 0200) && (psp->stupid_code & 0200)) 604 code = -55; 605 else 606 if((lpsp->stupid_code & 0200) && !(psp->stupid_code & 0200)) 607 code = 55; 608 return(code); 609 } 610 611 ptmcase() 612 { 613 614 putc(omcase ? 0105:0106, out); 615 } 616 617 ptesc(escc) 618 register int escc; 619 { 620 621 if((escc < 0 && !oback ) || (escc >= 0 && oback)) 622 ptback(); 623 escc = abs(escc); 624 while(escc > 0177) { 625 putc(0200, out); 626 escc -= 0177; 627 } 628 if(escc) 629 putc(0200 | ((~escc) & 0177), out); 630 } 631 632 ptlead(leadd) 633 register int leadd; 634 { 635 636 while(leadd > 037) { 637 putc(0140, out); 638 leadd -= 037; 639 } 640 if(leadd) 641 putc(0140 | ((~leadd) & 037), out); 642 } 643 644 #ifdef DUMPLINE 645 dumpline(linep) 646 register struct line *linep; 647 { 648 int i; 649 650 fprintf(stderr, "row: %d\n", linep->row); 651 fprintf(stderr, "start.col: %o ", linep->start.col & 0377); 652 fprintf(stderr, ".psize: %o ", linep->start.psize); 653 fprintf(stderr, ".railmag: %o ", linep->start.railmag); 654 fprintf(stderr, ".verd: %o ", linep->start.verd); 655 fprintf(stderr, ".back: %o ", linep->start.back); 656 fprintf(stderr, ".mcase: %o\n", linep->start.mcase); 657 fprintf(stderr, " end.col: %o ", linep->end.col); 658 fprintf(stderr, ".psize: %o ", linep->end.psize); 659 fprintf(stderr, ".railmag: %o ", linep->end.railmag); 660 fprintf(stderr, ".verd: %o ", linep->end.verd); 661 fprintf(stderr, ".back: %o ", linep->end.back); 662 fprintf(stderr, ".mcase: %o\n", linep->end.mcase); 663 fprintf(stderr, "len: %d\t", linep->len); 664 fprintf(stderr, "codep: "); 665 for (i = 0; i < linep->len; i++) 666 fprintf(stderr, "%o ", linep->codep[i] & 0377); 667 fprintf(stderr, "\n\n"); 668 } 669 #endif 670