| #include <u.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <math.h> |
| #include <ctype.h> |
| #include <unistd.h> |
| #include "grap.h" |
| #include "y.tab.h" |
| |
| double margin = MARGIN; /* extra space around edges */ |
| extern double frame_ht, frame_wid, ticklen; |
| extern int just, sizeop, tick_dir; |
| extern double sizexpr, lab_up, lab_rt; |
| |
| char graphname[50] = "Graph"; |
| char graphpos[200] = ""; |
| |
| void print(void) /* arrange final output */ |
| { |
| FILE *fd; |
| Obj *p, *dfp; |
| int c; |
| double dx, dy, xfac, yfac; |
| |
| if (tfd != stdout) { |
| if (tfd) |
| fclose(tfd); /* end the temp file */ |
| tfd = stdout; |
| } |
| |
| if ((p=lookup("margin",0)) != NULL) |
| margin = p->fval; |
| if (frame_ht < 0) /* wasn't set explicitly, so use default */ |
| frame_ht = getvar(lookup("frameht", 0)); |
| if (frame_wid < 0) |
| frame_wid = getvar(lookup("framewid", 0)); |
| dfp = NULL; |
| for (p = objlist; p; p = p->next) { |
| dprintf("print: name = <%s>, type = %d\n", p->name, p->type); |
| if (p->type == NAME) { |
| Point pt, pt1; |
| pt = p->pt; |
| pt1 = p->pt1; |
| fprintf(tfd, "\t# %s %g .. %g, %g .. %g\n", |
| p->name, pt.x, pt1.x, pt.y, pt1.y); |
| if (p->log & XFLAG) { |
| if (pt.x <= 0.0) |
| ERROR "can't take log of x coord %g", pt.x FATAL; |
| logit(pt.x); |
| logit(pt1.x); |
| } |
| if (p->log & YFLAG) { |
| if (pt.y <= 0.0) |
| ERROR "can't take log of y coord %g", pt.y FATAL; |
| logit(pt.y); |
| logit(pt1.y); |
| } |
| if (!(p->coord & XFLAG)) { |
| dx = pt1.x - pt.x; |
| pt.x -= margin * dx; |
| pt1.x += margin * dx; |
| } |
| if (!(p->coord & YFLAG)) { |
| dy = pt1.y - pt.y; |
| pt.y -= margin * dy; |
| pt1.y += margin * dy; |
| } |
| if (autoticks && strcmp(p->name, dflt_coord) == 0) { |
| p->pt = pt; |
| p->pt1 = pt1; |
| if (p->log & XFLAG) { |
| p->pt.x = pow(10.0, pt.x); |
| p->pt1.x = pow(10.0, pt1.x); |
| } |
| if (p->log & YFLAG) { |
| p->pt.y = pow(10.0, pt.y); |
| p->pt1.y = pow(10.0, pt1.y); |
| } |
| dfp = setauto(); |
| } |
| dx = pt1.x - pt.x; |
| dy = pt1.y - pt.y; |
| xfac = dx > 0 ? frame_wid/dx : frame_wid/2; |
| yfac = dy > 0 ? frame_ht/dy : frame_ht/2; |
| |
| fprintf(tfd, "define xy_%s @ ", p->name); |
| if (dx > 0) |
| fprintf(tfd, "\t(($1)-(%g))*%g", pt.x, xfac); |
| else |
| fprintf(tfd, "\t%g", xfac); |
| if (dy > 0) |
| fprintf(tfd, ", (($2)-(%g))*%g @\n", pt.y, yfac); |
| else |
| fprintf(tfd, ", %g @\n", yfac); |
| fprintf(tfd, "define x_%s @ ", p->name); |
| if (dx > 0) |
| fprintf(tfd, "\t(($1)-(%g))*%g @\n", pt.x, xfac); |
| else |
| fprintf(tfd, "\t%g @\n", xfac); |
| fprintf(tfd, "define y_%s @ ", p->name); |
| if (dy > 0) |
| fprintf(tfd, "\t(($1)-(%g))*%g @\n", pt.y, yfac); |
| else |
| fprintf(tfd, "\t%g @\n", yfac); |
| } |
| } |
| if (codegen) |
| frame(); |
| if (codegen && autoticks && dfp) |
| do_autoticks(dfp); |
| |
| if ((fd = fopen(tempfile, "r")) != NULL) { |
| while ((c = getc(fd)) != EOF) |
| putc(c, tfd); |
| fclose(fd); |
| } |
| tfd = NULL; |
| } |
| |
| void endstat(void) /* clean up after each statement */ |
| { |
| |
| just = sizeop = 0; |
| lab_up = lab_rt = 0.0; |
| sizexpr = 0.0; |
| nnum = 0; |
| ntick = 0; |
| tside = 0; |
| tick_dir = OUT; |
| ticklen = TICKLEN; |
| } |
| |
| void graph(char *s) /* graph statement */ |
| { |
| char *p, *os; |
| int c; |
| |
| if (codegen) { |
| fprintf(stdout, "%s: [\n", graphname); |
| print(); /* pump out previous graph */ |
| fprintf(stdout, "\n] %s\n", graphpos); |
| reset(); |
| } |
| if (s) { |
| dprintf("into graph with <%s>\n", s); |
| opentemp(); |
| os = s; |
| while ((c = *s) == ' ' || c == '\t') |
| s++; |
| if (c == '\0') |
| ERROR "no name on graph statement" WARNING; |
| if (!isupper((uchar)s[0])) |
| ERROR "graph name %s must be capitalized", s WARNING; |
| for (p=graphname; (c = *s) != ' ' && c != '\t' && c != '\0'; ) |
| *p++ = *s++; |
| *p = '\0'; |
| strcpy(graphpos, s); |
| dprintf("graphname = <%s>, graphpos = <%s>\n", graphname, graphpos); |
| free(os); |
| } |
| } |
| |
| void setup(void) /* done at each .G1 */ |
| { |
| static int firstG1 = 0; |
| |
| reset(); |
| opentemp(); |
| frame_ht = frame_wid = -1; /* reset in frame() */ |
| ticklen = getvar(lookup("ticklen", 0)); |
| if (firstG1++ == 0) |
| do_first(); |
| codegen = synerr = 0; |
| strcpy(graphname, "Graph"); |
| strcpy(graphpos, ""); |
| } |
| |
| void do_first(void) /* done at first .G1: definitions, etc. */ |
| { |
| extern int lib; |
| extern char *lib_defines; |
| static char buf[100], buf1[100]; /* static because pbstr uses them */ |
| FILE *fp; |
| |
| snprintf(buf, sizeof buf, "define pid /%d/\n", getpid()); |
| pbstr(buf); |
| if (lib != 0) { |
| if ((fp = fopen(lib_defines, "r")) != NULL) { |
| snprintf(buf1, sizeof buf, "copy \"%s\"\n", lib_defines); |
| pbstr(buf1); |
| fclose(fp); |
| } else { |
| fprintf(stderr, "grap warning: can't open %s\n", lib_defines); |
| } |
| } |
| } |
| |
| void reset(void) /* done at each "graph ..." statement */ |
| { |
| Obj *p, *np, *deflist; |
| extern int tlist, toffside, autodir; |
| |
| curr_coord = dflt_coord; |
| ncoord = auto_x = 0; |
| autoticks = LEFT|BOT; |
| autodir = 0; |
| tside = tlist = toffside = 0; |
| tick_dir = OUT; |
| margin = MARGIN; |
| deflist = NULL; |
| for (p = objlist; p; p = np) { |
| np = p->next; |
| if (p->type == DEFNAME || p->type == VARNAME) { |
| p->next = deflist; |
| deflist = p; |
| } else { |
| free(p->name); |
| freeattr(p->attr); |
| free((char *) p); |
| } |
| } |
| objlist = deflist; |
| } |
| |
| void opentemp(void) |
| { |
| if (tfd != stdout) { |
| if (tfd != NULL) |
| fclose(tfd); |
| if ((tfd = fopen(tempfile, "w")) == NULL) { |
| fprintf(stderr, "grap: can't open %s\n", tempfile); |
| exit(1); |
| } |
| } |
| } |