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