plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

misc.c (9012B)


      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <math.h>
      5 #include "pic.h"
      6 #include "y.tab.h"
      7 
      8 int whatpos(obj *p, int corner, double *px, double *py);
      9 void makeattr(int type, int sub, YYSTYPE val);
     10 YYSTYPE getblk(obj *, char *);
     11 
     12 int
     13 setdir(int n)	/* set direction (hvmode) from LEFT, RIGHT, etc. */
     14 {
     15 	switch (n) {
     16 	case UP:	hvmode = U_DIR; break;
     17 	case DOWN:	hvmode = D_DIR; break;
     18 	case LEFT:	hvmode = L_DIR; break;
     19 	case RIGHT:	hvmode = R_DIR; break;
     20 	}
     21  	return(hvmode);
     22 }
     23 
     24 int
     25 curdir(void)	/* convert current dir (hvmode) to RIGHT, LEFT, etc. */
     26 {
     27 	switch (hvmode) {
     28 	case R_DIR:	return RIGHT;
     29 	case L_DIR:	return LEFT;
     30 	case U_DIR:	return UP;
     31 	case D_DIR:	return DOWN;
     32 	}
     33 	ERROR "can't happen curdir" FATAL;
     34 	return 0;
     35 }
     36 
     37 double
     38 getcomp(obj *p, int t)	/* return component of a position */
     39 {
     40 	switch (t) {
     41 	case DOTX:
     42 		return p->o_x;
     43 	case DOTY:
     44 		return p->o_y;
     45 	case DOTWID:
     46 		switch (p->o_type) {
     47 		case BOX:
     48 		case BLOCK:
     49 		case TEXT:
     50 			return p->o_val[0];
     51 		case CIRCLE:
     52 		case ELLIPSE:
     53 			return 2 * p->o_val[0];
     54 		case LINE:
     55 		case ARROW:
     56 			return p->o_val[0] - p->o_x;
     57 		case PLACE:
     58 			return 0;
     59 		}
     60 	case DOTHT:
     61 		switch (p->o_type) {
     62 		case BOX:
     63 		case BLOCK:
     64 		case TEXT:
     65 			return p->o_val[1];
     66 		case CIRCLE:
     67 		case ELLIPSE:
     68 			return 2 * p->o_val[1];
     69 		case LINE:
     70 		case ARROW:
     71 			return p->o_val[1] - p->o_y;
     72 		case PLACE:
     73 			return 0;
     74 		}
     75 	case DOTRAD:
     76 		switch (p->o_type) {
     77 		case CIRCLE:
     78 		case ELLIPSE:
     79 			return p->o_val[0];
     80 		}
     81 	}
     82 	ERROR "you asked for a weird dimension or position" WARNING;
     83 	return 0;
     84 }
     85 
     86 double	exprlist[100];
     87 int	nexpr	= 0;
     88 
     89 void exprsave(double f)
     90 {
     91 	exprlist[nexpr++] = f;
     92 }
     93 
     94 char *sprintgen(char *fmt)
     95 {
     96 	char buf[1000];
     97 
     98 	sprintf(buf, fmt, exprlist[0], exprlist[1], exprlist[2], exprlist[3], exprlist[4]);
     99 	nexpr = 0;
    100 	free(fmt);
    101 	return tostring(buf);
    102 }
    103 
    104 void makefattr(int type, int sub, double f)	/* double attr */
    105 {
    106 	YYSTYPE val;
    107 	val.f = f;
    108 	makeattr(type, sub, val);
    109 }
    110 
    111 void makeoattr(int type, obj *o)	/* obj* attr */
    112 {
    113 	YYSTYPE val;
    114 	val.o = o;
    115 	makeattr(type, 0, val);
    116 }
    117 
    118 void makeiattr(int type, int i)	/* int attr */
    119 {
    120 	YYSTYPE val;
    121 	val.i = i;
    122 	makeattr(type, 0, val);
    123 }
    124 
    125 void maketattr(int sub, char *p)	/* text attribute: takes two */
    126 {
    127 	YYSTYPE val;
    128 	val.p = p;
    129 	makeattr(TEXTATTR, sub, val);
    130 }
    131 
    132 void addtattr(int sub)		/* add text attrib to existing item */
    133 {
    134 	attr[nattr-1].a_sub |= sub;
    135 }
    136 
    137 void makevattr(char *p)	/* varname attribute */
    138 {
    139 	YYSTYPE val;
    140 	val.p = p;
    141 	makeattr(VARNAME, 0, val);
    142 }
    143 
    144 void makeattr(int type, int sub, YYSTYPE val)	/* add attribute type and val */
    145 {
    146 	if (type == 0 && val.i == 0) {	/* clear table for next stat */
    147 		nattr = 0;
    148 		return;
    149 	}
    150 	if (nattr >= nattrlist)
    151 		attr = (Attr *) grow((char *)attr, "attr", nattrlist += 100, sizeof(Attr));
    152 	dprintf("attr %d:  %d %d %d\n", nattr, type, sub, val.i);
    153 	attr[nattr].a_type = type;
    154 	attr[nattr].a_sub = sub;
    155 	attr[nattr].a_val = val;
    156 	nattr++;
    157 }
    158 
    159 void printexpr(double f)	/* print expression for debugging */
    160 {
    161 	printf("%g\n", f);
    162 }
    163 
    164 void printpos(obj *p)	/* print position for debugging */
    165 {
    166 	printf("%g, %g\n", p->o_x, p->o_y);
    167 }
    168 
    169 char *tostring(char *s)
    170 {
    171 	register char *p;
    172 
    173 	p = malloc(strlen(s)+1);
    174 	if (p == NULL)
    175 		ERROR "out of space in tostring on %s", s FATAL;
    176 	strcpy(p, s);
    177 	return(p);
    178 }
    179 
    180 obj *makepos(double x, double y)	/* make a position cell */
    181 {
    182 	obj *p;
    183 
    184 	p = makenode(PLACE, 0);
    185 	p->o_x = x;
    186 	p->o_y = y;
    187 	return(p);
    188 }
    189 
    190 obj *makebetween(double f, obj *p1, obj *p2)	/* make position between p1 and p2 */
    191 {
    192 	obj *p;
    193 
    194 	dprintf("fraction = %.2f\n", f);
    195 	p = makenode(PLACE, 0);
    196 	p->o_x = p1->o_x + f * (p2->o_x - p1->o_x);
    197 	p->o_y = p1->o_y + f * (p2->o_y - p1->o_y);
    198 	return(p);
    199 }
    200 
    201 obj *getpos(obj *p, int corner)	/* find position of point */
    202 {
    203 	double x, y;
    204 
    205 	whatpos(p, corner, &x, &y);
    206 	return makepos(x, y);
    207 }
    208 
    209 int whatpos(obj *p, int corner, double *px, double *py)	/* what is the position (no side effect) */
    210 {
    211 	double x, y, x1, y1;
    212 
    213 	x1 = y1 = 0.0; /* Botch? (gcc) */
    214 
    215 	dprintf("whatpos %p %d %d\n", (void*)p, p->o_type, corner);
    216 	x = p->o_x;
    217 	y = p->o_y;
    218 	if (p->o_type != PLACE && p->o_type != MOVE) {
    219 		x1 = p->o_val[0];
    220 		y1 = p->o_val[1];
    221 	}
    222 	switch (p->o_type) {
    223 	case PLACE:
    224 		break;
    225 	case BOX:
    226 	case BLOCK:
    227 	case TEXT:
    228 		switch (corner) {
    229 		case NORTH:	y += y1 / 2; break;
    230 		case SOUTH:	y -= y1 / 2; break;
    231 		case EAST:	x += x1 / 2; break;
    232 		case WEST:	x -= x1 / 2; break;
    233 		case NE:	x += x1 / 2; y += y1 / 2; break;
    234 		case SW:	x -= x1 / 2; y -= y1 / 2; break;
    235 		case SE:	x += x1 / 2; y -= y1 / 2; break;
    236 		case NW:	x -= x1 / 2; y += y1 / 2; break;
    237 		case START:
    238 			if (p->o_type == BLOCK)
    239 				return whatpos(objlist[(int)p->o_val[2]], START, px, py);
    240 		case END:
    241 			if (p->o_type == BLOCK)
    242 				return whatpos(objlist[(int)p->o_val[3]], END, px, py);
    243 		}
    244 		break;
    245 	case ARC:
    246 		switch (corner) {
    247 		case START:
    248 			if (p->o_attr & CW_ARC) {
    249 				x = p->o_val[2]; y = p->o_val[3];
    250 			} else {
    251 				x = x1; y = y1;
    252 			}
    253 			break;
    254 		case END:
    255 			if (p->o_attr & CW_ARC) {
    256 				x = x1; y = y1;
    257 			} else {
    258 				x = p->o_val[2]; y = p->o_val[3];
    259 			}
    260 			break;
    261 		}
    262 		if (corner == START || corner == END)
    263 			break;
    264 		x1 = y1 = sqrt((x1-x)*(x1-x) + (y1-y)*(y1-y));
    265 		/* Fall Through! */
    266 	case CIRCLE:
    267 	case ELLIPSE:
    268 		switch (corner) {
    269 		case NORTH:	y += y1; break;
    270 		case SOUTH:	y -= y1; break;
    271 		case EAST:	x += x1; break;
    272 		case WEST:	x -= x1; break;
    273 		case NE:	x += 0.707 * x1; y += 0.707 * y1; break;
    274 		case SE:	x += 0.707 * x1; y -= 0.707 * y1; break;
    275 		case NW:	x -= 0.707 * x1; y += 0.707 * y1; break;
    276 		case SW:	x -= 0.707 * x1; y -= 0.707 * y1; break;
    277 		}
    278 		break;
    279 	case LINE:
    280 	case SPLINE:
    281 	case ARROW:
    282 		switch (corner) {
    283 		case START:	break;	/* already in place */
    284 		case END:	x = x1; y = y1; break;
    285 		default: /* change! */
    286 		case CENTER:	x = (x+x1)/2; y = (y+y1)/2; break;
    287 		case NORTH:	if (y1 > y) { x = x1; y = y1; } break;
    288 		case SOUTH:	if (y1 < y) { x = x1; y = y1; } break;
    289 		case EAST:	if (x1 > x) { x = x1; y = y1; } break;
    290 		case WEST:	if (x1 < x) { x = x1; y = y1; } break;
    291 		}
    292 		break;
    293 	case MOVE:
    294 		/* really ought to be same as line... */
    295 		break;
    296 	}
    297 	dprintf("whatpos returns %g %g\n", x, y);
    298 	*px = x;
    299 	*py = y;
    300 	return 1;
    301 }
    302 
    303 obj *gethere(void)	/* make a place for curx,cury */
    304 {
    305 	dprintf("gethere %g %g\n", curx, cury);
    306 	return(makepos(curx, cury));
    307 }
    308 
    309 obj *getlast(int n, int t)	/* find n-th previous occurrence of type t */
    310 {
    311 	int i, k;
    312 	obj *p;
    313 
    314 	k = n;
    315 	for (i = nobj-1; i >= 0; i--) {
    316 		p = objlist[i];
    317 		if (p->o_type == BLOCKEND) {
    318 			i = p->o_val[4];
    319 			continue;
    320 		}
    321 		if (p->o_type != t)
    322 			continue;
    323 		if (--k > 0)
    324 			continue;	/* not there yet */
    325 		dprintf("got a last of x,y= %g,%g\n", p->o_x, p->o_y);
    326 		return(p);
    327 	}
    328 	ERROR "there is no %dth last", n WARNING;
    329 	return(NULL);
    330 }
    331 
    332 obj *getfirst(int n, int t)	/* find n-th occurrence of type t */
    333 {
    334 	int i, k;
    335 	obj *p;
    336 
    337 	k = n;
    338 	for (i = 0; i < nobj; i++) {
    339 		p = objlist[i];
    340 		if (p->o_type == BLOCK && t != BLOCK) {	/* skip whole block */
    341 			i = p->o_val[5] + 1;
    342 			continue;
    343 		}
    344 		if (p->o_type != t)
    345 			continue;
    346 		if (--k > 0)
    347 			continue;	/* not there yet */
    348 		dprintf("got a first of x,y= %g,%g\n", p->o_x, p->o_y);
    349 		return(p);
    350 	}
    351 	ERROR "there is no %dth ", n WARNING;
    352 	return(NULL);
    353 }
    354 
    355 double getblkvar(obj *p, char *s)	/* find variable s2 in block p */
    356 {
    357 	YYSTYPE y;
    358 
    359 	y = getblk(p, s);
    360 	return y.f;
    361 }
    362 
    363 obj *getblock(obj *p, char *s)	/* find variable s in block p */
    364 {
    365 	YYSTYPE y;
    366 
    367 	y = getblk(p, s);
    368 	return y.o;
    369 }
    370 
    371 YYSTYPE getblk(obj *p, char *s)	/* find union type for s in p */
    372 {
    373 	static YYSTYPE bug;
    374 	struct symtab *stp;
    375 
    376 	if (p->o_type != BLOCK) {
    377 		ERROR ".%s is not in that block", s WARNING;
    378 		return(bug);
    379 	}
    380 	for (stp = p->o_symtab; stp != NULL; stp = stp->s_next)
    381 		if (strcmp(s, stp->s_name) == 0) {
    382 			dprintf("getblk %s found x,y= %g,%g\n",
    383 				s, (stp->s_val.o)->o_x, (stp->s_val.o)->o_y);
    384 			return(stp->s_val);
    385 		}
    386 	ERROR "there is no .%s in that []", s WARNING;
    387 	return(bug);
    388 }
    389 
    390 obj *fixpos(obj *p, double x, double y)
    391 {
    392 	dprintf("fixpos returns %g %g\n", p->o_x + x, p->o_y + y);
    393 	return makepos(p->o_x + x, p->o_y + y);
    394 }
    395 
    396 obj *addpos(obj *p, obj *q)
    397 {
    398 	dprintf("addpos returns %g %g\n", p->o_x+q->o_x, p->o_y+q->o_y);
    399 	return makepos(p->o_x+q->o_x, p->o_y+q->o_y);
    400 }
    401 
    402 obj *subpos(obj *p, obj *q)
    403 {
    404 	dprintf("subpos returns %g %g\n", p->o_x-q->o_x, p->o_y-q->o_y);
    405 	return makepos(p->o_x-q->o_x, p->o_y-q->o_y);
    406 }
    407 
    408 obj *makenode(int type, int n)
    409 {
    410 	obj *p;
    411 
    412 	p = (obj *) calloc(1, sizeof(obj) + (n-1)*sizeof(ofloat));
    413 	if (p == NULL)
    414 		ERROR "out of space in makenode" FATAL;
    415 	p->o_type = type;
    416 	p->o_count = n;
    417 	p->o_nobj = nobj;
    418 	p->o_mode = hvmode;
    419 	p->o_x = curx;
    420 	p->o_y = cury;
    421 	p->o_nt1 = ntext1;
    422 	p->o_nt2 = ntext;
    423 	ntext1 = ntext;	/* ready for next caller */
    424 	if (nobj >= nobjlist)
    425 		objlist = (obj **) grow((char *) objlist, "objlist",
    426 			nobjlist *= 2, sizeof(obj *));
    427 	objlist[nobj++] = p;
    428 	return(p);
    429 }
    430 
    431 void extreme(double x, double y)	/* record max and min x and y values */
    432 {
    433 	if (x > xmax)
    434 		xmax = x;
    435 	if (y > ymax)
    436 		ymax = y;
    437 	if (x < xmin)
    438 		xmin = x;
    439 	if (y < ymin)
    440 		ymin = y;
    441 }