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