Commit | Line | Data |
---|---|---|
0f4556f1 C |
1 | #ifndef lint |
2 | static char sccsid[] = "@(#)code2.c 4.1 (Berkeley) 7/3/83"; | |
3 | #endif | |
4 | ||
59cc90dc C |
5 | #include "Courier.h" |
6 | ||
7 | /* | |
8 | * Generate functions for user and server calls to a procedure. | |
9 | */ | |
10 | proc_functions(proc_name, type, value) | |
11 | char *proc_name; | |
12 | struct object *type, *value; | |
13 | { | |
14 | list p, q; | |
15 | int nresults; | |
16 | struct object *t, *result_type; | |
17 | char *result_name, *func, *ref; | |
18 | ||
19 | /* | |
20 | * Make sure there is at most one result returned. | |
21 | */ | |
22 | nresults = length(type->t_results); | |
23 | if (nresults == 1) | |
24 | /* could be multiple names with one type */ | |
25 | nresults = length(car(car(type->t_results))); | |
26 | if (nresults > 1) { | |
27 | yyerror("Procedures that return multiple results are not supported"); | |
28 | return; | |
29 | } | |
30 | if (nresults) { | |
31 | result_name = name_of(car(car(car(type->t_results)))); | |
32 | result_type = (struct object *) cdr(car(type->t_results)); | |
33 | } | |
34 | ||
35 | /* | |
36 | * Server routine. | |
37 | */ | |
38 | if (nresults) { | |
39 | fprintf(sf, "\nextern "); | |
40 | print_decl(sf, proc_name, result_type, 1); | |
41 | fprintf(sf, "();\n"); | |
42 | } else | |
43 | fprintf(sf, "\nextern void %s();\n", proc_name); | |
44 | fprintf(sf, | |
45 | "\nServer_%s(_buf)\n\ | |
46 | \tregister Unspecified *_buf;\n\ | |
47 | {\n\ | |
48 | \tregister Unspecified *_bp;\n\ | |
49 | \tregister LongCardinal _n;\n", | |
50 | proc_name); | |
51 | print_level++; | |
52 | for (p = type->t_args; p != NIL; p = cdr(p)) { | |
53 | t = (struct object *) cdr(car(p)); | |
54 | for (q = car(car(p)); q != NIL; q = cdr(q)) | |
55 | print_decl(sf, name_of(car(q)), t, 0); | |
56 | } | |
57 | if (nresults) | |
58 | print_decl(sf, result_name, result_type, 0); | |
59 | print_level--; | |
60 | fprintf(sf, "\n\t_bp = _buf;\n"); | |
61 | for (p = type->t_args; p != NIL; p = cdr(p)) { | |
62 | t = (struct object *) cdr(car(p)); | |
63 | ref = refstr(t); | |
64 | for (q = car(car(p)); q != NIL; q = cdr(q)) | |
65 | fprintf(sf, "\t_bp += %s(%s%s, _bp);\n", | |
66 | unpack_function(t), ref, name_of(car(q))); | |
67 | } | |
68 | if (nresults) | |
69 | fprintf(sf, "\t%s = %s(", result_name, proc_name); | |
70 | else | |
71 | fprintf(sf, "\t%s(", proc_name); | |
72 | for (p = type->t_args; p != NIL; p = cdr(p)) { | |
73 | for (q = car(car(p)); q != NIL; q = cdr(q)) { | |
74 | fprintf(sf, "%s", name_of(car(q))); | |
75 | if (cdr(q) != NIL) | |
76 | fprintf(sf, ", "); | |
77 | } | |
78 | if (cdr(p) != NIL) | |
79 | fprintf(sf, ", "); | |
80 | } | |
81 | fprintf(sf, ");\n"); | |
82 | if (nresults) { | |
83 | func = pack_function(result_type); | |
84 | ref = refstr(result_type); | |
85 | fprintf(sf, | |
86 | "\t_n = %s(%s%s, 0, 0);\n\ | |
87 | \t_bp = Allocate(_n);\n\ | |
88 | \t%s(%s%s, _bp, 1);\n\ | |
89 | \tSendReturnMessage(_n, _bp);\n\ | |
90 | \tDeallocate(_bp);\n", | |
91 | func, ref, result_name, func, ref, result_name); | |
92 | } | |
93 | fprintf(sf, "}\n"); | |
94 | ||
95 | /* | |
96 | * Remote access routine. | |
97 | */ | |
98 | if (nresults) { | |
99 | fprintf(hf, "\nextern "); | |
100 | print_decl(hf, proc_name, result_type, 1); | |
101 | fprintf(hf, "();\n"); | |
102 | ||
103 | fprintf(uf, "\n"); | |
104 | print_decl(uf, proc_name, result_type, 1); | |
105 | fprintf(uf, "("); | |
106 | } else { | |
107 | fprintf(hf, "\nextern void %s();\n", proc_name); | |
108 | fprintf(uf, "\nvoid %s(", proc_name); | |
109 | } | |
110 | if (explicit) { | |
111 | fprintf(uf, "_machine"); | |
112 | if (type->t_args != NIL) | |
113 | fprintf(uf, ", "); | |
114 | } | |
115 | for (p = type->t_args; p != NIL; p = cdr(p)) { | |
116 | for (q = car(car(p)); q != NIL; q = cdr(q)) { | |
117 | fprintf(uf, "%s", name_of(car(q))); | |
118 | if (cdr(q) != NIL) | |
119 | fprintf(uf, ", "); | |
120 | } | |
121 | if (cdr(p) != NIL) | |
122 | fprintf(uf, ", "); | |
123 | } | |
124 | fprintf(uf, ")\n"); | |
125 | if (explicit) | |
126 | fprintf(uf, "\tString _machine;\n"); | |
127 | print_level++; | |
128 | for (p = type->t_args; p != NIL; p = cdr(p)) { | |
129 | t = (struct object *) cdr(car(p)); | |
130 | for (q = car(car(p)); q != NIL; q = cdr(q)) | |
131 | print_decl(uf, name_of(car(q)), t, 0); | |
132 | } | |
133 | fprintf(uf, "{\n"); | |
134 | if (nresults) | |
135 | print_decl(uf, result_name, result_type, 0); | |
136 | fprintf(uf, | |
137 | "\tregister Unspecified *_buf, *_bp;\n\ | |
138 | \tregister LongCardinal _n;\n\ | |
139 | \n\ | |
140 | \t_n = 0;\n"); | |
141 | print_level--; | |
142 | for (p = type->t_args; p != NIL; p = cdr(p)) { | |
143 | t = (struct object *) cdr(car(p)); | |
144 | ref = refstr(t); | |
145 | for (q = car(car(p)); q != NIL; q = cdr(q)) | |
146 | fprintf(uf, "\t_n += %s(%s%s, 0, 0);\n", | |
147 | pack_function(t), ref, name_of(car(q))); | |
148 | } | |
149 | fprintf(uf, | |
150 | "\t_buf = Allocate(_n);\n\ | |
151 | \t_bp = _buf;\n"); | |
152 | for (p = type->t_args; p != NIL; p = cdr(p)) { | |
153 | t = (struct object *) cdr(car(p)); | |
154 | ref = refstr(t); | |
155 | for (q = car(car(p)); q != NIL; q = cdr(q)) | |
156 | fprintf(uf, "\t_bp += %s(%s%s, _bp, 1);\n", | |
157 | pack_function(t), ref, name_of(car(q))); | |
158 | } | |
159 | if (explicit) | |
160 | fprintf(uf, | |
161 | "\tSendCallMessage(CourierProgram(\"%s\", _machine), %s, _n, _buf);\n", | |
162 | program_name, obj_rep(value)); | |
163 | else | |
164 | fprintf(uf, | |
165 | "\tSendCallMessage(_%sConnection, %s, _n, _buf);\n", | |
166 | program_name, obj_rep(value)); | |
167 | fprintf(uf, "\tDeallocate(_buf);\n"); | |
168 | if (nresults) { | |
169 | if (explicit) | |
170 | fprintf(uf, | |
171 | "\t_bp = ReceiveReturnMessage(CourierProgram(\"%s\", _machine));\n", | |
172 | program_name); | |
173 | else | |
174 | fprintf(uf, | |
175 | "\t_bp = ReceiveReturnMessage(_%sConnection);\n", | |
176 | program_name); | |
177 | fprintf(uf, | |
178 | "\t%s(%s%s, _bp);\n\ | |
179 | \tDeallocate(_bp);\n\ | |
180 | \treturn (%s);\n", | |
181 | unpack_function(result_type), refstr(result_type), | |
182 | result_name, result_name); | |
183 | } | |
184 | fprintf(uf, "}\n"); | |
185 | } | |
186 | ||
187 | program(prog) | |
188 | struct object *prog; | |
189 | { | |
190 | /* | |
191 | * Program_name should have been set by now, | |
192 | * but a little paranoia never hurt anyone. | |
193 | */ | |
194 | if (! streq(name_of(prog), program_name)) { | |
195 | yyerror("Internal error: conflicting program names %s and %s\n", | |
196 | name_of(prog), program_name); | |
197 | exit(1); | |
198 | } | |
199 | generate_server(); | |
200 | } | |
201 | ||
202 | /* | |
203 | * Generate main loop for server program. | |
204 | */ | |
205 | generate_server() | |
206 | { | |
207 | list p; | |
208 | struct object *t, *proc, *v; | |
209 | ||
210 | fprintf(sf, | |
211 | "\nServer()\n\ | |
212 | {\n\ | |
213 | \tCardinal procedure;\n\ | |
214 | \tregister Unspecified *buf;\n\ | |
215 | \n\ | |
216 | \tServerInit();\n\ | |
217 | \tfor (;;) {\n\ | |
218 | \t\tbuf = ReceiveCallMessage(&procedure);\n\ | |
219 | \t\tswitch (procedure) {\n" | |
220 | ); | |
221 | /* | |
222 | * Find all the procedures declared in the program. | |
223 | */ | |
224 | for (p = Types; p != NIL; p = cdr(p)) { | |
225 | t = (struct object *) cdr(car(p)); | |
226 | if (t->t_constr == C_PROCEDURE) { | |
227 | proc = (struct object *) car(car(p)); | |
228 | v = lookup(Values, proc); | |
229 | fprintf(sf, | |
230 | "\t\tcase %s:\n\ | |
231 | \t\t\tServer_%s(buf);\n\ | |
232 | \t\t\tbreak;\n", | |
233 | obj_rep(v), name_of(proc)); | |
234 | } | |
235 | } | |
236 | fprintf(sf, | |
237 | "\t\tdefault:\n\ | |
238 | \t\t\tNoSuchProcedureValue(\"%s\", procedure);\n\ | |
239 | \t\t\tbreak;\n\ | |
240 | \t\t}\n\ | |
241 | \t\tDeallocate(buf);\n\ | |
242 | \t}\n\ | |
243 | }\n", | |
244 | program_name); | |
245 | } | |
246 | ||
247 | /* | |
248 | * When implicit binding is used, this routine generates functions to | |
249 | * bind the remote Courier program to a machine by setting the global | |
250 | * connection variable for the program, and to remove the binding by | |
251 | * closing the connection. | |
252 | */ | |
253 | generate_binding_functions() | |
254 | { | |
255 | fprintf(uf, | |
256 | "\nint _%sConnection = -1;\n\ | |
257 | \n\ | |
258 | Bind%sToMachine(machine)\n\ | |
259 | \tString machine;\n\ | |
260 | {\n\ | |
261 | \tclose(_%sConnection);\n\ | |
262 | \t_%sConnection = CourierActivate(\"%s\", machine);\n\ | |
263 | }\n\ | |
264 | \n\ | |
265 | Unbind%s()\n\ | |
266 | {\n\ | |
267 | \tclose(_%sConnection);\n\ | |
268 | \t_%sConnection = -1;\n\ | |
269 | }\n", | |
270 | program_name, program_name, program_name, program_name, | |
271 | program_name, program_name, program_name, program_name); | |
272 | } |