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