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