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