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