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