Changed generated code so that it compiles with Visual C++
[dyninst.git] / igen / src / main.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 #include "parse.h"
43 #include <iostream.h>
44 #include <stdio.h>
45
46 bool Options::dont_gen_handle_err = false;
47 dictionary_hash<string, type_defn*> Options::all_types(string::hash);
48 vector<type_defn*> Options::vec_types;
49 vector<message_layer*> Options::all_ml;
50 vector<Options::stl_data> Options::stl_types;
51 vector<string> Options::forward_decls;
52
53 extern FILE *yyin;
54 extern int yyparse();
55
56 static bool set_ml(const string);
57 static void init_ml();
58 static void open_interface_file(int argc, char *argv[]);
59 static void open_output_files();
60 static void do_opts(int argc, char *argv[]);
61 static void usage();
62 static void init_header_files();
63 static void end_header_files();
64 static void init_types();
65
66 interface_spec *Options::current_interface;
67
68 ifstream Options::input;
69 ofstream Options::dot_h;
70 ofstream Options::dot_c;
71 ofstream Options::clnt_dot_h;
72 ofstream Options::clnt_dot_c;
73 ofstream Options::srvr_dot_h;
74 ofstream Options::temp_dot_c;
75 ofstream Options::srvr_dot_c;
76 string Options::file_base_;
77 string Options::input_file_;
78 bool Options::profile_;
79 unsigned Options::var_count_ = 0;
80 Options::mem_type Options::mem_;
81 message_layer *Options::ml;
82 bool Options::stl_seen = false;
83
84 static void usage() {
85   cerr << "igen " << "[-prof] -xdr | -thread | -pvm [-header | -code]\n";
86   cerr << "      [-ignore | -detect | -handle] [-input <file>] <fileName>\n";
87   cerr << "  CODE OPTIONS\n";
88   cerr << "    -xdr     -->  produce code for sockets/xdr\n";
89   cerr << "    -pvm     -->  produce code for PVM\n";
90   cerr << "    -thread  -->  produce code for threads\n";
91   cerr << "    -sas     -->  produce code for unknown threading systems\n";
92   cerr << "    -mas     -->  produce code for unknown multi-process message passing\n";
93   cerr << "  DATA OPTIONS\n";
94   cerr << "    -input <file> --> file that supplies data for unknown systems\n";
95   cerr << "  MARSHALLING OPTIONS\n";
96   cerr << "     currently unsupported\n";
97   cerr << "    -ignore  -->  don't detect pointers to the same memory\n";
98   cerr << "    -detect  -->  detect (and assert) duplicate pointers\n";
99   cerr << "    -handle  -->  handle duplicate\n";
100   cerr << "  PROFILE OPTIONS\n";
101   cerr << "     currently unsupported\n";
102   cerr << "    -prof    -->  generate profile code\n";
103 }
104
105 static void do_opts(int argc, char *argv[]) {
106   Options::current_interface = NULL;
107
108   for (int i=0; i<argc-1; i++) {
109     if (!strcmp("-pvm", argv[i])) {
110       if (!set_ml("pvm")) {
111         cerr << "Message layer 'pvm' unknown\n";
112         exit(-1);
113       }
114     } else if (!strcmp("-no_err", argv[i])) {
115       Options::dont_gen_handle_err = true;
116     } else if (!strcmp("-xdr", argv[i])) {
117       if (!set_ml("xdr")) {
118         cerr << "Message layer 'xdr' unknown\n";
119         exit(-1);
120       }
121     } else if (!strcmp("-rpc", argv[i])) {
122       if (!set_ml("rpc")) {
123         cerr << "Message layer 'rpc' unknown\n";
124         exit(-1);
125       }
126     } else if (!strcmp("-sas", argv[i])) {
127
128     } else if (!strcmp("-mas", argv[i])) {
129
130     } else if (!strcmp("-prof", argv[i])) {
131       cerr << "-prof is currently unsupported, bye\n"; exit(-1);
132     } else if (!strcmp("-thread", argv[i])) {
133       if (!set_ml("thread")) {
134         cerr << "Message layer 'thread' unknown\n";
135         exit(-1);
136       }
137     } else if (!strcmp("-ignore", argv[i])) {
138       cerr << "-ignore is currently unsupported, bye\n"; exit(-1);
139     } else if (!strcmp("-detect", argv[i])) {
140       cerr << "-detect is currently unsupported, bye\n"; exit(-1);
141     } else if (!strcmp("-handle", argv[i])) {
142       cerr << "-handle is currently unsupported, bye\n"; exit(-1);
143     } else if (!strcmp("-input", argv[i])) {
144       if (!argv[i+1]) {
145         cerr << "-input specified with no filename, goodbye!\n";
146         exit(-1);
147       }
148       Options::set_input_file(argv[i+1]);
149     }
150   }
151
152   if (Options::ml->med() == message_layer::Med_none) {
153     cerr << "No message layer defined\n";
154     usage();
155     exit(-1);
156   }
157
158   char *buffer = strdup(argv[argc-1]);
159   char *temp = strrchr(buffer, '/');
160   if (temp)
161     temp++;
162   else
163     temp = buffer;
164
165   char *temp2 = strstr(temp, ".I");
166   if (!temp2) {
167     cerr << "The file " << argv[argc-1] << " must end with the suffix '.I' \n";
168     usage();
169     exit(-1);
170   }
171   *(temp2) = '\0';
172   Options::set_file_base(temp);
173   delete [] buffer;
174   
175   if ((Options::input_file()).length()) {
176     Options::input.open((Options::input_file()).string_of(), ios::in);
177     if (!Options::input.good()) {
178       cerr << "Could not open " << Options::input_file() << " for input, goodbye\n";
179       usage();
180       exit(-1);
181     }
182   }
183 }
184
185 static void open_interface_file(int argc, char *argv[]) {
186
187   if (argc < 2) {
188     cerr << "Not enough arguments\n";
189     usage();
190     exit(-1);
191   }
192
193   if (!(yyin = fopen(argv[argc-1], "r"))) {
194     cerr << "Unable to open " << argv[argc-1] << endl;
195     usage();
196     exit(-1);
197   }
198 }
199
200 static void open_output_files() {
201   string base(Options::file_base() + "." + Options::ml->name() + ".");
202   string cpp_base(Options::file_base() + "_" + Options::ml->name() + "_");
203
204   string dump_to = base + "temp.C";
205   Options::temp_dot_c.open(dump_to.string_of(), ios::out);
206   if (!Options::temp_dot_c.good()) {
207     cerr << "Could not open " << dump_to << " for output\n";
208     exit(-1);
209   }
210
211   dump_to = base + "h";
212   Options::dot_h.open(dump_to.string_of(), ios::out);
213   if (!Options::dot_h.good()) {
214     cerr << "Could not open " << dump_to << " for output\n";
215     exit(-1);
216   }
217
218   dump_to = base + "C";
219   Options::dot_c.open(dump_to.string_of(), ios::out);
220   if (!Options::dot_c.good()) {
221     cerr << "Could not open " << dump_to << " for output\n";
222     exit(-1);
223   }
224
225   dump_to = base + "SRVR.h";
226   Options::srvr_dot_h.open(dump_to.string_of(), ios::out);
227   if (!Options::srvr_dot_h.good()) {
228     cerr << "Could not open " << dump_to << " for output\n";
229     exit(-1);
230   }
231
232   dump_to = base + "SRVR.C";
233   Options::srvr_dot_c.open(dump_to.string_of(), ios::out);
234   if (!Options::srvr_dot_c.good()) {
235     cerr << "Could not open " << dump_to << " for output\n";
236     exit(-1);
237   }
238
239   dump_to = base + "CLNT.C";
240   Options::clnt_dot_c.open(dump_to.string_of(), ios::out);
241   if (!Options::clnt_dot_c.good()) {
242     cerr << "Could not open " << dump_to << " for output\n";
243     exit(-1);
244   }
245
246   dump_to = base + "CLNT.h";
247   Options::clnt_dot_h.open(dump_to.string_of(), ios::out);
248   if (!Options::clnt_dot_h.good()) {
249     cerr << "Could not open " << dump_to << " for output\n";
250     exit(-1);
251   }
252 }
253
254 static void init_header_files() {
255   string base(Options::file_base() + "." + Options::ml->name() + ".");
256   string cpp_base(Options::file_base() + "_" + Options::ml->name() + "_");
257
258   Options::temp_dot_c << "#pragma implementation \"Vector.h\"\n";
259   Options::temp_dot_c << "#include \"util/h/Vector.h\"\n";
260   Options::temp_dot_c << "#pragma implementation \"Queue.h\"\n";
261   Options::temp_dot_c << "#include \"util/h/Queue.h\"\n";
262   Options::temp_dot_c << "#pragma implementation \"" << base << "h\"\n";
263   Options::temp_dot_c << "#include \"" << base << "h\"\n";
264   Options::temp_dot_c << "#include \"util/h/String.h\"\n";
265 /* trace data streams */
266   Options::temp_dot_c << "#include \"util/h/ByteArray.h\"\n";
267
268   Options::dot_h << "#ifndef " << cpp_base << "BASE_H\n";
269   Options::dot_h << "#define " << cpp_base << "BASE_H\n";
270
271   Options::dot_h << "#include \"util/h/rpcUtil.h\"\n";
272   Options::dot_h << Options::ml->includes() << endl;
273
274   Options::dot_h << "#ifdef IGEN_ERR_ASSERT_ON\n";
275   Options::dot_h << "#ifndef IGEN_ERR_ASSERT\n";
276   Options::dot_h << "#define IGEN_ERR_ASSERT assert(0)\n";
277   Options::dot_h << "#endif\n";
278   Options::dot_h << "#else\n";
279   Options::dot_h << "#define IGEN_ERR_ASSERT\n";
280   Options::dot_h << "#endif\n\n";
281
282   Options::dot_h << "\n // Errors that can occur internal to igen\n";
283   Options::dot_h << "#ifndef _IGEN_ERR_DEF\n";
284   Options::dot_h << "#define _IGEN_ERR_DEF\n";
285   Options::dot_h << "typedef enum e_IGEN_ERR {\n";
286   Options::dot_h << "                       igen_no_err=0,\n";
287   Options::dot_h << "                       igen_encode_err,\n";
288   Options::dot_h << "                       igen_decode_err,\n";
289   Options::dot_h << "                       igen_send_err,\n";
290   Options::dot_h << "                       igen_read_err,\n";
291   Options::dot_h << "                       igen_request_err,\n";
292   Options::dot_h << "                       igen_call_err,\n";
293   Options::dot_h << "                       igen_proto_err\n";
294   Options::dot_h << "                       }  IGEN_ERR;\n\n";
295   Options::dot_h << "#endif\n";
296
297   Options::dot_c << "#include \"" << base << "h\"\n";
298
299   Options::clnt_dot_h << "#ifndef " << cpp_base << "CLNT_H\n";
300   Options::clnt_dot_h << "#define " << cpp_base << "CLNT_H\n";
301   Options::clnt_dot_h << "#include \"" << base << "h\"\n";
302
303   Options::clnt_dot_h << "#include \"util/h/Queue.h\"\n";
304
305   Options::srvr_dot_h << "#ifndef " << cpp_base << "SRVR_H\n";
306   Options::srvr_dot_h << "#define " << cpp_base << "SRVR_H\n";
307   Options::srvr_dot_h << "#include \"" << base << "h\"\n";
308   Options::srvr_dot_h << "#include \"util/h/Queue.h\"\n";
309
310   Options::clnt_dot_c << "#include \"" << base << "CLNT.h\"\n";
311   Options::srvr_dot_c << "#include \"" << base << "SRVR.h\"\n";
312 }
313
314 static void end_header_files() {
315   Options::dot_h << "\n#endif\n";
316   Options::dot_h << endl;
317
318   Options::clnt_dot_h << "#endif\n" << endl;
319   Options::srvr_dot_h << "#endif\n" << endl;
320 }
321
322 static void close_files() {
323   Options::srvr_dot_h.close();
324   Options::clnt_dot_h.close();
325   Options::dot_c.close();
326   Options::dot_h.close();
327
328   Options::srvr_dot_c.close();
329   Options::clnt_dot_c.close();
330 }
331
332 static void init_types() {
333   Options::stl_data sd;
334   sd.name = "vector"; sd.include_file = "util/h/Vector.h";
335   sd.need_include = false; sd.pragma_name = "Vector.h";
336   Options::stl_types += sd;
337   Options::el_data el;
338   el.name = "string"; el.type = "string"; el.stars = 0;
339   Options::stl_types[0].elements += el;
340
341   Options::add_type("int", false, false, false, "", type_defn::TYPE_SCALAR, false,
342                     true, NULL);
343   Options::add_type("double", false, false, false, "", type_defn::TYPE_SCALAR, false,
344                     true, NULL);
345   Options::add_type("void", false, false, false, "", type_defn::TYPE_SCALAR, false, true,
346                     NULL);
347   Options::add_type("bool", false, false, false, "", type_defn::TYPE_SCALAR, false, true,
348                     NULL, "", "Boolean");
349   Options::add_type("u_int", false, false, false, "", type_defn::TYPE_SCALAR, false, true,
350                     NULL);
351   Options::add_type("float", false, false, false, "", type_defn::TYPE_SCALAR, false, true,
352                     NULL);
353   Options::add_type("u_char", false, false, false, "", type_defn::TYPE_SCALAR, false, true,
354                     NULL);
355   Options::add_type("char", false, false, false, "", type_defn::TYPE_SCALAR, false, true,
356                     NULL);
357   Options::add_type("string", false, false, false, "", type_defn::TYPE_SCALAR, false, true,
358                     NULL, "", "string_pd");
359 /* trace data streams */
360   Options::add_type("byteArray", false, false, false, "", type_defn::TYPE_SCALAR, false, true,
361                     NULL, "", "byteArray_pd");
362 }
363
364 static bool set_ml(const string ml_name) {
365   for (unsigned i=0; i<Options::all_ml.size(); i++) {
366     if (Options::all_ml[i]->name() == ml_name) {
367       Options::ml = Options::all_ml[i];
368       return true;
369     }
370   }
371   return false;
372 }
373
374 static void init_ml() {
375   message_layer * xdr_ml = new message_layer("xdr",
376                                              message_layer::Med_xdr,
377                                              "P_xdr_",
378                                              "bool_t",
379                                              "*",
380                                              "XDR",
381                                              "*",
382                                              message_layer::AS_many,
383                                              "FALSE",
384                                              "TRUE",
385                                              "x_op",
386                                              "XDR_ENCODE",
387                                              "XDR_DECODE", 
388                                              "XDR_FREE",
389                                              "XDRrpc",
390                                              "P_xdrrec_endofrecord(net_obj(), TRUE)",
391                                              true,
392                                              "P_xdrrec_skiprecord(net_obj())",
393                                              "XXX_RECV",
394                                              " ",
395                                              true,
396                                              "setDirEncode()",
397                                              "setDirDecode()",
398                                              true);
399   
400   message_layer * thrd_ml = new message_layer("thread",
401                                               message_layer::Med_thread,
402                                               "P_thread_",
403                                               "int",
404                                               "*",
405                                               "XDR",
406                                               "*",
407                                               message_layer::AS_one,
408                                               "THR_ERR",
409                                               "THR_OKAY",
410                                               "x_op",
411                                               "XX_ENCODE",
412                                               "XX_DECODE", 
413                                               "XX_FREE",
414                                               "THREADrpc",
415                                               "msg_send",
416                                               true,
417                                               "XXX_skip",
418                                               "msg_recv",
419                                       "#include \"thread/h/thread.h\"\n",
420                                               false,
421                                               " ",
422                                               " ",
423                                               false);
424
425
426   message_layer * rpc_ml = new message_layer("rpc",
427                                              message_layer::Med_rpc,
428                                              "P_rpc_",
429                                              "bool",
430                                              "*",
431                                              "RPC",
432                                              "*",
433                                              message_layer::AS_many,
434                                              "false",
435                                              "true",
436                                              "x_op",
437                                              "RPC::ENCODE",
438                                              "RPC::DECODE", 
439                                              "RPC::FREE",
440                                              "RPCrpc",
441                                              "P_xdrrec_endofrecord(net_obj(), TRUE)",
442                                              true,
443                                              "P_xdrrec_skiprecord(net_obj())",
444                                              "XXX_RECV",
445                                              " ",
446                                              true,
447                                              "setDirEncode()",
448                                              "setDirDecode()",
449                                              true);
450
451   /*
452   message_layer pvm_ml("pvm", message_layer::Med_pvm, "pvm_", "bool_t", "*", "XDR", "*",
453                        message_layer::AS_many, "FALSE", "TRUE");
454   message_layer tcp_ml("tcp", message_layer::Med_other, "", "bool_t", "*", "XDR", "*",
455                        message_layer::AS_many, "false", "true");
456                        */
457   Options::all_ml += xdr_ml; Options::all_ml += thrd_ml; Options::all_ml += rpc_ml;
458 }
459
460 int main(int argc, char *argv[]) {
461   init_ml();
462   init_types();
463   do_opts(argc, argv);
464   open_interface_file(argc, argv);
465   open_output_files();
466   init_header_files();
467   yyparse();
468
469   if (!Options::current_interface) {
470     cerr << "no interface defined\n";
471     exit(-1);
472   }
473
474   Options::current_interface->gen_interface();
475   end_header_files();
476   close_files();
477   exit(0);
478 }
479
480 void dump_to_dot_h(const char *msg) {
481   Options::dot_h << msg << endl;
482 }
483
484 string Options::make_ptrs(unsigned count) {
485   static char buffer[100];
486   assert(count < 100);
487
488   buffer[0] = (char)0;
489   for (unsigned i=0; i<count; i++)
490     buffer[i] = '*';
491   buffer[count] = '\0';
492   return buffer;
493 }
494
495 string arg::deref(const bool use_ref) const {
496   if (stars_)
497     return pointers_;
498   else if (is_ref_ && use_ref)
499     return "&";
500   else
501     return "";
502 }
503
504 string arg::type(const bool use_const, const bool local) const {
505   if (use_const)
506     return ((constant_ ? string("const ") : string("")) + type_ + deref(local));
507   else
508     return (type_ + deref(local));
509 }
510
511 string arg::gen_bundler_name() const {
512   string suffix;
513   switch (stars_) {
514   case 0: break;
515   case 1: suffix = "_PTR"; break;
516   default: abort();
517   }
518   return ((Options::all_types[base_type()])->gen_bundler_name() + suffix);
519 }
520
521
522 void arg::gen_bundler(ofstream &out_stream, const string obj_name,
523                       const string data_name) const
524 {
525   out_stream <<
526     (Options::all_types[base_type()])->gen_bundler_call(obj_name,
527                                                         data_name+name_, stars_);
528 }
529
530 arg::arg(const string *type, const unsigned star_count,
531          const bool b, const string *name, const bool is_ref) 
532 : pointers_(Options::make_ptrs(star_count)), type_(*type),
533   constant_(b), stars_(star_count), is_ref_(is_ref) {
534
535   if(is_ref_ && star_count) {
536     cerr << "Cannot use pointers with a reference, good bye\n";
537     exit(0);
538   }
539
540   if (name)
541     name_ = *name;
542   else
543     name_ = Options::gen_name();
544
545   if (!(Options::all_types[type_])->can_point() &&
546       (star_count>1) &&
547       (Options::ml->address_space() == message_layer::AS_many)) {
548     cerr << "Sorry, pointers not handled for this type, goodbye\n";
549     cerr << "Type = " << *type << "  name = " << *name << endl;
550     exit(-1);
551   }
552   if (star_count)
553     (Options::all_types[type_])->set_pointer_used();
554 }
555
556 bool arg::tag_bundle_send(ofstream &out_stream, const string bundle_val,
557                           const string tag_val, const string return_value) const
558 {
559   if (Options::ml->address_space() == message_layer::AS_many)
560     return (tag_bundle_send_many(out_stream, bundle_val,
561                                  tag_val, return_value));
562   else
563     return (tag_bundle_send_one(out_stream, bundle_val,
564                                 tag_val, return_value));
565 }
566
567 bool arg::tag_bundle_send_many(ofstream &out_stream, const string bundle_val,
568                                const string tag_val, const string return_value) const
569 {
570   // set direction encode
571   out_stream << Options::set_dir_encode() << ";\n";
572
573   // bundle individual args
574   out_stream << "if (!" << Options::ml->read_tag("net_obj()", tag_val) << "\n";
575
576   if (type_ != "void") {
577     out_stream << " || !" <<
578       (Options::all_types[type_])->gen_bundler_call("net_obj()",
579                                                     string("&")+bundle_val, stars_)
580         << "\n";
581   }
582   
583   out_stream << ") ";
584   out_stream << Options::error_state("igen_encode_err", return_value);
585
586   // send message
587   out_stream << "if (!" << Options::ml->send_message() << ") ";
588   out_stream << Options::error_state("igen_send_err", return_value);
589
590   return true;
591 }
592
593 bool arg::tag_bundle_send_one(ofstream &, const string,
594                           const string, const string) const 
595 {
596   abort();
597   return false;
598 }
599
600 string type_defn::qual_id() const { return (Options::type_prefix()+unqual_id());}
601
602 bool type_defn::assign_to(const string prefix, const vector<arg*> &alist,
603                           ofstream &out_stream) const
604 {
605   assert (alist.size() == arglist_.size());
606   for (unsigned i=0; i<alist.size(); i++) 
607     out_stream << prefix << arglist_[i]->name() << " = " << alist[i]->name() << ";\n";
608   return true;
609 }
610
611 bool type_defn::is_same_type(vector<arg*> *arglist) const {
612   assert(arglist);
613   if (arglist_.size() != arglist->size())
614     return false;
615
616   for (unsigned i=0; i<arglist_.size(); i++) {
617     if (arglist_[i]->type() != (*arglist)[i]->type())
618       return false;
619   }
620   return true;
621 }
622
623 string type_defn::gen_bundler_name() const {
624   return (prefix_ +
625           Options::ml->bundler_prefix() +
626           bundle_name_);
627 }
628
629 string type_defn::gen_bundler_call(const string obj, const string data,
630                                    const unsigned pointer_count) const
631 {
632   string pointer_suffix;
633   switch (pointer_count) {
634   case 0: pointer_suffix = ""; break;
635   case 1: pointer_suffix = "_PTR"; break;
636   default: assert(0);
637   }
638
639   if (!is_stl())
640     return (gen_bundler_name() + pointer_suffix + "(" + obj + ", " + data + ")");
641   else 
642     return (gen_bundler_name() + pointer_suffix + "(" + obj + ", " + data + ", " +
643             stl_arg_->gen_bundler_name() + ", (" + stl_arg_->type() + "*)NULL)");
644 }
645
646 string type_defn::dump_args(const string data_name, const string sep) const {
647   string ret("");
648
649   if (my_type_ == type_defn::TYPE_SCALAR) {
650     if (name_ != "void")
651       ret = data_name;
652   } else if (is_stl()) {
653     ret = data_name;
654   } else {
655     switch (arglist_.size()) {
656     case 0:
657       break;
658     case 1:
659       ret = data_name;
660       break;
661     default:
662       for (unsigned i=0; i<arglist_.size(); i++) {
663         ret += string(data_name + sep + arglist_[i]->name());
664         if (i < (arglist_.size() - 1))
665           ret += string(", ");
666       }
667       break;
668     }
669   }
670   return ret;
671 }
672
673 type_defn::type_defn(string stl_name, string element_name, const unsigned ct,
674                      const bool in_lib)
675 : my_type_(type_defn::TYPE_COMPLEX), 
676   in_lib_(in_lib), is_stl_(true),
677   pointer_used_(false), can_point_(true), is_class_(false), is_derived_(false) 
678 {
679   string ptrs = Options::make_ptrs(ct);
680   string waste="dummy";
681   name_ = stl_name + "<" + element_name + ptrs + ">";
682   stl_arg_ = new arg(&element_name, ct, false, &waste, false);
683   if (Options::all_types.defines(name_)) {
684     cerr << name_ << " is already defined\n";
685     exit(-1);
686   }
687   prefix_ = Options::type_class() + "_";
688   unqual_name_ = name_;
689   bundle_name_ = "stl";
690 }
691
692 static string process_ignore(const string txt) {
693   if (txt.length() < 17) return "";
694   char *buffer = P_strdup(txt.string_of());
695   char *temp = buffer;
696
697   temp[strlen(temp) - 8] = (char) 0;
698   temp += 8;
699   string s = temp;
700   delete buffer;
701   return s;
702 }
703
704 type_defn::type_defn(const string name, const bool is_cl, const bool is_abs,
705                      const bool is_der, const string par, 
706                      const type_type type,
707                      vector<arg*> *arglist, const bool can_point, 
708                      bool in_lib, const string ignore, const string bundle_name)
709 : my_type_(type), bundle_name_(bundle_name), in_lib_(in_lib),
710   is_stl_(false), pointer_used_(false), can_point_(can_point),
711   ignore_(process_ignore(ignore)),
712   is_class_(is_cl), is_abstract_(is_abs), is_derived_(is_der) 
713 {
714   stl_arg_ = NULL;
715   if (Options::all_types.defines(name)) {
716     cerr << name << " is already defined\n";
717     exit(-1);
718   }
719   if (in_lib || Options::ml->AS_one) {
720     name_ = name;
721     prefix_ = "";
722   } else {
723     name_ = Options::type_prefix() + name;
724     prefix_ = Options::type_prefix();
725   }
726   unqual_name_ = name;
727
728   if (!bundle_name_.length())
729     bundle_name_ = unqual_name_;
730   
731   if (arglist) {
732     for (unsigned i=0; i< arglist->size(); i++)
733       arglist_ += (*arglist)[i];
734   }
735   if (is_derived_) {
736     parent_ = Options::type_prefix() + par;
737     if (!Options::all_types.defines(parent_)) {
738       cerr << "Parent " << par << " not defined\n";
739       exit(0);
740     } else {
741       type_defn *p = Options::all_types[parent_];
742       assert(p);
743       p->add_kid(name_);
744     }
745   }
746 }
747
748 void type_defn::add_kid(const string kid_name) { kids_ += kid_name; }
749
750 /* Convert a type name with qualified names to a names with unqualified names.
751    E.g. vector<T_dyninstRPC::mdl_expr*> to vector<mdl_expr*>
752    This is needed to compile the igen output with Visual C++, which
753    does not accept the qualified names (in the example above, it complains
754    that T_dyninstRPC is undefined).
755 */
756 string unqual_type(const string &type) {
757   string ret;
758   const char *t = type.string_of();
759   char *p;
760
761   while (1) {
762     p = strstr(t, Options::type_prefix().string_of());
763     if (!p) {
764       ret += t;
765       return ret;
766     }
767     ret += string(t, p-t);
768     t = p + Options::type_prefix().length();
769   }
770 }
771
772
773 bool type_defn::gen_class(const string, ofstream &out_stream) {
774
775   if (is_class())
776     out_stream << "class "; 
777   else
778     out_stream << "struct ";
779   out_stream << unqual_name();
780   if (is_derived()) 
781     out_stream << " : public " << Options::qual_to_unqual(parent()) << " ";
782   out_stream << "{ \n";
783   if (is_class()) {
784     out_stream << " public: \n ";
785     out_stream << unqual_name() << "();\n";
786   }
787   
788   for (unsigned i=0; i<arglist_.size(); i++) 
789     out_stream << unqual_type(arglist_[i]->type(true)) << " " << arglist_[i]->name() << ";\n";
790
791   if (ignore_.length())
792     out_stream << "\n" << ignore_ << endl;
793
794   if (is_class()) {
795     out_stream << "public:\n";
796     if (has_kids())
797       out_stream << "virtual ";
798     out_stream << Options::ml->bundler_return_type() << " marshall "
799       << "(" << Options::ml->marshall_obj()
800         << " " << Options::ml->marshall_obj_ptr() << " obj);\n";
801     if (has_kids())
802       out_stream << "virtual ";
803     out_stream << "class_ids getId() { return " << unqual_id() << ";}\n";
804   }
805
806   out_stream << "};\n";
807
808   if (!is_class()) 
809     out_stream << "typedef struct " << unqual_name() << " " << unqual_name()
810       << ";\n";
811   return true;
812 }
813
814 bool type_defn::gen_bundler_ptr(const string class_prefix, const string bundler_prefix,
815                                 ofstream &out_c, ofstream &out_h) const 
816 {
817   bool do_it = false;
818   if (pointer_used())
819     do_it = true;
820   else if (is_class()) {
821     const type_defn *curr_defn = this;
822     while (curr_defn->is_derived()) {
823       if (!Options::all_types.defines(curr_defn->parent())) {
824         cerr << "Parent " << curr_defn->parent() << " should be defined\n";
825         assert(0);
826       }
827       curr_defn = Options::all_types[curr_defn->parent()];
828       if (curr_defn->pointer_used()) {
829         do_it = true;
830         break;
831       }
832     }
833   }
834
835   // if (!do_it)
836   // return true;
837
838   if (is_class()) 
839     return (gen_bundler_ptr_class(class_prefix, bundler_prefix, out_c, out_h));
840   else
841     return (gen_bundler_ptr_struct(class_prefix, bundler_prefix, out_c, out_h));
842 }
843
844 bool type_defn::gen_bundler_ptr_struct(const string class_prefix, const string bundler_prefix,
845                                 ofstream &out_c, ofstream &out_h) const 
846 {
847   out_h << "static " << Options::ml->bundler_return_type() << " "
848     << bundler_prefix << unqual_name() << "_PTR" << "(" << Options::ml->marshall_obj()
849       << " " << Options::ml->marshall_obj_ptr() << " obj, "
850         << unqual_name() << Options::ml->marshall_data_ptr() << "*"
851           << " data);\n";
852
853   out_c << Options::ml->bundler_return_type() << " "
854     << class_prefix << bundler_prefix << unqual_name() << "_PTR"
855       << "(" << Options::ml->marshall_obj()
856         << " " << Options::ml->marshall_obj_ptr() << " obj, "
857           << name() << Options::ml->marshall_data_ptr() << "*" << " data) { \n";
858   out_c << "assert(obj);\n";
859   out_c << "assert(" << Options::obj_ptr() << " != " << Options::ml->free_const() << ");\n";
860   out_c << "bool is_null(false);\n";
861   out_c << "switch (" << Options::obj_ptr() << ") {\n";
862   out_c << "case " << Options::ml->pack_const() << ":\n";
863   out_c << "if (!*data) is_null=true;\n";
864   out_c << "if (!" << Options::all_types["bool"]->gen_bundler_call("obj", "&is_null", 0)
865     << ") return " << Options::ml->bundle_fail() << ";\n";
866   out_c << "if (!*data) return " << Options::ml->bundle_ok() << ";\n";
867   out_c << "break;\n";
868   out_c << "case " << Options::ml->unpack_const() << ":\n";
869   out_c << "if (!" << Options::all_types["bool"]->gen_bundler_call("obj", "&is_null", 0)
870     << ") return " << Options::ml->bundle_fail() << ";\n";
871   out_c << "if (is_null) { *data = NULL; return " << Options::ml->bundle_ok() << ";}\n";
872   out_c << "*data = new " << name() << ";\n";
873   out_c << "if (!*data) return " << Options::ml->bundle_fail() << ";\n";
874   out_c << "break;\n";
875   out_c << "default: \n return " << Options::ml->bundle_fail() << ";\n";
876   out_c << "}\n";
877   out_c << "return " << class_prefix << bundler_prefix << unqual_name() << "(obj, *data);\n";
878   out_c << "}\n";
879   return true;
880 }
881
882 bool type_defn::gen_bundler_ptr_class(const string class_prefix, const string bundler_prefix,
883                                 ofstream &out_c, ofstream &out_h) const 
884 {
885   out_h << "static " << Options::ml->bundler_return_type() << " "
886     << bundler_prefix << unqual_name() << "_PTR" << "(" << Options::ml->marshall_obj()
887       << " " << Options::ml->marshall_obj_ptr() << " obj, "
888         << unqual_name() << Options::ml->marshall_data_ptr() << "*" << " data);\n";
889
890   out_c << Options::ml->bundler_return_type() << " "  << class_prefix
891     << bundler_prefix << unqual_name() << "_PTR" << "("
892       << Options::ml->marshall_obj() << " " << Options::ml->marshall_obj_ptr()
893         << " obj, ";
894   out_c << class_prefix << unqual_name() << Options::ml->marshall_data_ptr() << "*" 
895     << " data) {\n";
896   out_c << "assert(obj);\n";
897   out_c << "assert(" << Options::obj_ptr() << " != " << Options::ml->free_const()
898     << ");\n";
899   out_c << "bool is_null = (*data == NULL);\n";
900   out_c << "unsigned tag;\n";
901   out_c << "if (" << Options::obj_ptr() << " == " << Options::ml->pack_const()
902     << ") {\n";
903   out_c << "if (!*data) tag = " << qual_id() << ";\n";
904   out_c << "else tag = (unsigned) (*data)->getId();\n";
905   out_c << "}\n";
906   out_c << "if (!" << Options::all_types["bool"]->gen_bundler_call("obj", 
907                                                                    "&is_null",
908                                                                    0)
909     << ") return " << Options::ml->bundle_fail() << ";\n";
910   out_c << "if (!" << Options::all_types["u_int"]->gen_bundler_call("obj",
911                                                                     "&tag",
912                                                                     0)
913     << ") return " << Options::ml->bundle_fail() << ";\n";
914
915   out_c << "if (" << Options::obj_ptr() << " == " << Options::ml->unpack_const()
916     << ") {\n";
917   out_c << "if (is_null) { *data = NULL; return " << Options::ml->bundle_ok() << ";}\n";
918   out_c << "switch (tag) {\n";
919   if (!is_abstract()) {
920     out_c << "case " << qual_id() << ":\n";
921     out_c << "*data = new " << name() << ";\n";
922     out_c << "break;\n";
923   }
924   
925   recursive_dump_kids(this, out_c);
926
927   out_c << "default: \n return " << Options::ml->bundle_fail() << ";\n";
928   out_c << "};\n";
929   out_c << "if (!*data) return " << Options::ml->bundle_fail() << ";\n";
930   out_c << "} else if (" << Options::obj_ptr() << " == "
931     << Options::ml->pack_const() << ") {\n";
932   out_c << "if (!*data) return " << Options::ml->bundle_ok() << ";\n";
933   out_c << "} else  \n return " << Options::ml->bundle_fail() << ";\n";
934   out_c << "return ((*data)->marshall(obj));\n";
935   out_c << "}\n";
936
937   out_c << Options::ml->bundler_return_type() << " " 
938     << name() << "::"
939       << "marshall("
940         << Options::ml->marshall_obj()
941           << " " << Options::ml->marshall_obj_ptr() << " obj) {\n";
942
943   for (unsigned i=0; i<arglist_.size(); i++) {
944     out_c << " if (!";
945     arglist_[i]->gen_bundler(out_c, "obj", "&");
946     out_c << ")\n";
947     out_c << "return " << Options::ml->bundle_fail() << ";\n";
948   }
949   const type_defn *curr_defn = this;
950   while (curr_defn->is_derived()) {
951     if (!Options::all_types.defines(curr_defn->parent())) {
952       cerr << "Parent " << curr_defn->parent() << " should be defined\n";
953       assert(0);
954     }
955     curr_defn = Options::all_types[curr_defn->parent()];
956     assert(curr_defn);
957     for (unsigned ui=0; ui<curr_defn->arglist_.size(); ui++) {
958       out_c << " if (!";
959       arglist_[ui]->gen_bundler(out_c, "obj", "&");
960       out_c << ")\n";
961       out_c << "return " << Options::ml->bundle_fail() << ";\n";
962     }
963   }
964   out_c << "return " << Options::ml->bundle_ok() << " ;\n";
965   out_c << "}\n";
966   return true;
967 }
968
969 bool type_defn::gen_bundler_body(const string bundler_prefix, const string class_prefix,
970                                  ofstream &out_stream) const
971 {
972   if (is_class()) 
973     return (gen_bundler_body_class(bundler_prefix, class_prefix, out_stream));
974   else
975     return (gen_bundler_body_struct(bundler_prefix, class_prefix, out_stream));
976 }
977                                  
978 bool type_defn::gen_bundler_body_struct(const string bundler_prefix, const string class_prefix,
979                                  ofstream &out_stream) const
980 {
981   gen_bundler_sig(false, class_prefix, bundler_prefix, out_stream);
982   out_stream << "{\n";
983   out_stream << "assert(obj);\n";
984   out_stream << "assert(" << Options::obj_ptr() << " != "
985     << Options::ml->free_const() << ");\n";
986
987   for (unsigned i=0; i<arglist_.size(); i++) {
988     out_stream << " if (!";
989     arglist_[i]->gen_bundler(out_stream, "obj", "&data->");
990     out_stream << ")\n";
991     out_stream << "return " << Options::ml->bundle_fail() << ";\n";
992   }
993   
994   out_stream << "return " << Options::ml->bundle_ok() << " ;\n}\n";
995   return true;
996 }
997
998 bool type_defn::gen_bundler_body_class(const string bundler_prefix, const string class_prefix,
999                                  ofstream &out_stream) const
1000 {
1001   gen_bundler_sig(false, class_prefix, bundler_prefix, out_stream);
1002   out_stream << "{\n";
1003   out_stream << "assert(obj);\n";
1004   out_stream << "assert(" << Options::obj_ptr() << " != "
1005     << Options::ml->free_const() << ");\n";
1006   out_stream << "return (data->marshall(obj));\n";
1007   out_stream << "}\n";
1008   return true;
1009 }
1010
1011 bool type_defn::gen_bundler_sig(const bool &print_extern, const string class_prefix,
1012                                 const string &bundler_prefix,
1013                                 ofstream &out_stream) const
1014 {
1015   if (print_extern) 
1016     out_stream << "static ";
1017
1018   out_stream << Options::ml->bundler_return_type() << " ";
1019
1020   if (!print_extern) 
1021     out_stream << class_prefix;
1022
1023   out_stream << bundler_prefix
1024     << unqual_name() << "(" << Options::ml->marshall_obj() << " "
1025       << Options::ml->marshall_obj_ptr() << " obj, ";
1026
1027   if (!print_extern) 
1028     out_stream << class_prefix;
1029
1030   out_stream << unqual_name() << Options::ml->marshall_data_ptr() << " data)";
1031     
1032   if (print_extern)
1033     out_stream << ";";
1034   out_stream << endl;
1035   return true;
1036 }
1037
1038 void type_defn::dump_type() {
1039   cerr << "Type " << name_ << "  in_lib=" << in_lib_ << endl;
1040   for (unsigned i=0; i<arglist_.size(); i++)
1041     cerr << "   " << arglist_[i]->type() << "    "  << arglist_[i]->name() << endl;
1042 }
1043
1044 string Options::qual_to_unqual(const string type_name) {
1045   assert(Options::all_types.defines(type_name));
1046   type_defn *td = Options::all_types[type_name];
1047   return (td->unqual_name());
1048 }
1049
1050 string Options::set_dir_decode() {
1051   return (Options::ml->set_dir_decode());
1052   //  return (string("setDirDecode()"));
1053 }
1054 string Options::set_dir_encode() {
1055   return (Options::ml->set_dir_encode());
1056   // return (string("setDirEncode()"));
1057 }
1058
1059 string Options::error_state(const string err_name, const string return_value) {
1060   return (string("{\n ") +
1061           "IGEN_ERR_ASSERT;\n " +
1062           "set_err_state(" + err_name + ");\n " +
1063           "handle_error();\n " +
1064           "return " + return_value + ";\n " +
1065           "}\n");
1066 }
1067
1068 string Options::gen_name() {
1069   char number[20];
1070   sprintf(number, "%d", var_count_++);
1071   return (string("var_") + number);
1072 }
1073
1074 string Options::allocate_stl_type(string stl_type, string element_name,
1075                                   const unsigned star_count, const bool in_lib) {
1076   type_defn *ign = new type_defn(stl_type, element_name, star_count, in_lib);
1077   assert(ign);
1078   Options::all_types[ign->name()] = ign;
1079   Options::vec_types += ign;
1080   return (ign->name());
1081 }
1082
1083 string Options::allocate_type(const string name, const bool is_class, const bool is_abstract,
1084                               const bool is_derived, const string parent,
1085                               const type_defn::type_type &typ,
1086                               const bool can_point, const bool &in_lib,
1087                               vector<arg*> *arglist, const string ignore_text,
1088                               const string bundle_name) {
1089   return (Options::add_type(name, is_class, is_abstract, is_derived, parent, typ, can_point,
1090                             in_lib, arglist, ignore_text, bundle_name));
1091 }
1092
1093
1094 string Options::add_type(const string name, const bool is_class, const bool is_abstract,
1095                          const bool is_derived, const string parent,
1096                          const type_defn::type_type &type,
1097                          const bool can_point, const bool in_lib,
1098                          vector<arg*> *arglist, const string ignore_text,
1099                          const string bundler_name) {
1100   type_defn *ign = new type_defn(name, is_class, is_abstract, is_derived, parent, type,
1101                                  arglist, can_point,
1102                                  in_lib, ignore_text, bundler_name);
1103   assert(ign);
1104   Options::all_types[ign->name()] = ign;
1105   Options::vec_types += ign;
1106   return (ign->name());
1107 }
1108                             
1109
1110 message_layer::message_layer(const string nm, const medium md, const string bp,
1111                              const string brt, const string mdp, const string mo,
1112                              const string mop, const AS as, const string bfail,
1113                              const string bok, const string dir_f, const string pack_f,
1114                              const string unpack_f, const string free_f,
1115                              const string rpc_par, const string send_msg,
1116                              const bool r_used, const string skip_msg,
1117                              const string recv_msg, const string incs,
1118                              const bool do_serial, 
1119                              const string enc, const string dec,
1120                              const bool do_skip)
1121 : name_(nm), med_(md), bundler_prefix_(bp), bundler_return_type_(brt),
1122   marshall_data_ptr_(mdp), marshall_obj_(mo), marshall_obj_ptr_(mop), address_space_(as),
1123   bundle_fail_(bfail), bundle_ok_(bok), dir_field_(dir_f), pack_const_(pack_f), 
1124   unpack_const_(unpack_f), free_const_(free_f), rpc_parent_(rpc_par),
1125   send_message_(send_msg), records_used_(r_used), skip_message_(skip_msg),
1126   recv_message_(recv_msg), incs_(incs), serial_(do_serial), 
1127   encode_(enc), decode_(dec), skip_(do_skip)
1128 {
1129   
1130 }
1131
1132 string message_layer::read_tag(const string obj_name, const string tag_s) const {
1133   return(Options::ml->bundler_prefix() + "u_int(" + obj_name + ", (u_int*) &" + tag_s + ")");
1134 }
1135
1136 void Options::dump_types() {
1137   dictionary_hash_iter<string, type_defn*> dhi(Options::all_types);
1138   string s; type_defn *td;
1139   while (dhi.next(s, td)) 
1140     td->dump_type();
1141 }
1142
1143 string remote_func::request_tag(bool unqual) const {
1144   return((unqual ? string("") : Options::type_prefix()) + name() + "_REQ");}
1145
1146 string remote_func::response_tag(bool unqual) const {
1147   return((unqual ? string("") : Options::type_prefix()) + name() + "_RESP");}
1148
1149 remote_func::remote_func(const string name, vector<arg*> *arglist, const call_type &ct,
1150                          const bool &is_v, const arg &return_arg, const bool do_free)
1151 : name_(name), function_type_(ct), is_virtual_(is_v),
1152   call_sig_(arglist, name_), return_arg_(return_arg), do_free_(do_free)
1153 {
1154 }
1155
1156 // If I am generating code for the server, I don't handle async upcalls since
1157 // these are calls that the server makes, not receives
1158 // And the opposite applies for the client
1159 bool remote_func::handle_request(ofstream &out_stream, const bool srvr, bool special) const {
1160   if (is_srvr_call()) {
1161     if (srvr) return false;
1162   } else {
1163     if (!srvr) return false;
1164   }
1165   out_stream << "case " << request_tag() << ":\n";
1166   out_stream << "{\n";
1167   if (call_sig_.type() != "void") {
1168     if (Options::ml->address_space() == message_layer::AS_many) {
1169       out_stream << call_sig_.type() << " message;\n";
1170       out_stream << "if (!" <<
1171         call_sig_.gen_bundler_call("net_obj()", "&message") << ") ";
1172       out_stream << Options::error_state("igen_decode_err",
1173                                          Options::type_prefix() + "error");
1174       if (special)
1175         out_stream << "if (buffer) { *(" << call_sig_.type() << " *)buffer = message; break; }\n";
1176     }
1177   }
1178
1179   if (Options::ml->address_space() == message_layer::AS_one) {
1180     if (special)
1181       out_stream << "if (buffer) { *(" << Options::type_prefix() << "msg_buf *)buffer = KLUDGE_msg_buf; break; }\n";
1182   }
1183
1184   if (return_arg_.base_type() != "void") 
1185     out_stream << return_arg_.type() << " ret = ";
1186   out_stream << name() << "(";
1187
1188   if (Options::ml->address_space() == message_layer::AS_one) {
1189     out_stream << call_sig_.dump_args(string("KLUDGE_msg_buf.")+name()+"_call", ".");
1190   } else {
1191     out_stream << call_sig_.dump_args("message", ".");
1192   }
1193
1194   out_stream << ")" << ";\n";
1195
1196   // reply
1197   if (Options::ml->address_space() == message_layer::AS_many) {
1198     if (!is_async_call()) {
1199       out_stream << "unsigned ret_tag = " << response_tag() << ";\n";
1200       return_arg_.tag_bundle_send(out_stream, "ret", "ret_tag", 
1201                                   Options::type_prefix() + "error");
1202     }
1203   } else {
1204     if (!is_async_call()) {
1205       string size, msg;
1206       out_stream << "val = msg_send(getRequestingThread(), " << response_tag();
1207       if (return_arg_.type() == "void") {
1208         size = ", 0"; msg = ", (void*)NULL";
1209       } else {
1210         size = ", sizeof(ret)"; msg = ", (void*) &ret";
1211       }
1212       out_stream << msg << size << ");\n";
1213     }
1214   }
1215
1216   // only attempt to free the return value, the user should free the call_sig args
1217   // only if there is a return arg
1218   if ((Options::ml->address_space() != message_layer::AS_one) && do_free() &&
1219       (return_arg_.base_type() != "void")) {
1220     out_stream << "delete ret;\n";
1221   }
1222
1223   out_stream << "}\n";
1224   out_stream << "break;\n";
1225   return true;
1226 }
1227
1228 bool remote_func::free_async(ofstream &out_stream, const bool srvr) const {
1229   if (is_srvr_call()) {
1230     if (srvr) return false;
1231   } else {
1232     if (!srvr) return false;
1233   }
1234   if (!is_async_call()) return false;
1235   out_stream << "case " << request_tag() << ":\n";
1236   out_stream << "{\n";
1237   if (call_sig_.type() != "void") {
1238     out_stream << call_sig_.type() << " *message = (" << call_sig_.type() <<
1239       "*)(item->data_ptr);\n";
1240   }
1241
1242   out_stream << name() << "(";
1243   out_stream << call_sig_.dump_args("(*message)", ".");
1244   // out_stream << (Options::all_types[call_sig_.base_type()])->dump_args("(*message)", ".");
1245   out_stream << ");\n";
1246
1247   if (call_sig_.type() != "void") {
1248     out_stream << "assert(item->data_ptr);\n";
1249     out_stream << "delete (" << call_sig_.type() << "*) (item->data_ptr);\n";
1250   }
1251
1252   out_stream << "}\n";
1253
1254   out_stream << "break;\n";
1255   return true;
1256 }
1257
1258 // If I am generating code for the server, I don't handle async upcalls since
1259 // these are calls that the server makes, not receives
1260 // And the opposite applies for the client
1261 bool remote_func::save_async_request(ofstream &out_stream, const bool srvr) const {
1262   if (is_srvr_call()) {
1263     if (srvr) return false;
1264   } else {
1265     if (!srvr) return false;
1266   }
1267   if (!is_async_call()) return false;
1268
1269   out_stream << "case " << request_tag() << ":\n";
1270   out_stream << "{\n";
1271
1272   if (call_sig_.type() != "void") {
1273     out_stream << call_sig_.type() << " *message = new " << call_sig_.type()
1274       << ";\n" << "if (!"
1275         << call_sig_.gen_bundler_call("net_obj()", "message") << ") ";
1276     out_stream << Options::error_state("igen_decode_err", "false");
1277   }
1278   out_stream << Options::type_prefix()
1279     << "buf_struct *buffer = new " << Options::type_prefix() << "buf_struct;\n";
1280   out_stream << "assert(buffer);\n";
1281   out_stream << "buffer->data_type = " << request_tag() << ";\n";
1282
1283   if (call_sig_.type() != "void")
1284     out_stream << "buffer->data_ptr = (void*) message" << ";\n";
1285   else
1286     out_stream << "buffer->data_ptr = NULL;\n";
1287
1288   out_stream << "async_buffer += buffer;\n";
1289   out_stream << "}\n";
1290   out_stream << "break;\n";
1291   return true;
1292 }
1293
1294 bool remote_func::gen_async_struct(ofstream &) const { return true; }
1295
1296 bool remote_func::gen_signature(ofstream &out_stream, const bool &hdr,
1297                                 const bool server) const
1298 {
1299   if (hdr)
1300     if ((server && !is_srvr_call()) ||
1301         (!server && is_srvr_call()))
1302       if (is_virtual())
1303          out_stream << " virtual ";
1304
1305   out_stream << return_arg_.type(true, true) << " ";
1306
1307   if (!hdr)
1308     out_stream << Options::current_interface->gen_class_prefix(is_srvr_call());
1309
1310   out_stream << name() << "(";
1311   call_sig_.gen_sig(out_stream);
1312   out_stream << ")" << (hdr ? ";\n" : "");
1313   return true;
1314 }
1315
1316 bool remote_func::gen_stub(ofstream &out_srvr, ofstream &out_clnt) const 
1317 {
1318   switch (function_type_) {
1319   case async_upcall:
1320     gen_stub_helper(out_srvr, out_clnt, true);
1321     break;
1322   case async_call:
1323   case sync_call:
1324     gen_stub_helper(out_srvr, out_clnt, false);
1325     break;
1326   default:
1327     abort();
1328   }
1329   return true;
1330 }
1331
1332 bool remote_func::gen_stub_helper(ofstream &out_srvr, ofstream &out_clnt,
1333                                   const bool srvr) const 
1334 {
1335   if (Options::ml->address_space() == message_layer::AS_one) 
1336     return (gen_stub_helper_one(out_srvr, out_clnt, srvr));
1337   else
1338     return (gen_stub_helper_many(out_srvr, out_clnt, srvr));
1339             
1340 }
1341
1342 bool remote_func::gen_stub_helper_many(ofstream &out_srvr, ofstream &out_clnt,
1343                                        const bool srvr) const
1344 {
1345   gen_signature((srvr ? out_srvr : out_clnt), false, srvr);
1346   (srvr ? out_srvr : out_clnt) << "{\n";
1347   if (!is_async_call() && !is_void()) 
1348     (srvr ? out_srvr : out_clnt) << return_arg_.type() << " ret_arg;\n";
1349
1350   (srvr ? out_srvr : out_clnt) << "if (get_err_state() != igen_no_err) {\n"
1351     << "IGEN_ERR_ASSERT;\nreturn " << return_value() << ";\n}\n";
1352   
1353   if (srvr) {
1354     out_srvr << "if (!getVersionVerifyDone()) {\n";
1355     out_srvr << "if (!verify_protocol()) ";
1356     out_srvr << Options::error_state("igen_proto_err", return_value());
1357     out_srvr << "\n}\n";
1358   }
1359
1360   (srvr ? out_srvr : out_clnt) << "unsigned tag = " << request_tag() << ";\n";
1361   call_sig_.tag_bundle_send((srvr ? out_srvr : out_clnt), return_value(),
1362                             request_tag());
1363
1364   if (!is_async_call()) {
1365     (srvr?out_srvr:out_clnt) << "if (!awaitResponse(" << response_tag() << ")) "
1366       << Options::error_state("igen_read_err", return_value());
1367
1368     // set direction decode 
1369     if (!is_void()) {
1370     // (srvr?out_srvr:out_clnt) << Options::set_dir_decode() << ";\n";
1371
1372       // decode something
1373       (srvr?out_srvr:out_clnt) << "if(!"
1374         << (Options::all_types[return_arg_.base_type()])->gen_bundler_call("net_obj()",
1375                                                                       "&ret_arg",
1376                                                                       return_arg_.stars())
1377           << ") ";
1378       (srvr?out_srvr:out_clnt) << Options::error_state("igen_decode_err", return_value());
1379     }
1380
1381     (srvr?out_srvr:out_clnt) << "return " << return_value() << ";\n";
1382   }
1383
1384   (srvr ? out_srvr : out_clnt) << "}\n";
1385   return true;
1386 }
1387
1388 bool remote_func::gen_stub_helper_one(ofstream &out_srvr, ofstream &out_clnt,
1389                                       const bool srvr) const
1390 {
1391   gen_signature((srvr ? out_srvr : out_clnt), false, srvr);
1392   (srvr ? out_srvr : out_clnt) << "{\n";
1393   if (!is_async_call() && !is_void()) 
1394     (srvr ? out_srvr : out_clnt) << return_arg_.type() << " ret_arg;\n";
1395
1396   (srvr ? out_srvr : out_clnt) << "if (get_err_state() != igen_no_err) {\n"
1397     << "IGEN_ERR_ASSERT;\nreturn " << return_value() << ";\n}\n";
1398   
1399   call_sig_.tag_bundle_send((srvr ? out_srvr : out_clnt), return_value(),
1400                             request_tag());
1401
1402   if (!is_async_call()) {
1403     if (return_arg_.type() != "void") {
1404       (srvr?out_srvr:out_clnt) << "unsigned len = sizeof(ret_arg);\n";
1405     } else
1406       (srvr?out_srvr:out_clnt) << "unsigned len = 0;\n";
1407
1408     (srvr?out_srvr:out_clnt) << "unsigned tag = " << response_tag() << ";\n";
1409
1410     string rb;
1411     string lb;
1412     if (return_arg_.type() != "void") {
1413       rb = "(void*)&ret_arg, ";
1414       lb = "sizeof(ret_arg)";
1415     } else {
1416       rb = "(void*) NULL, ";
1417       lb = "0";
1418     }
1419
1420     (srvr?out_srvr:out_clnt) << "if (" << Options::ml->recv_message()
1421       << "(&tag, " << rb << "&len) == " << Options::ml->bundle_fail() << ") ";
1422     (srvr?out_srvr:out_clnt) << Options::error_state("igen_read_err", return_value());
1423     
1424     (srvr?out_srvr:out_clnt) << "if (len != " << lb << ") ";
1425     (srvr?out_srvr:out_clnt) << Options::error_state("igen_read_err", return_value());
1426
1427     (srvr?out_srvr:out_clnt) << "if (tag != " << response_tag() << ") ";
1428     (srvr?out_srvr:out_clnt) << Options::error_state("igen_read_err", return_value());
1429
1430     (srvr?out_srvr:out_clnt) << "return " << return_value() << ";\n";
1431   }
1432
1433   (srvr ? out_srvr : out_clnt) << "}\n";
1434   return true;
1435 }
1436
1437 signature::signature(vector<arg*> *alist, const string rf_name) : is_const_(false), stars_(0) {
1438   assert(alist);
1439   for (unsigned i=0; i<alist->size(); i++) 
1440     args += (*alist)[i];
1441
1442   switch (args.size()) {
1443   case 0: type_ = "void"; break;
1444   case 1:
1445     type_ = args[0]->base_type();
1446     stars_ = args[0]->stars();
1447     is_const_ = args[0]->is_const();
1448     break;
1449   default:
1450     type_defn *td; string s;
1451     dictionary_hash_iter<string, type_defn*> tdi(Options::all_types);
1452     bool match = false;
1453     while (!match && tdi.next(s, td))
1454       match = td->is_same_type(alist);
1455     if (match) {
1456       type_ = td->name();
1457       for (unsigned q=0; q<args.size(); ++q)
1458         delete args[q];
1459       args.resize(0);
1460       args = td->copy_args();
1461       // get names here
1462     } else {
1463       type_ = Options::allocate_type(string("T_") + rf_name, false, false,
1464                                      false, "",
1465                                      type_defn::TYPE_COMPLEX,
1466                                      true, false, &args);
1467     }
1468     break;
1469   }
1470 }
1471
1472 string signature::type(const bool use_c) const {
1473   string ret;
1474   if (use_c && is_const_)
1475     ret = "const ";
1476   ret += type_;
1477   ret += Options::make_ptrs(stars_);
1478   return ret;
1479 }
1480
1481 string signature::gen_bundler_call(const string obj_nm, const string data_nm) const {
1482   return ((Options::all_types[base_type()])->gen_bundler_call(obj_nm,
1483                                                               data_nm, stars_));
1484 }
1485
1486 bool signature::tag_bundle_send(ofstream &out_stream, const string return_value,
1487                                 const string req_tag) const
1488 {
1489   if (Options::ml->address_space() == message_layer::AS_many)
1490     return (tag_bundle_send_many(out_stream, return_value, req_tag));
1491   else
1492     return (tag_bundle_send_one(out_stream, return_value, req_tag));
1493 }
1494
1495 bool signature::tag_bundle_send_many(ofstream &out_stream, const string return_value,
1496                                      const string) const
1497 {
1498   // set direction encode
1499   out_stream << Options::set_dir_encode() << ";\n";
1500
1501   // bundle individual args
1502   out_stream << "if (!" << Options::ml->read_tag("net_obj()", "tag") << "\n";
1503
1504   for (unsigned i=0; i<args.size(); i++) {
1505     out_stream << " || !";
1506     args[i]->gen_bundler(out_stream, "net_obj()", "&");
1507     out_stream << "\n";
1508   }
1509   
1510   out_stream << ") ";
1511   out_stream << Options::error_state("igen_encode_err", return_value);
1512
1513   // send message
1514   out_stream << "if (!" << Options::ml->send_message() << ") ";
1515   out_stream << Options::error_state("igen_send_err", return_value);
1516
1517   return true;
1518 }
1519
1520 bool signature::tag_bundle_send_one(ofstream &out_stream, const string return_value,
1521                                     const string req_tag) const
1522 {
1523   switch (args.size()) {
1524   case 0:
1525     break;
1526   case 1:
1527     out_stream << type(true) << " send_buffer(";
1528     out_stream << args[0]->name() << ");\n";
1529     break;
1530   default:
1531     out_stream << type(true) << " send_buffer;\n";
1532     (Options::all_types[type()])->assign_to("send_buffer.", args, out_stream);
1533     break;
1534   }
1535
1536   string sb;
1537   if (type() != "void")
1538     sb = "(void*) &send_buffer, sizeof(send_buffer));\n";
1539   else
1540     sb = "(void*) NULL, 0);\n";
1541
1542   out_stream << Options::ml->bundler_return_type() << " res = "
1543     << Options::ml->send_message() << "(net_obj(), " << req_tag
1544       << ", " << sb;
1545
1546   out_stream << "if (res != " << Options::ml->bundle_ok() << ") ";
1547   out_stream << Options::error_state("igen_send_err", return_value);
1548
1549   return true;
1550 }
1551
1552 string signature::dump_args(const string data_name, const string sep) const {
1553   string ret;
1554   switch (args.size()) {
1555   case 0:
1556     // out_stream << "void";
1557     return "";
1558   case 1:
1559     return data_name;
1560   default:
1561     for (unsigned i=0; i<args.size(); i++) {
1562       ret += data_name + sep + args[i]->name();
1563       if (i < (args.size() - 1))
1564         ret += ", ";
1565     }
1566     return ret;
1567   }
1568 }
1569
1570 bool signature::gen_sig(ofstream &out_stream) const {
1571   switch (args.size()) {
1572   case 0:
1573     out_stream << "void";
1574     break;
1575   case 1:
1576   default:
1577     for (unsigned i=0; i<args.size(); i++) {
1578       out_stream << args[i]->type(true, true) << " " << args[i]->name();
1579       if (i < (args.size()-1))
1580         out_stream << ", ";
1581     }
1582     break;
1583   }
1584   return true;
1585 }
1586
1587 bool signature::arg_struct(ofstream &out_stream) const {
1588   for (unsigned i=0; i<args.size(); i++)
1589     out_stream << args[i]->type() << " " << args[i]->name() << ";\n";
1590   return true;
1591 }
1592
1593 void recursive_dump_kids(const type_defn *curr_defn, ofstream &output) {
1594   for (unsigned u=0; u<curr_defn->kids_.size(); u++) {
1595     string kid_name = curr_defn->kids_[u];
1596     if (!Options::all_types.defines(kid_name)) {
1597       cerr << "Child: " << kid_name << " should be defined\n";
1598       assert(0);
1599     }    
1600     const type_defn *kid_defn = Options::all_types[kid_name];
1601     output << "case " << kid_defn->qual_id() << ":\n";
1602     output << "*data = new " << kid_defn->name() << ";\n";
1603     output << "break;\n";
1604     recursive_dump_kids(kid_defn, output);
1605   }
1606 }