BSD 3 development
[unix-history] / usr / src / cmd / versatec / vsort.c
# include <stdio.h>
/*
* vsort - Sort troff output for versatec to reduce amount of reverse leading
*/
#define cycle for(;;)
#define NULL 0
#define INTR 2
#define QUIT 3
#define HUP 1
#define BROKENPIPE 13
double atof();
FILE *inbuf,*outbuf;
int skmagic = 1; /* skip the first leading so start at top of page */
int cpsize = 02; /* Funny sizes */
struct point_sizes
{
int stupid_code;
int real_code;
} point_sizes[]
{
010, 6,
0, 7,
01, 8,
07, 9,
02, 10,
03, 11,
04, 12,
05, 14,
0211, 16,
06, 18,
0212, 20,
0213, 22,
0214, 24,
0215, 28,
0216, 36,
0, 0
};
int overflow = 144 * 11;
int pagemod;
#define MODOFF 3672 /* 432 * 8.5 */
int esc, lead, back, verd, mcase, railmag;
int col, row;
int pstart 0; /* Means a startline is pending */
int oback, omcase, orailmag, ocol;
int opsize 02;
struct lstate
{
int row;
int col;
int psize;
char railmag;
char verd;
char back;
char mcase;
};
struct line
{
struct line *nextp;
struct line *lastp;
int len;
struct lstate start;
struct lstate end;
char *codep;
};
struct line *head;
struct line *tail;
struct line cline { -1,-1,-1,-1};
#define TBUFLEN 1024
char *codep;
char tbuf[TBUFLEN];
#ifdef MONITORING
extern etext();
int monbuf[1000];
#endif
main(argc, argv)
int argc;
char *argv[];
{
register i;
#ifndef TESTING
signal(BROKENPIPE, 1);
#endif
for(i = 3; i < 15; i++)
close(i);
#ifdef MONITORING
monitor(2,etext,monbuf,sizeof monbuf/2,0);
#endif
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'l') {
float f = 144 * atof(argv[1] + 2);
if (f < 144) {
error("bad length");
exit(1);
}
overflow = f;
argc--, argv++;
}
outbuf = stdout;
if(argc > 1)
{
while(--argc)
{
argv++;
process(argv[0]);
}
}
else
{
inbuf = stdin;
ofile();
}
#ifdef MONITORING
monitor(0);
#endif
done();
}
process(name)
char *name;
{
if((inbuf=fopen(name, "r")) == NULL)
error("cannot open data file");
ofile();
}
ofile()
{
register int c;
static int initialized;
while((c = getch()) != -1) {
if(!c)
continue;
if(c & 0200)
{
if(!pstart)
stuffc(c);
esc += (~c) & 0177;
continue;
}
if(esc)
{
if(back)
esc = -esc;
col += esc;
esc = 0;
}
if((c & 0377) < 0100) /* Purely for efficiency */
goto normal_char;
switch(c) {
case 0100:
if(initialized++)
goto out;
row = 0;
col = 0; esc = 0;
lead = 0;
verd = 0; back = 0; mcase = 0;
railmag = 0;
ocol = 0;
oback = 0; omcase = 0;
orailmag = 0;
if(loadfont(railmag, cpsize) < 0)
error("init");
startline();
putc(0100, outbuf); /* Dont stuff it guys */
break;
case 0101: /* lower rail */
crail(railmag =& ~01);
if(!pstart)
stuffc(c);
break;
case 0102: /* upper rail */
crail(railmag =| 01);
if(!pstart)
stuffc(c);
break;
case 0103: /* upper mag */
crail(railmag =| 02);
if(!pstart)
stuffc(c);
break;
case 0104: /* lower mag */
crail(railmag =& ~02);
if(!pstart)
stuffc(c);
break;
case 0105: /* lower case */
mcase = 0;
if(!pstart)
stuffc(c);
break;
case 0106: /* upper case */
mcase = 0100;
if(!pstart)
stuffc(c);
break;
case 0107: /* escape forward */
back = 0;
if(!pstart)
stuffc(c);
break;
case 0110: /* escape backwards */
back = 1;
if(!pstart)
stuffc(c);
break;
case 0111: /* stop */
stuffc(c);
break;
case 0112: /* lead forward */
verd = 0;
break;
case 0113: /* undefined */
break;
case 0114: /* lead backward */
verd = 1;
break;
case 0115: /* undefined */
case 0116:
case 0117:
break;
default:
if((c & 0340) == 0140) /* leading */
{
termline();
lead = (~c) & 037;
if(verd)
lead = -lead;
if (skmagic > 0) {
skmagic--;
ptlead(lead);
continue;
}
row += lead;
if (row >= overflow) {
if (pagemod == 3) {
allflush();
col %= MODOFF;
pagemod = 0;
} else {
pagemod++;
col += MODOFF;
row -= overflow;
}
}
if (row >= overflow)
write(2, "URK\n", 4);
/*
if (row > overflow)
miniflush();
*/
if (row < 0) {
if (pagemod) {
pagemod--;
col -= MODOFF;
row += overflow;
}
}
if (row < 0)
write(2, "URK2\n", 5);
pstart++;
continue;
}
if((c & 0360) == 0120) /* size change */
{
if(!pstart)
stuffc(c);
col += stupidadj(c & 017, cpsize);
loadfont(railmag, c & 017);
continue;
}
if(c & 0300)
continue;
normal_char:
c = (c & 077);
stuffc(c);
}
}
out:
termline();
allflush();
fclose(inbuf);
}
done() {
termline();
allflush();
exit();
}
int peekc;
getch() {
register c;
if(peekc) {
c = peekc;
peekc = 0;
return(c);
}
return(getc(inbuf));
}
ungetc(c) {
peekc = c;
}
error(s)
char *s;
{
fflush(outbuf);
fprintf(stderr, "Vsort: %s\n", s);
}
crail(nrail)
register int nrail;
{
register int psize;
psize = cpsize;
loadfont(nrail, psize);
}
loadfont(fnum, size)
register int fnum;
register int size;
{
cpsize = size;
return(0);
}
startline()
{
if(pstart != 0) {
cline.start.row = row;
return;
}
cline.len = 0;
cline.start.row = row;
cline.start.col = col;
cline.start.psize = cpsize;
cline.start.mcase = mcase;
cline.start.back = back;
cline.start.verd = verd;
cline.start.railmag = railmag;
codep = tbuf;
}
termline()
{
register struct line *linep;
register char *allp;
register char *cp;
int i;
if(pstart != 0)
return;
if((allp = calloc(sizeof *linep,1)) == -1)
error("alloc");
linep = allp;
linep->end.row = row;
linep->end.col = col;
linep->end.psize = cpsize;
linep->end.mcase = mcase;
linep->end.back = back;
linep->end.verd = verd;
linep->end.railmag = railmag;
linep->start.row = cline.start.row;
linep->start.col = cline.start.col;
linep->start.psize = cline.start.psize;
linep->start.mcase = cline.start.mcase;
linep->start.back = cline.start.back;
linep->start.verd = cline.start.verd;
linep->start.railmag = cline.start.railmag;
linep->len = cline.len;
if((allp = calloc(cline.len,1)) == -1)
error("alloc");
linep->codep = allp;
cp = tbuf;
for(i = 0; i < cline.len; i++)
*allp++ = *cp++;
sortin(linep);
}
sortin(linep)
register struct line *linep;
{
register struct line *clp;
if((clp = tail) == NULL) {
head = tail = linep;
linep->lastp = linep->nextp = NULL;
return;
}
while(clp != NULL && clp->start.row > linep->start.row)
clp = clp->lastp;
if(clp == tail) {
linep->lastp = tail;
linep->nextp = NULL;
tail->nextp = linep;
tail = linep;
} else
if(clp == NULL) /* goes at head of list */ {
linep->lastp = NULL;
linep->nextp = head;
head->lastp = linep;
head = linep;
} else {
linep->lastp = clp;
linep->nextp = clp->nextp;
clp->nextp->lastp = linep;
clp->nextp = linep;
}
}
stuffc(code)
register int code;
{
if(pstart != 0) {
pstart = 0;
startline();
}
if(cline.len > TBUFLEN) {
termline();
startline();
}
*codep++ = code;
cline.len++;
}
miniflush()
{
sendline();
}
allflush()
{
while(head != NULL)
sendline();
sendline();
fflush(outbuf);
}
sendline()
{
register char *cp;
register struct line *linep;
register int i;
int drow;
if((linep = head) == NULL) {
while(row >= overflow) {
/* fprintf(stderr, "spitting %d\n", overflow - row); */
if (overflow - row)
ptlead(overflow - row);
updatelist(overflow);
}
return;
}
adjparms(linep);
cp = linep->codep;
for(i = 0; i < linep->len; i++)
putc(*cp++, outbuf);
setparms(linep);
if(linep->nextp != NULL)
drow = linep->nextp->start.row;
else
drow = overflow;
head = linep->nextp;
cfree(linep->codep);
cfree(linep);
if(head == NULL)
tail = NULL;
else
head->lastp = NULL;
ptlead(drow - row);
row = drow;
/* updatelist(drow); */
}
adjparms(linep)
register struct line *linep;
{
if(linep->start.railmag != orailmag)
ptrail(linep->start.railmag);
if(linep->start.psize != opsize)
ptsize(linep->start.psize);
if(linep->start.mcase != omcase)
ptmcase();
if(linep->start.row != row) /* lead forward */
{
ptlead(linep->start.row - row);
row = linep->start.row;
/* updatelist(linep->start.row); */
}
if(linep->start.col != ocol)
ptesc(linep->start.col-ocol);
if(linep->start.back != oback)
ptback();
}
ptrail(rlmg)
register int rlmg;
{
if((rlmg & 01) != (orailmag & 01))
putc((rlmg & 01) ? 0102:0101, outbuf); /* rail */
if((rlmg & 02) != (orailmag & 02))
putc((rlmg & 02) ? 0103:0104, outbuf); /* mag */
}
ptback()
{
putc(oback ? 0107:0110, outbuf);
oback = !oback;
}
ptsize(size)
register int size;
{
putc(0120 | (size & 017), outbuf);
ptesc(-stupidadj(size, opsize));
}
stupidadj(code, lcode)
register int code;
int lcode;
{
register struct point_sizes *psp;
register struct point_sizes *lpsp;
psp = point_sizes;
while(psp->real_code != 0) {
if((psp->stupid_code & 017) == code)
break;
psp++;
}
lpsp = point_sizes;
while(lpsp->real_code != 0) {
if((lpsp->stupid_code & 017) == lcode)
break;
lpsp++;
}
code = 0;
if(!(lpsp->stupid_code & 0200) && (psp->stupid_code & 0200))
code = -55;
else
if((lpsp->stupid_code & 0200) && !(psp->stupid_code & 0200))
code = 55;
return(code);
}
ptmcase()
{
putc(omcase ? 0105:0106, outbuf);
}
ptesc(escc)
register int escc;
{
if((escc < 0 && !oback ) || (escc >= 0 && oback))
ptback();
escc = abs(escc);
while(escc > 0177) {
putc(0200, outbuf);
escc -= 0177;
}
if(escc)
putc(0200 | ((~escc) & 0177), outbuf);
}
ptlead(leadd)
register int leadd;
{
while(leadd > 037) {
putc(0140, outbuf);
leadd -= 037;
}
if(leadd)
putc(0140 | ((~leadd) & 037), outbuf);
}
setparms(linep)
register struct line *linep;
{
orailmag = linep->end.railmag;
opsize = linep->end.psize;
omcase = linep->end.mcase;
ocol = linep->end.col;
oback = linep->end.back;
}
updatelist(drow)
register int drow;
{
register struct line *clp;
for(clp = head; clp != NULL; clp = clp->nextp)
clp->start.row -= drow;
row -= drow;
}