changes due to visiLib interface changes
[dyninst.git] / visiClients / barchart / src / dg2.C
1 // dg2.C
2 // customized (for barchart) version of DGclient.C in tclVisi directory
3
4 /* $Log: dg2.C,v $
5 /* Revision 1.15  1996/01/19 20:56:06  newhall
6 /* changes due to visiLib interface changes
7 /*
8  * Revision 1.14  1996/01/17 18:31:14  newhall
9  * changes due to new visiLib
10  *
11  * Revision 1.13  1996/01/10 21:11:15  tamches
12  * added METRICAVEUNITS, METRICSUMUNITS
13  *
14  * Revision 1.12  1995/11/29 00:40:07  tamches
15  * removed myTclEval
16  *
17  * Revision 1.11  1995/11/17 17:39:32  newhall
18  * changed Dg start command, and call to GetMetsRes
19  *
20  * Revision 1.10  1995/11/17  17:32:27  newhall
21  * changed Dg start command to take no arguments, replaced call to MetricUnits
22  * with call to MetricLabel
23  *
24  * Revision 1.9  1995/09/22  19:23:41  tamches
25  * removed warnings under g++ 2.7.0
26  *
27  * Revision 1.8  1995/08/06  22:11:48  tamches
28  * removed some warnings by using myTclEval
29  *
30  * Revision 1.7  1995/02/26  02:01:48  newhall
31  * added callback functions for new visiLib phase info.
32  *
33  * Revision 1.6  1994/11/06  10:24:04  tamches
34  * minor cleanups (especially commenting)
35  *
36  * Revision 1.5  1994/10/11  21:59:47  tamches
37  * Removed extra StartVisi() bug.
38  * Implemented dataGrid[][].Enabled()
39  *
40  * Revision 1.4  1994/10/10  23:08:47  tamches
41  * preliminary changes on the way to swapping the x and y axes
42  *
43  * Revision 1.3  1994/10/10  14:36:18  tamches
44  * fixed some resizing bugs
45  *
46  * Revision 1.2  1994/09/29  20:05:39  tamches
47  * minor cvs fixes
48  *
49  * Revision 1.1  1994/09/29  19:52:25  tamches
50  * initial implementation.
51  * This is a modified version of DGclient.C (tclVisi/src), specially
52  * tuned for the barchart program.
53  *
54 */
55
56 // An updated version of DGClient.C for barchart2.C
57 // Contains several **deletions** to remove blt_barchart influences
58
59 #include <stdlib.h> // exit()
60 #include <iostream.h>
61
62 #include "tcl.h"
63 #include "tk.h"
64 #include "tkTools.h" // myTclEval()
65
66 #include "dg2.h"
67 #include "visi/h/visualization.h"
68 #include "barChartTcl.h"
69 #include "barChart.h"
70
71 void my_visi_callback(void*, int*, long unsigned int*) {
72    if (visi_callback() == -1)
73       exit(0);
74 }
75
76 int Dg2AddMetricsCallback(int) {
77    myTclEval(MainInterp, "DgConfigCallback");
78
79    // if necessary, the tcl program will call xAxisHasChanged and/or
80    // yAxisHasChanged, which are commands we implement in barChart.C.
81    // We take action then.
82
83    return TCL_OK;
84 }
85
86 int Dg2Fold(int) {
87    myTclEval(MainInterp, "DgFoldCallback");
88    return TCL_OK;
89 }
90
91 int Dg2InvalidMetricsOrResources(int) {
92    myTclEval(MainInterp, "DgInvalidCallback");
93    return TCL_OK;
94 }
95
96 int Dg2PhaseNameCallback(int) {
97    myTclEval(MainInterp, "DgPhaseCallback");
98    return TCL_OK;
99 }
100
101 #define   AGGREGATE        0
102 #define   BINWIDTH         1
103 #define   FOLDMETHOD       2
104 #define   METRICNAME       3
105 #define   METRICUNITS      4
106 #define   METRICAVEUNITS   5
107 #define   METRICSUMUNITS   6
108 #define   NUMBINS          7
109 #define   NUMMETRICS       8
110 #define   NUMRESOURCES     9
111 #define   DEFINEPHASE      10
112 #define   RESOURCENAME     11
113 #define   STARTSTREAM      12
114 #define   STOPSTREAM       13
115 #define   DGSUM            14
116 #define   DGVALID          15
117 #define   DGENABLED        16
118 #define   VALUE            17
119 #define   CMDERROR         18
120 #define   LASTBUCKET       19
121 #define   FIRSTBUCKET      20
122
123 struct cmdTabEntry {
124    const char *cmdname;
125    int index;
126    int numargs;
127 };
128
129 static struct cmdTabEntry Dg_Cmds[] = {
130   {"aggregate",    AGGREGATE,       2},
131   {"binwidth",     BINWIDTH,        0},
132   {"firstbucket",  FIRSTBUCKET,     2},
133   {"foldmethod",   FOLDMETHOD,      2},
134   {"lastbucket",   LASTBUCKET,      2},
135   {"metricname",   METRICNAME,      1},
136   {"metricunits",  METRICUNITS,     1},
137   {"metricaveunits", METRICAVEUNITS,1},
138   {"metricsumunits", METRICSUMUNITS,1},
139   {"numbins",      NUMBINS,         0},
140   {"nummetrics",   NUMMETRICS,      0},
141   {"numresources", NUMRESOURCES,    0},
142   {"phase",        DEFINEPHASE,     3},
143   {"resourcename", RESOURCENAME,    1},
144   {"start",        STARTSTREAM,     2},
145   {"stop",         STOPSTREAM,      2},
146   {"sum",          DGSUM,           2},
147   {"valid",        DGVALID,         2},
148   {"enabled",      DGENABLED,       2},
149   {"value",        VALUE,           3},
150   {NULL,           CMDERROR,        0}
151 };
152
153 int findCommand(Tcl_Interp *interp, 
154                        int argc, 
155                        char *argv[]) {
156
157   if (argc == 0) {
158      sprintf(interp->result, "USAGE: Dg <option> [args...]\n");
159      return CMDERROR;
160   }
161
162   for (cmdTabEntry *C = Dg_Cmds; C->cmdname!=NULL; C++) {
163      if (strcmp(argv[0], C->cmdname) == 0) {
164         if (argc-1 == C->numargs) 
165            return C->index; // successful parsing
166
167         sprintf(interp->result, 
168               "%s: wrong number of args (%d). Should be %d\n",
169               argv[0], argc-1, C->numargs);
170         return CMDERROR;
171      }
172   }
173
174   sprintf(interp->result, "unknown option (%s)\n", argv[0]);
175   return CMDERROR;
176 }
177
178 int Dg_TclCommand(ClientData,
179                   Tcl_Interp *interp, 
180                   int argc, char *argv[]) {
181   // entrypoint to the tcl "Dg" command we've installed
182   // all the sprintf()'s are rather slow...
183
184   // parse the arguments, using global vrble Dg_Cmds[] to tell what's what.
185   int cmdDex = findCommand(interp, argc-1, argv+1);
186   if (cmdDex == CMDERROR)
187     return TCL_ERROR;
188
189   int m, r, buck; // metric number, resource number, bucket number
190
191   switch(cmdDex) {
192   case AGGREGATE:   
193     m = atoi(argv[2]);
194     r = atoi(argv[3]);
195     sprintf(interp->result,"%g", visi_AverageValue(m,r));
196     return TCL_OK;
197
198   case BINWIDTH:     
199     sprintf(interp->result, "%g", visi_BucketWidth());
200     return TCL_OK;
201
202   case FIRSTBUCKET:
203     m = atoi(argv[2]);
204     r = atoi(argv[3]);
205     sprintf(interp->result,"%d", visi_FirstValidBucket(m,r)); 
206     return TCL_OK;
207
208   case LASTBUCKET:
209     m = atoi(argv[2]);
210     r = atoi(argv[3]);
211     sprintf(interp->result,"%d", visi_LastBucketFilled(m,r));
212     return TCL_OK;
213
214   case METRICNAME:  
215     m = atoi(argv[2]);
216     strcpy(interp->result, visi_MetricName(m));
217     return TCL_OK;
218
219   case METRICUNITS:  
220     m = atoi(argv[2]);
221     strcpy(interp->result, visi_MetricLabel(m));
222     return TCL_OK;
223
224   case METRICAVEUNITS:  
225     m = atoi(argv[2]);
226     strcpy(interp->result, visi_MetricAveLabel(m));
227     return TCL_OK;
228
229   case METRICSUMUNITS:  
230     m = atoi(argv[2]);
231     strcpy(interp->result, visi_MetricSumLabel(m));
232     return TCL_OK;
233
234   case NUMBINS:     
235     sprintf(interp->result, "%d", visi_NumBuckets());
236     return TCL_OK;
237
238   case NUMMETRICS:  
239     sprintf(interp->result, "%d", visi_NumMetrics());
240     return TCL_OK;
241
242   case NUMRESOURCES:
243     sprintf(interp->result, "%d", visi_NumResources());
244     return TCL_OK;
245
246   case DEFINEPHASE:       
247     visi_DefinePhase(NULL);
248     return TCL_OK;
249
250   case RESOURCENAME:
251     r = atoi(argv[2]);
252     strcpy(interp->result, visi_ResourceName(r));
253     return TCL_OK;
254
255   case STARTSTREAM:       
256     visi_GetMetsRes(argv[2],0); 
257     return TCL_OK;
258
259   case STOPSTREAM:
260     m = atoi(argv[2]);
261     r = atoi(argv[3]);
262     visi_StopMetRes(m, r);
263     return TCL_OK;
264
265   case DGSUM:         
266     m = atoi(argv[2]);
267     r = atoi(argv[3]);
268     sprintf(interp->result,"%g", visi_SumValue(m,r));
269     return TCL_OK;
270
271   case DGVALID:
272     m = atoi(argv[2]);
273     r = atoi(argv[3]);
274     sprintf(interp->result, "%d", visi_Valid(m,r));
275     return TCL_OK;
276
277   case DGENABLED:
278     m = atoi(argv[2]);
279     r = atoi(argv[3]);
280     sprintf(interp->result, "%d", visi_Enabled(m,r));
281 //    sprintf(interp->result, "%d", Enabled(m,r));
282     return TCL_OK;
283
284   case VALUE:       
285     m = atoi(argv[2]);
286     r = atoi(argv[3]);
287     buck = atoi(argv[4]);
288     sprintf(interp->result,"%g", visi_DataValue(m,r,buck));
289     return TCL_OK;
290   }
291
292   sprintf(interp->result, "Internal error (func findCommand)\n");
293   return TCL_ERROR;
294 }
295
296 void (*UsersNewDataCallbackRoutine)(int firstBucket, int lastBucket);
297    // we will call this routine for you when we get a new-data callback
298    // from the visi lib (first, we do a bit of processing for you, such
299    // as determining what the range is buckets you haven't seen yet is).
300
301 int Dg2_Init(Tcl_Interp *interp) {
302    // initialize with the visi lib
303    int fd = visi_Init();
304    if (fd < 0) {
305       cerr << "Dg2_Init() -- could not initialize with the visi lib" << endl;
306       exit(5);
307    }
308
309    // Register C++ Callback routines with the visi lib when
310    // certain events happen.  The most important (performance-wise)
311    // is the DATAVALUES callback, which signals the arrival of
312    // new barchart data.  We must process this callback very quickly,
313    // in order to perturb the system as little as possible.
314
315    if (visi_RegistrationCallback(ADDMETRICSRESOURCES,Dg2AddMetricsCallback)!=0)
316       panic("Dg2_Init() -- couldn't install ADDMETRICSRESOURCES callback");
317
318    if (visi_RegistrationCallback(FOLD, Dg2Fold) != 0)
319       panic("Dg2_Init() -- couldn't install FOLD callback");
320
321    if (visi_RegistrationCallback(INVALIDMETRICSRESOURCES, Dg2InvalidMetricsOrResources) != 0)
322       panic("Dg2_Init() -- couldn't install INVALID callback");
323
324    if (visi_RegistrationCallback(PHASESTART, Dg2PhaseNameCallback) != 0)
325       panic("Dg2_Init() -- couldn't install PHASENAME callback");
326
327    if (visi_RegistrationCallback(DATAVALUES, Dg2NewDataCallback) != 0)
328       panic("Dg2_Init() -- couldn't install DATAVALUES callback");
329
330    // install "Dg" as a new tcl command; Dg_TclCommand() will be invoked when
331    // a tcl script calls Dg
332    Tcl_CreateCommand(interp, "Dg", Dg_TclCommand, 
333                     (ClientData *) NULL,(Tcl_CmdDeleteProc *) NULL);
334  
335    // Arrange for my_visi_callback() to be called whenever data is waiting
336    // to be read off of descriptor "fd".  Extremely important! [tcl book
337    // page 357]
338    Tk_CreateFileHandler(fd, TK_READABLE, (Tk_FileProc *) my_visi_callback, 0);
339
340    return TCL_OK;
341 }