📄 procedures.c
字号:
#ifndef lintstatic char RCSid[] = "$Header: procedures.c,v 2.2 86/11/11 09:49:06 jqj Exp $";#endif/* $Log: procedures.c,v $ * Revision 2.2 86/11/11 09:49:06 jqj * Per Ed Flint, if a Courier procedure returns void, the server should still * do a SendReturnMessage(0,0), so generate the proper code for this case. * Note that this eventually implies (in xnslib/readwrite.c) that a writev() * has an iovec with 0 length, which might tickle a kernel bug in some * implementations. * * Revision 2.1 86/06/06 07:28:49 jqj * many mods for better symbol table management: added CurrentModule, * made check_dependency, make_symbol, check_def set/use/use a symbol * table instead of a module name string, etc. Result is that we can * now handle DEPENDS UPON 2 versions of same program. * * Revision 2.0 85/11/21 07:21:43 jqj * 4.3BSD standard release * * Revision 1.5 85/05/06 08:13:31 jqj * *** empty log message *** * * Revision 1.5 85/05/06 08:13:31 jqj * Almost Beta-test version. * * Revision 1.4 85/03/26 06:10:21 jqj * Revised public alpha-test version, released 26 March 1985 * * Revision 1.3 85/03/11 16:39:55 jqj * Public alpha-test version, released 11 March 1985 * * Revision 1.2 85/02/21 11:05:39 jqj * alpha test version * * Revision 1.1 85/02/15 13:55:36 jqj * Initial revision * */#define argname(p) ((char *) car(caar(p)))#define argtype(p) ((struct type *) cdar(p))/* * routines for generating procedures and errors */#include "compiler.h"/* * Generate client and server functions for procedure declarations. */define_procedure_constant(symbol,typtr,value) struct object *symbol; struct type *typtr; struct constant *value;{ struct type *resulttype; char *procvalue; char * resultname; char buf[MAXSTR]; list p, q; if (recursive_flag) /* don't bother to do anything for procs */ return; /* in DEPENDS UPON modules */ if (typtr->type_constr != C_PROCEDURE) error(FATAL, "internal error (define_procedure): not a procedure"); if (value->cn_constr != C_NUMERIC) { error(ERROR,"Values of procedure constants must be numeric"); procvalue = "-1"; } else procvalue = value->cn_value; /* * RETURNS stuff: coerce the result to be a single record */ if (length(typtr->type_results) > 0) { struct object *resultobj; resulttype = record_type(typtr->type_results); sprintf(buf,"%sResults",name_of(symbol)); resultname = copy(buf); resultobj = make_symbol(resultname,CurrentModule); define_type(resultobj, resulttype); /* replaces define_record_type(resulttype); */ typtr->type_results = cons( cons( cons((list)resultname, NIL), (list)resulttype), NIL); } /* * REPORTS stuff: check here to make sure the errors are all defined */ for (p = typtr->type_errors, q = NIL; p != NIL; q = p, p = cdr(p)) { struct object *sym; sym = check_def((char *)car(p),CurrentModule); if (sym == (struct object *)0) { error(ERROR,"Error constant %s not defined", (char*)car(p)); if (q == NIL) typtr->type_errors = cdr(p); else cdr(q) = cdr(p); } else if (sym->o_class != O_CONSTANT || sym->o_constant->cn_constr != C_ERROR) { error(ERROR,"Symbol %s is not of appropriate type", name_of(sym)); if (q == NIL) typtr->type_errors = cdr(p); else cdr(q) = cdr(p); } } /* * Argument stuff: make sure all the argument types are defined */ for (p = typtr->type_args; p != NIL; p = cdr(p)) { if (typename(argtype(p)) == NULL) { struct object *name; name = make_symbol(gensym("T_p"),CurrentModule); define_type(name,argtype(p)); } } /* * Actually generate code for this procedure */ proc_functions(symbol->o_constant->cn_name, typtr, procvalue); /* * Save this procedure on the global procs for wrapup (server * dispatch code) */ Procedures = cons(cons( (list)symbol->o_constant->cn_name, (list)procvalue ), Procedures);}/* * Generate funcions for client and server calls to a procedure. */proc_functions(proc_name, type, proc_number) char *proc_name; struct type *type; char *proc_number;{ list p; int nresults, fixed_size, variable_size; struct type *t, *bt, *result_type; char *result_name, *ref, *rtname; /* * Make sure there is at most one result returned. */ nresults = length(type->type_results); if (nresults > 1) { error(ERROR, "procedures that return multiple results are not supported"); return; } if (nresults) { result_name = "_Results"; result_type = argtype(type->type_results); rtname = typename(result_type); } else { rtname = "void"; } /* * Server routine. */ fprintf(server, "\nextern %s %s();\n", rtname, proc_name); fprintf(server,"\nserver_%s(_buf)\n\\tregister Unspecified *_buf;\n\{\n\\tregister Unspecified *_bp = _buf;\n\\tregister LongCardinal _n;\n", proc_name); for (p = type->type_args; p != NIL; p = cdr(p)) { t = argtype(p); fprintf(server, "\t%s %s;\n", typename(t), argname(p)); } if (nresults) fprintf(server, "\t%s %s;\n", rtname, result_name); fprintf(server, "\n"); /* * Generate code to internalize the arguments. */ for (p = type->type_args; p != NIL; p = cdr(p)) { t = argtype(p); ref = refstr(t); fprintf(server, "\t_bp += %s(%s%s, _bp);\n", xfn(INTERNALIZE, t), ref, argname(p)); } /* * Generate code to call the procedure. */ if (nresults) fprintf(server, "\t%s = %s(_serverConnection, 0", result_name, proc_name); else fprintf(server, "\t%s(_serverConnection, 0", proc_name); for (p = type->type_args; p != NIL; p = cdr(p)) { fprintf(server, ", %s", argname(p)); } fprintf(server, ");\n"); /* * Generate code to externalize the result. */ if (nresults) { ref = refstr(result_type); fprintf(server,"\t_n = sizeof_%s(%s%s);\n\\t_bp = Allocate(_n);\n\\t%s(%s%s, _bp);\n\\tSendReturnMessage(_n, _bp);\n\\tDeallocate(_bp);\n\}\n", rtname, ref, result_name, xfn(EXTERNALIZE, result_type), ref, result_name); } else fprintf(server,"\tSendReturnMessage( 0, _bp);\n\}\n" ); /* * Stub routine for client. */ fprintf(header, "\nextern %s %s();\n", rtname, proc_name); fprintf(client,"\n\%s\n\%s(_Connection, _BDTprocptr", rtname, proc_name); for (p = type->type_args; p != NIL; p = cdr(p)) fprintf(client, ", %s", argname(p)); fprintf(client, ")\n\\tCourierConnection *_Connection;\n\\tint (*_BDTprocptr)();\n\" ); for (p = type->type_args; p != NIL; p = cdr(p)) { t = argtype(p); fprintf(client, "\t%s %s;\n", typename(t), argname(p)); } fprintf(client, "{\n"); if (nresults) fprintf(client, "\t%s %s;\n", rtname, result_name); fprintf(client,"\tregister Unspecified *_buf, *_bp;\n\\tBoolean _errorflag;\n\\tCardinal _errtype;\n" ); /* * Determine the size of the arguments. * This is like the code in record_type(). */ fixed_size = 0; variable_size = 0; for (p = type->type_args; p != NIL; p = cdr(p)) { bt = argtype(p); if (bt->type_xsize == -1) { variable_size = 1; } else { fixed_size += bt->type_xsize; } } if (!variable_size) { /* * The argument list is fixed-size. */ fprintf(client,"\n\\t_buf = Allocate(%d);\n", fixed_size); } else { /* * There are some variable-size arguments. */ fprintf(client,"\tregister LongCardinal _n = %d;\n\\n", fixed_size); for (p = type->type_args; p != NIL; p = cdr(p)) { t = argtype(p); bt = t; if (bt->type_xsize != -1) continue; ref = refstr(bt); fprintf(client,"\t_n += sizeof_%s(%s%s);\n", typename(t), ref, argname(p)); } fprintf(client,"\t_buf = Allocate(_n);\n" ); } fprintf(client,"\t_bp = _buf;\n" ); /* * Generate code to externalize the arguments. */ for (p = type->type_args; p != NIL; p = cdr(p)) { t = argtype(p); ref = refstr(t); fprintf(client, "\t_bp += %s(%s%s, _bp);\n", xfn(EXTERNALIZE, t), ref, argname(p)); } if (!variable_size) { fprintf(client,"\tSendCallMessage(_Connection, %d, %d, %s, %d, _buf);\n", CurrentNumber, CurrentVersion, proc_number, fixed_size); } else { fprintf(client,"\tSendCallMessage(_Connection, %d, %d, %s, _n, _buf);\n", CurrentNumber, CurrentVersion, proc_number); } fprintf(client,"\tDeallocate(_buf);\n\\tMaybeCallBDTHandler(_Connection, _BDTprocptr);\n" ); /* * Generate code to receive the results and interpret them * as errors */ fprintf(client,"\t_bp = ReceiveReturnMessage(_Connection, &_errorflag);\n\\t_buf = _bp;\n\\tif (_errorflag) {\n\\t\t_bp += %s(&_errtype, _bp);\n\\t\tswitch (ERROR_OFFSET+_errtype) {\n", xfn(INTERNALIZE, Cardinal_type) ); for (p = type->type_errors; p != NIL; p = cdr(p)) { struct constant *errconst; struct type *errtype; errconst = (check_def((char *)car(p),CurrentModule))->o_constant; errtype = (struct type *) cdr(errconst->cn_list); if (errtype == TNIL) fprintf(client,"\t\tcase %s:\n\\t\t\traise(ERROR_OFFSET+_errtype, 0);\n\\t\t\t/*NOTREACHED*/\n", errconst->cn_name); else fprintf(client,"\t\tcase %s: {\n\\t\t\tstatic %s _result;\n\\t\t\t_bp += %s(%s_result, _bp);\n\\t\t\traise(ERROR_OFFSET+_errtype, (char *) &_result);\n\\t\t\t/*NOTREACHED*/\n\\t\t\t}\n", errconst->cn_name, typename(errtype), xfn(INTERNALIZE, errtype), refstr(errtype) ); } fprintf(client,"\t\tdefault:\n\\t\t\t/* don't know how to unpack this */\n\\t\t\traise(ERROR_OFFSET+_errtype, 0);\n\\t\t\t/*NOTREACHED*/\n\\t\t}\n" ); /* * Code to unpack results and return */ if (nresults) fprintf(client,"\t} else\n\\t\t_bp += %s(%s%s, _bp);\n\\tDeallocate(_buf);\n\\treturn (%s);\n\}\n", xfn(INTERNALIZE, result_type), refstr(result_type), result_name, result_name); else fprintf(client,"\t}\n\\tDeallocate(_buf);\n\}\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -