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