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