misc.c 8.8 KB

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