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