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 }