Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 /* -*-Mode: c++;-*- (Tell emacs to use c++ mode) */ 00037 /* ==================================================================== 00038 * 00039 * 00040 * Description: 00041 * Interface to daVinci. The DaVinci class, along with its 00042 * subordinate classes and types, provides a high level model 00043 * for interactive examination of graph-based data structures. 00044 * Sufficient sanity checking is done to detect most daVinci 00045 * usage errors before issuing commands to daVinci. 00046 * 00047 * Key concepts and interface functions are described below: 00048 * 00049 * daVinci X-Window visualization tool from University of Bremen, Germany. 00050 * runs as a separate process. Commands are sent to daVinci via 00051 * a UNIX pipe, replies (ack, events) are returned though another 00052 * pipe. 00053 * see http://www.informatik.uni-bremen.de/~davinci/ 00054 * 00055 * DA_ACK return type indicating a reply from daVinci. 00056 * NULL => ok; otherwise an error message (const char *). 00057 * Assume message is statically allocated and may be overwritten 00058 * by any subsequence DaVinci member function. 00059 * 00060 * DaVinci(FILE *trace_fp = NULL) 00061 * create DaVinci object. if trace_fp != NULL then all traffic 00062 * to/from daVinci is logged in indicated file. 00063 * 00064 * bool Davinci::enabled(bool msg) 00065 * use environment variable DAVINCIHOME as indication daVinci 00066 * availability. return true iff set; if not set and msg is true 00067 * then issue (at most one) warning. 00068 * 00069 * void DaVinci::Event_Loop(DaVinci_Callback *cb_hook) 00070 * void DaVinci::Exit_Event_Loop() 00071 * respond to actions from daVinci window until exit action taken. 00072 * daVinci file menu - exit daVinci 00073 * daVinci edit menu - exit_event_loop 00074 * in callback function, call exit_event_loop. 00075 * The first closes the daVinci window while the later two allow 00076 * the caller to resume w/o closing the DaVinci window. If the 00077 * DaVinci object is not destroyed, and the daVinci is not exited, 00078 * subsequence calls to event_loop() will resume response to actions. 00079 * see notes on DaVinci_Callback below. 00080 * 00081 * DA_ACK DaVinci::Title(const char *title) 00082 * DA_ACK DaVinci::Show_Status(const char *status) 00083 * DA_ACK DaVinci::Show_Message(const char *msg) 00084 * Display strings at top, lower left, lower right resp. of window. 00085 * The daVinci doc. suggests using "message" for transient events 00086 * such as "file saved" and "status" for ongoing state. "title" 00087 * seems like a good place to identify the origin of the DaVinci 00088 * client. 00089 * 00090 * struct MENU_INFO 00091 * for defining submenu under "edit". suggest that this be done 00092 * using static initialization. A menu item may identify a submenu 00093 * or be itself a leave item. The initially_active field indicates 00094 * if the item is accessable on immediately after menu_create(). 00095 * 00096 * DA_ACK DaVinci::Menu_Create(INT n_items, const MENU_INFO *items) 00097 * create new menu hierarchy under the daVinci "edit" menu. 00098 * see MENU_INFO structure. 00099 * 00100 * DA_ACK DaVinci::Menu_Activate(INT n_ids, const char *ids[]) 00101 * DA_ACK DaVinci::Menu_Deactivate(INT n_ids, const char *ids[]) 00102 * enable/disable sets of menu items. 00103 * 00104 * void DaVinci::Graph_Begin() 00105 * void DaVinci::Node_Begin( id, label, node_type ) 00106 * void DaVinci::Out_Edge( edge_id, edge_type, dest_id ) 00107 * void DaVinci::Node_End() 00108 * DA_ACK DaVinci::Graph_End() 00109 * The above define a graph. Each node as a unique NODE_ID; 00110 * each edge a uniq EDGE_ID. 00111 * Usage: graph_begin [ node_begin out_edge* node_end ]* graph_end 00112 * see also: NODE_ID, EDGE_ID, NODE_TYPE, EDGE_TYPE 00113 * 00114 * DA_ACK DaVinci::Change_Attr( node_id, node_type, new_label = NULL ) 00115 * DA_ACK DaVinci::Change_Attr( edge_id, edge_type ) 00116 * change attributes (color, shape, line-type, etc.) of node/edge. 00117 * 00118 * void DaVinci::Update_Begin() 00119 * void DaVinci::New_Node( node_id, label, node_type ) 00120 * void DaVinci::New_Edge( edge_id, edge_type, src, dst ) 00121 * DA_ACK DaVinci::Update_End() 00122 * add new nodes/edges. must list all new nodes before any 00123 * new edges in an update group. i.e., usage symopsis is: 00124 * Update_Begin New_Node* New_Edge* Update_End 00125 * 00126 * class DaVinci_Callback 00127 * virtual void DaVinci_Callback::node_select( n_ids, id_array ) 00128 * virtual void DaVinci_Callback::edge_select( edge_id ) 00129 * virtual void DaVinci_Callback::menu_select( menu_id ) 00130 * 00131 * Response to daVinci events is managented by Callback functions. 00132 * The DaVinci class client creates a subclass of DaVinci_Callback 00133 * and redefines the virtual member for events of interest. 00134 * The Callback subclass object is passed to event_loop(). 00135 * 00136 * ==================================================================== 00137 */ 00138 00139 //more: open use MEM_POOL * or keep 'generic' for use outside Mongoose? 00140 00141 #ifndef DaVinci_INCLUDED 00142 #define DaVinci_INCLUDED 00143 00144 // Avoid compile errors for STL files 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 // Solaris CC workaround 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 { // if multiple edges add occurence 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 // WARNING: Do _NOT_ delete strings/arrays passed back by Callback 00184 // functions. These are allocated/deleted by the DaVinci 00185 // class in accordance with its lifetime. 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, // default is BOX. 00198 NS_BOX, 00199 NS_CIRCLE, 00200 NS_ELLIPSE, 00201 NS_RHOMBUS, 00202 NS_TEXT 00203 //more NS_ICON 00204 } NODE_SHAPE; 00205 00206 typedef enum { 00207 NB_UNSET, // default is SINGLE. 00208 NB_SINGLE, 00209 NB_DOUBLE 00210 } NODE_BORDER; 00211 00212 typedef enum { 00213 NH_UNSET, // default is SHOW. 00214 NH_HIDE, 00215 NH_SHOW 00216 } NODE_HIDE; 00217 00218 class NODE_TYPE { 00219 private: 00220 char _type_name[20]; // node type name. "" if unset. 00221 char _node_color[30]; // attribute: COLOR "" if unset. 00222 NODE_SHAPE _node_shape; // attribute: _GO 00223 NODE_BORDER _border; // attribute: BORDER 00224 NODE_HIDE _hide; // attribute: HIDDEN 00225 // more: fontfamily,fontstyle,iconfile. 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, // default is SOLID. 00251 EP_SOLID, 00252 EP_DOTTED, 00253 EP_DASHED, 00254 EP_THICK, // beware: same as a selected edge. 00255 EP_DOUBLE 00256 } EDGE_PATTERN; 00257 00258 typedef enum { 00259 ED_UNSET, // default is NORMAL (->). 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]; // edge type name. "" if unset. 00269 char _edge_color[30]; // attribute: EDGECOLOR "" if unset. 00270 EDGE_PATTERN _edge_pattern; // attribute: EDGEPATTERN 00271 EDGE_DIR _edge_dir; // attribute: _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; // id from/to DaVinci. 00289 char *label; // displayed by DaVinci. 00290 bool initially_active; // active on startup ? 00291 INT n_subitems; // 0 => this is a leaf item. 00292 MENU_INFO *subitems; // NULL => this is leaf item. 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 // DaVinci exiting. 00302 // more: many more event kinds .. 00303 } EVENT_KIND; 00304 00305 00306 struct EVENT_T { //more? full OO-style - queue ptrs, use class heir .. 00307 EVENT_KIND kind; 00308 union { 00309 struct { 00310 const char *msg; // ptr into static buffer. 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; // always a heap object. 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, // want menu item turned on. 00337 DM_INACTIVE, // want menu item turned on. 00338 DM_UNKNOWN // entry from menu select (using map domain as string pool). 00339 } Item_status; 00340 00341 00342 // Solaris CC workaround 00343 // replace hash_map with map 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) {} // alloc to pool; free with pool. 00365 ~Menu_info() {} 00366 void operator=(Menu_info&); // don't define. 00367 Menu_info(Menu_info&); // don't define. 00368 00369 const char *Add(const char *cp); // use items maps domain as string pool. 00370 void Set(const char *cp, Item_status status); 00371 }; 00372 00373 typedef const char *DA_ACK; // NULL => ok, otherwise error string. 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(); // sync read; NULL => EOF. 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; // used iff _usage_check == true. 00408 set<NODE_ID> _node_ref_set; // used iff _usage_check == true. 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&); // don't allow/define. 00477 void operator=(const DaVinci&); // don't allow/define. 00478 00479 void Event_Loop(DaVinci_Callback *cb_hook); 00480 void Exit_Event_Loop(); 00481 00482 DA_ACK Title(const char *title); // on top. 00483 DA_ACK Show_Status(const char *status); // lower right. 00484 DA_ACK Show_Message(const char *msg); // lower left (for transient 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(); // all new_node() must preceed first new_edge(). 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