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