2 * main.C - main function of the interface compiler igen.
5 * Revision 1.24 1994/06/02 23:34:26 markc
6 * New igen features: error checking, synchronous upcalls.
8 * Revision 1.23 1994/04/07 19:03:33 markc
9 * Fixed bug for async client calls with threads. Removed msg_recv.
11 * Revision 1.22 1994/04/06 21:28:45 markc
12 * Added constructor for client side of xdr based code.
14 * Revision 1.21 1994/04/01 04:57:50 markc
15 * Added checks in bundlers. Fixed xdrrec_endofrecord.
17 * Revision 1.20 1994/03/31 22:57:52 hollings
18 * Fixed xdr_endofrecord bug and added wellKnownScoket parameter.
20 * Revision 1.19 1994/03/31 02:12:18 markc
21 * Added code to initialize versionVerifyDone
23 * Revision 1.18 1994/03/25 22:35:21 hollings
24 * Get the test for callErr right.
26 * Revision 1.17 1994/03/25 20:57:02 hollings
27 * Changed all asserts to set the error member variable. This makes it
28 * possible to detect/continue when the remote process dies.
30 * Revision 1.16 1994/03/07 23:28:46 markc
31 * Added support to free arrays of classes.
33 * Revision 1.15 1994/03/07 02:50:56 markc
34 * Set callErr to 0 in constructors.
36 * Revision 1.14 1994/03/07 02:35:17 markc
37 * Added code to detect failures for xdr code. Provides member instance
38 * callErr which is set to -1 on failures.
40 * Revision 1.13 1994/03/06 20:51:09 markc
41 * Added float as a basic type.
43 * Revision 1.12 1994/03/01 21:39:37 jcargill
44 * Rearranged order of includes for igen-generated code, so that it compiles
45 * on MIPS. Some of the Ultrix headers really suck.
47 * Revision 1.11 1994/03/01 01:50:46 markc
48 * Fixed memory access errors.
50 * Revision 1.10 1994/02/25 11:41:32 markc
51 * Fixed bug. Igen generated versionVerify tests for client code when async.
53 * Revision 1.9 1994/02/24 05:14:32 markc
55 * Initial version for solaris2.2.
56 * Dependencies changed.
57 * Added pvm support, virtual function support, inclusion of data members,
58 * separate client and header include files.
60 * Revision 1.8 1994/02/08 00:17:55 hollings
61 * Fixed pointer problems to work on DECstations.
63 * Revision 1.7 1994/02/04 01:25:46 hollings
64 * *** empty log message ***
66 * Revision 1.6 1994/02/04 00:35:01 hollings
67 * constructor inheritance round two.
69 * Revision 1.5 1994/01/31 20:05:57 hollings
70 * Added code to check the protocol name and version tests are run
71 * before any upcalls get invoked.
73 * Revision 1.4 1994/01/28 19:42:30 hollings
74 * Fixed max variable name length.
76 * Revision 1.3 1994/01/27 20:36:29 hollings
77 * changes in include syntax round 2 or 3.
79 * Revision 1.2 1994/01/26 06:50:10 hollings
80 * made the output of igen pass through g++ -Wall.
82 * Revision 1.1 1994/01/25 20:48:43 hollings
83 * New utility for interfaces.
84 * new utility for interfaces.
95 #include "util/h/list.h"
96 #include "util/h/stringPool.h"
111 char *serverTypeName;
112 List <typeDefn *> types;
114 interfaceSpec *currentInterface;
115 typedef struct pvm_args { char *type_name; char *pvm_name; char *arg;} pvm_args;
116 List <pvm_args *> pvm_types;
117 void PVM_map_scalar_includes (const pvm_args *);
118 void PVM_map_array_includes (const pvm_args *);
119 void templatePVMscalar (const pvm_args *);
120 void templatePVMarray (const pvm_args *);
121 static List<char*> client_pass_thru;
122 static List<char*> server_pass_thru;
124 void usage(char *name)
126 printf("%s -xdr | -thread | -pvm [-header | -code] <fileName>\n", name);
130 // generate code to handle igen errors
131 // the code to set the error state will be generated prior to this function being
133 void interfaceSpec::genErrHandler(ofstream &ofstr, Boolean client)
136 ofstr << " void " << name << "User::handle_error()\n" << " {\n";
138 ofstr << " void " << name << "::handle_error()\n" << " {\n";
140 ofstr << " fprintf(stderr, \"Error not handled: err_state = %d\\n\", err_state);\n";
141 ofstr << " IGEN_ERR_ASSERT;\n";
142 ofstr << " exit(-1);\n";
146 // this goes into the dot_c file since all client and server code go into one file
147 // for threads. (an igen artifact).
148 // this generates code for ::mainLoop, including the code for the switch statement
149 // that handles all of the message types.
151 void interfaceSpec::generateThreadLoop()
153 List <remoteFunc*> cf;
155 unionName = genVariable();
156 dot_c << "union " << unionName << " {\n";
157 for (cf = methods; *cf; cf++)
158 dot_c << " struct " << (*cf)->structName << " " << (*cf)->name << ";\n";
162 dot_c << "int " << name << "::mainLoop(void)\n";
164 dot_c << " unsigned int __len__;\n";
165 dot_c << " unsigned int __tag__;\n";
166 dot_c << " int __val__ = THR_OKAY;\n";
167 dot_c << " union " << unionName << " __recvBuffer__;\n";
169 dot_c << " if (err_state != igen_no_err) return (-1);\n";
170 dot_c << " __tag__ = MSG_TAG_ANY;\n";
171 dot_c << " __len__ = sizeof(__recvBuffer__);\n";
172 dot_c << " if ((requestingThread = msg_recv(&__tag__, &__recvBuffer__, &__len__)) ==\n";
173 dot_c << " THR_ERR)\n";
175 dot_c << " err_state = igen_read_err;\n";
176 dot_c << " handle_error();\n";
177 dot_c << " return (-1);\n";
180 dot_c << " switch (__tag__)\n" << " {\n";
182 for (cf = methods; *cf; cf++)
183 (*cf)->genSwitch(FALSE, "-1", dot_c);
185 dot_c << " default:\n";
186 dot_c << " return(__tag__);\n";
189 dot_c << " if (__val__ != THR_OKAY)\n";
191 dot_c << " err_state = igen_send_err;\n";
192 dot_c << " handle_error();\n";
193 dot_c << " return (-1);\n";
196 dot_c << " return(0);\n";
200 // generate the main loop for xdr
201 void interfaceSpec::generateXDRLoop()
203 List <remoteFunc*> cf;
205 genXDRServerVerifyProtocol();
206 genXDRLookForVerify();
208 srvr_dot_c << "int " << name << "::mainLoop(void)\n";
210 srvr_dot_c << " unsigned int __tag__, __status__;\n";
211 srvr_dot_c << " if (err_state != igen_no_err) return (-1);\n";
212 srvr_dot_c << " __xdrs__->x_op = XDR_DECODE;\n";
213 srvr_dot_c << " if (xdrrec_skiprecord(__xdrs__) == FALSE)\n";
214 srvr_dot_c << " {\n";
215 srvr_dot_c << " err_state = igen_read_err;\n";
216 srvr_dot_c << " handle_error();\n";
217 srvr_dot_c << " return (-1);\n";
218 srvr_dot_c << " }\n";
219 srvr_dot_c << " __status__ = xdr_int(__xdrs__, &__tag__);\n";
220 srvr_dot_c << " if (!__status__)\n";
221 srvr_dot_c << " {\n";
222 srvr_dot_c << " err_state = igen_read_err;\n";
223 srvr_dot_c << " handle_error();\n";
224 srvr_dot_c << " return(-1);\n";
225 srvr_dot_c << " }\n";
226 srvr_dot_c << " switch (__tag__)\n " << " {\n";
228 // generate the zero RPC that returns interface name & version.
229 srvr_dot_c << " case 0:\n";
230 srvr_dot_c << " if (verify_protocol())\n";
231 srvr_dot_c << " return (-1);\n";
232 srvr_dot_c << " break;\n";
234 for (cf = methods; *cf; cf++)
235 (*cf)->genSwitch(FALSE, "-1", srvr_dot_c);
237 srvr_dot_c << " default:\n";
238 srvr_dot_c << " return(__tag__);\n";
239 srvr_dot_c << " }\n";
240 srvr_dot_c << " return(0);\n";
244 // generate the main loop for pvm
245 void interfaceSpec::generatePVMLoop()
247 List <remoteFunc*> cf;
249 srvr_dot_c << "int " << name << "::mainLoop(void)\n";
251 srvr_dot_c << " int __tag__, __bytes__, __msgtag__, __tid__, __bufid__, __other__, __count__;\n";
252 srvr_dot_c << " struct taskinfo __taskp__, *__tp__;\n";
253 srvr_dot_c << " __tp__ = &__taskp__;\n";
254 srvr_dot_c << " if (err_state != igen_no_err) return (-1);\n";
255 srvr_dot_c << " // this code checks for message \n";
256 srvr_dot_c << " __other__ = get_other_tid();\n";
257 srvr_dot_c << " if (__other__ < -1) return -1;\n";
258 srvr_dot_c << " if (get_error() == -1) return -1;\n";
259 srvr_dot_c << " if ((__bufid__ = pvm_recv (__other__, -1)) < 0) return -1;\n";
260 srvr_dot_c << " if (pvm_bufinfo (__bufid__, &__bytes__, &__msgtag__, &__tid__) < 0) return -1;\n";
261 srvr_dot_c << " switch (__msgtag__)\n" << " {\n";
263 // generate the zero PVM that returns interface name & version.
264 srvr_dot_c << " case 0:\n";
265 srvr_dot_c << " char *__ProtocolName__ = \"" << name << "\";\n";
266 srvr_dot_c << " int __val__;\n";
267 srvr_dot_c << " __val__ = 0;\n";
268 srvr_dot_c << " assert(pvm_initsend(0) >= 0);\n";
269 srvr_dot_c << " pvm_pkstr(__ProtocolName__);\n";
270 srvr_dot_c << " __val__ = %d;\n", version;
271 srvr_dot_c << " pvm_pkint(&__val__, 1, 1);\n";
272 srvr_dot_c << " pvm_send (__tid__, 0);";
273 srvr_dot_c << " break;\n";
275 for (cf = methods; *cf; cf++)
276 (*cf)->genSwitch(FALSE, "-1", srvr_dot_c);
278 srvr_dot_c << " default:\n";
279 srvr_dot_c << " return(__tag__);\n";
280 srvr_dot_c << " }\n";
281 srvr_dot_c << " return(0);\n";
286 // the include files for *SRVR.C and *.C
287 void interfaceSpec::genIncludes(ofstream &output)
289 output << "#include <stdio.h>\n";
290 output << "#include <stdlib.h>\n";
291 output << "#include <rpc/types.h>\n";
292 output << "#include <assert.h>\n";
294 if (generateTHREAD) {
295 output << "extern \"C\" {\n";
296 output << "#include \"thread/h/thread.h\"\n";
297 output << "#include <errno.h>\n";
301 output << "extern \"C\" {\n";
302 output << "#include <rpc/xdr.h>\n";
303 output << "#include <errno.h>\n";
307 output << "extern \"C\" {\n";
308 output << "#include <pvm3.h> \n";
309 output << "#include <errno.h>\n";
313 // printf("#include \"%s\"\n\n", headerFile);
316 // generates code for the server
317 // this code is written into *.SRVR.C, except for thread code
318 void interfaceSpec::generateServerCode()
320 List<remoteFunc*> cf;
322 if (generateTHREAD) {
323 generateThreadLoop();
325 // generate error handler code
326 genErrHandler(dot_c, FALSE);
327 } else if (generateXDR) {
328 genIncludes(srvr_dot_c);
330 // include server header
331 srvr_dot_c << "#include \"" << protoFile << "SRVR.h\"\n";
336 // generate XDR-only class constructors to allow server to
339 genXDRServerCons(name);
341 // generate error handler code
342 genErrHandler(srvr_dot_c, FALSE);
343 } else if (generatePVM) {
345 genIncludes(srvr_dot_c);
347 // include server header
348 srvr_dot_c << "#include \"" << protoFile << "SRVR.h\"\n";
353 // generate PVM-only class constructors to allow server to
356 genPVMServerCons(name);
358 // generate error handler code
359 genErrHandler(srvr_dot_c, FALSE);
362 // generate stubs for upcalls.
363 for (cf = methods; *cf; cf++)
364 (*cf)->genStub(name, TRUE, srvr_dot_c);
368 void interfaceSpec::genWaitLoop()
370 List<remoteFunc*> cf;
372 // generate a loop to wait for a tag, and call upcalls as they arrive.
373 clnt_dot_c << "void " << name << "User::awaitResponce(int __targetTag__) {\n";
374 clnt_dot_c << " unsigned int __tag__;\n";
377 clnt_dot_c << " union " << unionName << " __recvBuffer__;\n";
378 clnt_dot_c << " unsigned __len__ = sizeof(__recvBuffer__);\n";
380 else if (generatePVM)
381 clnt_dot_c << " int __tid__, __bufid__, __bytes__;\n";
383 // make sure it is safe to proceed
384 clnt_dot_c << " if (err_state != igen_no_err) return;\n";
386 clnt_dot_c << " while (1)\n " << " {\n";
388 clnt_dot_c << " __xdrs__->x_op = XDR_DECODE;\n";
389 clnt_dot_c << " if (xdrrec_skiprecord(__xdrs__) == FALSE)\n";
390 clnt_dot_c << " {\n";
391 clnt_dot_c << " err_state = igen_read_err;\n";
392 clnt_dot_c << " handle_error();\n";
393 clnt_dot_c << " return;\n";
394 clnt_dot_c << " }\n";
395 clnt_dot_c << " if (xdr_int(__xdrs__, &__tag__) == FALSE)\n"
396 ; clnt_dot_c << " {\n";
397 clnt_dot_c << " err_state = igen_decode_err;\n";
398 clnt_dot_c << " handle_error();\n";
399 clnt_dot_c << " return;\n";
400 clnt_dot_c << " }\n";
401 } else if (generatePVM) {
402 clnt_dot_c << " int __other__ = get_other_tid();\n";
403 clnt_dot_c << " if (get_error() == -1) abort();\n";
404 clnt_dot_c << " if (__other__ < 0) abort();\n";
405 clnt_dot_c << " if ((__bufid__ = pvm_recv (__other__, -1)) < 0)\n";
406 clnt_dot_c << " abort();\n";
407 clnt_dot_c << " if (pvm_bufinfo(__bufid__, &__bytes__, (int*) &__tag__, &__tid__) < 0)\n";
408 clnt_dot_c << " abort();\n";
409 } else if (generateTHREAD) {
410 clnt_dot_c << " __tag__ = MSG_TAG_ANY;\n";
411 clnt_dot_c << " if ((requestingThread = msg_recv(&__tag__, (void *) &__recvBuffer__, &__len__)) == THR_ERR)\n";
412 clnt_dot_c << " {\n";
413 clnt_dot_c << " err_state = igen_read_err;\n";
414 clnt_dot_c << " handle_error();\n";
415 clnt_dot_c << " return;\n";
416 clnt_dot_c << " }\n";
419 // look for success error message
420 clnt_dot_c << " if (__tag__ == __targetTag__) return;\n";
422 clnt_dot_c << " switch (__tag__)\n" << " {\n";
423 for (cf = methods; *cf; cf++) {
424 (*cf)->genSwitch(TRUE, " ", clnt_dot_c);
426 clnt_dot_c << " default: \n";
427 clnt_dot_c << " err_state = igen_request_err;\n";
428 clnt_dot_c << " handle_error();\n";
429 clnt_dot_c << " return;\n";
430 clnt_dot_c << " }\n";
431 clnt_dot_c << " if (__targetTag__ == -1) return;\n";
432 clnt_dot_c << " }\n";
435 clnt_dot_c << "int " << name << "User::isValidUpCall(int tag) {\n";
436 clnt_dot_c << " return((tag >= " << baseTag << ") && (tag <= " << boundTag << "));\n",
440 void interfaceSpec::genProtoVerify()
442 // generate stub to verify version.
443 clnt_dot_c << "void " << name << "User::verifyProtocolAndVersion() {\n";
444 clnt_dot_c << " unsigned int __tag__;\n";
445 clnt_dot_c << " String proto;\n";
446 clnt_dot_c << " int version;\n";
447 clnt_dot_c << " __tag__ = 0;\n";
448 clnt_dot_c << " __xdrs__->x_op = XDR_ENCODE;\n";
449 clnt_dot_c << " if (xdr_int(__xdrs__, &__tag__) != TRUE)\n";
450 clnt_dot_c << " {\n";
451 clnt_dot_c << " err_state = igen_encode_err;\n";
452 clnt_dot_c << " handle_error();\n";
453 clnt_dot_c << " return;\n";
454 clnt_dot_c << " }\n";
455 clnt_dot_c << " if (xdrrec_endofrecord(__xdrs__, TRUE) != TRUE)";
456 clnt_dot_c << " {\n";
457 clnt_dot_c << " err_state = igen_read_err;\n";
458 clnt_dot_c << " handle_error();\n";
459 clnt_dot_c << " return;\n";
460 clnt_dot_c << " }\n";
461 clnt_dot_c << " awaitResponce(0);\n";
462 clnt_dot_c << " if (err_state != igen_no_err)\n";
463 clnt_dot_c << " {\n";
464 clnt_dot_c << " printf(\"Protocol verify - no response from server\\n\");\n";
465 clnt_dot_c << " handle_error();";
466 clnt_dot_c << " exit(-1);\n";
467 clnt_dot_c << " }\n";
468 clnt_dot_c << " __xdrs__->x_op = XDR_DECODE;\n";
469 clnt_dot_c << " if ((xdr_String(__xdrs__, &(proto)) == FALSE) ||\n";
470 clnt_dot_c << " (xdr_int(__xdrs__, &(version)) == FALSE))\n";
471 clnt_dot_c << " {\n";
472 clnt_dot_c << " err_state = igen_decode_err;\n";
473 clnt_dot_c << " printf(\"Protocol verify - bad response from server\\n\");\n";
474 clnt_dot_c << " handle_error();";
475 clnt_dot_c << " exit(-1);\n";
476 clnt_dot_c << " }\n";
477 clnt_dot_c << " if ((version != " << version << ") || (strcmp(proto, \"" << name << "\"))) {\n";
478 clnt_dot_c << " printf(\"protocol " << name << " version " << version << " expected\\n\");\n",
479 clnt_dot_c << " printf(\"protocol %s version %d found\\n\", proto, version);\n";
480 clnt_dot_c << " exit(-1);\n";
481 clnt_dot_c << " }\n";
482 clnt_dot_c << " __xdrs__->x_op = XDR_FREE;\n";
483 clnt_dot_c << " xdr_String (__xdrs__, &proto);\n";
485 clnt_dot_c << "\n\n";
486 clnt_dot_c << name << "User::" << name << "User(int fd, xdrIOFunc r, xdrIOFunc w, int nblock):\n";
487 clnt_dot_c << "RPCUser(igen_no_err),\n";
488 clnt_dot_c << "XDRrpc(fd, r, w, nblock) {\n";
489 clnt_dot_c << " if (__xdrs__) verifyProtocolAndVersion();\n";
490 clnt_dot_c << " IGEN_in_call_handler = 0;\n";
492 clnt_dot_c << name << "User::" << name << "User(int family, int port, int type, char *machine, xdrIOFunc rf, xdrIOFunc wr, int nblock):\n";
493 clnt_dot_c << "RPCUser(igen_no_err),\n";
494 clnt_dot_c << "XDRrpc(family, port, type, machine, rf, wr, nblock) {\n";
495 clnt_dot_c << " if (__xdrs__) verifyProtocolAndVersion();\n";
496 clnt_dot_c << " IGEN_in_call_handler = 0;\n";
498 clnt_dot_c << name << "User::" << name << "User(char *m,char *l,char *p,xdrIOFunc r,xdrIOFunc w, char **args, int nblock):\n";
499 clnt_dot_c << "RPCUser(igen_no_err),\n";
500 clnt_dot_c << " XDRrpc(m, l, p, r, w, args, nblock, __wellKnownPortFd__) {\n";
501 clnt_dot_c << " if (__xdrs__) verifyProtocolAndVersion();\n";
502 clnt_dot_c << " IGEN_in_call_handler = 0;\n";
509 // generate code to perform protocol verification
511 void interfaceSpec::genProtoVerifyPVM()
513 // generate stub to verify version.
514 clnt_dot_c << "void " << name << "User::verifyProtocolAndVersion() {\n";
515 clnt_dot_c << " unsigned int __tag__;\n";
516 clnt_dot_c << " String proto;\n";
517 clnt_dot_c << " int version = -1;\n";
518 clnt_dot_c << " __tag__ = 0;\n";
519 clnt_dot_c << " // msgtag = 0 --> verify protocol\n";
520 clnt_dot_c << " assert (pvm_initsend(0) >= 0);\n";
521 clnt_dot_c << " pvm_send (get_other_tid(), 0);\n";
522 clnt_dot_c << " awaitResponce(0);\n";
523 clnt_dot_c << " IGEN_pvm_String (IGEN_PVM_DECODE, &proto);\n";
524 clnt_dot_c << " pvm_upkint(&(version), 1, 1);\n";
525 clnt_dot_c << " if ((version != " << version << " ) || (strcmp(proto, \"";
526 clnt_dot_c << name << "\"))) {\n";
527 clnt_dot_c << " printf(\"protocol " << name << " version " << version;
528 clnt_dot_c << " expected\\n\");\n";
529 clnt_dot_c << " printf(\"protocol %%s version %%d found\\n\", proto, version);\n";
530 clnt_dot_c << " pvm_exit(); exit(-1);\n";
531 clnt_dot_c << " }\n";
532 clnt_dot_c << " IGEN_pvm_String (IGEN_PVM_FREE, &proto);\n";
534 clnt_dot_c << "\n\n";
535 clnt_dot_c << name << "User::" << name << "User(char *w, char *p, char **a, int f):\n";
536 clnt_dot_c << "PVMrpc(w, p, a, f) {\n";
537 clnt_dot_c << "if (get_error() != -1) verifyProtocolAndVersion();\n";
538 clnt_dot_c << " IGEN_in_call_handler = 0;\n";
540 clnt_dot_c << name << "User::" << name << "User(int o):\n";
541 clnt_dot_c << "PVMrpc(o) {\n";
542 clnt_dot_c << "if (get_error() != -1) verifyProtocolAndVersion();\n";
543 clnt_dot_c << " IGEN_in_call_handler = 0;\n";
546 clnt_dot_c << name << "User::" << "User():\n";
547 clnt_dot_c << "PVMrpc() {\n";
548 clnt_dot_c << "if (get_error() != -1) verifyProtocolAndVersion();\n";
549 clnt_dot_c << " IGEN_in_call_handler = 0;\n";
555 void interfaceSpec::generateStubs(ofstream &output)
557 List <remoteFunc*> cf;
560 sprintf(className, "%sUser", name);
561 for (cf = methods; *cf; cf++) {
562 (*cf)->genStub(className, FALSE, output);
566 void interfaceSpec::generateClientCode()
569 genIncludes(clnt_dot_c);
571 // include client header
572 clnt_dot_c << "#include \"" << protoFile << "CLNT.h\"\n";
574 clnt_dot_c << "int " << name << "User::__wellKnownPortFd__;\n";
576 // generate the error handler for the client
577 genErrHandler(clnt_dot_c, TRUE);
578 } else if (generatePVM) {
579 genIncludes(clnt_dot_c);
581 // include client header
582 clnt_dot_c << "#include \"" << protoFile << "CLNT.h\"\n";
584 // generate the error handler for the client
585 genErrHandler(clnt_dot_c, TRUE);
588 // generate the error handler for the client
589 genErrHandler(dot_c, TRUE);
592 generateStubs(clnt_dot_c);
596 } else if (generatePVM) {
603 void interfaceSpec::generateBundlers()
607 for (cs = types; *cs; cs++) {
612 int main(int argc, char *argv[])
618 /* define pre-defined types */
619 (void) new typeDefn("int");
620 (void) new typeDefn("double");
621 (void) new typeDefn("String");
622 (void) new typeDefn("void");
623 (void) new typeDefn("Boolean");
624 (void) new typeDefn("u_int");
625 (void) new typeDefn("float");
629 for (i=0; i < argc-1; i++) {
630 if (!strcmp("-pvm", argv[i])) {
634 serverTypeName = pool.findAndAdd("int");
635 transportBase = "PVMrpc";
636 } if (!strcmp("-xdr", argv[i])) {
640 (void) new typeDefn("XDRptr");
641 serverTypeName = pool.findAndAdd("XDRptr");
642 transportBase = "XDRrpc";
643 } if (!strcmp("-thread", argv[i])) {
647 serverTypeName = pool.findAndAdd("int");
648 transportBase = "THREADrpc";
649 } else if (!strcmp("-header", argv[i])) {
652 } else if (!strcmp("-code", argv[i])) {
657 if (!emitHeader && !emitCode) {
660 if (!generatePVM && !generateXDR && !generateTHREAD) {
664 // build the list that contains PVM type information
668 protoFile = argv[argc-1];
670 yyin = fopen(protoFile, "r");
672 printf("unable to open %s\n", protoFile);
676 // skip to trailing component of file name.
677 temp = strrchr(protoFile, '/');
678 if (temp) protoFile = temp+1;
680 temp = strstr(protoFile, ".I");
682 printf("file names must end in .I\n");
688 // open the files for output
689 char *dump_to = new char[strlen(protoFile) + 10];
692 sprintf(dump_to, "%sh", protoFile);
693 dot_h.open(dump_to, ios::out);
694 assert(dot_h.good());
696 sprintf(dump_to, "%sC", protoFile);
697 dot_c.open(dump_to, ios::out);
698 assert(dot_c.good());
700 sprintf(dump_to, "%sSRVR.h", protoFile);
701 srvr_dot_h.open(dump_to, ios::out);
702 assert(srvr_dot_h.good());
704 sprintf(dump_to, "%sCLNT.h", protoFile);
705 clnt_dot_h.open(dump_to, ios::out);
706 assert(clnt_dot_h.good());
708 if (generateXDR || generatePVM)
710 sprintf(dump_to, "%sSRVR.C", protoFile);
711 srvr_dot_c.open(dump_to, ios::out);
712 assert(srvr_dot_c.good());
714 sprintf(dump_to, "%sCLNT.C", protoFile);
715 clnt_dot_c.open(dump_to, ios::out);
716 assert(clnt_dot_c.good());
722 assert(clnt_dot_c.good());
723 assert(srvr_dot_c.good());
729 len = strlen(protoFile);
730 prefix = new char[len];
731 strncpy (prefix, protoFile, len - 1);
732 prefix[len-1] = '\0';
734 dot_h << "#ifndef " << prefix << "BASE_H\n";
735 dot_h << "#define " << prefix << "BASE_H\n";
736 dot_h << "#include \"util/h/rpcUtil.h\"\n";
739 dot_h << "#include \"util/h/rpcUtilPVM.h\"\n";
741 dot_h << "#include <sys/types.h>\n";
744 dot_h << "#include <assert.h>\n";
746 dot_h << "#ifdef IGEN_ERR_ASSERT_ON\n";
747 dot_h << "#ifndef IGEN_ERR_ASSERT\n";
748 dot_h << "#define IGEN_ERR_ASSERT assert(0)\n";
751 dot_h << "#define IGEN_ERR_ASSERT\n";
752 dot_h << "#endif\n\n";
754 dot_h << "\n // Errors that can occur internal to igen\n";
755 dot_h << "#ifndef _IGEN_ERR_DEF\n";
756 dot_h << "#define _IGEN_ERR_DEF\n";
757 dot_h << "typedef enum e_IGEN_ERR {\n";
758 dot_h << " igen_no_err=0,\n";
759 dot_h << " igen_encode_err,\n";
760 dot_h << " igen_decode_err,\n";
761 dot_h << " igen_send_err,\n";
762 dot_h << " igen_read_err,\n";
763 dot_h << " igen_request_err,\n";
764 dot_h << " igen_call_err\n";
765 dot_h << " } IGEN_ERR;\n\n";
774 // this is opened in genClass
776 dot_h << "\n#endif\n";
780 if (!currentInterface) {
781 printf("no interface defined\n");
786 currentInterface->genIncludes(dot_c);
788 if (generateTHREAD) {
789 dot_c << "#include \"" << protoFile << "SRVR.h\"\n";
790 dot_c << "#include \"" << protoFile << "CLNT.h\"\n";
792 dot_c << "#include \"" << protoFile << "h\"\n";
798 if (generateXDR || generatePVM) currentInterface->generateBundlers();
800 currentInterface->generateServerCode();
802 currentInterface->generateClientCode();
824 char *interfaceSpec::genVariable()
829 ret = (char *) malloc(strlen(name)+10);
830 sprintf(ret, "%s__%d", name, count++);
834 int interfaceSpec::getNextTag()
839 // in_client == 1 when client headers are being generated
840 void remoteFunc::genMethodHeader(char *className, int in_client,
848 current << retType << " " << className << "::" << name << "(";
850 // figure out if "virtual" should be printed
852 // for the client --> if it is an upcall then print virtual
853 // for the server --> if it is not an upcall the print virtual
854 // for both an additional constraint is that virtual_f must be true
855 if ((((upcall == syncUpcall) || (upcall == asyncUpcall)) && virtual_f && in_client) ||
856 (!in_client && virtual_f && ((upcall == asyncCall) || (upcall == syncCall))))
859 current << "virtual " << retType << " " << name << "(";
863 // don't print virtual
864 current << retType << " " << name << "(";
867 for (lp = args, spitOne = 0; *lp; lp++)
869 if (spitOne) current << ",";
871 current << (*lp)->type << " ";
873 for (cl = *(*lp)->stars; *cl; cl++)
875 current << (*lp)->name;
877 if (!spitOne) current << "void";
881 // forUpcalls == TRUE -> when client code is being generated
882 // client code is being generated to handle upcalls in awaitResponce
884 // this procedure prints code under 2 circumstances
885 // 1- (client code) forUpcalls == TRUE, call must be an upcall
886 // 2- (server code) forUpcalls == FALSE, call must not be an upcall
888 void remoteFunc::genSwitch(Boolean forUpcalls, char *ret_str, ofstream &output)
891 List <argument *> ca;
893 // return if generating client code, and call is not an upcall
895 ((upcall == syncCall) || (upcall == asyncCall)))
898 // return if generating server code, and call is an upcall
899 if (!forUpcalls && (upcall != syncCall) && (upcall != asyncCall))
902 output << " case " << spec->getName() << "_" << name << "_REQ:\n";
904 // print out the return type
905 if ((generateTHREAD) && (upcall != asyncUpcall) && (upcall != asyncCall))
906 // output << " int __val__;\n";
910 if (strcmp(retType, "void")) {
911 output << " " << retType << " __ret__;\n";
914 // print out the local types
916 output << " // extern xdr_" << retType << "(XDR*, " << retType << "*);\n";
918 output << " " << structName << " __recvBuffer__;\n";
919 for (ca = args; *ca; ca++) {
920 output << " if (xdr_" << (*ca)->type << "(__xdrs__, &__recvBuffer__.";
921 output << (*ca)->name << ") == FALSE)\n";
923 output << " err_state = igen_decode_err;\n";
924 output << " handle_error();\n";
925 output << " return " << ret_str << ";\n";
930 } else if (generatePVM) {
931 output << " extern IGEN_pvm_" << retType << "(IGEN_PVM_FILTER, " << retType << "*);\n";
932 if ((upcall != asyncUpcall) && (upcall != asyncCall))
933 output << " assert(pvm_initsend(0) >= 0);\n";
935 output << " " << structName << " __recvBuffer__;\n";
936 for (ca = args; *ca; ca++) {
937 output << " IGEN_pvm_" << (*ca)->type << "(IGEN_PVM_DECODE, &__recvBuffer__." << (*ca)->name << ");\n";
943 // to determine when sync upcalls cannot be made
945 (upcall == asyncUpcall || upcall == asyncCall))
946 output << " IGEN_in_call_handler = 1;\n";
948 if (strcmp(retType, "void")) {
949 output << " __ret__ = " << name << "(";
951 output << " " << name << "(";
954 for (ca = args, first = 1; *ca; ca++) {
955 if (!first) output << ",";
957 if (generateTHREAD) {
958 output << "__recvBuffer__." << name << "." << (*ca)->name;
959 } else if (generateXDR) {
960 output << "__recvBuffer__." << (*ca)->name;
961 } else if (generatePVM) {
962 output << "__recvBuffer__." << (*ca)->name;
967 // to determine when sync upcalls cannot be made
969 (upcall == asyncUpcall || upcall == asyncCall))
970 output << " IGEN_in_call_handler = 0;\n";
972 if (generateTHREAD && (upcall != asyncUpcall) && (upcall != asyncCall)) {
973 if (strcmp(retType, "void")) {
974 output << " __val__ = msg_send(requestingThread, ";
975 output << spec->getName();
976 output << "_" << name << "_RESP, (void *) &__ret__, sizeof(";
977 output << retType << "));\n";
979 output << " __val__ = msg_send(requestingThread, ";
980 output << spec->getName();
981 output << "_" << name << "_RESP, NULL, 0);\n";
983 // output << " if (__val__ != THR_OKAY)\n";
985 // output << " err_state = igen_send_error;\n";
986 // output << " handle_error();\n";
987 // output << " return " << ret_str << ";\n";
989 } else if (generateXDR && (upcall != asyncUpcall) && (upcall != asyncCall)) {
990 output << " __xdrs__->x_op = XDR_ENCODE;\n";
991 output << " __tag__ = " << spec->getName() << "_" << name;
992 output << "_RESP;\n";
993 output << " if (xdr_int(__xdrs__, &__tag__) == FALSE)\n";
995 output << " err_state = igen_encode_err;\n";
996 output << " handle_error();\n";
997 output << " return " << ret_str << ";\n";
999 if (strcmp(retType, "void")) {
1000 output << " if (xdr_" << retType << "(__xdrs__,&__ret__) == FALSE)\n";
1002 output << " err_state = igen_encode_err;\n";
1003 output << " handle_error();\n";
1004 output << " return " << ret_str << ";\n";
1007 output << " if (xdrrec_endofrecord(__xdrs__, TRUE) == FALSE)\n";
1009 output << " err_state = igen_send_err;\n";
1010 output << " handle_error();\n";
1011 output << " return " << ret_str << ";\n";
1013 } else if (generatePVM && (upcall != asyncUpcall) && (upcall != asyncCall)) {
1014 output << " __tag__ = " << spec->getName() << "_" << name << "_RESP;\n";
1015 if (strcmp(retType, "void")) {
1016 output << " IGEN_pvm_" << retType << " (IGEN_PVM_ENCODE,&__ret__);\n";
1018 output << " assert (pvm_send (__tid__, __tag__) >= 0);\n";
1021 // free allocated memory
1025 else if (generateXDR)
1027 output << " __xdrs__->x_op = XDR_FREE;\n";
1030 for (ca = args; *ca; ca++)
1032 // only if Array or string or user defined
1034 output << " xdr_" << (*ca)->type << "(__xdrs__, &__recvBuffer__." << (*ca)->name<< ");\n";
1038 output << " xdr_" << retType << "(__xdrs__, &__ret__);\n";
1040 else if (generatePVM)
1044 for (ca = args; *ca; ca++)
1046 // only if Array or string
1048 output << " IGEN_pvm_" << (*ca)->type;
1049 output << "(IGEN_PVM_FREE, &__recvBuffer__." << (*ca)->name << ");\n";
1053 output << " IGEN_pvm_" << retType << "(IGEN_PVM_FREE, &__ret__);\n";
1056 output << " }\n break;\n\n";
1060 // generates the stub code for the client or the server
1062 void remoteFunc::genThreadStub(char *className, ofstream &output)
1066 char *structUseName = spec->genVariable();
1068 genMethodHeader(className, 0, output);
1072 output << " struct " << structName << " " << structUseName << ";\n";
1073 if ((upcall != asyncUpcall) && (upcall != asyncCall))
1074 output << " unsigned int __tag__;\n";
1075 if (strcmp(retType, "void"))
1076 output << " unsigned int __len__;\n";
1077 output << " int __val__;\n";
1078 if (strcmp(retType, "void")) {
1079 retVar = spec->genVariable();
1080 output << " " << retType << " " << retVar << ";\n";
1083 retVar = strdup(" ");
1085 output << " if (err_state != igen_no_err)\n";
1087 output << " IGEN_ERR_ASSERT;\n";
1088 output << " return " << retVar << ";\n";
1091 for (lp = args; *lp; lp++) {
1092 output << " " << structUseName << "." << (*lp)->name << " = ";
1093 output << (*lp)->name << "; \n";
1096 output << " __val__ = msg_send(tid, " << spec->getName() << "_";
1097 output << name << "_REQ, (void *) &";
1098 output << structUseName << ", sizeof(" << structUseName << "));\n";
1100 output << " __val__ = msg_send(tid, " << spec->getName() << "_";
1101 output << name << "_REQ, NULL, 0); \n";
1103 output << " if (__val__ != THR_OKAY)\n";
1105 output << " err_state = igen_send_err;\n";
1106 output << " handle_error();\n";
1107 output << " return " << retVar << " ;\n";
1109 if ((upcall != asyncUpcall) && (upcall != asyncCall)) {
1110 output << " __tag__ = " << spec->getName() << "_" << name << "_RESP;\n";
1111 if (strcmp(retType, "void")) {
1112 output << " __len__ = sizeof(" << retVar << ");\n";
1113 output << " if (msg_recv(&__tag__, (void *) &" << retVar;
1114 output << ", &__len__)\n == THR_ERR) \n";
1116 output << " err_state = igen_read_err;\n";
1117 output << " handle_error();\n";
1118 output << " return " << retVar << " ;\n";
1120 output << " if (__len__ != sizeof(" << retVar << "))\n";
1122 output << " err_state = igen_read_err;\n";
1123 output << " handle_error();\n";
1124 output << " return " << retVar << " ;\n";
1127 output << " if (msg_recv(&__tag__, NULL, 0) == THR_ERR)\n";
1129 output << " err_state = igen_read_err;\n";
1130 output << " handle_error();\n";
1131 output << " return " << retVar << " ;\n";
1135 output << " if (__tag__ != " << spec->getName() << "_" << name;
1136 output << "_RESP)\n";
1138 output << " err_state = igen_read_err;\n";
1139 output << " handle_error();\n";
1140 output << " return " << retVar << " ;\n";
1143 output << " return " << retVar << " ;\n";
1148 void remoteFunc::genXDRStub(char *className, ofstream &output)
1154 genMethodHeader(className, 0, output);
1157 output << " unsigned int __tag__;\n";
1158 if (strcmp(retType, "void"))
1160 retVar = spec->genVariable();
1161 output << " " << retType << " " << retVar << ";\n";
1165 retVar = strdup(" ");
1167 output << " if (err_state != igen_no_err)\n";
1169 output << " IGEN_ERR_ASSERT;\n";
1170 output << " return " << retVar << ";\n";
1173 if ((upcall == syncUpcall) || (upcall == syncCall))
1175 output << " if (IGEN_in_call_handler)\n";
1177 output << " fprintf(stderr, \"cannot do sync call when in async call handler\\n\");\n";
1178 output << " IGEN_ERR_ASSERT;\n";
1179 output << " err_state = igen_call_err;\n";
1180 output << " return " << retVar << ";\n";
1184 // check to see protocol verify has been done.
1185 if ((upcall != syncCall) && (upcall != asyncCall)) {
1186 output << " if (!__versionVerifyDone__)\n";
1188 output << " // handle error is called for errors\n";
1189 output << " if (!look_for_verify() && !verify_protocol())\n";
1190 output << " __versionVerifyDone__ = TRUE;\n";
1191 output << " else\n";
1192 output << " return " << retVar << " ;\n";
1195 output << " __tag__ = " << spec->getName() << "_" << name << "_REQ;\n";
1196 output << " __xdrs__->x_op = XDR_ENCODE;\n";
1198 // the error check depends on short circuit boolean expression evaluation!
1199 output << " if ((xdr_int(__xdrs__, &__tag__) != TRUE)\n";
1200 for (lp = args; *lp; lp++)
1202 output << " || (xdr_" << (*lp)->type << "(__xdrs__, &";
1203 output << (*lp)->name << ") != TRUE)\n";
1207 output << " err_state = igen_encode_err;\n";
1208 output << " handle_error();\n";
1209 output << " return " << retVar << " ;\n";
1211 output << " if(!xdrrec_endofrecord(__xdrs__, TRUE))\n";
1213 output << " err_state = igen_send_err;\n";
1214 output << " handle_error();\n";
1215 output << " return " << retVar << " ;\n";
1218 if ((upcall != asyncUpcall) && (upcall != asyncCall))
1220 if (upcall == syncCall)
1222 output << " awaitResponce(" << spec->getName() << "_";
1223 output << name << "_RESP);\n";
1225 else if (upcall == syncUpcall)
1227 output << " int res;\n";
1228 output << " while (!(res = mainLoop())) ;\n";
1229 output << " if (res != " << spec->getName() << "_" << name << "_RESP)\n";
1230 output << " { err_state = igen_request_err; handle_error(); return ";
1232 output << "(" << retVar << ");}\n";
1236 output << " if (err_state != igen_no_err)\n";
1237 output << " return " << retVar << ";\n";
1239 if (strcmp(retType, "void"))
1241 output << " __xdrs__->x_op = XDR_DECODE;\n";
1242 output << " if (xdr_" << retType << "(__xdrs__, &(";
1243 output << retVar << ")) == FALSE)\n";
1245 output << " err_state = igen_decode_err;\n";
1246 output << " handle_error();\n";
1247 output << " return " << retVar << " ;\n";
1250 output << " return(" << retVar << ");\n";
1256 void remoteFunc::genPVMStub(char *className, ofstream &output)
1259 char *retVar = spec->genVariable();
1261 genMethodHeader(className, 0, output);
1264 output << " unsigned int __tag__;\n";
1265 if (strcmp(retType, "void")) {
1266 output << " " << retType << " " << retVar << ";\n";
1269 output << " if (err_state != igen_no_err)\n";
1271 output << " IGEN_ERR_ASSERT;\n";
1272 output << " return " << retVar << ";\n";
1275 output << " __tag__ = " << spec->getName() << "_" << name << "_REQ;\n";
1276 output << " assert(pvm_initsend(0) >= 0);\n";
1277 for (lp = args; *lp; lp++) {
1278 output << " IGEN_pvm_" << (*lp)->type << " (IGEN_PVM_ENCODE, &" << (*lp)->name << ");\n";
1280 output << " pvm_send ( get_other_tid(), __tag__);\n";
1281 if (upcall != asyncUpcall)
1283 if (upcall == syncCall)
1285 output << " awaitResponce(" << spec->getName() << "_" << name << "_RESP);\n";
1287 else if (upcall == syncUpcall)
1289 output << " if (pvm_recv(-1, " << spec->getName() << "_" << name << "_RESP) < 0) abort();\n";
1291 if (strcmp(retType, "void"))
1293 output << " IGEN_pvm_" << retType << "(IGEN_PVM_DECODE, &(" << retVar << ")); \n";
1294 output << " return(" << retVar << ");\n";
1300 void remoteFunc::genStub(char *className, Boolean forUpcalls, ofstream &output)
1302 if (forUpcalls && ((upcall == syncCall) || (upcall == asyncCall))) return;
1303 if (!forUpcalls && (upcall != syncCall) && (upcall != asyncCall)) return;
1308 genXDRStub(className, output);
1309 } else if (generateTHREAD) {
1310 genThreadStub(className, output);
1311 } else if (generatePVM) {
1312 genPVMStub(className, output);
1316 void remoteFunc::genHeader()
1321 dot_h << "struct " << structName << " {\n";
1322 for (lp = args; *lp; lp++) {
1323 dot_h << " " << (*lp)->type << " ";
1324 for (cl = *(*lp)->stars; *cl; cl++)
1326 dot_h << (*lp)->name;
1331 dot_h << "#define " << spec->getName() << "_" << name << "_REQ " << spec->getNextTag() << "\n";
1332 dot_h << "#define " << spec->getName() << "_" << name << "_RESP " << spec->getNextTag() << "\n";
1335 void typeDefn::genHeader()
1339 dot_h << "#ifndef " << name << "_TYPE\n";
1340 dot_h << "#define " << name << "_TYPE\n";
1341 dot_h << "class " << name << " { \npublic:\n";
1343 dot_h << " int count;\n";
1344 dot_h << " " << type << "* data;\n";
1346 for (fp = fields; *fp; fp++) {
1347 (*fp)->genHeader(dot_h);
1351 dot_h << "#endif\n";
1354 if (userDefined) dot_h << "extern xdr_" << name << "(XDR*, " << name << "*);\n";
1355 } else if (generatePVM) {
1356 if (userDefined) dot_h << "extern IGEN_pvm_" << name << "(IGEN_PVM_FILTER, " << name << "*);\n";
1361 // this is only called if generatePVM or generateXDR is TRUE
1362 // this is not called for generateTHREAD since no bundling is done since everything
1363 // exists in the same address space
1364 // builds data bundlers - code that bundles user defined structures for the transport
1365 // note - the basic filters {string, int, ...} are taken care of elsewhere
1368 // how are bundlers built
1369 // each bundler has an if branch and an else branch. The if branch is taken if the
1370 // request is to free memory, otherwise the else branch is taken. If the type of the
1371 // bundler is an array of <x>, each element of the array must have its bundler called
1372 // in the if branch. If the bundler is not an array of some type, but is a structure,
1373 // with fields, the bundlers for each field is called.
1375 void typeDefn::genBundler()
1380 if (!userDefined) return;
1382 // the code for the if branch - taken to free memory
1385 // build the handlers for xdr
1386 dot_c << "bool_t xdr_" << name << "(XDR *__xdrs__, " << name << " *__ptr__) {\n";
1387 dot_c << " if (__xdrs__->x_op == XDR_FREE) {\n";
1389 // note - a user defined type contains an array of other types, each element in the
1390 // array must be freed
1393 assert (foundType = types.find(type));
1394 if (foundType->userDefined == TRUE)
1396 dot_c << " int i;\n";
1397 dot_c << " for (i=0; i<__ptr__->count; ++i)\n";
1398 dot_c << " if (!xdr_" << type << "(__xdrs__, &(__ptr__->data[i])))\n";
1399 dot_c << " return FALSE;\n";
1401 // free the memory used for this structure
1402 dot_c << " free ((char*) __ptr__->data);\n";
1403 dot_c << " __ptr__->data = 0;\n";
1404 dot_c << " __ptr__->count = 0;\n";
1407 else for (fp = fields; *fp; fp++) {
1408 // xdr - non-array types
1409 // call the bundler for each element of this user defined type
1410 // don't call for non-user defined types such as {int, char, bool}
1411 // since those will not have had memory allocated for them
1412 foundType = types.find((*fp)->getType());
1414 if (foundType->userDefined ||
1415 foundType->arrayType ||
1416 !(strcmp("String", foundType->name)))
1417 (*fp)->genBundler(dot_c);
1419 } else if (generatePVM) {
1420 // build the handlers for PVM
1421 dot_c << "bool_t IGEN_pvm_" << name << "(IGEN_PVM_FILTER __dir__, " << name << " *__ptr__) {\n";
1422 dot_c << " if (__dir__ == IGEN_PVM_FREE) {\n";
1424 // free the array of user defined types
1425 // this calls the bundlers
1428 assert (foundType = types.find(type));
1429 if (foundType->userDefined == TRUE)
1431 dot_c << " int i;\n";
1432 dot_c << " for (i=0; i<__ptr__->count; ++i)\n";
1433 dot_c << " if (!IGEN_pvm_" << type << "(__dir__, &(__ptr__->data[i])))\n";
1434 dot_c << " return FALSE;\n";
1436 dot_c << " free ((char*) __ptr__->data);\n";
1437 dot_c << " __ptr__->data = 0;\n";
1438 dot_c << " __ptr__->count = 0;\n";
1440 else for (fp = fields; *fp; fp++) {
1441 foundType = types.find((*fp)->getType());
1443 if (foundType->userDefined ||
1444 foundType->arrayType ||
1445 !(strcmp("String", foundType->name)))
1446 (*fp)->genBundler(dot_c);
1449 dot_c << " } else {\n";
1451 // the code for the else branch - taken to encode or decode
1455 dot_c << "if (__xdrs__->x_op == XDR_DECODE) __ptr__->data = NULL;\n";
1456 dot_c << " if (xdr_array(__xdrs__, &(__ptr__->data), &__ptr__->count, ~0, sizeof(";
1457 dot_c << type << "), xdr_" << type << ") == FALSE)\n";
1458 dot_c << " return FALSE;\n";
1459 } else if (generatePVM) {
1460 dot_c << " IGEN_pvm_Array_of_" << type << "(__dir__, &(__ptr__->data),&(__ptr__->count));\n";
1463 for (fp = fields; *fp; fp++)
1464 (*fp)->genBundler(dot_c);
1467 dot_c << " return(TRUE);\n";
1472 char *findAndAddArrayType(char *name)
1476 char *arrayTypeName;
1478 // now find the associated array type.
1479 sprintf(temp, "%s_Array", name);
1480 arrayTypeName = pool.findAndAdd(temp);
1481 if (!types.find(arrayTypeName)) {
1482 s = new typeDefn(arrayTypeName, name);
1485 return arrayTypeName;
1489 print_pass_thru_clnt (const char *the_string)
1491 clnt_dot_h << " " << the_string << ";\n";
1495 print_pass_thru_srvr (const char *the_string)
1497 srvr_dot_h << " " << the_string << ";\n";
1500 // changed to print to separate files, one include for the server, and
1501 // one for the client
1502 // g++ was attempting to link the virtual functions for the client in the
1505 void interfaceSpec::genClass()
1507 List <remoteFunc *> curr;
1511 clnt_dot_h << "#ifndef _" << name << "CLNT_H\n";
1512 clnt_dot_h << "#define _" << name << "CLNT_H\n";
1513 clnt_dot_h << "#include \"" << protoFile << "h\"\n\n";
1514 clnt_dot_h << "class " << name << "User: public RPCUser, public " << transportBase << " {\n";
1515 clnt_dot_h << " public:\n";
1516 client_pass_thru.map(&print_pass_thru_clnt);
1517 clnt_dot_h << " static int __wellKnownPortFd__;\n";
1520 clnt_dot_h << " virtual void verifyProtocolAndVersion();\n";
1521 clnt_dot_h << " " << name << "User(int fd, xdrIOFunc r, xdrIOFunc w, int nblock=0);\n";
1522 clnt_dot_h << " " << name << "User(int family, int port, int type, char *host, xdrIOFunc rf, xdrIOFunc wf, int nblock=0);\n";
1523 clnt_dot_h << " " << name << "User(char *machine, char *login, char *program, xdrIOFunc r, xdrIOFunc w, char **args=0, int nblock=0);\n";
1524 } else if (generatePVM) {
1525 clnt_dot_h << " virtual void verifyProtocolAndVersion();\n";
1526 clnt_dot_h << " " << name << "User(char *w, char *p, char **a, int f);\n";
1527 clnt_dot_h << " " << name << "User(int other);\n";
1528 clnt_dot_h << " " << name << "User();\n";
1529 } else if (generateTHREAD) {
1530 clnt_dot_h << " " << name << "User(int tid): THREADrpc(tid), RPCUser(igen_no_err) {}\n";
1533 clnt_dot_h << " void awaitResponce(int);\n";
1534 clnt_dot_h << " int isValidUpCall(int);\n";
1536 for (curr = methods; *curr; curr++) {
1538 (*curr)->genMethodHeader(NULL, 1, clnt_dot_h);
1539 clnt_dot_h << ";\n";
1541 clnt_dot_h << " protected:\n";
1542 clnt_dot_h << " virtual void handle_error();\n";
1543 clnt_dot_h << " int IGEN_in_call_handler;\n";
1544 clnt_dot_h << "};\n";
1545 clnt_dot_h << "#endif\n";
1547 srvr_dot_h << "#ifndef _" << name << "SRVR_H\n";
1548 srvr_dot_h << "#define _" << name << "SRVR_H\n";
1549 srvr_dot_h << "#include \"" << protoFile << "h\"\n\n";
1550 srvr_dot_h << "class " << name << ": protected RPCServer, public " << transportBase << " {\n";
1551 srvr_dot_h << " public:\n";
1553 server_pass_thru.map(&print_pass_thru_srvr);
1556 srvr_dot_h << " " << name << "();\n";
1557 srvr_dot_h << " " << name << "(int o);\n";
1558 srvr_dot_h << " " << name << "(char *w, char *p, char **a, int f);\n";
1560 else if (generateXDR) {
1561 srvr_dot_h << " " << name << "(int family, int port, int type, char *host, xdrIOFunc rf, xdrIOFunc wf, int nblock=0);\n";
1562 srvr_dot_h << " " << name << "(int fd, xdrIOFunc r, xdrIOFunc w, int nblock=0);\n";
1563 srvr_dot_h << " " << name << "(char *m, char *l, char *p, xdrIOFunc r, xdrIOFunc w, char **args=0, int nblock=0);\n";
1564 srvr_dot_h << " verify_protocol();\n";
1565 srvr_dot_h << " look_for_verify();\n";
1566 } else if (generateTHREAD) {
1567 srvr_dot_h << " " << name << "(int tid): THREADrpc(tid), RPCServer(igen_no_err) {}\n";
1569 srvr_dot_h << " mainLoop(void);\n";
1571 for (curr = methods; *curr; curr++) {
1573 (*curr)->genMethodHeader(NULL, 0, srvr_dot_h);
1574 srvr_dot_h << ";\n";
1576 if (generatePVM || generateXDR) {
1577 srvr_dot_h << " void set_versionVerifyDone(bool_t val)\n";
1578 srvr_dot_h << " { __versionVerifyDone__ = val;}\n";
1580 srvr_dot_h << " protected:\n";
1581 srvr_dot_h << " virtual void handle_error();\n";
1582 srvr_dot_h << " bool_t __versionVerifyDone__;\n";
1583 srvr_dot_h << " int IGEN_in_call_handler;\n";
1584 srvr_dot_h << "};\n\n";
1585 srvr_dot_h << "#endif\n";
1589 // builds filters for PVM to go into *.C
1590 // these filters are similar to the xdr_TYPE {TYPE = int, char...}
1591 // these filters are meant to be bidirectional
1592 // these filters will malloc for arrays and strings
1597 dot_c << "bool_t IGEN_pvm_String (IGEN_PVM_FILTER direction, String *data) {\n";
1598 dot_c << " int buf_id, bytes, msgtag, tid;\n";
1599 dot_c << " assert(data);\n";
1600 dot_c << " switch (direction) \n";
1602 dot_c << " case IGEN_PVM_DECODE:\n";
1603 dot_c << " buf_id = pvm_getrbuf();\n";
1604 dot_c << " if (buf_id == 0) return (FALSE);\n";
1605 dot_c << " if (pvm_bufinfo(buf_id, &bytes, &msgtag, &tid) < 0) return(FALSE);\n";
1606 dot_c << " *data = (String) new char[bytes+1];\n";
1607 dot_c << " if (!(*data)) return (FALSE);\n";
1608 dot_c << " data[bytes] = '\\0';\n";
1609 dot_c << " if (pvm_upkstr(*data) < 0) return (FALSE);\n";
1610 dot_c << " break;\n";
1611 dot_c << " case IGEN_PVM_ENCODE:\n";
1612 dot_c << " if (pvm_pkstr (*data) < 0) return (FALSE);\n";
1613 dot_c << " break;\n";
1614 dot_c << " case IGEN_PVM_FREE:\n";
1615 dot_c << " delete [] (*data);\n";
1616 dot_c << " *data = 0;\n";
1617 dot_c << " break;\n";
1618 dot_c << " default:\n";
1619 dot_c << " assert(0);\n";
1621 dot_c << " return(TRUE);\n}\n";
1623 pvm_types.map(&templatePVMscalar);
1624 pvm_types.map(&templatePVMarray);
1629 templatePVMscalar (const pvm_args *the_arg)
1631 if (!the_arg || !(the_arg->type_name) || !(the_arg->pvm_name)) return;
1633 dot_c << "bool_t IGEN_pvm_" << the_arg->type_name << " (IGEN_PVM_FILTER direction,";
1634 dot_c << the_arg->type_name << " *data) {\n";
1635 dot_c << " assert(data);\n";
1636 dot_c << " switch (direction)\n";
1638 dot_c << " case IGEN_PVM_DECODE:\n";
1639 dot_c << " if (pvm_upk" << the_arg->pvm_name << " (data, 1, 1) < 0)\n";
1640 dot_c << " return (FALSE);\n";
1641 dot_c << " break;\n";
1642 dot_c << " case IGEN_PVM_ENCODE:\n";
1643 dot_c << " if (pvm_pk" << the_arg->pvm_name << " (data, 1, 1) < 0)\n";
1644 dot_c << " return (FALSE);\n";
1645 dot_c << " break;\n";
1646 dot_c << " case IGEN_PVM_FREE:\n";
1647 dot_c << " break;\n";
1648 dot_c << " default:\n";
1649 dot_c << " assert(0);\n";
1651 dot_c << " return(TRUE);\n";
1656 templatePVMarray (const pvm_args * the_arg)
1659 !(the_arg->type_name) ||
1660 !(the_arg->pvm_name) ||
1663 dot_c << "bool_t IGEN_pvm_Array_of_" << the_arg->type_name << " (IGEN_PVM_FILTER dir, ";
1664 dot_c << the_arg->type_name << " **data, int *count) {\n";
1665 dot_c << " int bytes, msgtag, tid;\n";
1666 dot_c << " switch (dir)\n";
1668 dot_c << " case IGEN_PVM_DECODE:\n";
1669 dot_c << " int buf_id = pvm_getrbuf();\n";
1670 dot_c << " if (buf_id == 0) return (FALSE);\n";
1671 dot_c << " if (pvm_bufinfo(buf_id, &bytes, &msgtag, &tid) < 0) return(FALSE);\n";
1672 dot_c << " *count = bytes " << the_arg->arg << ";\n";
1673 dot_c << " *data = (" << the_arg->type_name << " *) new char[*count];\n";
1674 dot_c << " if (!(*data)) return (FALSE);\n";
1675 dot_c << " if (pvm_upk" << the_arg->pvm_name << " (*data, *count, 1) < 0) return (FALSE);\n";
1676 dot_c << " break;\n";
1677 dot_c << " case IGEN_PVM_ENCODE:\n";
1678 dot_c << " if (pvm_pk" << the_arg->pvm_name << " (*data, *count, 1) < 0) return (FALSE);\n";
1679 dot_c << " break;\n";
1680 dot_c << " case IGEN_PVM_FREE:\n";
1681 dot_c << " delete [] (*data);\n";
1682 dot_c << " break;\n";
1683 dot_c << " default:\n";
1684 dot_c << " assert(0);\n";
1686 dot_c << " return(TRUE);\n";
1692 // generate the pvm specific includes for _.h
1697 dot_h << "enum IGEN_PVM_FILTER {IGEN_PVM_ENCODE, IGEN_PVM_DECODE, IGEN_PVM_FREE};\n\n";
1698 dot_h << "bool_t IGEN_pvm_String (IGEN_PVM_FILTER direction, String *data);\n";
1699 pvm_types.map(&PVM_map_scalar_includes);
1700 pvm_types.map(&PVM_map_array_includes);
1703 // the constructor for the pvm constructor class
1704 void genPVMServerCons(char *name)
1706 srvr_dot_c << name << "::" << name << " (char *w, char *p, char **a, int f):\n";
1707 srvr_dot_c << "PVMrpc(w, p, a, f) {\n";
1708 srvr_dot_c << " __versionVerifyDone__ = FALSE; IGEN_in_call_handler = 0;}\n";
1709 srvr_dot_c << name << "::" << name << " (int o):\n";
1710 srvr_dot_c << "PVMrpc(o) {\n";
1711 srvr_dot_c << " __versionVerifyDone__ = FALSE; IGEN_in_call_handler = 0;}\n";
1712 srvr_dot_c << name << "::" << name << " ():\n";
1713 srvr_dot_c << "PVMrpc() {\n";
1714 srvr_dot_c << " __versionVerifyDone__ = FALSE; IGEN_in_call_handler = 0;}\n";
1717 // the constructor for the xdr server class
1718 void genXDRServerCons(char *name)
1720 srvr_dot_c << name << "::" << name << "(int family, int port, int type, char *host, xdrIOFunc rf, xdrIOFunc wf, int nblock):\n";
1721 srvr_dot_c << "XDRrpc(family, port, type, host, rf, wf, nblock),\n";
1722 srvr_dot_c << "RPCServer(igen_no_err)\n";
1723 srvr_dot_c << " { __versionVerifyDone__ = FALSE; IGEN_in_call_handler = 0;}\n";
1724 srvr_dot_c << name << "::" << name << "(int fd, xdrIOFunc r, xdrIOFunc w, int nblock):\n";
1725 srvr_dot_c << "XDRrpc(fd, r, w, nblock),\n";
1726 srvr_dot_c << "RPCServer(igen_no_err)\n";
1727 srvr_dot_c << " { __versionVerifyDone__ = FALSE; IGEN_in_call_handler = 0;}\n";
1729 srvr_dot_c << name << "::" << name << "(char *m,char *l,char *p,xdrIOFunc r,xdrIOFunc w, char **args, int nblock):\n";
1730 srvr_dot_c << " XDRrpc(m, l, p, r, w, args, nblock),\n";
1731 srvr_dot_c << " RPCServer(igen_no_err)\n";
1732 srvr_dot_c << " { __versionVerifyDone__ = FALSE; IGEN_in_call_handler = 0;}\n";
1736 buildPVMargs_ptr (char *type_name, char *pvm_name, char *arg)
1738 pvm_args *arg_ptr = NULL;
1740 if (!pvm_name || !type_name)
1743 arg_ptr = (pvm_args *) malloc (sizeof(pvm_args));
1747 arg_ptr->type_name = (char *) malloc (strlen(type_name) + 1);
1748 arg_ptr->pvm_name = (char *) malloc (strlen(type_name) + 1);
1751 arg_ptr->arg = (char *) malloc (strlen(arg) + 1);
1752 if (!(arg_ptr->arg)) return NULL;
1753 if (!strcpy (arg_ptr->arg, arg)) return NULL;
1755 if (!(arg_ptr->type_name) || !(arg_ptr->pvm_name))
1758 if (!strcpy (arg_ptr->pvm_name, pvm_name)) return NULL;
1759 if (!strcpy (arg_ptr->type_name, type_name)) return NULL;
1765 // builds List pvm_types with PVM type information
1766 // this list is used by 2 procedures
1771 pvm_args *arg_ptr = 0;
1773 pvm_args *buildPVMargs_ptr (char *type_name, char *pvm_name, char *arg);
1775 assert (arg_ptr = buildPVMargs_ptr ("int", "int", " >> 2 "));
1776 pvm_types.add(arg_ptr);
1778 assert (arg_ptr = buildPVMargs_ptr ("char", "byte", " "));
1779 pvm_types.add(arg_ptr);
1781 assert (arg_ptr = buildPVMargs_ptr ("float", "float", " >> 2 "));
1782 pvm_types.add(arg_ptr);
1784 assert (arg_ptr = buildPVMargs_ptr ("double", "double", " >> 3 "));
1785 pvm_types.add(arg_ptr);
1787 assert (arg_ptr = buildPVMargs_ptr ("u_int", "uint", " >> 2 "));
1788 pvm_types.add(arg_ptr);
1792 PVM_map_scalar_includes (const pvm_args * the_arg)
1794 if (!the_arg || !(the_arg->type_name))
1796 dot_h << "bool_t IGEN_pvm_" << the_arg->type_name << " (IGEN_PVM_FILTER direction, ";
1797 dot_h << the_arg->type_name << " *data);\n";
1801 PVM_map_array_includes (const pvm_args * the_arg)
1803 if (!the_arg || !(the_arg->type_name))
1805 dot_h << "bool_t IGEN_pvm_Array_of_" << the_arg->type_name << " (IGEN_PVM_FILTER ";
1806 dot_h << "direction, " << the_arg->type_name << " **data, int *count);\n";
1810 add_to_list (char *type, char *name, List<char*> *ptrs, List<char*> *holder)
1817 count = ptrs->count();
1819 ptr_string = new char[count + 1];
1820 ptr_string[0] = '\0';
1821 for (i=0; i < count; ++i)
1822 ptr_string[i] = '*';
1823 ptr_string[count] = '\0';
1825 new_length = strlen(type) + strlen(name) + 3 + count;
1826 new_string = new char[new_length];
1828 sprintf (new_string, "%s %s %s", type, ptr_string, name);
1829 holder->add (new_string);
1833 addCMember (char *type, char *name, List<char*> *ptrs)
1835 add_to_list (type, name, ptrs, &client_pass_thru);
1839 addSMember (char *type, char *name, List<char*> *ptrs)
1841 add_to_list (type, name, ptrs, &server_pass_thru);
1845 dump_to_dot_h(char *msg)
1850 void interfaceSpec::genXDRServerVerifyProtocol()
1852 srvr_dot_c << " int " << name << "::verify_protocol()\n";
1853 srvr_dot_c << " {\n";
1854 srvr_dot_c << " char *__ProtocolName__ = \"" << name << "\";\n";
1855 srvr_dot_c << " int __val__;\n";
1856 srvr_dot_c << " int __sig__ = 0;\n";
1857 srvr_dot_c << " __xdrs__->x_op = XDR_ENCODE;\n";
1858 srvr_dot_c << " __val__ = " << version << ";\n";
1859 srvr_dot_c << " if ((xdr_int(__xdrs__, &__sig__) == FALSE) ||\n";
1860 srvr_dot_c << " (xdr_String(__xdrs__, &__ProtocolName__) == FALSE) ||\n";
1861 srvr_dot_c << " (xdr_int(__xdrs__, &__val__) == FALSE))\n";
1862 srvr_dot_c << " {\n";
1863 srvr_dot_c << " err_state = igen_encode_err;\n";
1864 srvr_dot_c << " handle_error();\n";
1865 srvr_dot_c << " return(-1);\n";
1866 srvr_dot_c << " }\n";
1867 srvr_dot_c << " if (xdrrec_endofrecord(__xdrs__, TRUE) == FALSE)\n";
1868 srvr_dot_c << " {\n";
1869 srvr_dot_c << " err_state = igen_send_err;\n";
1870 srvr_dot_c << " handle_error();\n";
1871 srvr_dot_c << " return(-1);\n";
1872 srvr_dot_c << " }\n";
1873 srvr_dot_c << " __versionVerifyDone__ = TRUE;\n";
1874 srvr_dot_c << " return 0;\n";
1875 srvr_dot_c << " }\n";
1878 void interfaceSpec::genXDRLookForVerify()
1880 srvr_dot_c << " int " << name << "::look_for_verify()\n";
1881 srvr_dot_c << " {\n";
1882 srvr_dot_c << " int __status__, __tag__;\n\n";
1883 srvr_dot_c << " if (xdrrec_skiprecord(__xdrs__) == FALSE)\n";
1884 srvr_dot_c << " {\n";
1885 srvr_dot_c << " err_state = igen_read_err;\n";
1886 srvr_dot_c << " handle_error();\n";
1887 srvr_dot_c << " return (-1);\n";
1888 srvr_dot_c << " }\n\n";
1889 srvr_dot_c << " __xdrs__->x_op = XDR_DECODE;\n\n";
1891 srvr_dot_c << " __status__ = xdr_int(__xdrs__, &__tag__);\n";
1892 srvr_dot_c << " if (__status__ != TRUE)\n";
1893 srvr_dot_c << " {\n";
1894 srvr_dot_c << " err_state = igen_decode_err;\n";
1895 srvr_dot_c << " handle_error();\n";
1896 srvr_dot_c << " return (-1);\n";
1897 srvr_dot_c << " }\n";
1898 srvr_dot_c << " if (__tag__ != 0)\n";
1899 srvr_dot_c << " {\n";
1900 srvr_dot_c << " err_state = igen_request_err;\n";
1901 srvr_dot_c << " handle_error();\n";
1902 srvr_dot_c << " return (-1);\n";
1903 srvr_dot_c << " }\n";
1904 srvr_dot_c << " return 0;\n";
1905 srvr_dot_c << " }\n";