Implement block-diagram schema generation in svg or postscript format. More...
#include <stdio.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <ostream>
#include <sstream>
#include <set>
#include <utility>
#include <map>
#include <stack>
#include <string>
#include "boxes.hh"
#include "ppbox.hh"
#include "prim2.hh"
#include <vector>
#include "devLib.h"
#include "xtended.hh"
#include "occurrences.hh"
#include "boxcomplexity.h"
#include "schema.h"
#include "drawschema.hh"
#include "compatibility.hh"
#include "names.hh"
Go to the source code of this file.
Defines | |
#define | linkcolor "#003366" |
#define | normalcolor "#4B71A1" |
#define | uicolor "#477881" |
#define | slotcolor "#47945E" |
#define | numcolor "#f44800" |
Functions | |
static void | writeSchemaFile (Tree bd) |
Write a top level diagram. | |
static schema * | generateDiagramSchema (Tree t) |
Generate an appropriate schema according to the type of block diagram. | |
static schema * | generateInsideSchema (Tree t) |
Generate the inside schema of a block diagram according to its type. | |
static void | scheduleDrawing (Tree t) |
Schedule a makeBlockSchema diagram to be drawn. | |
static bool | pendingDrawing (Tree &t) |
Retrieve next block diagram that must be drawn. | |
static schema * | generateAbstractionSchema (schema *x, Tree t) |
Generate an abstraction schema by placing in sequence the input slots and the body. | |
static schema * | generateOutputSlotSchema (Tree a) |
Generate a 0->1 block schema for an output slot. | |
static schema * | generateInputSlotSchema (Tree a) |
Generate a 1->0 block schema for an input slot. | |
static schema * | generateBargraphSchema (Tree t) |
Generate a 1->1 block schema for a user interface bargraph. | |
static schema * | generateUserInterfaceSchema (Tree t) |
Generate a 0->1 block schema for a user interface element. | |
static char * | legalFileName (Tree t, int n, char *dst) |
Transform the definition name property of tree <t> into a legal file name. | |
static int | cholddir () |
Switch back to the previously stored current directory. | |
static int | mkchdir (const char *dirname) |
Create a new directory in the current one to store the diagrams. | |
void | drawSchema (Tree bd, const char *projname, const char *dev) |
The entry point to generate from a block diagram as a set of svg files stored in the directory "<projname>-svg/" or "<projname>-ps/" depending of <dev>. | |
Variables | |
int | gFoldThreshold |
static Occurrences * | gOccurrences |
static bool | sFoldingFlag |
static stack< Tree > | gPendingExp |
static set< Tree > | gDrawnExp |
static const char * | gDevSuffix |
static char | gCurrentDir [512] |
static string | gSchemaFileName |
static map< Tree, string > | gBackLink |
Implement block-diagram schema generation in svg or postscript format.
The result is a folder containing one or more schema files in svg or ps format. Complex block-diagrams are automatically splitted.
Definition in file drawschema.cpp.
#define linkcolor "#003366" |
Definition at line 112 of file drawschema.cpp.
Referenced by generateDiagramSchema().
#define normalcolor "#4B71A1" |
Definition at line 113 of file drawschema.cpp.
Referenced by generateInsideSchema().
#define numcolor "#f44800" |
Definition at line 116 of file drawschema.cpp.
Referenced by generateInsideSchema().
#define slotcolor "#47945E" |
Definition at line 115 of file drawschema.cpp.
Referenced by generateInputSlotSchema(), and generateOutputSlotSchema().
#define uicolor "#477881" |
Definition at line 114 of file drawschema.cpp.
Referenced by generateBargraphSchema(), and generateUserInterfaceSchema().
static int cholddir | ( | ) | [static] |
Switch back to the previously stored current directory.
Definition at line 273 of file drawschema.cpp.
References gCurrentDir.
Referenced by drawSchema().
00274 { 00275 if (chdir(gCurrentDir) == 0) { 00276 return 0; 00277 } else { 00278 perror("cholddir"); 00279 exit(errno); 00280 } 00281 }
void drawSchema | ( | Tree | bd, | |
const char * | projname, | |||
const char * | dev | |||
) |
The entry point to generate from a block diagram as a set of svg files stored in the directory "<projname>-svg/" or "<projname>-ps/" depending of <dev>.
Definition at line 158 of file drawschema.cpp.
References boxComplexity(), cholddir(), gDevSuffix, gFoldThreshold, mkchdir(), pendingDrawing(), scheduleDrawing(), sFoldingFlag, and writeSchemaFile().
Referenced by main(), and printDocDgm().
00159 { 00160 gDevSuffix = dev; 00161 sFoldingFlag = boxComplexity(bd) > gFoldThreshold; 00162 00163 mkchdir(projname); // create a directory to store files 00164 00165 scheduleDrawing(bd); // schedule the initial drawing 00166 00167 Tree t; while (pendingDrawing(t)) { 00168 writeSchemaFile(t); // generate all the pending drawing 00169 } 00170 00171 cholddir(); // return to current directory 00172 }
Generate an abstraction schema by placing in sequence the input slots and the body.
Definition at line 491 of file drawschema.cpp.
References generateDiagramSchema(), generateInputSlotSchema(), isBoxSymbolic(), makeParSchema(), and makeSeqSchema().
Referenced by generateInsideSchema().
00492 { 00493 Tree a,b; 00494 00495 while (isBoxSymbolic(t,a,b)) { 00496 x = makeParSchema(x, generateInputSlotSchema(a)); 00497 t = b; 00498 } 00499 return makeSeqSchema(x, generateDiagramSchema(t)); 00500 }
Generate a 1->1 block schema for a user interface bargraph.
Definition at line 453 of file drawschema.cpp.
References makeBlockSchema(), and uicolor.
Referenced by generateInsideSchema().
00454 { 00455 stringstream s; 00456 s << boxpp(t); 00457 00458 return makeBlockSchema(1, 1, s.str(), uicolor, ""); 00459 }
Generate an appropriate schema according to the type of block diagram.
When folding is requiered, instead of going down block-diagrams with a name, schedule them for an individual file.
Definition at line 318 of file drawschema.cpp.
References boxComplexity(), gDevSuffix, generateInsideSchema(), getBoxType(), getDefNameProperty(), isBoxSlot(), legalFileName(), linkcolor, makeBlockSchema(), makeDecorateSchema(), scheduleDrawing(), sFoldingFlag, and tree2str().
Referenced by generateAbstractionSchema(), and generateInsideSchema().
00319 { 00320 Tree id; 00321 int ins, outs; 00322 00323 //cerr << t << " generateDiagramSchema " << boxpp(t)<< endl; 00324 00325 if (getDefNameProperty(t, id)) { 00326 stringstream s; s << tree2str(id); 00327 //cerr << t << "\tNAMED : " << s.str() << endl; 00328 } 00329 00330 if ( sFoldingFlag && /*(gOccurrences->getCount(t) > 0) &&*/ 00331 (boxComplexity(t) > 2) && getDefNameProperty(t, id)) { 00332 char temp[1024]; 00333 getBoxType(t, &ins, &outs); 00334 stringstream s, l; 00335 s << tree2str(id); 00336 l << legalFileName(t,1024,temp) << "." << gDevSuffix; 00337 scheduleDrawing(t); 00338 return makeBlockSchema(ins, outs, s.str(), linkcolor, l.str()); 00339 00340 } else if (getDefNameProperty(t, id) && ! isBoxSlot(t)) { 00341 // named case : not a slot, with a name 00342 // draw a line around the object with its name 00343 stringstream s; s << tree2str(id); 00344 return makeDecorateSchema(generateInsideSchema(t), 10, s.str()); 00345 00346 } else { 00347 // normal case 00348 return generateInsideSchema(t); 00349 } 00350 }
Generate a 1->0 block schema for an input slot.
Definition at line 466 of file drawschema.cpp.
References getDefNameProperty(), makeBlockSchema(), slotcolor, and tree2str().
Referenced by generateAbstractionSchema(), and generateInsideSchema().
00467 { 00468 Tree id; assert(getDefNameProperty(a, id)); 00469 stringstream s; s << tree2str(id); 00470 return makeBlockSchema(1, 0, s.str(), slotcolor, ""); 00471 }
Generate the inside schema of a block diagram according to its type.
Definition at line 358 of file drawschema.cpp.
References xtended::arity(), ffarity(), ffname(), generateAbstractionSchema(), generateBargraphSchema(), generateDiagramSchema(), generateInputSlotSchema(), generateOutputSlotSchema(), generateUserInterfaceSchema(), getDefNameProperty(), getUserData(), isBoxButton(), isBoxCheckbox(), isBoxCut(), isBoxFConst(), isBoxFFun(), isBoxFVar(), isBoxHBargraph(), isBoxHGroup(), isBoxHSlider(), isBoxInt(), isBoxMerge(), isBoxNumEntry(), isBoxPar(), isBoxPrim0(), isBoxPrim1(), isBoxPrim2(), isBoxPrim3(), isBoxPrim4(), isBoxPrim5(), isBoxReal(), isBoxRec(), isBoxSeq(), isBoxSlot(), isBoxSplit(), isBoxSymbolic(), isBoxTGroup(), isBoxVBargraph(), isBoxVGroup(), isBoxVSlider(), isBoxWire(), makeBlockSchema(), makeCableSchema(), makeCutSchema(), makeDecorateSchema(), makeMergeSchema(), makeParSchema(), makeRecSchema(), makeSeqSchema(), makeSplitSchema(), xtended::name(), name(), normalcolor, numcolor, prim0name(), prim1name(), prim2name(), prim3name(), prim4name(), prim5name(), print(), and tree2str().
Referenced by generateDiagramSchema(), and writeSchemaFile().
00359 { 00360 Tree a, b, ff, l, type,name,file; 00361 int i; 00362 double r; 00363 prim0 p0; 00364 prim1 p1; 00365 prim2 p2; 00366 prim3 p3; 00367 prim4 p4; 00368 prim5 p5; 00369 00370 00371 xtended* xt = (xtended*)getUserData(t); 00372 00373 if (xt) { return makeBlockSchema(xt->arity(), 1, xt->name(), normalcolor, ""); } 00374 00375 else if (isBoxInt(t, &i)) { stringstream s; s << i; return makeBlockSchema(0, 1, s.str(), numcolor, "" ); } 00376 else if (isBoxReal(t, &r)) { stringstream s; s << r; return makeBlockSchema(0, 1, s.str(), numcolor, "" ); } 00377 else if (isBoxWire(t)) { return makeCableSchema(); } 00378 else if (isBoxCut(t)) { return makeCutSchema(); } 00379 00380 else if (isBoxPrim0(t, &p0)) { return makeBlockSchema(0, 1, prim0name(p0), normalcolor, ""); } 00381 else if (isBoxPrim1(t, &p1)) { return makeBlockSchema(1, 1, prim1name(p1), normalcolor, ""); } 00382 else if (isBoxPrim2(t, &p2)) { return makeBlockSchema(2, 1, prim2name(p2), normalcolor, ""); } 00383 else if (isBoxPrim3(t, &p3)) { return makeBlockSchema(3, 1, prim3name(p3), normalcolor, ""); } 00384 else if (isBoxPrim4(t, &p4)) { return makeBlockSchema(4, 1, prim4name(p4), normalcolor, ""); } 00385 else if (isBoxPrim5(t, &p5)) { return makeBlockSchema(5, 1, prim5name(p5), normalcolor, ""); } 00386 00387 else if (isBoxFFun(t, ff)) { return makeBlockSchema(ffarity(ff), 1, ffname(ff), normalcolor, ""); } 00388 else if (isBoxFConst(t, type,name,file)) { return makeBlockSchema(0, 1, tree2str(name), normalcolor, ""); } 00389 else if (isBoxFVar (t, type, name,file)) { return makeBlockSchema(0, 1, tree2str(name), normalcolor, ""); } 00390 00391 else if (isBoxButton(t)) { return generateUserInterfaceSchema(t); } 00392 else if (isBoxCheckbox(t)) { return generateUserInterfaceSchema(t); } 00393 else if (isBoxVSlider(t)) { return generateUserInterfaceSchema(t); } 00394 else if (isBoxHSlider(t)) { return generateUserInterfaceSchema(t); } 00395 else if (isBoxNumEntry(t)) { return generateUserInterfaceSchema(t); } 00396 else if (isBoxVBargraph(t)) { return generateBargraphSchema(t); } 00397 else if (isBoxHBargraph(t)) { return generateBargraphSchema(t); } 00398 00399 // don't draw group rectangle when labels are empty (ie "") 00400 else if (isBoxVGroup(t,l,a)) { stringstream s; s << "vgroup(" << tree2str(l) << ")"; 00401 schema* r = generateDiagramSchema(a); 00402 return makeDecorateSchema(r, 10, s.str()); } 00403 else if (isBoxHGroup(t,l,a)) { stringstream s; s << "hgroup(" << tree2str(l) << ")"; 00404 schema* r = generateDiagramSchema(a); 00405 return makeDecorateSchema(r, 10, s.str()); } 00406 else if (isBoxTGroup(t,l,a)) { stringstream s; s << "tgroup(" << tree2str(l) << ")"; 00407 schema* r = generateDiagramSchema(a); 00408 return makeDecorateSchema(r, 10, s.str()); } 00409 00410 else if (isBoxSeq(t, a, b)) { return makeSeqSchema(generateDiagramSchema(a), generateDiagramSchema(b)); } 00411 else if (isBoxPar(t, a, b)) { return makeParSchema(generateDiagramSchema(a), generateDiagramSchema(b)); } 00412 else if (isBoxSplit(t, a, b)) { return makeSplitSchema(generateDiagramSchema(a), generateDiagramSchema(b)); } 00413 else if (isBoxMerge(t, a, b)) { return makeMergeSchema(generateDiagramSchema(a), generateDiagramSchema(b)); } 00414 else if (isBoxRec(t, a, b)) { return makeRecSchema(generateDiagramSchema(a), generateDiagramSchema(b)); } 00415 00416 else if (isBoxSlot(t, &i)) { return generateOutputSlotSchema(t); } 00417 else if (isBoxSymbolic(t,a,b)) { 00418 Tree id; 00419 if (getDefNameProperty(t, id)) { 00420 return generateAbstractionSchema(generateInputSlotSchema(a), b); 00421 } else { 00422 return makeDecorateSchema(generateAbstractionSchema(generateInputSlotSchema(a), b), 10, "Abstraction"); 00423 } 00424 } 00425 00426 else { 00427 00428 fprintf(stderr, "Internal Error, box expression not recognized : "); print(t, stderr); fprintf(stderr, "\n"); 00429 exit(1); 00430 00431 } 00432 }
Generate a 0->1 block schema for an output slot.
Definition at line 478 of file drawschema.cpp.
References getDefNameProperty(), makeBlockSchema(), slotcolor, and tree2str().
Referenced by generateInsideSchema().
00479 { 00480 Tree id; assert(getDefNameProperty(a, id)); 00481 stringstream s; s << tree2str(id); 00482 return makeBlockSchema(0, 1, s.str(), slotcolor, ""); 00483 }
Generate a 0->1 block schema for a user interface element.
Definition at line 440 of file drawschema.cpp.
References makeBlockSchema(), and uicolor.
Referenced by generateInsideSchema().
00441 { 00442 stringstream s; 00443 s << boxpp(t); 00444 00445 return makeBlockSchema(0, 1, s.str(), uicolor, ""); 00446 }
static char * legalFileName | ( | Tree | t, | |
int | n, | |||
char * | dst | |||
) | [static] |
Transform the definition name property of tree <t> into a legal file name.
The resulting file name is stored in <dst> a table of at least <n> chars. Returns the <dst> pointer for convenience.
Definition at line 290 of file drawschema.cpp.
References getDefNameProperty(), and tree2str().
Referenced by generateDiagramSchema(), and writeSchemaFile().
00291 { 00292 Tree id; 00293 int i=0; 00294 if (getDefNameProperty(t, id)) { 00295 const char* src = tree2str(id); 00296 for (i=0; isalnum(src[i]) && i<16; i++) { 00297 dst[i] = src[i]; 00298 } 00299 } 00300 dst[i] = 0; 00301 if (strcmp(dst, "process") != 0) { 00302 // if it is not process add the hex address to make the name unique 00303 snprintf(&dst[i], n-i, "-%p", t); 00304 } 00305 return dst; 00306 }
static int mkchdir | ( | const char * | dirname | ) | [static] |
Create a new directory in the current one to store the diagrams.
The current directory is saved to be later restaured.
Definition at line 253 of file drawschema.cpp.
References gCurrentDir.
Referenced by drawSchema().
00254 { 00255 //cerr << "mkchdir of " << dirname << endl; 00256 if (getcwd(gCurrentDir, 512) != 0) { 00257 int status = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 00258 if (status == 0 || errno == EEXIST) { 00259 if (chdir(dirname) == 0) { 00260 return 0; 00261 } 00262 } 00263 } 00264 perror("mkchdir"); 00265 exit(errno); 00266 //return errno; 00267 }
static bool pendingDrawing | ( | Tree & | t | ) | [static] |
Retrieve next block diagram that must be drawn.
Definition at line 199 of file drawschema.cpp.
References gPendingExp.
Referenced by drawSchema().
00200 { 00201 if (gPendingExp.empty()) return false; 00202 t = gPendingExp.top(); 00203 gPendingExp.pop(); 00204 return true; 00205 }
static void scheduleDrawing | ( | Tree | t | ) | [static] |
Schedule a makeBlockSchema diagram to be drawn.
Definition at line 187 of file drawschema.cpp.
References gBackLink, gDrawnExp, gPendingExp, and gSchemaFileName.
Referenced by drawSchema(), and generateDiagramSchema().
00188 { 00189 if (gDrawnExp.find(t) == gDrawnExp.end()) { 00190 gDrawnExp.insert(t); 00191 gBackLink.insert(make_pair(t,gSchemaFileName)); // remember the enclosing filename 00192 gPendingExp.push(t); 00193 } 00194 }
static void writeSchemaFile | ( | Tree | bd | ) | [static] |
Write a top level diagram.
A top level diagram is decorated with its definition name property and is drawn in an individual file
Definition at line 216 of file drawschema.cpp.
References schema::draw(), gBackLink, gDevSuffix, generateInsideSchema(), getDefNameProperty(), gSchemaFileName, schema::height(), kLeftRight, legalFileName(), makeTopSchema(), schema::place(), tree2str(), and schema::width().
Referenced by drawSchema().
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); assert(hasname); 00226 00227 // generate legal file name for the schema 00228 stringstream s1; s1 << legalFileName(bd, 1024, temp) << "." << gDevSuffix; 00229 gSchemaFileName = s1.str(); 00230 00231 // generate the label of the schema 00232 stringstream s2; s2 << tree2str(id); 00233 string link = gBackLink[bd]; 00234 ts = makeTopSchema(generateInsideSchema(bd), 20, s2.str(), link); 00235 // draw to the device defined by gDevSuffix 00236 if (strcmp(gDevSuffix, "svg") == 0) { 00237 SVGDev dev(s1.str().c_str(), ts->width(), ts->height()); 00238 ts->place(0,0, kLeftRight); 00239 ts->draw(dev); 00240 } else { 00241 PSDev dev(s1.str().c_str(), ts->width(), ts->height()); 00242 ts->place(0,0, kLeftRight); 00243 ts->draw(dev); 00244 } 00245 }
Definition at line 133 of file drawschema.cpp.
Referenced by scheduleDrawing(), and writeSchemaFile().
char gCurrentDir[512] [static] |
Definition at line 131 of file drawschema.cpp.
Referenced by cholddir(), and mkchdir().
const char* gDevSuffix [static] |
Definition at line 130 of file drawschema.cpp.
Referenced by drawSchema(), generateDiagramSchema(), and writeSchemaFile().
Definition at line 129 of file drawschema.cpp.
Referenced by scheduleDrawing().
int gFoldThreshold |
Definition at line 119 of file main.cpp.
Referenced by drawSchema(), and process_cmdline().
Occurrences* gOccurrences [static] |
Definition at line 126 of file drawschema.cpp.
stack<Tree> gPendingExp [static] |
Definition at line 128 of file drawschema.cpp.
Referenced by pendingDrawing(), and scheduleDrawing().
string gSchemaFileName [static] |
Definition at line 132 of file drawschema.cpp.
Referenced by scheduleDrawing(), and writeSchemaFile().
bool sFoldingFlag [static] |
Definition at line 127 of file drawschema.cpp.
Referenced by drawSchema(), and generateDiagramSchema().