|
|
researchv10 Norman
/*
* dsort
*
* sort troff output into troff output that only goes one
* direction down the page.
* caveat user:
* there are bugs herein
* it doesn't do anything with graphics like \D'...'
*/
/*
output language from troff:
all numbers are character strings
sn size in points
fn font as number from 1-n
cx ascii character x
Cxyz funny char xyz. terminated by white space
Hn go to absolute horizontal position n
Vn go to absolute vertical position n (down is positive)
hn go n units horizontally (relative)
vn ditto vertically
nnc move right nn, then print c (exactly 2 digits!)
(this wart is an optimization that shrinks output file size
about 35% and run-time about 15% while preserving ascii-ness)
Dt ...\n draw operation 't':
Dl x y line from here by x,y
Dc d circle of diameter d with left side here
De x y ellipse of axes x,y with left side here
Da x y r arc counter-clockwise by x,y of radius r
D~ x y x y ... wiggly line by x,y then x,y ...
nb a end of line (information only -- no action needed)
b = space before line, a = after
p new page begins -- set v to 0
#...\n comment
x ...\n device control functions:
x i init
x T s name of device is s
x r n h v resolution is n/inch
h = min horizontal motion, v = min vert
x p pause (can restart)
x s stop -- done for ever
x t generate trailer
x f n s font position n contains font s
x H n set character height to n
x S n set slant to N
Subcommands like "i" are often spelled out like "init".
*/
#include <stdio.h>
#include <ctype.h>
#define FATAL 1
int dbg = 0;
int res; /* input assumed computed according to this resolution */
int size = 0; /* current size */
int font = 0; /* current font */
int hpos; /* horizontal position where we are supposed to be next (left = 0) */
int vpos; /* current vertical position (down positive) */
int horig; /* h origin of current block; hpos rel to this */
int vorig;
main(argc, argv)
char *argv[];
{
FILE *fp;
int i;
int done();
extern int obufsize;
while (argc > 1 && argv[1][0] == '-') {
switch (argv[1][1]) {
case 'd':
dbg = atoi(&argv[1][2]);
if (dbg == 0) dbg = 1;
obufsize = 50;
break;
}
argc--;
argv++;
}
if (argc <= 1)
conv(stdin);
else
while (--argc > 0) {
if (strcmp(*++argv, "-") == 0)
fp = stdin;
else if ((fp = fopen(*argv, "r")) == NULL)
error(FATAL, "can't open %s", *argv);
conv(fp);
fclose(fp);
}
done();
}
/* new data declarations go here */
struct vlist {
int v;
int h;
int s;
int f;
char *p;
};
#define NVLIST 1500
struct vlist vlist[NVLIST + 1];
struct vlist *vlp = vlist;
int nvlist = 0;
#define OBUFSIZE 32000
int obufsize = OBUFSIZE;
#define SLOP 500
char obuf[OBUFSIZE + SLOP];
char *op = obuf;
conv(fp)
register FILE *fp;
{
register int c, k;
int m, n, i, n1, m1;
char str[100], buf[300];
while ((c = getc(fp)) != EOF) {
if(dbg)fprintf(stderr, "%c i=%d V=%d\n", c, op-obuf, vpos);
pause();
if (op >= obuf + obufsize)
oflush();
switch (c) {
case '\n': /* when input is text */
case ' ':
*op++ = c;
break;
case '{': /* push down current environment */
*op++ = c;
t_push();
break;
case '}':
*op++ = c;
t_pop();
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
/* two motion digits plus a character */
*op++ = c;
*op++ = getc(fp);
hmot((op[-2]-'0') * 10 + op[-1] - '0');
*op++ = getc(fp);
break;
case 'c': /* single ascii character */
*op++ = c;
*op++ = getc(fp);
break;
case 'C':
*op++ = c;
while ((c = getc(fp)) != ' ' && c != '\n')
*op++ = c;
ungetc(c, fp);
break;
case 't': /* straight text */
*op++ = c;
fgets(op, SLOP, fp);
op += strlen(op);
break;
case 'D': /* draw function */
*op++ = c;
fgets(op, SLOP, fp);
switch (*op) {
case 'l': /* draw a line */
sscanf(op+1, "%d %d", &n, &m);
hmot(n);
break;
case 'c': /* circle */
sscanf(op+1, "%d", &n);
hmot(n);
break;
case 'e': /* ellipse */
sscanf(op+1, "%d %d", &m, &n);
hmot(m);
break;
case 'a': /* arc */
sscanf(op+1, "%d %d %d", &n, &m, &n1);
hmot(n);
break;
case '~': /* wiggly line */
hmot(0); /* bug */
break;
default:
error(FATAL, "unknown drawing function %s\n", buf);
break;
}
op += strlen(op); /* skip over new stuff */
break;
case 's':
*op++ = c;
fscanf(fp, "%s", op); /* ignore fractional sizes */
size = atoi(op);
op += strlen(op);
break;
case 'f':
*op++ = c;
fscanf(fp, "%s", op);
font = atoi(op);
op += strlen(op);
break;
case 'H': /* absolute horizontal motion */
/* fscanf(fp, "%d", &n); */
*op++ = c;
while ((c = getc(fp)) == ' ')
;
k = 0;
do {
*op++ = c;
k = 10 * k + c - '0';
} while (isdigit(c = getc(fp)));
ungetc(c, fp);
hgoto(k);
break;
case 'h': /* relative horizontal motion */
/* fscanf(fp, "%d", &n); */
*op++ = c;
while ((c = getc(fp)) == ' ')
;
k = 0;
do {
*op++ = c;
k = 10 * k + c - '0';
} while (isdigit(c = getc(fp)));
ungetc(c, fp);
hmot(k);
break;
case 'w':
break;
case 'V':
*op++ = 0;
if (vlp >= vlist + NVLIST) {
oflush();
}
vlp->p = op;
*op++ = c;
fscanf(fp, "%s", op);
n = atoi(op);
vgoto(n);
op += strlen(op);
vlp->v = vpos;
vlp->h = hpos;
vlp->s = size;
vlp->f = font;
vlp++;
nvlist++;
break;
case 'v':
*op++ = c;
fscanf(fp, "%d", &n);
vmot(n);
/* punt for now, since never occurs */
break;
case 'p': /* new page */
vpos = 0;
oflush();
*op++ = c;
fscanf(fp, "%s", op);
op += strlen(op);
break;
case 'n': /* end of line */
*op++ = c;
while ((*op++ = getc(fp)) != '\n')
;
hpos = 0;
break;
case '#': /* comment */
*op++ = c;
while ((*op++ = getc(fp)) != '\n')
;
break;
case 'x': /* device control */
oflush();
putchar(c);
fgets(buf, sizeof buf, fp);
fputs(buf, stdout);
fflush(stdout);
break;
default:
error(!FATAL, "unknown input character %o %c\n", c, c);
done();
}
}
}
pause(i, j, k)
{
}
oflush() /* sort, then dump out contents of obuf */
{
char *p;
struct vlist *vp;
int i;
int compar();
if(dbg)fprintf(stderr, "into oflush, V=%d\n", vpos);
if (op == obuf)
return;
qsort((char *) vlist, nvlist, sizeof (struct vlist), compar);
*op++ = 0;
vp = vlist;
printf("V%d\n", vp->v);
for (i = 0; i < nvlist; i++, vp++) {
printf("H%ds%df%d\n", vp->h, vp->s, vp->f);
for (p = vp->p; *p != 0; p++)
putchar(*p);
}
fflush(stdout);
vlp = vlist;
vlp->p = op = obuf;
sprintf(op, "V%dH%d\n", vpos, hpos);
op += strlen(op);
vlp->h = hpos;
vlp->v = vpos;
vlp->s = size;
vlp->f = font;
*op = 0;
vlp++;
nvlist = 1;
}
compar(p1, p2)
struct vlist *p1, *p2;
{
return(p1->v - p2->v);
}
done()
{
oflush();
exit(0);
}
error(f, s, a1, a2, a3, a4, a5, a6, a7) {
fprintf(stderr, "dsort: ");
fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
fprintf(stderr, "\n");
if (f)
done();
}
#define MAXSTATE 5
struct state {
int ssize;
int sfont;
int shpos;
int svpos;
int shorig;
int svorig;
};
struct state state[MAXSTATE];
struct state *statep = state;
t_push() /* begin a new block */
{
statep->ssize = size;
statep->sfont = font;
statep->shorig = horig;
statep->svorig = vorig;
statep->shpos = hpos;
statep->svpos = vpos;
horig = hpos;
vorig = vpos;
hpos = vpos = 0;
if (statep++ >= state+MAXSTATE)
error(FATAL, "{ nested too deep");
hpos = vpos = 0;
}
t_pop() /* pop to previous state */
{
if (--statep < state)
error(FATAL, "extra }");
size = statep->ssize;
font = statep->sfont;
hpos = statep->shpos;
vpos = statep->svpos;
horig = statep->shorig;
vorig = statep->svorig;
}
t_page(n) /* do whatever new page functions */
{
int i;
vpos = 0;
}
hgoto(n)
{
hpos = n; /* this is where we want to be */
/* before printing a character, */
/* have to make sure it's true */
}
hmot(n) /* generate n units of horizontal motion */
int n;
{
hgoto(hpos + n);
}
vgoto(n)
{
vpos = n;
}
vmot(n) /* generate n units of vertical motion */
int n;
{
vgoto(vpos + n); /* ignores rounding */
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.