constructor inheritance round two.
[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.6  1994/02/04 00:35:01  hollings
6  * constructor inheritance round two.
7  *
8  * Revision 1.5  1994/01/31  20:05:57  hollings
9  * Added code to check the protocol name and version tests are run
10  * before any upcalls get invoked.
11  *
12  * Revision 1.4  1994/01/28  19:42:30  hollings
13  * Fixed max variable name length.
14  *
15  * Revision 1.3  1994/01/27  20:36:29  hollings
16  * changes in include syntax round 2 or 3.
17  *
18  * Revision 1.2  1994/01/26  06:50:10  hollings
19  * made the output of igen pass through g++ -Wall.
20  *
21  * Revision 1.1  1994/01/25  20:48:43  hollings
22  * New utility for interfaces.
23  * new utility for interfaces.
24  *
25  *
26  */
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/file.h>
32
33 #include "util/h/list.h"
34 #include "util/h/stringPool.h"
35
36 #include "parse.h"
37
38 int yyparse();
39 int emitCode;
40 int emitHeader;
41 char *codeFile;
42 char *serverFile;
43 char *clientFile;
44 int generateXDR;
45 int generatePVM;
46 stringPool pool;
47 char *headerFile;
48 extern FILE *yyin;
49 int generateTHREAD;
50 char *transportBase;
51 char *serverTypeName;
52 List <typeDefn *> types;
53 interfaceSpec *currentInterface;
54
55 void usage(char *name)
56 {
57     printf("%s -xdr | -thread | -pvm [-header | -code] <fileName>\n", name);
58     exit(-1);
59 }
60
61 void interfaceSpec::generateThreadLoop()
62 {
63     List <remoteFunc*> cf;
64
65     unionName = genVariable();
66     printf("union %s {\n", unionName);
67     for (cf = methods; *cf; cf++) {
68         printf("    struct %s %s;\n", (*cf)->structName, (*cf)->name);
69     }
70     printf("};\n\n");
71
72     printf("int %s::mainLoop(void)\n", name);
73     printf("{\n");
74     printf("  unsigned int __len__;\n");
75     printf("  unsigned int __tag__;\n");
76     printf("  union %s __recvBuffer__;\n", unionName);
77     printf("\n");
78     printf("  __tag__ = MSG_TAG_ANY;\n");
79     printf("  __len__ = sizeof(__recvBuffer__);\n");
80     printf("  requestingThread = msg_recv(&__tag__, &__recvBuffer__, &__len__);\n");
81     printf("  switch (__tag__) {\n");
82     for (cf = methods; *cf; cf++) {
83         (*cf)->genSwitch(FALSE);
84     }
85     printf("    default:\n");
86     printf("        return(__tag__);\n");
87     printf("  }\n");
88     printf("  return(0);\n");
89     printf("}\n");
90 }
91
92 void interfaceSpec::generateXDRLoop()
93 {
94     List <remoteFunc*> cf;
95
96     printf("int %s::mainLoop(void)\n", name);
97     printf("{\n");
98     printf("    unsigned int __tag__, __status__;\n");
99     printf("    __xdrs__->x_op = XDR_DECODE;\n");
100     printf("    xdrrec_skiprecord(__xdrs__);\n");
101     printf("    __status__ = xdr_int(__xdrs__, &__tag__);\n");
102     printf("    if (!__status__) return(-1);\n");
103     printf("    switch (__tag__) {\n");
104
105     // generate the zero RPC that returns interface name & version.
106     printf("        case 0:\n");
107     printf("            char *__ProtocolName__ = \"%s\";\n", name);
108     printf("            int __val__;\n");
109     printf("            __xdrs__->x_op = XDR_ENCODE;\n");
110     printf("            __val__ = 0;\n");
111     printf("            xdr_int(__xdrs__, &__val__);\n");
112     printf("            xdr_String(__xdrs__, &__ProtocolName__);\n");
113     printf("            __val__ = %d;\n", version);
114     printf("            xdr_int(__xdrs__, &__val__);\n");
115     printf("            xdrrec_endofrecord(__xdrs__, TRUE);\n");
116     printf("            __versionVerifyDone__ = TRUE;\n");
117     printf("            break;\n");
118
119     for (cf = methods; *cf; cf++) {
120         (*cf)->genSwitch(FALSE);
121     }
122     printf("    default:\n");
123     printf("        return(__tag__);\n");
124     printf("  }\n");
125     printf("  return(0);\n");
126     printf("}\n");
127 }
128
129
130
131 void interfaceSpec::genIncludes()
132 {
133     printf("#include <stdio.h>\n");
134     printf("#include <stdlib.h>\n");
135     printf("#include <assert.h>\n");
136     if (generateTHREAD) {
137         printf("extern \"C\" {\n");
138         printf("#include \"thread/h/thread.h\"\n");
139         printf("}\n");
140     }
141     if (generateXDR) {
142         printf("extern \"C\" {\n");
143         printf("#include <rpc/types.h>\n");
144         printf("#include <rpc/xdr.h>\n");
145         printf("}\n");
146     }
147
148     printf("#include \"%s\"\n\n", headerFile);
149 }
150
151 void interfaceSpec::generateServerCode()
152 {
153     List<remoteFunc*> cf;
154
155     if (generateTHREAD) {
156         generateThreadLoop();
157     } else if (generateXDR) {
158         FILE *sf;
159
160         // needs to go into a seperate file.
161         fflush(stdout);
162
163         sf = fopen(serverFile, "w");
164         dup2(sf->_file, 1);
165
166         genIncludes();
167
168         generateXDRLoop();
169     }
170
171     // generate stubs for upcalls.
172     for (cf = methods; *cf; cf++) {
173         (*cf)->genStub(name, TRUE);
174     }
175 }
176
177
178 void interfaceSpec::genWaitLoop() 
179 {
180     List<remoteFunc*> cf;
181
182     // generate a loop to wait for a tag, and call upcalls as the arrive.
183     printf("void %sUser::awaitResponce(int __targetTag__) {\n", name);
184     printf("    unsigned int __tag__;\n");
185     if (generateTHREAD) {
186         printf("  union %s __recvBuffer__;\n", unionName);
187         printf("  unsigned __len__ = sizeof(__recvBuffer__);\n");
188     }
189     printf("  while (1) {\n");
190     if (generateXDR) {
191         printf("    __xdrs__->x_op = XDR_DECODE;\n");
192         printf("    xdrrec_skiprecord(__xdrs__);\n");
193         printf("    xdr_int(__xdrs__, &__tag__);\n");
194     } else if (generateTHREAD) {
195         printf("  __tag__ = MSG_TAG_ANY;\n");
196         printf("    requestingThread = msg_recv(&__tag__, (void *) &__recvBuffer__, &__len__); \n");
197     }
198     printf("    if (__tag__ == __targetTag__) return;\n");
199     printf("    switch (__tag__) {\n");
200     for (cf = methods; *cf; cf++) {
201         (*cf)->genSwitch(TRUE);
202     }
203     printf("        default: \n        abort();\n");
204     printf("    }\n");
205     printf("    if (__targetTag__ == -1) return;\n");
206     printf("  }\n");
207     printf("}\n");
208
209     printf("int %sUser::isValidUpCall(int tag) {\n", name);
210     printf("    return((tag >= %d) && (tag <= %d));\n", baseTag, boundTag);
211     printf("}\n");
212 }
213
214 void interfaceSpec::genProtoVerify()
215 {
216     // generate stub to verify version.
217     printf("void %sUser::verifyProtocolAndVersion() {\n", name);
218     printf("    unsigned int __tag__;\n");
219     printf("    String proto;\n");
220     printf("    int version;\n");
221     printf("    __tag__ = 0;\n");
222     printf("    __xdrs__->x_op = XDR_ENCODE;\n");
223     printf("    xdr_int(__xdrs__, &__tag__);\n");
224     printf("    xdrrec_endofrecord(__xdrs__, TRUE);\n");
225     printf("    awaitResponce(0);\n");
226     printf("    xdr_String(__xdrs__, &(proto));\n");
227     printf("    xdr_int(__xdrs__, &(version));\n");
228     printf("    if ((version != %d) || (strcmp(proto, \"%s\"))) {\n",
229         version, name);
230     printf("        printf(\"protocol %s version %d expected\\n\");\n", 
231         name, version);
232     printf("        printf(\"protocol %%s version %%d found\\n\", proto, version);\n");
233     printf("        exit(-1);\n");
234     printf("    }\n");
235     printf("}\n");
236     printf("\n\n");
237     printf("%sUser::%sUser(int fd, xdrIOFunc r, xdrIOFunc w):\n", name, name);
238     printf("XDRrpc(fd, r, w) { if (__xdrs__) verifyProtocolAndVersion(); }\n");
239     printf("%sUser::%sUser(char *m,char *l,char *p,xdrIOFunc r,xdrIOFunc w):\n",
240         name, name);
241     printf("    XDRrpc(m, l, p, r, w) { if (__xdrs__) \n");
242     printf("       verifyProtocolAndVersion(); }\n");
243     printf("\n");
244 }
245
246
247 void interfaceSpec::generateStubs()
248 {
249     List <remoteFunc*> cf;
250     char className[80];
251
252     sprintf(className, "%sUser", name);
253     for (cf = methods; *cf; cf++) {
254         (*cf)->genStub(className, FALSE);
255     }
256 }
257
258 void interfaceSpec::generateClientCode()
259 {
260     if (generateXDR) {
261         FILE *cf;
262
263         // needs to go into a seperate file.
264         fflush(stdout);
265
266         cf = fopen(clientFile, "w");
267         dup2(cf->_file, 1);
268
269         genIncludes();
270     }
271
272     generateStubs();
273
274     if (generateXDR) {
275         genProtoVerify();
276     }
277
278     genWaitLoop();
279 }
280
281 void interfaceSpec::generateBundlers()
282 {
283     List <typeDefn*> cs;
284
285     for (cs = types; *cs; cs++) {
286         (*cs)->genBundler();
287     }
288 }
289
290 int main(int argc, char *argv[])
291 {
292     int i;
293     FILE *of;
294     char *temp;
295     char *file;
296
297     /* define pre-defined types */
298     (void) new typeDefn("int");
299     (void) new typeDefn("double");
300     (void) new typeDefn("String");
301     (void) new typeDefn("void");
302     (void) new typeDefn("Boolean");
303
304     emitCode = 1;
305     emitHeader = 1;
306     for (i=0; i < argc-1; i++) {
307         if (!strcmp("-pvm", argv[i])) {
308             generatePVM = 1;
309             generateXDR = 0;
310             generateTHREAD = 0;
311             serverTypeName = pool.findAndAdd("int");
312         } if (!strcmp("-xdr", argv[i])) {
313             generatePVM = 0;
314             generateXDR = 1;
315             generateTHREAD = 0;
316             (void) new typeDefn("XDRptr");
317             serverTypeName = pool.findAndAdd("XDRptr");
318             transportBase = "XDRrpc";
319         } if (!strcmp("-thread", argv[i])) {
320             generatePVM = 0;
321             generateXDR = 0;
322             generateTHREAD = 1;
323             serverTypeName = pool.findAndAdd("int");
324             transportBase = "THREADrpc";
325         } else if (!strcmp("-header", argv[i])) {
326             emitCode = 0;
327             emitHeader = 1;
328         } else if (!strcmp("-code", argv[i])) {
329             emitCode = 1;
330             emitHeader = 0;
331         }
332     }
333     if (!emitHeader && !emitCode) {
334         usage(argv[0]);
335     }
336     if (!generatePVM && !generateXDR && !generateTHREAD) {
337         usage(argv[0]);
338     }
339
340     file = argv[argc-1];
341
342     yyin = fopen(file, "r");
343     if (!yyin) {
344         printf("unable to open %s\n", file);
345         exit(-1);
346     }
347
348     // skip to trailing component of file name.
349     temp = strrchr(file, '/');
350     if (temp) file = temp+1;
351
352     temp = strstr(file, ".I");
353     if (!temp) {
354         printf("file names must end in .I\n");
355         exit(-1);
356     }
357     *(temp+1) = '\0';
358
359     headerFile = (char *) malloc(strlen(file)+1);
360     sprintf(headerFile, "%sh", file);
361
362     codeFile = (char *) malloc(strlen(file)+1);
363     sprintf(codeFile, "%sC", file);
364
365     serverFile = (char *) malloc(strlen(file)+6);
366     sprintf(serverFile, "%sSRVR.C", file);
367
368     clientFile = (char *) malloc(strlen(file)+6);
369     sprintf(clientFile, "%sCLNT.C", file);
370
371     if (emitHeader) {
372         of = fopen(headerFile, "w");
373         dup2(of->_file, 1);
374         printf("#include \"util/h/rpcUtil.h\"\n");
375     }
376
377     yyparse();
378
379     if (emitHeader) {
380         fflush(stdout);
381         fclose(of);
382     }
383
384     if (!currentInterface) {
385         printf("no interface defined\n");
386         exit(-1);
387     }
388
389     if (emitCode) {
390         FILE *cf;
391
392         cf = fopen(codeFile, "w");
393         dup2(cf->_file, 1);
394
395         currentInterface->genIncludes();
396         if (generateXDR || generatePVM) currentInterface->generateBundlers();
397
398         currentInterface->generateServerCode();
399
400         currentInterface->generateClientCode();
401         fflush(stdout);
402     }
403
404     exit(0);
405 }
406
407 char *interfaceSpec::genVariable()
408 {
409     static int count;
410     char *ret;
411
412     ret = (char *) malloc(strlen(name)+10);
413     sprintf(ret, "%s__%d", name, count++);
414     return(ret);
415 }
416
417 int interfaceSpec::getNextTag()
418 {
419     return(++boundTag);
420 }
421
422 void remoteFunc::genMethodHeader(char *className)
423 {
424     int spitOne;
425     List <char *> cl;
426     List<argument*> lp;
427
428     if (className) {
429         printf("%s %s::%s(", retType, className, name);
430     } else {
431         printf("%s %s(", retType, name);
432     }
433     for (lp = args, spitOne = 0; *lp; lp++) {
434         if (spitOne) printf(",");
435         spitOne =1;
436         printf("%s ", (*lp)->type);
437         for (cl = *(*lp)->stars; *cl; cl++) printf("*");
438         printf("%s", (*lp)->name);
439     }
440     if (!spitOne) printf("void");
441     printf(")");
442 }
443
444 void remoteFunc::genSwitch(Boolean forUpcalls)
445 {
446     int first;
447     List <argument *> ca;
448
449
450     if (forUpcalls && (upcall == notUpcall)) return;
451     if (!forUpcalls && (upcall != notUpcall)) return;
452
453     printf("        case %s_%s_REQ: {\n", spec->getName(), name);
454     printf("            ");
455     if (generateTHREAD && (upcall != asyncUpcall)) 
456         printf("            int __val__;\n");
457     if (strcmp(retType, "void")) {
458         printf("            %s __ret__;\n", retType);
459     }
460     if (generateXDR) {
461         printf("            extern xdr_%s(XDR*, %s*);\n", retType, retType);
462         if (args.count()) {
463             printf("            %s __recvBuffer__;\n", structName);
464                 for (ca = args; *ca; ca++) {
465                 printf("            xdr_%s(__xdrs__, &__recvBuffer__.%s);\n", 
466                     (*ca)->type, (*ca)->name);
467             }
468         }
469     }
470     if (strcmp(retType, "void")) {
471         printf("            __ret__ = %s(", name);
472     } else {
473         printf("            %s(", name);
474     }
475     for (ca = args, first = 1; *ca; ca++) {
476         if (!first) printf(",");
477         first = 0;
478         if (generateTHREAD) {
479             printf("__recvBuffer__.%s.%s", name, (*ca)->name);
480         } else if (generateXDR) {
481             printf("__recvBuffer__.%s", (*ca)->name);
482         }
483     }
484     printf(");\n");
485     if (generateTHREAD && (upcall != asyncUpcall)) {
486         if (strcmp(retType, "void")) {
487             printf("        __val__ = msg_send(requestingThread, %s_%s_RESP, (void *) &__ret__, sizeof(%s));\n", spec->getName(), name, retType);
488         } else {
489             printf("        __val__ = msg_send(requestingThread, %s_%s_RESP, NULL, 0);\n", 
490                 spec->getName(), name);
491         }
492         printf("            assert(__val__ == THR_OKAY);\n");
493     } else if (generateXDR && (upcall != asyncUpcall)) {
494         printf("            __xdrs__->x_op = XDR_ENCODE;\n");
495         printf("            __tag__ = %s_%s_RESP;\n", spec->getName(), name);
496         printf("            xdr_int(__xdrs__, &__tag__);\n");
497         if (strcmp(retType, "void")) {
498             printf("            xdr_%s(__xdrs__,&__ret__);\n", retType);
499         }
500         printf("            xdrrec_endofrecord(__xdrs__, TRUE);\n");
501     }
502     printf("            break;\n         }\n\n");
503 }
504
505
506 void remoteFunc::genThreadStub(char *className)
507 {
508     List<argument*> lp;
509     char *retVar = spec->genVariable();
510     char *structUseName = spec->genVariable();
511
512     genMethodHeader(className);
513     printf(" {\n");
514
515     if (*args) printf("    struct %s %s;\n", structName, structUseName);
516     if (upcall != asyncUpcall) printf("    unsigned int __tag__;\n");
517     if (strcmp(retType, "void")) printf("    unsigned int __len__;\n");
518     printf("    int __val__;\n");
519     if (strcmp(retType, "void")) {
520         printf("    %s %s;\n", retType, retVar);
521     }
522     for (lp = args; *lp; lp++) {
523         printf("    %s.%s = %s;  \n",structUseName,
524             (*lp)->name, (*lp)->name);
525     }
526     if (*args) {
527         printf("    __val__ = msg_send(tid, %s_%s_REQ, (void *) &%s, sizeof(%s));\n",
528             spec->getName(), name, structUseName, structUseName);
529     } else {
530         printf("    __val__ = msg_send(tid, %s_%s_REQ, NULL, 0); \n", 
531             spec->getName(), name);
532     }
533     printf("    assert(__val__ == THR_OKAY);\n");
534     if (upcall != asyncUpcall) {
535         printf("    __tag__ = %s_%s_RESP;\n", spec->getName(), name);
536         if (strcmp(retType, "void")) {
537             printf("    __len__ = sizeof(%s);\n", retVar);
538             printf("    msg_recv(&__tag__, (void *) &%s, &__len__); \n",retVar);
539             printf("    assert(__len__ == sizeof(%s));\n", retVar);
540             printf("    return(%s);\n", retVar);
541         } else {
542             printf("    msg_recv(&__tag__, NULL, 0); \n",spec->getName(), name);
543         }
544         printf("    assert(__tag__ == %s_%s_RESP);\n",spec->getName(),name);
545     }
546     printf("}\n\n");
547 }
548
549 void remoteFunc::genXDRStub(char *className)
550 {
551     List<argument*> lp;
552     char *retVar = spec->genVariable();
553
554     genMethodHeader(className);
555     printf(" {\n");
556
557     printf("    unsigned int __tag__;\n");
558     if (strcmp(retType, "void")) {
559         printf("    %s %s;\n", retType, retVar);
560     }
561     // check to see protocol verify has been done.
562     if (upcall != notUpcall) {
563         printf("    if (!__versionVerifyDone__) {\n");
564         printf("        char *__ProtocolName__ = \"%s\";\n", spec->getName());
565         printf("        int __status__;\n");
566         printf("        __xdrs__->x_op = XDR_DECODE;\n");
567         printf("        xdrrec_skiprecord(__xdrs__);\n");
568         printf("        __status__ = xdr_int(__xdrs__, &__tag__);\n");
569         printf("        assert(__status__ && (__tag__ == 0));\n");
570         printf("        __xdrs__->x_op = XDR_ENCODE;\n");
571         printf("        xdr_int(__xdrs__, &__tag__);\n");
572         printf("        xdr_String(__xdrs__, &__ProtocolName__);\n");
573         printf("        __tag__ = %d;\n", spec->getVersion());
574         printf("        xdr_int(__xdrs__, &__tag__);\n");
575         printf("        xdrrec_endofrecord(__xdrs__, TRUE);\n");
576         printf("        __versionVerifyDone__ = TRUE;\n");
577         printf("    }\n");
578     }
579     printf("    __tag__ = %s_%s_REQ;\n", spec->getName(), name);
580     printf("    __xdrs__->x_op = XDR_ENCODE;\n");
581     printf("    xdr_int(__xdrs__, &__tag__);\n");
582     for (lp = args; *lp; lp++) {
583         printf("    xdr_%s(__xdrs__, &%s);\n", (*lp)->type, (*lp)->name);
584     }
585     printf("    xdrrec_endofrecord(__xdrs__, TRUE);\n");
586     if (upcall != asyncUpcall) {
587         if (upcall == notUpcall) {
588             printf("    awaitResponce(%s_%s_RESP);\n",spec->getName(), name);
589         } else if (upcall == syncUpcall) {
590             printf("    __xdrs__->x_op = XDR_DECODE;\n");
591             printf("    xdrrec_skiprecord(__xdrs__);\n");
592             printf("    xdr_int(__xdrs__, &__tag__);\n");
593             printf("    assert(__tag__ == %s_%s_RESP);\n", spec->getName(), name);
594         }
595         if (strcmp(retType, "void")) {
596             printf("    xdr_%s(__xdrs__, &(%s)); \n", retType, retVar);
597             printf("    return(%s);\n", retVar);
598         }
599     }
600     printf("}\n\n");
601 }
602
603 void remoteFunc::genStub(char *className, Boolean forUpcalls)
604 {
605     if (forUpcalls && (upcall == notUpcall)) return;
606     if (!forUpcalls && (upcall != notUpcall)) return;
607
608     printf("\n");
609
610     if (generateXDR) {
611         genXDRStub(className);
612     } else if (generateTHREAD) {
613         genThreadStub(className);
614     }
615 }
616
617 void remoteFunc::genHeader()
618 {
619     List<char *> cl;
620     List<argument*> lp;
621
622     printf("struct %s {\n", structName);
623     for (lp = args; *lp; lp++) {
624         printf("    %s ", (*lp)->type);
625         for (cl = *(*lp)->stars; *cl; cl++) printf("*");
626         printf("%s", (*lp)->name);
627         printf(";\n");
628     }
629     printf("};\n\n");
630
631     printf("#define %s_%s_REQ %d\n", spec->getName(),name, spec->getNextTag());
632     printf("#define %s_%s_RESP %d\n", spec->getName(), name,spec->getNextTag());
633 }
634
635 void typeDefn::genHeader()
636 {
637     List<field*> fp;
638
639     printf("#ifndef %s_TYPE\n", name);
640     printf("#define %s_TYPE\n", name);
641     printf("class %s {  \npublic:\n", name);
642     if (arrayType) {
643         printf("    int count;\n");
644         printf("    %s* data;\n", type);
645     } else {
646         for (fp = fields; *fp; fp++) {
647             (*fp)->genHeader();
648         }
649     }
650     printf("};\n\n");
651     printf("#endif\n");
652
653     if (generateXDR) {
654         if (userDefined) printf("extern xdr_%s(XDR*, %s*);\n", name, name);
655     }
656 }
657
658
659 void typeDefn::genBundler()
660 {
661     List<field*> fp;
662
663     if (!userDefined) return;
664
665     printf("bool_t xdr_%s(XDR *__xdrs__, %s *__ptr__) {\n", name, name);
666     if (arrayType) {
667         printf("if (__xdrs__->x_op == XDR_DECODE) __ptr__->data = NULL;\n");
668         printf("    xdr_array(__xdrs__, &(__ptr__->data), &__ptr__->count, ~0, sizeof(%s), xdr_%s);\n",
669             type, type);
670     } else {
671         for (fp = fields; *fp; fp++) {
672             (*fp)->genBundler();
673         }
674     }
675     printf("    return(TRUE);\n");
676     printf("}\n\n");
677 }
678
679
680 char *findAndAddArrayType(char *name) 
681 {
682     typeDefn *s;
683     char temp[80];
684     char *arrayTypeName;
685
686     // now find the associated array type.
687     sprintf(temp, "%s_Array", name);
688     arrayTypeName = pool.findAndAdd(temp);
689     if (!types.find(arrayTypeName)) {
690         s = new typeDefn(arrayTypeName, name);
691         s->genHeader();
692     }
693     return arrayTypeName;
694 }
695
696 void interfaceSpec::genClass()
697 {
698     List <remoteFunc *> curr; 
699
700     printf("class %sUser: public RPCUser, public %s {\n", name, transportBase);
701     printf("  public:\n");
702     if (generateTHREAD) {
703         printf("    %sUser(int tid): THREADrpc(tid) {}\n", name);
704     } else if (generateXDR) {
705         printf("    virtual void verifyProtocolAndVersion();\n");
706         printf("    %sUser(int fd, xdrIOFunc r, xdrIOFunc w);\n", name);
707         printf("    %sUser(char *,char *,char*, xdrIOFunc r, xdrIOFunc w);\n", 
708                 name);
709     }
710     printf("    void awaitResponce(int);\n");
711     printf("    int isValidUpCall(int);\n");
712
713     for (curr = methods; *curr; curr++) {
714         printf("    ");
715         (*curr)->genMethodHeader(NULL);
716         printf(";\n");
717     }
718     printf("};\n");
719
720
721     printf("class %s: private RPCServer, public %s {\n", name, transportBase);
722     printf("  public:\n");
723     if (generateTHREAD) {
724         printf("    %s(int tid): THREADrpc(tid) {}\n", name);
725     } else if (generateXDR) {
726         printf("    %s(char*m,char *u, char *p, xdrIOFunc rd, xdrIOFunc wr):\n",
727             name);
728         printf("      XDRrpc(m, u, p, rd, wr) {}\n");
729         printf("    %s(int fd, xdrIOFunc rd, xdrIOFunc wr):\n", name);
730         printf("      XDRrpc(fd, rd, wr) {}\n");
731     }
732     printf("    mainLoop(void);\n");
733     for (curr = methods; *curr; curr++) {
734         printf("    ");
735         (*curr)->genMethodHeader(NULL);
736         printf(";\n");
737     }
738     printf("};\n\n");
739 }