|
|
1.1 ! root 1: #include "draw_dag.h" ! 2: #include "dag.h" ! 3: #include "paths.h" ! 4: #include "parsedag.h" ! 5: #include "defaults.h" ! 6: #include "unistd.h" ! 7: ! 8: /*** utility functions ***/ ! 9: ! 10: char* Infile::gets(char *buf,int n) { ! 11: if (!fp) return 0; ! 12: line_number++; ! 13: return fgets(buf,n,fp); ! 14: } ! 15: ! 16: Infile nextfile(char** &argv) ! 17: { ! 18: argv++; ! 19: while (**argv == '-') argv++; ! 20: Infile rv = Infile(*argv); ! 21: if (!rv.fp) fprintf(stderr,"%s: can't open %s\n",Cmd_name,*argv); ! 22: return rv; ! 23: } ! 24: ! 25: /*** shared strings ***/ ! 26: ! 27: shared_string_t *shared_string_pool; ! 28: char *newstring(char *init) { ! 29: shared_string_t *it ! 30: = (shared_string_t*) malloc(sizeof(shared_string_t) + strlen(init)); ! 31: it->next = shared_string_pool; ! 32: shared_string_pool = it; ! 33: strcpy(it->data,init); ! 34: return it->data; ! 35: } ! 36: ! 37: void freestrings() { ! 38: shared_string_t *q,*p = shared_string_pool; ! 39: while (p) { ! 40: q = p->next; ! 41: free((char*)p); ! 42: p = q; ! 43: } ! 44: shared_string_pool = 0; ! 45: } ! 46: ! 47: /*** hash table ***/ ! 48: ! 49: int hash(register char* s, int size) { ! 50: register unsigned int h; ! 51: register int c; ! 52: ! 53: h = 0; ! 54: while (c = *s++) { ! 55: if ((h <<= 1) < 0) h ^= c ^ ((~(((unsigned int)~0) >> 1)) | 1); ! 56: else h ^= c; ! 57: } ! 58: return(h % size); ! 59: } ! 60: ! 61: const int Hash_extent = 517; ! 62: struct hashrec { ! 63: int node; ! 64: hashrec *next; ! 65: ! 66: hashrec(int argnode, hashrec *argnext) { ! 67: node = argnode; ! 68: next = argnext; ! 69: }; ! 70: } *Hashtab[Hash_extent]; ! 71: ! 72: boolean expand_graph(int new_size) { ! 73: if (! (Node = (DAG_node_t**)realloc((char*)Node,sizeof(DAG_node_t*)*new_size))) ! 74: return false; ! 75: else ! 76: if (! (Edge = (DAG_edge_t**)realloc((char*)Edge,sizeof(DAG_edge_t*)*new_size))) ! 77: return false; ! 78: return true; ! 79: } ! 80: ! 81: /* look name and insert in symbol table if not found. return new node's number. */ ! 82: int node_lookup(char *name) { ! 83: int h = hash(name,Hash_extent); ! 84: for (hashrec *hp = Hashtab[h]; hp; hp = hp->next) ! 85: if (!strcmp(name,Node[hp->node]->name)) break; ! 86: if (!hp) { ! 87: Hashtab[h] = hp = new hashrec(N,Hashtab[h]); ! 88: ! 89: if (N > Extent - 1) { ! 90: Extent += Extent; ! 91: if (!expand_graph(Extent)) { ! 92: yyerror("too many nodes, out of memory"); ! 93: exit(1); ! 94: } ! 95: } ! 96: Node[N] = new DAG_node_t(); ! 97: *Node[N] = Default_node; ! 98: Node[N]->setname(name); ! 99: Edge[N] = (DAG_edge_t*)0; ! 100: N++; ! 101: } ! 102: return hp->node; ! 103: } ! 104: ! 105: /*** utility functions for code gen */ ! 106: ! 107: void cat_libfile(char* name) { ! 108: char buf[BUFSIZ]; ! 109: if (!Uselib) return; ! 110: if (!Lib_path) { ! 111: #ifdef EXPTOOLS ! 112: char *tools = getenv("TOOLS"); ! 113: if (tools) { ! 114: Lib_path = new char[strlen(Lib_path)+strlen(EXPTOOLS_SUBDIR)+2]; ! 115: sprintf(Lib_path,"%s/%s",tools,EXPTOOLS_SUBDIR); ! 116: sprintf(buf,"%s/%s",Lib_path,name); ! 117: if (access(buf,R_OK)) ! 118: Lib_path = LIB_PATH; ! 119: } ! 120: else ! 121: #endif EXPTOOLS ! 122: Lib_path = LIB_PATH; ! 123: } ! 124: fflush(stdout); ! 125: sprintf(buf,"cat %s/%s",Lib_path,name); ! 126: system(buf); ! 127: } ! 128: ! 129: Point find_edge_midpoint(DAG_edge_t *e) { ! 130: int x,y; ! 131: for (int npts = 0; e->splinept[npts].y >= 0; npts++); ! 132: if (iabs(e->splinept[0].y - e->splinept[npts-1].y) > ! 133: iabs(e->splinept[0].x - e->splinept[npts-1].x)) { // "vertical" edge ! 134: int i,y1 = 0; ! 135: y1 = (e->splinept[0].y + e->splinept[npts-1].y)/2; ! 136: for (i = 0; e->splinept[i].y >= 0; i++) ! 137: if (between(e->splinept[i].y,y1,e->splinept[i+1].y)) break; ! 138: y = y1; ! 139: x = (int) (e->splinept[i].x + ! 140: (double)(y1 - e->splinept[i].y)/(e->splinept[i+1].y-e->splinept[i].y) ! 141: * (e->splinept[i+1].x - e->splinept[i].x)); ! 142: } ! 143: else { // "horizontal" edge ! 144: int i,x1 = 0; ! 145: x1 = (e->splinept[0].x + e->splinept[npts-1].x)/2; ! 146: for (i = 0; e->splinept[i].y >= 0; i++) ! 147: if (between(e->splinept[i].x,x1,e->splinept[i+1].x)) break; ! 148: x = x1; ! 149: y = (int) (e->splinept[i].y + ! 150: (double)(x1 - e->splinept[i].x)/(e->splinept[i+1].x-e->splinept[i].x) ! 151: * (e->splinept[i+1].y - e->splinept[i].y)); ! 152: } ! 153: Point rv; ! 154: rv .x = x; rv .y = y; ! 155: return rv; ! 156: } ! 157: ! 158: static boolean seginter(int x0,int y0, int x1, int y1, int x2, int y2, int x3, int y3, ! 159: int& xinter, int& yinter) { ! 160: double m0,b0,m1,b1,x; ! 161: ! 162: if ((x0 == x1) && (x2 == x3)) return false; ! 163: if (x2 == x3) {swap(x0,x2); swap(x1,x3); swap(y0,y2); swap(y1,y3);} ! 164: if (x0 == x1) { ! 165: x = x0; ! 166: } ! 167: else { ! 168: m0 = (y1 - y0)/(double)(x1 - x0); ! 169: b0 = y0 - m0*x0; ! 170: m1 = (y3 - y2)/(double)(x3 - x2); ! 171: b1 = y2 - m1*x2; ! 172: if (m1 == m0) { ! 173: if (b0 != b1) return false; ! 174: int l0lowx = min(x0,x1); ! 175: int l0highx = max(x0,x1); ! 176: int l1lowx = min(x2,x3); ! 177: int l1highx = max(x2,x3); ! 178: if (between(l0lowx,l1lowx,l0highx)) ! 179: x = l1lowx; ! 180: else if (between(l0lowx,l1highx,l0highx)) ! 181: x = l1highx; ! 182: else if (between(l1lowx,l0lowx,l1highx)) ! 183: x = l0lowx; ! 184: else return false; ! 185: } ! 186: else x = (b1 - b0)/(m0 - m1); ! 187: } ! 188: ! 189: if (between(x2,round(x),x3)) { ! 190: if (between(y2,round(m1 * x + b1),y3)) { ! 191: yinter = round(m1 * x + b1); ! 192: xinter = round(x); ! 193: return true; ! 194: } ! 195: } ! 196: return false; ! 197: } ! 198: ! 199: /* ! 200: * return point of intersection of the node ! 201: * with the ray from (x0,y0) through (x1,y1). ! 202: * p1 must be on the bounding box of the node. ! 203: * assume User_defined nodes are like Box. ! 204: */ ! 205: Point find_nodeport(int node, Point p0, Point p1) { ! 206: Point rv; ! 207: if ((p0.x == p1.x) && (p0.y == p1.y)) {return p0;} ! 208: int x0 = p0.x; int y0 = p0.y; int x1 = p1.x; int y1 = p1.y; ! 209: ! 210: /* handle degenerate case of vertical line segment */ ! 211: if (x0 == x1) return p1; ! 212: ! 213: while (1) { ! 214: /* normal case */ ! 215: double m = (double)(y1 - y0) / (double)(x1 - x0); ! 216: double b = y0 - m * x0; ! 217: switch(Node[node]->shape.shape_id) { ! 218: case Circle: ! 219: case Doublecircle: ! 220: case Ellipse: ! 221: double s0,s1; // two solutions (x values) ! 222: //double b1 = m*Node[node]->pos.x + b - Node[node]->pos.y; ! 223: double b1 = (y0 - Node[node]->pos.y) - m * (x0 - Node[node]->pos.x); ! 224: double rx = Node[node]->xsize/2.; ! 225: double ry = Node[node]->ysize/2.; ! 226: double aa = 1/(rx*rx) + (m*m)/(ry*ry); ! 227: double bb = 2.*m*b1/(ry*ry); ! 228: double cc = (b1*b1)/(ry*ry) - 1; ! 229: if (m == 0.) { ! 230: s0 = rx; ! 231: s1 = -rx; ! 232: } ! 233: else { ! 234: double t = bb*bb - 4.*aa*cc; ! 235: if (t < 0) { ! 236: if (x1 == Node[node]->pos.x && y1 == Node[node]->pos.y) ! 237: panic("can't find node intersection"); ! 238: x1 = Node[node]->pos.x; ! 239: y1 = Node[node]->pos.y; ! 240: continue; ! 241: } ! 242: s0 = (-bb + sqrt(t))/(2.*aa); ! 243: s1 = (-bb - sqrt(t))/(2.*aa); ! 244: } ! 245: s0 += Node[node]->pos.x; ! 246: s1 += Node[node]->pos.x; ! 247: if (distance(s0,m*s0+b,x0,y0) <= distance(s1,m*s1+b,x0,y0)) { ! 248: rv.x = round(s0); ! 249: rv.y = round(s0 * m + b); ! 250: } ! 251: else { ! 252: rv.x = round(s1); ! 253: rv.y = round(s1 * m + b); ! 254: } ! 255: return rv; ! 256: case Diamond: ! 257: x1 = Node[node]->pos.x; ! 258: y1 = (int)(m*x1 + b); ! 259: switch((sign(x0 - Node[node]->pos.x)== -1) + 2*(sign(y0 - Node[node]->pos.y)== -1)) { ! 260: case 0: ! 261: if (seginter(x0,y0,x1,y1,Node[node]->pos.x+Node[node]->xsize/2,Node[node]->pos.y,Node[node]->pos.x,Node[node]->pos.y+Node[node]->ysize/2,rv.x,rv.y)) return rv; ! 262: break; ! 263: case 1: ! 264: if (seginter(x0,y0,x1,y1,Node[node]->pos.x,Node[node]->pos.y+Node[node]->ysize/2,Node[node]->pos.x-Node[node]->xsize/2,Node[node]->pos.y,rv.x,rv.y)) return rv; ! 265: break; ! 266: case 2: ! 267: if (seginter(x0,y0,x1,y1,Node[node]->pos.x,Node[node]->pos.y-Node[node]->ysize/2,Node[node]->pos.x+Node[node]->xsize/2,Node[node]->pos.y,rv.x,rv.y)) return rv; ! 268: break; ! 269: case 3: ! 270: if (seginter(x0,y0,x1,y1,Node[node]->pos.x-Node[node]->xsize/2,Node[node]->pos.y,Node[node]->pos.x,Node[node]->pos.y-Node[node]->ysize/2,rv.x,rv.y)) return rv; ! 271: break; ! 272: } ! 273: case Box: ! 274: case Square: ! 275: case Plaintext: ! 276: case User_defined: ! 277: default: ! 278: return p1; ! 279: } ! 280: } ! 281: } ! 282: ! 283: void reclaim_hashtable() { ! 284: for (int i = 0; i < Hash_extent; i++) { ! 285: hashrec *h,*h1; ! 286: if (Hashtab[i]) ! 287: for (h = Hashtab[i], h1 = h->next; h1; h1=h1->next){ ! 288: delete h; h = h1; ! 289: } ! 290: Hashtab[i] = 0; ! 291: } ! 292: } ! 293: ! 294: void set_output_type(char *name) { ! 295: const int n_output_types = 4; ! 296: static struct { ! 297: char* name; ! 298: output_lang_t lang; ! 299: } map[] = { ! 300: "pic", Pic, ! 301: "ps", Postscript, ! 302: "simple", Graphdraw, ! 303: "cip", Cip ! 304: }; ! 305: for (int i = 0; i < n_output_types; i++) ! 306: if (!strcmp(name,map[i].name)) { ! 307: Output_type = map[i].lang; ! 308: return; ! 309: } ! 310: fprintf(stderr,"%s: warning, no output driver for %s, option ignored.\n", ! 311: Cmd_name,name); ! 312: } ! 313: ! 314: void set_page_size(char *arg) { ! 315: double w,h,mw,mh; /* width, height, margin width, margin height */ ! 316: int nargs; ! 317: nargs = sscanf(arg,"%lfx%lf,%lfx%lf",&w,&h,&mw,&mh); ! 318: if (nargs > 1) { ! 319: Page_size.x = (int)(w*Resolution); ! 320: Page_size.y = (int)(h*Resolution); ! 321: } ! 322: if (nargs > 2) { ! 323: Margin.x = (int)(mw * Resolution); ! 324: if (nargs > 3) Margin.y = (int)(mh * Resolution); ! 325: else Margin.y = Margin.x; ! 326: } ! 327: Page_size.x -= 2*Margin.x; ! 328: Page_size.y -= 2*Margin.y; ! 329: if (Page_size.x <= 0 || Page_size.y <= 0) { ! 330: fprintf(stderr,"%s: warning, bad page or margin size options (ignored)\n",Cmd_name); ! 331: Page_size.x = 0; Page_size.y = 0; ! 332: } ! 333: } ! 334: ! 335: options_t reset_options() { ! 336: options_t rv; ! 337: ! 338: rv.quick = Default_options_quick; ! 339: rv.verbose = Default_options_verbose; ! 340: rv.rankadjust = Default_options_rankadjust; ! 341: rv.ranksep = Default_options_ranksep; ! 342: rv.nodesep = Default_options_nodesep; ! 343: rv.xbound = 0; ! 344: rv.ybound = 0; ! 345: ! 346: rv.n_same_nodes= 0; ! 347: rv.same_nodes = 0; ! 348: rv.source_nodes= 0; ! 349: rv.sink_nodes = 0; ! 350: return rv; ! 351: } ! 352: ! 353: void set_bounds(double xdimen, double ydimen) { ! 354: if ((xdimen <= 0.0) || (ydimen <= 0.0)) return; ! 355: /* the following because the picture will be rotated down in draw_dag */ ! 356: if (User.rotated) {double t = xdimen; xdimen = ydimen; ydimen = t;} ! 357: Options.xbound = round(xdimen * Resolution); ! 358: Options.ybound = round(ydimen * Resolution); ! 359: } ! 360: ! 361: shape_t::shape_t(int intype, char* invalue) { ! 362: const int n_predefined_shapes = 7; ! 363: static struct { ! 364: char * n; ! 365: shape_id_t s; ! 366: } map[] = { ! 367: "Circle", Circle, ! 368: "Doublecircle", Doublecircle, ! 369: "Box", Box, ! 370: "Ellipse", Ellipse, ! 371: "Square", Square, ! 372: "Plaintext", Plaintext, ! 373: "Diamond", Diamond ! 374: }; ! 375: type = intype; ! 376: value = invalue; ! 377: if (type == STRING) { ! 378: for (int i = 0; i < n_predefined_shapes; i++) { ! 379: if (!strcmp(invalue,map[i].n)) { ! 380: type = intype; ! 381: predefined = true; ! 382: shape_id = map[i].s; ! 383: return; ! 384: } ! 385: } ! 386: } ! 387: predefined = false; ! 388: shape_id = User_defined; ! 389: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.