plan9port

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

misc.c (8814B)


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