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