|
|
1.1 root 1: /*
2: * dsort
3: *
4: * sort troff output into troff output that only goes one
5: * direction down the page.
6: * caveat user:
7: * there are bugs herein
8: * it doesn't do anything with graphics like \D'...'
9: */
10:
11: /*
12: output language from troff:
13: all numbers are character strings
14:
15: sn size in points
16: fn font as number from 1-n
17: cx ascii character x
18: Cxyz funny char xyz. terminated by white space
19: Hn go to absolute horizontal position n
20: Vn go to absolute vertical position n (down is positive)
21: hn go n units horizontally (relative)
22: vn ditto vertically
23: nnc move right nn, then print c (exactly 2 digits!)
24: (this wart is an optimization that shrinks output file size
25: about 35% and run-time about 15% while preserving ascii-ness)
26: Dt ...\n draw operation 't':
27: Dl x y line from here by x,y
28: Dc d circle of diameter d with left side here
29: De x y ellipse of axes x,y with left side here
30: Da x y r arc counter-clockwise by x,y of radius r
31: D~ x y x y ... wiggly line by x,y then x,y ...
32: nb a end of line (information only -- no action needed)
33: b = space before line, a = after
34: p new page begins -- set v to 0
35: #...\n comment
36: x ...\n device control functions:
37: x i init
38: x T s name of device is s
39: x r n h v resolution is n/inch
40: h = min horizontal motion, v = min vert
41: x p pause (can restart)
42: x s stop -- done for ever
43: x t generate trailer
44: x f n s font position n contains font s
45: x H n set character height to n
46: x S n set slant to N
47:
48: Subcommands like "i" are often spelled out like "init".
49: */
50:
51: #include <stdio.h>
52: #include <ctype.h>
53:
54: #define FATAL 1
55: int dbg = 0;
56: int res; /* input assumed computed according to this resolution */
57: int size = 0; /* current size */
58: int font = 0; /* current font */
59: int hpos; /* horizontal position where we are supposed to be next (left = 0) */
60: int vpos; /* current vertical position (down positive) */
61: int horig; /* h origin of current block; hpos rel to this */
62: int vorig;
63:
64:
65: main(argc, argv)
66: char *argv[];
67: {
68: FILE *fp;
69: int i;
70: int done();
71: extern int obufsize;
72:
73: while (argc > 1 && argv[1][0] == '-') {
74: switch (argv[1][1]) {
75: case 'd':
76: dbg = atoi(&argv[1][2]);
77: if (dbg == 0) dbg = 1;
78: obufsize = 50;
79: break;
80: }
81: argc--;
82: argv++;
83: }
84: if (argc <= 1)
85: conv(stdin);
86: else
87: while (--argc > 0) {
88: if (strcmp(*++argv, "-") == 0)
89: fp = stdin;
90: else if ((fp = fopen(*argv, "r")) == NULL)
91: error(FATAL, "can't open %s", *argv);
92: conv(fp);
93: fclose(fp);
94: }
95: done();
96: }
97:
98: /* new data declarations go here */
99: struct vlist {
100: int v;
101: int h;
102: int s;
103: int f;
104: char *p;
105: };
106:
107: #define NVLIST 1500
108: struct vlist vlist[NVLIST + 1];
109: struct vlist *vlp = vlist;
110: int nvlist = 0;
111: #define OBUFSIZE 32000
112: int obufsize = OBUFSIZE;
113: #define SLOP 500
114: char obuf[OBUFSIZE + SLOP];
115: char *op = obuf;
116:
117: conv(fp)
118: register FILE *fp;
119: {
120: register int c, k;
121: int m, n, i, n1, m1;
122: char str[100], buf[300];
123:
124: while ((c = getc(fp)) != EOF) {
125: if(dbg)fprintf(stderr, "%c i=%d V=%d\n", c, op-obuf, vpos);
126: pause();
127: if (op >= obuf + obufsize)
128: oflush();
129: switch (c) {
130: case '\n': /* when input is text */
131: case ' ':
132: *op++ = c;
133: break;
134: case '{': /* push down current environment */
135: *op++ = c;
136: t_push();
137: break;
138: case '}':
139: *op++ = c;
140: t_pop();
141: break;
142: case '0': case '1': case '2': case '3': case '4':
143: case '5': case '6': case '7': case '8': case '9':
144: /* two motion digits plus a character */
145: *op++ = c;
146: *op++ = getc(fp);
147: hmot((op[-2]-'0') * 10 + op[-1] - '0');
148: *op++ = getc(fp);
149: break;
150: case 'c': /* single ascii character */
151: *op++ = c;
152: *op++ = getc(fp);
153: break;
154: case 'C':
155: *op++ = c;
156: while ((c = getc(fp)) != ' ' && c != '\n')
157: *op++ = c;
158: ungetc(c, fp);
159: break;
160: case 't': /* straight text */
161: *op++ = c;
162: fgets(op, SLOP, fp);
163: op += strlen(op);
164: break;
165: case 'D': /* draw function */
166: *op++ = c;
167: fgets(op, SLOP, fp);
168: switch (*op) {
169: case 'l': /* draw a line */
170: sscanf(op+1, "%d %d", &n, &m);
171: hmot(n);
172: break;
173: case 'c': /* circle */
174: sscanf(op+1, "%d", &n);
175: hmot(n);
176: break;
177: case 'e': /* ellipse */
178: sscanf(op+1, "%d %d", &m, &n);
179: hmot(m);
180: break;
181: case 'a': /* arc */
182: sscanf(op+1, "%d %d %d", &n, &m, &n1);
183: hmot(n);
184: break;
185: case '~': /* wiggly line */
186: hmot(0); /* bug */
187: break;
188: default:
189: error(FATAL, "unknown drawing function %s\n", buf);
190: break;
191: }
192: op += strlen(op); /* skip over new stuff */
193: break;
194: case 's':
195: *op++ = c;
196: fscanf(fp, "%s", op); /* ignore fractional sizes */
197: size = atoi(op);
198: op += strlen(op);
199: break;
200: case 'f':
201: *op++ = c;
202: fscanf(fp, "%s", op);
203: font = atoi(op);
204: op += strlen(op);
205: break;
206: case 'H': /* absolute horizontal motion */
207: /* fscanf(fp, "%d", &n); */
208: *op++ = c;
209: while ((c = getc(fp)) == ' ')
210: ;
211: k = 0;
212: do {
213: *op++ = c;
214: k = 10 * k + c - '0';
215: } while (isdigit(c = getc(fp)));
216: ungetc(c, fp);
217: hgoto(k);
218: break;
219: case 'h': /* relative horizontal motion */
220: /* fscanf(fp, "%d", &n); */
221: *op++ = c;
222: while ((c = getc(fp)) == ' ')
223: ;
224: k = 0;
225: do {
226: *op++ = c;
227: k = 10 * k + c - '0';
228: } while (isdigit(c = getc(fp)));
229: ungetc(c, fp);
230: hmot(k);
231: break;
232: case 'w':
233: break;
234: case 'V':
235: *op++ = 0;
236: if (vlp >= vlist + NVLIST) {
237: oflush();
238: }
239: vlp->p = op;
240: *op++ = c;
241: fscanf(fp, "%s", op);
242: n = atoi(op);
243: vgoto(n);
244: op += strlen(op);
245: vlp->v = vpos;
246: vlp->h = hpos;
247: vlp->s = size;
248: vlp->f = font;
249: vlp++;
250: nvlist++;
251: break;
252: case 'v':
253: *op++ = c;
254: fscanf(fp, "%d", &n);
255: vmot(n);
256: /* punt for now, since never occurs */
257: break;
258: case 'p': /* new page */
259: vpos = 0;
260: oflush();
261: *op++ = c;
262: fscanf(fp, "%s", op);
263: op += strlen(op);
264: break;
265: case 'n': /* end of line */
266: *op++ = c;
267: while ((*op++ = getc(fp)) != '\n')
268: ;
269: hpos = 0;
270: break;
271: case '#': /* comment */
272: *op++ = c;
273: while ((*op++ = getc(fp)) != '\n')
274: ;
275: break;
276: case 'x': /* device control */
277: oflush();
278: putchar(c);
279: fgets(buf, sizeof buf, fp);
280: fputs(buf, stdout);
281: fflush(stdout);
282: break;
283: default:
284: error(!FATAL, "unknown input character %o %c\n", c, c);
285: done();
286: }
287: }
288: }
289:
290: pause(i, j, k)
291: {
292: }
293:
294: oflush() /* sort, then dump out contents of obuf */
295: {
296: char *p;
297: struct vlist *vp;
298: int i;
299: int compar();
300:
301: if(dbg)fprintf(stderr, "into oflush, V=%d\n", vpos);
302: if (op == obuf)
303: return;
304: qsort((char *) vlist, nvlist, sizeof (struct vlist), compar);
305: *op++ = 0;
306: vp = vlist;
307: printf("V%d\n", vp->v);
308: for (i = 0; i < nvlist; i++, vp++) {
309: printf("H%ds%df%d\n", vp->h, vp->s, vp->f);
310: for (p = vp->p; *p != 0; p++)
311: putchar(*p);
312: }
313: fflush(stdout);
314: vlp = vlist;
315: vlp->p = op = obuf;
316: sprintf(op, "V%dH%d\n", vpos, hpos);
317: op += strlen(op);
318: vlp->h = hpos;
319: vlp->v = vpos;
320: vlp->s = size;
321: vlp->f = font;
322: *op = 0;
323: vlp++;
324: nvlist = 1;
325: }
326:
327:
328: compar(p1, p2)
329: struct vlist *p1, *p2;
330: {
331: return(p1->v - p2->v);
332: }
333:
334: done()
335: {
336: oflush();
337: exit(0);
338: }
339:
340: error(f, s, a1, a2, a3, a4, a5, a6, a7) {
341: fprintf(stderr, "dsort: ");
342: fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
343: fprintf(stderr, "\n");
344: if (f)
345: done();
346: }
347:
348: #define MAXSTATE 5
349:
350: struct state {
351: int ssize;
352: int sfont;
353: int shpos;
354: int svpos;
355: int shorig;
356: int svorig;
357: };
358: struct state state[MAXSTATE];
359: struct state *statep = state;
360:
361: t_push() /* begin a new block */
362: {
363: statep->ssize = size;
364: statep->sfont = font;
365: statep->shorig = horig;
366: statep->svorig = vorig;
367: statep->shpos = hpos;
368: statep->svpos = vpos;
369: horig = hpos;
370: vorig = vpos;
371: hpos = vpos = 0;
372: if (statep++ >= state+MAXSTATE)
373: error(FATAL, "{ nested too deep");
374: hpos = vpos = 0;
375: }
376:
377: t_pop() /* pop to previous state */
378: {
379: if (--statep < state)
380: error(FATAL, "extra }");
381: size = statep->ssize;
382: font = statep->sfont;
383: hpos = statep->shpos;
384: vpos = statep->svpos;
385: horig = statep->shorig;
386: vorig = statep->svorig;
387: }
388:
389: t_page(n) /* do whatever new page functions */
390: {
391: int i;
392:
393: vpos = 0;
394: }
395:
396: hgoto(n)
397: {
398: hpos = n; /* this is where we want to be */
399: /* before printing a character, */
400: /* have to make sure it's true */
401: }
402:
403: hmot(n) /* generate n units of horizontal motion */
404: int n;
405: {
406: hgoto(hpos + n);
407: }
408:
409: vgoto(n)
410: {
411: vpos = n;
412: }
413:
414: vmot(n) /* generate n units of vertical motion */
415: int n;
416: {
417: vgoto(vpos + n); /* ignores rounding */
418: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.