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 }