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