xref: /plan9/sys/src/cmd/pic/main.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
13e12c5d1SDavid du Colombier #include	<stdio.h>
23e12c5d1SDavid du Colombier #include	<signal.h>
33e12c5d1SDavid du Colombier #include	<stdlib.h>
43e12c5d1SDavid du Colombier #include	<string.h>
53e12c5d1SDavid du Colombier #include	"pic.h"
63e12c5d1SDavid du Colombier #include	"y.tab.h"
73e12c5d1SDavid du Colombier 
8*7dd7cddfSDavid du Colombier char	*version = "version July 5, 1993";
9*7dd7cddfSDavid du Colombier 
103e12c5d1SDavid du Colombier obj	**objlist = 0;		/* store the elements here */
113e12c5d1SDavid du Colombier int	nobjlist = 0;		/* size of objlist array */
123e12c5d1SDavid du Colombier int	nobj	= 0;
133e12c5d1SDavid du Colombier 
143e12c5d1SDavid du Colombier Attr	*attr;	/* attributes stored here as collected */
153e12c5d1SDavid du Colombier int	nattrlist = 0;
163e12c5d1SDavid du Colombier int	nattr	= 0;	/* number of entries in attr_list */
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier Text	*text	= 0;	/* text strings stored here as collected */
193e12c5d1SDavid du Colombier int	ntextlist = 0;		/* size of text[] array */
203e12c5d1SDavid du Colombier int	ntext	= 0;
213e12c5d1SDavid du Colombier int	ntext1	= 0;	/* record ntext here on entry to each figure */
223e12c5d1SDavid du Colombier 
233e12c5d1SDavid du Colombier double	curx	= 0;
243e12c5d1SDavid du Colombier double	cury	= 0;
253e12c5d1SDavid du Colombier 
263e12c5d1SDavid du Colombier int	hvmode	= R_DIR;	/* R => join left to right, D => top to bottom, etc. */
273e12c5d1SDavid du Colombier 
283e12c5d1SDavid du Colombier int	codegen	= 0;	/* 1=>output for this picture; 0=>no output */
29*7dd7cddfSDavid du Colombier char	*PEstring;	/* "PS" or "PE" picked up by lexer */
303e12c5d1SDavid du Colombier 
313e12c5d1SDavid du Colombier double	deltx	= 6;	/* max x value in output, for scaling */
323e12c5d1SDavid du Colombier double	delty	= 6;	/* max y value in output, for scaling */
333e12c5d1SDavid du Colombier int	dbg	= 0;
343e12c5d1SDavid du Colombier int	lineno	= 0;
353e12c5d1SDavid du Colombier char	*filename	= "-";
363e12c5d1SDavid du Colombier int	synerr	= 0;
373e12c5d1SDavid du Colombier int	anyerr	= 0;	/* becomes 1 if synerr ever 1 */
383e12c5d1SDavid du Colombier char	*cmdname;
393e12c5d1SDavid du Colombier 
403e12c5d1SDavid du Colombier double	xmin	= 30000;	/* min values found in actual data */
413e12c5d1SDavid du Colombier double	ymin	= 30000;
423e12c5d1SDavid du Colombier double	xmax	= -30000;	/* max */
433e12c5d1SDavid du Colombier double	ymax	= -30000;
443e12c5d1SDavid du Colombier 
45*7dd7cddfSDavid du Colombier void	fpecatch(int);
463e12c5d1SDavid du Colombier void	getdata(void), setdefaults(void);
473e12c5d1SDavid du Colombier void	setfval(char *, double);
483e12c5d1SDavid du Colombier int	getpid(void);
493e12c5d1SDavid du Colombier 
main(int argc,char * argv[])503e12c5d1SDavid du Colombier main(int argc, char *argv[])
513e12c5d1SDavid du Colombier {
523e12c5d1SDavid du Colombier 	char buf[20];
533e12c5d1SDavid du Colombier 
543e12c5d1SDavid du Colombier 	signal(SIGFPE, fpecatch);
553e12c5d1SDavid du Colombier 	cmdname = argv[0];
563e12c5d1SDavid du Colombier 	while (argc > 1 && *argv[1] == '-') {
573e12c5d1SDavid du Colombier 		switch (argv[1][1]) {
583e12c5d1SDavid du Colombier 		case 'd':
593e12c5d1SDavid du Colombier 			dbg = atoi(&argv[1][2]);
603e12c5d1SDavid du Colombier 			if (dbg == 0)
613e12c5d1SDavid du Colombier 				dbg = 1;
623e12c5d1SDavid du Colombier 			fprintf(stderr, "%s\n", version);
633e12c5d1SDavid du Colombier 			break;
64*7dd7cddfSDavid du Colombier 		case 'V':
65*7dd7cddfSDavid du Colombier 			fprintf(stderr, "%s\n", version);
66*7dd7cddfSDavid du Colombier 			return 0;
673e12c5d1SDavid du Colombier 		}
683e12c5d1SDavid du Colombier 		argc--;
693e12c5d1SDavid du Colombier 		argv++;
703e12c5d1SDavid du Colombier 	}
713e12c5d1SDavid du Colombier 	setdefaults();
723e12c5d1SDavid du Colombier 	objlist = (obj **) grow((char *)objlist, "objlist", nobjlist += 1000, sizeof(obj *));
733e12c5d1SDavid du Colombier 	text = (Text *) grow((char *)text, "text", ntextlist += 1000, sizeof(Text));
743e12c5d1SDavid du Colombier 	attr = (Attr *) grow((char *)attr, "attr", nattrlist += 100, sizeof(Attr));
753e12c5d1SDavid du Colombier 
763e12c5d1SDavid du Colombier 	sprintf(buf, "/%d/", getpid());
773e12c5d1SDavid du Colombier 	pushsrc(String, buf);
783e12c5d1SDavid du Colombier 	definition("pid");
793e12c5d1SDavid du Colombier 
803e12c5d1SDavid du Colombier 	curfile = infile;
813e12c5d1SDavid du Colombier 	pushsrc(File, curfile->fname);
823e12c5d1SDavid du Colombier 	if (argc <= 1) {
833e12c5d1SDavid du Colombier 		curfile->fin = stdin;
843e12c5d1SDavid du Colombier 		curfile->fname = tostring("-");
853e12c5d1SDavid du Colombier 		getdata();
863e12c5d1SDavid du Colombier 	} else
873e12c5d1SDavid du Colombier 		while (argc-- > 1) {
883e12c5d1SDavid du Colombier 			if ((curfile->fin = fopen(*++argv, "r")) == NULL) {
893e12c5d1SDavid du Colombier 				fprintf(stderr, "%s: can't open %s\n", cmdname, *argv);
903e12c5d1SDavid du Colombier 				exit(1);
913e12c5d1SDavid du Colombier 			}
923e12c5d1SDavid du Colombier 			curfile->fname = tostring(*argv);
933e12c5d1SDavid du Colombier 			getdata();
943e12c5d1SDavid du Colombier 			fclose(curfile->fin);
953e12c5d1SDavid du Colombier 			free(curfile->fname);
963e12c5d1SDavid du Colombier 		}
97*7dd7cddfSDavid du Colombier 	return anyerr;
983e12c5d1SDavid du Colombier }
993e12c5d1SDavid du Colombier 
fpecatch(int n)100*7dd7cddfSDavid du Colombier void fpecatch(int n)
1013e12c5d1SDavid du Colombier {
102*7dd7cddfSDavid du Colombier 	ERROR "floating point exception %d", n FATAL;
1033e12c5d1SDavid du Colombier }
1043e12c5d1SDavid du Colombier 
grow(char * ptr,char * name,int num,int size)1053e12c5d1SDavid du Colombier char *grow(char *ptr, char *name, int num, int size)	/* make array bigger */
1063e12c5d1SDavid du Colombier {
1073e12c5d1SDavid du Colombier 	char *p;
1083e12c5d1SDavid du Colombier 
1093e12c5d1SDavid du Colombier 	if (ptr == NULL)
1103e12c5d1SDavid du Colombier 		p = malloc(num * size);
1113e12c5d1SDavid du Colombier 	else
1123e12c5d1SDavid du Colombier 		p = realloc(ptr, num * size);
1133e12c5d1SDavid du Colombier 	if (p == NULL)
1143e12c5d1SDavid du Colombier 		ERROR "can't grow %s to %d", name, num * size FATAL;
1153e12c5d1SDavid du Colombier 	return p;
1163e12c5d1SDavid du Colombier }
1173e12c5d1SDavid du Colombier 
1183e12c5d1SDavid du Colombier static struct {
1193e12c5d1SDavid du Colombier 	char *name;
1203e12c5d1SDavid du Colombier 	double val;
1213e12c5d1SDavid du Colombier 	short scalable;		/* 1 => adjust when "scale" changes */
1223e12c5d1SDavid du Colombier } defaults[] ={
1233e12c5d1SDavid du Colombier 	"scale", SCALE, 1,
1243e12c5d1SDavid du Colombier 	"lineht", HT, 1,
1253e12c5d1SDavid du Colombier 	"linewid", HT, 1,
1263e12c5d1SDavid du Colombier 	"moveht", HT, 1,
1273e12c5d1SDavid du Colombier 	"movewid", HT, 1,
1283e12c5d1SDavid du Colombier 	"dashwid", HT10, 1,
1293e12c5d1SDavid du Colombier 	"boxht", HT, 1,
1303e12c5d1SDavid du Colombier 	"boxwid", WID, 1,
1313e12c5d1SDavid du Colombier 	"circlerad", HT2, 1,
1323e12c5d1SDavid du Colombier 	"arcrad", HT2, 1,
1333e12c5d1SDavid du Colombier 	"ellipseht", HT, 1,
1343e12c5d1SDavid du Colombier 	"ellipsewid", WID, 1,
1353e12c5d1SDavid du Colombier 	"arrowht", HT5, 1,
1363e12c5d1SDavid du Colombier 	"arrowwid", HT10, 1,
1373e12c5d1SDavid du Colombier 	"arrowhead", 2, 0,		/* arrowhead style */
1383e12c5d1SDavid du Colombier 	"textht", 0.0, 1,		/* 6 lines/inch is also a useful value */
1393e12c5d1SDavid du Colombier 	"textwid", 0.0, 1,
1403e12c5d1SDavid du Colombier 	"maxpsht", MAXHT, 0,
1413e12c5d1SDavid du Colombier 	"maxpswid", MAXWID, 0,
142*7dd7cddfSDavid du Colombier 	"fillval", 0.7, 0,		/* gray value for filling boxes */
1433e12c5d1SDavid du Colombier 	NULL, 0, 0
1443e12c5d1SDavid du Colombier };
1453e12c5d1SDavid du Colombier 
setdefaults(void)1463e12c5d1SDavid du Colombier void setdefaults(void)	/* set default sizes for variables like boxht */
1473e12c5d1SDavid du Colombier {
1483e12c5d1SDavid du Colombier 	int i;
1493e12c5d1SDavid du Colombier 	YYSTYPE v;
1503e12c5d1SDavid du Colombier 
1513e12c5d1SDavid du Colombier 	for (i = 0; defaults[i].name != NULL; i++) {
1523e12c5d1SDavid du Colombier 		v.f = defaults[i].val;
1533e12c5d1SDavid du Colombier 		makevar(tostring(defaults[i].name), VARNAME, v);
1543e12c5d1SDavid du Colombier 	}
1553e12c5d1SDavid du Colombier }
1563e12c5d1SDavid du Colombier 
resetvar(void)1573e12c5d1SDavid du Colombier void resetvar(void)	/* reset variables listed */
1583e12c5d1SDavid du Colombier {
1593e12c5d1SDavid du Colombier 	int i, j;
1603e12c5d1SDavid du Colombier 
1613e12c5d1SDavid du Colombier 	if (nattr == 0) {	/* none listed, so do all */
1623e12c5d1SDavid du Colombier 		setdefaults();
1633e12c5d1SDavid du Colombier 		return;
1643e12c5d1SDavid du Colombier 	}
1653e12c5d1SDavid du Colombier 	for (i = 0; i < nattr; i++) {
1663e12c5d1SDavid du Colombier 		for (j = 0; defaults[j].name != NULL; j++)
1673e12c5d1SDavid du Colombier 			if (strcmp(defaults[j].name, attr[i].a_val.p) == 0) {
1683e12c5d1SDavid du Colombier 				setfval(defaults[j].name, defaults[j].val);
1693e12c5d1SDavid du Colombier 				free(attr[i].a_val.p);
1703e12c5d1SDavid du Colombier 				break;
1713e12c5d1SDavid du Colombier 			}
1723e12c5d1SDavid du Colombier 	}
1733e12c5d1SDavid du Colombier }
1743e12c5d1SDavid du Colombier 
checkscale(char * s)1753e12c5d1SDavid du Colombier void checkscale(char *s)	/* if s is "scale", adjust default variables */
1763e12c5d1SDavid du Colombier {
1773e12c5d1SDavid du Colombier 	int i;
1783e12c5d1SDavid du Colombier 	double scale;
1793e12c5d1SDavid du Colombier 
1803e12c5d1SDavid du Colombier 	if (strcmp(s, "scale") == 0) {
1813e12c5d1SDavid du Colombier 		scale = getfval("scale");
1823e12c5d1SDavid du Colombier 		for (i = 1; defaults[i].name != NULL; i++)
1833e12c5d1SDavid du Colombier 			if (defaults[i].scalable)
1843e12c5d1SDavid du Colombier 				setfval(defaults[i].name, defaults[i].val * scale);
1853e12c5d1SDavid du Colombier 	}
1863e12c5d1SDavid du Colombier }
1873e12c5d1SDavid du Colombier 
getdata(void)1883e12c5d1SDavid du Colombier void getdata(void)
1893e12c5d1SDavid du Colombier {
1903e12c5d1SDavid du Colombier 	char *p, buf[1000], buf1[100];
1913e12c5d1SDavid du Colombier 	int ln;
192*7dd7cddfSDavid du Colombier 	void reset(void), openpl(char *), closepl(char *), print(void);
1933e12c5d1SDavid du Colombier 	int yyparse(void);
1943e12c5d1SDavid du Colombier 
1953e12c5d1SDavid du Colombier 	curfile->lineno = 0;
1963e12c5d1SDavid du Colombier 	printlf(1, curfile->fname);
1973e12c5d1SDavid du Colombier 	while (fgets(buf, sizeof buf, curfile->fin) != NULL) {
1983e12c5d1SDavid du Colombier 		curfile->lineno++;
1993e12c5d1SDavid du Colombier 		if (*buf == '.' && *(buf+1) == 'P' && *(buf+2) == 'S') {
2003e12c5d1SDavid du Colombier 			for (p = &buf[3]; *p == ' '; p++)
2013e12c5d1SDavid du Colombier 				;
2023e12c5d1SDavid du Colombier 			if (*p++ == '<') {
2033e12c5d1SDavid du Colombier 				Infile svfile;
2043e12c5d1SDavid du Colombier 				svfile = *curfile;
2053e12c5d1SDavid du Colombier 				sscanf(p, "%s", buf1);
2063e12c5d1SDavid du Colombier 				if ((curfile->fin=fopen(buf1, "r")) == NULL)
2073e12c5d1SDavid du Colombier 					ERROR "can't open %s", buf1 FATAL;
2083e12c5d1SDavid du Colombier 				curfile->fname = tostring(buf1);
2093e12c5d1SDavid du Colombier 				getdata();
2103e12c5d1SDavid du Colombier 				fclose(curfile->fin);
2113e12c5d1SDavid du Colombier 				free(curfile->fname);
2123e12c5d1SDavid du Colombier 				*curfile = svfile;
2133e12c5d1SDavid du Colombier 				printlf(curfile->lineno, curfile->fname);
2143e12c5d1SDavid du Colombier 				continue;
2153e12c5d1SDavid du Colombier 			}
2163e12c5d1SDavid du Colombier 			reset();
2173e12c5d1SDavid du Colombier 			yyparse();
2183e12c5d1SDavid du Colombier 			anyerr += synerr;
2193e12c5d1SDavid du Colombier 			deltx = (xmax - xmin) / getfval("scale");
2203e12c5d1SDavid du Colombier 			delty = (ymax - ymin) / getfval("scale");
2213e12c5d1SDavid du Colombier 			if (buf[3] == ' ') {	/* next things are wid & ht */
2223e12c5d1SDavid du Colombier 				if (sscanf(&buf[4],"%lf %lf", &deltx, &delty) < 2)
2233e12c5d1SDavid du Colombier 					delty = deltx * (ymax-ymin) / (xmax-xmin);
2243e12c5d1SDavid du Colombier 				/* else {
2253e12c5d1SDavid du Colombier 				/*	double xfac, yfac; */
2263e12c5d1SDavid du Colombier 				/*	xfac = deltx / (xmax-xmin);
2273e12c5d1SDavid du Colombier 				/*	yfac = delty / (ymax-ymin);
2283e12c5d1SDavid du Colombier 				/*	if (xfac <= yfac)
2293e12c5d1SDavid du Colombier 				/*		delty = xfac * (ymax-ymin);
2303e12c5d1SDavid du Colombier 				/*	else
2313e12c5d1SDavid du Colombier 				/*		deltx = yfac * (xmax-xmin);
2323e12c5d1SDavid du Colombier 				/*}
2333e12c5d1SDavid du Colombier 				*/
2343e12c5d1SDavid du Colombier 			}
2353e12c5d1SDavid du Colombier 			dprintf("deltx = %g, delty = %g\n", deltx, delty);
2363e12c5d1SDavid du Colombier 			if (codegen && !synerr) {
2373e12c5d1SDavid du Colombier 				openpl(&buf[3]);	/* puts out .PS, with ht & wid stuck in */
2383e12c5d1SDavid du Colombier 				printlf(curfile->lineno+1, NULL);
2393e12c5d1SDavid du Colombier 				print();	/* assumes \n at end */
240*7dd7cddfSDavid du Colombier 				closepl(PEstring);	/* does the .PE/F */
241*7dd7cddfSDavid du Colombier 				free(PEstring);
2423e12c5d1SDavid du Colombier 			}
2433e12c5d1SDavid du Colombier 			printlf(curfile->lineno+1, NULL);
2443e12c5d1SDavid du Colombier 			fflush(stdout);
2453e12c5d1SDavid du Colombier 		} else if (buf[0] == '.' && buf[1] == 'l' && buf[2] == 'f') {
2463e12c5d1SDavid du Colombier 			if (sscanf(buf+3, "%d %s", &ln, buf1) == 2) {
2473e12c5d1SDavid du Colombier 				free(curfile->fname);
2483e12c5d1SDavid du Colombier 				printlf(curfile->lineno = ln, curfile->fname = tostring(buf1));
2493e12c5d1SDavid du Colombier 			} else
2503e12c5d1SDavid du Colombier 				printlf(curfile->lineno = ln, NULL);
2513e12c5d1SDavid du Colombier 		} else
2523e12c5d1SDavid du Colombier 			fputs(buf, stdout);
2533e12c5d1SDavid du Colombier 	}
2543e12c5d1SDavid du Colombier }
2553e12c5d1SDavid du Colombier 
reset(void)2563e12c5d1SDavid du Colombier void reset(void)
2573e12c5d1SDavid du Colombier {
2583e12c5d1SDavid du Colombier 	obj *op;
2593e12c5d1SDavid du Colombier 	int i;
2603e12c5d1SDavid du Colombier 	extern int nstack;
2613e12c5d1SDavid du Colombier 	extern	void freesymtab(struct symtab *);
2623e12c5d1SDavid du Colombier 
2633e12c5d1SDavid du Colombier 	for (i = 0; i < nobj; i++) {
2643e12c5d1SDavid du Colombier 		op = objlist[i];
2653e12c5d1SDavid du Colombier 		if (op->o_type == BLOCK)
2663e12c5d1SDavid du Colombier 			freesymtab(op->o_symtab);
2673e12c5d1SDavid du Colombier 		free((char *)objlist[i]);
2683e12c5d1SDavid du Colombier 	}
2693e12c5d1SDavid du Colombier 	nobj = 0;
2703e12c5d1SDavid du Colombier 	nattr = 0;
2713e12c5d1SDavid du Colombier 	for (i = 0; i < ntext; i++)
2723e12c5d1SDavid du Colombier 		if (text[i].t_val)
2733e12c5d1SDavid du Colombier 			free(text[i].t_val);
2743e12c5d1SDavid du Colombier 	ntext = ntext1 = 0;
2753e12c5d1SDavid du Colombier 	codegen = synerr = 0;
2763e12c5d1SDavid du Colombier 	nstack = 0;
2773e12c5d1SDavid du Colombier 	curx = cury = 0;
278*7dd7cddfSDavid du Colombier 	PEstring = 0;
2793e12c5d1SDavid du Colombier 	hvmode = R_DIR;
2803e12c5d1SDavid du Colombier 	xmin = ymin = 30000;
2813e12c5d1SDavid du Colombier 	xmax = ymax = -30000;
2823e12c5d1SDavid du Colombier }
283