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