changes due to new visiLib
[dyninst.git] / visiClients / tclVisi / src / DGclient.C
1 /*
2  *  DGclient.C -- Code for the visi<->tcl interface.
3  *    
4  * $Log: DGclient.C,v $
5  * Revision 1.10  1996/01/17 18:32:34  newhall
6  * changes due to new visiLib
7  *
8  * Revision 1.9  1995/11/17  17:30:32  newhall
9  * added Dg metriclabel, Dg metricavelabel, and Dg metricsumlabel commands
10  * changed the Dg start command so that it doesn't take any arguments
11  *
12  * Revision 1.8  1995/11/12  23:30:49  newhall
13  * added Dg_Exited
14  *
15  * Revision 1.7  1995/02/26  02:02:02  newhall
16  * added callback functions for new visiLib phase info.
17  *
18  * Revision 1.6  1994/11/08  00:20:26  tamches
19  * removed blt-ish influences
20  * sped up processing of new data callbacks
21  * very close now to dg2.C of barchart
22  *
23  * Revision 1.5  1994/09/30  21:03:07  newhall
24  * removed call to StartVisi
25  *
26  * Revision 1.4  1994/09/25  02:07:47  newhall
27  * changed arguments to GetMetsRes
28  *
29  * Revision 1.3  1994/08/05  20:17:10  rbi
30  * Update for new version of libvisi.a
31  *
32  * Revision 1.2  1994/06/14  18:57:47  rbi
33  * Updated layout and added curve validation callback.
34  *
35  * Revision 1.1  1994/05/31  21:05:47  rbi
36  * Initial version of tclVisi and tabVis
37  *
38  */
39 #include <stdlib.h>
40 #include <iostream.h>
41 #include <tcl.h>
42 #include <tk.h>
43 #include "visi/h/visualization.h"
44
45 extern Tcl_Interp *MainInterp;
46
47 void my_visi_callback(void* , int* , long unsigned int* ) {
48     if (-1 == visi_callback())
49        exit(1);
50 }
51
52 int Dg_Add(int) {
53    // Gets called by visi lib when it detects new METRICS and/or RESOURCES
54
55    const int retval = Tcl_Eval(MainInterp, "DgConfigCallback");
56    if (retval == TCL_ERROR)
57       cerr << MainInterp->result << endl;
58
59    return retval;
60 }
61
62 int Dg_Data(int lastBucket) {
63    // New data has arrived.
64    // We are passed the bucket number.  We can grab data for all current
65    // metric/resource pairs and do something.
66
67    // Here, we just invoke the tcl script "DgDataCallback", passing lastBucket
68
69    char buffer[100];
70    sprintf(buffer, "DgDataCallback %d", lastBucket);
71    const int retval = Tcl_Eval(MainInterp, buffer);
72    if (retval == TCL_ERROR)
73       cerr << MainInterp->result << endl;
74
75    return retval;
76 }
77
78 int Dg_Fold(int) {
79    const int retval=Tcl_Eval(MainInterp, "DgFoldCallback");
80    if (retval == TCL_ERROR)
81       cerr << MainInterp->result << endl;
82
83    return retval;
84 }
85
86 int Dg_Invalid(int) {
87    const int retval=Tcl_Eval(MainInterp, "DgInvalidCallback");
88    if (retval == TCL_ERROR)
89       cerr << MainInterp->result << endl;
90
91    return retval;
92 }
93
94 int Dg_PhaseStart(int which) {
95    char buffer[100];
96    sprintf(buffer, "DgPhaseStartCallback %d", which);
97    const int retval = Tcl_Eval(MainInterp, buffer);
98    if (retval == TCL_ERROR)
99       cerr << MainInterp->result << endl;
100
101   return retval;
102 }
103
104 int Dg_PhaseEnd(int which) {
105    char buffer[100];
106    sprintf(buffer, "DgPhaseEndCallback %d", which);
107    const int retval = Tcl_Eval(MainInterp, buffer);
108    if (retval == TCL_ERROR)
109       cerr << MainInterp->result << endl;
110
111   return retval;
112 }
113
114 int Dg_PhaseData(int) {
115    const int retval=Tcl_Eval(MainInterp, "DgPhaseDataCallback");
116    if (retval == TCL_ERROR)
117       cerr << MainInterp->result << endl;
118
119   return retval;
120 }
121
122 int Dg_Exited(int) {
123    const int retval=Tcl_Eval(MainInterp, "DgParadynExitedCallback");
124    if (retval == TCL_ERROR){
125       // cerr << MainInterp->result << endl;
126       exit(-1);
127    }
128
129   return retval;
130 }
131
132 #define   AGGREGATE        0
133 #define   BINWIDTH         1
134 #define   METRICNAME       2
135 #define   METRICUNITS      3
136 #define   NUMBINS          4
137 #define   NUMMETRICS       5
138 #define   NUMRESOURCES     6
139 #define   DEFINEPHASE      7
140 #define   RESOURCENAME     8
141 #define   STARTSTREAM      9
142 #define   STOPSTREAM       10
143 #define   DGSUM            11
144 #define   DGVALID          12
145 #define   DGENABLED        13
146 #define   VALUE            14
147 #define   CMDERROR         15
148 #define   LASTBUCKET       16
149 #define   FIRSTBUCKET      17
150 #define   NUMPHASES        18
151 #define   PHASENAME        19
152 #define   PHASESTARTTIME   20
153 #define   PHASEENDTIME     21
154 #define   METRICAVELAB     22
155 #define   METRICSUMLAB     23
156
157 struct cmdTabEntry {
158    char *cmdname;
159    int index;
160    int numargs;
161 };
162
163 static struct cmdTabEntry Dg_Cmds[] = {
164   {"aggregate",    AGGREGATE,       2},
165   {"binwidth",     BINWIDTH,        0},
166   {"firstbucket",  FIRSTBUCKET,     2},
167   {"lastbucket",   LASTBUCKET,      2},
168   {"metricname",   METRICNAME,      1},
169   {"metriclabel",  METRICUNITS,     1},
170   {"numbins",      NUMBINS,         0},
171   {"nummetrics",   NUMMETRICS,      0},
172   {"numresources", NUMRESOURCES,    0},
173   {"phase",        DEFINEPHASE,     0},
174   {"resourcename", RESOURCENAME,    1},
175   {"start",        STARTSTREAM,     0},
176   {"stop",         STOPSTREAM,      2},
177   {"sum",          DGSUM,           2},
178   {"valid",        DGVALID,         2},
179   {"enabled",      DGENABLED,       2},
180   {"value",        VALUE,           3},
181   {"phasename",    PHASENAME,       1},
182   {"phasestartT",  PHASESTARTTIME,  1},
183   {"phaseendT",    PHASEENDTIME,    1},
184   {"numphases",    NUMPHASES,       0},
185   {"metricavelabel",  METRICAVELAB, 1},
186   {"metricsumlabel",  METRICSUMLAB, 1},
187   {NULL,           CMDERROR,        0}
188 };
189
190 int findCommand(Tcl_Interp *interp, 
191                 int argc, char *argv[]) {
192   if (argc == 0) {
193     sprintf(interp->result, "USAGE: Dg <option> [args...]\n");
194     return CMDERROR;
195   }
196   for (cmdTabEntry *C = Dg_Cmds; C->cmdname; C++) {
197     if (strcmp(argv[0], C->cmdname) == 0) {
198       if ((argc-1) == C->numargs) 
199         return C->index; // successful parsing
200
201       sprintf(interp->result, 
202               "%s: wrong number of args (%d). Should be %d\n",
203               argv[0], argc-1, C->numargs);
204       return CMDERROR;
205     }
206   }
207
208   sprintf(interp->result, "unknown option (%s)\n", argv[0]);
209   return CMDERROR;
210 }
211
212 int Dg_TclCommand(ClientData clientData,
213                   Tcl_Interp *interp, 
214                   int argc, 
215                   char *argv[]) {
216   const int cmdDex = findCommand(interp, argc-1, argv+1);
217   if (cmdDex == CMDERROR)
218      return TCL_ERROR;
219
220   int m, r, buck;
221
222   switch(cmdDex) {
223   case AGGREGATE:   
224     m = atoi(argv[2]);
225     r = atoi(argv[3]);
226     sprintf(interp->result,"%g", visi_AverageValue(m,r));
227     return TCL_OK;
228
229   case BINWIDTH:     
230     sprintf(interp->result, "%g", visi_BucketWidth());
231     return TCL_OK;
232
233   case FIRSTBUCKET:
234     m = atoi(argv[2]);
235     r = atoi(argv[3]);
236     sprintf(interp->result,"%d", visi_FirstValidBucket(m,r)); 
237     return TCL_OK;
238
239   case LASTBUCKET:
240     m = atoi(argv[2]);
241     r = atoi(argv[3]);
242     sprintf(interp->result,"%d", visi_LastBucketFilled(m,r));
243     return TCL_OK;
244
245   case METRICNAME:  
246     m = atoi(argv[2]);
247     sprintf(interp->result, "%s", visi_MetricName(m));
248     return TCL_OK;
249
250   case METRICUNITS:  
251     m = atoi(argv[2]);
252     sprintf(interp->result, "%s", visi_MetricLabel(m));
253     return TCL_OK;
254
255   case NUMBINS:     
256     sprintf(interp->result, "%d", visi_NumBuckets());
257     return TCL_OK;
258
259   case NUMMETRICS:  
260     sprintf(interp->result, "%d", visi_NumMetrics());
261     return TCL_OK;
262
263   case NUMRESOURCES:
264     sprintf(interp->result, "%d", visi_NumResources());
265     return TCL_OK;
266
267   case DEFINEPHASE:       
268     visi_DefinePhase(-1.0, NULL);
269     return TCL_OK;
270
271   case RESOURCENAME:
272     r = atoi(argv[2]);
273     sprintf(interp->result, "%s", visi_ResourceName(r));
274     return TCL_OK;
275
276   case STARTSTREAM:       
277     visi_GetMetsRes();
278     return TCL_OK;
279
280   case STOPSTREAM:
281     m = atoi(argv[2]);
282     r = atoi(argv[3]);
283     visi_StopMetRes(m, r);
284     return TCL_OK;
285
286   case DGSUM:         
287     m = atoi(argv[2]);
288     r = atoi(argv[3]);
289     sprintf(interp->result,"%g", visi_SumValue(m,r));
290     return TCL_OK;
291
292   case DGVALID:
293     m = atoi(argv[2]);
294     r = atoi(argv[3]);
295     sprintf(interp->result, "%d", visi_Valid(m,r));
296     return TCL_OK;
297
298   case DGENABLED:
299     m = atoi(argv[2]);
300     r = atoi(argv[3]);
301     sprintf(interp->result, "%d", visi_Enabled(m,r));
302     return TCL_OK;
303
304   case VALUE:       
305     m = atoi(argv[2]);
306     r = atoi(argv[3]);
307     buck = atoi(argv[4]);
308     sprintf(interp->result,"%g", visi_DataValue(m,r,buck));
309     return TCL_OK;
310
311   case NUMPHASES:
312     sprintf(interp->result, "%d", visi_NumPhases());
313     return TCL_OK;
314
315   case PHASENAME:
316     m = atoi(argv[2]);
317     sprintf(interp->result, "%s", visi_GetPhaseName(m));
318     return TCL_OK;
319
320   case PHASESTARTTIME:
321     m = atoi(argv[2]);
322     sprintf(interp->result, "%f", visi_GetPhaseStartTime(m));
323     return TCL_OK;
324
325   case PHASEENDTIME:
326     m = atoi(argv[2]);
327     sprintf(interp->result, "%f", visi_GetPhaseEndTime(m));
328     return TCL_OK;
329
330   case METRICAVELAB:
331     m = atoi(argv[2]);
332     sprintf(interp->result, "%s", visi_MetricAveLabel(m));
333     return TCL_OK;
334
335   case METRICSUMLAB:
336     m = atoi(argv[2]);
337     sprintf(interp->result, "%s", visi_MetricSumLabel(m));
338     return TCL_OK;
339    
340   }
341
342   sprintf(interp->result, "Internal error (func findCommand)\n");
343   return TCL_ERROR;
344 }
345
346 int Dg_Init(Tcl_Interp *interp) {
347    int fd=visi_Init();
348    if (fd < 0) {
349       cerr << "tclVisi: could not initialize visilib" << endl;
350       exit(-1);
351    }
352
353   (void) visi_RegistrationCallback(ADDMETRICSRESOURCES,Dg_Add); 
354   (void) visi_RegistrationCallback(DATAVALUES,Dg_Data); 
355   (void) visi_RegistrationCallback(FOLD,Dg_Fold); 
356   (void) visi_RegistrationCallback(INVALIDMETRICSRESOURCES,Dg_Invalid);
357   (void) visi_RegistrationCallback(PHASESTART,Dg_PhaseStart);
358   (void) visi_RegistrationCallback(PHASEEND,Dg_PhaseEnd);
359   (void) visi_RegistrationCallback(PHASEDATA,Dg_PhaseData);
360   (void) visi_RegistrationCallback(PARADYNEXITED,Dg_Exited);
361
362   Tcl_CreateCommand(interp, "Dg", Dg_TclCommand, 
363                     (ClientData *) NULL,(Tcl_CmdDeleteProc *) NULL);
364  
365   // Arrange for my_visi_callback() to be called whenever data is waiting
366   // to be read off of descriptor "fd".  Extremely important! [tcl book
367   // page 357]
368   Tk_CreateFileHandler(fd, TK_READABLE, (Tk_FileProc *) my_visi_callback, 0);
369
370   return TCL_OK;
371 }
372
373