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