added support for derived classes
[dyninst.git] / igen / src / interface_spec.C
1
2 #include "parse.h"
3
4 interface_spec::interface_spec(const string *name, const unsigned &b,
5                                const unsigned &v)
6 : name_(*name), base_(b), version_(v),
7   client_prefix_(*name+"User::"), server_prefix_(*name+"::"), 
8   client_name_(*name + "User"), server_name_(*name), all_functions_(string::hash) 
9 {
10 }
11
12
13 interface_spec::~interface_spec() {
14
15 }
16
17 bool interface_spec::gen_dtor_hdr(ofstream &out_stream, const bool &server,
18                                   const bool &hdr) const
19 {
20   if (!hdr)
21     return true;
22
23   out_stream << "virtual ~"
24       << gen_class_name(server) << "() {  } \n";
25
26   return true;
27 }
28
29 bool interface_spec::gen_ctor_hdr(ofstream &out_stream, const bool &server) const {
30   if (Options::ml->address_space() == message_layer::AS_many) {
31     gen_ctor_1(out_stream, server, true);
32     gen_ctor_2(out_stream, server, true);
33     gen_ctor_3(out_stream, server, true);
34   } else {
35     gen_ctor_4(out_stream, server, true);
36   }
37
38   if (server) {
39     if (Options::ml->address_space() == message_layer::AS_many) {
40       out_stream << "private:\n";
41       out_stream << "bool verify_protocol(bool tag_read=false);\n";
42       out_stream << "public:\n";
43     }
44   } else {
45     if (Options::ml->address_space() == message_layer::AS_many) {
46       out_stream << "private:\n";
47       out_stream << "virtual bool verifyProtocolAndVersion();\n";
48       out_stream << "public:\n";
49     }
50   }
51
52   if (Options::ml->address_space() == message_layer::AS_many) {
53     out_stream << Options::type_prefix() << "message_tags"
54       << " waitLoop(void);\n";
55   } else {
56     out_stream << Options::type_prefix() << "message_tags"
57       << " waitLoop(" 
58         << "bool specific, "
59           << Options::type_prefix() << "message_tags mt);\n";
60   }
61   out_stream << "bool isValidTag(const " 
62     << Options::type_prefix() << "message_tags &tag) {\n";
63   out_stream << "return((tag >= " << Options::type_prefix() << "verify) && "
64     << "(tag <= " << Options::type_prefix() << "last));\n}\n";
65
66   if (Options::ml->address_space() == message_layer::AS_one) {
67     out_stream << "// KLUDGE ALERT -- can't use a class member for msg_buf because this class \n";
68     out_stream << "// instance is being abused -- multiplexed by several threads \n";
69   }
70
71   out_stream << Options::type_prefix() << "message_tags switch_on("
72     << Options::type_prefix() << "message_tags m";
73   if (Options::ml->address_space() == message_layer::AS_one) 
74     out_stream << ", " << Options::type_prefix() << "msg_buf& KLUDGE";
75   out_stream << ");\n";
76
77   if (Options::ml->serial()) {
78     out_stream << "// returns true if any requests are buffered\n";
79     out_stream << "bool buffered_requests() {\n"
80       << "return (async_buffer.size());\n}\n";
81
82     out_stream << "// Wait until this mesage tag is received, or is found buffered\n";
83     out_stream << "bool wait_for(" << Options::type_prefix() << "message_tags m);\n";
84
85     out_stream << "bool is_buffered(" << Options::type_prefix() << "message_tags m) {\n";
86     out_stream << "unsigned size = async_buffer.size();\n";
87     out_stream << "for (unsigned u=head; u<size; u++) \n";
88     out_stream << "if (async_buffer[u]->data_type == m) return true;\n";
89     out_stream << "return false;\n}\n";
90
91     out_stream << "// Handles any buffered request\n";
92     out_stream << Options::type_prefix() << "message_tags process_buffered();\n";
93
94     out_stream << "private:\n";
95     out_stream << Options::type_prefix() << "message_tags process_buffered(unsigned dex);\n";
96     out_stream << "bool awaitResponse(const " << Options::type_prefix() << "message_tags &);\n";
97     out_stream << Options::type_prefix() << "message_tags delete_buffer(unsigned dex);\n";
98     out_stream << "public:\n";
99   }
100   return true;
101 }
102
103 bool interface_spec::gen_prelude(ofstream &out_stream, const bool &server) const {
104   out_stream << "\nclass " << gen_class_name(server) << ":" 
105     << " public RPCBase, public " << Options::ml->rpc_parent() << "{\npublic:\n";
106   gen_ctor_hdr(out_stream, server);
107   gen_dtor_hdr(out_stream, server, true);
108
109   out_stream << "\n // Begin passed through text from interface file\n";
110   if (server) {
111     for (unsigned ts=0; ts<server_ignore.size(); ++ts)
112       out_stream << server_ignore[ts] << endl;
113   } else {
114     for (unsigned ts=0; ts<client_ignore.size(); ++ts)
115       out_stream << client_ignore[ts] << endl;
116   }
117   out_stream << "// End passed through text from interface file\n";
118
119   return true;
120 }
121
122
123 bool interface_spec::gen_stl_bundler(ofstream &out_h, ofstream &out_c) const {
124   if (Options::ml->address_space() == message_layer::AS_one) 
125     return true;
126
127   out_h << "#if defined(external_templates)\n#pragma interface\n#endif\n"; 
128
129   out_h << "template <class Cont, class Elem, class Bund_Func> \ninline\n";
130   out_h << Options::ml->bundler_return_type() << " " 
131     << Options::type_class() << "_"
132     << Options::ml->bundler_prefix() << "stl("
133       << Options::ml->marshall_obj() << Options::ml->marshall_obj_ptr() 
134         << " obj, Cont *data, Bund_Func Func, Elem *ptr) {\n";
135  
136   out_h << "assert(obj);\n";
137   out_h << "assert(" << Options::obj_ptr() << " != "
138     << Options::ml->free_const() << ");\n";
139
140   out_h << "if (" << Options::obj_ptr() << " == "
141     << Options::ml->unpack_const() << ") {\n";
142   out_h << "unsigned index=0;\n";
143   out_h << "unsigned count;\n";
144   out_h << "if (!" << Options::ml->read_tag("obj", "count") << ")\n"
145     << " return FALSE;\n";
146
147   out_h << "while (index < count) {\n ";
148   out_h << "Elem element;\n";
149   out_h << "if (Func(obj, &element)) {\n";
150   out_h << "(*data) += element;\n";
151   out_h << "index++;\n";
152   out_h << "} else { \n";
153   out_h << "break;\n";
154   out_h << "}\n}\n";
155   out_h << "if (index == count) return "
156     << Options::ml->bundle_ok() << "; else return " 
157       << Options::ml->bundle_fail() << ";\n";
158   out_h << "} ";
159
160   out_h << "else {\n";
161   out_h << "unsigned index=0;\n";
162   out_h << "unsigned count=data->size();\n";
163   out_h << "if (!" << Options::ml->read_tag("obj", "count") << ")\n"
164     << " return FALSE;\n";
165   out_h << "while ((index <count) && ";
166   out_h << "Func(obj, &((*data)[index]))) index++;\n";
167   out_h << "if (index == count) return TRUE; else return FALSE;\n";
168   out_h << "}\n}\n";
169   return true;
170 }
171
172 bool interface_spec::gen_stl_bundler_ptr(ofstream &out_h, ofstream &out_c) const {
173   if (Options::ml->address_space() == message_layer::AS_one) 
174     return true;
175
176   out_h << "template <class Cont, class Elem, class Bund_Func> \ninline\n";
177   out_h << Options::ml->bundler_return_type() << " " 
178     << Options::type_class() << "_"
179     << Options::ml->bundler_prefix() << "stl_PTR("
180       << Options::ml->marshall_obj() << Options::ml->marshall_obj_ptr() 
181         << " obj, Cont **data, Bund_Func Func, Elem *ptr) {\n";
182  
183   out_h << "assert(obj);\n";
184   out_h << "assert(" << Options::obj_ptr() << " != "
185     << Options::ml->free_const() << ");\n";
186
187   out_h << "bool is_null = (*data == NULL);\n";
188   out_h << "if (!P_xdr_Boolean(obj, &is_null)) return " << Options::ml->bundle_fail()
189     << ";\n";
190
191   out_h << "if (" << Options::obj_ptr() << " == "
192     << Options::ml->unpack_const() << ") {\n";
193   out_h << "if (is_null) { *data = NULL; return " << Options::ml->bundle_ok() << "; }\n";
194   out_h << "*data = new Cont;\n";
195   out_h << "if (!*data) return " << Options::ml->bundle_fail() << ";\n";
196   out_h << "return "
197     << Options::type_class() << "_"
198     << Options::ml->bundler_prefix() << "stl(obj, *data, Func, ptr);\n";
199   out_h << "} ";
200
201   out_h << "else {\n";
202   out_h << "if (!*data) return " << Options::ml->bundle_ok() << ";\n";
203   out_h << "return "
204          << Options::type_class() << "_"
205           <<  Options::ml->bundler_prefix() << "stl(obj, *data, Func, ptr);\n";
206   out_h << "}\n}\n";
207   return true;
208 }
209
210 bool interface_spec::gen_scope(ofstream &out_h, ofstream &out_c) const {
211
212   out_h << "class " << Options::type_class() << "  {\npublic:\n";
213
214   type_defn *td; string s;
215
216   bool first = true;
217   out_h << "typedef enum {\n ";
218   for (unsigned u=0; u<Options::vec_types.size(); u++) {
219     td = Options::vec_types[u];
220     if (td->is_class()) {
221       if (!first)
222         out_h << ", " << td->unqual_id();
223       else {
224         out_h << td->unqual_id() << " = " << base()+2001;
225         first=false;
226       }
227     }
228   }
229   out_h << "} class_ids;\n";
230
231   for (u=0; u<Options::vec_types.size(); u++) {
232     td = Options::vec_types[u];
233     if (!td->is_in_library() && !td->is_stl()) {
234       td->gen_class(Options::ml->bundler_prefix(), out_h);
235       if (Options::ml->address_space() == message_layer::AS_many) {
236         td->gen_bundler_sig(true, Options::type_prefix(), 
237                             Options::ml->bundler_prefix(), out_h);
238         td->gen_bundler_body(Options::ml->bundler_prefix(), Options::type_prefix(),
239                              out_c);
240         td->gen_bundler_ptr(Options::type_prefix(), Options::ml->bundler_prefix(),
241                             out_c, out_h);
242
243       }
244     }
245   }
246
247   remote_func *rf; 
248   dictionary_hash_iter<string, remote_func*> rfi(all_functions_);  
249   if (Options::ml->address_space() == message_layer::AS_one) {
250     out_h << "union msg_buf { \n";
251     while (rfi.next(s, rf)) {
252       if (rf->sig_type() != "void")
253         out_h << rf->sig_type(true) << " " << rf->name() << "_call;\n";
254       if (rf->ret_type() != "void")
255         out_h << rf->ret_type(true) << " " << rf->name() << "_req;\n";
256     }
257     out_h << "};\n";
258   }
259
260   out_h << "enum message_tags {\n";
261   out_h << "verify = " << base() << ",\n";
262
263   rfi.reset();
264   while (rfi.next(s, rf)) 
265     out_h << rf->request_tag(true) << ", " << rf->response_tag(true) << ",\n";
266   out_h << "error, " << "last }; \n typedef enum message_tags message_tags;\n";
267
268   if (Options::ml->serial()) {
269     out_h << "typedef struct buf_struct {\n";
270     out_h << "void *data_ptr;\n";
271     out_h << Options::type_prefix() << "message_tags data_type;\n";
272     out_h << "} buf_struct;\n";
273   }
274
275   out_h << "};\n";
276   return true;
277 }
278
279 bool interface_spec::gen_inlines(ofstream &out_stream, const bool &server) const {
280             
281   return true;
282 }
283
284 bool interface_spec::gen_header(ofstream &out_stream, const bool &server) const {
285   gen_prelude(out_stream, server);
286
287   string s; remote_func *rf;
288   dictionary_hash_iter<string, remote_func*> dhi(all_functions_);
289   while (dhi.next(s, rf))
290     rf->gen_signature(out_stream, true, server);
291
292   out_stream << "\nprotected:\n virtual void handle_error();\n";
293   if (Options::ml->serial()) {
294     out_stream << "vector<" << Options::type_prefix()
295       << "buf_struct*> async_buffer;\n";
296     out_stream << "unsigned head;\n";
297   } 
298   if (Options::ml->address_space() == message_layer::AS_one)
299     out_stream << "// " << Options::type_prefix() << "msg_buf msg_buf;\n";
300
301
302   out_stream << "};\n";
303
304   gen_inlines(out_stream, server);
305
306   return true;
307 }
308
309 bool interface_spec::gen_ctor_helper(ofstream &out_stream, const bool &server) const {
310   if (!server)
311     out_stream << "if (!opened()) assert(0);\nif (!verifyProtocolAndVersion()) assert(0);\n";
312   return true;
313 }
314
315 bool interface_spec::gen_ctor_4(ofstream &out_stream, const bool &server,
316                                 const bool &hdr) const
317 {
318   if (!hdr)
319     return true;
320
321   out_stream << (!hdr ? gen_class_prefix(server) : string(""))
322     << gen_class_name(server) 
323       << "(const unsigned tid) :\n ";
324   out_stream << " RPCBase(igen_no_err, 0), \n"
325     << Options::ml->rpc_parent() << "(tid)";
326   if (Options::ml->serial()) out_stream << ", head(0) ";
327   out_stream << " { } \n";
328   return true;
329 }
330
331 bool interface_spec::gen_ctor_1(ofstream &out_stream, const bool &server,
332                                 const bool &hdr) const {
333   out_stream << (!hdr ? gen_class_prefix(server) : string(""))
334     << gen_class_name(server) 
335       << "(int use_fd, xdr_rd_func r, xdr_wr_func w, const bool nblock)";
336   if (hdr) {
337     out_stream << ";\n";
338     return true;
339   }
340   
341   out_stream << "\n: RPCBase(igen_no_err, 0),\n"
342     << Options::ml->rpc_parent() << "(use_fd, r, w, nblock) ";
343   if (Options::ml->serial()) out_stream << " , head(0) ";
344   out_stream << "\n";
345   return true;
346 }
347
348 bool interface_spec::gen_ctor_2(ofstream &out_stream, const bool &server,
349                                 const bool &hdr) const
350 {
351   out_stream << (!hdr ? gen_class_prefix(server) : string("")) << gen_class_name(server)
352     << "(int family, int port, int type, const string host, xdr_rd_func r, xdr_wr_func w, bool nblock)";
353
354   if (hdr) {
355     out_stream << ";\n";
356     return true;
357   }
358   out_stream << "\n: RPCBase(igen_no_err, 0),\n"
359     << Options::ml->rpc_parent() << "(family, port, type, host, r, w, nblock)";
360   if (Options::ml->serial()) out_stream << ", head(0)";
361   out_stream << "\n";
362   return true;
363 }
364
365 bool interface_spec::gen_ctor_3(ofstream &out_stream, const bool &server,
366                                 const bool &hdr) const
367 {
368   out_stream << (!hdr ? gen_class_prefix(server) : string("")) << gen_class_name(server)
369     << "(const string machine, const string login, const string program, xdr_rd_func rf, xdr_wr_func wf, vector<string> &args, bool nblock, int port_fd)";
370
371   if (hdr) {
372     out_stream << ";\n";
373     return true;
374   }
375   out_stream << "\n: RPCBase(igen_no_err, 0),\n"
376     << Options::ml->rpc_parent() << "(machine, login, program, rf, wf, args, nblock, port_fd)";
377   if (Options::ml->serial()) out_stream << ", head(0) ";
378   out_stream << "\n";
379  
380   return true;
381 }
382
383 bool interface_spec::gen_ctor_body(ofstream &out_stream, const bool &server) const {
384   if (Options::ml->address_space() == message_layer::AS_many) {
385     gen_ctor_1(out_stream, server, false);
386     out_stream << "{\n";
387     gen_ctor_helper(out_stream, server);
388     out_stream << "}\n";
389
390     gen_ctor_2(out_stream, server, false);
391     out_stream << "{\n";
392     gen_ctor_helper(out_stream, server);
393     out_stream << "}\n";
394
395     gen_ctor_3(out_stream, server, false);
396     out_stream << "{\n";
397     gen_ctor_helper(out_stream, server);
398     out_stream << "}\n";
399   } else {
400     // do nothing
401   }
402   return true;
403 }
404
405 bool interface_spec::gen_dtor_body(ofstream &out_stream, const bool &server) const {
406   // gen_dtor_hdr(out_stream, server, false);
407   // out_stream << "{ }\n";
408   return true;
409 }
410
411 bool interface_spec::gen_server_verify(ofstream &out_stream) const {
412
413   if (!Options::dont_gen_handle_err) {
414     out_stream << "void " << gen_class_prefix(true) << "handle_error() {\n";
415     out_stream << "cerr << \"Error not handled, exiting\";\n";
416     out_stream << "IGEN_ERR_ASSERT;\n";
417     out_stream << "exit(-1);\n";
418     out_stream << "}\n\n";
419   }
420
421   if (Options::ml->address_space() == message_layer::AS_one) 
422     return true;
423
424   out_stream << "bool " << gen_class_prefix(true) << "verify_protocol(bool tag_read) {\n";
425   out_stream << "unsigned tag;\n";
426   out_stream << "if (!tag_read) {\n";
427   out_stream << Options::set_dir_decode() << ";\n";
428
429   if (Options::ml->skip()) {
430     out_stream << "if (!" << Options::ml->skip_message() << ") ";
431     out_stream << Options::error_state("igen_read_err", "false");
432   }
433   out_stream << "if (!" << Options::ml->bundler_prefix() << "u_int(net_obj(), &tag)) ";
434   out_stream << Options::error_state("igen_proto_err", "false");
435   out_stream << "if (tag != " << Options::type_prefix() << "verify) ";
436   out_stream << Options::error_state("igen_proto_err", "false");
437   out_stream << "}\n";
438
439   out_stream << Options::set_dir_encode() << ";\n";
440   out_stream << "tag = " << Options::type_prefix() << "verify;\n";
441   out_stream << "unsigned version = " << version() << ";\n";
442   out_stream << "string name = " << "\"" << name() << "\";\n";
443   out_stream << "if (!" << Options::ml->bundler_prefix()
444     << "u_int(net_obj(), &tag) || \n !" << Options::ml->bundler_prefix() 
445       << "string_pd(net_obj(), &name) || \n !" << Options::ml->bundler_prefix()
446         << "u_int(net_obj(), &version)) ";
447   out_stream << Options::error_state("igen_encode_err", "false");
448
449   out_stream << "if (!" << Options::ml->send_message() << ") ";
450   out_stream << Options::error_state("igen_send_err", "false");
451   out_stream << "setVersionVerifyDone();\n";
452   out_stream << "return true;\n}\n";
453
454   return true;
455 }
456
457 bool interface_spec::gen_client_verify(ofstream &out_stream) const {
458
459   if (!Options::dont_gen_handle_err) {
460     out_stream << "void " << gen_class_prefix(false) << "handle_error() {\n";
461     out_stream << "cerr << \"Error not handled, exiting\";\n";
462     out_stream << "assert(0);\n";
463     out_stream << "}\n\n";
464   }
465
466   if (Options::ml->address_space() == message_layer::AS_many) {
467     out_stream << "bool  " << gen_class_prefix(false)
468       << "verifyProtocolAndVersion() {\n";
469
470     out_stream << "unsigned tag = " << Options::type_prefix() << "verify;\n";
471     out_stream << Options::set_dir_encode() << ";\n";
472     out_stream << "if (!" << Options::ml->bundler_prefix()
473       << "u_int(net_obj(), &tag)) ";
474     out_stream << Options::error_state("igen_encode_err", "false");
475
476     out_stream << "if (!" << Options::ml->send_message() << ") ";
477     out_stream << Options::error_state("igen_send_err", "false");
478
479     out_stream << "if (!awaitResponse(" << Options::type_prefix() << "verify)) ";
480     out_stream << Options::error_state("igen_proto_err", "false");
481
482     out_stream << Options::set_dir_decode() << ";\n";
483     out_stream << "string proto;\n";
484     out_stream << "if (!" << Options::ml->bundler_prefix()
485       << "string_pd(net_obj(), &proto) || \n !" 
486         << Options::ml->bundler_prefix() << "u_int(net_obj(), &tag)) {\n";
487     out_stream << "set_err_state(igen_proto_err);\n";
488     out_stream << "cerr << \"Protocol verify - bad response from server\\n\" << endl;";
489     out_stream << "handle_error(); exit(-1); return false;\n}\n";
490     
491     out_stream << "if ((tag != " << version() << "|| proto != \""
492       << name() << "\")) {\n";
493     out_stream << "cerr << \" Protocol " << name() << " version " << version()
494       << " expected\\n\" << endl;";
495     out_stream << "cerr << \" Found Protocol \" << proto << \" version \" << tag << endl;";
496     out_stream << "set_err_state(igen_proto_err);\n";
497     out_stream << "handle_error();\nexit(-1); return false;\n}\n";
498     out_stream << "return true;\n}\n";
499   }
500   return true;
501 }
502
503 bool interface_spec::gen_interface() const {
504
505   gen_scope(Options::dot_h, Options::dot_c);
506
507   gen_header(Options::clnt_dot_h, false);
508   gen_header(Options::srvr_dot_h, true);
509
510   gen_ctor_body(Options::srvr_dot_c, true);
511   gen_ctor_body(Options::clnt_dot_c, false);
512
513   gen_dtor_body(Options::srvr_dot_c, true);
514   gen_dtor_body(Options::clnt_dot_c, false);
515
516   remote_func *rf; string s;
517   dictionary_hash_iter<string, remote_func*> rfi(all_functions_);
518   while (rfi.next(s, rf))
519     rf->gen_stub(Options::srvr_dot_c, Options::clnt_dot_c);
520
521   gen_await_response(Options::clnt_dot_c, false);
522   gen_await_response(Options::srvr_dot_c, true);
523   gen_wait_loop(Options::clnt_dot_c, false);
524   gen_wait_loop(Options::srvr_dot_c, true);
525   gen_process_buffered(Options::srvr_dot_c, true);
526   gen_process_buffered(Options::clnt_dot_c, false);
527   gen_client_verify(Options::clnt_dot_c);
528   gen_server_verify(Options::srvr_dot_c);
529
530   if (Options::stl_seen) {
531     gen_stl_bundler(Options::dot_h, Options::dot_c);
532     gen_stl_bundler_ptr(Options::dot_h, Options::dot_c);
533     gen_stl_temps();
534   }
535
536   return true;
537 }
538
539 // I am assuming that Vector and Queue have already been included
540 bool interface_spec::gen_stl_temps() const {
541
542   if (Options::ml->address_space() == message_layer::AS_many) 
543     Options::temp_dot_c << "template class queue<"
544       << Options::type_prefix() << "buf_struct*>;\n";
545   
546   for (unsigned stl_index=0; stl_index < Options::stl_types.size(); stl_index++) {
547     if (Options::stl_types[stl_index].elements.size()) {
548       if (Options::stl_types[stl_index].need_include) {
549         Options::temp_dot_c <<  "#pragma implementation \"" 
550           << Options::stl_types[stl_index].pragma_name << "\"\n";
551         Options::temp_dot_c << "#include "
552           << Options::stl_types[stl_index].include_file << "\n";
553       }
554       for (int el_index=0; el_index < Options::stl_types[stl_index].elements.size();
555            el_index++) {
556         Options::temp_dot_c << "template class " <<
557           Options::stl_types[stl_index].name << "<"
558             << Options::stl_types[stl_index].elements[el_index].name << ">;\n";
559       }
560     }
561   }
562
563   if (Options::ml->address_space() == message_layer::AS_one)
564     return true;
565
566   for (stl_index=0; stl_index < Options::stl_types.size(); stl_index++) {
567     for (unsigned el_index=0; el_index < Options::stl_types[stl_index].elements.size();
568          el_index++) {
569       Options::temp_dot_c << "template "
570         << Options::ml->bundler_return_type() << " "
571           << Options::type_class() << "_"
572           << Options::ml->bundler_prefix() << "stl";
573       Options::temp_dot_c << "(" 
574         << Options::ml->marshall_obj() << Options::ml->marshall_obj_ptr() << ", "
575         << Options::stl_types[stl_index].name
576         << "<"
577         << Options::stl_types[stl_index].elements[el_index].name
578         << ">*, "
579         << Options::ml->bundler_return_type() << " (*)("
580         << Options::ml->marshall_obj()
581         << Options::ml->marshall_obj_ptr() << ", "
582         << Options::stl_types[stl_index].elements[el_index].name << "*), "
583         << Options::stl_types[stl_index].elements[el_index].name
584         << "*);\n";
585     }
586   }
587
588   for (stl_index=0; stl_index < Options::stl_types.size(); stl_index++) {
589     for (unsigned el_index=0; el_index < Options::stl_types[stl_index].elements.size();
590          el_index++) {
591       Options::temp_dot_c << "template "
592         << Options::ml->bundler_return_type() << " "
593         << Options::type_class() << "_"
594           << Options::ml->bundler_prefix() << "stl";
595       Options::temp_dot_c << "_PTR";
596       Options::temp_dot_c << "(" 
597         << Options::ml->marshall_obj() << Options::ml->marshall_obj_ptr() << ", "
598         << Options::stl_types[stl_index].name
599         << "<"
600         << Options::stl_types[stl_index].elements[el_index].name
601         << ">**, "
602         << Options::ml->bundler_return_type() << " (*)("
603         << Options::ml->marshall_obj()
604         << Options::ml->marshall_obj_ptr() << ", "
605         << Options::stl_types[stl_index].elements[el_index].name << "*), "
606         << Options::stl_types[stl_index].elements[el_index].name
607         << "*);\n";
608     }
609   }
610   
611   return true;
612 }
613
614 bool interface_spec::gen_process_buffered(ofstream &out_stream, const bool &srvr) const {
615   if (!Options::ml->serial())
616     return true;
617
618   out_stream << Options::type_prefix() << "message_tags " << gen_class_prefix(srvr)
619     << "process_buffered() {\n";
620   out_stream << "if (!async_buffer.size()) return "
621     << Options::type_prefix() << "error;\n";
622
623   out_stream << "return (delete_buffer(head));\n";
624   out_stream << "}\n";
625
626   out_stream << Options::type_prefix() << "message_tags " << gen_class_prefix(srvr)
627     << "process_buffered(unsigned index) {\n";
628   out_stream << "if (!async_buffer.size()) return "
629     << Options::type_prefix() << "error;\n";
630   out_stream << "return (delete_buffer(index));\n";
631   out_stream << "}\n";
632
633   out_stream << Options::type_prefix() << "message_tags "
634     << gen_class_prefix(srvr) << "delete_buffer(unsigned index) {\n";
635   out_stream << "unsigned asize = async_buffer.size();\n";
636   out_stream << "assert(index < asize);\n";
637   out_stream << Options::type_prefix() << "buf_struct *item = async_buffer[index];\n";
638
639   out_stream << "unsigned elems_left = asize - head - 1;\n";
640   out_stream << "if (index == head) \n head++;\n";
641   out_stream << "else if (index == (asize - 1))   \n";
642   out_stream << "   async_buffer.resize(asize - 1); \n";
643   out_stream << "else {   \n";
644   out_stream << "   async_buffer[index] = async_buffer[asize - 1]; \n";
645   out_stream << "   async_buffer.resize(asize - 1);   \n";
646   out_stream << "}\n";
647
648   out_stream << "if (!elems_left) {    \n";
649   out_stream << "head = 0; async_buffer.resize(0);   \n";
650   out_stream << "}\n";
651   out_stream << "assert((!async_buffer.size() && !head) || (elems_left == (async_buffer.size()-head)));\n";
652   out_stream << Options::type_prefix() << "message_tags tag = item->data_type;\n";
653   out_stream << "switch (tag) {\n";
654   
655   remote_func *rf; string s;
656   dictionary_hash_iter<string, remote_func*> rfi(all_functions_);
657   while (rfi.next(s, rf))
658     rf->free_async(out_stream, srvr);
659   
660   out_stream << "default:\n";
661   out_stream << "IGEN_ERR_ASSERT;\n";
662   out_stream << "set_err_state(igen_request_err);\n";
663   out_stream << "return " << Options::type_prefix() << "error" << ";\n";
664   out_stream << "break;\n";
665   out_stream << "}\n";
666
667   out_stream << "delete item;\n";
668   out_stream << "return tag;\n";
669   out_stream << "}\n";
670
671   return true;
672 }
673
674 bool interface_spec::gen_await_response(ofstream &out_stream, const bool srvr) const {
675   if (!Options::ml->serial())
676     return true;
677
678   out_stream << "bool " << gen_class_prefix(srvr)
679     << "awaitResponse(const " << Options::type_prefix()
680       << "message_tags &target_tag) {\n";
681   out_stream << "unsigned tag;\n";
682   out_stream << "if (get_err_state() != igen_no_err) return false;\n";
683   out_stream << Options::set_dir_decode() << ";\n";
684
685   out_stream << "while (true) {\n";
686
687   if (Options::ml->records_used()) {
688     out_stream << "if (!" << Options::ml->skip_message() << ") ";
689     out_stream << Options::error_state("igen_read_err", "false");
690   }
691
692   out_stream << "if (!" << Options::ml->read_tag("net_obj()", "tag") << ") ";
693   out_stream << Options::error_state("igen_read_err", "false");
694
695   out_stream << "if (tag == target_tag) return true;\n";
696
697   out_stream << "switch (tag) {\n";
698   
699   remote_func *rf; string s;
700   dictionary_hash_iter<string, remote_func*> rfi(all_functions_);
701   while (rfi.next(s, rf))
702     rf->save_async_request(out_stream, srvr);
703   out_stream << "default:\n";
704   out_stream << "set_err_state(igen_request_err);\n";
705   out_stream << "IGEN_ERR_ASSERT;\n";
706   out_stream << "return false;\n";
707   out_stream << "}\n";
708
709   out_stream << "}\n";
710   out_stream << "}\n";
711   return true;
712 }
713
714 bool interface_spec::gen_wait_loop(ofstream &out_stream, const bool srvr) const {
715
716   out_stream << Options::type_prefix() << "message_tags "
717     << gen_class_prefix(srvr) << "waitLoop(";
718   
719   if (Options::ml->address_space() == message_layer::AS_many) {
720     out_stream << "void) {\n";
721   } else {
722     out_stream << " bool specific, "
723       << Options::type_prefix() << "message_tags mt) {\n"; 
724   }
725
726   out_stream << Options::type_prefix() << "message_tags tag;\n";
727
728   out_stream << "if (get_err_state() != igen_no_err) return "
729     << Options::type_prefix() << "error;\n";
730
731   out_stream << Options::set_dir_decode() << ";\n";
732
733   if (Options::ml->records_used()) {
734     if (Options::ml->skip()) {
735       out_stream << "if (!" << Options::ml->skip_message() << ") ";
736       out_stream << Options::error_state("igen_read_err",
737                                          Options::type_prefix()+"error");
738     }
739   }
740
741   if (Options::ml->address_space() != message_layer::AS_one) {
742     out_stream << "if (!" << Options::ml->read_tag("net_obj()", "tag") << ") ";
743     out_stream << Options::error_state("igen_read_err",
744                          Options::type_prefix()+"error");
745     out_stream << "return switch_on(tag);\n"; 
746   } else {
747     out_stream << "if (!specific) \n";
748     out_stream << "tag = " << Options::type_prefix() << "message_tags(MSG_TAG_ANY);\n";
749     out_stream << "else \n";
750     out_stream << "tag = mt;\n";
751
752     out_stream << Options::type_prefix() << "msg_buf KLUDGE_msg_buf;\n";    
753     out_stream << "// unsigned len = sizeof(msg_buf);\n";
754     out_stream << "unsigned len = sizeof(KLUDGE_msg_buf);\n";
755     out_stream << "// setRequestingThread(msg_recv((unsigned*)&tag, &msg_buf, &len));\n";
756     out_stream << "setRequestingThread(msg_recv((unsigned*)&tag, &KLUDGE_msg_buf, &len));\n";
757     out_stream << "if (getRequestingThread() == THR_ERR) ";
758     out_stream << Options::error_state("igen_read_err", Options::type_prefix()+"error");
759     out_stream << "return switch_on(tag, KLUDGE_msg_buf);\n"; 
760   }
761
762
763   out_stream << "}\n";
764
765   out_stream << Options::type_prefix() << "message_tags " << gen_class_prefix(srvr)
766     << "switch_on(" << Options::type_prefix() << "message_tags tag";
767   if (Options::ml->address_space() == message_layer::AS_one) 
768     out_stream << ", " << Options::type_prefix() << "msg_buf& KLUDGE_msg_buf";
769   out_stream << ") {\n";
770
771   if (Options::ml->address_space() == message_layer::AS_one) {
772     out_stream << "int val = THR_OKAY;\n";
773   }
774
775   out_stream << "switch (tag) {\n";
776
777   if (srvr && (Options::ml->address_space() != message_layer::AS_one)) {
778     out_stream << "case " << Options::type_prefix() << "verify:\n";
779     out_stream << "if (!verify_protocol(true)) ";
780     out_stream << Options::error_state("igen_proto_err", Options::type_prefix()+"error");
781     out_stream << "return tag;\n";
782   }
783
784   remote_func *rf; string s;
785   dictionary_hash_iter<string, remote_func*> rfi(all_functions_);
786   while (rfi.next(s, rf))
787     rf->handle_request(out_stream, srvr);
788
789   out_stream << "default:\n";
790   out_stream << "set_err_state(igen_request_err);\n";
791   out_stream << "IGEN_ERR_ASSERT;\n";
792   out_stream << "return " << Options::type_prefix() << "error;\n";
793   out_stream << "}\n";
794
795   if (Options::ml->address_space() == message_layer::AS_one) {
796     out_stream << "if (val != THR_OKAY) ";
797     out_stream <<
798       Options::error_state("igen_read_err", Options::type_prefix()+"error");
799   }
800
801   out_stream << "return tag;\n";
802   out_stream << "}\n";
803
804   if (Options::ml->address_space() != message_layer::AS_one) {
805     out_stream << "bool " << gen_class_prefix(srvr)
806       << "wait_for(" << Options::type_prefix() << "message_tags tag) {\n";
807
808     out_stream << "unsigned size = async_buffer.size();\n";
809     out_stream << "for (unsigned u=head; u<size; u++) \n";
810     out_stream << "if (async_buffer[u]->data_type == tag) {\n";
811     out_stream << "if (process_buffered(u) != tag) \n return false;\n";
812     out_stream << "else \n return true;\n";
813     out_stream << "}\n";
814
815     out_stream << "if (!awaitResponse(tag)) ";
816     out_stream << Options::error_state("igen_proto_err", "false");
817     
818     out_stream << "if (!switch_on(tag)) \n return false;\n";
819     out_stream << "else \n return true;\n";
820     out_stream << "}\n";
821   }
822   return true;
823 }
824
825 bool interface_spec::new_remote_func(const string *name, vector<arg*> *arglist,
826                                      const remote_func::call_type &callT,
827                                      const bool &is_virtual, const arg &return_arg,
828                                      const bool do_free) {
829   assert(name);
830   remote_func *rf = new remote_func(*name, arglist, callT, is_virtual,
831                                     return_arg, do_free);
832   assert(rf);
833   all_functions_[*name] = rf;
834   return true;
835 }
836
837 bool interface_spec::are_bundlers_generated() const {
838   return (Options::ml->address_space() == message_layer::AS_many);
839 }
840
841 void interface_spec::ignore(bool is_srvr, char *text) {
842   if (!text || (P_strlen(text) < 17)) return;
843   char *buffer = P_strdup(text);
844   char *temp = buffer;
845   temp[strlen(temp) - 8] = (char) 0;
846   temp += 8;
847   if (is_srvr)
848     server_ignore += temp;
849   else
850     client_ignore += temp;
851   delete buffer;
852 }