Removed extra StartVisi() bug.
[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.5  1994/10/11 21:59:47  tamches
6 /* Removed extra StartVisi() bug.
7 /* Implemented dataGrid[][].Enabled()
8 /*
9  * Revision 1.4  1994/10/10  23:08:47  tamches
10  * preliminary changes on the way to swapping the x and y axes
11  *
12  * Revision 1.3  1994/10/10  14:36:18  tamches
13  * fixed some resizing bugs
14  *
15  * Revision 1.2  1994/09/29  20:05:39  tamches
16  * minor cvs fixes
17  *
18  * Revision 1.1  1994/09/29  19:52:25  tamches
19  * initial implementation.
20  * This is a modified version of DGclient.C (tclVisi/src), specially
21  * tuned for the barchart program.
22  *
23 */
24
25 // An updated version of DGClient.C for barchart2.C
26 // Contains several **deletions** to remove blt_barchart influences
27
28 #include <stdlib.h> // exit()
29 #include <iostream.h>
30 #include <tcl.h>
31 #include <tk.h>
32 #include "dg2.h"
33 #include "visi/h/visualization.h"
34 #include "barChartTcl.h"
35 #include "barChart.h"
36
37
38 void my_visi_callback(void* arg0, int* arg1, long unsigned int* arg2) {
39    if (visi_callback() == -1)
40       exit(0);
41 }
42
43 int Dg2AddMetricsCallback(int dummy) {
44   int retval = Tcl_Eval(MainInterp, "DgConfigCallback");
45   if (retval == TCL_ERROR)
46      fprintf(stderr, "%s\n", MainInterp->result);
47
48   // if necessary, the tcl program will call xAxisHasChanged and/or yAxisHasChanged, which
49   // are commands we implement in barChart.C.
50   // We take action then.
51
52   return(retval);
53 }
54
55 int Dg2Fold(int dummy) {
56   int retval = Tcl_Eval(MainInterp, "DgFoldCallback");
57   if (retval == TCL_ERROR)
58     fprintf(stderr, "%s\n", MainInterp->result);
59
60   return(retval);
61 }
62
63 int Dg2InvalidMetricsOrResources(int dummy) {
64   int retval = Tcl_Eval(MainInterp, "DgInvalidCallback");
65   if (retval == TCL_ERROR)
66     fprintf(stderr, "%s\n", MainInterp->result);
67
68   return(retval);
69 }
70
71 int Dg2PhaseNameCallback(int dummy) {
72   int retval = Tcl_Eval(MainInterp, "DgPhaseCallback");
73   if (retval == TCL_ERROR)
74     fprintf(stderr, "%s\n", MainInterp->result);
75
76   return(retval);
77 }
78
79 #define   AGGREGATE        0
80 #define   BINWIDTH         1
81 #define   FOLDMETHOD       2
82 #define   METRICNAME       3
83 #define   METRICUNITS      4
84 #define   NUMBINS          5
85 #define   NUMMETRICS       6
86 #define   NUMRESOURCES     7
87 #define   DEFINEPHASE      8
88 #define   RESOURCENAME     9
89 #define   STARTSTREAM      10
90 #define   STOPSTREAM       11
91 #define   DGSUM            12
92 #define   DGVALID          13
93 #define   DGENABLED        14
94 #define   VALUE            15
95 #define   CMDERROR         16
96 #define   LASTBUCKET       17
97 #define   FIRSTBUCKET      18
98
99 struct cmdTabEntry {
100    char *cmdname;
101    int index;
102    int numargs;
103 };
104
105 static struct cmdTabEntry Dg_Cmds[] = {
106   {"aggregate",    AGGREGATE,       2},
107   {"binwidth",     BINWIDTH,        0},
108   {"firstbucket",  FIRSTBUCKET,     2},
109   {"foldmethod",   FOLDMETHOD,      2},
110   {"lastbucket",   LASTBUCKET,      2},
111   {"metricname",   METRICNAME,      1},
112   {"metricunits",  METRICUNITS,     1},
113   {"numbins",      NUMBINS,         0},
114   {"nummetrics",   NUMMETRICS,      0},
115   {"numresources", NUMRESOURCES,    0},
116   {"phase",        DEFINEPHASE,     3},
117   {"resourcename", RESOURCENAME,    1},
118   {"start",        STARTSTREAM,     2},
119   {"stop",         STOPSTREAM,      2},
120   {"sum",          DGSUM,           2},
121   {"valid",        DGVALID,         2},
122   {"enabled",      DGENABLED,       2},
123   {"value",        VALUE,           3},
124   {NULL,           CMDERROR,        0}
125 };
126
127 int findCommand(Tcl_Interp *interp, 
128                        int argc, 
129                        char *argv[]) {
130
131   if (argc == 0) {
132      sprintf(interp->result, "USAGE: Dg <option> [args...]\n");
133      return CMDERROR;
134   }
135
136   for (cmdTabEntry *C = Dg_Cmds; C->cmdname!=NULL; C++) {
137      if (strcmp(argv[0], C->cmdname) == 0) {
138         if (argc-1 == C->numargs) 
139            return C->index; // successful parsing
140
141         sprintf(interp->result, 
142               "%s: wrong number of args (%d). Should be %d\n",
143               argv[0], argc-1, C->numargs);
144         return CMDERROR;
145      }
146   }
147
148   sprintf(interp->result, "unknown option (%s)\n", argv[0]);
149   return CMDERROR;
150 }
151
152 int Dg_TclCommand(ClientData clientData,
153                Tcl_Interp *interp, 
154                int argc, 
155                char *argv[]) {
156   // entrypoint to the tcl "Dg" command we've installed
157   // all the sprintf()'s are rather slow...
158
159   // parse the arguments, using the global variable Dg_Cmds[] to tell what's what.
160   int cmdDex = findCommand(interp, argc-1, argv+1);
161   if (cmdDex == CMDERROR)
162     return TCL_ERROR;
163
164   int m, r, buck; // metric number, resource number, bucket number
165
166   switch(cmdDex) {
167   case AGGREGATE:   
168     m = atoi(argv[2]);
169     r = atoi(argv[3]);
170     sprintf(interp->result,"%g", dataGrid.AggregateValue(m,r));
171     return TCL_OK;
172
173   case BINWIDTH:     
174     sprintf(interp->result, "%g", dataGrid.BinWidth());
175     return TCL_OK;
176
177   case FIRSTBUCKET:
178     m = atoi(argv[2]);
179     r = atoi(argv[3]);
180     sprintf(interp->result,"%d", dataGrid[m][r].FirstValidBucket()); 
181     return TCL_OK;
182
183   case FOLDMETHOD:
184     m = atoi(argv[2]);
185     sprintf(interp->result,"%d", dataGrid.FoldMethod(m));
186     return TCL_OK;
187
188   case LASTBUCKET:
189     m = atoi(argv[2]);
190     r = atoi(argv[3]);
191     sprintf(interp->result,"%d", dataGrid[m][r].LastBucketFilled());
192     return TCL_OK;
193
194   case METRICNAME:  
195     m = atoi(argv[2]);
196     sprintf(interp->result, "%s", dataGrid.MetricName(m));
197     return TCL_OK;
198
199   case METRICUNITS:  
200     m = atoi(argv[2]);
201     sprintf(interp->result, "%s", dataGrid.MetricUnits(m));
202     return TCL_OK;
203
204   case NUMBINS:     
205     sprintf(interp->result, "%d", dataGrid.NumBins());
206     return TCL_OK;
207
208   case NUMMETRICS:  
209     sprintf(interp->result, "%d", dataGrid.NumMetrics());
210     return TCL_OK;
211
212   case NUMRESOURCES:
213     sprintf(interp->result, "%d", dataGrid.NumResources());
214     return TCL_OK;
215
216   case DEFINEPHASE:       
217     NamePhase(atof(argv[2]), atof(argv[3]), argv[4]);
218     return TCL_OK;
219
220   case RESOURCENAME:
221     r = atoi(argv[2]);
222     sprintf(interp->result, "%s", dataGrid.ResourceName(r));
223     return TCL_OK;
224
225   case STARTSTREAM:       
226     GetMetsRes(argv[2], atoi(argv[3]), 0); // 0-->histogram (1-->scalar)
227                                            // argv[3] is num
228     return TCL_OK;
229
230   case STOPSTREAM:
231     m = atoi(argv[2]);
232     r = atoi(argv[3]);
233     StopMetRes(m, r);
234     return TCL_OK;
235
236   case DGSUM:         
237     m = atoi(argv[2]);
238     r = atoi(argv[3]);
239     sprintf(interp->result,"%g", dataGrid.SumValue(m,r));
240     return TCL_OK;
241
242   case DGVALID:
243     m = atoi(argv[2]);
244     r = atoi(argv[3]);
245     sprintf(interp->result, "%d", dataGrid.Valid(m,r));
246     return TCL_OK;
247
248   case DGENABLED:
249     m = atoi(argv[2]);
250     r = atoi(argv[3]);
251     sprintf(interp->result, "%d", dataGrid[m][r].Enabled());
252 //    sprintf(interp->result, "%d", dataGrid.Enabled(m,r));
253     return TCL_OK;
254
255   case VALUE:       
256     m = atoi(argv[2]);
257     r = atoi(argv[3]);
258     buck = atoi(argv[4]);
259     sprintf(interp->result,"%g", dataGrid[m][r].Value(buck));
260     return TCL_OK;
261   }
262
263   sprintf(interp->result, "Internal error (func findCommand)\n");
264   return TCL_ERROR;
265 }
266
267 void (*UsersNewDataCallbackRoutine)(int firstBucket, int lastBucket);
268    // we will call this routine for you when we get a new-data callback
269    // from the visi lib (first, we do a bit of processing for you, such
270    // as determining what the range is buckets you haven't seen yet is).
271
272 int Dg2_Init(Tcl_Interp *interp) {
273    // initialize with the visi lib
274    int fd = VisiInit();
275    if (fd < 0) {
276       cerr << "Dg2_Init() -- could not initialize with the visi lib" << endl;
277       exit(5);
278    }
279
280    // Arrange for my_visi_callback() to be called whenever there is data waiting
281    // to be read off of descriptor "fd".  Extremely important! [tcl book page 357]
282    Tk_CreateFileHandler(fd, TK_READABLE, (Tk_FileProc *) my_visi_callback, 0);
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 (RegistrationCallback(ADDMETRICSRESOURCES, Dg2AddMetricsCallback) != 0) {
291       cerr << "Dg2_Init() -- couldn't install ADDMETRICSRESOURCES callback with visilib" << endl;
292       exit(5);
293    }
294
295    if (RegistrationCallback(FOLD, Dg2Fold) != 0) {
296       cerr << "Dg2_Init() -- couldn't install FOLD callback with visilib" << endl;
297       exit(5);
298    }
299
300    if (RegistrationCallback(INVALIDMETRICSRESOURCES, Dg2InvalidMetricsOrResources) != 0) {
301       cerr << "Dg2_Init() -- couldn't install INVALID callback with visilib" << endl;
302       exit(5);
303    }
304
305    if (RegistrationCallback(PHASENAME, Dg2PhaseNameCallback) != 0) {
306       cerr << "Dg2_Init() -- couldn't install PHASENAME callback with visilib" << endl;
307       exit(5);
308    }
309
310    if (RegistrationCallback(DATAVALUES, Dg2NewDataCallback) != 0) {
311       cerr << "Dg2_Init() -- couldn't install DATAVALUES callback with visilib" << endl;
312       exit(5);
313    }
314
315    // install "Dg" as a new tcl command; Dg_TclCommand() will be invoked when a script
316    // calls Dg.
317    Tcl_CreateCommand(interp, "Dg", Dg_TclCommand, 
318                     (ClientData *) NULL,(Tcl_CmdDeleteProc *) NULL);
319  
320    return TCL_OK;
321 }