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