merged version from ralph; add copyright
[unix-history] / usr / src / old / vfilters / vsort / vsort.c
CommitLineData
56cd5299
BJ
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
8double atof();
9char *calloc();
10
11FILE *in,*out;
12
13int skipfirst = 1; /* skip the first leading so start at top of page */
14int cpsize = 02; /* Funny sizes */
15struct 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
39int pagelength = 144 * 11; /* in Leading units */
40int pagemod; /* horizontal page number (for versatec) */
41#define MODOFF 3672 /* 432 * 8.5 */
42
43int esc, lead, back, verd, mcase, railmag;
44int col, row;
45int pstart = 0; /* Means a startline is pending */
46
47int oback, omcase, orailmag, ocol, orow;
48int opsize = 02;
49
50struct lstate
51 {
52 int col;
53 int psize;
54 char railmag;
55 char verd;
56 char back;
57 char mcase;
58 };
59
60struct 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
71struct line *head;
72struct line *tail;
73struct line cline;
74
75#define TBUFLEN 1024
76char *codep;
77char tbuf[TBUFLEN];
78
79char wide = 0;
80char nocutmarks = 0; /* Remove lines that seem to be cut marks. */
81
82#define iscutmark(ch) (ch == 023 || ch == 040 || ch == 061)
83main(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
135ofile()
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
290int peekc;
291getch() {
292 register c;
293 if(peekc) {
294 c = peekc;
295 peekc = 0;
296 return(c);
297 }
298 return(getc(in));
299}
300
301ungetc(c) {
302 peekc = c;
303}
304
305
306error(s)
307 char *s;
308{
309
310 fflush(out);
311 fprintf(stderr, stderr, "vsort: %s\n", s);
312}
313
314crail(nrail)
315 register int nrail;
316{
317 register int psize;
318
319 psize = cpsize;
320 loadfont(nrail, psize);
321}
322
323loadfont(fnum, size)
324 register int fnum;
325 register int size;
326{
327
328 cpsize = size;
329 return(0);
330}
331
332startline()
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
350termline()
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
385sortin(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
416stuffc(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
433allflush() /* 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
444linesflush()
445{
446 while(head != NULL)
447 sendline();
448}
449
450sendline()
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
520int
521cutmark(linep)
522register 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
546ptrail(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
556ptback()
557{
558
559 putc(oback ? 0107:0110, out);
560 oback = !oback;
561}
562
563ptsize(size)
564 register int size;
565{
566
567 putc(0120 | (size & 017), out);
568 ptesc(-stupidadj(size, opsize));
569}
570
571stupidadj(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
599ptmcase()
600{
601
602 putc(omcase ? 0105:0106, out);
603}
604
605ptesc(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
620ptlead(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
633dumpline(linep)
634register 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