|
|
1.1 root 1: #ifndef lint
2: static char RCSid[] = "$Header: procedures.c,v 2.0 85/11/21 07:21:43 jqj Exp $";
3: #endif
4:
5: /* $Log: procedures.c,v $
6: * Revision 2.0 85/11/21 07:21:43 jqj
7: * 4.3BSD standard release
8: *
9: * Revision 1.5 85/05/06 08:13:31 jqj
10: * *** empty log message ***
11: *
12: * Revision 1.5 85/05/06 08:13:31 jqj
13: * Almost Beta-test version.
14: *
15: * Revision 1.4 85/03/26 06:10:21 jqj
16: * Revised public alpha-test version, released 26 March 1985
17: *
18: * Revision 1.3 85/03/11 16:39:55 jqj
19: * Public alpha-test version, released 11 March 1985
20: *
21: * Revision 1.2 85/02/21 11:05:39 jqj
22: * alpha test version
23: *
24: * Revision 1.1 85/02/15 13:55:36 jqj
25: * Initial revision
26: *
27: */
28:
29: #define argname(p) ((char *) car(caar(p)))
30: #define argtype(p) ((struct type *) cdar(p))
31:
32: /*
33: * routines for generating procedures and errors
34: */
35:
36: #include "compiler.h"
37:
38: /*
39: * Generate client and server functions for procedure declarations.
40: */
41: define_procedure_constant(symbol,typtr,value)
42: struct object *symbol;
43: struct type *typtr;
44: struct constant *value;
45: {
46: struct type *resulttype;
47: char *procvalue;
48: char * resultname;
49: char buf[MAXSTR];
50: list p, q;
51:
52: if (recursive_flag) /* don't bother to do anything for procs */
53: return; /* in DEPENDS UPON modules */
54: if (typtr->type_constr != C_PROCEDURE)
55: error(FATAL, "internal error (define_procedure): not a procedure");
56: if (value->cn_constr != C_NUMERIC) {
57: error(ERROR,"Values of procedure constants must be numeric");
58: procvalue = "-1";
59: }
60: else
61: procvalue = value->cn_value;
62: /*
63: * RETURNS stuff: coerce the result to be a single record
64: */
65: if (length(typtr->type_results) > 0) {
66: struct object *resultobj;
67:
68: resulttype = record_type(typtr->type_results);
69: sprintf(buf,"%sResults",name_of(symbol));
70: resultname = copy(buf);
71: resultobj = make_symbol(resultname,CurrentProgram);
72: define_type(resultobj, resulttype);
73: /* replaces define_record_type(resulttype); */
74: typtr->type_results = cons( cons( cons((list)resultname, NIL),
75: (list)resulttype),
76: NIL);
77: }
78: /*
79: * REPORTS stuff: check here to make sure the errors are all defined
80: */
81: for (p = typtr->type_errors, q = NIL; p != NIL; q = p, p = cdr(p)) {
82: struct object *sym;
83: sym = check_def((char *)car(p),CurrentProgram);
84: if (sym == (struct object *)0) {
85: error(ERROR,"Error constant %s not defined",
86: (char*)car(p));
87: if (q == NIL) typtr->type_errors = cdr(p);
88: else cdr(q) = cdr(p);
89: }
90: else if (sym->o_class != O_CONSTANT
91: || sym->o_constant->cn_constr != C_ERROR) {
92: error(ERROR,"Symbol %s is not of appropriate type",
93: name_of(sym));
94: if (q == NIL) typtr->type_errors = cdr(p);
95: else cdr(q) = cdr(p);
96: }
97: }
98: /*
99: * Argument stuff: make sure all the argument types are defined
100: */
101: for (p = typtr->type_args; p != NIL; p = cdr(p)) {
102: if (typename(argtype(p)) == NULL) {
103: struct object *name;
104: name = make_symbol(gensym("T_p"),CurrentProgram);
105: define_type(name,argtype(p));
106: }
107: }
108: /*
109: * Actually generate code for this procedure
110: */
111: proc_functions(symbol->o_constant->cn_name, typtr, procvalue);
112: /*
113: * Save this procedure on the global procs for wrapup (server
114: * dispatch code)
115: */
116: Procedures = cons(cons( (list)symbol->o_constant->cn_name,
117: (list)procvalue ),
118: Procedures);
119: }
120:
121:
122: /*
123: * Generate funcions for client and server calls to a procedure.
124: */
125: proc_functions(proc_name, type, proc_number)
126: char *proc_name;
127: struct type *type;
128: char *proc_number;
129: {
130: list p;
131: int nresults, fixed_size, variable_size;
132: struct type *t, *bt, *result_type;
133: char *result_name, *ref, *rtname;
134:
135: /*
136: * Make sure there is at most one result returned.
137: */
138: nresults = length(type->type_results);
139: if (nresults > 1) {
140: error(ERROR, "procedures that return multiple results are not supported");
141: return;
142: }
143: if (nresults) {
144: result_name = "_Results";
145: result_type = argtype(type->type_results);
146: rtname = typename(result_type);
147: } else {
148: rtname = "void";
149: }
150:
151: /*
152: * Server routine.
153: */
154:
155: fprintf(server, "\nextern %s %s();\n", rtname, proc_name);
156: fprintf(server,
157: "\nserver_%s(_buf)\n\
158: \tregister Unspecified *_buf;\n\
159: {\n\
160: \tregister Unspecified *_bp = _buf;\n\
161: \tregister LongCardinal _n;\n",
162: proc_name);
163: for (p = type->type_args; p != NIL; p = cdr(p)) {
164: t = argtype(p);
165: fprintf(server, "\t%s %s;\n", typename(t), argname(p));
166: }
167: if (nresults)
168: fprintf(server, "\t%s %s;\n", rtname, result_name);
169: fprintf(server, "\n");
170: /*
171: * Generate code to internalize the arguments.
172: */
173: for (p = type->type_args; p != NIL; p = cdr(p)) {
174: t = argtype(p);
175: ref = refstr(t);
176: fprintf(server, "\t_bp += %s(%s%s, _bp);\n",
177: xfn(INTERNALIZE, t), ref, argname(p));
178: }
179: /*
180: * Generate code to call the procedure.
181: */
182: if (nresults)
183: fprintf(server, "\t%s = %s(_serverConnection, 0",
184: result_name, proc_name);
185: else
186: fprintf(server, "\t%s(_serverConnection, 0", proc_name);
187: for (p = type->type_args; p != NIL; p = cdr(p)) {
188: fprintf(server, ", %s", argname(p));
189: }
190: fprintf(server, ");\n");
191: /*
192: * Generate code to externalize the result.
193: */
194: if (nresults) {
195: ref = refstr(result_type);
196: fprintf(server,
197: "\t_n = sizeof_%s(%s%s);\n\
198: \t_bp = Allocate(_n);\n\
199: \t%s(%s%s, _bp);\n\
200: \tSendReturnMessage(_n, _bp);\n\
201: \tDeallocate(_bp);\n\
202: }\n",
203: rtname, ref, result_name,
204: xfn(EXTERNALIZE, result_type), ref, result_name);
205: } else
206: fprintf(server,"}\n" );
207:
208: /*
209: * Stub routine for client.
210: */
211:
212: fprintf(header, "\nextern %s %s();\n",
213: rtname, proc_name);
214: fprintf(client,
215: "\n\
216: %s\n\
217: %s(_Connection, _BDTprocptr",
218: rtname, proc_name);
219: for (p = type->type_args; p != NIL; p = cdr(p))
220: fprintf(client, ", %s", argname(p));
221: fprintf(client, ")\n\
222: \tCourierConnection *_Connection;\n\
223: \tint (*_BDTprocptr)();\n\
224: "
225: );
226: for (p = type->type_args; p != NIL; p = cdr(p)) {
227: t = argtype(p);
228: fprintf(client, "\t%s %s;\n", typename(t), argname(p));
229: }
230: fprintf(client, "{\n");
231: if (nresults)
232: fprintf(client, "\t%s %s;\n", rtname, result_name);
233: fprintf(client,
234: "\tregister Unspecified *_buf, *_bp;\n\
235: \tBoolean _errorflag;\n\
236: \tCardinal _errtype;\n"
237: );
238: /*
239: * Determine the size of the arguments.
240: * This is like the code in record_type().
241: */
242: fixed_size = 0;
243: variable_size = 0;
244: for (p = type->type_args; p != NIL; p = cdr(p)) {
245: bt = argtype(p);
246: if (bt->type_xsize == -1) {
247: variable_size = 1;
248: } else {
249: fixed_size += bt->type_xsize;
250: }
251: }
252: if (!variable_size) {
253: /*
254: * The argument list is fixed-size.
255: */
256: fprintf(client,
257: "\n\
258: \t_buf = Allocate(%d);\n",
259: fixed_size);
260: } else {
261: /*
262: * There are some variable-size arguments.
263: */
264: fprintf(client,
265: "\tregister LongCardinal _n = %d;\n\
266: \n",
267: fixed_size);
268: for (p = type->type_args; p != NIL; p = cdr(p)) {
269: t = argtype(p);
270: bt = t;
271: if (bt->type_xsize != -1)
272: continue;
273: ref = refstr(bt);
274: fprintf(client,
275: "\t_n += sizeof_%s(%s%s);\n",
276: typename(t), ref, argname(p));
277: }
278: fprintf(client,
279: "\t_buf = Allocate(_n);\n"
280: );
281: }
282: fprintf(client,
283: "\t_bp = _buf;\n"
284: );
285: /*
286: * Generate code to externalize the arguments.
287: */
288: for (p = type->type_args; p != NIL; p = cdr(p)) {
289: t = argtype(p);
290: ref = refstr(t);
291: fprintf(client, "\t_bp += %s(%s%s, _bp);\n",
292: xfn(EXTERNALIZE, t), ref, argname(p));
293: }
294: if (!variable_size) {
295: fprintf(client,
296: "\tSendCallMessage(_Connection, %d, %d, %s, %d, _buf);\n",
297: CurrentNumber, CurrentVersion,
298: proc_number, fixed_size);
299: } else {
300: fprintf(client,
301: "\tSendCallMessage(_Connection, %d, %d, %s, _n, _buf);\n",
302: CurrentNumber, CurrentVersion,
303: proc_number);
304: }
305: fprintf(client,
306: "\tDeallocate(_buf);\n\
307: \tMaybeCallBDTHandler(_Connection, _BDTprocptr);\n"
308: );
309: /*
310: * Generate code to receive the results and interpret them
311: * as errors
312: */
313: fprintf(client,
314: "\t_bp = ReceiveReturnMessage(_Connection, &_errorflag);\n\
315: \t_buf = _bp;\n\
316: \tif (_errorflag) {\n\
317: \t\t_bp += %s(&_errtype, _bp);\n\
318: \t\tswitch (ERROR_OFFSET+_errtype) {\n",
319: xfn(INTERNALIZE, Cardinal_type)
320: );
321: for (p = type->type_errors; p != NIL; p = cdr(p)) {
322: struct constant *errconst;
323: struct type *errtype;
324: errconst = (check_def((char *)car(p),CurrentProgram))->o_constant;
325: errtype = (struct type *) cdr(errconst->cn_list);
326: if (errtype == TNIL)
327: fprintf(client,
328: "\t\tcase %s:\n\
329: \t\t\traise(ERROR_OFFSET+_errtype, 0);\n\
330: \t\t\t/*NOTREACHED*/\n",
331: errconst->cn_name);
332: else
333: fprintf(client,
334: "\t\tcase %s: {\n\
335: \t\t\tstatic %s _result;\n\
336: \t\t\t_bp += %s(%s_result, _bp);\n\
337: \t\t\traise(ERROR_OFFSET+_errtype, (char *) &_result);\n\
338: \t\t\t/*NOTREACHED*/\n\
339: \t\t\t}\n",
340: errconst->cn_name,
341: typename(errtype),
342: xfn(INTERNALIZE, errtype), refstr(errtype)
343: );
344: }
345: fprintf(client,
346: "\t\tdefault:\n\
347: \t\t\t/* don't know how to unpack this */\n\
348: \t\t\traise(ERROR_OFFSET+_errtype, 0);\n\
349: \t\t\t/*NOTREACHED*/\n\
350: \t\t}\n"
351: );
352: /*
353: * Code to unpack results and return
354: */
355: if (nresults)
356: fprintf(client,
357: "\t} else\n\
358: \t\t_bp += %s(%s%s, _bp);\n\
359: \tDeallocate(_buf);\n\
360: \treturn (%s);\n\
361: }\n",
362: xfn(INTERNALIZE, result_type),
363: refstr(result_type), result_name, result_name);
364: else
365: fprintf(client,
366: "\t}\n\
367: \tDeallocate(_buf);\n\
368: }\n");
369: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.