|
|
1.1 root 1: /* fdevelop: convert script to intermediate language in two passes
2: Input defined in script.def, output in int.def
3: Pass 1 reads named file or stdin, writes intermediate file
4: Pass 2 reads intermediate, writes output
5: Intermediate file is like output, with these differences:
6: Header lines (d v, d c, etc.) absent
7: Erase commands: refer to line numbers in int file and
8: do not have geometric command following
9: Geometry commands: numbers not yet scaled, slots not
10: assigned
11: fdevelop is a filter, transforming stdin or one named file to stdout
12: the shell script develop uses this program to develop foo.s
13: into foo.i, if needed
14: */
15:
16: #include "fdevelop.h"
17:
18: #define SCALE 9999
19:
20: extern dox(), doy();
21: extern float stof();
22:
23: /* SLOTS */
24: int slotmax = 10000;
25:
26: /* STATUS OF EACH LINE IN INTERMEDIATE FILE*/
27: int linemax = 50000;
28: char *linevec; /* malloc'ed to [linemax] before pass 1 */
29: #define MAXVIEWS 10
30: /* if >10 views, change one-byte getc in pass2 */
31: #define ERASED 11
32: #define NOTGEOM 12
33:
34: /* VIEWS */
35: extern recordx(), recordy();
36: extern int scalex(), scaley();
37: int viewcnt = 0;
38: struct Viewelmt {
39: char name[MAXSTR]; /* character string name */
40: float maxx; /* range of values, both coords */
41: float minx;
42: float maxy;
43: float miny;
44: float factorx; /* factors used by scalex and scaley */
45: float factory;
46: int initx; /* max and min set yet? */
47: int inity;
48: } viewarr[MAXVIEWS];
49:
50: /* CLICKS */
51: #define MAXCLICKS 30
52: int clickcnt = 0;
53: char clickname [MAXCLICKS] [MAXSTR];
54:
55: /* OPTIONS FOR GEOMETRIC OBJECTS */
56: extern getoptions();
57: #define OPTMAX 10
58: char optstring[OPTMAX];
59: #define TEXT 0
60: #define LINE 1
61: #define BOX 2
62: #define CIRCLE 3
63: char *defaulttab[] = { /* match with above defines */
64: "cm7", /* TEXT: center, medium, white */
65: "s-7", /* LINE: solid, -, white */
66: "n7", /* BOX: nofill, white */
67: "n7" /* CIRCLE: nofill, white */
68: };
69: struct Geoelmt {
70: int cmd;
71: int pos;
72: char *name;
73: char val;
74: } geooptarr[] = {
75: TEXT, 0, "center", 'c',
76: TEXT, 0, "ljust", 'l',
77: TEXT, 0, "rjust", 'r',
78: TEXT, 0, "above", 'a',
79: TEXT, 0, "below", 'b',
80: TEXT, 1, "medium", 'm',
81: TEXT, 1, "small", 's',
82: TEXT, 1, "big", 'b',
83: TEXT, 1, "bigbig", 'B',
84: TEXT, 2, "c0", '0',
85: TEXT, 2, "c1", '1',
86: TEXT, 2, "c2", '2',
87: TEXT, 2, "c3", '3',
88: TEXT, 2, "c4", '4',
89: TEXT, 2, "c5", '5',
90: TEXT, 2, "c6", '6',
91: TEXT, 2, "c7", '7',
92: TEXT, 2, "black", '0',
93: TEXT, 2, "red", '1',
94: TEXT, 2, "green", '2',
95: TEXT, 2, "yellow", '3',
96: TEXT, 2, "blue", '4',
97: TEXT, 2, "magenta", '5',
98: TEXT, 2, "cyan", '6',
99: TEXT, 2, "white", '7',
100: LINE, 0, "solid", 's',
101: LINE, 0, "fat", 'f',
102: LINE, 0, "fatfat", 'F',
103: LINE, 0, "dotted", 'o',
104: LINE, 0, "dashed", 'a',
105: LINE, 1, "-", '-',
106: LINE, 1, "->", '>',
107: LINE, 1, "<-", '<',
108: LINE, 1, "<->", 'x',
109: LINE, 2, "c0", '0',
110: LINE, 2, "c1", '1',
111: LINE, 2, "c2", '2',
112: LINE, 2, "c3", '3',
113: LINE, 2, "c4", '4',
114: LINE, 2, "c5", '5',
115: LINE, 2, "c6", '6',
116: LINE, 2, "c7", '7',
117: LINE, 2, "black", '0',
118: LINE, 2, "red", '1',
119: LINE, 2, "green", '2',
120: LINE, 2, "yellow", '3',
121: LINE, 2, "blue", '4',
122: LINE, 2, "magenta", '5',
123: LINE, 2, "cyan", '6',
124: LINE, 2, "white", '7',
125: BOX, 0, "nofill", 'n',
126: BOX, 0, "fill", 'f',
127: BOX, 1, "c0", '0',
128: BOX, 1, "c1", '1',
129: BOX, 1, "c2", '2',
130: BOX, 1, "c3", '3',
131: BOX, 1, "c4", '4',
132: BOX, 1, "c5", '5',
133: BOX, 1, "c6", '6',
134: BOX, 1, "c7", '7',
135: BOX, 1, "black", '0',
136: BOX, 1, "red", '1',
137: BOX, 1, "green", '2',
138: BOX, 1, "yellow", '3',
139: BOX, 1, "blue", '4',
140: BOX, 1, "magenta", '5',
141: BOX, 1, "cyan", '6',
142: BOX, 1, "white", '7',
143: CIRCLE, 0, "nofill", 'n',
144: CIRCLE, 0, "fill", 'f',
145: CIRCLE, 1, "c0", '0',
146: CIRCLE, 1, "c1", '1',
147: CIRCLE, 1, "c2", '2',
148: CIRCLE, 1, "c3", '3',
149: CIRCLE, 1, "c4", '4',
150: CIRCLE, 1, "c5", '5',
151: CIRCLE, 1, "c6", '6',
152: CIRCLE, 1, "c7", '7',
153: CIRCLE, 1, "black", '0',
154: CIRCLE, 1, "red", '1',
155: CIRCLE, 1, "green", '2',
156: CIRCLE, 1, "yellow", '3',
157: CIRCLE, 1, "blue", '4',
158: CIRCLE, 1, "magenta", '5',
159: CIRCLE, 1, "cyan", '6',
160: CIRCLE, 1, "white", '7'
161: };
162: int geooptcnt = (sizeof(geooptarr) / sizeof(struct Geoelmt));
163:
164: /* VARIABLES FOR LEXICAL ANALYSIS */
165: char buf[MAXBUF];
166: int lexsaweof = 0;
167:
168: /* UTILITY VARIABLES */
169: char *NULLSTR = "";
170: char *cmdname;
171: int lineno, outlineno;
172: char *tempfname;
173: FILE *infp, *tempfp;
174:
175: extern double atof();
176: #define STOF(s) ((float) atof(s))
177:
178: main(argc, argv)
179: char *argv[];
180: {
181: register int i;
182:
183: cmdname = argv[0];
184: while (argc > 1 && argv[1][0] == '-') {
185: switch (argv[1][1]) {
186: case 'l':
187: linemax = atoi(&argv[1][2]);
188: break;
189: case 's':
190: slotmax = atoi(&argv[1][2]);
191: break;
192: }
193: argc--;
194: argv++;
195: }
196: if (argc == 1)
197: infp = stdin;
198: else {
199: if ((infp = fopen(argv[1], "r")) == NULL)
200: error(FATAL, "can't open input file");
201: }
202: linevec = emalloc(linemax);
203: for (i = 0; i < linemax; i++)
204: linevec[i] = 0;
205: tempfname = "/tmp/dev.XXXXXX";
206: mktemp(tempfname);
207: /* DEBUG tempfname = "djunk"; */
208: if ((tempfp = fopen(tempfname, "w")) == NULL)
209: error(FATAL, "can't open temp file");
210: pass1();
211: fclose(tempfp);
212: if ((tempfp = fopen(tempfname, "r")) == NULL)
213: error(FATAL, "can't open temp file");
214: pass2();
215: unlink(tempfname); /* DEBUG */
216: }
217:
218: pass1()
219: {
220: int currentview; /* view number */
221: int erased[MAXVIEWS]; /* last line erased */
222: int badlabel; /* 1 if label, 0 if geom */
223: char savelabel[MAXSTR]; /* label */
224: int geomalready = 0; /* seen any geometry yet? */
225: struct Symbol *sp;
226: int i;
227:
228: #define DOGEOM badlabel = 0;\
229: geomalready = 1;\
230: linevec[outlineno] = currentview;
231:
232: #define DOERASE(L) linevec[(L)] = ERASED;\
233: linevec[outlineno] = NOTGEOM;\
234: fprintf(tempfp, "e\t%d\n", (L));\
235: outlineno++;
236:
237: /* init */
238: currentview = 0;
239: for (i = 0; i < MAXVIEWS; i++)
240: erased[i] = 0;
241: opensymtab();
242:
243: /* read and process file */
244: lineno = 0;
245: outlineno = 1;
246: while (moreinput(infp)) {
247: if (++lineno > linemax)
248: error(FATAL, "too many input lines");
249: /* fprintf(stderr, "STARTING TO PROCESS INPUT LINE %d\n",
250: lineno); */
251: linevec[outlineno] = NOTGEOM;
252: lex(infp);
253: if (buf[0] == '#') {
254: gobble2(infp);
255: continue;
256: }
257: badlabel = 0;
258: if (buf[strlen(buf)-1] == ':') {
259: buf[strlen(buf)-1] = '\0';
260: badlabel = 1;
261: strcpy(savelabel, buf);
262: sp = lookup(buf, currentview);
263: if (sp != NULL) {
264: if (linevec[sp->outnum] == currentview) {
265: DOERASE(sp->outnum)
266: }
267: sp->outnum = outlineno;
268: } else {
269: insert(buf, currentview, outlineno);
270: }
271: lex(infp);
272: }
273: if (eq(buf, "text")) {
274: DOGEOM
275: getoptions(TEXT);
276: fprintf(tempfp, "g\t0\tt\t%d\t%s",
277: currentview, optstring);
278: dox(currentview);
279: lex(infp);
280: doy(currentview);
281: lexstr(infp);
282: fprintf(tempfp, "\t%s\n", buf);
283: outlineno++;
284: } else if (eq(buf, "circle")) {
285: float savex, rad;
286: DOGEOM
287: getoptions(CIRCLE);
288: fprintf(tempfp, "g\t0\tc\t%d\t%s",
289: currentview, optstring);
290: dox(currentview);
291: savex = STOF(buf);
292: lex(infp);
293: doy(currentview);
294: lex(infp);
295: if (!strisnum(buf)) {
296: error(WARN, "radius not a number");
297: strcpy(buf, "0");
298: }
299: rad = STOF(buf);
300: if (rad < 0.0)
301: error(WARN, "radius is negative");
302: recordx(currentview, savex-rad);
303: recordx(currentview, savex+rad);
304: fprintf(tempfp, "\t%s\n", buf);
305: outlineno++;
306: gobble(infp);
307: } else if (eq(buf, "line") || eq(buf, "box")) {
308: char cmdchar;
309: DOGEOM
310: if (eq(buf, "line")) {
311: getoptions(LINE);
312: cmdchar = 'l';
313: } else {
314: getoptions(BOX);
315: cmdchar = 'b';
316: }
317: fprintf(tempfp, "g\t0\t%c\t%d\t%s",
318: cmdchar, currentview, optstring);
319: dox(currentview);
320: lex(infp);
321: doy(currentview);
322: lex(infp);
323: dox(currentview);
324: lex(infp);
325: doy(currentview);
326: fprintf(tempfp, "\n");
327: outlineno++;
328: gobble(infp);
329: } else if (eq(buf, "view")) {
330: lex(infp);
331: if (eq(buf,NULLSTR)) {
332: error(WARN, "no name in view statement");
333: strcpy(buf, "def.view");
334: }
335: if (viewcnt == 0 && geomalready)
336: error(WARN, "first view after geom");
337: for (i = 0; i < viewcnt; i++)
338: if (eq(buf, viewarr[i].name))
339: break;
340: if (i >= viewcnt) {
341: viewcnt++;
342: if (i >= MAXVIEWS)
343: error(FATAL, "too many views");
344: strcpy(viewarr[i].name, buf);
345: viewarr[i].initx = viewarr[i].inity = 0;
346: }
347: currentview = i;
348: gobble(infp);
349: } else if (eq(buf, "click")) {
350: lex(infp);
351: if (eq(buf,NULLSTR))
352: strcpy(buf, "def.click");
353: for (i = 0; i < clickcnt; i++)
354: if (eq(buf, clickname[i]))
355: break;
356: if (i >= clickcnt) {
357: clickcnt++;
358: if (i >= MAXCLICKS)
359: error(FATAL, "too many click names");
360: strcpy(clickname[i], buf);
361: }
362: fprintf(tempfp, "c\t%d\n", i);
363: outlineno++;
364: gobble(infp);
365: } else if (eq(buf, "erase")) {
366: lex(infp);
367: if (eq(buf,NULLSTR))
368: error(WARN, "no label in erase statement");
369: sp = lookup(buf, currentview);
370: if (sp != NULL) {
371: if (linevec[sp->outnum] == currentview) {
372: DOERASE(sp->outnum)
373: }
374: delete(buf, currentview);
375: } else {
376: error(WARN, "undefined label");
377: }
378: gobble(infp);
379: } else if (eq(buf, "clear")) {
380: int i, endline;
381: fprintf(tempfp, "b\ts\t%d\n", currentview);
382: endline = outlineno++;
383: for (i = erased[currentview]+1; i <= endline; i++) {
384: if (linevec[i] == currentview) {
385: DOERASE(i)
386: }
387: }
388: erased[currentview] = outlineno;
389: fprintf(tempfp, "b\te\t%d\n", currentview);
390: linevec[outlineno] = NOTGEOM;
391: outlineno++;
392: gobble(infp);
393: } else {
394: if (!eq(buf, NULLSTR))
395: error(WARN, "unrecognized command");
396: gobble(infp);
397: }
398: if (badlabel) {
399: error(WARN, "label on nongeometric object");
400: delete(savelabel, currentview);
401: }
402: }
403: /* tidy up */
404: lineno = 0;
405: closesymtab();
406: if (viewcnt == 0) {
407: viewcnt = 1;
408: strcpy(viewarr[0].name, "def.view");
409: }
410: }
411:
412:
413: pass2()
414: {
415: typedef struct Slot {
416: union {
417: int i;
418: char *p;
419: } v;
420: } Slot;
421: char cmd; /* first char on a line */
422: int tlineno; /* line number in temp file */
423: int slothead; /* ptr to free list within slots */
424: Slot *slotarr; /* init by malloc to slotmax elmts */
425: int i;
426: int c;
427: int v;
428: struct Viewelmt *vp;
429:
430: /* Init */
431: opensymtab();
432: slotarr = (Slot *) emalloc(slotmax * sizeof(Slot));
433: for (i = 1; i <= slotmax-2; i++)
434: slotarr[i].v.i = i+1;
435: slothead = 1;
436: /* Write header for output file */
437: for (i = 0; i < viewcnt; i++) {
438: vp = &viewarr[i];
439: printf("d\tv\t%d\t%s\t%g\t%g\t%g\t%g\n", i,
440: vp->name, vp->minx, vp->miny, vp->maxx, vp->maxy);
441: }
442: for (i = 0; i < clickcnt; i++)
443: printf("d\tc\t%d\t%s\n", i, clickname[i]);
444: printf("d\tp\te\n");
445: /* Calculate view factors used to scale */
446: for (v = 0; v < viewcnt; v++) {
447: vp = &viewarr[v];
448: if (vp->minx == vp->maxx) {
449: vp->minx = 0.0;
450: vp->maxx = 2*vp->maxx;
451: if (vp->maxx == 0.0) {
452: vp->minx = -1.0;
453: vp->maxx = 1.0;
454: }
455: }
456: vp->factorx = SCALE / (vp->maxx-vp->minx);
457: if (vp->miny == vp->maxy) {
458: vp->miny = 0.0;
459: vp->maxy = 2*vp->maxy;
460: if (vp->maxy == 0.0) {
461: vp->miny = -1.0;
462: vp->maxy = 1.0;
463: }
464: }
465: vp->factory = SCALE / (vp->maxy-vp->miny);
466: }
467: /* Read and process intermediate file */
468: tlineno = 0;
469: while ((c = getc(tempfp)) != EOF) {
470: tlineno++;
471: cmd = c;
472: getc(tempfp); /* gobble tab */
473: putchar(cmd);
474: putchar('\t');
475: if (cmd == 'g') {
476: int snum, vnum;
477: char gcmd;
478: char opts[OPTMAX];
479: float x1, y1, x2, y2;
480: int i1, j1, i2, j2;
481: char bufa[MAXBUF+100];
482: /* fscanf(tempfp, "%d %c %d", &snum, &gcmd, &vnum); */
483: getc(tempfp); /* don't need snum -- always zero */
484: getc(tempfp); /* gobble tab */
485: gcmd = getc(tempfp);
486: getc(tempfp); /* gobble tab */
487: vnum = getc(tempfp) - '0';
488: fscanf(tempfp, "%s %f %f", opts, &x1, &y1);
489: if (linevec[tlineno] != ERASED)
490: snum = 0;
491: else {
492: snum = slothead;
493: slothead = slotarr[snum].v.i;
494: if (slothead == 0)
495: error(FATAL, "ran out of slots");
496: }
497: insert(NULLSTR, tlineno, snum);
498: i1 = scalex(vnum, x1);
499: j1 = scaley(vnum, y1);
500: if (gcmd == 'b' || gcmd == 'l') {
501: fscanf(tempfp, "%f %f", &x2, &y2);
502: if (getc(tempfp) != '\n')
503: error(FATAL, "develop bug: missing newline");
504: i2 = scalex(vnum, x2);
505: j2 = scaley(vnum, y2);
506: if (gcmd == 'b') {
507: int t; /* normalize: min, max */
508: if (i1 > i2) { t=i1; i1=i2; i2=t; }
509: if (j1 > j2) { t=j1; j1=j2; j2=t; }
510: }
511: sprintf(bufa, "%d\t%c\t%d\t%s\t%d\t%d\t%d\t%d",
512: snum, gcmd, vnum, opts, i1, j1, i2, j2);
513: } else if (gcmd == 'c') {
514: fscanf(tempfp, "%f", &x2);
515: if (getc(tempfp) != '\n')
516: error(FATAL, "develop bug: missing newline");
517: i2 = scalex(vnum, x1+x2) - i1;
518: if (i2 < 0)
519: i2 = -i2;
520: if (i2 == 0)
521: i2 = 1;
522: sprintf(bufa, "%d\t%c\t%d\t%s\t%d\t%d\t%d",
523: snum, gcmd, vnum, opts, i1, j1, i2);
524: } else if (gcmd == 't') {
525: getc(tempfp); /* gobble tab */
526: lexrest(tempfp);
527: sprintf(bufa, "%d\t%c\t%d\t%s\t%d\t%d\t%s",
528: snum, gcmd, vnum, opts, i1, j1, buf);
529: } else error(FATAL, "develop bug: invalid g cmd");
530: slotarr[snum].v.p = emalloc(strlen(bufa)+1);
531: strcpy(slotarr[snum].v.p, bufa);
532: puts(bufa);
533: } else if (cmd == 'e') {
534: int linenum, slotnum;
535: Symbol *sp;
536: fscanf(tempfp, "%d", &linenum);
537: if (getc(tempfp) != '\n')
538: error(FATAL, "develop bug: missing newline");
539: sp = lookup(NULLSTR, linenum);
540: if (sp == NULL)
541: error(FATAL, "develop bug: bad erase lookup");
542: slotnum = sp->outnum;
543: puts(slotarr[slotnum].v.p);
544: efree(slotarr[slotnum].v.p);
545: slotarr[slotnum].v.i = slothead;
546: slothead = slotnum;
547: delete(NULLSTR, linenum);
548: } else {
549: lexrest(tempfp);
550: puts(buf);
551: }
552: }
553: /* tidy up */
554: /* closesymtab(); delete stuff in slots? */
555: }
556:
557: recordx(vnum, t)
558: int vnum;
559: float t;
560: {
561: struct Viewelmt *vp;
562:
563: vp = &viewarr[vnum];
564: if (vp->initx != 1) {
565: vp->initx = 1;
566: vp->minx = t;
567: vp->maxx = t;
568: } else {
569: if (t < vp->minx)
570: vp->minx = t;
571: if (t > vp->maxx)
572: vp->maxx = t;
573: }
574: }
575:
576: recordy(vnum, t)
577: int vnum;
578: float t;
579: {
580: struct Viewelmt *vp;
581:
582: vp = &viewarr[vnum];
583: if (vp->inity != 1) {
584: vp->inity = 1;
585: vp->miny = t;
586: vp->maxy = t;
587: } else {
588: if (t < vp->miny)
589: vp->miny = t;
590: if (t > vp->maxy)
591: vp->maxy = t;
592: }
593: }
594:
595: int scalex(vnum, t)
596: int vnum;
597: float t;
598: {
599: struct Viewelmt *vp;
600:
601: vp = &viewarr[vnum];
602: return (int) ((t - vp->minx) * vp->factorx);
603: }
604:
605: int scaley(vnum, t)
606: int vnum;
607: float t;
608: {
609: struct Viewelmt *vp;
610:
611: vp = &viewarr[vnum];
612: return (int) ((t - vp->miny) * vp->factory);
613: }
614:
615: getoptions(cmdtype) /* put options into optstring */
616: int cmdtype;
617: {
618: int i;
619: struct Geoelmt *gp;
620:
621: strcpy(optstring, defaulttab[cmdtype]);
622: for (lex(infp); !eq(buf,NULLSTR) && !strisnum(buf); lex(infp)) {
623: for (i = 0; i < geooptcnt; i++) {
624: gp = &geooptarr[i];
625: if (cmdtype == gp->cmd && eq(buf, gp->name))
626: break;
627: }
628: if (i < geooptcnt)
629: optstring[gp->pos] = gp -> val;
630: else
631: error(WARN, "unrecognized option");
632: }
633: }
634:
635: dox(view) /* handle x in input file */
636: int view;
637: {
638: if (!strisnum(buf)) {
639: error(WARN, "x value not a number");
640: strcpy(buf, "0");
641: }
642: recordx(view, STOF(buf));
643: fprintf(tempfp, "\t%s", buf);
644: }
645:
646: doy(view) /* handle y in input file */
647: int view;
648: {
649: if (!strisnum(buf)) {
650: error(WARN, "y value not a number");
651: strcpy(buf, "0");
652: }
653: recordy(view, STOF(buf));
654: fprintf(tempfp, "\t%s", buf);
655: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.