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