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