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)
main(argc,argv)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
ofile()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;
getch()308 getch() {
309 register c;
310 if(peekc) {
311 c = peekc;
312 peekc = 0;
313 return(c);
314 }
315 return(getc(in));
316 }
317
error(s)318 error(s)
319 char *s;
320 {
321
322 fflush(out);
323 fprintf(stderr, "vsort: %s\n", s);
324 }
325
crail(nrail)326 crail(nrail)
327 register int nrail;
328 {
329 register int psize;
330
331 psize = cpsize;
332 loadfont(nrail, psize);
333 }
334
loadfont(fnum,size)335 loadfont(fnum, size)
336 register int fnum;
337 register int size;
338 {
339
340 cpsize = size;
341 return(0);
342 }
343
startline()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
termline()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
sortin(linep)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
stuffc(code)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
allflush()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
linesflush()456 linesflush()
457 {
458 while(head != NULL)
459 sendline();
460 }
461
sendline()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
cutmark(linep)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
ptrail(rlmg)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
ptback()568 ptback()
569 {
570
571 putc(oback ? 0107:0110, out);
572 oback = !oback;
573 }
574
ptsize(size)575 ptsize(size)
576 register int size;
577 {
578
579 putc(0120 | (size & 017), out);
580 ptesc(-stupidadj(size, opsize));
581 }
582
stupidadj(code,lcode)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
ptmcase()611 ptmcase()
612 {
613
614 putc(omcase ? 0105:0106, out);
615 }
616
ptesc(escc)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
ptlead(leadd)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
dumpline(linep)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