1*3e12c5d1SDavid du Colombier #include <stdio.h>
2*3e12c5d1SDavid du Colombier #include <stdlib.h>
3*3e12c5d1SDavid du Colombier #include <string.h>
4*3e12c5d1SDavid du Colombier #include <math.h>
5*3e12c5d1SDavid du Colombier #include <ctype.h>
6*3e12c5d1SDavid du Colombier #include "grap.h"
7*3e12c5d1SDavid du Colombier #include "y.tab.h"
8*3e12c5d1SDavid du Colombier
9*3e12c5d1SDavid du Colombier double margin = MARGIN; /* extra space around edges */
10*3e12c5d1SDavid du Colombier extern double frame_ht, frame_wid, ticklen;
11*3e12c5d1SDavid du Colombier extern int just, sizeop, tick_dir;
12*3e12c5d1SDavid du Colombier extern double sizexpr, lab_up, lab_rt;
13*3e12c5d1SDavid du Colombier
14*3e12c5d1SDavid du Colombier char graphname[50] = "Graph";
15*3e12c5d1SDavid du Colombier char graphpos[200] = "";
16*3e12c5d1SDavid du Colombier
print(void)17*3e12c5d1SDavid du Colombier void print(void) /* arrange final output */
18*3e12c5d1SDavid du Colombier {
19*3e12c5d1SDavid du Colombier FILE *fd;
20*3e12c5d1SDavid du Colombier Obj *p, *dfp;
21*3e12c5d1SDavid du Colombier int c;
22*3e12c5d1SDavid du Colombier double dx, dy, xfac, yfac;
23*3e12c5d1SDavid du Colombier
24*3e12c5d1SDavid du Colombier if (tfd != NULL) {
25*3e12c5d1SDavid du Colombier fclose(tfd); /* end the temp file */
26*3e12c5d1SDavid du Colombier tfd = stdout;
27*3e12c5d1SDavid du Colombier }
28*3e12c5d1SDavid du Colombier
29*3e12c5d1SDavid du Colombier if ((p=lookup("margin",0)) != NULL)
30*3e12c5d1SDavid du Colombier margin = p->fval;
31*3e12c5d1SDavid du Colombier if (frame_ht < 0) /* wasn't set explicitly, so use default */
32*3e12c5d1SDavid du Colombier frame_ht = getvar(lookup("frameht", 0));
33*3e12c5d1SDavid du Colombier if (frame_wid < 0)
34*3e12c5d1SDavid du Colombier frame_wid = getvar(lookup("framewid", 0));
35*3e12c5d1SDavid du Colombier dfp = NULL;
36*3e12c5d1SDavid du Colombier for (p = objlist; p; p = p->next) {
37*3e12c5d1SDavid du Colombier dprintf("print: name = <%s>, type = %d\n", p->name, p->type);
38*3e12c5d1SDavid du Colombier if (p->type == NAME) {
39*3e12c5d1SDavid du Colombier Point pt, pt1;
40*3e12c5d1SDavid du Colombier pt = p->pt;
41*3e12c5d1SDavid du Colombier pt1 = p->pt1;
42*3e12c5d1SDavid du Colombier fprintf(tfd, "\t# %s %g .. %g, %g .. %g\n",
43*3e12c5d1SDavid du Colombier p->name, pt.x, pt1.x, pt.y, pt1.y);
44*3e12c5d1SDavid du Colombier if (p->log & XFLAG) {
45*3e12c5d1SDavid du Colombier if (pt.x <= 0.0)
46*3e12c5d1SDavid du Colombier ERROR "can't take log of x coord %g", pt.x FATAL;
47*3e12c5d1SDavid du Colombier logit(pt.x);
48*3e12c5d1SDavid du Colombier logit(pt1.x);
49*3e12c5d1SDavid du Colombier }
50*3e12c5d1SDavid du Colombier if (p->log & YFLAG) {
51*3e12c5d1SDavid du Colombier if (pt.y <= 0.0)
52*3e12c5d1SDavid du Colombier ERROR "can't take log of y coord %g", pt.y FATAL;
53*3e12c5d1SDavid du Colombier logit(pt.y);
54*3e12c5d1SDavid du Colombier logit(pt1.y);
55*3e12c5d1SDavid du Colombier }
56*3e12c5d1SDavid du Colombier if (!(p->coord & XFLAG)) {
57*3e12c5d1SDavid du Colombier dx = pt1.x - pt.x;
58*3e12c5d1SDavid du Colombier pt.x -= margin * dx;
59*3e12c5d1SDavid du Colombier pt1.x += margin * dx;
60*3e12c5d1SDavid du Colombier }
61*3e12c5d1SDavid du Colombier if (!(p->coord & YFLAG)) {
62*3e12c5d1SDavid du Colombier dy = pt1.y - pt.y;
63*3e12c5d1SDavid du Colombier pt.y -= margin * dy;
64*3e12c5d1SDavid du Colombier pt1.y += margin * dy;
65*3e12c5d1SDavid du Colombier }
66*3e12c5d1SDavid du Colombier if (autoticks && strcmp(p->name, dflt_coord) == 0) {
67*3e12c5d1SDavid du Colombier p->pt = pt;
68*3e12c5d1SDavid du Colombier p->pt1 = pt1;
69*3e12c5d1SDavid du Colombier if (p->log & XFLAG) {
70*3e12c5d1SDavid du Colombier p->pt.x = pow(10.0, pt.x);
71*3e12c5d1SDavid du Colombier p->pt1.x = pow(10.0, pt1.x);
72*3e12c5d1SDavid du Colombier }
73*3e12c5d1SDavid du Colombier if (p->log & YFLAG) {
74*3e12c5d1SDavid du Colombier p->pt.y = pow(10.0, pt.y);
75*3e12c5d1SDavid du Colombier p->pt1.y = pow(10.0, pt1.y);
76*3e12c5d1SDavid du Colombier }
77*3e12c5d1SDavid du Colombier dfp = setauto();
78*3e12c5d1SDavid du Colombier }
79*3e12c5d1SDavid du Colombier dx = pt1.x - pt.x;
80*3e12c5d1SDavid du Colombier dy = pt1.y - pt.y;
81*3e12c5d1SDavid du Colombier xfac = dx > 0 ? frame_wid/dx : frame_wid/2;
82*3e12c5d1SDavid du Colombier yfac = dy > 0 ? frame_ht/dy : frame_ht/2;
83*3e12c5d1SDavid du Colombier
84*3e12c5d1SDavid du Colombier fprintf(tfd, "define xy_%s @ ", p->name);
85*3e12c5d1SDavid du Colombier if (dx > 0)
86*3e12c5d1SDavid du Colombier fprintf(tfd, "\t(($1)-(%g))*%g", pt.x, xfac);
87*3e12c5d1SDavid du Colombier else
88*3e12c5d1SDavid du Colombier fprintf(tfd, "\t%g", xfac);
89*3e12c5d1SDavid du Colombier if (dy > 0)
90*3e12c5d1SDavid du Colombier fprintf(tfd, ", (($2)-(%g))*%g @\n", pt.y, yfac);
91*3e12c5d1SDavid du Colombier else
92*3e12c5d1SDavid du Colombier fprintf(tfd, ", %g @\n", yfac);
93*3e12c5d1SDavid du Colombier fprintf(tfd, "define x_%s @ ", p->name);
94*3e12c5d1SDavid du Colombier if (dx > 0)
95*3e12c5d1SDavid du Colombier fprintf(tfd, "\t(($1)-(%g))*%g @\n", pt.x, xfac);
96*3e12c5d1SDavid du Colombier else
97*3e12c5d1SDavid du Colombier fprintf(tfd, "\t%g @\n", xfac);
98*3e12c5d1SDavid du Colombier fprintf(tfd, "define y_%s @ ", p->name);
99*3e12c5d1SDavid du Colombier if (dy > 0)
100*3e12c5d1SDavid du Colombier fprintf(tfd, "\t(($1)-(%g))*%g @\n", pt.y, yfac);
101*3e12c5d1SDavid du Colombier else
102*3e12c5d1SDavid du Colombier fprintf(tfd, "\t%g @\n", yfac);
103*3e12c5d1SDavid du Colombier }
104*3e12c5d1SDavid du Colombier }
105*3e12c5d1SDavid du Colombier if (codegen)
106*3e12c5d1SDavid du Colombier frame();
107*3e12c5d1SDavid du Colombier if (codegen && autoticks && dfp)
108*3e12c5d1SDavid du Colombier do_autoticks(dfp);
109*3e12c5d1SDavid du Colombier
110*3e12c5d1SDavid du Colombier if ((fd = fopen(tempfile, "r")) != NULL) {
111*3e12c5d1SDavid du Colombier while ((c = getc(fd)) != EOF)
112*3e12c5d1SDavid du Colombier putc(c, tfd);
113*3e12c5d1SDavid du Colombier fclose(fd);
114*3e12c5d1SDavid du Colombier }
115*3e12c5d1SDavid du Colombier tfd = NULL;
116*3e12c5d1SDavid du Colombier }
117*3e12c5d1SDavid du Colombier
endstat(void)118*3e12c5d1SDavid du Colombier void endstat(void) /* clean up after each statement */
119*3e12c5d1SDavid du Colombier {
120*3e12c5d1SDavid du Colombier
121*3e12c5d1SDavid du Colombier just = sizeop = 0;
122*3e12c5d1SDavid du Colombier lab_up = lab_rt = 0.0;
123*3e12c5d1SDavid du Colombier sizexpr = 0.0;
124*3e12c5d1SDavid du Colombier nnum = 0;
125*3e12c5d1SDavid du Colombier ntick = 0;
126*3e12c5d1SDavid du Colombier tside = 0;
127*3e12c5d1SDavid du Colombier tick_dir = OUT;
128*3e12c5d1SDavid du Colombier ticklen = TICKLEN;
129*3e12c5d1SDavid du Colombier }
130*3e12c5d1SDavid du Colombier
graph(char * s)131*3e12c5d1SDavid du Colombier void graph(char *s) /* graph statement */
132*3e12c5d1SDavid du Colombier {
133*3e12c5d1SDavid du Colombier char *p, *os;
134*3e12c5d1SDavid du Colombier int c;
135*3e12c5d1SDavid du Colombier
136*3e12c5d1SDavid du Colombier if (codegen) {
137*3e12c5d1SDavid du Colombier fprintf(stdout, "%s: [\n", graphname);
138*3e12c5d1SDavid du Colombier print(); /* pump out previous graph */
139*3e12c5d1SDavid du Colombier fprintf(stdout, "\n] %s\n", graphpos);
140*3e12c5d1SDavid du Colombier reset();
141*3e12c5d1SDavid du Colombier }
142*3e12c5d1SDavid du Colombier if (s) {
143*3e12c5d1SDavid du Colombier dprintf("into graph with <%s>\n", s);
144*3e12c5d1SDavid du Colombier opentemp();
145*3e12c5d1SDavid du Colombier os = s;
146*3e12c5d1SDavid du Colombier while ((c = *s) == ' ' || c == '\t')
147*3e12c5d1SDavid du Colombier s++;
148*3e12c5d1SDavid du Colombier if (c == '\0')
149*3e12c5d1SDavid du Colombier ERROR "no name on graph statement" WARNING;
150*3e12c5d1SDavid du Colombier if (!isupper(s[0]))
151*3e12c5d1SDavid du Colombier ERROR "graph name %s must be capitalized", s WARNING;
152*3e12c5d1SDavid du Colombier for (p=graphname; (c = *s) != ' ' && c != '\t' && c != '\0'; )
153*3e12c5d1SDavid du Colombier *p++ = *s++;
154*3e12c5d1SDavid du Colombier *p = '\0';
155*3e12c5d1SDavid du Colombier strcpy(graphpos, s);
156*3e12c5d1SDavid du Colombier dprintf("graphname = <%s>, graphpos = <%s>\n", graphname, graphpos);
157*3e12c5d1SDavid du Colombier free(os);
158*3e12c5d1SDavid du Colombier }
159*3e12c5d1SDavid du Colombier }
160*3e12c5d1SDavid du Colombier
setup(void)161*3e12c5d1SDavid du Colombier void setup(void) /* done at each .G1 */
162*3e12c5d1SDavid du Colombier {
163*3e12c5d1SDavid du Colombier static int firstG1 = 0;
164*3e12c5d1SDavid du Colombier
165*3e12c5d1SDavid du Colombier reset();
166*3e12c5d1SDavid du Colombier opentemp();
167*3e12c5d1SDavid du Colombier frame_ht = frame_wid = -1; /* reset in frame() */
168*3e12c5d1SDavid du Colombier ticklen = getvar(lookup("ticklen", 0));
169*3e12c5d1SDavid du Colombier if (firstG1++ == 0)
170*3e12c5d1SDavid du Colombier do_first();
171*3e12c5d1SDavid du Colombier codegen = synerr = 0;
172*3e12c5d1SDavid du Colombier strcpy(graphname, "Graph");
173*3e12c5d1SDavid du Colombier strcpy(graphpos, "");
174*3e12c5d1SDavid du Colombier }
175*3e12c5d1SDavid du Colombier
do_first(void)176*3e12c5d1SDavid du Colombier void do_first(void) /* done at first .G1: definitions, etc. */
177*3e12c5d1SDavid du Colombier {
178*3e12c5d1SDavid du Colombier extern int lib;
179*3e12c5d1SDavid du Colombier extern char *lib_defines;
180*3e12c5d1SDavid du Colombier static char buf[50], buf1[50]; /* static because pbstr uses them */
181*3e12c5d1SDavid du Colombier FILE *fp;
182*3e12c5d1SDavid du Colombier extern int getpid(void);
183*3e12c5d1SDavid du Colombier
184*3e12c5d1SDavid du Colombier sprintf(buf, "define pid /%d/\n", getpid());
185*3e12c5d1SDavid du Colombier pbstr(buf);
186*3e12c5d1SDavid du Colombier if (lib != 0) {
187*3e12c5d1SDavid du Colombier if ((fp = fopen(lib_defines, "r")) != NULL) {
188*3e12c5d1SDavid du Colombier sprintf(buf1, "copy \"%s\"\n", lib_defines);
189*3e12c5d1SDavid du Colombier pbstr(buf1);
190*3e12c5d1SDavid du Colombier fclose(fp);
191*3e12c5d1SDavid du Colombier } else {
192*3e12c5d1SDavid du Colombier fprintf(stderr, "grap warning: can't open %s\n", lib_defines);
193*3e12c5d1SDavid du Colombier }
194*3e12c5d1SDavid du Colombier }
195*3e12c5d1SDavid du Colombier }
196*3e12c5d1SDavid du Colombier
reset(void)197*3e12c5d1SDavid du Colombier void reset(void) /* done at each "graph ..." statement */
198*3e12c5d1SDavid du Colombier {
199*3e12c5d1SDavid du Colombier Obj *p, *np, *deflist;
200*3e12c5d1SDavid du Colombier extern int tlist, toffside, autodir;
201*3e12c5d1SDavid du Colombier
202*3e12c5d1SDavid du Colombier curr_coord = dflt_coord;
203*3e12c5d1SDavid du Colombier ncoord = auto_x = 0;
204*3e12c5d1SDavid du Colombier autoticks = LEFT|BOT;
205*3e12c5d1SDavid du Colombier autodir = 0;
206*3e12c5d1SDavid du Colombier tside = tlist = toffside = 0;
207*3e12c5d1SDavid du Colombier tick_dir = OUT;
208*3e12c5d1SDavid du Colombier margin = MARGIN;
209*3e12c5d1SDavid du Colombier deflist = NULL;
210*3e12c5d1SDavid du Colombier for (p = objlist; p; p = np) {
211*3e12c5d1SDavid du Colombier np = p->next;
212*3e12c5d1SDavid du Colombier if (p->type == DEFNAME || p->type == VARNAME) {
213*3e12c5d1SDavid du Colombier p->next = deflist;
214*3e12c5d1SDavid du Colombier deflist = p;
215*3e12c5d1SDavid du Colombier } else {
216*3e12c5d1SDavid du Colombier free(p->name);
217*3e12c5d1SDavid du Colombier freeattr(p->attr);
218*3e12c5d1SDavid du Colombier free((char *) p);
219*3e12c5d1SDavid du Colombier }
220*3e12c5d1SDavid du Colombier }
221*3e12c5d1SDavid du Colombier objlist = deflist;
222*3e12c5d1SDavid du Colombier }
223*3e12c5d1SDavid du Colombier
opentemp(void)224*3e12c5d1SDavid du Colombier void opentemp(void)
225*3e12c5d1SDavid du Colombier {
226*3e12c5d1SDavid du Colombier if (tfd != stdout) {
227*3e12c5d1SDavid du Colombier if (tfd != NULL)
228*3e12c5d1SDavid du Colombier fclose(tfd);
229*3e12c5d1SDavid du Colombier if ((tfd = fopen(tempfile, "w")) == NULL) {
230*3e12c5d1SDavid du Colombier fprintf(stderr, "grap: can't open %s\n", tempfile);
231*3e12c5d1SDavid du Colombier exit(1);
232*3e12c5d1SDavid du Colombier }
233*3e12c5d1SDavid du Colombier }
234*3e12c5d1SDavid du Colombier }
235