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