xref: /plan9/sys/src/cmd/pic/main.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include	<stdio.h>
2 #include	<signal.h>
3 #include	<stdlib.h>
4 #include	<string.h>
5 #include	"pic.h"
6 #include	"y.tab.h"
7 
8 obj	**objlist = 0;		/* store the elements here */
9 int	nobjlist = 0;		/* size of objlist array */
10 int	nobj	= 0;
11 
12 Attr	*attr;	/* attributes stored here as collected */
13 int	nattrlist = 0;
14 int	nattr	= 0;	/* number of entries in attr_list */
15 
16 Text	*text	= 0;	/* text strings stored here as collected */
17 int	ntextlist = 0;		/* size of text[] array */
18 int	ntext	= 0;
19 int	ntext1	= 0;	/* record ntext here on entry to each figure */
20 
21 double	curx	= 0;
22 double	cury	= 0;
23 
24 int	hvmode	= R_DIR;	/* R => join left to right, D => top to bottom, etc. */
25 
26 int	codegen	= 0;	/* 1=>output for this picture; 0=>no output */
27 int	PEseen	= 0;	/* 1=> PE seen during parsing */
28 
29 double	deltx	= 6;	/* max x value in output, for scaling */
30 double	delty	= 6;	/* max y value in output, for scaling */
31 int	dbg	= 0;
32 int	lineno	= 0;
33 char	*filename	= "-";
34 int	synerr	= 0;
35 int	anyerr	= 0;	/* becomes 1 if synerr ever 1 */
36 char	*cmdname;
37 
38 double	xmin	= 30000;	/* min values found in actual data */
39 double	ymin	= 30000;
40 double	xmax	= -30000;	/* max */
41 double	ymax	= -30000;
42 
43 char	*version = "version May 7, 1990";
44 
45 void	fpecatch(long);
46 void	getdata(void), setdefaults(void);
47 void	setfval(char *, double);
48 int	getpid(void);
49 
50 main(int argc, char *argv[])
51 {
52 	char buf[20];
53 
54 	signal(SIGFPE, fpecatch);
55 	cmdname = argv[0];
56 	while (argc > 1 && *argv[1] == '-') {
57 		switch (argv[1][1]) {
58 		case 'd':
59 			dbg = atoi(&argv[1][2]);
60 			if (dbg == 0)
61 				dbg = 1;
62 			fprintf(stderr, "%s\n", version);
63 			break;
64 		}
65 		argc--;
66 		argv++;
67 	}
68 	setdefaults();
69 	objlist = (obj **) grow((char *)objlist, "objlist", nobjlist += 1000, sizeof(obj *));
70 	text = (Text *) grow((char *)text, "text", ntextlist += 1000, sizeof(Text));
71 	attr = (Attr *) grow((char *)attr, "attr", nattrlist += 100, sizeof(Attr));
72 
73 	sprintf(buf, "/%d/", getpid());
74 	pushsrc(String, buf);
75 	definition("pid");
76 
77 	curfile = infile;
78 	pushsrc(File, curfile->fname);
79 	if (argc <= 1) {
80 		curfile->fin = stdin;
81 		curfile->fname = tostring("-");
82 		getdata();
83 	} else
84 		while (argc-- > 1) {
85 			if ((curfile->fin = fopen(*++argv, "r")) == NULL) {
86 				fprintf(stderr, "%s: can't open %s\n", cmdname, *argv);
87 				exit(1);
88 			}
89 			curfile->fname = tostring(*argv);
90 			getdata();
91 			fclose(curfile->fin);
92 			free(curfile->fname);
93 		}
94 	exit(anyerr);
95 }
96 
97 void fpecatch(long n)
98 {
99 	ERROR "floating point exception" FATAL;
100 }
101 
102 char *grow(char *ptr, char *name, int num, int size)	/* make array bigger */
103 {
104 	char *p;
105 
106 	if (ptr == NULL)
107 		p = malloc(num * size);
108 	else
109 		p = realloc(ptr, num * size);
110 	if (p == NULL)
111 		ERROR "can't grow %s to %d", name, num * size FATAL;
112 	return p;
113 }
114 
115 static struct {
116 	char *name;
117 	double val;
118 	short scalable;		/* 1 => adjust when "scale" changes */
119 } defaults[] ={
120 	"scale", SCALE, 1,
121 	"lineht", HT, 1,
122 	"linewid", HT, 1,
123 	"moveht", HT, 1,
124 	"movewid", HT, 1,
125 	"dashwid", HT10, 1,
126 	"boxht", HT, 1,
127 	"boxwid", WID, 1,
128 	"circlerad", HT2, 1,
129 	"arcrad", HT2, 1,
130 	"ellipseht", HT, 1,
131 	"ellipsewid", WID, 1,
132 	"arrowht", HT5, 1,
133 	"arrowwid", HT10, 1,
134 	"arrowhead", 2, 0,		/* arrowhead style */
135 	"textht", 0.0, 1,		/* 6 lines/inch is also a useful value */
136 	"textwid", 0.0, 1,
137 	"maxpsht", MAXHT, 0,
138 	"maxpswid", MAXWID, 0,
139 	"fillval", 0.3, 0,		/* gray value for filling boxes */
140 	NULL, 0, 0
141 };
142 
143 void setdefaults(void)	/* set default sizes for variables like boxht */
144 {
145 	int i;
146 	YYSTYPE v;
147 
148 	for (i = 0; defaults[i].name != NULL; i++) {
149 		v.f = defaults[i].val;
150 		makevar(tostring(defaults[i].name), VARNAME, v);
151 	}
152 }
153 
154 void resetvar(void)	/* reset variables listed */
155 {
156 	int i, j;
157 
158 	if (nattr == 0) {	/* none listed, so do all */
159 		setdefaults();
160 		return;
161 	}
162 	for (i = 0; i < nattr; i++) {
163 		for (j = 0; defaults[j].name != NULL; j++)
164 			if (strcmp(defaults[j].name, attr[i].a_val.p) == 0) {
165 				setfval(defaults[j].name, defaults[j].val);
166 				free(attr[i].a_val.p);
167 				break;
168 			}
169 	}
170 }
171 
172 void checkscale(char *s)	/* if s is "scale", adjust default variables */
173 {
174 	int i;
175 	double scale;
176 
177 	if (strcmp(s, "scale") == 0) {
178 		scale = getfval("scale");
179 		for (i = 1; defaults[i].name != NULL; i++)
180 			if (defaults[i].scalable)
181 				setfval(defaults[i].name, defaults[i].val * scale);
182 	}
183 }
184 
185 void getdata(void)
186 {
187 	char *p, buf[1000], buf1[100];
188 	int ln;
189 	void reset(void), openpl(char *), closepl(int), print(void);
190 	int yyparse(void);
191 
192 	curfile->lineno = 0;
193 	printlf(1, curfile->fname);
194 	while (fgets(buf, sizeof buf, curfile->fin) != NULL) {
195 		curfile->lineno++;
196 		if (*buf == '.' && *(buf+1) == 'P' && *(buf+2) == 'S') {
197 			for (p = &buf[3]; *p == ' '; p++)
198 				;
199 			if (*p++ == '<') {
200 				Infile svfile;
201 				svfile = *curfile;
202 				sscanf(p, "%s", buf1);
203 				if ((curfile->fin=fopen(buf1, "r")) == NULL)
204 					ERROR "can't open %s", buf1 FATAL;
205 				curfile->fname = tostring(buf1);
206 				getdata();
207 				fclose(curfile->fin);
208 				free(curfile->fname);
209 				*curfile = svfile;
210 				printlf(curfile->lineno, curfile->fname);
211 				continue;
212 			}
213 			reset();
214 			yyparse();
215 			anyerr += synerr;
216 			/* yylval.i now contains 'E' or 'F' from .PE or .PF */
217 
218 			deltx = (xmax - xmin) / getfval("scale");
219 			delty = (ymax - ymin) / getfval("scale");
220 			if (buf[3] == ' ') {	/* next things are wid & ht */
221 				if (sscanf(&buf[4],"%lf %lf", &deltx, &delty) < 2)
222 					delty = deltx * (ymax-ymin) / (xmax-xmin);
223 				/* else {
224 				/*	double xfac, yfac; */
225 				/*	xfac = deltx / (xmax-xmin);
226 				/*	yfac = delty / (ymax-ymin);
227 				/*	if (xfac <= yfac)
228 				/*		delty = xfac * (ymax-ymin);
229 				/*	else
230 				/*		deltx = yfac * (xmax-xmin);
231 				/*}
232 				*/
233 			}
234 			dprintf("deltx = %g, delty = %g\n", deltx, delty);
235 			if (codegen && !synerr) {
236 				openpl(&buf[3]);	/* puts out .PS, with ht & wid stuck in */
237 				printlf(curfile->lineno+1, NULL);
238 				print();	/* assumes \n at end */
239 				closepl(yylval.i);	/* does the .PE/F */
240 			}
241 			printlf(curfile->lineno+1, NULL);
242 			fflush(stdout);
243 		} else if (buf[0] == '.' && buf[1] == 'l' && buf[2] == 'f') {
244 			if (sscanf(buf+3, "%d %s", &ln, buf1) == 2) {
245 				free(curfile->fname);
246 				printlf(curfile->lineno = ln, curfile->fname = tostring(buf1));
247 			} else
248 				printlf(curfile->lineno = ln, NULL);
249 		} else
250 			fputs(buf, stdout);
251 	}
252 }
253 
254 void reset(void)
255 {
256 	obj *op;
257 	int i;
258 	extern int nstack;
259 	extern	void freesymtab(struct symtab *);
260 
261 	for (i = 0; i < nobj; i++) {
262 		op = objlist[i];
263 		if (op->o_type == BLOCK)
264 			freesymtab(op->o_symtab);
265 		free((char *)objlist[i]);
266 	}
267 	nobj = 0;
268 	nattr = 0;
269 	for (i = 0; i < ntext; i++)
270 		if (text[i].t_val)
271 			free(text[i].t_val);
272 	ntext = ntext1 = 0;
273 	codegen = synerr = 0;
274 	nstack = 0;
275 	curx = cury = 0;
276 	PEseen = 0;
277 	hvmode = R_DIR;
278 	xmin = ymin = 30000;
279 	xmax = ymax = -30000;
280 }
281