#ifndef lint static char RCSid[] = "$Header: code.c,v 2.1 86/01/21 10:04:02 jqj Exp $"; #endif /* $Log: code.c,v $ * Revision 2.1 86/01/21 10:04:02 jqj * changes from Dan Chernikoff: dereferencing null pointer in code * generation for Abort messages from servers. * * Revision 2.0 85/11/21 07:21:28 jqj * 4.3BSD standard release * * Revision 1.6 85/05/23 06:19:16 jqj * *** empty log message *** * * Revision 1.6 85/05/23 06:19:16 jqj * Public Beta-test version, released 24 May 1985 * * Revision 1.5 85/05/06 08:12:58 jqj * Almost Beta-test version. * * Revision 1.4 85/03/26 06:09:24 jqj * Revised public alpha-test version, released 26 March 1985 * * Revision 1.3 85/03/11 16:38:39 jqj * Public alpha-test version, released 11 March 1985 * * Revision 1.2 85/02/21 11:04:47 jqj * alpha test version * * Revision 1.1 85/02/15 13:55:15 jqj * Initial revision * */ #include "compiler.h" #include char *CurrentProgram = "unknown"; int CurrentNumber = 0; int CurrentVersion = 0; /* * Generate comments, #includes, and client binding. * This action is called before the module body has been reduced. * (jqj) */ program_header(symbol, number, version) char *symbol; char *number, *version; { if (check_dependency(symbol)) { char *tempsym; tempsym = gensym(symbol); error(WARNING,"Module %s already seen. Using %s.", symbol,tempsym); symbol = tempsym; } (void) make_module(symbol,number,version); CurrentProgram = symbol; CurrentVersion = stringtocard(version); CurrentNumber = stringtocard(number); /* * only do this stuff for the main Courier program -- generate * minimal code for DEPENDS UPON inclusions. */ if (recursive_flag) { fprintf(header1,"/* DEPENDS UPON %s NUMBER %d VERSION %d */\n", CurrentProgram, CurrentNumber, CurrentVersion); return; } /* * Generate initial contents of all sorts of stuff: * (1) set up gensym counter, * (2) generate beginning of header files, support file, * client file, server file */ setgensym(number,version); fprintf(header1, "/*\n\ * This header file contains inclusions for the main definitions and for\n\ * any DEPENDS UPON modules. It also contains #define commands to open\n\ * the scope of the main definitons module.\n\ *\n\ * main inclusion:\n\ */\n\ #include \"%s%d.h\"\n\n", CurrentProgram, CurrentVersion); /* * In the definitions for this module, make sure we don't * compile things twice by wrapping everything inside of a * #ifndef ... #endif (the #endif is in wrapup_program() ). */ fprintf(header, "/*\n\ * Definitions for %s VERSION %s NUMBER %s.\n\ */\n\ #ifndef __%s%d\n\ #define __%s%d\n\ #include \n\ #include \n\n", CurrentProgram, version, number, CurrentProgram, CurrentVersion, CurrentProgram, CurrentVersion); fprintf(support1, "/*\n\ * Support routines for %s.\n\ */\n\ #include \"%s%d.h\"\n", CurrentProgram, CurrentProgram, CurrentVersion); fprintf(client, "/*\n\ * Client routines for %s.\n\ */\n\ #include \"%s%d.h\"\n", CurrentProgram, CurrentProgram, CurrentVersion); fprintf(server, "/*\n\ * Server for %s.\n\ */\n\ #include \"%s%d.h\"\n\ #include \n\n\ extern CourierConnection *_serverConnection;\n", CurrentProgram, CurrentProgram, CurrentVersion); } /* * Recursively parse a program to get types and constants. * as a side effect, enters the program name into the SymbolTables * symbol table. */ ref_program(name, number, version) char *name, *number, *version; { long save_offset; char *save_input_file; char buf[MAXSTR]; int *p; int intversion; extern int *save_parser_state(); struct courierdbent *dbent; intversion = stringtocard(version); /* * in a DEPENDS UPON inclusion, generate minimal code, making * sure we don't do it twice. The included program is wrapped in * an #ifdef ... #endif */ if (!recursive_flag) { fprintf(header,"\n\ /*\n\ * Definitions from DEPENDS UPON %s inclusion\n\ * (must be linked with %s%d_support.c also)\n\ */\n\ #include \n", name, name, intversion, name, intversion); } if (check_module_def(name,number,version)) /* we've already parsed this one, so don't bother to redo */ return; save_offset = ftell(stdin); save_input_file = input_file; sprintf(buf, "%s%d.cr", name, intversion); input_file = buf; if (freopen(input_file, "r", stdin) == NULL) { dbent = getcourierservice(stringtocard(number),intversion); if (dbent == NULL || dbent->cr_description == NULL || (input_file = copy(dbent->cr_description)) == NULL || freopen(input_file, "r", stdin) == NULL) { error(ERROR, "file %s not found", input_file); input_file = save_input_file; freopen(input_file, "r", stdin); fseek(stdin, save_offset, 0); return; } } p = save_parser_state(); /* note: recursive_flag is now set */ (void) yyparse(); /* recursively parse */ restore_parser_state(p); input_file = save_input_file; freopen(input_file, "r", stdin); fseek(stdin, save_offset, 0); return; } /* * Generate any code needed after DEPENDS UPON modules have been * parsed, but before declarations. */ program_body() { if (recursive_flag) return; fprintf(header1, "/*\n\ * Widen scope to include all symbols defined in main inclusion:\n\ */\n"); } /* * Generate code relating to binding. * This action is called after the entire module has been reduced. */ wrapup_program(prog) char *prog; { if (recursive_flag) return; fprintf(header,"\n#endif __%s\n\n", CurrentProgram); if (!streq(prog,CurrentProgram)) error(FATAL,"internal error (module): conflicting module names, %s and %s", prog,CurrentProgram); generate_server_binding(); generate_client_binding(); } /* * Generate export function for server. */ generate_server_binding() { list p; fprintf(server, "\nServer(skipcount,skippedwords)\n\ \tint skipcount;\n\ \tUnspecified skippedwords[];\n\ {\n\ \tCardinal _procedure;\n\ \tregister Unspecified *_buf;\n\ \tLongCardinal programnum;\n\ \tCardinal versionnum;\n\ \tCardinal _n;\n\ \n\ \tfor (;;) {\n\ \t\t_buf = ReceiveCallMessage(&_procedure, skipcount, skippedwords);\n\ \t\tDURING switch (_procedure) {\n"); /* * Find all the procedures declared in the program. */ for (p = Procedures; p != NIL; p = cdr(p)) { fprintf(server, "\t\tcase %s:\n\ \t\t\tserver_%s(_buf);\n\ \t\t\tbreak;\n", (char *)cdar(p), (char *)caar(p)); } fprintf(server, "\t\tdefault:\n\ \t\t\tNoSuchProcedureValue(\"%s\", _procedure);\n\ \t\t\tbreak;\n\ \t\t} HANDLER {\n\ \t\t Deallocate(_buf);\n\ \t\t switch (Exception.Code) {\n", CurrentProgram); for (p = Errors; p != NIL; p = cdr(p)) { struct constant *errconst; struct type *errtype; errconst = (struct constant *) caar(p); errtype = (struct type *) cdar(p); if (errtype == TNIL) fprintf(server, "\t\t case %s:\n\ \t\t\t_buf = Allocate(0);\n\ \t\t\tSendAbortMessage(Exception.Code-ERROR_OFFSET, 0, _buf);\n\ \t\t\tbreak;\n", errconst->cn_name); /* errtype != TNIL */ else if (typename(errtype) == NULL) { error(ERROR,"Internal error (server): unexpanded type for %s", errconst->cn_name); break; } /* errtype != TNIL && typename(errtype) != NULL */ else fprintf(server, "\t\t case %s:\n\ \t\t\t_n = sizeof_%s((%s *)Exception.Message);\n\ \t\t\t_buf = Allocate(_n);\n\ \t\t\t(void) %s((%s*)Exception.Message, _buf);\n\ \t\t\tSendAbortMessage(Exception.Code-ERROR_OFFSET, _n, _buf);\n\ \t\t\tbreak;\n", errconst->cn_name, typename(errtype), typename(errtype), xfn(EXTERNALIZE,errtype), typename(errtype)); } fprintf(server, "\t\t default:\n\ \t\t\t_buf = Allocate(0);\n\ \t\t\tSendRejectMessage(unspecifiedError, 0, _buf);\n\ \t\t\tbreak;\n\ \t\t }\n\ \t\t} END_HANDLER;\n\ \t\tDeallocate(_buf);\n\ \t\tfor (;;) {\n\ \t\t\tskipcount = LookAheadCallMsg(&programnum, &versionnum,\n\ \t\t\t\t\tskippedwords);\n\ \t\t\tif (skipcount < 0) return(0);\t/* timed out */\n\ \t\t\tif (programnum != %d || versionnum != %d)\n\ \t\t\t\tExecCourierProgram(programnum, versionnum,\n\ \t\t\t\t\t\tskipcount, skippedwords);\n\ \t\t\} /* loop if can't exec that program */\n\ \t}\n\ }\n", CurrentNumber, CurrentVersion ); } /* * Generate function for importing server module. */ generate_client_binding() { }