00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 #ifndef DaVinci_INCLUDED
00142 #define DaVinci_INCLUDED
00143
00144
00145
00146 #if defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00147 #undef short
00148 #undef int
00149 #undef long
00150 #endif // defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00151
00152 #include <stdio.h>
00153 #include <assert.h>
00154 #include <sys/types.h>
00155
00156
00157
00158 #include <stack>
00159 #include <queue>
00160 #include <set>
00161
00162 #ifndef _USE_STL_EXT
00163 #include <map>
00164 #else
00165 #include <hash_map>
00166 #endif
00167
00168 using namespace std;
00169
00170 #include "defs.h"
00171 #include "errors.h"
00172 #include "cxx_memory.h"
00173
00174 typedef void *NODE_ID;
00175
00176 struct EDGE_ID {
00177 NODE_ID src;
00178 NODE_ID dst;
00179
00180 EDGE_ID(NODE_ID s, NODE_ID d) : src(s), dst(d) {}
00181 };
00182
00183
00184
00185
00186
00187 class DaVinci_Callback {
00188 public:
00189 virtual void Node_Select(const INT n_ids, const NODE_ID id_array[]);
00190 virtual void Edge_Select(const EDGE_ID& edge_id);
00191 virtual void Menu_Select(const char *menu_id);
00192 };
00193
00194 class DaVinci;
00195
00196 typedef enum {
00197 NS_UNSET,
00198 NS_BOX,
00199 NS_CIRCLE,
00200 NS_ELLIPSE,
00201 NS_RHOMBUS,
00202 NS_TEXT
00203
00204 } NODE_SHAPE;
00205
00206 typedef enum {
00207 NB_UNSET,
00208 NB_SINGLE,
00209 NB_DOUBLE
00210 } NODE_BORDER;
00211
00212 typedef enum {
00213 NH_UNSET,
00214 NH_HIDE,
00215 NH_SHOW
00216 } NODE_HIDE;
00217
00218 class NODE_TYPE {
00219 private:
00220 char _type_name[20];
00221 char _node_color[30];
00222 NODE_SHAPE _node_shape;
00223 NODE_BORDER _border;
00224 NODE_HIDE _hide;
00225
00226
00227 friend class DaVinci;
00228 public:
00229 NODE_TYPE() {
00230 _type_name[0] = '\0';
00231 _node_color[0] = '\0';
00232 _node_shape = NS_UNSET;
00233 _border = NB_UNSET;
00234 _hide = NH_UNSET;
00235 }
00236 NODE_TYPE& Name(const char *typ_name);
00237 NODE_TYPE& Color(const char *rgb);
00238 NODE_TYPE& Shape(NODE_SHAPE ns) {
00239 _node_shape = ns; return *this;
00240 }
00241 NODE_TYPE& Boarder(NODE_BORDER nb) {
00242 _border = nb; return *this;
00243 }
00244 NODE_TYPE& Hidden(NODE_HIDE nh) {
00245 _hide = nh; return *this;
00246 }
00247 };
00248
00249 typedef enum {
00250 EP_UNSET,
00251 EP_SOLID,
00252 EP_DOTTED,
00253 EP_DASHED,
00254 EP_THICK,
00255 EP_DOUBLE
00256 } EDGE_PATTERN;
00257
00258 typedef enum {
00259 ED_UNSET,
00260 ED_NORMAL,
00261 ED_INVERSE,
00262 ED_BOTH,
00263 ED_NONE
00264 } EDGE_DIR;
00265
00266 class EDGE_TYPE {
00267 private:
00268 char _type_name[20];
00269 char _edge_color[30];
00270 EDGE_PATTERN _edge_pattern;
00271 EDGE_DIR _edge_dir;
00272
00273 friend class DaVinci;
00274 public:
00275 EDGE_TYPE() {
00276 _type_name[0] = '\0';
00277 _edge_color[0] = '\0';
00278 _edge_pattern = EP_UNSET;
00279 _edge_dir = ED_UNSET;
00280 }
00281 EDGE_TYPE& Name(const char *typ_name);
00282 EDGE_TYPE& Color(const char *rgb);
00283 EDGE_TYPE& Pattern(EDGE_PATTERN pat) { _edge_pattern = pat; return *this; }
00284 EDGE_TYPE& Direction(EDGE_DIR dir) { _edge_dir = dir; return *this; }
00285 };
00286
00287 struct MENU_INFO {
00288 char *id;
00289 char *label;
00290 bool initially_active;
00291 INT n_subitems;
00292 MENU_INFO *subitems;
00293 };
00294
00295 typedef enum {
00296 EK_COM_ERROR,
00297 EK_OK,
00298 EK_SEL_EDGE,
00299 EK_SEL_MENU,
00300 EK_SEL_NODES,
00301 EK_QUIT
00302
00303 } EVENT_KIND;
00304
00305
00306 struct EVENT_T {
00307 EVENT_KIND kind;
00308 union {
00309 struct {
00310 const char *msg;
00311 } com_error;
00312
00313 struct {
00314 NODE_ID edge_src;
00315 NODE_ID edge_dst;
00316 } sel_edge;
00317
00318 struct {
00319 const char *label;
00320 } sel_menu;
00321
00322 struct {
00323 INT n_nodes;
00324 NODE_ID *node_ids;
00325 } sel_nodes;
00326 } u;
00327 };
00328
00329 struct Equal_obj {
00330 bool operator()(const char* s1, const char* s2) const {
00331 return strcmp(s1, s2) == 0;
00332 }
00333 };
00334
00335 typedef enum {
00336 DM_ACTIVE,
00337 DM_INACTIVE,
00338 DM_UNKNOWN
00339 } Item_status;
00340
00341
00342
00343
00344 #ifndef _USE_STL_EXT
00345 struct char_ss_compare {
00346 bool operator() (const char* s1, const char* s2) const
00347 {
00348 return strcmp(s1, s2) < 0;
00349 }
00350 };
00351 typedef map < const char *, Item_status, char_ss_compare > Item_info;
00352
00353 #else
00354 typedef hash_map< const char *, Item_status,
00355 hash<const char *>, Equal_obj > Item_info;
00356 #endif
00357
00358 class Menu_info {
00359 private:
00360 MEM_POOL *_m;
00361 public:
00362 Item_info items;
00363
00364 Menu_info(MEM_POOL *m) : _m(m) {}
00365 ~Menu_info() {}
00366 void operator=(Menu_info&);
00367 Menu_info(Menu_info&);
00368
00369 const char *Add(const char *cp);
00370 void Set(const char *cp, Item_status status);
00371 };
00372
00373 typedef const char *DA_ACK;
00374
00375 class DaVinci {
00376 private:
00377 class IO {
00378 private:
00379 FILE *_to_fp;
00380 FILE *_from_fp;
00381 FILE *_trace_fp;
00382 bool _trace_tagged;
00383 public:
00384 IO() {
00385 _to_fp = _from_fp = _trace_fp = NULL;
00386 _trace_tagged = false;
00387 }
00388 void Trace(FILE *tfp) { _trace_fp = tfp; }
00389 ~IO();
00390
00391 void Init(FILE *to, FILE *from) {
00392 _to_fp = to;
00393 _from_fp = from;
00394 }
00395 void Close();
00396 void Out_Fmt(const char *fmt, ...);
00397 char *In_Line();
00398 };
00399 typedef UINT32 FTAG;
00400 typedef FTAG FTAGS;
00401
00402 IO _io;
00403 MEM_POOL *_m;
00404
00405 queue<EVENT_T> _event_q;
00406
00407 set<NODE_ID> _node_def_set;
00408 set<NODE_ID> _node_ref_set;
00409 Menu_info _menu_state;
00410 bool _basic_menu_added;
00411 bool _in_event_loop;
00412 bool _display_ok;
00413 bool _usage_check;
00414 FTAG _ftag_last;
00415 INT _node_cnt;
00416 INT _edge_cnt;
00417 pid_t _pid;
00418
00419 const char *Ft_Str(const FTAG ftag);
00420 void Usage_Error(FTAG curr, FTAGS prereq);
00421
00422 bool Usage_Ok(FTAG curr, FTAGS prereq) {
00423 if ( _display_ok && (prereq == 0 || (_ftag_last & prereq)) ) {
00424 _ftag_last = curr;
00425 return true;
00426 }
00427 Usage_Error(curr, prereq);
00428 return false;
00429 }
00430 DA_ACK Wait_For_Ack();
00431
00432 DA_ACK Emit_Ack(const char *line) {
00433 assert( strchr( line, '\n' ) == NULL );
00434 _io.Out_Fmt( line );
00435 _io.Out_Fmt( "\n" );
00436 return Wait_For_Ack();
00437 }
00438 void Emit_Do(const char *line) {
00439 DA_ACK msg = Emit_Ack( line );
00440 if ( msg ) {
00441 fprintf(stderr, "Unexpected DaVinci error: %s\n", msg);
00442 }
00443 }
00444 const char *Parse_Menu_Label(const char *epfx);
00445 bool Parse_Event(const char *line, EVENT_T *event);
00446 bool Parse_Node_Ids(const char *epfx,
00447 INT *n_nodes, NODE_ID **node_ids);
00448
00449 void Emit_Menu(INT n_items, const MENU_INFO *items);
00450 void Emit_Attr(const NODE_TYPE& nt, char **comma);
00451 void Emit_Attr(const EDGE_TYPE& et);
00452
00453 void Menu_Basic_Do( const char *label );
00454 DA_ACK Menu_Set_Active();
00455
00456 void Kill_Davinci();
00457 public:
00458 static bool enabled(bool msg) {
00459 bool is_enabled = ( getenv("DAVINCIHOME") != NULL );
00460 if ( ! is_enabled ) {
00461 static bool msg_given = false;
00462 if ( ! msg_given ) {
00463 DevWarn("daVinci not enabled; %s\n",
00464 "must set DAVINCIHOME and put daVinci on path.");
00465 msg_given = true;
00466 }
00467 }
00468 return is_enabled;
00469 }
00470
00471 DaVinci(MEM_POOL *m, FILE *trace_fp = NULL, bool usage_check = false);
00472 ~DaVinci();
00473
00474 bool is_ok() const { return _display_ok; }
00475
00476 DaVinci(const DaVinci&);
00477 void operator=(const DaVinci&);
00478
00479 void Event_Loop(DaVinci_Callback *cb_hook);
00480 void Exit_Event_Loop();
00481
00482 DA_ACK Title(const char *title);
00483 DA_ACK Show_Status(const char *status);
00484 DA_ACK Show_Message(const char *msg);
00485
00486 DA_ACK Menu_Create(INT n_items, const MENU_INFO *items);
00487 DA_ACK Menu_Activate(INT n_ids, const char *ids[]);
00488 DA_ACK Menu_Deactivate(INT n_ids, const char *ids[]);
00489
00490 void Graph_Begin();
00491 void Node_Begin(NODE_ID id, const char *label, const NODE_TYPE& node_type);
00492 void Out_Edge(const EDGE_ID& edge_id,
00493 const EDGE_TYPE& edge_type,
00494 const NODE_ID dest_id);
00495 void Node_End();
00496 DA_ACK Graph_End();
00497
00498 DA_ACK Change_Attr(const NODE_ID node_id,
00499 const NODE_TYPE& nt,
00500 const char *new_label = NULL);
00501
00502 DA_ACK Change_Attr(const EDGE_ID& edge_id, const EDGE_TYPE& et);
00503
00504 void Update_Begin();
00505 void New_Node(NODE_ID id, const char *label, const NODE_TYPE& nt );
00506 void New_Edge(const EDGE_ID& id, const EDGE_TYPE& et,
00507 NODE_ID src, NODE_ID dst);
00508 DA_ACK Update_End();
00509 };
00510
00511 #endif