Fixed iSymCount problem, improved speed of search for lib functions,
[dyninst.git] / igen / src / main.C
1 /*
2  * main.C - main function of the interface compiler igen.
3  *
4  * $Log: main.C,v $
5  * Revision 1.24  1994/06/02 23:34:26  markc
6  * New igen features: error checking, synchronous upcalls.
7  *
8  * Revision 1.23  1994/04/07  19:03:33  markc
9  * Fixed bug for async client calls with threads.  Removed msg_recv.
10  *
11  * Revision 1.22  1994/04/06  21:28:45  markc
12  * Added constructor for client side of xdr based code.
13  *
14  * Revision 1.21  1994/04/01  04:57:50  markc
15  * Added checks in bundlers.  Fixed xdrrec_endofrecord.
16  *
17  * Revision 1.20  1994/03/31  22:57:52  hollings
18  * Fixed xdr_endofrecord bug and added wellKnownScoket parameter.
19  *
20  * Revision 1.19  1994/03/31  02:12:18  markc
21  * Added code to initialize versionVerifyDone
22  *
23  * Revision 1.18  1994/03/25  22:35:21  hollings
24  * Get the test for callErr right.
25  *
26  * Revision 1.17  1994/03/25  20:57:02  hollings
27  * Changed all asserts to set the error member variable.  This makes it
28  * possible to detect/continue when the remote process dies.
29  *
30  * Revision 1.16  1994/03/07  23:28:46  markc
31  * Added support to free arrays of classes.
32  *
33  * Revision 1.15  1994/03/07  02:50:56  markc
34  * Set callErr to 0 in constructors.
35  *
36  * Revision 1.14  1994/03/07  02:35:17  markc
37  * Added code to detect failures for xdr code.  Provides member instance
38  * callErr which is set to -1 on failures.
39  *
40  * Revision 1.13  1994/03/06  20:51:09  markc
41  * Added float as a basic type.
42  *
43  * Revision 1.12  1994/03/01  21:39:37  jcargill
44  * Rearranged order of includes for igen-generated code, so that it compiles
45  * on MIPS.  Some of the Ultrix headers really suck.
46  *
47  * Revision 1.11  1994/03/01  01:50:46  markc
48  * Fixed memory access errors.
49  *
50  * Revision 1.10  1994/02/25  11:41:32  markc
51  * Fixed bug.  Igen generated versionVerify tests for client code when async.
52  *
53  * Revision 1.9  1994/02/24  05:14:32  markc
54  * Man page for igen.
55  * Initial version for solaris2.2.
56  * Dependencies changed.
57  * Added pvm support, virtual function support, inclusion of data members,
58  * separate client and header include files.
59  *
60  * Revision 1.8  1994/02/08  00:17:55  hollings
61  * Fixed pointer problems to work on DECstations.
62  *
63  * Revision 1.7  1994/02/04  01:25:46  hollings
64  * *** empty log message ***
65  *
66  * Revision 1.6  1994/02/04  00:35:01  hollings
67  * constructor inheritance round two.
68  *
69  * Revision 1.5  1994/01/31  20:05:57  hollings
70  * Added code to check the protocol name and version tests are run
71  * before any upcalls get invoked.
72  *
73  * Revision 1.4  1994/01/28  19:42:30  hollings
74  * Fixed max variable name length.
75  *
76  * Revision 1.3  1994/01/27  20:36:29  hollings
77  * changes in include syntax round 2 or 3.
78  *
79  * Revision 1.2  1994/01/26  06:50:10  hollings
80  * made the output of igen pass through g++ -Wall.
81  *
82  * Revision 1.1  1994/01/25  20:48:43  hollings
83  * New utility for interfaces.
84  * new utility for interfaces.
85  *
86  *
87  */
88 #include <stdlib.h>
89 #include <unistd.h>
90 #include <stdio.h>
91 #include <string.h>
92 #include <assert.h>
93 #include <sys/file.h>
94
95 #include "util/h/list.h"
96 #include "util/h/stringPool.h"
97
98 int generateXDR;
99 int generatePVM;
100
101 #include "parse.h"
102
103 int yyparse();
104 int emitCode;
105 int emitHeader;
106 char *protoFile;
107 stringPool pool;
108 extern FILE *yyin;
109 int generateTHREAD;
110 char *transportBase;
111 char *serverTypeName;
112 List <typeDefn *> types;
113 typeDefn *foundType;
114 interfaceSpec *currentInterface;
115 typedef struct pvm_args { char *type_name; char *pvm_name; char *arg;} pvm_args;
116 List <pvm_args *> pvm_types;
117 void PVM_map_scalar_includes (const pvm_args *);
118 void PVM_map_array_includes (const pvm_args *);
119 void templatePVMscalar (const pvm_args *);
120 void templatePVMarray (const pvm_args *);
121 static List<char*> client_pass_thru;
122 static List<char*> server_pass_thru;
123
124 void usage(char *name)
125 {
126     printf("%s -xdr | -thread | -pvm [-header | -code] <fileName>\n", name);
127     exit(-1);
128 }
129
130 // generate code to handle igen errors
131 // the code to set the error state will be generated prior to this function being
132 // called
133 void interfaceSpec::genErrHandler(ofstream &ofstr, Boolean client)
134 {
135   if (client)
136     ofstr << " void " << name << "User::handle_error()\n" << "  {\n";
137   else
138     ofstr << " void " << name << "::handle_error()\n" << " {\n";
139
140   ofstr << "       fprintf(stderr, \"Error not handled: err_state = %d\\n\", err_state);\n";
141   ofstr << "       IGEN_ERR_ASSERT;\n";
142   ofstr << "       exit(-1);\n";
143   ofstr << " }\n";
144 }
145
146 // this goes into the dot_c file since all client and server code go into one file
147 // for threads. (an igen artifact).
148 // this generates code for ::mainLoop, including the code for the switch statement
149 // that handles all of the message types.
150 //
151 void interfaceSpec::generateThreadLoop()
152 {
153     List <remoteFunc*> cf;
154
155     unionName = genVariable();
156     dot_c << "union " << unionName << " {\n";
157     for (cf = methods; *cf; cf++)
158       dot_c << "    struct " << (*cf)->structName << " " << (*cf)->name << ";\n";
159
160     dot_c << "};\n\n";
161
162     dot_c << "int " << name << "::mainLoop(void)\n";
163     dot_c << "{\n";
164     dot_c << "  unsigned int __len__;\n";
165     dot_c << "  unsigned int __tag__;\n";
166     dot_c << "  int  __val__ = THR_OKAY;\n";
167     dot_c << "  union " << unionName << " __recvBuffer__;\n";
168     dot_c << "\n";
169     dot_c << "  if (err_state != igen_no_err) return (-1);\n";
170     dot_c << "  __tag__ = MSG_TAG_ANY;\n";
171     dot_c << "  __len__ = sizeof(__recvBuffer__);\n";
172     dot_c << "  if ((requestingThread = msg_recv(&__tag__, &__recvBuffer__, &__len__)) ==\n";
173     dot_c << "            THR_ERR)\n";
174     dot_c << "      {\n";
175     dot_c << "         err_state = igen_read_err;\n";
176     dot_c << "         handle_error();\n";
177     dot_c << "         return (-1);\n";
178     dot_c << "      }\n";
179
180     dot_c << "  switch (__tag__)\n" << "     {\n";
181
182     for (cf = methods; *cf; cf++)
183      (*cf)->genSwitch(FALSE, "-1", dot_c);
184
185     dot_c << "    default:\n";
186     dot_c << "      return(__tag__);\n";
187     dot_c << "  }\n";
188     
189     dot_c << "  if (__val__ != THR_OKAY)\n";
190     dot_c << "    {\n";
191     dot_c << "        err_state = igen_send_err;\n";
192     dot_c << "        handle_error();\n";
193     dot_c << "        return (-1);\n";
194     dot_c << "    }\n";
195
196     dot_c << "  return(0);\n";
197     dot_c << "}\n";
198 }
199
200 // generate the main loop for xdr
201 void interfaceSpec::generateXDRLoop()
202 {
203     List <remoteFunc*> cf;
204
205     genXDRServerVerifyProtocol();
206     genXDRLookForVerify();
207
208     srvr_dot_c << "int " << name  << "::mainLoop(void)\n";
209     srvr_dot_c << "{\n";
210     srvr_dot_c << "    unsigned int __tag__, __status__;\n";
211     srvr_dot_c << "    if (err_state != igen_no_err) return (-1);\n";
212     srvr_dot_c << "    __xdrs__->x_op = XDR_DECODE;\n";
213     srvr_dot_c << "    if (xdrrec_skiprecord(__xdrs__) == FALSE)\n";
214     srvr_dot_c << "        {\n";
215     srvr_dot_c << "             err_state = igen_read_err;\n";
216     srvr_dot_c << "             handle_error();\n";
217     srvr_dot_c << "             return (-1);\n";
218     srvr_dot_c << "        }\n";
219     srvr_dot_c << "    __status__ = xdr_int(__xdrs__, &__tag__);\n";
220     srvr_dot_c << "     if (!__status__)\n";
221     srvr_dot_c << "        {\n";
222     srvr_dot_c << "             err_state = igen_read_err;\n";
223     srvr_dot_c << "             handle_error();\n";
224     srvr_dot_c << "             return(-1);\n";
225     srvr_dot_c << "        }\n";
226     srvr_dot_c << "    switch (__tag__)\n " << "     {\n";
227     
228     // generate the zero RPC that returns interface name & version.
229     srvr_dot_c << "        case 0:\n";
230     srvr_dot_c << "            if (verify_protocol())\n";
231     srvr_dot_c << "                return (-1);\n";
232     srvr_dot_c << "            break;\n";
233
234     for (cf = methods; *cf; cf++)
235       (*cf)->genSwitch(FALSE, "-1", srvr_dot_c);
236
237     srvr_dot_c << "    default:\n";
238     srvr_dot_c << "     return(__tag__);\n";
239     srvr_dot_c << "  }\n";
240     srvr_dot_c << "  return(0);\n";
241     srvr_dot_c << "}\n";
242 }
243
244 // generate the main loop for pvm
245 void interfaceSpec::generatePVMLoop()
246 {
247     List <remoteFunc*> cf;
248
249     srvr_dot_c << "int " << name << "::mainLoop(void)\n";
250     srvr_dot_c << "{\n";
251     srvr_dot_c << "    int __tag__, __bytes__, __msgtag__, __tid__, __bufid__, __other__, __count__;\n";
252     srvr_dot_c << "    struct taskinfo __taskp__, *__tp__;\n";
253     srvr_dot_c << "    __tp__ = &__taskp__;\n";
254     srvr_dot_c << "    if (err_state != igen_no_err) return (-1);\n";
255     srvr_dot_c << "    // this code checks for message \n";
256     srvr_dot_c << "    __other__ = get_other_tid();\n";
257     srvr_dot_c << "    if (__other__ < -1) return -1;\n";
258     srvr_dot_c << "    if (get_error() == -1) return -1;\n";
259     srvr_dot_c << "    if ((__bufid__ = pvm_recv (__other__, -1)) < 0) return -1;\n";
260     srvr_dot_c << "    if (pvm_bufinfo (__bufid__, &__bytes__, &__msgtag__, &__tid__) < 0) return -1;\n";
261     srvr_dot_c << "    switch (__msgtag__)\n" << "     {\n";
262
263     // generate the zero PVM that returns interface name & version.
264     srvr_dot_c << "        case 0:\n";
265     srvr_dot_c << "            char *__ProtocolName__ = \"" << name << "\";\n";
266     srvr_dot_c << "            int __val__;\n";
267     srvr_dot_c << "            __val__ = 0;\n";
268     srvr_dot_c << "            assert(pvm_initsend(0) >= 0);\n";
269     srvr_dot_c << "            pvm_pkstr(__ProtocolName__);\n";
270     srvr_dot_c << "            __val__ = %d;\n", version;
271     srvr_dot_c << "            pvm_pkint(&__val__, 1, 1);\n";
272     srvr_dot_c << "            pvm_send (__tid__, 0);";
273     srvr_dot_c << "            break;\n";
274
275     for (cf = methods; *cf; cf++)
276       (*cf)->genSwitch(FALSE, "-1", srvr_dot_c);
277
278     srvr_dot_c << "    default:\n";
279     srvr_dot_c << "         return(__tag__);\n";
280     srvr_dot_c << "  }\n";
281     srvr_dot_c << "  return(0);\n";
282     srvr_dot_c << "}\n";
283 }
284
285
286 // the include files for *SRVR.C and *.C
287 void interfaceSpec::genIncludes(ofstream &output)
288 {
289     output << "#include <stdio.h>\n";
290     output << "#include <stdlib.h>\n";
291     output << "#include <rpc/types.h>\n";
292     output << "#include <assert.h>\n";
293
294     if (generateTHREAD) {
295         output << "extern \"C\" {\n";
296         output << "#include \"thread/h/thread.h\"\n";
297         output << "#include <errno.h>\n";
298         output << "}\n";
299     }
300     if (generateXDR) {
301         output << "extern \"C\" {\n";
302         output << "#include <rpc/xdr.h>\n";
303         output << "#include <errno.h>\n";
304         output << "}\n";
305     }
306     if (generatePVM) {
307         output << "extern \"C\" {\n";
308         output << "#include <pvm3.h> \n";
309         output << "#include <errno.h>\n";
310         output << "}\n";
311       }
312
313     // printf("#include \"%s\"\n\n", headerFile);
314 }
315
316 // generates code for the server
317 // this code is written into  *.SRVR.C, except for thread code
318 void interfaceSpec::generateServerCode()
319 {
320     List<remoteFunc*> cf;
321
322     if (generateTHREAD) {
323         generateThreadLoop();
324
325         // generate error handler code
326         genErrHandler(dot_c, FALSE);
327     } else if (generateXDR) {
328         genIncludes(srvr_dot_c);
329
330         // include server header
331         srvr_dot_c << "#include \"" << protoFile << "SRVR.h\"\n";
332
333         generateXDRLoop();
334
335         //
336         // generate XDR-only class constructors to allow server to 
337         // start clients
338         //
339         genXDRServerCons(name);
340
341         // generate error handler code
342         genErrHandler(srvr_dot_c, FALSE);
343     } else if (generatePVM) {
344
345         genIncludes(srvr_dot_c);
346
347         // include server header
348         srvr_dot_c << "#include \"" << protoFile << "SRVR.h\"\n";
349         
350         generatePVMLoop();
351
352         //
353         // generate PVM-only class constructors to allow server to 
354         // start clients
355         //
356         genPVMServerCons(name);
357
358         // generate error handler code
359         genErrHandler(srvr_dot_c, FALSE);
360       }
361
362     // generate stubs for upcalls.
363     for (cf = methods; *cf; cf++)
364       (*cf)->genStub(name, TRUE, srvr_dot_c);
365 }
366
367
368 void interfaceSpec::genWaitLoop() 
369 {
370     List<remoteFunc*> cf;
371
372     // generate a loop to wait for a tag, and call upcalls as they arrive.
373     clnt_dot_c << "void " << name << "User::awaitResponce(int __targetTag__) {\n";
374     clnt_dot_c << "    unsigned int __tag__;\n";
375     if (generateTHREAD)
376       {
377         clnt_dot_c << "  union " << unionName << " __recvBuffer__;\n";
378         clnt_dot_c << "  unsigned __len__ = sizeof(__recvBuffer__);\n";
379       }
380     else if (generatePVM)
381       clnt_dot_c << "    int __tid__, __bufid__, __bytes__;\n";
382
383     // make sure it is safe to proceed
384     clnt_dot_c << "  if (err_state != igen_no_err) return;\n";
385
386     clnt_dot_c << "  while (1)\n " << "      {\n";
387     if (generateXDR) {
388         clnt_dot_c << "    __xdrs__->x_op = XDR_DECODE;\n";
389         clnt_dot_c << "    if (xdrrec_skiprecord(__xdrs__) == FALSE)\n";
390         clnt_dot_c << "       {\n";
391         clnt_dot_c << "          err_state = igen_read_err;\n";
392         clnt_dot_c << "          handle_error();\n";
393         clnt_dot_c << "          return;\n";
394         clnt_dot_c << "       }\n";
395         clnt_dot_c << "    if (xdr_int(__xdrs__, &__tag__) == FALSE)\n"
396 ;       clnt_dot_c << "       {\n";
397         clnt_dot_c << "          err_state = igen_decode_err;\n";
398         clnt_dot_c << "          handle_error();\n";
399         clnt_dot_c << "          return;\n";
400         clnt_dot_c << "       }\n";
401     } else if (generatePVM) {
402         clnt_dot_c << "    int __other__ = get_other_tid();\n";
403         clnt_dot_c << "    if (get_error() == -1) abort();\n";
404         clnt_dot_c << "     if (__other__ < 0) abort();\n";
405         clnt_dot_c << "    if ((__bufid__ = pvm_recv (__other__, -1)) < 0)\n";
406         clnt_dot_c << "        abort();\n";
407         clnt_dot_c << "    if (pvm_bufinfo(__bufid__, &__bytes__, (int*) &__tag__, &__tid__) < 0)\n";
408         clnt_dot_c << "       abort();\n";
409     } else if (generateTHREAD) {
410         clnt_dot_c << "  __tag__ = MSG_TAG_ANY;\n";
411         clnt_dot_c << "    if ((requestingThread = msg_recv(&__tag__, (void *) &__recvBuffer__, &__len__)) == THR_ERR)\n";
412         clnt_dot_c << "       {\n";
413         clnt_dot_c << "          err_state = igen_read_err;\n";
414         clnt_dot_c << "          handle_error();\n";
415         clnt_dot_c << "          return;\n";
416         clnt_dot_c << "       }\n";
417         
418     }
419     // look for success error message
420     clnt_dot_c << "    if (__tag__ == __targetTag__) return;\n";
421
422     clnt_dot_c << "    switch (__tag__)\n" << "         {\n";
423     for (cf = methods; *cf; cf++) {
424         (*cf)->genSwitch(TRUE, " ", clnt_dot_c);
425     }
426     clnt_dot_c << "         default: \n";
427     clnt_dot_c << "             err_state = igen_request_err;\n";
428     clnt_dot_c << "             handle_error();\n";
429     clnt_dot_c << "             return;\n";
430     clnt_dot_c << "    }\n";
431     clnt_dot_c << "     if (__targetTag__ == -1) return;\n";
432     clnt_dot_c << "  }\n";
433     clnt_dot_c << "}\n";
434
435     clnt_dot_c << "int " << name << "User::isValidUpCall(int tag) {\n";
436     clnt_dot_c << "    return((tag >= " << baseTag << ") && (tag <= " << boundTag << "));\n",
437     clnt_dot_c << "}\n";
438 }
439
440 void interfaceSpec::genProtoVerify()
441 {
442     // generate stub to verify version.
443     clnt_dot_c << "void " << name << "User::verifyProtocolAndVersion() {\n";
444     clnt_dot_c << "    unsigned int __tag__;\n";
445     clnt_dot_c << "    String proto;\n";
446     clnt_dot_c << "    int version;\n";
447     clnt_dot_c << "    __tag__ = 0;\n";
448     clnt_dot_c << "    __xdrs__->x_op = XDR_ENCODE;\n";
449     clnt_dot_c << "    if (xdr_int(__xdrs__, &__tag__) != TRUE)\n";
450     clnt_dot_c << "       {\n";
451     clnt_dot_c << "          err_state = igen_encode_err;\n";
452     clnt_dot_c << "          handle_error();\n";
453     clnt_dot_c << "          return;\n";
454     clnt_dot_c << "       }\n";
455     clnt_dot_c << "     if (xdrrec_endofrecord(__xdrs__, TRUE) != TRUE)";
456     clnt_dot_c << "       {\n";
457     clnt_dot_c << "          err_state = igen_read_err;\n";
458     clnt_dot_c << "          handle_error();\n";
459     clnt_dot_c << "          return;\n";
460     clnt_dot_c << "       }\n";
461     clnt_dot_c << "    awaitResponce(0);\n";
462     clnt_dot_c << "    if (err_state != igen_no_err)\n";
463     clnt_dot_c << "       {\n";
464     clnt_dot_c << "           printf(\"Protocol verify - no response from server\\n\");\n";
465     clnt_dot_c << "           handle_error();";
466     clnt_dot_c << "           exit(-1);\n";
467     clnt_dot_c << "       }\n";
468     clnt_dot_c << "    __xdrs__->x_op = XDR_DECODE;\n";
469     clnt_dot_c << "    if ((xdr_String(__xdrs__, &(proto)) == FALSE) ||\n";
470     clnt_dot_c << "        (xdr_int(__xdrs__, &(version)) == FALSE))\n";
471     clnt_dot_c << "       {\n";
472     clnt_dot_c << "          err_state = igen_decode_err;\n";
473     clnt_dot_c << "          printf(\"Protocol verify - bad response from server\\n\");\n";
474     clnt_dot_c << "          handle_error();";
475     clnt_dot_c << "          exit(-1);\n";
476     clnt_dot_c << "       }\n";
477     clnt_dot_c << "    if ((version != " << version << ") || (strcmp(proto, \"" << name << "\"))) {\n";
478     clnt_dot_c << "         printf(\"protocol " << name << " version " << version << " expected\\n\");\n", 
479     clnt_dot_c << "         printf(\"protocol %s version %d found\\n\", proto, version);\n";
480     clnt_dot_c << "         exit(-1);\n";
481     clnt_dot_c << "    }\n";
482     clnt_dot_c << "    __xdrs__->x_op = XDR_FREE;\n";
483     clnt_dot_c << "    xdr_String (__xdrs__, &proto);\n";
484     clnt_dot_c << "}\n";
485     clnt_dot_c << "\n\n";
486     clnt_dot_c << name << "User::" << name << "User(int fd, xdrIOFunc r, xdrIOFunc w, int nblock):\n";
487     clnt_dot_c << "RPCUser(igen_no_err),\n";
488     clnt_dot_c << "XDRrpc(fd, r, w, nblock) {\n";
489     clnt_dot_c << "    if (__xdrs__) verifyProtocolAndVersion();\n";
490     clnt_dot_c << "    IGEN_in_call_handler = 0;\n";
491     clnt_dot_c << "}\n";
492     clnt_dot_c << name << "User::" << name << "User(int family, int port, int type, char *machine, xdrIOFunc rf, xdrIOFunc wr, int nblock):\n";
493     clnt_dot_c << "RPCUser(igen_no_err),\n";
494     clnt_dot_c << "XDRrpc(family, port, type, machine, rf, wr, nblock) {\n";
495     clnt_dot_c << "    if (__xdrs__) verifyProtocolAndVersion();\n";
496     clnt_dot_c << "    IGEN_in_call_handler = 0;\n";
497     clnt_dot_c << "}\n";
498     clnt_dot_c << name << "User::" << name << "User(char *m,char *l,char *p,xdrIOFunc r,xdrIOFunc w, char **args, int nblock):\n";
499     clnt_dot_c << "RPCUser(igen_no_err),\n";
500     clnt_dot_c << "    XDRrpc(m, l, p, r, w, args, nblock, __wellKnownPortFd__) {\n";
501     clnt_dot_c << "    if (__xdrs__) verifyProtocolAndVersion();\n";
502     clnt_dot_c << "    IGEN_in_call_handler = 0;\n";
503     clnt_dot_c << "}\n";
504     clnt_dot_c << "\n";
505 }
506
507
508 //
509 // generate code to perform protocol verification 
510 //
511 void interfaceSpec::genProtoVerifyPVM()
512 {
513     // generate stub to verify version.
514     clnt_dot_c << "void " << name << "User::verifyProtocolAndVersion() {\n";
515     clnt_dot_c << "    unsigned int __tag__;\n";
516     clnt_dot_c << "    String proto;\n";
517     clnt_dot_c << "    int version = -1;\n";
518     clnt_dot_c << "    __tag__ = 0;\n";
519     clnt_dot_c << "    // msgtag = 0 --> verify protocol\n";
520     clnt_dot_c << "    assert (pvm_initsend(0) >= 0);\n";
521     clnt_dot_c << "    pvm_send (get_other_tid(), 0);\n";
522     clnt_dot_c << "    awaitResponce(0);\n";
523     clnt_dot_c << "    IGEN_pvm_String (IGEN_PVM_DECODE, &proto);\n";
524     clnt_dot_c << "    pvm_upkint(&(version), 1, 1);\n";
525     clnt_dot_c << "    if ((version != " << version << " ) || (strcmp(proto, \"";
526     clnt_dot_c << name << "\"))) {\n";
527     clnt_dot_c << "        printf(\"protocol " << name << " version " << version;
528     clnt_dot_c << " expected\\n\");\n";
529     clnt_dot_c << "        printf(\"protocol %%s version %%d found\\n\", proto, version);\n";
530     clnt_dot_c << "         pvm_exit(); exit(-1);\n";
531     clnt_dot_c << "    }\n";
532     clnt_dot_c << "    IGEN_pvm_String (IGEN_PVM_FREE, &proto);\n";
533     clnt_dot_c << "}\n";
534     clnt_dot_c << "\n\n";
535     clnt_dot_c << name << "User::" << name << "User(char *w, char *p, char **a, int f):\n";
536     clnt_dot_c << "PVMrpc(w, p, a, f) {\n";
537     clnt_dot_c << "if (get_error() != -1) verifyProtocolAndVersion();\n";
538     clnt_dot_c << "    IGEN_in_call_handler = 0;\n";
539     clnt_dot_c << "}\n";
540     clnt_dot_c << name << "User::" << name << "User(int o):\n";
541     clnt_dot_c << "PVMrpc(o) {\n";
542     clnt_dot_c << "if (get_error() != -1) verifyProtocolAndVersion();\n";
543     clnt_dot_c << "    IGEN_in_call_handler = 0;\n";
544     clnt_dot_c << "}\n";
545
546     clnt_dot_c << name << "User::" << "User():\n";
547     clnt_dot_c << "PVMrpc() {\n";
548     clnt_dot_c << "if (get_error() != -1) verifyProtocolAndVersion();\n";
549     clnt_dot_c << "    IGEN_in_call_handler = 0;\n";
550     clnt_dot_c << "}\n";
551     clnt_dot_c << "\n";
552 }
553
554
555 void interfaceSpec::generateStubs(ofstream &output)
556 {
557     List <remoteFunc*> cf;
558     char className[80];
559
560     sprintf(className, "%sUser", name);
561     for (cf = methods; *cf; cf++) {
562         (*cf)->genStub(className, FALSE, output);
563     }
564 }
565
566 void interfaceSpec::generateClientCode()
567 {
568     if (generateXDR) {
569         genIncludes(clnt_dot_c);
570
571         // include client header
572         clnt_dot_c << "#include \"" << protoFile << "CLNT.h\"\n";
573
574         clnt_dot_c << "int " << name << "User::__wellKnownPortFd__;\n";
575
576         // generate the error handler for the client
577         genErrHandler(clnt_dot_c, TRUE);
578     } else if (generatePVM) {
579         genIncludes(clnt_dot_c);
580
581         // include client header
582         clnt_dot_c << "#include \"" << protoFile << "CLNT.h\"\n";
583
584         // generate the error handler for the client
585         genErrHandler(clnt_dot_c, TRUE);
586       }
587     else {
588       // generate the error handler for the client
589       genErrHandler(dot_c, TRUE);
590     }
591
592     generateStubs(clnt_dot_c);
593
594     if (generateXDR) {
595         genProtoVerify();
596     } else if (generatePVM) {
597         genProtoVerifyPVM();
598       }
599
600     genWaitLoop();
601 }
602
603 void interfaceSpec::generateBundlers()
604 {
605     List <typeDefn*> cs;
606
607     for (cs = types; *cs; cs++) {
608         (*cs)->genBundler();
609     }
610 }
611
612 int main(int argc, char *argv[])
613 {
614     int i;
615     FILE *of;
616     char *temp;
617
618     /* define pre-defined types */
619     (void) new typeDefn("int");
620     (void) new typeDefn("double");
621     (void) new typeDefn("String");
622     (void) new typeDefn("void");
623     (void) new typeDefn("Boolean");
624     (void) new typeDefn("u_int");
625     (void) new typeDefn("float");
626
627     emitCode = 1;
628     emitHeader = 1;
629     for (i=0; i < argc-1; i++) {
630         if (!strcmp("-pvm", argv[i])) {
631             generatePVM = 1;
632             generateXDR = 0;
633             generateTHREAD = 0;
634             serverTypeName = pool.findAndAdd("int");
635             transportBase = "PVMrpc";
636         } if (!strcmp("-xdr", argv[i])) {
637             generatePVM = 0;
638             generateXDR = 1;
639             generateTHREAD = 0;
640             (void) new typeDefn("XDRptr");
641             serverTypeName = pool.findAndAdd("XDRptr");
642             transportBase = "XDRrpc";
643         } if (!strcmp("-thread", argv[i])) {
644             generatePVM = 0;
645             generateXDR = 0;
646             generateTHREAD = 1;
647             serverTypeName = pool.findAndAdd("int");
648             transportBase = "THREADrpc";
649         } else if (!strcmp("-header", argv[i])) {
650             emitCode = 0;
651             emitHeader = 1;
652         } else if (!strcmp("-code", argv[i])) {
653             emitCode = 1;
654             emitHeader = 0;
655         }
656     }
657     if (!emitHeader && !emitCode) {
658         usage(argv[0]);
659     }
660     if (!generatePVM && !generateXDR && !generateTHREAD) {
661         usage(argv[0]);
662     }
663
664     // build the list that contains PVM type information
665     if (generatePVM)
666       buildPVMargs();
667
668     protoFile = argv[argc-1];
669
670     yyin = fopen(protoFile, "r");
671     if (!yyin) {
672         printf("unable to open %s\n", protoFile);
673         exit(-1);
674     }
675
676     // skip to trailing component of file name.
677     temp = strrchr(protoFile, '/');
678     if (temp) protoFile = temp+1;
679
680     temp = strstr(protoFile, ".I");
681     if (!temp) {
682         printf("file names must end in .I\n");
683         exit(-1);
684     }
685     *(temp+1) = '\0';
686
687
688     // open the files for output
689     char *dump_to = new char[strlen(protoFile) + 10];
690     assert(dump_to);
691
692     sprintf(dump_to, "%sh", protoFile);
693     dot_h.open(dump_to, ios::out);
694     assert(dot_h.good());
695
696     sprintf(dump_to, "%sC", protoFile);
697     dot_c.open(dump_to, ios::out);
698     assert(dot_c.good());
699
700     sprintf(dump_to, "%sSRVR.h", protoFile);
701     srvr_dot_h.open(dump_to, ios::out);
702     assert(srvr_dot_h.good());
703
704     sprintf(dump_to, "%sCLNT.h", protoFile);
705     clnt_dot_h.open(dump_to, ios::out);
706     assert(clnt_dot_h.good());
707
708     if (generateXDR || generatePVM)
709       {
710         sprintf(dump_to, "%sSRVR.C", protoFile);
711         srvr_dot_c.open(dump_to, ios::out);
712         assert(srvr_dot_c.good());
713
714         sprintf(dump_to, "%sCLNT.C", protoFile);
715         clnt_dot_c.open(dump_to, ios::out);
716         assert(clnt_dot_c.good());
717       }
718     else
719       {
720         srvr_dot_c = dot_c;
721         clnt_dot_c = dot_c;
722         assert(clnt_dot_c.good());
723         assert(srvr_dot_c.good());
724       }
725
726     if (emitHeader) {
727         char *prefix;
728         int len;
729         len = strlen(protoFile);
730         prefix = new char[len];
731         strncpy (prefix, protoFile, len - 1);
732         prefix[len-1] = '\0';
733
734         dot_h << "#ifndef " << prefix << "BASE_H\n";
735         dot_h << "#define " << prefix << "BASE_H\n";
736         dot_h << "#include \"util/h/rpcUtil.h\"\n";
737
738         if (generatePVM)
739           dot_h << "#include \"util/h/rpcUtilPVM.h\"\n";
740
741         dot_h << "#include <sys/types.h>\n";
742         delete [] prefix;
743
744         dot_h << "#include <assert.h>\n";
745
746         dot_h << "#ifdef IGEN_ERR_ASSERT_ON\n";
747         dot_h << "#ifndef IGEN_ERR_ASSERT\n";
748         dot_h << "#define IGEN_ERR_ASSERT assert(0)\n";
749         dot_h << "#endif\n";
750         dot_h << "#else\n";
751         dot_h << "#define IGEN_ERR_ASSERT\n";
752         dot_h << "#endif\n\n";
753
754         dot_h << "\n // Errors that can occur internal to igen\n";
755         dot_h << "#ifndef _IGEN_ERR_DEF\n";
756         dot_h << "#define _IGEN_ERR_DEF\n";
757         dot_h << "typedef enum e_IGEN_ERR {\n";
758         dot_h << "                       igen_no_err=0,\n";
759         dot_h << "                       igen_encode_err,\n";
760         dot_h << "                       igen_decode_err,\n";
761         dot_h << "                       igen_send_err,\n";
762         dot_h << "                       igen_read_err,\n";
763         dot_h << "                       igen_request_err,\n";
764         dot_h << "                       igen_call_err\n";
765         dot_h << "                       }  IGEN_ERR;\n\n";
766         dot_h << "#endif\n";
767
768         if (generatePVM) 
769           buildPVMincludes();
770       }
771
772     yyparse();
773
774     // this is opened in genClass
775     if (emitHeader) {
776       dot_h << "\n#endif\n";
777       dot_h << endl;
778     }
779
780     if (!currentInterface) {
781         printf("no interface defined\n");
782         exit(-1);
783     }
784
785     if (emitCode) {
786         currentInterface->genIncludes(dot_c);
787         
788         if (generateTHREAD) {
789           dot_c << "#include \"" << protoFile << "SRVR.h\"\n";
790           dot_c << "#include \"" << protoFile << "CLNT.h\"\n";
791         } else {
792           dot_c << "#include \"" << protoFile << "h\"\n";
793         }
794
795         if (generatePVM)
796           buildPVMfilters();
797
798         if (generateXDR || generatePVM) currentInterface->generateBundlers();
799         
800         currentInterface->generateServerCode();
801
802         currentInterface->generateClientCode();
803         fflush(stdout);
804     }
805
806     
807     if (generateTHREAD)
808       {
809       }
810     else
811       {
812         srvr_dot_c.close();
813         clnt_dot_c.close();
814       }
815     exit(0);
816
817     srvr_dot_h.close();
818     clnt_dot_h.close();
819
820     dot_c.close();
821     dot_h.close();
822 }
823
824 char *interfaceSpec::genVariable()
825 {
826     static int count;
827     char *ret;
828
829     ret = (char *) malloc(strlen(name)+10);
830     sprintf(ret, "%s__%d", name, count++);
831     return(ret);
832 }
833
834 int interfaceSpec::getNextTag()
835 {
836     return(++boundTag);
837 }
838
839 // in_client == 1 when client headers are being generated
840 void remoteFunc::genMethodHeader(char *className, int in_client,
841                                  ofstream &current)
842 {
843   int spitOne;
844   List <char *> cl;
845   List<argument*> lp;
846   
847   if (className) {
848     current << retType << " " << className << "::" << name << "(";
849   } else {
850     // figure out if "virtual" should be printed
851     // here is the logic
852     // for the client --> if it is an upcall then print virtual
853     // for the server --> if it is not an upcall the print virtual
854     // for both an additional constraint is that virtual_f must be true
855     if ((((upcall == syncUpcall) || (upcall == asyncUpcall)) && virtual_f && in_client) ||
856         (!in_client && virtual_f && ((upcall == asyncCall) || (upcall == syncCall))))
857       {
858         // print virtual
859         current << "virtual " << retType << " " << name << "(";
860       }
861     else
862       {
863         // don't print virtual
864         current << retType << " " << name << "(";
865       }
866   }
867   for (lp = args, spitOne = 0; *lp; lp++)
868     {
869       if (spitOne) current << ",";
870       spitOne =1;
871       current << (*lp)->type << " ";
872       
873       for (cl = *(*lp)->stars; *cl; cl++)
874         current << "*";
875       current << (*lp)->name;
876     }
877   if (!spitOne) current << "void";
878   current << ")";
879 }
880
881 // forUpcalls == TRUE -> when client code is being generated
882 // client code is being generated to handle upcalls in awaitResponce
883 //
884 // this procedure prints code under 2 circumstances
885 // 1-  (client code) forUpcalls == TRUE, call must be an upcall
886 // 2-  (server code) forUpcalls == FALSE, call must not be an upcall
887 //
888 void remoteFunc::genSwitch(Boolean forUpcalls, char *ret_str, ofstream &output)
889 {
890     int first;
891     List <argument *> ca;
892
893     // return if generating client code, and call is not an upcall
894     if (forUpcalls &&
895         ((upcall == syncCall) || (upcall == asyncCall)))
896       return;
897
898     // return if generating server code, and call is an upcall
899     if (!forUpcalls && (upcall != syncCall) && (upcall != asyncCall))
900       return;
901
902     output << "        case " << spec->getName() << "_" << name << "_REQ:\n";
903
904     // print out the return type
905     if ((generateTHREAD) && (upcall != asyncUpcall) && (upcall != asyncCall))
906       // output << "            int __val__;\n";
907       ;
908
909     output << "           {\n";
910     if (strcmp(retType, "void")) {
911         output << "             " << retType << " __ret__;\n";
912     }
913
914     // print out the local types
915     if (generateXDR) {
916         output << "        // extern xdr_" << retType << "(XDR*, " << retType << "*);\n";
917         if (args.count()) {
918             output << "            " << structName << " __recvBuffer__;\n";
919                 for (ca = args; *ca; ca++) {
920                 output << "            if (xdr_" << (*ca)->type << "(__xdrs__, &__recvBuffer__.";
921                 output << (*ca)->name << ") == FALSE)\n";
922                 output << "              {\n";
923                 output << "                  err_state = igen_decode_err;\n";
924                 output << "                  handle_error();\n";
925                 output << "                  return " << ret_str << ";\n";
926                 output << "              }\n";
927
928             }
929         }
930     } else if (generatePVM) {
931         output << "            extern IGEN_pvm_" << retType << "(IGEN_PVM_FILTER, " << retType << "*);\n";
932         if ((upcall != asyncUpcall) && (upcall != asyncCall))
933           output << "            assert(pvm_initsend(0) >= 0);\n";
934         if (args.count()) {
935           output << "            " << structName << " __recvBuffer__;\n";
936           for (ca = args; *ca; ca++) {
937             output << "            IGEN_pvm_" << (*ca)->type << "(IGEN_PVM_DECODE, &__recvBuffer__." << (*ca)->name << ");\n";
938
939           }
940         }
941       }
942
943     // to determine when sync upcalls cannot be made
944     if (generateXDR &&
945         (upcall == asyncUpcall || upcall == asyncCall))
946       output << "                 IGEN_in_call_handler = 1;\n";
947
948     if (strcmp(retType, "void")) {
949         output << "                __ret__ = " << name << "(";
950     } else {
951         output << "                 " << name <<  "(";
952     }
953
954     for (ca = args, first = 1; *ca; ca++) {
955         if (!first) output << ",";
956         first = 0;
957         if (generateTHREAD) {
958             output << "__recvBuffer__." << name << "." << (*ca)->name;
959         } else if (generateXDR) {
960             output << "__recvBuffer__." << (*ca)->name;
961         } else if (generatePVM) {
962           output << "__recvBuffer__." << (*ca)->name;
963         }
964     }
965     output << ");\n";
966
967     // to determine when sync upcalls cannot be made
968     if (generateXDR &&
969         (upcall == asyncUpcall || upcall == asyncCall))
970       output << "                 IGEN_in_call_handler = 0;\n";
971
972     if (generateTHREAD && (upcall != asyncUpcall) && (upcall != asyncCall)) {
973         if (strcmp(retType, "void")) {
974             output << "               __val__ = msg_send(requestingThread, ";
975             output << spec->getName();
976             output << "_" << name << "_RESP, (void *) &__ret__, sizeof(";
977             output << retType << "));\n";
978         } else {
979           output << "                 __val__ = msg_send(requestingThread, ";
980           output << spec->getName();
981           output << "_" << name << "_RESP, NULL, 0);\n";
982         }
983         // output << "         if (__val__ != THR_OKAY)\n";
984         // output << "            {\n";
985         // output << "                 err_state = igen_send_error;\n";
986         // output << "                 handle_error();\n";
987         // output << "                 return " << ret_str << ";\n";
988         // output << "            }\n";
989     } else if (generateXDR && (upcall != asyncUpcall) && (upcall != asyncCall)) {
990         output << "                 __xdrs__->x_op = XDR_ENCODE;\n";
991         output << "                 __tag__ = " << spec->getName() << "_" << name;
992         output << "_RESP;\n";
993         output << "                if (xdr_int(__xdrs__, &__tag__) == FALSE)\n";
994         output << "                    {\n";
995         output << "                      err_state = igen_encode_err;\n";
996         output << "                      handle_error();\n";
997         output << "                      return " << ret_str << ";\n";
998         output << "                    }\n";
999         if (strcmp(retType, "void")) {
1000             output << "                   if (xdr_" << retType << "(__xdrs__,&__ret__) == FALSE)\n";
1001             output << "                   {\n";
1002             output << "                      err_state = igen_encode_err;\n";
1003             output << "                      handle_error();\n";
1004             output << "                      return " << ret_str << ";\n";
1005             output << "                   }\n";
1006         }
1007         output << "         if (xdrrec_endofrecord(__xdrs__, TRUE) == FALSE)\n";
1008         output << "            {\n";
1009         output << "               err_state = igen_send_err;\n";
1010         output << "               handle_error();\n";
1011         output << "               return " << ret_str << ";\n";
1012         output << "            }\n";
1013     } else if (generatePVM && (upcall != asyncUpcall) && (upcall != asyncCall)) {
1014         output << "            __tag__ = " << spec->getName() << "_" << name << "_RESP;\n";
1015         if (strcmp(retType, "void")) {
1016             output << "            IGEN_pvm_" << retType << " (IGEN_PVM_ENCODE,&__ret__);\n";
1017           }
1018         output << "            assert (pvm_send (__tid__, __tag__) >= 0);\n";
1019       }
1020
1021     // free allocated memory
1022     if (generateTHREAD)
1023       {
1024       }
1025     else if (generateXDR)
1026       {
1027         output << "            __xdrs__->x_op = XDR_FREE;\n";
1028         if (args.count())
1029           {
1030             for (ca = args; *ca; ca++)
1031               {
1032                 // only if Array or string or user defined
1033                 if ((*ca)->mallocs)
1034                   output << "            xdr_" << (*ca)->type << "(__xdrs__, &__recvBuffer__." << (*ca)->name<< ");\n";
1035               }
1036           }
1037         if (retStructs)
1038           output << "            xdr_" << retType << "(__xdrs__, &__ret__);\n";
1039       }
1040     else if (generatePVM)
1041       {
1042         if (args.count())
1043           {
1044             for (ca = args; *ca; ca++)
1045               {
1046                 // only if Array or string 
1047                 if ((*ca)->mallocs)
1048                   output << "            IGEN_pvm_" << (*ca)->type;
1049                   output << "(IGEN_PVM_FREE, &__recvBuffer__." << (*ca)->name << ");\n";
1050               }
1051           }
1052         if (retStructs)
1053           output << "            IGEN_pvm_" << retType << "(IGEN_PVM_FREE, &__ret__);\n";
1054       }
1055
1056     output << "           }\n              break;\n\n";
1057 }
1058  
1059
1060 // generates the stub code for the client or the server
1061 //
1062 void remoteFunc::genThreadStub(char *className, ofstream &output)
1063 {
1064     List<argument*> lp;
1065     char *retVar = 0;
1066     char *structUseName = spec->genVariable();
1067
1068     genMethodHeader(className, 0, output);
1069     output << " {\n";
1070
1071     if (*args)
1072       output << "    struct " << structName << " " << structUseName << ";\n";
1073     if ((upcall != asyncUpcall) && (upcall != asyncCall))
1074       output << "    unsigned int __tag__;\n";
1075     if (strcmp(retType, "void"))
1076       output << "    unsigned int __len__;\n";
1077     output << "    int __val__;\n";
1078     if (strcmp(retType, "void")) {
1079       retVar = spec->genVariable();
1080       output << "    " << retType << " " << retVar << ";\n";
1081     }
1082     else
1083       retVar = strdup(" ");
1084
1085     output << "    if (err_state != igen_no_err)\n";
1086     output << "      {\n";
1087     output << "        IGEN_ERR_ASSERT;\n";
1088     output << "        return " << retVar << ";\n";
1089     output << "      }\n";
1090
1091     for (lp = args; *lp; lp++) {
1092         output << "    " << structUseName << "." << (*lp)->name << " = ";
1093         output << (*lp)->name << ";  \n";
1094     }
1095     if (*args) {
1096         output << "    __val__ = msg_send(tid, " << spec->getName() << "_";
1097         output << name << "_REQ, (void *) &";
1098         output << structUseName << ", sizeof(" << structUseName << "));\n";
1099     } else {
1100         output << "    __val__ = msg_send(tid, " << spec->getName() << "_";
1101         output << name <<  "_REQ, NULL, 0); \n";
1102     }
1103     output << "    if (__val__ != THR_OKAY)\n";
1104     output << "      {\n";
1105     output << "          err_state = igen_send_err;\n";
1106     output << "          handle_error();\n";
1107     output << "          return " << retVar << " ;\n";
1108     output << "      }\n";
1109     if ((upcall != asyncUpcall) && (upcall != asyncCall)) {
1110         output << "    __tag__ = " << spec->getName() << "_" << name << "_RESP;\n";
1111         if (strcmp(retType, "void")) {
1112             output << "    __len__ = sizeof(" << retVar << ");\n";
1113             output << "    if (msg_recv(&__tag__, (void *) &" << retVar;
1114             output << ", &__len__)\n        == THR_ERR) \n";
1115             output << "      {\n";
1116             output << "          err_state = igen_read_err;\n";
1117             output << "          handle_error();\n";
1118             output << "          return " << retVar << " ;\n";
1119             output << "      }\n";
1120             output << "    if (__len__ != sizeof(" << retVar << "))\n";
1121             output << "      {\n";
1122             output << "          err_state = igen_read_err;\n";
1123             output << "          handle_error();\n";
1124             output << "          return " << retVar << " ;\n";
1125             output << "      }\n";
1126         } else {
1127             output << "    if (msg_recv(&__tag__, NULL, 0) == THR_ERR)\n";
1128             output << "      {\n";
1129             output << "          err_state = igen_read_err;\n";
1130             output << "          handle_error();\n";
1131             output << "          return " << retVar << " ;\n";
1132             output << "      }\n";
1133
1134         }
1135         output << "    if (__tag__ != " << spec->getName() << "_" << name;
1136         output << "_RESP)\n";
1137         output << "      {\n";
1138         output << "          err_state = igen_read_err;\n";
1139         output << "          handle_error();\n";
1140         output << "          return " << retVar << " ;\n";
1141         output << "      }\n";
1142
1143         output << "    return " << retVar << " ;\n";
1144     }
1145     output << "}\n\n";
1146 }
1147
1148 void remoteFunc::genXDRStub(char *className, ofstream &output)
1149 {
1150   List<argument*> lp;
1151   char *retVar = 0;
1152   int retS = 0;
1153
1154   genMethodHeader(className, 0, output);
1155   output << "\n {\n";
1156
1157   output << "    unsigned int __tag__;\n";
1158   if (strcmp(retType, "void"))
1159     {
1160       retVar = spec->genVariable();
1161       output << "    " << retType << " " << retVar << ";\n";
1162       retS = 1;
1163     }
1164   else
1165     retVar = strdup(" ");
1166
1167   output << "    if (err_state != igen_no_err)\n";
1168   output << "      {\n";
1169   output << "        IGEN_ERR_ASSERT;\n";
1170   output << "        return " << retVar << ";\n";
1171   output << "      }\n";
1172
1173   if ((upcall == syncUpcall) || (upcall == syncCall))
1174     {
1175       output << "       if (IGEN_in_call_handler)\n";
1176       output << "         {\n";
1177       output << "            fprintf(stderr, \"cannot do sync call when in async call handler\\n\");\n";
1178       output << "            IGEN_ERR_ASSERT;\n";
1179       output << "            err_state = igen_call_err;\n";
1180       output << "            return " << retVar << ";\n";
1181       output << "         }\n";
1182     }
1183
1184   // check to see protocol verify has been done.
1185   if ((upcall != syncCall) && (upcall != asyncCall)) {
1186     output << "    if (!__versionVerifyDone__)\n";
1187     output << "       {\n";
1188     output << "    // handle error is called for errors\n";
1189     output << "          if (!look_for_verify() && !verify_protocol())\n";
1190     output << "              __versionVerifyDone__ = TRUE;\n";
1191     output << "          else\n";
1192     output << "              return " << retVar << " ;\n";
1193     output << "       }\n";
1194   }
1195   output << "    __tag__ = " << spec->getName() << "_" << name << "_REQ;\n";
1196   output << "    __xdrs__->x_op = XDR_ENCODE;\n";
1197
1198   // the error check depends on short circuit boolean expression evaluation!
1199   output << "    if ((xdr_int(__xdrs__, &__tag__) != TRUE)\n";
1200   for (lp = args; *lp; lp++)
1201     {
1202       output << "      ||  (xdr_" << (*lp)->type << "(__xdrs__, &";
1203       output << (*lp)->name << ") != TRUE)\n";
1204     }
1205   output << " )\n";
1206   output << "         {\n";
1207   output << "             err_state = igen_encode_err;\n";
1208   output << "             handle_error();\n";
1209   output << "             return " << retVar << " ;\n";
1210   output << "         }\n";
1211   output << "       if(!xdrrec_endofrecord(__xdrs__, TRUE))\n";
1212   output << "         {\n";
1213   output << "             err_state = igen_send_err;\n";
1214   output << "             handle_error();\n";
1215   output << "             return " << retVar << " ;\n";
1216   output << "         }\n";
1217
1218   if ((upcall != asyncUpcall) && (upcall != asyncCall))
1219     {
1220       if (upcall == syncCall)
1221         {
1222           output << "    awaitResponce(" << spec->getName() << "_";
1223           output << name << "_RESP);\n";
1224         }
1225       else if (upcall == syncUpcall)
1226         {
1227           output << " int res;\n";
1228           output << " while (!(res = mainLoop())) ;\n";
1229           output << " if (res != " << spec->getName() << "_" << name << "_RESP)\n";
1230           output << "        { err_state = igen_request_err; handle_error(); return ";
1231           if (retS)
1232             output << "(" << retVar << ");}\n";
1233           else
1234             output << ";}\n";
1235         }
1236       output << "    if (err_state != igen_no_err)\n";
1237       output << "    return " << retVar << ";\n";
1238
1239       if (strcmp(retType, "void"))
1240         {
1241           output << "    __xdrs__->x_op = XDR_DECODE;\n";
1242           output << "    if (xdr_" << retType << "(__xdrs__, &(";
1243           output << retVar << ")) == FALSE)\n";
1244           output << "         {\n";
1245           output << "             err_state = igen_decode_err;\n";
1246           output << "             handle_error();\n";
1247           output << "             return " << retVar << " ;\n";
1248           output << "         }\n";
1249           
1250           output << "    return(" << retVar << ");\n";
1251         }
1252     }
1253   output << "}\n\n";
1254 }
1255
1256 void remoteFunc::genPVMStub(char *className, ofstream &output)
1257 {
1258     List<argument*> lp;
1259     char *retVar = spec->genVariable();
1260
1261     genMethodHeader(className, 0, output);
1262     output << " {\n";
1263
1264     output << "    unsigned int __tag__;\n";
1265     if (strcmp(retType, "void")) {
1266         output << "    " << retType << " " << retVar << ";\n";
1267     }
1268
1269     output << "    if (err_state != igen_no_err)\n";
1270     output << "      {\n";
1271     output << "        IGEN_ERR_ASSERT;\n";
1272     output << "        return " << retVar << ";\n";
1273     output << "      }\n";
1274
1275     output << "    __tag__ = " << spec->getName() << "_" << name << "_REQ;\n";
1276     output << "    assert(pvm_initsend(0) >= 0);\n";
1277     for (lp = args; *lp; lp++) {
1278         output << "    IGEN_pvm_" << (*lp)->type << " (IGEN_PVM_ENCODE, &" << (*lp)->name << ");\n";
1279     }
1280     output << "    pvm_send ( get_other_tid(), __tag__);\n";
1281     if (upcall != asyncUpcall)
1282       {
1283         if (upcall == syncCall)
1284           {
1285             output << "    awaitResponce(" << spec->getName() << "_" << name << "_RESP);\n";
1286           }
1287         else if (upcall == syncUpcall)
1288           {
1289             output << "    if (pvm_recv(-1, " << spec->getName() << "_" << name << "_RESP) < 0) abort();\n";
1290           }
1291         if (strcmp(retType, "void"))
1292           {
1293             output << "    IGEN_pvm_" << retType << "(IGEN_PVM_DECODE, &(" << retVar << ")); \n";
1294             output << "    return(" << retVar << ");\n";
1295           }
1296       }
1297     output << "}\n\n";
1298 }
1299
1300 void remoteFunc::genStub(char *className, Boolean forUpcalls, ofstream &output)
1301 {
1302     if (forUpcalls && ((upcall == syncCall) || (upcall == asyncCall))) return;
1303     if (!forUpcalls && (upcall != syncCall) && (upcall != asyncCall)) return;
1304
1305     output << "\n";
1306
1307     if (generateXDR) {
1308         genXDRStub(className, output);
1309     } else if (generateTHREAD) {
1310         genThreadStub(className, output);
1311     } else if (generatePVM) {
1312         genPVMStub(className, output);
1313     }
1314 }
1315
1316 void remoteFunc::genHeader()
1317 {
1318     List<char *> cl;
1319     List<argument*> lp;
1320
1321     dot_h << "struct " << structName << " {\n";
1322     for (lp = args; *lp; lp++) {
1323         dot_h << "    " << (*lp)->type << " ";
1324         for (cl = *(*lp)->stars; *cl; cl++)
1325           dot_h << "*";
1326         dot_h << (*lp)->name;
1327         dot_h << ";\n";
1328     }
1329     dot_h << "};\n\n";
1330
1331     dot_h << "#define " << spec->getName() << "_" << name << "_REQ " << spec->getNextTag() << "\n";
1332     dot_h << "#define " << spec->getName() << "_" << name << "_RESP " << spec->getNextTag() << "\n";
1333 }
1334
1335 void typeDefn::genHeader()
1336 {
1337     List<field*> fp;
1338
1339     dot_h << "#ifndef " << name << "_TYPE\n";
1340     dot_h << "#define " << name << "_TYPE\n";
1341     dot_h << "class " << name << " {  \npublic:\n";
1342     if (arrayType) {
1343         dot_h << "    int count;\n";
1344         dot_h << "    " << type << "* data;\n";
1345     } else {
1346         for (fp = fields; *fp; fp++) {
1347             (*fp)->genHeader(dot_h);
1348         }
1349     }
1350     dot_h << "};\n\n";
1351     dot_h << "#endif\n";
1352
1353     if (generateXDR) {
1354         if (userDefined) dot_h << "extern xdr_" << name << "(XDR*, " << name << "*);\n";
1355     } else if (generatePVM) {
1356         if (userDefined) dot_h << "extern IGEN_pvm_" << name << "(IGEN_PVM_FILTER, " << name << "*);\n";
1357     }
1358 }
1359
1360 //
1361 // this is only called if generatePVM or generateXDR is TRUE
1362 // this is not called for generateTHREAD since no bundling is done since everything
1363 // exists in the same address space
1364 // builds data bundlers - code that bundles user defined structures for the transport
1365 // note - the basic filters {string, int, ...} are taken care of elsewhere
1366 //
1367 //
1368 // how are bundlers built
1369 //     each bundler has an if branch and an else branch.  The if branch is taken if the
1370 //     request is to free memory, otherwise the else branch is taken.  If the type of the
1371 //     bundler is an array of <x>, each element of the array must have its bundler called
1372 //     in the if branch.  If the bundler is not an array of some type, but is a structure,
1373 //     with fields, the bundlers for each field is called.
1374 //
1375 void typeDefn::genBundler()
1376 {
1377     List<field*> fp;
1378
1379
1380     if (!userDefined) return;
1381
1382     // the code for the if branch - taken to free memory
1383
1384     if (generateXDR) {
1385       // build the handlers for xdr
1386       dot_c << "bool_t xdr_" << name << "(XDR *__xdrs__, " << name << " *__ptr__) {\n";
1387       dot_c << "    if (__xdrs__->x_op == XDR_FREE) {\n";
1388
1389       // note - a user defined type contains an array of other types, each element in the
1390       // array must be freed
1391       if (arrayType)
1392         {
1393           assert (foundType = types.find(type));
1394           if (foundType->userDefined == TRUE)
1395             {
1396               dot_c << "        int i;\n";
1397               dot_c << "        for (i=0; i<__ptr__->count; ++i)\n";
1398               dot_c << "            if (!xdr_" << type << "(__xdrs__, &(__ptr__->data[i])))\n";
1399               dot_c << "              return FALSE;\n";
1400             }
1401           // free the memory used for this structure
1402           dot_c << "        free ((char*) __ptr__->data);\n";
1403           dot_c << "        __ptr__->data = 0;\n";
1404           dot_c << "        __ptr__->count = 0;\n";
1405         }
1406
1407       else for (fp = fields; *fp; fp++) {
1408         // xdr - non-array types
1409         // call the bundler for each element of this user defined type
1410         // don't call for non-user defined types such as {int, char, bool}
1411         // since those will not have had memory allocated for them
1412         foundType = types.find((*fp)->getType());
1413         assert (foundType);
1414         if (foundType->userDefined ||
1415             foundType->arrayType ||
1416             !(strcmp("String", foundType->name)))
1417           (*fp)->genBundler(dot_c);
1418       }
1419     } else if (generatePVM) {
1420       // build the handlers for PVM
1421       dot_c << "bool_t IGEN_pvm_" << name << "(IGEN_PVM_FILTER __dir__, " << name << " *__ptr__) {\n";
1422       dot_c << "    if (__dir__ == IGEN_PVM_FREE) {\n";
1423
1424       // free the array of user defined types
1425       // this calls the bundlers
1426       if (arrayType)
1427         {
1428           assert (foundType = types.find(type));
1429           if (foundType->userDefined == TRUE)
1430             {
1431               dot_c << "        int i;\n";
1432               dot_c << "        for (i=0; i<__ptr__->count; ++i)\n";
1433               dot_c << "            if (!IGEN_pvm_" << type << "(__dir__, &(__ptr__->data[i])))\n";
1434               dot_c << "              return FALSE;\n";
1435             }
1436           dot_c << "        free ((char*) __ptr__->data);\n";
1437           dot_c << "        __ptr__->data = 0;\n";
1438           dot_c << "        __ptr__->count = 0;\n";
1439         }
1440       else for (fp = fields; *fp; fp++) {
1441         foundType = types.find((*fp)->getType());
1442         assert (foundType);
1443         if (foundType->userDefined ||
1444             foundType->arrayType ||
1445             !(strcmp("String", foundType->name)))
1446           (*fp)->genBundler(dot_c);
1447       }
1448     }
1449     dot_c << "    } else {\n";
1450
1451     // the code for the else branch - taken to encode or decode 
1452
1453     if (arrayType) {
1454       if (generateXDR) {
1455         dot_c << "if (__xdrs__->x_op == XDR_DECODE) __ptr__->data = NULL;\n";
1456         dot_c << "    if (xdr_array(__xdrs__, &(__ptr__->data), &__ptr__->count, ~0, sizeof(";
1457         dot_c << type << "), xdr_" << type << ") == FALSE)\n";
1458         dot_c << "      return FALSE;\n";
1459       } else if (generatePVM) {
1460         dot_c << "    IGEN_pvm_Array_of_" << type << "(__dir__, &(__ptr__->data),&(__ptr__->count));\n";
1461       }
1462     } else {
1463         for (fp = fields; *fp; fp++)
1464           (*fp)->genBundler(dot_c);
1465       }
1466     dot_c << "    }\n";
1467     dot_c << "    return(TRUE);\n";
1468     dot_c << "}\n\n";
1469 }
1470
1471
1472 char *findAndAddArrayType(char *name) 
1473 {
1474     typeDefn *s;
1475     char temp[80];
1476     char *arrayTypeName;
1477
1478     // now find the associated array type.
1479     sprintf(temp, "%s_Array", name);
1480     arrayTypeName = pool.findAndAdd(temp);
1481     if (!types.find(arrayTypeName)) {
1482         s = new typeDefn(arrayTypeName, name);
1483         s->genHeader();
1484     }
1485     return arrayTypeName;
1486 }
1487
1488 void
1489 print_pass_thru_clnt (const char *the_string)
1490 {
1491   clnt_dot_h << "       " << the_string << ";\n";
1492 }
1493
1494 void
1495 print_pass_thru_srvr (const char *the_string)
1496 {
1497   srvr_dot_h << "       " << the_string << ";\n";
1498 }
1499
1500 // changed to print to separate files, one include for the server, and
1501 // one for the client 
1502 // g++ was attempting to link the virtual functions for the client in the
1503 // server code
1504 // 
1505 void interfaceSpec::genClass()
1506 {
1507     List <remoteFunc *> curr; 
1508
1509
1510
1511     clnt_dot_h <<  "#ifndef _" << name << "CLNT_H\n";
1512     clnt_dot_h <<  "#define _" << name << "CLNT_H\n";
1513     clnt_dot_h <<  "#include \"" << protoFile << "h\"\n\n";
1514     clnt_dot_h <<  "class " << name << "User: public RPCUser, public " << transportBase << " {\n";
1515     clnt_dot_h <<  "  public:\n";
1516     client_pass_thru.map(&print_pass_thru_clnt);
1517     clnt_dot_h <<  "    static int __wellKnownPortFd__;\n";
1518
1519     if (generateXDR) {
1520       clnt_dot_h <<  "    virtual void verifyProtocolAndVersion();\n";
1521       clnt_dot_h <<  "    " << name << "User(int fd, xdrIOFunc r, xdrIOFunc w, int nblock=0);\n";
1522       clnt_dot_h <<  "    " << name << "User(int family, int port, int type, char *host, xdrIOFunc rf, xdrIOFunc wf, int nblock=0);\n";
1523       clnt_dot_h <<  "    " << name << "User(char *machine, char *login, char *program, xdrIOFunc r, xdrIOFunc w, char **args=0, int nblock=0);\n";
1524     } else if (generatePVM) {
1525       clnt_dot_h <<  "    virtual void verifyProtocolAndVersion();\n";
1526       clnt_dot_h <<  "    " << name << "User(char *w, char *p, char **a, int f);\n";
1527       clnt_dot_h <<  "    " << name << "User(int other);\n";
1528       clnt_dot_h <<  "    " << name << "User();\n";
1529     } else if (generateTHREAD) {
1530         clnt_dot_h << "    " << name << "User(int tid): THREADrpc(tid), RPCUser(igen_no_err) {}\n";
1531     }
1532       
1533     clnt_dot_h << "    void awaitResponce(int);\n";
1534     clnt_dot_h << "    int isValidUpCall(int);\n";
1535     
1536     for (curr = methods; *curr; curr++) {
1537       clnt_dot_h << "    ";
1538         (*curr)->genMethodHeader(NULL, 1, clnt_dot_h);
1539         clnt_dot_h << ";\n";
1540     }
1541     clnt_dot_h << " protected:\n";
1542     clnt_dot_h << "   virtual void handle_error();\n";
1543     clnt_dot_h << "   int IGEN_in_call_handler;\n";
1544     clnt_dot_h << "};\n";
1545     clnt_dot_h << "#endif\n";
1546
1547     srvr_dot_h <<  "#ifndef _" << name << "SRVR_H\n";
1548     srvr_dot_h <<  "#define _" << name << "SRVR_H\n";
1549     srvr_dot_h <<  "#include \"" << protoFile << "h\"\n\n";
1550     srvr_dot_h << "class " << name << ": protected RPCServer, public " << transportBase << " {\n";
1551     srvr_dot_h << "  public:\n";
1552
1553     server_pass_thru.map(&print_pass_thru_srvr);
1554
1555     if (generatePVM) {
1556       srvr_dot_h << "   " << name << "();\n";
1557       srvr_dot_h << "   " << name << "(int o);\n";
1558       srvr_dot_h << "   " << name << "(char *w, char *p, char **a, int f);\n";
1559     }
1560     else if (generateXDR) {
1561       srvr_dot_h << "   " << name << "(int family, int port, int type, char *host, xdrIOFunc rf, xdrIOFunc wf, int nblock=0);\n";
1562       srvr_dot_h << "   " << name << "(int fd, xdrIOFunc r, xdrIOFunc w, int nblock=0);\n";
1563       srvr_dot_h << "   " << name << "(char *m, char *l, char *p, xdrIOFunc r, xdrIOFunc w, char **args=0, int nblock=0);\n";
1564       srvr_dot_h << "    verify_protocol();\n";
1565       srvr_dot_h << "    look_for_verify();\n";
1566     } else if (generateTHREAD) {
1567         srvr_dot_h << "    " << name << "(int tid): THREADrpc(tid), RPCServer(igen_no_err) {}\n";
1568       }
1569     srvr_dot_h << "    mainLoop(void);\n";
1570
1571     for (curr = methods; *curr; curr++) {
1572         srvr_dot_h << "    ";
1573         (*curr)->genMethodHeader(NULL, 0, srvr_dot_h);
1574         srvr_dot_h << ";\n";
1575       }
1576     if (generatePVM || generateXDR) {
1577       srvr_dot_h << "    void set_versionVerifyDone(bool_t val)\n";
1578       srvr_dot_h << "           { __versionVerifyDone__ = val;}\n";
1579     }
1580     srvr_dot_h << " protected:\n";
1581     srvr_dot_h << "   virtual void handle_error();\n";
1582     srvr_dot_h << "   bool_t __versionVerifyDone__;\n";
1583     srvr_dot_h << "   int IGEN_in_call_handler;\n";
1584     srvr_dot_h << "};\n\n";
1585     srvr_dot_h << "#endif\n";
1586 }
1587
1588 //
1589 // builds filters for PVM to go into *.C
1590 // these filters are similar to the xdr_TYPE {TYPE = int, char...}
1591 // these filters are meant to be bidirectional
1592 // these filters will malloc for arrays and strings
1593 //
1594 void
1595 buildPVMfilters()
1596 {
1597   dot_c << "bool_t IGEN_pvm_String (IGEN_PVM_FILTER direction, String *data) {\n";
1598   dot_c << "   int buf_id, bytes, msgtag, tid;\n";
1599   dot_c << "   assert(data);\n";
1600   dot_c << "   switch (direction) \n";
1601   dot_c << "       {\n";
1602   dot_c << "         case IGEN_PVM_DECODE:\n";
1603   dot_c << "             buf_id = pvm_getrbuf();\n";
1604   dot_c << "             if (buf_id == 0) return (FALSE);\n";
1605   dot_c << "             if (pvm_bufinfo(buf_id, &bytes, &msgtag, &tid) < 0) return(FALSE);\n";
1606   dot_c << "             *data = (String) new char[bytes+1];\n";
1607   dot_c << "             if (!(*data)) return (FALSE);\n";
1608   dot_c << "             data[bytes] = '\\0';\n";
1609   dot_c << "             if (pvm_upkstr(*data) < 0) return (FALSE);\n";
1610   dot_c << "             break;\n";
1611   dot_c << "         case IGEN_PVM_ENCODE:\n";
1612   dot_c << "             if (pvm_pkstr (*data) < 0) return (FALSE);\n";
1613   dot_c << "             break;\n";
1614   dot_c << "         case IGEN_PVM_FREE:\n";
1615   dot_c << "             delete [] (*data);\n";
1616   dot_c << "             *data = 0;\n";
1617   dot_c << "             break;\n";
1618   dot_c << "         default:\n";
1619   dot_c << "             assert(0);\n";
1620   dot_c << "        }\n";
1621   dot_c << "   return(TRUE);\n}\n";
1622
1623   pvm_types.map(&templatePVMscalar);
1624   pvm_types.map(&templatePVMarray);
1625 }
1626
1627
1628 void
1629 templatePVMscalar (const pvm_args *the_arg)
1630 {
1631   if (!the_arg || !(the_arg->type_name) || !(the_arg->pvm_name)) return;
1632   dot_c << "\n";
1633   dot_c << "bool_t IGEN_pvm_" << the_arg->type_name << " (IGEN_PVM_FILTER direction,";
1634   dot_c << the_arg->type_name << " *data) {\n";
1635   dot_c << "   assert(data);\n";
1636   dot_c << "   switch (direction)\n";
1637   dot_c << "     {\n";
1638   dot_c << "        case IGEN_PVM_DECODE:\n";
1639   dot_c << "            if (pvm_upk" << the_arg->pvm_name << " (data, 1, 1) < 0)\n";
1640   dot_c << "                return (FALSE);\n";
1641   dot_c << "            break;\n";
1642   dot_c << "        case IGEN_PVM_ENCODE:\n";
1643   dot_c << "            if (pvm_pk" << the_arg->pvm_name << " (data, 1, 1) < 0)\n";
1644   dot_c << "                return (FALSE);\n";
1645   dot_c << "            break;\n";
1646   dot_c << "        case IGEN_PVM_FREE:\n";
1647   dot_c << "            break;\n";
1648   dot_c << "        default:\n";
1649   dot_c << "            assert(0);\n";
1650   dot_c << "     }\n";
1651   dot_c << "   return(TRUE);\n";
1652   dot_c << "}\n\n";
1653 }
1654
1655 void
1656 templatePVMarray (const pvm_args * the_arg)
1657 {
1658   if (!the_arg ||
1659       !(the_arg->type_name) ||
1660       !(the_arg->pvm_name) ||
1661       !(the_arg->arg)) 
1662     return;
1663   dot_c << "bool_t IGEN_pvm_Array_of_" << the_arg->type_name << " (IGEN_PVM_FILTER dir, ";
1664   dot_c << the_arg->type_name << " **data, int *count) {\n";
1665   dot_c << "   int bytes, msgtag, tid;\n";
1666   dot_c << "   switch (dir)\n";
1667   dot_c << "     {\n";
1668   dot_c << "        case IGEN_PVM_DECODE:\n";
1669   dot_c << "           int buf_id = pvm_getrbuf();\n";
1670   dot_c << "           if (buf_id == 0) return (FALSE);\n";
1671   dot_c << "           if (pvm_bufinfo(buf_id, &bytes, &msgtag, &tid) < 0) return(FALSE);\n";
1672   dot_c << "           *count = bytes " << the_arg->arg << ";\n";
1673   dot_c << "           *data = (" << the_arg->type_name << " *) new char[*count];\n";
1674   dot_c << "           if (!(*data)) return (FALSE);\n";
1675   dot_c << "           if (pvm_upk" << the_arg->pvm_name << " (*data, *count, 1) < 0) return (FALSE);\n";
1676   dot_c << "           break;\n";
1677   dot_c << "        case IGEN_PVM_ENCODE:\n";
1678   dot_c << "           if (pvm_pk" << the_arg->pvm_name << " (*data, *count, 1) < 0) return (FALSE);\n";
1679   dot_c << "           break;\n";
1680   dot_c << "        case IGEN_PVM_FREE:\n";
1681   dot_c << "           delete [] (*data);\n";
1682   dot_c << "           break;\n";
1683   dot_c << "        default:\n";
1684   dot_c << "           assert(0);\n";
1685   dot_c << "     }\n";
1686   dot_c << "   return(TRUE);\n";
1687   dot_c << "}\n\n";
1688 }
1689
1690
1691 //
1692 // generate the pvm specific includes for _.h
1693 //
1694 void
1695 buildPVMincludes()
1696 {
1697   dot_h << "enum IGEN_PVM_FILTER {IGEN_PVM_ENCODE, IGEN_PVM_DECODE, IGEN_PVM_FREE};\n\n";
1698   dot_h << "bool_t IGEN_pvm_String (IGEN_PVM_FILTER direction, String *data);\n";
1699   pvm_types.map(&PVM_map_scalar_includes);
1700   pvm_types.map(&PVM_map_array_includes);
1701 }
1702
1703 // the constructor for the pvm constructor class
1704 void genPVMServerCons(char *name)
1705 {
1706   srvr_dot_c << name << "::" << name << " (char *w, char *p, char **a, int f):\n";
1707   srvr_dot_c << "PVMrpc(w, p, a, f) {\n";
1708   srvr_dot_c << "    __versionVerifyDone__ = FALSE; IGEN_in_call_handler = 0;}\n";
1709   srvr_dot_c << name << "::" << name << " (int o):\n";
1710   srvr_dot_c << "PVMrpc(o) {\n";
1711   srvr_dot_c << "    __versionVerifyDone__ = FALSE; IGEN_in_call_handler = 0;}\n";
1712   srvr_dot_c << name << "::" << name << " ():\n";
1713   srvr_dot_c << "PVMrpc() {\n";
1714   srvr_dot_c << "    __versionVerifyDone__ = FALSE; IGEN_in_call_handler = 0;}\n";
1715 }
1716
1717 // the constructor for the xdr server class
1718 void genXDRServerCons(char *name)
1719 {
1720   srvr_dot_c << name << "::" << name << "(int family, int port, int type, char *host, xdrIOFunc rf, xdrIOFunc wf, int nblock):\n";
1721   srvr_dot_c << "XDRrpc(family, port, type, host, rf, wf, nblock),\n";
1722   srvr_dot_c << "RPCServer(igen_no_err)\n";
1723   srvr_dot_c << "  { __versionVerifyDone__ = FALSE; IGEN_in_call_handler = 0;}\n";
1724   srvr_dot_c << name << "::" << name << "(int fd, xdrIOFunc r, xdrIOFunc w, int nblock):\n";
1725   srvr_dot_c << "XDRrpc(fd, r, w, nblock),\n";
1726   srvr_dot_c << "RPCServer(igen_no_err)\n";
1727   srvr_dot_c << "  { __versionVerifyDone__ = FALSE; IGEN_in_call_handler = 0;}\n";
1728
1729   srvr_dot_c << name << "::" << name << "(char *m,char *l,char *p,xdrIOFunc r,xdrIOFunc w, char **args, int nblock):\n";
1730   srvr_dot_c << "    XDRrpc(m, l, p, r, w, args, nblock),\n";
1731   srvr_dot_c << "    RPCServer(igen_no_err)\n";
1732   srvr_dot_c << "  { __versionVerifyDone__ = FALSE; IGEN_in_call_handler = 0;}\n";
1733 }
1734
1735 pvm_args *
1736 buildPVMargs_ptr (char *type_name, char *pvm_name, char *arg)
1737 {
1738   pvm_args *arg_ptr = NULL;
1739   
1740   if (!pvm_name || !type_name)
1741     return NULL;
1742
1743   arg_ptr = (pvm_args *) malloc (sizeof(pvm_args));
1744   if (!arg_ptr)
1745     return NULL;
1746
1747   arg_ptr->type_name = (char *) malloc (strlen(type_name) + 1);
1748   arg_ptr->pvm_name = (char *) malloc (strlen(type_name) + 1);
1749   if (arg)
1750     {
1751       arg_ptr->arg = (char *) malloc (strlen(arg) + 1);
1752       if (!(arg_ptr->arg)) return NULL;
1753       if (!strcpy (arg_ptr->arg, arg)) return NULL;
1754     }
1755   if (!(arg_ptr->type_name) || !(arg_ptr->pvm_name))
1756     return NULL;
1757
1758   if (!strcpy (arg_ptr->pvm_name, pvm_name)) return NULL;
1759   if (!strcpy (arg_ptr->type_name, type_name)) return NULL;
1760
1761   return arg_ptr;
1762 }
1763
1764 //
1765 // builds List pvm_types with PVM type information
1766 // this list is used by 2 procedures
1767 //
1768 void
1769 buildPVMargs()
1770 {
1771   pvm_args *arg_ptr = 0;
1772
1773   pvm_args *buildPVMargs_ptr (char *type_name, char *pvm_name, char *arg);
1774
1775   assert (arg_ptr = buildPVMargs_ptr ("int", "int", " >> 2 "));
1776   pvm_types.add(arg_ptr);
1777
1778   assert (arg_ptr = buildPVMargs_ptr ("char", "byte", "  "));
1779   pvm_types.add(arg_ptr);
1780
1781   assert (arg_ptr = buildPVMargs_ptr ("float", "float", " >> 2 "));
1782   pvm_types.add(arg_ptr);
1783
1784   assert (arg_ptr = buildPVMargs_ptr ("double", "double", " >> 3 "));
1785   pvm_types.add(arg_ptr);
1786
1787   assert (arg_ptr = buildPVMargs_ptr ("u_int", "uint", " >> 2 "));
1788   pvm_types.add(arg_ptr);
1789 }
1790
1791 void
1792 PVM_map_scalar_includes (const pvm_args * the_arg)
1793 {
1794   if (!the_arg || !(the_arg->type_name))
1795     return;
1796   dot_h << "bool_t IGEN_pvm_" << the_arg->type_name << " (IGEN_PVM_FILTER direction, ";
1797   dot_h << the_arg->type_name << " *data);\n";
1798 }
1799
1800 void
1801 PVM_map_array_includes (const pvm_args * the_arg)
1802 {
1803   if (!the_arg || !(the_arg->type_name))
1804     return;
1805   dot_h << "bool_t IGEN_pvm_Array_of_" << the_arg->type_name << " (IGEN_PVM_FILTER ";
1806   dot_h << "direction, " << the_arg->type_name << " **data, int *count);\n";
1807 }
1808
1809 void
1810 add_to_list (char *type, char *name, List<char*> *ptrs, List<char*> *holder) 
1811 {
1812   int new_length;
1813   char *new_string;
1814   char *ptr_string;
1815   int i, count;
1816
1817   count = ptrs->count();
1818
1819   ptr_string = new char[count + 1];
1820   ptr_string[0] = '\0';
1821   for (i=0; i < count; ++i)
1822     ptr_string[i] = '*';
1823   ptr_string[count] = '\0';
1824
1825   new_length = strlen(type) + strlen(name) + 3 + count;
1826   new_string = new char[new_length];
1827   
1828   sprintf (new_string, "%s %s %s", type, ptr_string, name);
1829   holder->add (new_string);
1830 }
1831
1832 void 
1833 addCMember (char *type, char *name, List<char*> *ptrs)
1834 {
1835   add_to_list (type, name, ptrs, &client_pass_thru);
1836 }
1837
1838 void 
1839 addSMember (char *type, char *name, List<char*> *ptrs)
1840 {
1841   add_to_list (type, name, ptrs, &server_pass_thru);
1842 }
1843
1844 void
1845 dump_to_dot_h(char *msg)
1846 {
1847   dot_h << msg;
1848 }
1849
1850 void interfaceSpec::genXDRServerVerifyProtocol()
1851 {
1852   srvr_dot_c << "   int " << name << "::verify_protocol()\n";
1853   srvr_dot_c << "   {\n";
1854   srvr_dot_c << "   char *__ProtocolName__ = \"" << name << "\";\n";
1855   srvr_dot_c << "   int __val__;\n";
1856   srvr_dot_c << "   int __sig__ = 0;\n";
1857   srvr_dot_c << "   __xdrs__->x_op = XDR_ENCODE;\n";
1858   srvr_dot_c << "    __val__ = " << version << ";\n";
1859   srvr_dot_c << "   if ((xdr_int(__xdrs__, &__sig__) == FALSE) ||\n";
1860   srvr_dot_c << "       (xdr_String(__xdrs__, &__ProtocolName__) == FALSE) ||\n";
1861   srvr_dot_c << "       (xdr_int(__xdrs__, &__val__) == FALSE))\n";
1862   srvr_dot_c << "      {\n";
1863   srvr_dot_c << "        err_state = igen_encode_err;\n";
1864   srvr_dot_c << "        handle_error();\n";
1865   srvr_dot_c << "        return(-1);\n";
1866   srvr_dot_c << "      }\n";
1867   srvr_dot_c << "    if (xdrrec_endofrecord(__xdrs__, TRUE) == FALSE)\n";
1868   srvr_dot_c << "      {\n";
1869   srvr_dot_c << "        err_state = igen_send_err;\n";
1870   srvr_dot_c << "        handle_error();\n";
1871   srvr_dot_c << "        return(-1);\n";
1872   srvr_dot_c << "      }\n";
1873   srvr_dot_c << "    __versionVerifyDone__ = TRUE;\n";
1874   srvr_dot_c << "    return 0;\n";
1875   srvr_dot_c << "    }\n";
1876 }
1877
1878 void interfaceSpec::genXDRLookForVerify()
1879 {
1880   srvr_dot_c << "   int " << name << "::look_for_verify()\n";
1881   srvr_dot_c << "   {\n";
1882   srvr_dot_c << "     int __status__, __tag__;\n\n";
1883   srvr_dot_c << "     if (xdrrec_skiprecord(__xdrs__) == FALSE)\n";
1884   srvr_dot_c << "        {\n";
1885   srvr_dot_c << "            err_state = igen_read_err;\n";
1886   srvr_dot_c << "            handle_error();\n";
1887   srvr_dot_c << "            return (-1);\n";
1888   srvr_dot_c << "        }\n\n";
1889   srvr_dot_c << "     __xdrs__->x_op = XDR_DECODE;\n\n";
1890
1891   srvr_dot_c << "        __status__ = xdr_int(__xdrs__, &__tag__);\n";
1892   srvr_dot_c << "       if (__status__ != TRUE)\n";
1893   srvr_dot_c << "        {\n";
1894   srvr_dot_c << "            err_state = igen_decode_err;\n";
1895   srvr_dot_c << "            handle_error();\n";
1896   srvr_dot_c << "            return (-1);\n";
1897   srvr_dot_c << "        }\n";
1898   srvr_dot_c << "       if (__tag__ != 0)\n";
1899   srvr_dot_c << "        {\n";
1900   srvr_dot_c << "            err_state = igen_request_err;\n";
1901   srvr_dot_c << "            handle_error();\n";
1902   srvr_dot_c << "            return (-1);\n";
1903   srvr_dot_c << "        }\n";
1904   srvr_dot_c << "     return 0;\n";
1905   srvr_dot_c << "   }\n";
1906 }