Fixed problem bwylie found with mdl.C for fully optimized code.
[dyninst.git] / paradyn / src / met / mdl.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /*
43  * $Log: mdl.C,v $
44  * Revision 1.32  1997/12/03 20:38:27  mcheyney
45  * Fixed problem bwylie found with mdl.C for fully optimized code.
46  *
47  * Revision 1.31  1997/11/26 21:47:49  mcheyney
48  * Changed syntax of exclude statement:
49  * Old:
50  *   exclude "function"  or
51  *   exclude "module/function"
52  * New:
53  *   exclude "/Code/module" or
54  *   exclude "/Code/module/function"
55  * Also some small mdl changes to make syntax a bit more transparent in
56  *  a few places & get rid of a few warnings.
57  *
58  * Revision 1.30  1997/06/27 18:21:20  tamches
59  * removed some warnings
60  *
61  * Revision 1.29  1997/06/24 19:57:25  tamches
62  * dummy mk_list()
63  *
64  * Revision 1.28  1997/06/07 21:01:22  newhall
65  * replaced exclude_func and exclude_lib with exclude_node
66  *
67  * Revision 1.27  1997/06/05 04:29:44  newhall
68  * added exclude_func mdl option to exclude shared object functions
69  *
70  * Revision 1.26  1997/04/14 20:01:52  zhichen
71  * Added MDL_T_RECORD and fixed a bug.
72  *
73  * Revision 1.25  1997/04/02 22:34:52  zhichen
74  * added 'Memory'
75  *
76  * Revision 1.24  1997/03/29 02:06:06  sec
77  * Changed /MsgTag to /Message
78  * Added environment variables $constraint[0], $constraint[1], etc.
79  * instead of $constraint
80  *
81  * Revision 1.23  1997/02/21 20:20:35  naim
82  * Eliminating references to dataReqNode from the ast class - Pre-dyninstAPI
83  * commit - naim
84  *
85  * Revision 1.22  1997/01/15 00:14:29  tamches
86  * extra bool arg to apply
87  *
88  * Revision 1.21  1996/11/14 14:19:33  naim
89  * Changing AstNodes back to pointers to improve performance - naim
90  *
91  * Revision 1.20  1996/10/08 21:52:14  mjrg
92  * changed the evaluation of resource lists
93  * removed warnings
94  *
95  * Revision 1.19  1996/09/26 19:03:25  newhall
96  * added "exclude_lib" mdl option
97  *
98  * Revision 1.18  1996/08/16 21:12:16  tamches
99  * updated copyright for release 1.1
100  *
101  * Revision 1.17  1996/03/25 20:18:37  tamches
102  * the reduce-mem-leaks-in-paradynd commit
103  *
104  * Revision 1.16  1996/03/20 17:04:16  mjrg
105  * Changed mdl to support calls with multiple arguments.
106  *
107  * Revision 1.15  1996/03/09 19:53:16  hollings
108  * Fixed a call to apply that was passing NULL where a vector was expected.
109  *
110  *
111  */
112 #include "dyninstRPC.xdr.CLNT.h"
113 #include "paradyn/src/met/globals.h"
114 #include "paradyn/src/met/metricExt.h"
115
116 #include <iostream.h>
117 #include <stdio.h>
118
119 extern FILE *yyin;
120 extern int yyparse();
121
122 #ifdef notdef
123 // Determine the type of "$constraint"
124 bool hack_in_cons=false;
125 void hack_cons_type(vector<string>*);
126 unsigned hacked_cons_type = MDL_T_NONE;
127 #endif
128
129 inline unsigned ui_hash(const unsigned &u) { return u; }
130
131 vector<unsigned> mdl_env::frames;
132 vector<mdl_var> mdl_env::all_vars;
133
134 vector<T_dyninstRPC::mdl_stmt*> mdl_data::stmts;
135 vector<T_dyninstRPC::mdl_metric*> mdl_data::all_metrics;
136 dictionary_hash<unsigned, vector<mdl_type_desc> > mdl_data::fields(ui_hash);
137 vector<mdl_focus_element> mdl_data::foci;
138 vector<T_dyninstRPC::mdl_constraint*> mdl_data::all_constraints;
139 vector<string> mdl_data::lib_constraints;
140
141 static bool do_operation(mdl_var& ret, mdl_var& left, mdl_var& right, unsigned bin_op);
142
143
144 void mdl_data::unique_name(string name) {
145   unsigned sz = mdl_data::stmts.size();
146   for (unsigned u = 0; u < sz; u++) {
147     T_dyninstRPC::mdl_list_stmt *lstmt = 
148                           (T_dyninstRPC::mdl_list_stmt *) mdl_data::stmts[u];
149     if (lstmt->id_ == name) {
150       delete mdl_data::stmts[u];
151       for (unsigned v = u; v < sz-1; v++) {
152         mdl_data::stmts[v] = mdl_data::stmts[v+1];
153       }
154       mdl_data::stmts.resize(sz-1);
155       break;
156     }
157   }
158
159   sz = mdl_data::all_constraints.size();
160   for (unsigned u = 0; u < sz; u++) {
161     if (mdl_data::all_constraints[u]->id_ == name) {
162       delete mdl_data::all_constraints[u];
163       for (unsigned v = u; v < sz-1; v++) {
164         mdl_data::all_constraints[v] = mdl_data::all_constraints[v+1];
165       }
166       mdl_data::all_constraints.resize(sz-1);
167       break;
168     }
169   }
170
171   sz = mdl_data::all_metrics.size();
172   for (unsigned u = 0; u < sz; u++) {
173     if (mdl_data::all_metrics[u]->id_ == name) {
174       delete mdl_data::all_metrics[u];
175       for (unsigned v = u; v < sz-1; v++) {
176         mdl_data::all_metrics[v] = mdl_data::all_metrics[v+1];
177       }
178       mdl_data::all_metrics.resize(sz-1);
179       break;
180     }
181   }
182 }
183
184
185 T_dyninstRPC::mdl_metric::mdl_metric(string id, string name, string units, 
186                                     u_int agg, u_int sty, u_int type,
187                                     vector<T_dyninstRPC::mdl_stmt*> *mv, 
188                                     vector<string> *flav,
189                                     vector<T_dyninstRPC::mdl_constraint*> *cons,
190                                     vector<string> *temp_counters,
191                                     bool developerMode,
192                                     int unitstype)
193 : id_(id), name_(name), units_(units), agg_op_(agg), style_(sty),
194   type_(type), stmts_(mv), flavors_(flav), constraints_(cons),
195   temp_ctr_(temp_counters), developerMode_(developerMode),
196   unitstype_(unitstype) { }
197
198 T_dyninstRPC::mdl_metric::mdl_metric() { }
199
200 T_dyninstRPC::mdl_metric::~mdl_metric() {
201   if (stmts_) {
202     unsigned size = stmts_->size();
203     for (unsigned u=0; u<size; u++)
204       delete (*stmts_)[u];
205     delete stmts_;
206   }
207   delete flavors_;
208   if (constraints_) {
209     unsigned size = constraints_->size();
210     for (unsigned u=0; u<size; u++)
211       delete (*constraints_)[u];
212     delete constraints_;
213   }
214 }
215
216 bool mdl_data::new_metric(string id, string name, string units,
217                           u_int agg, u_int sty, u_int type,
218                           vector<T_dyninstRPC::mdl_stmt*> *mv,
219                           vector<string> *flavs,
220                           vector<T_dyninstRPC::mdl_constraint*> *cons,
221                           vector<string> *temp_counters,
222                           bool developerMode,
223                           int normalized) {
224
225   T_dyninstRPC::mdl_metric *m = new T_dyninstRPC::mdl_metric(id, name, units, 
226                                                              agg,
227                                                              sty, type, mv, 
228                                                              flavs, cons,
229                                                              temp_counters,
230                                                              developerMode,
231                                                              normalized);
232   if (!m)
233     return false;
234   else {
235     mdl_data::unique_name(id);
236 #ifdef notdef
237     unsigned am_size = all_metrics.size();
238     for (unsigned am=0; am<am_size; am++)
239       if (all_metrics[am]->id_ == name) {
240         delete all_metrics[am];
241         all_metrics[am] = m;
242         return true;
243       }
244 #endif
245     all_metrics += m;
246     return true;
247   }
248 }
249
250 metricDefinitionNode *T_dyninstRPC::mdl_metric::apply(vector< vector<string> >&,
251                                                       string& , 
252                                                       vector<process *>,
253                                                       bool, bool) {
254   mdl_env::push();
255   if (!mdl_env::add(id_, true, type_)) return NULL;
256   assert(temp_ctr_);
257   unsigned tc_size = temp_ctr_->size();
258   for (unsigned tc=0; tc<tc_size; tc++)
259     if (!mdl_env::add((*temp_ctr_)[tc], true, MDL_T_COUNTER)) return NULL;
260   assert(stmts_);
261   unsigned size = stmts_->size();
262
263   vector<dataReqNode*> flags;
264   for (unsigned u=0; u<size; u++) {
265     if (!(*stmts_)[u]->apply(NULL, flags)) {
266       // cout << "apply of " << name_ << " failed\n";
267       return NULL;
268     }
269   }
270   size = constraints_->size();
271   for (unsigned u1=0; u1<size; u1++) {
272     if ((*constraints_)[u1]->match_path_) {
273       // inlined constraint def
274       dataReqNode *drn = NULL; vector<string> res;
275       if (!(*constraints_)[u1]->apply(NULL, drn, res, NULL, false)) {
276         return NULL;
277       }
278     } else {
279       // name of global constraint
280       unsigned gl_size = mdl_data::all_constraints.size(); bool found=false;
281       for (unsigned in=0; in<gl_size; in++)
282         if (mdl_data::all_constraints[in]->id_ == (*constraints_)[u1]->id_) {
283           found = true; break;
284         }
285       if (!found) {
286           cout << "unable to find global constraint " << (*constraints_)[u1]->id_ << endl;
287           return NULL;            // The global constraint does not exist
288       }
289     }
290   }
291
292   // cout << "apply of " << name_ << " ok\n";
293   mdl_env::pop();
294   return ((metricDefinitionNode*)1);
295 }
296
297 T_dyninstRPC::mdl_constraint::mdl_constraint() { }
298 T_dyninstRPC::mdl_constraint::mdl_constraint(string id, vector<string> *match_path,
299                                       vector<T_dyninstRPC::mdl_stmt*> *stmts,
300                                       bool replace, u_int d_type, bool& error)
301 : id_(id), match_path_(match_path), stmts_(stmts), replace_(replace),
302   data_type_(d_type), hierarchy_(0), type_(0)
303 {
304   error = false;
305
306   if (!match_path) {
307     error = false;
308     return;
309   }
310
311   unsigned size = match_path->size();
312
313   if (match_path && size) {
314 //    if ((*match_path)[0] == "Procedure") {
315     if ((*match_path)[0] == "Code") {
316       hierarchy_ = MDL_RES_CODE;
317       type_ = (size == 1) ? MDL_T_MODULE : MDL_T_PROCEDURE;
318     } else if ((*match_path)[0] == "Process") {
319       hierarchy_ = MDL_RES_PROCESS;
320     } else if ((*match_path)[0] == "Machine") {
321       hierarchy_ = MDL_RES_MACHINE;
322     } else if((*match_path)[0] == "Memory") {
323       hierarchy_ = MDL_RES_MEMORY;
324       type_ = MDL_T_INT ;
325     } else if ((*match_path)[0] == "SyncObject") {
326       hierarchy_ = MDL_RES_SYNCOBJECT;
327       if (size == 1) {
328         type_ = MDL_T_STRING;
329 //    }
330 //    if (size != 2) {
331 //      type_ = MDL_T_NONE;
332       } else if ((*match_path)[1] == "SpinLock") {
333         type_ = MDL_T_INT;
334       } else if ((*match_path)[1] == "Barrier") {
335         type_ = MDL_T_INT;
336       } else if ((*match_path)[1] == "Message") {
337         type_ = MDL_T_INT;
338       } else if ((*match_path)[1] == "Semaphore") {
339         type_ = MDL_T_INT;
340       } else {
341         printf("Error in constraint '%s': unknown resource '%s'\n", 
342              id.string_of(), (*match_path)[1].string_of());
343         error = true;
344       }
345     } else {
346       printf("Error in constraint '%s': unknown resource '%s'\n", 
347              id.string_of(), (*match_path)[0].string_of());
348       error = true;
349     }
350   }
351 }
352
353 T_dyninstRPC::mdl_constraint::~mdl_constraint() {
354   delete match_path_;
355   if (stmts_) {
356     for (unsigned u=0; u<stmts_->size(); u++)
357       delete (*stmts_)[u];
358     delete stmts_;
359   }
360 }
361   
362 bool T_dyninstRPC::mdl_constraint::apply(metricDefinitionNode * , 
363                                          dataReqNode *& ,
364                                          vector<string>& , process *, bool ) {
365   mdl_env::push();
366
367   switch (data_type_) {
368   case MDL_T_COUNTER:
369   case MDL_T_WALL_TIMER:
370   case MDL_T_PROC_TIMER:
371     break;
372   case MDL_T_NONE:
373     return true;
374   default:
375     return false;
376   }
377
378   if (!mdl_env::add(id_, true, data_type_)) return false;
379   
380   // find the type for "$constraint"
381   if (!stmts_ || !match_path_) return false;
382   unsigned size = match_path_->size();
383   if (!size) return false;
384   for(int dx = 0; dx < size; dx++) {
385     string s = string("$constraint") + string(dx);
386     if (!mdl_env::add(s, false, type_)) {
387       mdl_env::pop(); return false;
388     }
389   }
390
391   unsigned stmts_size = stmts_->size();
392   vector<dataReqNode*> flags;
393   for (unsigned q=0; q<stmts_size; q++)
394     if (!(*stmts_)[q]->apply(NULL, flags)) {
395       mdl_env::pop();
396       return false;
397     }
398   mdl_env::pop();
399   return true;
400 }
401
402 T_dyninstRPC::mdl_constraint *mdl_data::new_constraint(string id, vector<string> *path,
403                                                 vector<T_dyninstRPC::mdl_stmt*> *stmts,
404                                                 bool replace, u_int d_type) {
405   bool error;
406   T_dyninstRPC::mdl_constraint *cons = new T_dyninstRPC::mdl_constraint(id, path, stmts,
407                                                                         replace, d_type,
408                                                                         error);
409   if (error) {
410     delete cons;
411     return NULL;
412   } else
413     return cons;
414 }
415
416
417 T_dyninstRPC::mdl_rand::mdl_rand() {}
418
419 T_dyninstRPC::mdl_instr_rand::mdl_instr_rand() {}
420
421 T_dyninstRPC::mdl_instr_rand::mdl_instr_rand(u_int type)
422   : type_(type), val_(0), name_("") {}
423
424 T_dyninstRPC::mdl_instr_rand::mdl_instr_rand(u_int type, u_int val)
425   : type_(type), val_(val), name_("") {}
426
427 T_dyninstRPC::mdl_instr_rand::mdl_instr_rand(u_int type, string name)
428   : type_(type), val_(0), name_(name) {}
429
430 T_dyninstRPC::mdl_instr_rand::mdl_instr_rand(u_int type, string name, vector<mdl_instr_rand *>args)
431 : type_(type), val_(0), name_(name) {
432   for (unsigned u = 0; u < args.size(); u++)
433     args_ += args[u];
434 }
435
436 T_dyninstRPC::mdl_instr_rand::~mdl_instr_rand() { } 
437
438
439 bool T_dyninstRPC::mdl_instr_rand::apply(AstNode *&) {
440   AstNode *ast=NULL;
441   switch (type_) {
442   case MDL_T_INT:
443     break;
444   case MDL_ARG:
445     // TODO -- check arg_ that is used as register index
446     // Check the legality of this -- or allow to be used anywhere ?
447     break;
448   case MDL_RETURN:
449     break;
450   case MDL_READ_SYMBOL:
451     break;
452   case MDL_READ_ADDRESS:
453     break;
454   case MDL_CALL_FUNC:
455     for (unsigned u = 0; u < args_.size(); u++)
456       if (!args_[u]->apply(ast))
457         return false;
458     break;
459   case MDL_T_COUNTER:
460     break;
461   case MDL_T_COUNTER_PTR:
462     break;
463   case MDL_T_RECORD:
464     break;
465   default:
466     cout << "invalid operand\n";
467     return false;
468   }
469   return true;
470 }
471
472
473 T_dyninstRPC::mdl_instr_req::mdl_instr_req() { }
474
475 T_dyninstRPC::mdl_instr_req::mdl_instr_req(T_dyninstRPC::mdl_instr_rand *rand,
476                                            u_int type, string obj_name)
477 : type_(type), rand_(rand), timer_counter_name_(obj_name) { }
478
479 T_dyninstRPC::mdl_instr_req::mdl_instr_req(u_int type, string obj_name)
480 : type_(type), rand_(0), timer_counter_name_(obj_name) { }
481
482 T_dyninstRPC::mdl_instr_req::mdl_instr_req(u_int type,
483                                            T_dyninstRPC::mdl_instr_rand *rand)
484 : type_(type), rand_(rand), timer_counter_name_("") { }
485
486 T_dyninstRPC::mdl_instr_req::~mdl_instr_req() { }
487
488 //
489 // XXXX - This entire routine needs to be gutted. At minimum any condition that
490 // XXXX   produces a false return value should log a warning.  Right now it 
491 // XXXX   silently deletes metrics from considuration.  Debugging MDL is almost
492 // XXXX   impossible.  jkh 7/6/95.
493 //
494 bool T_dyninstRPC::mdl_instr_req::apply(AstNode *&, AstNode *, bool) {
495   // the args aren't used here, but they must be kept since paradynd's mdl
496   // uses them, or something like that...
497   AstNode *ast;
498   switch (type_) {
499   case MDL_SET_COUNTER:
500   case MDL_ADD_COUNTER:
501   case MDL_SUB_COUNTER:
502   case MDL_CALL_FUNC:
503     if (!rand_->apply(ast))
504       return false;
505     break;
506   }
507
508   // skip all this crude for a function call, must check at runtime in
509   //   paradynd.
510   if (type_ == MDL_CALL_FUNC) return true;
511
512   mdl_var timer;
513   if (!mdl_env::get(timer, timer_counter_name_)) return false;
514
515   switch (type_) {
516   case MDL_SET_COUNTER:
517   case MDL_ADD_COUNTER:
518   case MDL_SUB_COUNTER:
519   // should not have a timer as the first argument here. - jkh 7/6/95.
520   // case MDL_CALL_FUNC:
521     if (timer.type() != MDL_T_COUNTER) return false;
522     break;
523   case MDL_START_WALL_TIMER:
524   case MDL_STOP_WALL_TIMER:
525     if (timer.type() != MDL_T_WALL_TIMER) {
526         cout << "operand of timer operation is not a wall timer\n";
527         return false;
528     }
529     break;
530   case MDL_START_PROC_TIMER:
531   case MDL_STOP_PROC_TIMER:
532     if (timer.type() != MDL_T_PROC_TIMER) {
533         cout << "operand of timer operation is not a process timer\n";
534         return false;
535     }
536     break;
537   default:
538       cout << "unkown instrumentation request type\n";
539       return false;
540   }
541   return true;
542 }
543
544 T_dyninstRPC::mdl_stmt::mdl_stmt() { }
545
546 T_dyninstRPC::mdl_for_stmt::mdl_for_stmt(string index_name, T_dyninstRPC::mdl_expr *list_exp, T_dyninstRPC::mdl_stmt *body) 
547 : for_body_(body), index_name_(index_name), list_expr_(list_exp) { }
548 T_dyninstRPC::mdl_for_stmt::mdl_for_stmt() { }
549 T_dyninstRPC::mdl_for_stmt::~mdl_for_stmt() {
550   delete for_body_;
551   delete list_expr_;
552 }
553
554 bool T_dyninstRPC::mdl_for_stmt::apply(metricDefinitionNode *mn,
555                                          vector<dataReqNode*>& flags) {
556   mdl_env::push();
557   if (!mdl_env::add(index_name_, false)) return false;
558   mdl_var list_var(false);
559   if (!list_expr_->apply(list_var))
560     return false;
561   if (!list_var.is_list())
562     return false;
563   mdl_env::set_type(list_var.element_type(), index_name_);
564   bool res = for_body_->apply(mn, flags);
565   mdl_env::pop();
566   return res;
567 }
568
569 T_dyninstRPC::mdl_list_stmt::mdl_list_stmt(u_int type, string ident,
570                                            vector<string> *elems,
571                                            bool is_lib, vector<string> *flavor) 
572 : type_(type), id_(ident), elements_(elems), is_lib_(is_lib), flavor_(flavor) { }
573 T_dyninstRPC::mdl_list_stmt::mdl_list_stmt() { }
574 T_dyninstRPC::mdl_list_stmt::~mdl_list_stmt() { delete elements_; }
575
576 bool T_dyninstRPC::mdl_list_stmt::apply(metricDefinitionNode * ,
577                                          vector<dataReqNode*>& ) {
578   if (!elements_)
579     return false;
580   unsigned list_type = MDL_T_NONE;
581   switch (type_) {
582   case MDL_T_INT: list_type = MDL_T_LIST_INT; break;
583   case MDL_T_FLOAT: list_type = MDL_T_LIST_FLOAT; break;
584   case MDL_T_STRING: list_type = MDL_T_LIST_STRING; break;
585   case MDL_T_PROCEDURE_NAME: list_type = MDL_T_LIST_PROCEDURE_NAME; break;
586   case MDL_T_MODULE: list_type = MDL_T_LIST_MODULE; break;
587   default: 
588       // this should only happen if there is a parser error.
589       abort();
590       return false;
591   }
592   return (mdl_env::add(id_, false, list_type));
593 }
594
595 T_dyninstRPC::mdl_icode::mdl_icode() {}
596 T_dyninstRPC::mdl_icode::mdl_icode(T_dyninstRPC::mdl_instr_rand *iop1,
597                                    T_dyninstRPC::mdl_instr_rand *iop2,
598                                    u_int bin_op, bool use_if,
599                                    T_dyninstRPC::mdl_instr_req *ireq)
600 : if_op1_(iop1),
601   if_op2_(iop2),
602   bin_op_(bin_op), use_if_(use_if), req_(ireq) { }
603 T_dyninstRPC::mdl_icode::~mdl_icode() { delete req_; }
604
605 bool T_dyninstRPC::mdl_icode::apply(AstNode *&mn, bool mn_initialized) {
606   if (!req_) return false;
607   if (use_if_) {
608     string empty;
609     AstNode *ast=NULL;
610     if (!if_op1_->apply(ast)) return false;
611     switch (bin_op_) {
612     case MDL_LT:  case MDL_GT:  case MDL_LE:  case MDL_GE:  case MDL_EQ:  case MDL_NE:
613       if (!if_op2_->apply(ast)) return false;
614       break;
615     case MDL_T_NONE:
616       break;
617     default:
618       return false;
619     }
620   }
621   return (req_->apply(mn, NULL, mn_initialized)); // NULL --> no predicate
622 }
623
624 T_dyninstRPC::mdl_expr::mdl_expr() { }
625 T_dyninstRPC::mdl_expr::~mdl_expr() { }
626
627 T_dyninstRPC::mdl_v_expr::mdl_v_expr() 
628 : args_(NULL), literal_(0), arg_(0), left_(NULL), right_(NULL), type_(MDL_T_NONE),
629   ok_(false) { }
630
631 T_dyninstRPC::mdl_v_expr::mdl_v_expr(string var, vector<string> fields) 
632 : var_(var), fields_(fields),
633   args_(NULL), literal_(0), arg_(0), left_(NULL), right_(NULL),
634   type_(MDL_RVAL_DEREF), do_type_walk_(false), ok_(false) { }
635
636 T_dyninstRPC::mdl_v_expr::mdl_v_expr(string func_name,
637                                      vector<T_dyninstRPC::mdl_expr *> *a) 
638 : var_(func_name), args_(a),
639   literal_(0), arg_(100000), left_(NULL), right_(NULL),
640   type_(MDL_RVAL_FUNC), do_type_walk_(false), ok_(false) { }
641
642 T_dyninstRPC::mdl_v_expr::mdl_v_expr(int int_lit) 
643 : args_(NULL), literal_(int_lit), arg_(0), left_(NULL), right_(NULL),
644   type_(MDL_RVAL_INT), do_type_walk_(false), ok_(false) { }
645
646 T_dyninstRPC::mdl_v_expr::mdl_v_expr(string string_lit) 
647 : var_(string_lit),
648   args_(NULL), literal_(0), arg_(0), left_(NULL), right_(NULL),
649   type_(MDL_RVAL_STRING), do_type_walk_(false), ok_(false) { }
650
651 T_dyninstRPC::mdl_v_expr::mdl_v_expr(u_int bin_op, T_dyninstRPC::mdl_expr *left,
652                                  T_dyninstRPC::mdl_expr *right) 
653 : args_(NULL), literal_(0),
654   arg_(bin_op), left_(left), right_(right),
655   type_(MDL_RVAL_EXPR), do_type_walk_(false), ok_(false) { }
656
657 T_dyninstRPC::mdl_v_expr::mdl_v_expr(string var, u_int array_index) 
658 : var_(var), args_(NULL), literal_(0), arg_(array_index), left_(NULL), right_(NULL),
659   type_(MDL_RVAL_ARRAY), do_type_walk_(false), ok_(false) { }
660
661 T_dyninstRPC::mdl_v_expr::~mdl_v_expr() {
662   delete args_; delete left_; delete right_;
663   if (args_) {
664     unsigned size = args_->size();
665     for (unsigned u=0; u<size; u++)
666       delete (*args_)[u];
667     delete args_;
668   }
669 }
670
671 bool T_dyninstRPC::mdl_v_expr::apply(mdl_var& ret) {
672   switch (type_) {
673   case MDL_RVAL_INT: 
674     ok_ = true;
675     return (ret.set(literal_));
676   case MDL_RVAL_STRING:
677     ok_ = true;
678     return (ret.set(var_));
679   case MDL_RVAL_ARRAY:
680     {
681       mdl_var array(false);
682       if (!mdl_env::get(array, var_)) return false;
683       if (!array.is_list()) return false;  
684       ok_ = true;
685       ret.set_type(array.element_type());
686       return true;
687     }
688   case MDL_RVAL_EXPR:
689     {
690       mdl_var left_val(false), right_val(false);
691       if (!left_ || !right_) return false;
692       if (!left_->apply(left_val)) return false;
693       if (!right_->apply(right_val)) return false;
694       ok_ =  do_operation(ret, left_val, right_val, arg_);
695       return ok_;
696     }
697   case MDL_RVAL_FUNC:
698     if (!args_) return false;
699     else {  // DO NOT DEFINE VARIABLES ACROSS LABEL JUMPS
700     unsigned size = args_->size();
701
702     if (var_ == "lookupFunction") {
703       if (size != 1) return false;
704       mdl_var arg1(false);
705       if (!(*args_)[0]->apply(arg1)) return false;
706       if (arg1.type() != MDL_T_STRING) return false;
707       arg_ = 0;
708       ret.set_type(MDL_T_PROCEDURE);
709       ok_ = true;
710     } else if (var_ == "lookupModule") {
711       if (size != 1) return false;
712       mdl_var arg1(false);
713       if (!(*args_)[0]->apply(arg1)) return false;
714       if (arg1.type() != MDL_T_STRING) return false;
715       arg_ = 1;
716       ret.set_type(MDL_T_MODULE);
717       ok_ = true;
718     } else if (var_ == "libraryTag") {
719       if (size != 1) return false;
720       mdl_var arg1(false);
721       if (!(*args_)[0]->apply(arg1)) return false;
722       if (arg1.type() != MDL_T_INT) return false;
723       arg_ = 2;
724       int res = 1;
725       ok_ = ret.set(res);
726     } else
727       return false;
728     return ok_;
729     }
730   case MDL_RVAL_DEREF:
731     if (!fields_.size()) {
732       do_type_walk_ = false;
733       ok_ = mdl_env::get(ret, var_);
734       return ok_;
735     } else {
736       // TODO -- build type_walk here
737       do_type_walk_ = true;
738       mdl_var temp(false);
739       if (!mdl_env::get(temp, var_)) return false;
740
741       vector<mdl_type_desc> found;
742       unsigned v_index = 0, v_max = fields_.size();
743       unsigned current_type = temp.type();
744       if (current_type == MDL_T_PROCEDURE_NAME)
745         current_type = MDL_T_PROCEDURE;
746
747       while (v_index < v_max) {
748         if (!mdl_data::fields.defines(current_type)) return false;
749         found = mdl_data::fields[current_type];
750         string next_field = fields_[v_index];
751         bool type_found=false;
752         unsigned size = found.size();
753         for (unsigned u=0; u<size; u++) 
754           if (found[u].name == next_field) {
755             type_found = true;
756             type_walk += current_type;
757             type_walk += u;
758             current_type = found[u].type;
759             break;
760           }
761         if (!type_found) return false; 
762         v_index++;
763       }
764       ok_ = true;
765       ret.set_type(current_type);
766       return ok_;
767     }
768   default:
769     return false;
770   }
771   return false;
772 }
773
774 T_dyninstRPC::mdl_if_stmt::mdl_if_stmt(T_dyninstRPC::mdl_expr *expr, T_dyninstRPC::mdl_stmt *body) : expr_(expr), body_(body) { }
775 T_dyninstRPC::mdl_if_stmt::mdl_if_stmt() { }
776 T_dyninstRPC::mdl_if_stmt::~mdl_if_stmt() {
777   delete expr_; delete body_;
778 }
779
780 bool T_dyninstRPC::mdl_if_stmt::apply(metricDefinitionNode * ,
781                                       vector<dataReqNode*>& flags) {
782   mdl_var res(false); int iv;
783   if (!expr_->apply(res))
784     return false;
785   switch (res.type()) {
786   case MDL_T_INT:
787     if (!res.get(iv))
788       return false;
789     iv = 1;
790     if (!iv)
791       return true;
792     break;
793   default:
794     return false;
795   }
796   bool ret = body_->apply(NULL, flags);
797   return ret;
798 }
799
800 T_dyninstRPC::mdl_seq_stmt::mdl_seq_stmt(vector<T_dyninstRPC::mdl_stmt*> *stmts) : stmts_(stmts) { }
801 T_dyninstRPC::mdl_seq_stmt::mdl_seq_stmt() { }
802 T_dyninstRPC::mdl_seq_stmt::~mdl_seq_stmt() {
803   if (stmts_) {
804     unsigned size = stmts_->size();
805     for (unsigned u=0; u<size; u++)
806       delete (*stmts_)[u];
807     delete stmts_;
808   }
809 }
810  
811 bool T_dyninstRPC::mdl_seq_stmt::apply(metricDefinitionNode * ,
812                                        vector<dataReqNode*>& flags) {
813   if (!stmts_)
814     return true;
815   unsigned size = stmts_->size();
816   for (unsigned index=0; index<size; index++)
817     if (!(*stmts_)[index]->apply(NULL, flags))
818       return false;
819   return true;
820 }
821
822 T_dyninstRPC::mdl_instr_stmt::mdl_instr_stmt(unsigned pos, T_dyninstRPC::mdl_expr *expr,
823                                       vector<T_dyninstRPC::mdl_icode*> *reqs,
824                                       unsigned where, bool constrained) 
825 : position_(pos), point_expr_(expr), icode_reqs_(reqs),
826   where_instr_(where), constrained_(constrained) { }
827 T_dyninstRPC::mdl_instr_stmt::mdl_instr_stmt() { }
828 T_dyninstRPC::mdl_instr_stmt::~mdl_instr_stmt() {
829   delete point_expr_;
830   if (icode_reqs_) {
831     unsigned size = icode_reqs_->size();
832     for (unsigned u=0; u<size; u++)
833       delete (*icode_reqs_)[u];
834     delete icode_reqs_;
835   }
836 }
837
838 bool T_dyninstRPC::mdl_instr_stmt::apply(metricDefinitionNode * ,
839                                          vector<dataReqNode*>& ) {
840   mdl_var temp(false);
841   if (!icode_reqs_)
842     return false;
843   if (!point_expr_->apply(temp))
844     return false;
845
846   // It is illegal to add postInsn to a function exit point
847   if (temp.type() == MDL_T_POINT_RETURN) {
848     if (where_instr_ == MDL_POST_INSN) {
849       cout << "MDL error: you can't insert postInsn at a procedure exit point." << endl;
850       return false;
851     }
852     temp.set_type(MDL_T_POINT);
853   }
854
855   if (temp.type() != MDL_T_POINT)
856     return false;
857   instPoint *p;
858   if (!temp.get(p))
859     return false;
860   unsigned size = icode_reqs_->size();
861
862   switch (position_) {
863   case MDL_PREPEND:
864   case MDL_APPEND:
865     break;
866   default:
867     return false;
868   }
869
870   switch (where_instr_) {
871   case MDL_PRE_INSN:
872   case MDL_POST_INSN:
873     break;
874   default:
875     return false;
876   }
877
878   AstNode *an=NULL;
879   for (unsigned u=0; u<size; u++)
880     if (!(*icode_reqs_)[u]->apply(an, u > 0)) // an initialized if u > 0
881       return false;
882   return true;
883 }
884
885 bool mdl_init() {
886   static bool init_done = false;
887   if (init_done) return true;
888
889   vector<mdl_type_desc> kids;
890   mdl_type_desc self, kid;
891   mdl_focus_element fe;
892
893   self.name = "SyncObject"; self.type = 0; self.end_allowed = false; 
894   kid.name = "Message"; kid.type = MDL_T_INT; kid.end_allowed = true; kids += kid;
895   kid.name = "Barrier"; kid.type = MDL_T_INT; kid.end_allowed = true; kids += kid;
896   kid.name = "Semaphore"; kid.type = MDL_T_INT; kid.end_allowed = true; kids += kid;
897   kid.name = "SpinLock"; kid.type = MDL_T_INT; kid.end_allowed = true; kids += kid;
898   fe.self = self; fe.kids = kids;
899   mdl_data::foci += fe;
900   kids.resize(0);
901
902 //  self.name = "Procedure"; self.type = MDL_T_STRING; self.end_allowed = true;
903   self.name = "Code"; self.type = MDL_T_STRING; self.end_allowed = true;
904   kid.name = "Module"; kid.type = MDL_T_STRING; self.end_allowed = true; kids += kids;
905   fe.self = self; fe.kids = kids;
906   mdl_data::foci += fe;
907   kids.resize(0);
908
909   self.name = "Process"; self.type = MDL_T_STRING; self.end_allowed = true;
910   fe.self = self; fe.kids.resize(0);
911   mdl_data::foci += fe;
912
913   self.name = "Machine"; self.type = MDL_T_STRING; self.end_allowed = true;
914   fe.self = self; fe.kids.resize(0);
915   mdl_data::foci += fe;
916
917   self.name = "Memory"; self.type = MDL_T_STRING; self.end_allowed = true;
918   fe.self = self; fe.kids.resize(0);
919   mdl_data::foci += fe;
920
921   mdl_env::push();
922   // mdl_env::add(string("$procedures"), false, MDL_T_LIST_PROCEDURE);
923   // mdl_env::add(string("$modules"), false, MDL_T_LIST_MODULE);
924   // mdl_env::add(string("$start"), false, MDL_T_PROCEDURE);
925   // mdl_env::add(string("$exit"), false, MDL_T_PROCEDURE);
926   // mdl_env::add(string("$machine"), false, MDL_T_STRING);
927
928   string s = "$procedures";
929   mdl_env::add(s, false, MDL_T_LIST_PROCEDURE);
930   s = "$modules";
931   mdl_env::add(s, false, MDL_T_LIST_MODULE);
932   s = "$start";
933   mdl_env::add(s, false, MDL_T_PROCEDURE);
934   s = "$exit";
935   mdl_env::add(s, false, MDL_T_PROCEDURE);
936   s = "$machine";
937   mdl_env::add(s, false, MDL_T_STRING);
938
939
940   /* Are these entered by hand at the new scope ? */
941   /* $constraint, $arg, $return */
942
943   vector<mdl_type_desc> field_list;
944   mdl_type_desc desc;
945   desc.name = "name"; desc.type = MDL_T_STRING; field_list += desc;
946   desc.name = "calls"; desc.type = MDL_T_LIST_POINT; field_list += desc;
947   desc.name = "entry"; desc.type = MDL_T_POINT; field_list += desc;
948   desc.name = "return"; desc.type = MDL_T_POINT_RETURN; field_list += desc;
949 //  desc.name = "tag"; desc.type = MDL_T_INT; field_list += desc;
950   mdl_data::fields[MDL_T_PROCEDURE] = field_list;
951   field_list.resize(0);
952
953   desc.name = "name"; desc.type = MDL_T_STRING; field_list += desc;
954   desc.name = "funcs"; desc.type = MDL_T_LIST_PROCEDURE; field_list += desc;
955   mdl_data::fields[MDL_T_MODULE] = field_list;
956   field_list.resize(0);
957
958   desc.name = "upper"; desc.type = MDL_T_INT; field_list += desc;
959   desc.name = "lower"; desc.type = MDL_T_INT; field_list += desc;
960   mdl_data::fields[MDL_T_VARIABLE] = field_list;
961   field_list.resize(0);
962
963   field_list.resize(0);
964
965   return true;
966 }
967
968 // 970930 - changed mdl ehanged code exclusion to Code/module or 
969 //  Code/module/func instead of  module/func or module.
970 // check that exclude_node strings have form "module" or "module/func" only
971 bool mdl_check_node_constraints_OLD() {
972
973     for(u_int i=0; i < mdl_data::lib_constraints.size(); i++) {
974         char *temp = P_strdup(mdl_data::lib_constraints[i].string_of()); 
975         char *where = 0;
976         bool bad_string = false;
977         if(temp && (where = P_strchr(temp,'/'))) {
978             char *where2=0;
979             if(where == temp) { 
980                 bad_string = true; // first character is '/' 
981             }
982             else if((where2=P_strrchr(temp,'/')) && where2 != where ){ 
983                 bad_string = true; // there is more than one '/' in the string
984             }
985             else if (temp[mdl_data::lib_constraints[i].length()-1] == '/'){
986                 bad_string = true; // last character is '/' 
987             }
988         }
989         if(temp) delete temp;
990         if(bad_string) {
991             cout << "parse error: exclude_node " <<
992                 mdl_data::lib_constraints[i].string_of() << endl;
993             cout << "should be: `exclude_node \"module/function\";'  or `exclude_node \"module\";'" << endl;
994             return false;
995         }
996     }
997     return true;
998 }
999
1000 // 970930 - changed mdl ehanged code exclusion to /Code/module or 
1001 //  /Code/module/func instead of  module/func or module.
1002 //  In addition, modified mdl_data::lib_constraints to by
1003 //  stripping off the leading /Code/ from each entry.  Thus,
1004 //  after returning (with val == true) mdl_data::lib_constraints
1005 //  should have entries of the old form: "module", or "module/func"....
1006 // check that exclude_node strings have form "module" or "module/func" only
1007 bool mdl_check_node_constraints() {
1008     unsigned int i;
1009     // locations of first, second, and 3rd "/" characters....
1010     char *temp, *first_slash, *second_slash, *third_slash, *fourth_slash;
1011     string modified_constraint;
1012     bool bad_string;
1013
1014     first_slash = second_slash = third_slash = fourth_slash = NULL;
1015
1016     // temp vector to hold lib constraints with leading 
1017     //  "Code/" stripped off....
1018     vector<string> modified_lib_constraints;
1019
1020     for(i=0;i<mdl_data::lib_constraints.size(); i++) {
1021         first_slash = second_slash = third_slash = NULL;
1022
1023         bad_string = 0;
1024         // get copy of string char *data for strchr....
1025         temp = P_strdup(mdl_data::lib_constraints[i].string_of());
1026         // Doh!!!!  Changed exclude directive to have form /Code,
1027         //  instead of Code/, so strip off leading '/'
1028         first_slash = P_strchr(temp, RH_SEPERATOR);
1029         if (first_slash != temp) {
1030             bad_string = 1;
1031             first_slash = NULL;
1032         } 
1033         // Now that the leading "/" is stripped off, 
1034         // stript everything before new first slash off of constraint....
1035         // This should place constraint in form which system previously
1036         // expected....
1037         if (first_slash != NULL) {
1038             second_slash = P_strchr(&first_slash[1], RH_SEPERATOR);
1039         }
1040         if (second_slash != NULL) {
1041             modified_constraint = string(&second_slash[1]);
1042             third_slash = P_strchr(&second_slash[1], RH_SEPERATOR);
1043         }
1044         if (third_slash != NULL) {
1045             fourth_slash = P_strchr(&third_slash[1], RH_SEPERATOR);
1046         }
1047         // excluded item should have at least 2 "/", e.g.
1048         //  "/Code/module", or "/Code/module/func"....
1049         if (first_slash == NULL || second_slash == NULL) {
1050             bad_string = 1; 
1051             cerr << "exclude syntax : could not find 2 seperators in resource hierarchy path" << endl;
1052         }
1053         // and at most most 2....
1054         if (fourth_slash != NULL) {
1055             bad_string = 1;
1056             cerr << "exclude syntax : found too many seperators in resource hierarchy path" << endl;
1057         }
1058         if (bad_string != 1) {
1059             // the substring between the first and second slash 
1060             //  should be "Code"
1061             if (strncmp(CODE_RH_NAME, &first_slash[1], second_slash - \
1062                     first_slash - 1) != 0) {
1063               cerr << "exclude syntax : top level resource hierarchy path must be " << CODE_RH_NAME << endl;;
1064                 bad_string = 1;
1065             }
1066         }
1067         // dont forget to free up temp....
1068         if (temp != NULL) delete []temp;
1069         
1070         if (bad_string) {
1071             cout << "exclude syntax error : " << mdl_data::lib_constraints[i].string_of() << " is not of expected form : /Code/module/function, or /Code/module" << endl;
1072             return false;
1073         } 
1074         
1075         modified_lib_constraints += modified_constraint;
1076     }
1077
1078     mdl_data::lib_constraints = modified_lib_constraints;
1079     return true;
1080 }
1081
1082 // TODO -- if this fails, all metrics are unusable ?
1083 bool mdl_apply() {
1084   unsigned size = mdl_data::stmts.size();
1085
1086   vector<dataReqNode*> flags;
1087   for (unsigned u=0; u<size; u++)
1088     if (!mdl_data::stmts[u]->apply(NULL, flags))
1089       return false;
1090
1091   // TODO -- use a proper vector
1092   vector< vector<string> >vs;
1093   string empty;
1094   vector<process*> emptyP;
1095
1096   vector<T_dyninstRPC::mdl_constraint*> ok_cons;
1097   size = mdl_data::all_constraints.size();
1098   for (unsigned u1=0; u1<size; u1++) {
1099     dataReqNode *drn = NULL;
1100     vector<string> res;
1101     if (mdl_data::all_constraints[u1]->apply(NULL, drn, res, NULL, false)) {
1102       ok_cons += mdl_data::all_constraints[u1];
1103       // cout << "constraint defined: " << mdl_data::all_constraints[u1]->id_ << endl;
1104     } else {
1105       cout << "Error in constraint '" << mdl_data::all_constraints[u1]->id_ << 
1106            "'. Constraint deleted." << endl;
1107       delete mdl_data::all_constraints[u1];
1108     }
1109   }
1110   mdl_data::all_constraints = ok_cons;
1111
1112   vector<T_dyninstRPC::mdl_metric*> ok_mets;
1113   size = mdl_data::all_metrics.size();
1114   for (unsigned u2=0; u2<size; u2++) {
1115     if (mdl_data::all_metrics[u2]->apply(vs, empty, emptyP, false, false) == (metricDefinitionNode*)1) {
1116       ok_mets += mdl_data::all_metrics[u2];
1117       // cout << "metric defined: " << mdl_data::all_metrics[u2]->id_ << endl;
1118     } else {
1119       cout << "Error in metric '" << mdl_data::all_metrics[u2]->id_ << 
1120            "'. Metric deleted." << endl;
1121       delete mdl_data::all_metrics[u2];
1122     }
1123   }
1124   mdl_data::all_metrics = ok_mets;
1125   
1126   return true;
1127 }
1128
1129 bool mdl_send(dynRPCUser *remote) {
1130   remote->send_stmts(&mdl_data::stmts);
1131   remote->send_constraints(&mdl_data::all_constraints);
1132   remote->send_metrics(&mdl_data::all_metrics);
1133   if(mdl_data::lib_constraints.size()){
1134       remote->send_libs(&mdl_data::lib_constraints);
1135   }
1136   else {
1137       remote->send_no_libs();
1138   }
1139
1140 #ifdef notdef
1141   unsigned size = mdl_data::all_metrics.size(), index;
1142   for (index=0; index<size; index++) {
1143     cout << *(mdl_data::all_metrics[index]) << endl;
1144   }
1145   size = mdl_data::all_constraints.size();
1146   for (index=0; index<size; index++) {
1147     cout << *(mdl_data::all_constraints[index]) << endl;
1148   }
1149 #endif
1150
1151   return true;
1152 }
1153
1154
1155 bool mdl_get_lib_constraints(vector<string> &lc){
1156     for(u_int i=0; i < mdl_data::lib_constraints.size(); i++){
1157         lc += mdl_data::lib_constraints[i];
1158     }
1159     return (lc.size()>0);
1160 }
1161
1162 void mdl_destroy() {
1163   unsigned size = mdl_data::all_constraints.size();
1164   for (unsigned u=0; u<size; u++)
1165     delete (mdl_data::all_constraints[u]);
1166   mdl_data::all_constraints.resize(0);
1167   
1168   size = mdl_data::all_metrics.size();
1169   for (unsigned u1=0; u1<size; u1++)
1170     delete (mdl_data::all_metrics[u1]);
1171   mdl_data::all_metrics.resize(0);
1172
1173   size = mdl_data::stmts.size();
1174   for (unsigned u2=0; u2<size; u2++)
1175     delete mdl_data::stmts[u2];
1176 }
1177
1178 static bool do_operation(mdl_var& ret, mdl_var& left_val, mdl_var& right_val, unsigned bin_op) {
1179
1180   switch (bin_op) {
1181   case MDL_PLUS:
1182   case MDL_MINUS:
1183   case MDL_DIV:
1184   case MDL_MULT:
1185     if ((left_val.type() == MDL_T_INT) && (right_val.type() == MDL_T_INT)) {
1186       int v1, v2;
1187       if (!left_val.get(v1)) return false;
1188       if (!right_val.get(v2)) return false;
1189       switch (bin_op) {
1190       case MDL_PLUS: return (ret.set(v1+v2));
1191       case MDL_MINUS: return (ret.set(v1-v2));
1192       case MDL_DIV: return (ret.set(v1/v2));
1193       case MDL_MULT: return (ret.set(v1*v2));
1194       }
1195     } else if (((left_val.type() == MDL_T_INT) || (left_val.type() == MDL_T_FLOAT)) &&
1196                ((right_val.type() == MDL_T_INT) || (right_val.type() == MDL_T_FLOAT))) {
1197       float v1, v2;
1198       if (left_val.type() == MDL_T_INT) {
1199         int i1; if (!left_val.get(i1)) return false; v1 = i1;
1200       } else {
1201         if (!left_val.get(v1)) return false;
1202       }
1203       if (right_val.type() == MDL_T_INT) {
1204         int i1; if (!right_val.get(i1)) return false; v2 = i1;
1205       } else {
1206         if (!right_val.get(v2)) return false;
1207       }
1208       switch (bin_op) {
1209       case MDL_PLUS: return (ret.set(v1+v2));
1210       case MDL_MINUS: return (ret.set(v1-v2));
1211       case MDL_DIV: return (ret.set(v1/v2));
1212       case MDL_MULT: return (ret.set(v1*v2));
1213       }
1214     } else
1215       return false;
1216   case MDL_LT:
1217   case MDL_GT:
1218   case MDL_LE:
1219   case MDL_GE:
1220   case MDL_EQ:
1221   case MDL_NE:
1222     if ((left_val.type() == MDL_T_STRING) && (right_val.type() == MDL_T_STRING)) {
1223       return ret.set(1); 
1224     }
1225     if ((left_val.type() == MDL_T_INT) && (right_val.type() == MDL_T_INT)) {
1226       int v1, v2;
1227       if (!left_val.get(v1)) return false;
1228       if (!right_val.get(v2)) return false;
1229       switch (bin_op) {
1230       case MDL_LT: return (ret.set(v1 < v2));
1231       case MDL_GT: return (ret.set(v1 > v2));
1232       case MDL_LE: return (ret.set(v1 <= v2));
1233       case MDL_GE: return (ret.set(v1 >= v2));
1234       case MDL_EQ: return (ret.set(v1 == v2));
1235       case MDL_NE: return (ret.set(v1 != v2));
1236       }
1237     } else if (((left_val.type() == MDL_T_INT) || (left_val.type() == MDL_T_FLOAT)) &&
1238                ((right_val.type() == MDL_T_INT) || (right_val.type() == MDL_T_FLOAT))) {
1239       float v1, v2;
1240       if (left_val.type() == MDL_T_INT) {
1241         int i1; if (!left_val.get(i1)) return false; v1 = i1;
1242       } else {
1243         if (!left_val.get(v1)) return false;
1244       }
1245       if (right_val.type() == MDL_T_INT) {
1246         int i1; if (!right_val.get(i1)) return false; v2 = i1;
1247       } else {
1248         if (!right_val.get(v2)) return false;
1249       }
1250       switch (bin_op) {
1251       case MDL_LT: return (ret.set(v1 < v2));
1252       case MDL_GT: return (ret.set(v1 > v2));
1253       case MDL_LE: return (ret.set(v1 <= v2));
1254       case MDL_GE: return (ret.set(v1 >= v2));
1255       case MDL_EQ: return (ret.set(v1 == v2));
1256       case MDL_NE: return (ret.set(v1 != v2));
1257       }
1258     } else
1259       return false;
1260   case MDL_AND:
1261   case MDL_OR:
1262     if ((left_val.type() == MDL_T_INT) && (right_val.type() == MDL_T_INT)) {
1263       int v1, v2;
1264       if (!left_val.get(v1)) return false;
1265       if (!right_val.get(v2)) return false;
1266       switch (bin_op) {
1267       case MDL_AND: return (ret.set(v1 && v2));
1268       case MDL_OR: return (ret.set(v1 || v2));
1269       }
1270     } else
1271       return false;
1272   default:
1273       return false;
1274   }
1275   return false;
1276 }
1277
1278 bool T_dyninstRPC::mdl_list_stmt::mk_list(vector<string> &) {}
1279 bool T_dyninstRPC::mdl_for_stmt::mk_list(vector<string> &) {}
1280 bool T_dyninstRPC::mdl_if_stmt::mk_list(vector<string> &) {}
1281 bool T_dyninstRPC::mdl_seq_stmt::mk_list(vector<string> &) {}
1282 bool T_dyninstRPC::mdl_instr_stmt::mk_list(vector<string> &) {}
1283 bool T_dyninstRPC::mdl_constraint::mk_list(vector<string> &) {}
1284 bool T_dyninstRPC::mdl_v_expr::mk_list(vector<string> &) {}