First version of new table visi
[dyninst.git] / visiClients / tableVisi / src / dg2.C
1 // dg2.C
2 // customized (for tableVisi) version of DGclient.C in tclVisi directory
3
4 /*
5  * $Log: dg2.C,v $
6  * Revision 1.1  1995/11/04 00:44:11  tamches
7  * First version of new table visi
8  *
9  */
10
11 #include <stdlib.h> // exit()
12 #include <iostream.h>
13
14 #include "tclclean.h"
15 #include "tkclean.h"
16 #include "tkTools.h"
17
18 #include "tableVisiTcl.h"
19
20 #include "visi/h/visualization.h"
21 #include "dg2.h"
22
23 void my_visi_callback(ClientData, int) {
24    // Installed as a file-handler routine for whenever data arrives over
25    // the socket returned from VisiInit()
26    if (visi_callback() == -1)
27       exit(0);
28 }
29
30 #define   AGGREGATE        0
31 #define   BINWIDTH         1
32 #define   FOLDMETHOD       2
33 #define   METRICNAME       3
34 #define   METRICUNITS      4
35 #define   NUMBINS          5
36 #define   NUMMETRICS       6
37 #define   NUMRESOURCES     7
38 #define   DEFINEPHASE      8
39 #define   RESOURCENAME     9
40 #define   STARTSTREAM      10
41 #define   STOPSTREAM       11
42 #define   DGSUM            12
43 #define   DGVALID          13
44 #define   DGENABLED        14
45 #define   VALUE            15
46 #define   CMDERROR         16
47 #define   LASTBUCKET       17
48 #define   FIRSTBUCKET      18
49
50 struct cmdTabEntry {
51    const char *cmdname;
52    int index;
53    int numargs;
54 };
55
56 static struct cmdTabEntry Dg_Cmds[] = {
57   {"aggregate",    AGGREGATE,       2},
58   {"binwidth",     BINWIDTH,        0},
59   {"firstbucket",  FIRSTBUCKET,     2},
60   {"foldmethod",   FOLDMETHOD,      2},
61   {"lastbucket",   LASTBUCKET,      2},
62   {"metricname",   METRICNAME,      1},
63   {"metricunits",  METRICUNITS,     1},
64   {"numbins",      NUMBINS,         0},
65   {"nummetrics",   NUMMETRICS,      0},
66   {"numresources", NUMRESOURCES,    0},
67   {"phase",        DEFINEPHASE,     3},
68   {"resourcename", RESOURCENAME,    1},
69   {"start",        STARTSTREAM,     2},
70   {"stop",         STOPSTREAM,      2},
71   {"sum",          DGSUM,           2},
72   {"valid",        DGVALID,         2},
73   {"enabled",      DGENABLED,       2},
74   {"value",        VALUE,           3},
75   {NULL,           CMDERROR,        0}
76 };
77
78 int findCommand(Tcl_Interp *interp, 
79                        int argc, 
80                        char *argv[]) {
81
82   if (argc == 0) {
83      sprintf(interp->result, "USAGE: Dg <option> [args...]\n");
84      return CMDERROR;
85   }
86
87   for (cmdTabEntry *C = Dg_Cmds; C->cmdname!=NULL; C++) {
88      if (strcmp(argv[0], C->cmdname) == 0) {
89         if (argc-1 == C->numargs) 
90            return C->index; // successful parsing
91
92         sprintf(interp->result, 
93               "%s: wrong number of args (%d). Should be %d\n",
94               argv[0], argc-1, C->numargs);
95         return CMDERROR;
96      }
97   }
98
99   sprintf(interp->result, "unknown option (%s)\n", argv[0]);
100   return CMDERROR;
101 }
102
103 int Dg_TclCommand(ClientData, Tcl_Interp *interp, 
104                   int argc, char *argv[]) {
105   // entrypoint to the tcl "Dg" command we've installed
106   // all the sprintf()'s are rather slow...
107
108   // parse the arguments, using global vrble Dg_Cmds[] to tell what's what.
109   int cmdDex = findCommand(interp, argc-1, argv+1);
110   if (cmdDex == CMDERROR)
111     return TCL_ERROR;
112
113   int m, r, buck; // metric number, resource number, bucket number
114
115   switch(cmdDex) {
116   case AGGREGATE:   
117     m = atoi(argv[2]);
118     r = atoi(argv[3]);
119     sprintf(interp->result,"%g", dataGrid.AggregateValue(m,r));
120     return TCL_OK;
121
122   case BINWIDTH:     
123     sprintf(interp->result, "%g", dataGrid.BinWidth());
124     return TCL_OK;
125
126   case FIRSTBUCKET:
127     m = atoi(argv[2]);
128     r = atoi(argv[3]);
129     sprintf(interp->result,"%d", dataGrid[m][r].FirstValidBucket()); 
130     return TCL_OK;
131
132   case FOLDMETHOD:
133     m = atoi(argv[2]);
134     sprintf(interp->result,"%d", dataGrid.FoldMethod(m));
135     return TCL_OK;
136
137   case LASTBUCKET:
138     m = atoi(argv[2]);
139     r = atoi(argv[3]);
140     sprintf(interp->result,"%d", dataGrid[m][r].LastBucketFilled());
141     return TCL_OK;
142
143   case METRICNAME:  
144     m = atoi(argv[2]);
145     sprintf(interp->result, "%s", dataGrid.MetricName(m));
146     return TCL_OK;
147
148   case METRICUNITS:  
149     m = atoi(argv[2]);
150     sprintf(interp->result, "%s", dataGrid.MetricUnits(m));
151     return TCL_OK;
152
153   case NUMBINS:     
154     sprintf(interp->result, "%d", dataGrid.NumBins());
155     return TCL_OK;
156
157   case NUMMETRICS:  
158     sprintf(interp->result, "%d", dataGrid.NumMetrics());
159     return TCL_OK;
160
161   case NUMRESOURCES:
162     sprintf(interp->result, "%d", dataGrid.NumResources());
163     return TCL_OK;
164
165   case DEFINEPHASE:       
166     DefinePhase(-1.0,NULL);
167     return TCL_OK;
168
169   case RESOURCENAME:
170     r = atoi(argv[2]);
171     sprintf(interp->result, "%s", dataGrid.ResourceName(r));
172     return TCL_OK;
173
174   case STARTSTREAM:       
175     GetMetsRes(argv[2], atoi(argv[3]), 0); // 0-->histogram (1-->scalar)
176                                            // argv[3] is num
177     return TCL_OK;
178
179   case STOPSTREAM:
180     m = atoi(argv[2]);
181     r = atoi(argv[3]);
182     StopMetRes(m, r);
183     return TCL_OK;
184
185   case DGSUM:         
186     m = atoi(argv[2]);
187     r = atoi(argv[3]);
188     sprintf(interp->result,"%g", dataGrid.SumValue(m,r));
189     return TCL_OK;
190
191   case DGVALID:
192     m = atoi(argv[2]);
193     r = atoi(argv[3]);
194     sprintf(interp->result, "%d", dataGrid.Valid(m,r));
195     return TCL_OK;
196
197   case DGENABLED:
198     m = atoi(argv[2]);
199     r = atoi(argv[3]);
200     sprintf(interp->result, "%d", dataGrid[m][r].Enabled());
201     return TCL_OK;
202
203   case VALUE:       
204     m = atoi(argv[2]);
205     r = atoi(argv[3]);
206     buck = atoi(argv[4]);
207     sprintf(interp->result,"%g", dataGrid[m][r].Value(buck));
208     return TCL_OK;
209   }
210
211   sprintf(interp->result, "Internal error (func findCommand)\n");
212   return TCL_ERROR;
213 }
214
215 void (*UsersNewDataCallbackRoutine)(int firstBucket, int lastBucket);
216    // we will call this routine for you when we get a new-data callback
217    // from the visi lib (first, we do a bit of processing for you, such
218    // as determining what the range is buckets you haven't seen yet is).
219
220 extern void panic(const char *);
221
222 int Dg2_Init(Tcl_Interp *interp) {
223    // initialize with the visi lib
224    int fd = VisiInit();
225    if (fd < 0) {
226       cerr << "Dg2_Init() -- could not initialize with the visi lib" << endl;
227       exit(5);
228    }
229
230    // Register C++ Callback routines with the visi lib when
231    // certain events happen.  The most important (performance-wise)
232    // is the DATAVALUES callback, which signals the arrival of
233    // new barchart data.  We must process this callback very quickly,
234    // in order to perturb the system as little as possible.
235
236    if (RegistrationCallback(ADDMETRICSRESOURCES, Dg2AddMetricsCallback) != 0)
237       panic("Dg2_Init() -- couldn't install ADDMETRICSRESOURCES callback");
238
239    if (RegistrationCallback(FOLD, Dg2Fold) != 0)
240       panic("Dg2_Init() -- couldn't install FOLD callback");
241
242    if (RegistrationCallback(INVALIDMETRICSRESOURCES, Dg2InvalidMetricsOrResources) != 0)
243       panic("Dg2_Init() -- couldn't install INVALID callback");
244
245    if (RegistrationCallback(PHASESTART, Dg2PhaseNameCallback) != 0)
246       panic("Dg2_Init() -- couldn't install PHASENAME callback");
247
248    if (RegistrationCallback(DATAVALUES, Dg2NewDataCallback) != 0)
249       panic("Dg2_Init() -- couldn't install DATAVALUES callback");
250
251    // install "Dg" as a new tcl command; Dg_TclCommand() will be invoked when
252    // a tcl script calls Dg
253    Tcl_CreateCommand(interp, "Dg", Dg_TclCommand, 
254                     (ClientData *) NULL,(Tcl_CmdDeleteProc *) NULL);
255  
256    // Arrange for my_visi_callback() to be called whenever data is waiting
257    // to be read off of descriptor "fd".  Extremely important! [tcl book
258    // page 357]
259    Tk_CreateFileHandler(fd, TK_READABLE, my_visi_callback, 0);
260
261    return TCL_OK;
262 }