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