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