|  | #include <stdio.h> | 
|  | #include <string.h> | 
|  | #include <stdlib.h> | 
|  | #include "grap.h" | 
|  | #include "y.tab.h" | 
|  |  | 
|  | int	nnum	= 0;	/* number of saved numbers */ | 
|  | double	num[MAXNUM]; | 
|  |  | 
|  | int	just;		/* current justification mode (RJUST, etc.) */ | 
|  | int	sizeop;		/* current optional operator for size change */ | 
|  | double	sizexpr;	/* current size change expression */ | 
|  |  | 
|  | void savenum(int n, double f)	/* save f in num[n] */ | 
|  | { | 
|  | num[n] = f; | 
|  | nnum = n+1; | 
|  | if (nnum >= MAXNUM) | 
|  | ERROR "too many numbers" WARNING; | 
|  | } | 
|  |  | 
|  | void setjust(int j) | 
|  | { | 
|  | just |= j; | 
|  | } | 
|  |  | 
|  | void setsize(int op, double expr) | 
|  | { | 
|  | sizeop = op; | 
|  | sizexpr = expr; | 
|  | } | 
|  |  | 
|  | char *tostring(char *s) | 
|  | { | 
|  | register char *p; | 
|  |  | 
|  | p = malloc(strlen(s)+1); | 
|  | if (p == NULL) | 
|  | ERROR "out of space in tostring on %s", s FATAL; | 
|  | strcpy(p, s); | 
|  | return(p); | 
|  | } | 
|  |  | 
|  | void range(Point pt)	/* update the range for point pt */ | 
|  | { | 
|  | Obj *p = pt.obj; | 
|  |  | 
|  | if (!(p->coord & XFLAG)) { | 
|  | if (pt.x > p->pt1.x) | 
|  | p->pt1.x = pt.x; | 
|  | if (pt.x < p->pt.x) | 
|  | p->pt.x = pt.x; | 
|  | } | 
|  | if (!(p->coord & YFLAG)) { | 
|  | if (pt.y > p->pt1.y) | 
|  | p->pt1.y = pt.y; | 
|  | if (pt.y < p->pt.y) | 
|  | p->pt.y = pt.y; | 
|  | } | 
|  | } | 
|  |  | 
|  | void halfrange(Obj *p, int side, double val)	/* record max and min for one direction */ | 
|  | { | 
|  | if (!(p->coord&XFLAG) && (side == LEFT || side == RIGHT)) { | 
|  | if (val < p->pt.y) | 
|  | p->pt.y = val; | 
|  | if (val > p->pt1.y) | 
|  | p->pt1.y = val; | 
|  | } else if (!(p->coord&YFLAG) && (side == TOP || side == BOT)) { | 
|  | if (val < p->pt.x) | 
|  | p->pt.x = val; | 
|  | if (val > p->pt1.x) | 
|  | p->pt1.x = val; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | Obj *lookup(char *s, int inst)	/* find s in objlist, install if inst */ | 
|  | { | 
|  | Obj *p; | 
|  | int found = 0; | 
|  |  | 
|  | for (p = objlist; p; p = p->next){ | 
|  | if (strcmp(s, p->name) == 0) { | 
|  | found = 1; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (p == NULL && inst != 0) { | 
|  | p = (Obj *) calloc(1, sizeof(Obj)); | 
|  | if (p == NULL) | 
|  | ERROR "out of space in lookup" FATAL; | 
|  | p->name = tostring(s); | 
|  | p->type = NAME; | 
|  | p->pt = ptmax; | 
|  | p->pt1 = ptmin; | 
|  | p->fval = 0.0; | 
|  | p->next = objlist; | 
|  | objlist = p; | 
|  | } | 
|  | dprintf("lookup(%s,%d) = %d\n", s, inst, found); | 
|  | return p; | 
|  | } | 
|  |  | 
|  | double getvar(Obj *p)	/* return value of variable */ | 
|  | { | 
|  | return p->fval; | 
|  | } | 
|  |  | 
|  | double setvar(Obj *p, double f)	/* set value of variable to f */ | 
|  | { | 
|  | if (strcmp(p->name, "pointsize") == 0) {	/* kludge */ | 
|  | pointsize = f; | 
|  | ps_set = 1; | 
|  | } | 
|  | p->type = VARNAME; | 
|  | return p->fval = f; | 
|  | } | 
|  |  | 
|  | Point makepoint(Obj *s, double x, double y)	/* make a Point */ | 
|  | { | 
|  | Point p; | 
|  |  | 
|  | dprintf("makepoint: %s, %g,%g\n", s->name, x, y); | 
|  | p.obj = s; | 
|  | p.x = x; | 
|  | p.y = y; | 
|  | return p; | 
|  | } | 
|  |  | 
|  | Attr *makefattr(int type, double fval)	/* set double in attribute */ | 
|  | { | 
|  | return makeattr(type, fval, (char *) 0, 0, 0); | 
|  | } | 
|  |  | 
|  | Attr *makesattr(char *s)		/* make an Attr cell containing s */ | 
|  | { | 
|  | Attr *ap = makeattr(STRING, sizexpr, s, just, sizeop); | 
|  | just = sizeop = 0; | 
|  | sizexpr = 0.0; | 
|  | return ap; | 
|  | } | 
|  |  | 
|  | Attr *makeattr(int type, double fval, char *sval, int just, int op) | 
|  | { | 
|  | Attr *a; | 
|  |  | 
|  | a = (Attr *) malloc(sizeof(Attr)); | 
|  | if (a == NULL) | 
|  | ERROR "out of space in makeattr" FATAL; | 
|  | a->type = type; | 
|  | a->fval = fval; | 
|  | a->sval = sval; | 
|  | a->just = just; | 
|  | a->op = op; | 
|  | a->next = NULL; | 
|  | return a; | 
|  | } | 
|  |  | 
|  | Attr *addattr(Attr *a1, Attr *ap)	/* add attr ap to end of list a1 */ | 
|  | { | 
|  | Attr *p; | 
|  |  | 
|  | if (a1 == 0) | 
|  | return ap; | 
|  | if (ap == 0) | 
|  | return a1; | 
|  | for (p = a1; p->next; p = p->next) | 
|  | ; | 
|  | p->next = ap; | 
|  | return a1; | 
|  | } | 
|  |  | 
|  | void freeattr(Attr *ap)	/* free an attribute list */ | 
|  | { | 
|  | Attr *p; | 
|  |  | 
|  | while (ap) { | 
|  | p = ap->next;	/* save next */ | 
|  | if (ap->sval) | 
|  | free(ap->sval); | 
|  | free((char *) ap); | 
|  | ap = p; | 
|  | } | 
|  | } | 
|  |  | 
|  | char *slprint(Attr *stringlist)	/* print strings from stringlist */ | 
|  | { | 
|  | int ntext, n, last_op, last_just; | 
|  | double last_fval; | 
|  | static char buf[1000]; | 
|  | Attr *ap; | 
|  |  | 
|  | buf[0] = '\0'; | 
|  | last_op = last_just = 0; | 
|  | last_fval = 0.0; | 
|  | for (ntext = 0, ap = stringlist; ap != NULL; ap = ap->next) | 
|  | ntext++; | 
|  | sprintf(buf, "box invis wid 0 ht %d*textht", ntext); | 
|  | n = strlen(buf); | 
|  | for (ap = stringlist; ap != NULL; ap = ap->next) { | 
|  | if (ap->op == 0) {	/* propagate last value */ | 
|  | ap->op = last_op; | 
|  | ap->fval = last_fval; | 
|  | } else { | 
|  | last_op = ap->op; | 
|  | last_fval = ap->fval; | 
|  | } | 
|  | sprintf(buf+n, " \"%s\"", ps_set || ap->op ? sizeit(ap) : ap->sval); | 
|  | if (ap->just) | 
|  | last_just = ap->just; | 
|  | if (last_just) | 
|  | strcat(buf+n, juststr(last_just)); | 
|  | n = strlen(buf); | 
|  | } | 
|  | return buf;	/* watch it:  static */ | 
|  | } | 
|  |  | 
|  | char *juststr(int j)	/* convert RJUST, etc., into string */ | 
|  | { | 
|  | static char buf[50]; | 
|  |  | 
|  | buf[0] = '\0'; | 
|  | if (j & RJUST) | 
|  | strcat(buf, " rjust"); | 
|  | if (j & LJUST) | 
|  | strcat(buf, " ljust"); | 
|  | if (j & ABOVE) | 
|  | strcat(buf, " above"); | 
|  | if (j & BELOW) | 
|  | strcat(buf, " below"); | 
|  | return buf;	/* watch it:  static */ | 
|  | } | 
|  |  | 
|  | char *sprntf(char *s, Attr *ap)	/* sprintf(s, attrlist ap) */ | 
|  | { | 
|  | char buf[500]; | 
|  | int n; | 
|  | Attr *p; | 
|  |  | 
|  | for (n = 0, p = ap; p; p = p->next) | 
|  | n++; | 
|  | switch (n) { | 
|  | case 0: | 
|  | return s; | 
|  | case 1: | 
|  | sprintf(buf, s, ap->fval); | 
|  | break; | 
|  | case 2: | 
|  | sprintf(buf, s, ap->fval, ap->next->fval); | 
|  | break; | 
|  | case 3: | 
|  | sprintf(buf, s, ap->fval, ap->next->fval, ap->next->next->fval); | 
|  | break; | 
|  | case 5: | 
|  | ERROR "too many expressions in sprintf" WARNING; | 
|  | case 4: | 
|  | sprintf(buf, s, ap->fval, ap->next->fval, ap->next->next->fval, ap->next->next->next->fval); | 
|  | break; | 
|  | } | 
|  | free(s); | 
|  | return tostring(buf); | 
|  | } |