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