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