00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00030 #include <stdio.h>
00031 #include <ctype.h>
00032 #include <sys/stat.h>
00033 #include <sys/types.h>
00034 #include <errno.h>
00035 #include <string.h>
00036
00037 #include <ostream>
00038 #include <sstream>
00039 #include <set>
00040 #include <utility>
00041 #include <map>
00042 #include <stack>
00043 #include <string>
00044
00045 #include "boxes.hh"
00046 #include "ppbox.hh"
00047 #include "prim2.hh"
00048
00049 #include <vector>
00050 #include "devLib.h"
00051 #include "ppbox.hh"
00052 #include "xtended.hh"
00053 #include "occurrences.hh"
00054 #include "boxcomplexity.h"
00055
00056 #include "schema.h"
00057 #include "drawschema.hh"
00058 #include "compatibility.hh"
00059 #include "names.hh"
00060
00061
00062 #if 0
00063 #define linkcolor "#b3d1dc"
00064 #define normalcolor "#ffeaa2"
00065 #define uicolor "#F1CFA1"
00066 #define slotcolor "#ffffd7"
00067 #define numcolor "#ffffff"
00068 #endif
00069
00070 #if 0
00071 #define linkcolor "#F57900"
00072 #define normalcolor "#4B71A1"
00073 #define uicolor "#47945E"
00074 #define slotcolor "#EDD400"
00075 #define numcolor "#4B71A1"
00076 #endif
00077
00078 #if 0
00079 #define linkcolor "#47945E"
00080 #define normalcolor "#4B71A1"
00081 #define uicolor "#f44800"
00082 #define slotcolor "#EDD400"
00083 #define numcolor "#f44800"
00084 #endif
00085
00086 #if 0
00087 #define linkcolor "#47945E"
00088 #define normalcolor "#4B71A1"
00089 #define uicolor "#816647"
00090 #define slotcolor "#EDD400"
00091 #define numcolor "#f44800"
00092 #endif
00093
00094 #if 0
00095 #define linkcolor "#003366"
00096 #define normalcolor "#4B71A1"
00097 #define uicolor "#816647"
00098 #define slotcolor "#EDD400"
00099 #define numcolor "#f44800"
00100 #endif
00101
00102 #if 0
00103 #define linkcolor "#003366"
00104 #define normalcolor "#4B71A1"
00105 #define uicolor "#477881"
00106 #define slotcolor "#816647"
00107 #define numcolor "#f44800"
00108 #endif
00109
00110
00111 #if 1
00112 #define linkcolor "#003366"
00113 #define normalcolor "#4B71A1"
00114 #define uicolor "#477881"
00115 #define slotcolor "#47945E"
00116 #define numcolor "#f44800"
00117 #endif
00118
00119 using namespace std;
00120
00121
00122 extern int gFoldThreshold;
00123
00124
00125
00126 static Occurrences* gOccurrences;
00127 static bool sFoldingFlag;
00128 static stack<Tree> gPendingExp;
00129 static set<Tree> gDrawnExp;
00130 static const char* gDevSuffix;
00131 static char gCurrentDir[512];
00132 static string gSchemaFileName;
00133 static map<Tree,string> gBackLink;
00134
00135
00136 static void writeSchemaFile(Tree bd);
00137 static schema* generateDiagramSchema (Tree bd);
00138 static schema* generateInsideSchema(Tree t);
00139 static void scheduleDrawing(Tree t);
00140 static bool pendingDrawing(Tree& t);
00141 static schema* generateAbstractionSchema(schema* x, Tree t);
00142 static schema* generateOutputSlotSchema(Tree a);
00143 static schema* generateInputSlotSchema(Tree a);
00144 static schema* generateBargraphSchema(Tree t);
00145 static schema* generateUserInterfaceSchema(Tree t);
00146 static char* legalFileName(Tree t, int n, char* dst);
00147 static int cholddir ();
00148 static int mkchdir(const char* dirname);
00149
00150
00151
00152
00158 void drawSchema(Tree bd, const char* projname, const char* dev)
00159 {
00160 gDevSuffix = dev;
00161 sFoldingFlag = boxComplexity(bd) > gFoldThreshold;
00162
00163 mkchdir(projname);
00164
00165 scheduleDrawing(bd);
00166
00167 Tree t; while (pendingDrawing(t)) {
00168 writeSchemaFile(t);
00169 }
00170
00171 cholddir();
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00187 static void scheduleDrawing(Tree t)
00188 {
00189 if (gDrawnExp.find(t) == gDrawnExp.end()) {
00190 gDrawnExp.insert(t);
00191 gBackLink.insert(make_pair(t,gSchemaFileName));
00192 gPendingExp.push(t);
00193 }
00194 }
00195
00199 static bool pendingDrawing(Tree& t)
00200 {
00201 if (gPendingExp.empty()) return false;
00202 t = gPendingExp.top();
00203 gPendingExp.pop();
00204 return true;
00205 }
00206
00207
00208
00209
00210
00216 static void writeSchemaFile(Tree bd)
00217 {
00218 Tree id;
00219 schema* ts;
00220
00221 char temp[1024];
00222
00223 gOccurrences = new Occurrences(bd);
00224
00225 bool hasname = getDefNameProperty(bd, id);
00226
00227
00228 if (!hasname) {
00229
00230 id = tree(Node(unique("diagram_")));
00231 }
00232
00233
00234 stringstream s1; s1 << legalFileName(bd, 1024, temp) << "." << gDevSuffix;
00235 gSchemaFileName = s1.str();
00236
00237
00238 stringstream s2; s2 << tree2str(id);
00239 string link = gBackLink[bd];
00240 ts = makeTopSchema(generateInsideSchema(bd), 20, s2.str(), link);
00241
00242 if (strcmp(gDevSuffix, "svg") == 0) {
00243 SVGDev dev(s1.str().c_str(), ts->width(), ts->height());
00244 ts->place(0,0, kLeftRight);
00245 ts->draw(dev);
00246 } else {
00247 PSDev dev(s1.str().c_str(), ts->width(), ts->height());
00248 ts->place(0,0, kLeftRight);
00249 ts->draw(dev);
00250 }
00251 }
00252
00253
00254
00259 static int mkchdir(const char* dirname)
00260 {
00261
00262 if (getcwd(gCurrentDir, 512) != 0) {
00263 int status = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
00264 if (status == 0 || errno == EEXIST) {
00265 if (chdir(dirname) == 0) {
00266 return 0;
00267 }
00268 }
00269 }
00270 perror("mkchdir");
00271 exit(errno);
00272
00273 }
00274
00275
00279 static int cholddir ()
00280 {
00281 if (chdir(gCurrentDir) == 0) {
00282 return 0;
00283 } else {
00284 perror("cholddir");
00285 exit(errno);
00286 }
00287 }
00288
00289
00296 static char* legalFileName(Tree t, int n, char* dst)
00297 {
00298 Tree id;
00299 int i=0;
00300 if (getDefNameProperty(t, id)) {
00301 const char* src = tree2str(id);
00302 for (i=0; isalnum(src[i]) && i<16; i++) {
00303 dst[i] = src[i];
00304 }
00305 }
00306 dst[i] = 0;
00307 if (strcmp(dst, "process") != 0) {
00308
00309 snprintf(&dst[i], n-i, "-%p", t);
00310 }
00311 return dst;
00312 }
00313
00314
00315
00316
00317
00324 static schema* generateDiagramSchema(Tree t)
00325 {
00326 Tree id;
00327 int ins, outs;
00328
00329
00330
00331 if (getDefNameProperty(t, id)) {
00332 stringstream s; s << tree2str(id);
00333
00334 }
00335
00336 if ( sFoldingFlag &&
00337 (boxComplexity(t) > 2) && getDefNameProperty(t, id)) {
00338 char temp[1024];
00339 getBoxType(t, &ins, &outs);
00340 stringstream s, l;
00341 s << tree2str(id);
00342 l << legalFileName(t,1024,temp) << "." << gDevSuffix;
00343 scheduleDrawing(t);
00344 return makeBlockSchema(ins, outs, s.str(), linkcolor, l.str());
00345
00346 } else if (getDefNameProperty(t, id) && ! isBoxSlot(t)) {
00347
00348
00349 stringstream s; s << tree2str(id);
00350 return makeDecorateSchema(generateInsideSchema(t), 10, s.str());
00351
00352 } else {
00353
00354 return generateInsideSchema(t);
00355 }
00356 }
00357
00358
00359
00364 static schema* generateInsideSchema(Tree t)
00365 {
00366 Tree a, b, ff, l, type,name,file;
00367 int i;
00368 double r;
00369 prim0 p0;
00370 prim1 p1;
00371 prim2 p2;
00372 prim3 p3;
00373 prim4 p4;
00374 prim5 p5;
00375
00376
00377 xtended* xt = (xtended*)getUserData(t);
00378
00379 if (xt) { return makeBlockSchema(xt->arity(), 1, xt->name(), normalcolor, ""); }
00380
00381 else if (isBoxInt(t, &i)) { stringstream s; s << i; return makeBlockSchema(0, 1, s.str(), numcolor, "" ); }
00382 else if (isBoxReal(t, &r)) { stringstream s; s << r; return makeBlockSchema(0, 1, s.str(), numcolor, "" ); }
00383 else if (isBoxWire(t)) { return makeCableSchema(); }
00384 else if (isBoxCut(t)) { return makeCutSchema(); }
00385
00386 else if (isBoxPrim0(t, &p0)) { return makeBlockSchema(0, 1, prim0name(p0), normalcolor, ""); }
00387 else if (isBoxPrim1(t, &p1)) { return makeBlockSchema(1, 1, prim1name(p1), normalcolor, ""); }
00388 else if (isBoxPrim2(t, &p2)) { return makeBlockSchema(2, 1, prim2name(p2), normalcolor, ""); }
00389 else if (isBoxPrim3(t, &p3)) { return makeBlockSchema(3, 1, prim3name(p3), normalcolor, ""); }
00390 else if (isBoxPrim4(t, &p4)) { return makeBlockSchema(4, 1, prim4name(p4), normalcolor, ""); }
00391 else if (isBoxPrim5(t, &p5)) { return makeBlockSchema(5, 1, prim5name(p5), normalcolor, ""); }
00392
00393 else if (isBoxFFun(t, ff)) { return makeBlockSchema(ffarity(ff), 1, ffname(ff), normalcolor, ""); }
00394 else if (isBoxFConst(t, type,name,file)) { return makeBlockSchema(0, 1, tree2str(name), normalcolor, ""); }
00395 else if (isBoxFVar (t, type, name,file)) { return makeBlockSchema(0, 1, tree2str(name), normalcolor, ""); }
00396
00397 else if (isBoxButton(t)) { return generateUserInterfaceSchema(t); }
00398 else if (isBoxCheckbox(t)) { return generateUserInterfaceSchema(t); }
00399 else if (isBoxVSlider(t)) { return generateUserInterfaceSchema(t); }
00400 else if (isBoxHSlider(t)) { return generateUserInterfaceSchema(t); }
00401 else if (isBoxNumEntry(t)) { return generateUserInterfaceSchema(t); }
00402 else if (isBoxVBargraph(t)) { return generateBargraphSchema(t); }
00403 else if (isBoxHBargraph(t)) { return generateBargraphSchema(t); }
00404
00405
00406 else if (isBoxVGroup(t,l,a)) { stringstream s; s << "vgroup(" << tree2str(l) << ")";
00407 schema* r = generateDiagramSchema(a);
00408 return makeDecorateSchema(r, 10, s.str()); }
00409 else if (isBoxHGroup(t,l,a)) { stringstream s; s << "hgroup(" << tree2str(l) << ")";
00410 schema* r = generateDiagramSchema(a);
00411 return makeDecorateSchema(r, 10, s.str()); }
00412 else if (isBoxTGroup(t,l,a)) { stringstream s; s << "tgroup(" << tree2str(l) << ")";
00413 schema* r = generateDiagramSchema(a);
00414 return makeDecorateSchema(r, 10, s.str()); }
00415
00416 else if (isBoxSeq(t, a, b)) { return makeSeqSchema(generateDiagramSchema(a), generateDiagramSchema(b)); }
00417 else if (isBoxPar(t, a, b)) { return makeParSchema(generateDiagramSchema(a), generateDiagramSchema(b)); }
00418 else if (isBoxSplit(t, a, b)) { return makeSplitSchema(generateDiagramSchema(a), generateDiagramSchema(b)); }
00419 else if (isBoxMerge(t, a, b)) { return makeMergeSchema(generateDiagramSchema(a), generateDiagramSchema(b)); }
00420 else if (isBoxRec(t, a, b)) { return makeRecSchema(generateDiagramSchema(a), generateDiagramSchema(b)); }
00421
00422 else if (isBoxSlot(t, &i)) { return generateOutputSlotSchema(t); }
00423 else if (isBoxSymbolic(t,a,b)) {
00424 Tree id;
00425 if (getDefNameProperty(t, id)) {
00426 return generateAbstractionSchema(generateInputSlotSchema(a), b);
00427 } else {
00428 return makeDecorateSchema(generateAbstractionSchema(generateInputSlotSchema(a), b), 10, "Abstraction");
00429 }
00430 }
00431
00432 else {
00433
00434 fprintf(stderr, "Internal Error, box expression not recognized : "); print(t, stderr); fprintf(stderr, "\n");
00435 exit(1);
00436
00437 }
00438 }
00439
00440
00441
00442
00446 static schema* generateUserInterfaceSchema(Tree t)
00447 {
00448 stringstream s;
00449 s << boxpp(t);
00450
00451 return makeBlockSchema(0, 1, s.str(), uicolor, "");
00452 }
00453
00454
00455
00459 static schema* generateBargraphSchema(Tree t)
00460 {
00461 stringstream s;
00462 s << boxpp(t);
00463
00464 return makeBlockSchema(1, 1, s.str(), uicolor, "");
00465 }
00466
00467
00468
00472 static schema* generateInputSlotSchema(Tree a)
00473 {
00474 Tree id; assert(getDefNameProperty(a, id));
00475 stringstream s; s << tree2str(id);
00476 return makeBlockSchema(1, 0, s.str(), slotcolor, "");
00477 }
00478
00479
00480
00484 static schema* generateOutputSlotSchema(Tree a)
00485 {
00486 Tree id; assert(getDefNameProperty(a, id));
00487 stringstream s; s << tree2str(id);
00488 return makeBlockSchema(0, 1, s.str(), slotcolor, "");
00489 }
00490
00491
00492
00497 static schema* generateAbstractionSchema(schema* x, Tree t)
00498 {
00499 Tree a,b;
00500
00501 while (isBoxSymbolic(t,a,b)) {
00502 x = makeParSchema(x, generateInputSlotSchema(a));
00503 t = b;
00504 }
00505 return makeSeqSchema(x, generateDiagramSchema(t));
00506 }
00507