|
|
researchv10 Norman
#include "draw_dag.h"
#include "dag.h"
#include "paths.h"
#include "parsedag.h"
#include "defaults.h"
#include "unistd.h"
/*** utility functions ***/
char* Infile::gets(char *buf,int n) {
if (!fp) return 0;
line_number++;
return fgets(buf,n,fp);
}
Infile nextfile(char** &argv)
{
argv++;
while (**argv == '-') argv++;
Infile rv = Infile(*argv);
if (!rv.fp) fprintf(stderr,"%s: can't open %s\n",Cmd_name,*argv);
return rv;
}
/*** shared strings ***/
shared_string_t *shared_string_pool;
char *newstring(char *init) {
shared_string_t *it
= (shared_string_t*) malloc(sizeof(shared_string_t) + strlen(init));
it->next = shared_string_pool;
shared_string_pool = it;
strcpy(it->data,init);
return it->data;
}
void freestrings() {
shared_string_t *q,*p = shared_string_pool;
while (p) {
q = p->next;
free((char*)p);
p = q;
}
shared_string_pool = 0;
}
/*** hash table ***/
int hash(register char* s, int size) {
register unsigned int h;
register int c;
h = 0;
while (c = *s++) {
if ((h <<= 1) < 0) h ^= c ^ ((~(((unsigned int)~0) >> 1)) | 1);
else h ^= c;
}
return(h % size);
}
const int Hash_extent = 517;
struct hashrec {
int node;
hashrec *next;
hashrec(int argnode, hashrec *argnext) {
node = argnode;
next = argnext;
};
} *Hashtab[Hash_extent];
boolean expand_graph(int new_size) {
if (! (Node = (DAG_node_t**)realloc((char*)Node,sizeof(DAG_node_t*)*new_size)))
return false;
else
if (! (Edge = (DAG_edge_t**)realloc((char*)Edge,sizeof(DAG_edge_t*)*new_size)))
return false;
return true;
}
/* look name and insert in symbol table if not found. return new node's number. */
int node_lookup(char *name) {
int h = hash(name,Hash_extent);
for (hashrec *hp = Hashtab[h]; hp; hp = hp->next)
if (!strcmp(name,Node[hp->node]->name)) break;
if (!hp) {
Hashtab[h] = hp = new hashrec(N,Hashtab[h]);
if (N > Extent - 1) {
Extent += Extent;
if (!expand_graph(Extent)) {
yyerror("too many nodes, out of memory");
exit(1);
}
}
Node[N] = new DAG_node_t();
*Node[N] = Default_node;
Node[N]->setname(name);
Edge[N] = (DAG_edge_t*)0;
N++;
}
return hp->node;
}
/*** utility functions for code gen */
void cat_libfile(char* name) {
char buf[BUFSIZ];
if (!Uselib) return;
if (!Lib_path) {
#ifdef EXPTOOLS
char *tools = getenv("TOOLS");
if (tools) {
Lib_path = new char[strlen(Lib_path)+strlen(EXPTOOLS_SUBDIR)+2];
sprintf(Lib_path,"%s/%s",tools,EXPTOOLS_SUBDIR);
sprintf(buf,"%s/%s",Lib_path,name);
if (access(buf,R_OK))
Lib_path = LIB_PATH;
}
else
#endif EXPTOOLS
Lib_path = LIB_PATH;
}
fflush(stdout);
sprintf(buf,"cat %s/%s",Lib_path,name);
system(buf);
}
Point find_edge_midpoint(DAG_edge_t *e) {
int x,y;
for (int npts = 0; e->splinept[npts].y >= 0; npts++);
if (iabs(e->splinept[0].y - e->splinept[npts-1].y) >
iabs(e->splinept[0].x - e->splinept[npts-1].x)) { // "vertical" edge
int i,y1 = 0;
y1 = (e->splinept[0].y + e->splinept[npts-1].y)/2;
for (i = 0; e->splinept[i].y >= 0; i++)
if (between(e->splinept[i].y,y1,e->splinept[i+1].y)) break;
y = y1;
x = (int) (e->splinept[i].x +
(double)(y1 - e->splinept[i].y)/(e->splinept[i+1].y-e->splinept[i].y)
* (e->splinept[i+1].x - e->splinept[i].x));
}
else { // "horizontal" edge
int i,x1 = 0;
x1 = (e->splinept[0].x + e->splinept[npts-1].x)/2;
for (i = 0; e->splinept[i].y >= 0; i++)
if (between(e->splinept[i].x,x1,e->splinept[i+1].x)) break;
x = x1;
y = (int) (e->splinept[i].y +
(double)(x1 - e->splinept[i].x)/(e->splinept[i+1].x-e->splinept[i].x)
* (e->splinept[i+1].y - e->splinept[i].y));
}
Point rv;
rv .x = x; rv .y = y;
return rv;
}
static boolean seginter(int x0,int y0, int x1, int y1, int x2, int y2, int x3, int y3,
int& xinter, int& yinter) {
double m0,b0,m1,b1,x;
if ((x0 == x1) && (x2 == x3)) return false;
if (x2 == x3) {swap(x0,x2); swap(x1,x3); swap(y0,y2); swap(y1,y3);}
if (x0 == x1) {
x = x0;
}
else {
m0 = (y1 - y0)/(double)(x1 - x0);
b0 = y0 - m0*x0;
m1 = (y3 - y2)/(double)(x3 - x2);
b1 = y2 - m1*x2;
if (m1 == m0) {
if (b0 != b1) return false;
int l0lowx = min(x0,x1);
int l0highx = max(x0,x1);
int l1lowx = min(x2,x3);
int l1highx = max(x2,x3);
if (between(l0lowx,l1lowx,l0highx))
x = l1lowx;
else if (between(l0lowx,l1highx,l0highx))
x = l1highx;
else if (between(l1lowx,l0lowx,l1highx))
x = l0lowx;
else return false;
}
else x = (b1 - b0)/(m0 - m1);
}
if (between(x2,round(x),x3)) {
if (between(y2,round(m1 * x + b1),y3)) {
yinter = round(m1 * x + b1);
xinter = round(x);
return true;
}
}
return false;
}
/*
* return point of intersection of the node
* with the ray from (x0,y0) through (x1,y1).
* p1 must be on the bounding box of the node.
* assume User_defined nodes are like Box.
*/
Point find_nodeport(int node, Point p0, Point p1) {
Point rv;
if ((p0.x == p1.x) && (p0.y == p1.y)) {return p0;}
int x0 = p0.x; int y0 = p0.y; int x1 = p1.x; int y1 = p1.y;
/* handle degenerate case of vertical line segment */
if (x0 == x1) return p1;
while (1) {
/* normal case */
double m = (double)(y1 - y0) / (double)(x1 - x0);
double b = y0 - m * x0;
switch(Node[node]->shape.shape_id) {
case Circle:
case Doublecircle:
case Ellipse:
double s0,s1; // two solutions (x values)
//double b1 = m*Node[node]->pos.x + b - Node[node]->pos.y;
double b1 = (y0 - Node[node]->pos.y) - m * (x0 - Node[node]->pos.x);
double rx = Node[node]->xsize/2.;
double ry = Node[node]->ysize/2.;
double aa = 1/(rx*rx) + (m*m)/(ry*ry);
double bb = 2.*m*b1/(ry*ry);
double cc = (b1*b1)/(ry*ry) - 1;
if (m == 0.) {
s0 = rx;
s1 = -rx;
}
else {
double t = bb*bb - 4.*aa*cc;
if (t < 0) {
if (x1 == Node[node]->pos.x && y1 == Node[node]->pos.y)
panic("can't find node intersection");
x1 = Node[node]->pos.x;
y1 = Node[node]->pos.y;
continue;
}
s0 = (-bb + sqrt(t))/(2.*aa);
s1 = (-bb - sqrt(t))/(2.*aa);
}
s0 += Node[node]->pos.x;
s1 += Node[node]->pos.x;
if (distance(s0,m*s0+b,x0,y0) <= distance(s1,m*s1+b,x0,y0)) {
rv.x = round(s0);
rv.y = round(s0 * m + b);
}
else {
rv.x = round(s1);
rv.y = round(s1 * m + b);
}
return rv;
case Diamond:
x1 = Node[node]->pos.x;
y1 = (int)(m*x1 + b);
switch((sign(x0 - Node[node]->pos.x)== -1) + 2*(sign(y0 - Node[node]->pos.y)== -1)) {
case 0:
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;
break;
case 1:
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;
break;
case 2:
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;
break;
case 3:
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;
break;
}
case Box:
case Square:
case Plaintext:
case User_defined:
default:
return p1;
}
}
}
void reclaim_hashtable() {
for (int i = 0; i < Hash_extent; i++) {
hashrec *h,*h1;
if (Hashtab[i])
for (h = Hashtab[i], h1 = h->next; h1; h1=h1->next){
delete h; h = h1;
}
Hashtab[i] = 0;
}
}
void set_output_type(char *name) {
const int n_output_types = 4;
static struct {
char* name;
output_lang_t lang;
} map[] = {
"pic", Pic,
"ps", Postscript,
"simple", Graphdraw,
"cip", Cip
};
for (int i = 0; i < n_output_types; i++)
if (!strcmp(name,map[i].name)) {
Output_type = map[i].lang;
return;
}
fprintf(stderr,"%s: warning, no output driver for %s, option ignored.\n",
Cmd_name,name);
}
void set_page_size(char *arg) {
double w,h,mw,mh; /* width, height, margin width, margin height */
int nargs;
nargs = sscanf(arg,"%lfx%lf,%lfx%lf",&w,&h,&mw,&mh);
if (nargs > 1) {
Page_size.x = (int)(w*Resolution);
Page_size.y = (int)(h*Resolution);
}
if (nargs > 2) {
Margin.x = (int)(mw * Resolution);
if (nargs > 3) Margin.y = (int)(mh * Resolution);
else Margin.y = Margin.x;
}
Page_size.x -= 2*Margin.x;
Page_size.y -= 2*Margin.y;
if (Page_size.x <= 0 || Page_size.y <= 0) {
fprintf(stderr,"%s: warning, bad page or margin size options (ignored)\n",Cmd_name);
Page_size.x = 0; Page_size.y = 0;
}
}
options_t reset_options() {
options_t rv;
rv.quick = Default_options_quick;
rv.verbose = Default_options_verbose;
rv.rankadjust = Default_options_rankadjust;
rv.ranksep = Default_options_ranksep;
rv.nodesep = Default_options_nodesep;
rv.xbound = 0;
rv.ybound = 0;
rv.n_same_nodes= 0;
rv.same_nodes = 0;
rv.source_nodes= 0;
rv.sink_nodes = 0;
return rv;
}
void set_bounds(double xdimen, double ydimen) {
if ((xdimen <= 0.0) || (ydimen <= 0.0)) return;
/* the following because the picture will be rotated down in draw_dag */
if (User.rotated) {double t = xdimen; xdimen = ydimen; ydimen = t;}
Options.xbound = round(xdimen * Resolution);
Options.ybound = round(ydimen * Resolution);
}
shape_t::shape_t(int intype, char* invalue) {
const int n_predefined_shapes = 7;
static struct {
char * n;
shape_id_t s;
} map[] = {
"Circle", Circle,
"Doublecircle", Doublecircle,
"Box", Box,
"Ellipse", Ellipse,
"Square", Square,
"Plaintext", Plaintext,
"Diamond", Diamond
};
type = intype;
value = invalue;
if (type == STRING) {
for (int i = 0; i < n_predefined_shapes; i++) {
if (!strcmp(invalue,map[i].n)) {
type = intype;
predefined = true;
shape_id = map[i].s;
return;
}
}
}
predefined = false;
shape_id = User_defined;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.