|
|
1.1 root 1: /*
2: * drive hp2621 terminal
3: * just to see stuff quickly. like troff -a
4: */
5:
6: /*
7: output language from troff:
8: all numbers are character strings
9:
10: sn size in points
11: fn font as number from 1-n
12: cx ascii character x
13: Cxyz funny char xyz. terminated by white space
14: Hn go to absolute horizontal position n
15: Vn go to absolute vertical position n (down is positive)
16: hn go n units horizontally (relative)
17: vn ditto vertically
18: nnc move right nn, then print c (exactly 2 digits!)
19: (this wart is an optimization that shrinks output file size
20: about 35% and run-time about 15% while preserving ascii-ness)
21: dt ...\n draw operation 't':
22: d/ dx dy c line from here to dx,dy using c
23: dO r circle of radius r centered here
24: dE rx ry ellipse of semi-axes rx, ry centered here
25: dA dx1 dy1 dx2 dy2 arc counter-clockwise with center here
26: from dx1,dy1 to dx2,dy2.
27: nb a end of line (information only -- no action needed)
28: b = space before line, a = after
29: p new page begins -- set v to 0
30: #...\n comment
31: x ...\n device control functions:
32: x i init
33: x T s name of device is s
34: x r n h v resolution is n/inch
35: h = min horizontal motion, v = min vert
36: x p pause (can restart)
37: x s stop -- done for ever
38: x t generate trailer
39: x f n s font position n contains font s
40:
41: Subcommands like "i" are often spelled out like "init".
42: */
43:
44: #include <stdio.h>
45: #include <signal.h>
46: #include <ctype.h>
47:
48: #include "dev.h"
49: #define NFONT 10
50:
51: int output = 0; /* do we do output at all? */
52: int nolist = 0; /* output page list if > 0 */
53: int olist[20]; /* pairs of page numbers */
54:
55: int erase = 1;
56: float aspect = 1.5; /* default aspect ratio */
57: int wflag = 0; /* wait, looping, for new input if on */
58: int (*sigint)();
59: int (*sigquit)();
60:
61: struct dev dev;
62: struct font *fontbase[NFONT];
63: short psizes[] ={ 11, 16, 22, 36, 0}; /* approx sizes available */
64: short *pstab = psizes;
65: int nsizes = 1;
66: int nfonts;
67: int smnt; /* index of first special font */
68: int nchtab;
69: char *chname;
70: short *chtab;
71: char *fitab[NFONT];
72: char *widthtab[NFONT]; /* widtab would be a better name */
73: char *codetab[NFONT]; /* device codes */
74:
75: #define FATAL 1
76: #define BMASK 0377
77: int dbg = 0;
78: int res = 972; /* input assumed computed according to this resolution */
79: /* initial value to avoid 0 divide */
80: FILE *tf = stdout; /* output file */
81: char *fontdir = "/usr/lib/font";
82: extern char devname[];
83:
84: FILE *fp = stdin; /* input file pointer */
85:
86: int nowait = 0; /* 0 => wait at bottom of each page */
87:
88: main(argc, argv)
89: char *argv[];
90: {
91: char buf[BUFSIZ];
92: int done();
93: float atof();
94:
95: setbuf(stdout, buf);
96: while (argc > 1 && argv[1][0] == '-') {
97: switch (argv[1][1]) {
98: case 'a':
99: aspect = atof(&argv[1][2]);
100: break;
101: case 'e':
102: erase = 0;
103: break;
104: case 'o':
105: outlist(&argv[1][2]);
106: break;
107: case 'd':
108: dbg = atoi(&argv[1][2]);
109: if (dbg == 0) dbg = 1;
110: break;
111: case 'w': /* no wait at bottom of page */
112: nowait = 1;
113: break;
114: }
115: argc--;
116: argv++;
117: }
118:
119: if (argc <= 1)
120: conv(stdin);
121: else
122: while (--argc > 0) {
123: if (strcmp(*++argv, "-") == 0)
124: fp = stdin;
125: else if ((fp = fopen(*argv, "r")) == NULL)
126: error(FATAL, "can't open %s", *argv);
127: conv(fp);
128: fclose(fp);
129: }
130: done();
131: }
132:
133: outlist(s) /* process list of page numbers to be printed */
134: char *s;
135: {
136: int n1, n2, i;
137:
138: nolist = 0;
139: while (*s) {
140: n1 = 0;
141: if (isdigit(*s))
142: do
143: n1 = 10 * n1 + *s++ - '0';
144: while (isdigit(*s));
145: else
146: n1 = -9999;
147: n2 = n1;
148: if (*s == '-') {
149: s++;
150: n2 = 0;
151: if (isdigit(*s))
152: do
153: n2 = 10 * n2 + *s++ - '0';
154: while (isdigit(*s));
155: else
156: n2 = 9999;
157: }
158: olist[nolist++] = n1;
159: olist[nolist++] = n2;
160: if (*s != '\0')
161: s++;
162: }
163: olist[nolist] = 0;
164: if (dbg)
165: for (i=0; i<nolist; i += 2)
166: printf("%3d %3d\n", olist[i], olist[i+1]);
167: }
168:
169: in_olist(n) /* is n in olist? */
170: int n;
171: {
172: int i;
173:
174: if (nolist == 0)
175: return(1); /* everything is included */
176: for (i = 0; i < nolist; i += 2)
177: if (n >= olist[i] && n <= olist[i+1])
178: return(1);
179: return(0);
180: }
181:
182: conv(fp)
183: register FILE *fp;
184: {
185: register int c, k;
186: int m, n, i, n1, m1;
187: char str[100], buf[300];
188:
189: while ((c = getc(fp)) != EOF) {
190: switch (c) {
191: case '\n': /* when input is text */
192: case ' ':
193: case 0: /* occasional noise creeps in */
194: break;
195: case '{': /* push down current environment */
196: t_push();
197: break;
198: case '}':
199: t_pop();
200: break;
201: case '0': case '1': case '2': case '3': case '4':
202: case '5': case '6': case '7': case '8': case '9':
203: /* two motion digits plus a character */
204: hmot((c-'0')*10 + getc(fp)-'0');
205: put1(getc(fp));
206: break;
207: case 'c': /* single ascii character */
208: put1(getc(fp));
209: break;
210: case 'C':
211: fscanf(fp, "%s", str);
212: put1s(str);
213: break;
214: case 't': /* straight text */
215: fgets(buf, sizeof(buf), fp);
216: t_text(buf);
217: break;
218: case 'D': /* draw function */
219: fgets(buf, sizeof(buf), fp);
220: switch (buf[0]) {
221: case 'l': /* draw a line */
222: sscanf(buf+1, "%d %d", &n, &m);
223: drawline(n, m, ".");
224: break;
225: case 'c': /* circle */
226: sscanf(buf+1, "%d", &n);
227: drawcirc(n);
228: break;
229: case 'e': /* ellipse */
230: sscanf(buf+1, "%d %d", &m, &n);
231: drawellip(m, n);
232: break;
233: case 'a': /* arc */
234: sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
235: drawarc(n, m, n1, m1);
236: break;
237: case '~': /* wiggly line */
238: drawwig(buf+1);
239: break;
240: default:
241: error(FATAL, "unknown drawing function %s\n", buf);
242: break;
243: }
244: break;
245: case 's':
246: fscanf(fp, "%d", &n); /* ignore fractional sizes */
247: setsize(t_size(n));
248: break;
249: case 'f':
250: fscanf(fp, "%s", str);
251: setfont(t_font(str));
252: break;
253: case 'H': /* absolute horizontal motion */
254: /* fscanf(fp, "%d", &n); */
255: while ((c = getc(fp)) == ' ')
256: ;
257: k = 0;
258: do {
259: k = 10 * k + c - '0';
260: } while (isdigit(c = getc(fp)));
261: ungetc(c, fp);
262: hgoto(k);
263: break;
264: case 'h': /* relative horizontal motion */
265: /* fscanf(fp, "%d", &n); */
266: while ((c = getc(fp)) == ' ')
267: ;
268: k = 0;
269: do {
270: k = 10 * k + c - '0';
271: } while (isdigit(c = getc(fp)));
272: ungetc(c, fp);
273: hmot(k);
274: break;
275: case 'w': /* word space */
276: putc(' ', stdout);
277: break;
278: case 'V':
279: fscanf(fp, "%d", &n);
280: vgoto(n);
281: break;
282: case 'v':
283: fscanf(fp, "%d", &n);
284: vmot(n);
285: break;
286: case 'p': /* new page */
287: fscanf(fp, "%d", &n);
288: t_page(n);
289: break;
290: case 'n': /* end of line */
291: while (getc(fp) != '\n')
292: ;
293: t_newline();
294: break;
295: case '#': /* comment */
296: while (getc(fp) != '\n')
297: ;
298: break;
299: case 'x': /* device control */
300: devcntrl(fp);
301: break;
302: default:
303: error(!FATAL, "unknown input character %o %c\n", c, c);
304: done();
305: }
306: }
307: }
308:
309: devcntrl(fp) /* interpret device control functions */
310: FILE *fp;
311: {
312: char str[20];
313: int c, n;
314:
315: fscanf(fp, "%s", str);
316: switch (str[0]) { /* crude for now */
317: case 'i': /* initialize */
318: fileinit();
319: t_init(0);
320: break;
321: case 'T': /* device name */
322: fscanf(fp, "%s", devname);
323: break;
324: case 't': /* trailer */
325: t_trailer();
326: break;
327: case 'p': /* pause -- can restart */
328: t_reset('p');
329: break;
330: case 's': /* stop */
331: t_reset('s');
332: break;
333: case 'r': /* resolution assumed when prepared */
334: fscanf(fp, "%d", &res);
335: break;
336: case 'f': /* font used */
337: fscanf(fp, "%d %s", &n, str);
338: loadfont(n, str);
339: break;
340: }
341: while (getc(fp) != '\n') /* skip rest of input line */
342: ;
343: }
344:
345: fileinit() /* read in font and code files, etc. */
346: {
347: }
348:
349: fontprint(i) /* debugging print of font i (0,...) */
350: {
351: }
352:
353: loadcode(n, nw) /* load codetab on position n (0...); #chars is nw */
354: int n, nw;
355: {
356: }
357:
358: loadfont(n, s) /* load font info for font s on position n (1...) */
359: int n;
360: char *s;
361: {
362: }
363:
364: error(f, s, a1, a2, a3, a4, a5, a6, a7) {
365: fprintf(stderr, "ta: ");
366: fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
367: fprintf(stderr, "\n");
368: if (f)
369: exit(1);
370: }
371:
372:
373: /*
374: Here beginneth all the stuff that really depends
375: on the 202 (we hope).
376: */
377:
378:
379: char devname[20] = "hp2621";
380:
381: #define ESC 033
382: #define HOME 'H'
383: #define CLEAR 'J'
384: #define FF 014
385:
386: int size = 1;
387: int font = 1; /* current font */
388: int hpos; /* horizontal position where we are supposed to be next (left = 0) */
389: int vpos; /* current vertical position (down positive) */
390:
391: int horig; /* h origin of current block; hpos rel to this */
392: int vorig; /* v origin of current block; vpos rel to this */
393:
394: int DX = 10; /* step size in x for drawing */
395: int DY = 10; /* step size in y for drawing */
396: int drawdot = '.'; /* draw with this character */
397: int drawsize = 1; /* shrink by this factor when drawing */
398:
399: t_init(reinit) /* initialize device */
400: int reinit;
401: {
402: int i, j;
403:
404: fflush(stdout);
405: hpos = vpos = 0;
406: }
407:
408: #define MAXSTATE 5
409:
410: struct state {
411: int ssize;
412: int sfont;
413: int shpos;
414: int svpos;
415: int shorig;
416: int svorig;
417: };
418: struct state state[MAXSTATE];
419: struct state *statep = state;
420:
421: t_push() /* begin a new block */
422: {
423: hflush();
424: statep->ssize = size;
425: statep->sfont = font;
426: statep->shorig = horig;
427: statep->svorig = vorig;
428: statep->shpos = hpos;
429: statep->svpos = vpos;
430: horig = hpos;
431: vorig = vpos;
432: hpos = vpos = 0;
433: if (statep++ >= state+MAXSTATE)
434: error(FATAL, "{ nested too deep");
435: hpos = vpos = 0;
436: }
437:
438: t_pop() /* pop to previous state */
439: {
440: if (--statep < state)
441: error(FATAL, "extra }");
442: size = statep->ssize;
443: font = statep->sfont;
444: hpos = statep->shpos;
445: vpos = statep->svpos;
446: horig = statep->shorig;
447: vorig = statep->svorig;
448: }
449:
450: int np; /* number of pages seen */
451: int npmax; /* high-water mark of np */
452: int pgnum[40]; /* their actual numbers */
453: long pgadr[40]; /* their seek addresses */
454:
455: t_page(n) /* do whatever new page functions */
456: {
457: long ftell();
458: int c, m, i;
459: char buf[100], *bp;
460:
461: pgnum[np++] = n;
462: pgadr[np] = ftell(fp);
463: if (np > npmax)
464: npmax = np;
465: if (output == 0) {
466: output = in_olist(n);
467: t_init(1);
468: return;
469: }
470: /* have just printed something, and seen p<n> for next one */
471: putpage();
472: fflush(stdout);
473: if (nowait)
474: return;
475:
476: next:
477: for (bp = buf; (*bp = readch()); )
478: if (*bp++ == '\n')
479: break;
480: *bp = 0;
481: switch (buf[0]) {
482: case 0:
483: done();
484: break;
485: case '\n':
486: output = in_olist(n);
487: t_init(1);
488: return;
489: case '!':
490: callunix(&buf[1]);
491: fputs("!\n", stderr);
492: break;
493: case 'e':
494: erase = 1 - erase;
495: break;
496: case 'w':
497: wflag = 1 - wflag;
498: break;
499: case 'a':
500: aspect = atof(&buf[1]);
501: break;
502: case '-':
503: case 'p':
504: m = atoi(&buf[1]) + 1;
505: if (fp == stdin) {
506: fputs("you can't; it's not a file\n", stderr);
507: break;
508: }
509: if (np - m <= 0) {
510: fputs("too far back\n", stderr);
511: break;
512: }
513: np -= m;
514: fseek(fp, pgadr[np], 0);
515: output = 1;
516: t_init(1);
517: return;
518: case '0': case '1': case '2': case '3': case '4':
519: case '5': case '6': case '7': case '8': case '9':
520: m = atoi(&buf[0]);
521: for (i = 0; i < npmax; i++)
522: if (m == pgnum[i])
523: break;
524: if (i >= npmax || fp == stdin) {
525: fputs("you can't\n", stderr);
526: break;
527: }
528: np = i + 1;
529: fseek(fp, pgadr[np], 0);
530: output = 1;
531: t_init(1);
532: return;
533: case 'o':
534: outlist(&buf[1]);
535: output = 0;
536: t_init(1);
537: return;
538: case '?':
539: fputs("!cmd unix cmd\n", stderr);
540: fputs("p print this page again\n", stderr);
541: fputs("-n go back n pages\n", stderr);
542: fputs("n print page n (previously printed)\n", stderr);
543: fputs("o... set the -o output list to ...\n", stderr);
544: fputs("en n=0 -> don't erase; n=1 -> erase\n", stderr);
545: fputs("an sets aspect ratio to n\n", stderr);
546: break;
547: default:
548: fputs("?\n", stderr);
549: break;
550: }
551: goto next;
552: }
553:
554: putpage()
555: {
556: int i, j, k;
557:
558: fflush(stdout);
559: }
560:
561: t_newline() /* do whatever for the end of a line */
562: {
563: printf("\n");
564: hpos = 0;
565: }
566:
567: t_size(n) /* convert integer to internal size number*/
568: int n;
569: {
570: }
571:
572: t_font(s) /* convert string to internal font number */
573: char *s;
574: {
575: }
576:
577: t_text(s) /* print string s as text */
578: char *s;
579: {
580: int c, w;
581: char str[100];
582:
583: if (!output)
584: return;
585: while ((c = *s++) != '\n') {
586: if (c == '\\') {
587: switch (c = *s++) {
588: case '\\':
589: case 'e':
590: put1('\\');
591: break;
592: case '(':
593: str[0] = *s++;
594: str[1] = *s++;
595: str[2] = '\0';
596: put1s(str);
597: break;
598: }
599: } else {
600: put1(c);
601: }
602: hmot(w);
603: }
604: }
605:
606: t_reset(c)
607: {
608: int n;
609:
610: output = 1;
611: fflush(stdout);
612: if (c == 's')
613: t_page(9999);
614: }
615:
616: t_trailer()
617: {
618: }
619:
620: hgoto(n)
621: {
622: hpos = n; /* this is where we want to be */
623: /* before printing a character, */
624: /* have to make sure it's true */
625: }
626:
627: hmot(n) /* generate n units of horizontal motion */
628: int n;
629: {
630: hgoto(hpos + n);
631: }
632:
633: hflush() /* actual horizontal output occurs here */
634: {
635: }
636:
637: vgoto(n)
638: {
639: vpos = n;
640: }
641:
642: vmot(n) /* generate n units of vertical motion */
643: int n;
644: {
645: vgoto(vpos + n); /* ignores rounding */
646: }
647:
648: put1s(s) /* s is a funny char name */
649: char *s;
650: {
651: int i;
652: char *p;
653: extern char *spectab[];
654: static char prev[10] = "";
655: static int previ;
656:
657: if (!output)
658: return;
659: if (strcmp(s, prev) != 0) {
660: previ = -1;
661: for (i = 0; spectab[i] != 0; i += 2)
662: if (strcmp(spectab[i], s) == 0) {
663: strcpy(prev, s);
664: previ = i;
665: break;
666: }
667: }
668: if (previ >= 0) {
669: for (p = spectab[previ+1]; *p; p++)
670: putc(*p, stdout);
671: } else
672: prev[0] = 0;
673: }
674:
675: put1(c) /* output char c */
676: int c;
677: {
678: if (!output)
679: return;
680: putc(c, stdout);
681: }
682:
683: setsize(n) /* set point size to n (internal) */
684: int n;
685: {
686: }
687:
688: t_fp(n, s) /* font position n now contains font s */
689: int n;
690: char *s;
691: {
692: }
693:
694: setfont(n) /* set font to n */
695: int n;
696: {
697: }
698:
699: done()
700: {
701: output = 1;
702: putpage();
703: fflush(stdout);
704: exit(0);
705: }
706:
707: callunix(line)
708: char line[];
709: {
710: int rc, status, unixpid;
711: if( (unixpid=fork())==0 ) {
712: signal(SIGINT,sigint); signal(SIGQUIT,sigquit);
713: close(0); dup(2);
714: execl("/bin/sh", "-sh", "-c", line, 0);
715: exit(255);
716: }
717: else if(unixpid == -1)
718: return;
719: else{ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN);
720: while( (rc = wait(&status)) != unixpid && rc != -1 ) ;
721: signal(SIGINT,done); signal(SIGQUIT,sigquit);
722: }
723: }
724:
725: readch(){
726: char c;
727: if (read(2,&c,1)<1) c=0;
728: return(c);
729: }
730:
731: char *spectab[] ={
732: "em", "-",
733: "hy", "-",
734: "en", "-",
735: "ru", "_",
736: "l.", ".",
737: "br", "|",
738: "vr", "|",
739: "fm", "'",
740: "or", "|",
741: 0, 0,
742: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.