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