]> git.cameronkatri.com Git - apple_cmds.git/blob - bootstrap_cmds/migcom.tproj/server.c
Merge branch 'apple'
[apple_cmds.git] / bootstrap_cmds / migcom.tproj / server.c
1 /*
2 * Copyright (c) 1999-2018 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*
24 * @OSF_COPYRIGHT@
25 */
26 /*
27 * Mach Operating System
28 * Copyright (c) 1991,1990 Carnegie Mellon University
29 * All Rights Reserved.
30 *
31 * Permission to use, copy, modify and distribute this software and its
32 * documentation is hereby granted, provided that both the copyright
33 * notice and this permission notice appear in all copies of the
34 * software, derivative works or modified versions, and any portions
35 * thereof, and that both notices appear in supporting documentation.
36 *
37 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
38 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
39 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40 *
41 * Carnegie Mellon requests users of this software to return to
42 *
43 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
44 * School of Computer Science
45 * Carnegie Mellon University
46 * Pittsburgh PA 15213-3890
47 *
48 * any improvements or extensions that they make and grant Carnegie Mellon
49 * the rights to redistribute these changes.
50 */
51
52 #include <assert.h>
53 #include <stdlib.h>
54
55 #include <mach/message.h>
56 #include "write.h"
57 #include "utils.h"
58 #include "global.h"
59 #include "error.h"
60
61 #ifndef max
62 #define max(a,b) (((a) > (b)) ? (a) : (b))
63 #endif /* max */
64
65 void WriteLogDefines(FILE *file, string_t who);
66 void WriteIdentificationString(FILE *file);
67 static void WriteFieldDecl(FILE *file, argument_t *arg);
68
69 static void
70 WriteKPD_Iterator(FILE *file, boolean_t in, boolean_t varying, argument_t *arg, boolean_t bracket)
71 {
72 ipc_type_t *it = arg->argType;
73 char string[MAX_STR_LEN];
74
75 fprintf(file, "\t{\n");
76 fprintf(file, "\t %s\t*ptr;\n", it->itKPDType);
77 fprintf(file, "\t int\ti");
78 if (varying && !in)
79 fprintf(file, ", j");
80 fprintf(file, ";\n\n");
81
82 if (in)
83 sprintf(string, "In%dP", arg->argRequestPos);
84 else
85 sprintf(string, "OutP");
86
87 fprintf(file, "\t ptr = &%s->%s[0];\n", string, arg->argMsgField);
88
89 if (varying) {
90 argument_t *count = arg->argCount;
91
92 if (in)
93 fprintf(file, "\t for (i = 0; i < In%dP->%s; ptr++, i++) %s\n", count->argRequestPos, count->argMsgField, (bracket) ? "{" : "");
94 else {
95 fprintf(file, "\t j = min(%d, ", it->itKPD_Number);
96 if (akCheck(count->argKind, akbVarNeeded))
97 fprintf(file, "%s);\n", count->argName);
98 else
99 fprintf(file, "%s->%s);\n", string, count->argMsgField);
100 fprintf(file, "\t for (i = 0; i < j; ptr++, i++) %s\n", (bracket) ? "{" : "");
101 }
102 }
103 else
104 fprintf(file, "\t for (i = 0; i < %d; ptr++, i++) %s\n", it->itKPD_Number, (bracket) ? "{" : "");
105 }
106
107 static void
108 WriteMyIncludes(FILE *file, statement_t *stats)
109 {
110 if (ServerHeaderFileName == strNULL || UseSplitHeaders)
111 WriteIncludes(file, FALSE, FALSE);
112 if (ServerHeaderFileName != strNULL)
113 {
114 char *cp;
115
116 /* Strip any leading path from ServerHeaderFileName. */
117 cp = strrchr(ServerHeaderFileName, '/');
118 if (cp == 0)
119 cp = ServerHeaderFileName;
120 else
121 cp++; /* skip '/' */
122 fprintf(file, "#include \"%s\"\n", cp);
123 }
124 if (ServerHeaderFileName == strNULL || UseSplitHeaders)
125 WriteImplImports(file, stats, FALSE);
126 if (UseEventLogger) {
127 if (IsKernelServer) {
128 fprintf(file, "#if\t__MigKernelSpecificCode\n");
129 fprintf(file, "#include <mig_debug.h>\n");
130 fprintf(file, "#endif\t/* __MigKernelSpecificCode */\n");
131 }
132 fprintf(file, "#if MIG_DEBUG\n");
133 fprintf(file, "#include <mach/mig_log.h>\n");
134 fprintf(file, "#endif /* MIG_DEBUG */\n");
135 }
136
137 fprintf(file, "\n");
138 }
139
140 static void
141 WriteGlobalDecls(FILE *file)
142 {
143 if (BeAnsiC) {
144 fprintf(file, "#define novalue void\n");
145 }
146 else {
147 fprintf(file, "#if\t%s\n", NewCDecl);
148 fprintf(file, "#define novalue void\n");
149 fprintf(file, "#else\n");
150 fprintf(file, "#define novalue int\n");
151 fprintf(file, "#endif\t/* %s */\n", NewCDecl);
152 }
153 fprintf(file, "\n");
154
155 if (RCSId != strNULL)
156 WriteRCSDecl(file, strconcat(SubsystemName, "_server"), RCSId);
157
158 /* Used for locations in the request message, *not* reply message.
159 Reply message locations aren't dependent on IsKernelServer. */
160
161 if (IsKernelServer) {
162 fprintf(file, "#if\t__MigKernelSpecificCode\n");
163 fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n");
164 fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)");
165 fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n");
166 fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n");
167 fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)");
168 fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n");
169 fprintf(file, "#else\n");
170 }
171 fprintf(file, "#define msgh_request_port\tmsgh_local_port\n");
172 fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)");
173 fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n");
174 fprintf(file, "#define msgh_reply_port\t\tmsgh_remote_port\n");
175 fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)");
176 fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n");
177 if (IsKernelServer) {
178 fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
179 }
180 fprintf(file, "\n");
181 if (UseEventLogger)
182 WriteLogDefines(file, "MACH_MSG_LOG_SERVER");
183 fprintf(file, "#define MIG_RETURN_ERROR(X, code)\t{\\\n");
184 fprintf(file, "\t\t\t\t((mig_reply_error_t *)X)->RetCode = code;\\\n");
185 fprintf(file, "\t\t\t\t((mig_reply_error_t *)X)->NDR = NDR_record;\\\n");
186 fprintf(file, "\t\t\t\treturn;\\\n");
187 fprintf(file, "\t\t\t\t}\n");
188 fprintf(file, "\n");
189 }
190
191
192 static void
193 WriteForwardDeclarations(FILE *file, statement_t *stats)
194 {
195 statement_t *stat;
196
197 fprintf(file, "/* Forward Declarations */\n\n");
198 for (stat = stats; stat != stNULL; stat = stat->stNext)
199 if (stat->stKind == skRoutine) {
200 fprintf(file, "\nmig_internal novalue _X%s\n", stat->stRoutine->rtName);
201 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);\n");
202 }
203 fprintf(file, "\n");
204 }
205
206 static void
207 WriteMIGCheckDefines(FILE *file)
208 {
209 fprintf(file, "#define\t__MIG_check__Request__%s_subsystem__ 1\n", SubsystemName);
210 fprintf(file, "\n");
211 }
212
213 static void
214 WriteNDRDefines(FILE *file)
215 {
216 fprintf(file, "#define\t__NDR_convert__Request__%s_subsystem__ 1\n", SubsystemName);
217 fprintf(file, "\n");
218 }
219
220 static void
221 WriteProlog(FILE *file, statement_t *stats)
222 {
223 WriteIdentificationString(file);
224 fprintf(file, "\n");
225 fprintf(file, "/* Module %s */\n", SubsystemName);
226 fprintf(file, "\n");
227 WriteMIGCheckDefines(file);
228 if (CheckNDR)
229 WriteNDRDefines(file);
230 WriteMyIncludes(file, stats);
231 WriteBogusDefines(file);
232 WriteApplDefaults(file, "Rcv");
233 WriteGlobalDecls(file);
234 if (ServerHeaderFileName == strNULL) {
235 WriteRequestTypes(file, stats);
236 WriteReplyTypes(file, stats);
237 WriteServerReplyUnion(file, stats);
238 }
239 }
240
241 static void
242 WriteSymTabEntries(FILE *file, statement_t *stats)
243 {
244 statement_t *stat;
245 u_int current = 0;
246
247 for (stat = stats; stat != stNULL; stat = stat->stNext)
248 if (stat->stKind == skRoutine) {
249 int num = stat->stRoutine->rtNumber;
250 char *name = stat->stRoutine->rtName;
251 while (++current <= num)
252 fprintf(file,"\t\t\t{ \"\", 0, 0 },\n");
253 fprintf(file, "\t{ \"%s\", %d, _X%s },\n", name, SubsystemBase + current - 1, name);
254 }
255 while (++current <= rtNumber)
256 fprintf(file,"\t{ \"\", 0, 0 },\n");
257 }
258
259 static void
260 WriteRoutineEntries(FILE *file, statement_t *stats)
261 {
262 u_int current = 0;
263 statement_t *stat;
264 char *sig_array, *rt_name;
265 int arg_count, descr_count;
266 int offset = 0;
267 size_t serverSubsysNameLen = strlen(ServerSubsys);
268
269 fprintf(file, "\t{\n");
270 for (stat = stats; stat != stNULL; stat = stat->stNext)
271 if (stat->stKind == skRoutine) {
272 routine_t *rt = stat->stRoutine;
273 size_t rtNameLen = strlen(rt->rtName);
274
275 // Include length of rt->rtName in calculation of necessary buffer size, since that string
276 // is actually written into the buffer along with the Server Subsystem name.
277 sig_array = (char *) malloc(serverSubsysNameLen + rtNameLen + 80);
278 rt_name = (char *) malloc(rtNameLen + 5);
279 while (current++ < rt->rtNumber)
280 fprintf(file, "\t\t{0, 0, 0, 0, 0, 0},\n");
281 // NOTE: if either of the two string constants in the sprintf() function calls below get
282 // much longer, be sure to increase the constant '80' (in the first malloc() call) to ensure
283 // that the allocated buffer is large enough. (Currently, I count 66 characters in the first
284 // string constant, 65 in the second. 80 ought to be enough for now...)
285 if (UseRPCTrap) {
286 sprintf(sig_array, "&%s.arg_descriptor[%d], (mach_msg_size_t)sizeof(__Reply__%s_t)", ServerSubsys, offset, rt->rtName);
287 }
288 else {
289 sprintf(sig_array, "(routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__%s_t)", rt->rtName);
290 }
291 sprintf(rt_name, "_X%s", rt->rtName);
292 descr_count = rtCountArgDescriptors(rt->rtArgs, &arg_count);
293 offset += descr_count;
294 WriteRPCRoutineDescriptor(file, rt, arg_count, (UseRPCTrap) ? descr_count : 0, rt_name, sig_array);
295 fprintf(file, ",\n");
296 free(sig_array);
297 free(rt_name);
298 }
299 while (current++ < rtNumber)
300 fprintf(file, "\t\t{0, 0, 0, 0, 0, 0},\n");
301
302 fprintf(file, "\t}");
303 }
304
305 static void
306 WriteArgDescriptorEntries(FILE *file, statement_t *stats)
307 {
308 statement_t *stat;
309
310 fprintf(file, ",\n\n\t{\n");
311 for (stat = stats; stat != stNULL; stat = stat->stNext)
312 if (stat->stKind == skRoutine) {
313 routine_t *rt = stat->stRoutine;
314
315 /* For each arg of the routine, write an arg descriptor:
316 */
317 WriteRPCRoutineArgDescriptor(file, rt);
318 }
319 fprintf(file, "\t},\n\n");
320 }
321
322
323 /*
324 * Write out the description of this subsystem, for use in direct RPC
325 */
326 static void
327 WriteSubsystem(FILE *file, statement_t *stats)
328 {
329 statement_t *stat;
330 int descr_count = 0;
331
332 for (stat = stats; stat != stNULL; stat = stat->stNext)
333 if (stat->stKind == skRoutine) {
334 routine_t *rt = stat->stRoutine;
335 descr_count += rtCountArgDescriptors(rt->rtArgs, (int *) 0);
336 }
337 fprintf(file, "\n");
338 if (ServerHeaderFileName == strNULL) {
339 WriteMigExternal(file);
340 fprintf(file, "boolean_t %s(", ServerDemux);
341 if (BeAnsiC) {
342 fprintf(file, "\n\t\tmach_msg_header_t *InHeadP,");
343 fprintf(file, "\n\t\tmach_msg_header_t *OutHeadP");
344 }
345 fprintf(file, ");\n\n");
346
347 WriteMigExternal(file);
348 fprintf(file, "mig_routine_t %s_routine(", ServerDemux);
349 if (BeAnsiC) {
350 fprintf(file, "\n\t\tmach_msg_header_t *InHeadP");
351 }
352 fprintf(file, ");\n\n");
353 }
354 fprintf(file, "\n/* Description of this subsystem, for use in direct RPC */\n");
355 if (ServerHeaderFileName == strNULL) {
356 fprintf(file, "const struct %s {\n", ServerSubsys);
357 if (UseRPCTrap) {
358 fprintf(file, "\tstruct subsystem *\tsubsystem;\t/* Reserved for system use */\n");
359 }
360 else {
361 fprintf(file, "\tmig_server_routine_t \tserver;\t/* Server routine */\n");
362 }
363 fprintf(file, "\tmach_msg_id_t\tstart;\t/* Min routine number */\n");
364 fprintf(file, "\tmach_msg_id_t\tend;\t/* Max routine number + 1 */\n");
365 fprintf(file, "\tunsigned int\tmaxsize;\t/* Max msg size */\n");
366 if (UseRPCTrap) {
367 fprintf(file, "\tvm_address_t\tbase_addr;\t/* Base address */\n");
368 fprintf(file, "\tstruct rpc_routine_descriptor\t/*Array of routine descriptors */\n");
369 }
370 else {
371 fprintf(file, "\tvm_address_t\treserved;\t/* Reserved */\n");
372 fprintf(file, "\tstruct routine_descriptor\t/*Array of routine descriptors */\n");
373 }
374 fprintf(file, "\t\troutine[%d];\n", rtNumber);
375 if (UseRPCTrap) {
376 fprintf(file, "\tstruct rpc_routine_arg_descriptor\t/*Array of arg descriptors */\n");
377 fprintf(file, "\t\targ_descriptor[%d];\n", descr_count);
378 }
379 fprintf(file, "} %s = {\n", ServerSubsys);
380 }
381 else {
382 fprintf(file, "const struct %s %s = {\n", ServerSubsys, ServerSubsys);
383 }
384 if (UseRPCTrap) {
385 fprintf(file, "\t0,\n");
386 }
387 else {
388 fprintf(file, "\t%s_routine,\n", ServerDemux);
389 }
390 fprintf(file, "\t%d,\n", SubsystemBase);
391 fprintf(file, "\t%d,\n", SubsystemBase + rtNumber);
392 fprintf(file, "\t(mach_msg_size_t)sizeof(union __ReplyUnion__%s),\n", ServerSubsys);
393 if (UseRPCTrap) {
394 fprintf(file, "\t(vm_address_t)&%s,\n", ServerSubsys);
395 }
396 else {
397 fprintf(file, "\t(vm_address_t)0,\n");
398 }
399 WriteRoutineEntries(file, stats);
400
401 if (UseRPCTrap)
402 WriteArgDescriptorEntries(file, stats);
403 else
404 fprintf(file, "\n");
405
406 fprintf(file, "};\n\n");
407 }
408
409 #if NOT_CURRENTLY_USED
410
411 static void
412 WriteArraySizes(FILE *file, statement_t *stats)
413 {
414 u_int current = 0;
415 statement_t *stat;
416
417 for (stat = stats; stat != stNULL; stat = stat->stNext)
418 if (stat->stKind == skRoutine) {
419 routine_t *rt = stat->stRoutine;
420
421 while (current++ < rt->rtNumber)
422 fprintf(file, "\t\t0,\n");
423 fprintf(file, "\t\t(mach_msg_size_t)sizeof(__Reply__%s_t),\n", rt->rtName);
424 }
425 while (current++ < rtNumber)
426 fprintf(file, "\t\t\t0,\n");
427 }
428
429 #endif /* NOT_CURRENTLY_USED */
430
431 void
432 WriteServerRequestUnion(FILE *file, statement_t *stats)
433 {
434 statement_t *stat;
435
436 fprintf(file, "\n");
437 fprintf(file, "/* union of all requests */\n\n");
438 fprintf(file, "#ifndef __RequestUnion__%s__defined\n", ServerSubsys);
439 fprintf(file, "#define __RequestUnion__%s__defined\n", ServerSubsys);
440 fprintf(file, "union __RequestUnion__%s {\n", ServerSubsys);
441 for (stat = stats; stat != stNULL; stat = stat->stNext) {
442 if (stat->stKind == skRoutine) {
443 routine_t *rt;
444
445 rt = stat->stRoutine;
446 fprintf(file, "\t__Request__%s_t Request_%s;\n", rt->rtName, rt->rtName);
447 }
448 }
449 fprintf(file, "};\n");
450 fprintf(file, "#endif /* __RequestUnion__%s__defined */\n", ServerSubsys);
451 }
452
453 void
454 WriteServerReplyUnion(FILE *file, statement_t *stats)
455 {
456 statement_t *stat;
457
458 fprintf(file, "\n");
459 fprintf(file, "/* union of all replies */\n\n");
460 fprintf(file, "#ifndef __ReplyUnion__%s__defined\n", ServerSubsys);
461 fprintf(file, "#define __ReplyUnion__%s__defined\n", ServerSubsys);
462 fprintf(file, "union __ReplyUnion__%s {\n", ServerSubsys);
463 for (stat = stats; stat != stNULL; stat = stat->stNext) {
464 if (stat->stKind == skRoutine) {
465 routine_t *rt;
466
467 rt = stat->stRoutine;
468 fprintf(file, "\t__Reply__%s_t Reply_%s;\n", rt->rtName, rt->rtName);
469 }
470 }
471 fprintf(file, "};\n");
472 fprintf(file, "#endif /* __ReplyUnion__%s__defined */\n", ServerSubsys);
473 }
474
475 static void
476 WriteDispatcher(FILE *file, statement_t *stats)
477 {
478 /*
479 * Write the subsystem stuff.
480 */
481 fprintf(file, "\n");
482 WriteSubsystem(file, stats);
483
484 /*
485 * Then, the server routine
486 */
487 fprintf(file, "mig_external boolean_t %s\n", ServerDemux);
488 if (BeAnsiC) {
489 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
490 }
491 else {
492 fprintf(file, "#if\t%s\n", NewCDecl);
493 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
494 fprintf(file, "#else\n");
495 fprintf(file, "\t(InHeadP, OutHeadP)\n");
496 fprintf(file, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n");
497 fprintf(file, "#endif\t/* %s */\n", NewCDecl);
498 }
499
500 fprintf(file, "{\n");
501 fprintf(file, "\t/*\n");
502 fprintf(file, "\t * typedef struct {\n");
503 fprintf(file, "\t * \tmach_msg_header_t Head;\n");
504 fprintf(file, "\t * \tNDR_record_t NDR;\n");
505 fprintf(file, "\t * \tkern_return_t RetCode;\n");
506 fprintf(file, "\t * } mig_reply_error_t;\n");
507 fprintf(file, "\t */\n");
508 fprintf(file, "\n");
509
510 fprintf(file, "\tmig_routine_t routine;\n");
511 fprintf(file, "\n");
512
513 fprintf(file, "\tOutHeadP->msgh_bits = ");
514 fprintf(file, "MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0);\n");
515 fprintf(file, "\tOutHeadP->msgh_remote_port = InHeadP->msgh_reply_port;\n");
516 fprintf(file, "\t/* Minimal size: routine() will update it if different */\n");
517 fprintf(file, "\tOutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);\n");
518 fprintf(file, "\tOutHeadP->msgh_local_port = MACH_PORT_NULL;\n");
519 fprintf(file, "\tOutHeadP->msgh_id = InHeadP->msgh_id + 100;\n");
520 fprintf(file, "\tOutHeadP->msgh_reserved = 0;\n");
521 fprintf(file, "\n");
522
523 fprintf(file, "\tif ((InHeadP->msgh_id > %d) || (InHeadP->msgh_id < %d) ||\n", SubsystemBase + rtNumber - 1, SubsystemBase);
524 fprintf(file, "\t ((routine = %s.routine[InHeadP->msgh_id - %d].stub_routine) == 0)) {\n", ServerSubsys, SubsystemBase);
525 fprintf(file, "\t\t((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;\n");
526 fprintf(file, "\t\t((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;\n");
527 if (UseEventLogger) {
528 fprintf(file, "#if MIG_DEBUG\n");
529 fprintf(file, "\t\tLOG_ERRORS(MACH_MSG_LOG_SERVER, MACH_MSG_ERROR_UNKNOWN_ID,\n");
530 fprintf(file, "\t\t\t&InHeadP->msgh_id, __FILE__, __LINE__);\n");
531 fprintf(file, "#endif /* MIG_DEBUG */\n");
532 }
533 fprintf(file, "\t\treturn FALSE;\n");
534 fprintf(file, "\t}\n");
535
536 /* Call appropriate routine */
537 fprintf(file, "\t(*routine) (InHeadP, OutHeadP);\n");
538 fprintf(file, "\treturn TRUE;\n");
539 fprintf(file, "}\n");
540 fprintf(file, "\n");
541
542 /*
543 * Then, the <subsystem>_server_routine routine
544 */
545 fprintf(file, "mig_external mig_routine_t %s_routine\n", ServerDemux);
546 if (BeAnsiC) {
547 fprintf(file, "\t(mach_msg_header_t *InHeadP)\n");
548 }
549 else {
550 fprintf(file, "#if\t%s\n", NewCDecl);
551 fprintf(file, "\t(mach_msg_header_t *InHeadP)\n");
552 fprintf(file, "#else\n");
553 fprintf(file, "\t(InHeadP)\n");
554 fprintf(file, "\tmach_msg_header_t *InHeadP;\n");
555 fprintf(file, "#endif\t/* %s */\n", NewCDecl);
556 }
557
558 fprintf(file, "{\n");
559 fprintf(file, "\tint msgh_id;\n");
560 fprintf(file, "\n");
561 fprintf(file, "\tmsgh_id = InHeadP->msgh_id - %d;\n", SubsystemBase);
562 fprintf(file, "\n");
563 fprintf(file, "\tif ((msgh_id > %d) || (msgh_id < 0))\n", rtNumber - 1);
564 fprintf(file, "\t\treturn 0;\n");
565 fprintf(file, "\n");
566 fprintf(file, "\treturn %s.routine[msgh_id].stub_routine;\n", ServerSubsys);
567 fprintf(file, "}\n");
568
569 /* symtab */
570
571 if (GenSymTab) {
572 fprintf(file,"\nmig_symtab_t _%sSymTab[] = {\n",SubsystemName);
573 WriteSymTabEntries(file,stats);
574 fprintf(file,"};\n");
575 fprintf(file,"int _%sSymTabBase = %d;\n",SubsystemName,SubsystemBase);
576 fprintf(file,"int _%sSymTabEnd = %d;\n",SubsystemName,SubsystemBase+rtNumber);
577 }
578 }
579
580 #if NOT_CURRENTLY_USED
581 /*
582 * Returns the return type of the server-side work function.
583 * Suitable for "extern %s serverfunc()".
584 */
585 static char *
586 ServerSideType(routine_t *rt)
587 {
588 return rt->rtRetCode->argType->itTransType;
589 }
590 #endif /* NOT_CURRENTLY_USED */
591
592 static void
593 WriteRetCode(FILE *file, argument_t *ret)
594 {
595 ipc_type_t *it = ret->argType;
596
597 if (akCheck(ret->argKind, akbVarNeeded)) {
598 fprintf(file, "\t%s %s;\n", it->itTransType, ret->argVarName);
599 }
600 }
601
602 static void
603 WriteLocalVarDecl(FILE *file, argument_t *arg)
604 {
605 ipc_type_t *it = arg->argType;
606 ipc_type_t *btype = it->itElement;
607
608 if (IS_VARIABLE_SIZED_UNTYPED(it))
609 fprintf(file, "\t%s %s[%d]", btype->itTransType, arg->argVarName, btype->itNumber ? it->itNumber/btype->itNumber : 0);
610 else if (IS_MULTIPLE_KPD(it)) {
611 if (btype->itTransType != strNULL)
612 fprintf(file, "\t%s %s[%d]", btype->itTransType, arg->argVarName, it->itKPD_Number);
613 else
614 /* arrays of ool or oolport */
615 fprintf(file, "\tvoid *%s[%d]", arg->argVarName, it->itKPD_Number);
616 }
617 else
618 fprintf(file, "\t%s %s", it->itTransType, arg->argVarName);
619 }
620
621 #if NOT_CURRENTLY_USED
622 static void
623 WriteServerArgDecl(FILE *file, argument_t *arg)
624 {
625 fprintf(file, "%s %s%s", arg->argType->itTransType, arg->argByReferenceServer ? "*" : "", arg->argVarName);
626 }
627 #endif /* NOT_CURRENTLY_USED */
628
629 /*
630 * Writes the local variable declarations which are always
631 * present: InP, OutP, the server-side work function.
632 */
633 static void
634 WriteVarDecls(FILE *file, routine_t *rt)
635 {
636 int i;
637
638 fprintf(file, "\tRequest *In0P = (Request *) InHeadP;\n");
639 for (i = 1; i <= rt->rtMaxRequestPos; i++)
640 fprintf(file, "\tRequest *In%dP;\n", i);
641 fprintf(file, "\tReply *OutP = (Reply *) OutHeadP;\n");
642
643 /* if reply is variable, we may need msgh_size_delta and msgh_size */
644 if (rt->rtNumReplyVar > 1)
645 fprintf(file, "\tunsigned int msgh_size;\n");
646 if (rt->rtMaxReplyPos > 0)
647 fprintf(file, "\tunsigned int msgh_size_delta;\n");
648 if (rt->rtNumReplyVar > 1 || rt->rtMaxReplyPos > 0)
649 fprintf(file, "\n");
650
651 if (rt->rtServerImpl) {
652 fprintf(file, "\tmach_msg_max_trailer_t *TrailerP;\n");
653 fprintf(file, "#if\t__MigTypeCheck\n");
654 fprintf(file, "\tunsigned int trailer_size __attribute__((unused));\n");
655 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
656 }
657 fprintf(file, "#ifdef\t__MIG_check__Request__%s_t__defined\n", rt->rtName);
658 fprintf(file, "\tkern_return_t check_result;\n");
659 fprintf(file, "#endif\t/* __MIG_check__Request__%s_t__defined */\n", rt->rtName);
660 fprintf(file, "\n");
661 }
662
663 static void
664 WriteReplyInit(FILE *file, routine_t *rt)
665 {
666 fprintf(file, "\n");
667 if (rt->rtNumReplyVar > 1 || rt->rtMaxReplyPos)
668 /* WritheAdjustMsgSize() has been executed at least once! */
669 fprintf(file, "\tOutP = (Reply *) OutHeadP;\n");
670
671 if (!rt->rtSimpleReply) /* complex reply message */
672 fprintf(file, "\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n");
673
674 if (rt->rtNumReplyVar == 0) {
675 fprintf(file, "\tOutP->Head.msgh_size = ");
676 rtMinReplySize(file, rt, "Reply");
677 fprintf(file, ";\n");
678 }
679 else if (rt->rtNumReplyVar > 1)
680 fprintf(file, "\tOutP->Head.msgh_size = msgh_size;\n");
681 /* the case rt->rtNumReplyVar = 1 is taken care of in WriteAdjustMsgSize() */
682 }
683
684 static void
685 WriteRetCArgCheckError(FILE *file, routine_t *rt)
686 {
687 fprintf(file, "\tif (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&\n");
688 fprintf(file, "\t (In0P->Head.msgh_size == (mach_msg_size_t)sizeof(mig_reply_error_t)))\n");
689 fprintf(file, "\t{\n");
690 }
691
692 static void
693 WriteRetCArgFinishError(FILE *file, routine_t *rt)
694 {
695 argument_t *retcode = rt->rtRetCArg;
696
697 fprintf(file, "\treturn;\n");
698 fprintf(file, "\t}\n");
699 retcode->argMsgField = "KERN_SUCCESS";
700 }
701
702 static void
703 WriteCheckHead(FILE *file, routine_t *rt)
704 {
705 fprintf(file, "#if\t__MigTypeCheck\n");
706 if (rt->rtNumRequestVar > 0)
707 fprintf(file, "\tmsgh_size = In0P->Head.msgh_size;\n");
708
709 if (rt->rtSimpleRequest) {
710 /* Expecting a simple message. */
711 fprintf(file, "\tif ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
712 if (rt->rtNumRequestVar > 0) {
713 fprintf(file, "\t (msgh_size < ");
714 rtMinRequestSize(file, rt, "__Request");
715 fprintf(file, ") || (msgh_size > (mach_msg_size_t)sizeof(__Request)))\n");
716 }
717 else
718 fprintf(file, "\t (In0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Request)))\n");
719 }
720 else {
721 /* Expecting a complex message. */
722
723 fprintf(file, "\tif (");
724 if (rt->rtRetCArg != argNULL)
725 fprintf(file, "(");
726 fprintf(file, "!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
727 fprintf(file, "\t (In0P->msgh_body.msgh_descriptor_count != %d) ||\n", rt->rtRequestKPDs);
728 if (rt->rtNumRequestVar > 0) {
729 fprintf(file, "\t (msgh_size < ");
730 rtMinRequestSize(file, rt, "__Request");
731 fprintf(file, ") || (msgh_size > (mach_msg_size_t)sizeof(__Request))");
732 }
733 else
734 fprintf(file, "\t (In0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Request))");
735 if (rt->rtRetCArg == argNULL)
736 fprintf(file, ")\n");
737 else {
738 fprintf(file, ") &&\n");
739 fprintf(file, "\t ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
740 fprintf(file, "\t In0P->Head.msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||\n");
741 fprintf(file, "\t ((mig_reply_error_t *)In0P)->RetCode == KERN_SUCCESS))\n");
742 }
743 }
744 fprintf(file, "\t\treturn MIG_BAD_ARGUMENTS;\n");
745 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
746 fprintf(file, "\n");
747 }
748
749 void
750 WriteRequestNDRConvertIntRepArgCond(FILE *file, argument_t *arg)
751 {
752 routine_t *rt = arg->argRoutine;
753
754 fprintf(file, "defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
755 }
756
757 void
758 WriteRequestNDRConvertCharRepArgCond(FILE *file, argument_t *arg)
759 {
760 routine_t *rt = arg->argRoutine;
761
762 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
763 fprintf(file, "defined(__NDR_convert__char_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
764 else
765 fprintf(file, "0");
766 }
767
768 void
769 WriteRequestNDRConvertFloatRepArgCond(FILE *file, argument_t *arg)
770 {
771 routine_t *rt = arg->argRoutine;
772
773 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
774 fprintf(file, "defined(__NDR_convert__float_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
775 else
776 fprintf(file, "0");
777 }
778
779 void
780 WriteRequestNDRConvertIntRepArgDecl(FILE *file, argument_t *arg)
781 {
782 WriteNDRConvertArgDecl(file, arg, "int_rep", "Request");
783 }
784
785 void
786 WriteRequestNDRConvertCharRepArgDecl(FILE *file, argument_t *arg)
787 {
788 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
789 WriteNDRConvertArgDecl(file, arg, "char_rep", "Request");
790 }
791
792 void
793 WriteRequestNDRConvertFloatRepArgDecl(FILE *file, argument_t *arg)
794 {
795 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
796 WriteNDRConvertArgDecl(file, arg, "float_rep", "Request");
797 }
798
799 void
800 WriteRequestNDRConvertArgUse(FILE *file, argument_t *arg, char *convert)
801 {
802 routine_t *rt = arg->argRoutine;
803 argument_t *count = arg->argCount;
804 char argname[MAX_STR_LEN];
805
806 if ((akIdent(arg->argKind) == akeCount || akIdent(arg->argKind) == akeCountInOut) &&
807 (arg->argParent && akCheck(arg->argParent->argKind, akbSendNdr)))
808 return;
809
810 if (arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {
811 if (count && !arg->argSameCount && !strcmp(convert, "int_rep")) {
812 fprintf(file, "#if defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)\n", rt->rtName, count->argMsgField);
813 fprintf(file, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&In%dP->%s, In%dP->NDR.int_rep);\n", rt->rtName, count->argMsgField, count->argRequestPos, count->argMsgField, count->argRequestPos);
814 fprintf(file, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt->rtName, count->argMsgField);
815 }
816
817 sprintf(argname, "(%s)(In%dP->%s.address)", FetchServerType(arg->argType), arg->argRequestPos, arg->argMsgField);
818 }
819 else {
820 sprintf(argname, "&In%dP->%s", arg->argRequestPos, arg->argMsgField);
821 }
822
823 fprintf(file, "#if defined(__NDR_convert__%s__Request__%s_t__%s__defined)\n", convert, rt->rtName, arg->argMsgField);
824 fprintf(file, "\t\t__NDR_convert__%s__Request__%s_t__%s(%s, In0P->NDR.%s", convert, rt->rtName, arg->argMsgField, argname, convert);
825 if (count)
826 fprintf(file, ", In%dP->%s", count->argRequestPos, count->argMsgField);
827 fprintf(file, ");\n");
828 fprintf(file, "#endif\t/* __NDR_convert__%s__Request__%s_t__%s__defined */\n", convert, rt->rtName, arg->argMsgField);
829 }
830
831 void
832 WriteRequestNDRConvertIntRepOneArgUse(FILE *file, argument_t *arg)
833 {
834 routine_t *rt = arg->argRoutine;
835
836 fprintf(file, "#if defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)\n", rt->rtName, arg->argMsgField);
837 fprintf(file, "\tif (In0P->NDR.int_rep != NDR_record.int_rep)\n");
838 fprintf(file, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&In%dP->%s, In%dP->NDR.int_rep);\n", rt->rtName, arg->argMsgField, arg->argRequestPos, arg->argMsgField, arg->argRequestPos);
839 fprintf(file, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt->rtName, arg->argMsgField);
840 }
841
842 void
843 WriteRequestNDRConvertIntRepArgUse(FILE *file, argument_t *arg)
844 {
845 WriteRequestNDRConvertArgUse(file, arg, "int_rep");
846 }
847
848 void
849 WriteRequestNDRConvertCharRepArgUse(FILE *file, argument_t *arg)
850 {
851 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
852 WriteRequestNDRConvertArgUse(file, arg, "char_rep");
853 }
854
855 void
856 WriteRequestNDRConvertFloatRepArgUse(FILE *file, argument_t *arg)
857 {
858 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
859 WriteRequestNDRConvertArgUse(file, arg, "float_rep");
860 }
861
862 static void
863 WriteCalcArgSize(FILE *file, argument_t *arg)
864 {
865 ipc_type_t *ptype = arg->argType;
866
867 if (PackMsg == FALSE) {
868 fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize);
869 return;
870 }
871
872 if (IS_OPTIONAL_NATIVE(ptype))
873 fprintf(file, "(In%dP->__Present__%s ? _WALIGNSZ_(%s) : 0)" , arg->argRequestPos, arg->argMsgField, ptype->itServerType);
874 else {
875 ipc_type_t *btype = ptype->itElement;
876 argument_t *count = arg->argCount;
877 int multiplier = btype->itTypeSize;
878
879 if (btype->itTypeSize % itWordAlign != 0)
880 fprintf(file, "_WALIGN_");
881 fprintf(file, "(");
882
883 if (multiplier > 1)
884 fprintf(file, "%d * ", multiplier);
885 fprintf(file, "In%dP->%s", count->argRequestPos, count->argMsgField);
886 fprintf(file, ")");
887 }
888 }
889
890 static void
891 WriteCheckArgSize(FILE *file, routine_t *rt, argument_t *arg, const char *comparator)
892 {
893 ipc_type_t *ptype = arg->argType;
894
895
896 fprintf(file, "\tif (((msgh_size - ");
897 rtMinRequestSize(file, rt, "__Request");
898 fprintf(file, ") ");
899 if (PackMsg == FALSE) {
900 fprintf(file, "%s %d)", comparator, ptype->itTypeSize + ptype->itPadSize);
901 } else if (IS_OPTIONAL_NATIVE(ptype)) {
902 fprintf(file, "%s (In%dP->__Present__%s ? _WALIGNSZ_(%s) : 0))" , comparator, arg->argRequestPos, arg->argMsgField, ptype->itServerType);
903 } else {
904 ipc_type_t *btype = ptype->itElement;
905 argument_t *count = arg->argCount;
906 int multiplier = btype->itTypeSize;
907
908 if (multiplier > 1)
909 fprintf(file, "/ %d ", multiplier);
910 fprintf(file, "< In%dP->%s) ||\n", count->argRequestPos, count->argMsgField);
911 fprintf(file, "\t (msgh_size %s ", comparator);
912 rtMinRequestSize(file, rt, "__Request");
913 fprintf(file, " + ");
914 WriteCalcArgSize(file, arg);
915 fprintf(file, ")");
916 }
917 fprintf(file, ")\n\t\treturn MIG_BAD_ARGUMENTS;\n");
918 }
919
920 static void
921 WriteCheckMsgSize(FILE *file, argument_t *arg)
922 {
923 routine_t *rt = arg->argRoutine;
924
925 if (arg->argCount && !arg->argSameCount)
926 WriteRequestNDRConvertIntRepOneArgUse(file, arg->argCount);
927 if (arg->argRequestPos == rt->rtMaxRequestPos) {
928 fprintf(file, "#if\t__MigTypeCheck\n");
929
930 /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */
931 fprintf(file, "\t" "if ( In%dP->%s > %d )\n", arg->argCount->argRequestPos, arg->argCount->argMsgField, arg->argType->itNumber);
932 fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file);
933 /* ...end... */
934
935 WriteCheckArgSize(file, rt, arg, "!=");
936
937 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
938 }
939 else {
940 /* If there aren't any more variable-sized arguments after this,
941 then we must check for exact msg-size and we don't need to
942 update msgh_size. */
943
944 boolean_t LastVarArg = arg->argRequestPos+1 == rt->rtNumRequestVar;
945
946 /* calculate the actual size in bytes of the data field. note
947 that this quantity must be a multiple of four. hence, if
948 the base type size isn't a multiple of four, we have to
949 round up. note also that btype->itNumber must
950 divide btype->itTypeSize (see itCalculateSizeInfo). */
951
952 fprintf(file, "\tmsgh_size_delta = ");
953 WriteCalcArgSize(file, arg);
954 fprintf(file, ";\n");
955 fprintf(file, "#if\t__MigTypeCheck\n");
956
957 /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */
958 fprintf(file, "\t" "if ( In%dP->%s > %d )\n", arg->argCount->argRequestPos, arg->argCount->argMsgField, arg->argType->itNumber);
959 fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file);
960 /* ...end... */
961
962 /* Don't decrement msgh_size until we've checked that
963 it won't underflow. */
964 WriteCheckArgSize(file, rt, arg, LastVarArg ? "!=" : "<");
965
966 if (!LastVarArg)
967 fprintf(file, "\tmsgh_size -= msgh_size_delta;\n");
968
969 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
970 }
971 fprintf(file, "\n");
972 }
973
974 static char *
975 InArgMsgField(argument_t *arg, char *str)
976 {
977 static char buffer[MAX_STR_LEN];
978 char who[20] = {0};
979
980 /*
981 * Inside the kernel, the request and reply port fields
982 * really hold ipc_port_t values, not mach_port_t values.
983 * Hence we must cast the values.
984 */
985
986 if (!(arg->argFlags & flRetCode)) {
987 if (akCheck(arg->argKind, akbServerImplicit))
988 sprintf(who, "TrailerP->");
989 else
990 sprintf(who, "In%dP->", arg->argRequestPos);
991 }
992
993 #ifdef MIG_KERNEL_PORT_CONVERSION
994 if (IsKernelServer &&
995 ((akIdent(arg->argKind) == akeRequestPort) ||
996 (akIdent(arg->argKind) == akeReplyPort)))
997 sprintf(buffer, "(ipc_port_t) %s%s%s", who, str, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField);
998 else
999 #endif
1000 sprintf(buffer, "%s%s%s", who, str, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField);
1001
1002 return buffer;
1003 }
1004
1005 static void
1006 WriteExtractArgValue(FILE *file, argument_t *arg)
1007 {
1008 ipc_type_t *it = arg->argType;
1009 string_t recast;
1010
1011 #ifdef MIG_KERNEL_PORT_CONVERSION
1012 if (IsKernelServer && it->itPortType && streql(it->itServerType, "ipc_port_t")
1013 && akIdent(arg->argKind) != akeRequestPort
1014 && akIdent(arg->argKind) != akeReplyPort)
1015 recast = "(mach_port_t)";
1016 else
1017 #endif
1018 recast = "";
1019 if (it->itInTrans != strNULL)
1020 WriteCopyType(file, it, FALSE, "%s", "/* %s */ %s(%s%s)", arg->argVarName, it->itInTrans, recast, InArgMsgField(arg, ""));
1021 else
1022 WriteCopyType(file, it, FALSE, "%s", "/* %s */ %s%s", arg->argVarName, recast, InArgMsgField(arg, ""));
1023
1024 fprintf(file, "\n");
1025 }
1026
1027 /*
1028 * argKPD_Extract discipline for Port types.
1029 */
1030 static void
1031 WriteExtractKPD_port(FILE *file, argument_t *arg)
1032 {
1033 ipc_type_t *it = arg->argType;
1034 char *recast = "";
1035
1036 WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE);
1037 /* translation function do not apply to complex types */
1038 #ifdef MIG_KERNEL_PORT_CONVERSION
1039 if (IsKernelServer)
1040 recast = "(mach_port_t)";
1041 #endif
1042 fprintf(file, "\t\t%s[i] = %sptr->name;\n", arg->argVarName, recast);
1043 fprintf(file, "\t}\n");
1044 }
1045
1046 /*
1047 * argKPD_Extract discipline for out-of-line types.
1048 */
1049 static void
1050 WriteExtractKPD_ool(FILE *file, argument_t *arg)
1051 {
1052 ipc_type_t *it = arg->argType;
1053
1054 WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE);
1055 fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName);
1056 fprintf(file, "\t}\n");
1057 }
1058
1059 /*
1060 * argKPD_Extract discipline for out-of-line Port types.
1061 */
1062 static void
1063 WriteExtractKPD_oolport(FILE *file, argument_t *arg)
1064 {
1065 ipc_type_t *it = arg->argType;
1066
1067 WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE);
1068 fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName);
1069 fprintf(file, "\t}\n");
1070 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendRcv)) {
1071 argument_t *poly = arg->argPoly;
1072 char *pref = poly->argByReferenceServer ? "*" : "";
1073
1074 fprintf(file, "\t%s%s = In%dP->%s[0].disposition;\n", pref, poly->argVarName, arg->argRequestPos, arg->argMsgField);
1075 }
1076 }
1077
1078
1079 static void
1080 WriteInitializeCount(FILE *file, argument_t *arg)
1081 {
1082 ipc_type_t *ptype = arg->argParent->argType;
1083 ipc_type_t *btype = ptype->itElement;
1084 identifier_t newstr;
1085
1086 /*
1087 * Initialize 'count' argument for variable-length inline OUT parameter
1088 * with maximum allowed number of elements.
1089 */
1090
1091 if (akCheck(arg->argKind, akbVarNeeded))
1092 newstr = arg->argMsgField;
1093 else
1094 newstr = (identifier_t)strconcat("OutP->", arg->argMsgField);
1095
1096 fprintf(file, "\t%s = ", newstr);
1097 if (IS_MULTIPLE_KPD(ptype))
1098 fprintf(file, "%d;\n", ptype->itKPD_Number);
1099 else
1100 fprintf(file, "%d;\n", btype->itNumber? ptype->itNumber/btype->itNumber : 0);
1101
1102 /*
1103 * If the user passed in a count, then we use the minimum.
1104 * We can't let the user completely override our maximum,
1105 * or the user might convince the server to overwrite the buffer.
1106 */
1107
1108 if (arg->argCInOut != argNULL) {
1109 char *msgfield = InArgMsgField(arg->argCInOut, "");
1110
1111 fprintf(file, "\tif (%s < %s)\n", msgfield, newstr);
1112 fprintf(file, "\t\t%s = %s;\n", newstr, msgfield);
1113 }
1114
1115 fprintf(file, "\n");
1116 }
1117
1118 static void
1119 WriteAdjustRequestMsgPtr(FILE *file, argument_t *arg)
1120 {
1121 ipc_type_t *ptype = arg->argType;
1122
1123 if (PackMsg == FALSE) {
1124 fprintf(file, "\t*In%dPP = In%dP = (__Request *) ((pointer_t) In%dP);\n\n", arg->argRequestPos+1, arg->argRequestPos+1, arg->argRequestPos);
1125 return;
1126 }
1127
1128 fprintf(file, "\t*In%dPP = In%dP = (__Request *) ((pointer_t) In%dP + msgh_size_delta - ", arg->argRequestPos+1, arg->argRequestPos+1, arg->argRequestPos);
1129 if (IS_OPTIONAL_NATIVE(ptype))
1130 fprintf(file, "_WALIGNSZ_(%s)", ptype->itUserType);
1131 else
1132 fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize);
1133 fprintf(file, ");\n\n");
1134 }
1135
1136 static void
1137 WriteCheckRequestTrailerArgs(FILE *file, routine_t *rt)
1138 {
1139 argument_t *arg;
1140
1141 if (rt->rtServerImpl)
1142 WriteCheckTrailerHead(file, rt, FALSE);
1143
1144 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
1145 if (akCheck(arg->argKind, akbServerImplicit))
1146 WriteCheckTrailerSize(file, FALSE, arg);
1147 }
1148 }
1149
1150 static void
1151 WriteExtractArg(FILE *file, argument_t *arg)
1152 {
1153 if (akCheckAll(arg->argKind, akbSendRcv|akbVarNeeded)) {
1154 if (akCheck(arg->argKind, akbSendKPD))
1155 (*arg->argKPD_Extract)(file, arg);
1156 else
1157 WriteExtractArgValue(file, arg);
1158 }
1159
1160 if ((akIdent(arg->argKind) == akeCount) &&
1161 akCheck(arg->argKind, akbReturnSnd)) {
1162
1163 ipc_type_t *ptype = arg->argParent->argType;
1164 /*
1165 * the count will be initialized to 0 in the case of
1166 * unbounded arrays (MigInLine = TRUE): this is because
1167 * the old interface used to pass to the target procedure
1168 * the maximum in-line size (it was 2048 bytes)
1169 */
1170 if (IS_VARIABLE_SIZED_UNTYPED(ptype) ||
1171 IS_MIG_INLINE_EMUL(ptype) ||
1172 (IS_MULTIPLE_KPD(ptype) && ptype->itVarArray))
1173 WriteInitializeCount(file, arg);
1174 }
1175 }
1176
1177 static void
1178 WriteServerCallArg(FILE *file, argument_t *arg)
1179 {
1180 ipc_type_t *it = arg->argType;
1181 boolean_t NeedClose = FALSE;
1182 u_int elemsize = 0;
1183 string_t at = (arg->argByReferenceServer ||
1184 it->itNativePointer) ? "&" : "";
1185 string_t star = (arg->argByReferenceServer) ? " *" : "";
1186 string_t msgfield =
1187 (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField;
1188
1189 if ((it->itInTrans != strNULL) &&
1190 akCheck(arg->argKind, akbSendRcv) &&
1191 !akCheck(arg->argKind, akbVarNeeded)) {
1192 fprintf(file, "%s%s(", at, it->itInTrans);
1193 NeedClose = TRUE;
1194 }
1195
1196 if (akCheckAll(arg->argKind, akbVarNeeded|akbServerArg))
1197 fprintf(file, "%s%s", at, arg->argVarName);
1198 else if (akCheckAll(arg->argKind, akbSendRcv|akbSendKPD)) {
1199 if (!it->itInLine)
1200 /* recast the void *, although it is not necessary */
1201 fprintf(file, "(%s%s)%s(%s)", it->itTransType, star, at, InArgMsgField(arg, ""));
1202 else
1203 #ifdef MIG_KERNEL_PORT_CONVERSION
1204 if (IsKernelServer && streql(it->itServerType, "ipc_port_t"))
1205 /* recast the port to the kernel internal form value */
1206 fprintf(file, "(ipc_port_t%s)%s(%s)", star, at, InArgMsgField(arg, ""));
1207 else
1208 #endif
1209 fprintf(file, "%s%s", at, InArgMsgField(arg, ""));
1210 }
1211 else if (akCheck(arg->argKind, akbSendRcv)) {
1212 if (IS_OPTIONAL_NATIVE(it)) {
1213 fprintf(file, "(%s ? ", InArgMsgField(arg, "__Present__"));
1214 fprintf(file, "%s%s.__Real__%s : %s)", at, InArgMsgField(arg, ""), arg->argMsgField, it->itBadValue);
1215 }
1216 else {
1217 if (akIdent(arg->argKind) == akeCount && arg->argParent) {
1218 char *suffix = arg->argParent->argSuffix;
1219 ipc_type_t *elemType = arg->argParent->argType->itElement;
1220 /* temporarily squash any name suffix such as ".address" (we'll be adding our own) */
1221 arg->argParent->argSuffix = NULL;
1222 switch (arg->argParent->argKPD_Type) {
1223 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
1224 /* count of the number of descriptors */
1225 fprintf(file, "%s%s.count", at, InArgMsgField(arg->argParent, ""));
1226 break;
1227 case MACH_MSG_OOL_DESCRIPTOR:
1228 /* descriptor buffer size / element size */
1229 if (!(arg->argByReferenceServer || it->itNativePointer)) {
1230 fprintf(file, "%s%s.size", at, InArgMsgField(arg->argParent, ""));
1231 elemsize = ((elemType->itNumber * elemType->itSize) + 7) / 8;
1232 if (elemsize > 1) {
1233 fprintf(file, " / %d", elemsize);
1234 }
1235 } else {
1236 fprintf(file, "%s%s", at, InArgMsgField(arg, ""));
1237 }
1238 break;
1239 default:
1240 fprintf(file, "%s%s", at, InArgMsgField(arg, ""));
1241 break;
1242 }
1243 arg->argParent->argSuffix = suffix;
1244 } else {
1245 fprintf(file, "%s%s", at, InArgMsgField(arg, ""));
1246 }
1247 }
1248 }
1249 else if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnKPD)) {
1250 if (!it->itInLine)
1251 /* recast the void *, although it is not necessary */
1252 fprintf(file, "(%s%s)%s(OutP->%s)", it->itTransType, star, at, msgfield);
1253 else
1254 #ifdef MIG_KERNEL_PORT_CONVERSION
1255 if (IsKernelServer && streql(it->itServerType, "ipc_port_t"))
1256 /* recast the port to the kernel internal form value */
1257 fprintf(file, "(mach_port_t%s)%s(OutP->%s)", star, at, msgfield);
1258 else
1259 #endif
1260 fprintf(file, "%sOutP->%s", at, msgfield);
1261
1262 }
1263 else if (akCheck(arg->argKind, akbReturnSnd))
1264 fprintf(file, "%sOutP->%s", at, msgfield);
1265
1266 if (NeedClose)
1267 fprintf(file, ")");
1268 }
1269
1270 /*
1271 * Shrunk version of WriteServerCallArg, to implement the RetCode functionality:
1272 * we have received a mig_reply_error_t, therefore we want to call the target
1273 * routine with all 0s except for the error code (and the implicit data).
1274 * We know that we are a SimpleRoutine.
1275 */
1276 static void
1277 WriteConditionalCallArg(FILE *file, argument_t *arg)
1278 {
1279 ipc_type_t *it = arg->argType;
1280 boolean_t NeedClose = FALSE;
1281
1282 if ((it->itInTrans != strNULL) &&
1283 akCheck(arg->argKind, akbSendRcv) &&
1284 !akCheck(arg->argKind, akbVarNeeded)) {
1285 fprintf(file, "%s(", it->itInTrans);
1286 NeedClose = TRUE;
1287 }
1288
1289 if (akCheck(arg->argKind, akbSendRcv)) {
1290 if (akIdent(arg->argKind) == akeRequestPort ||
1291 akCheck(arg->argKind, akbServerImplicit))
1292 fprintf(file, "%s", InArgMsgField(arg, ""));
1293 else if (akIdent(arg->argKind) == akeRetCode)
1294 fprintf(file, "((mig_reply_error_t *)In0P)->RetCode");
1295 else
1296 fprintf(file, "(%s)(0)", it->itTransType);
1297 }
1298
1299 if (NeedClose)
1300 fprintf(file, ")");
1301 }
1302
1303 static void
1304 WriteDestroyArg(FILE *file, argument_t *arg)
1305 {
1306 ipc_type_t *it = arg->argType;
1307
1308 /*
1309 * Deallocate IN/INOUT out-of-line args if specified by "auto" flag.
1310 *
1311 * We also have to deallocate in the cases where the target routine
1312 * is given a itInLine semantic whereas the underlying transmission
1313 * was out-of-line
1314 */
1315 if ((argIsIn(arg) && akCheck(arg->argKind, akbSendKPD|akbReturnKPD) &&
1316 arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR &&
1317 (arg->argFlags & flAuto))
1318 ||
1319 IS_MIG_INLINE_EMUL(it)
1320 ) {
1321 /*
1322 * Deallocate only if out-of-line.
1323 */
1324 argument_t *count = arg->argCount;
1325 ipc_type_t *btype = it->itElement;
1326 int multiplier = btype->itNumber ? btype->itSize / (8 * btype->itNumber) : 0;
1327
1328 if (IsKernelServer) {
1329 fprintf(file, "#if __MigKernelSpecificCode\n");
1330 fprintf(file, "\tvm_map_copy_discard(%s);\n", InArgMsgField(arg, ""));
1331 fprintf(file, "#else\n");
1332 }
1333 fprintf(file, "\tmig_deallocate((vm_offset_t) %s, ", InArgMsgField(arg, ""));
1334 if (it->itVarArray) {
1335 char *suffix = arg->argSuffix;
1336 /*
1337 * temporarily squash any name suffix such as ".address"
1338 * (we'll be adding our own)
1339 */
1340 arg->argSuffix = NULL;
1341 switch (arg->argKPD_Type) {
1342 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
1343 if (multiplier > 1) {
1344 fprintf(file, "%d * ", multiplier);
1345 }
1346 fprintf(file, "%s.count);\n", InArgMsgField(arg, ""));
1347 break;
1348 case MACH_MSG_OOL_DESCRIPTOR:
1349 fprintf(file, "%s.size);\n", InArgMsgField(arg, ""));
1350 break;
1351 default:
1352 if (multiplier > 1) {
1353 fprintf(file, "%d * ", multiplier);
1354 }
1355 fprintf(file, "%s);\n", InArgMsgField(count, ""));
1356 break;
1357 }
1358 arg->argSuffix = suffix;
1359 }
1360 else
1361 fprintf(file, "%d);\n", (it->itNumber * it->itSize + 7) / 8);
1362 if (IsKernelServer) {
1363 fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
1364 }
1365 fprintf(file, "\t%s = (void *) 0;\n", InArgMsgField(arg, ""));
1366 fprintf(file, "\tIn%dP->%s.%s = (mach_msg_size_t) 0;\n", arg->argRequestPos, arg->argMsgField, (RPCPortArray(arg) ? "count" : "size"));
1367 }
1368 else {
1369 if (akCheck(arg->argKind, akbVarNeeded))
1370 fprintf(file, "\t%s(%s);\n", it->itDestructor, arg->argVarName);
1371 else
1372 fprintf(file, "\t%s(%s);\n", it->itDestructor, InArgMsgField(arg, ""));
1373 }
1374 }
1375
1376 static void
1377 WriteDestroyPortArg(FILE *file, argument_t *arg)
1378 {
1379 ipc_type_t *it = arg->argType;
1380
1381 /*
1382 * If a translated port argument occurs in the body of a request
1383 * message, and the message is successfully processed, then the
1384 * port right should be deallocated. However, the called function
1385 * didn't see the port right; it saw the translation. So we have
1386 * to release the port right for it.
1387 *
1388 * The test over it->itInTrans will exclude any complex type
1389 * made out of ports
1390 */
1391 if ((it->itInTrans != strNULL) &&
1392 (it->itOutName == MACH_MSG_TYPE_PORT_SEND)) {
1393 fprintf(file, "\n");
1394 fprintf(file, "\tif (IP_VALID((ipc_port_t)%s))\n", InArgMsgField(arg, ""));
1395 fprintf(file, "\t\tipc_port_release_send((ipc_port_t)%s);\n", InArgMsgField(arg, ""));
1396 }
1397 }
1398
1399 /*
1400 * Check whether WriteDestroyPortArg would generate any code for arg.
1401 */
1402 boolean_t
1403 CheckDestroyPortArg(argument_t *arg)
1404 {
1405 ipc_type_t *it = arg->argType;
1406
1407 if ((it->itInTrans != strNULL) &&
1408 (it->itOutName == MACH_MSG_TYPE_PORT_SEND)) {
1409 return TRUE;
1410 }
1411 return FALSE;
1412 }
1413
1414 static void
1415 WriteServerCall(FILE *file, routine_t *rt, void (*func)(FILE *, argument_t *))
1416 {
1417 argument_t *arg = rt->rtRetCode;
1418 ipc_type_t *it = arg->argType;
1419 boolean_t NeedClose = FALSE;
1420
1421 fprintf(file, "\t");
1422 if (akCheck(arg->argKind, akbVarNeeded))
1423 fprintf(file, "%s = ", arg->argMsgField);
1424 else
1425 fprintf(file, "OutP->%s = ", arg->argMsgField);
1426 if (it->itOutTrans != strNULL) {
1427 fprintf(file, "%s(", it->itOutTrans);
1428 NeedClose = TRUE;
1429 }
1430 fprintf(file, "%s(", rt->rtServerName);
1431 WriteList(file, rt->rtArgs, func, akbServerArg, ", ", "");
1432 if (NeedClose)
1433 fprintf(file, ")");
1434 fprintf(file, ");\n");
1435 }
1436
1437 static void
1438 WriteCheckReturnValue(FILE *file, routine_t *rt)
1439 {
1440 argument_t *arg = rt->rtRetCode;
1441 char string[MAX_STR_LEN];
1442
1443 if (akCheck(arg->argKind, akbVarNeeded))
1444 sprintf(string, "%s", arg->argMsgField);
1445 else
1446 sprintf(string, "OutP->%s", arg->argMsgField);
1447 fprintf(file, "\tif (%s != KERN_SUCCESS) {\n", string);
1448 fprintf(file, "\t\tMIG_RETURN_ERROR(OutP, %s);\n", string);
1449 fprintf(file, "\t}\n");
1450 }
1451
1452 /*
1453 * WriteInitKPD_port, WriteInitKPD_ool, WriteInitKPD_oolport
1454 * initializes the OutP KPD fields (this job cannot be done once
1455 * the target routine has been called, otherwise informations
1456 * would be lost)
1457 */
1458 /*
1459 * argKPD_Init discipline for Port types.
1460 */
1461 static void
1462 WriteInitKPD_port(FILE *file, argument_t *arg)
1463 {
1464 ipc_type_t *it = arg->argType;
1465 char *subindex = "";
1466 boolean_t close = FALSE;
1467 char firststring[MAX_STR_LEN];
1468 char string[MAX_STR_LEN];
1469
1470 if (IS_MULTIPLE_KPD(it)) {
1471 WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE);
1472 (void)sprintf(firststring, "\t*ptr");
1473 (void)sprintf(string, "\tptr->");
1474 subindex = "[i]";
1475 close = TRUE;
1476 }
1477 else {
1478 (void)sprintf(firststring, "OutP->%s", arg->argMsgField);
1479 (void)sprintf(string, "OutP->%s.", arg->argMsgField);
1480 }
1481
1482 fprintf(file, "#if\tUseStaticTemplates\n");
1483 fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
1484 fprintf(file, "#else\t/* UseStaticTemplates */\n");
1485 if (IS_MULTIPLE_KPD(it) && it->itVarArray)
1486 fprintf(file, "\t%sname = MACH_PORT_NULL;\n", string);
1487 if (arg->argPoly == argNULL) {
1488 if (IsKernelServer) {
1489 fprintf(file, "#if __MigKernelSpecificCode\n");
1490 fprintf(file, "\t%sdisposition = %s;\n", string, it->itOutNameStr);
1491 fprintf(file, "#else\n");
1492 }
1493 fprintf(file, "\t%sdisposition = %s;\n", string, it->itInNameStr);
1494 if (IsKernelServer)
1495 fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
1496 }
1497 fprintf(file, "#if !(defined(KERNEL) && defined(__LP64__))\n");
1498 fprintf(file, "\t%spad1 = 0;\n", string);
1499 fprintf(file, "#endif\n");
1500 fprintf(file, "\t%spad2 = 0;\n", string);
1501 fprintf(file, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string);
1502 fprintf(file, "#if defined(KERNEL)\n");
1503 fprintf(file, "\t%spad_end = 0;\n", string);
1504 fprintf(file, "#endif\n");
1505 fprintf(file, "#endif\t/* UseStaticTemplates */\n");
1506 if (close)
1507 fprintf(file, "\t }\n\t}\n");
1508 fprintf(file, "\n");
1509 }
1510
1511 /*
1512 * argKPD_Init discipline for out-of-line types.
1513 */
1514 static void
1515 WriteInitKPD_ool(FILE *file, argument_t *arg)
1516 {
1517 ipc_type_t *it = arg->argType;
1518 char firststring[MAX_STR_LEN];
1519 char string[MAX_STR_LEN];
1520 boolean_t VarArray;
1521 u_int howmany, howbig;
1522
1523 if (IS_MULTIPLE_KPD(it)) {
1524 WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE);
1525 (void)sprintf(firststring, "\t*ptr");
1526 (void)sprintf(string, "\tptr->");
1527 VarArray = it->itElement->itVarArray;
1528 howmany = it->itElement->itNumber;
1529 howbig = it->itElement->itSize;
1530 }
1531 else {
1532 (void)sprintf(firststring, "OutP->%s", arg->argMsgField);
1533 (void)sprintf(string, "OutP->%s.", arg->argMsgField);
1534 VarArray = it->itVarArray;
1535 howmany = it->itNumber;
1536 howbig = it->itSize;
1537 }
1538
1539 fprintf(file, "#if\tUseStaticTemplates\n");
1540 fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
1541 fprintf(file, "#else\t/* UseStaticTemplates */\n");
1542 if (!VarArray)
1543 fprintf(file, "\t%ssize = %d;\n", string, (howmany * howbig + 7)/8);
1544 if (arg->argDeallocate != d_MAYBE)
1545 fprintf(file, "\t%sdeallocate = %s;\n", string, (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE");
1546 fprintf(file, "\t%scopy = %s;\n", string, (arg->argFlags & flPhysicalCopy) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY");
1547 #ifdef ALIGNMENT
1548 fprintf(file, "\t%salignment = MACH_MSG_ALIGN_%d;\n", string, arg->argMsgField, (howbig < 8) ? 1 : howbig / 8);
1549 #endif
1550 fprintf(file, "\t%spad1 = 0;\n", string);
1551 fprintf(file, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string);
1552 fprintf(file, "#if defined(KERNEL) && !defined(__LP64__)\n");
1553 fprintf(file, "\t%spad_end = 0;\n", string);
1554 fprintf(file, "#endif\n");
1555 fprintf(file, "#endif\t/* UseStaticTemplates */\n");
1556
1557 if (IS_MULTIPLE_KPD(it))
1558 fprintf(file, "\t }\n\t}\n");
1559 fprintf(file, "\n");
1560 }
1561
1562 /*
1563 * argKPD_Init discipline for out-of-line Port types.
1564 */
1565 static void
1566 WriteInitKPD_oolport(FILE *file, argument_t *arg)
1567 {
1568 ipc_type_t *it = arg->argType;
1569 boolean_t VarArray;
1570 ipc_type_t *howit;
1571 u_int howmany;
1572 char firststring[MAX_STR_LEN];
1573 char string[MAX_STR_LEN];
1574
1575 if (IS_MULTIPLE_KPD(it)) {
1576 WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE);
1577 (void)sprintf(firststring, "\t*ptr");
1578 (void)sprintf(string, "\tptr->");
1579 VarArray = it->itElement->itVarArray;
1580 howmany = it->itElement->itNumber;
1581 howit = it->itElement;
1582 }
1583 else {
1584 (void)sprintf(firststring, "OutP->%s", arg->argMsgField);
1585 (void)sprintf(string, "OutP->%s.", arg->argMsgField);
1586 VarArray = it->itVarArray;
1587 howmany = it->itNumber;
1588 howit = it;
1589 }
1590
1591 fprintf(file, "#if\tUseStaticTemplates\n");
1592 fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
1593 fprintf(file, "#else\t/* UseStaticTemplates */\n");
1594
1595 if (!VarArray)
1596 fprintf(file, "\t%scount = %d;\n", string, howmany);
1597 if (arg->argPoly == argNULL) {
1598 if (IsKernelServer) {
1599 fprintf(file, "#if\t__MigKernelSpecificCode\n");
1600 fprintf(file, "\t%sdisposition = %s;\n", string, howit->itOutNameStr);
1601 fprintf(file, "#else\n");
1602 }
1603 fprintf(file, "\t%sdisposition = %s;\n", string, howit->itInNameStr);
1604 if (IsKernelServer)
1605 fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
1606 }
1607 if (arg->argDeallocate != d_MAYBE)
1608 fprintf(file, "\t%sdeallocate = %s;\n", string, (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE");
1609 fprintf(file, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string);
1610 fprintf(file, "#endif\t/* UseStaticTemplates */\n");
1611
1612 if (IS_MULTIPLE_KPD(it))
1613 fprintf(file, "\t }\n\t}\n");
1614 fprintf(file, "\n");
1615 }
1616
1617 static void
1618 WriteInitKPDValue(FILE *file, argument_t *arg)
1619 {
1620 (*arg->argKPD_Init)(file, arg);
1621 }
1622
1623 static void
1624 WriteAdjustMsgCircular(FILE *file, argument_t *arg)
1625 {
1626 fprintf(file, "\n");
1627
1628 fprintf(file,"#if\t__MigKernelSpecificCode\n");
1629 if (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
1630 fprintf(file, "\tif (%s == MACH_MSG_TYPE_PORT_RECEIVE)\n", arg->argPoly->argVarName);
1631
1632 /*
1633 * The carried port right can be accessed in OutP->XXXX. Normally
1634 * the server function stuffs it directly there. If it is InOut,
1635 * then it has already been copied into the reply message.
1636 * If the server function deposited it into a variable (perhaps
1637 * because the reply message is variable-sized) then it has already
1638 * been copied into the reply message.
1639 *
1640 * The old MiG does not check for circularity in the case of
1641 * array of ports. So do I ...
1642 */
1643
1644 fprintf(file, "\t if (IP_VALID((ipc_port_t) In0P->Head.msgh_reply_port) &&\n");
1645 fprintf(file, "\t IP_VALID((ipc_port_t) OutP->%s.name) &&\n", arg->argMsgField);
1646 fprintf(file, "\t ipc_port_check_circularity((ipc_port_t) OutP->%s.name, (ipc_port_t) In0P->Head.msgh_reply_port))\n", arg->argMsgField);
1647 fprintf(file, "\t\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_CIRCULAR;\n");
1648 fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
1649 }
1650
1651 /*
1652 * argKPD_Pack discipline for Port types.
1653 */
1654 static void
1655 WriteKPD_port(FILE *file, argument_t *arg)
1656 {
1657 ipc_type_t *it = arg->argType;
1658 char *subindex = "";
1659 char *recast = "";
1660 boolean_t close = FALSE;
1661 char string[MAX_STR_LEN];
1662 ipc_type_t *real_it;
1663
1664 if (akCheck(arg->argKind, akbVarNeeded)) {
1665 if (IS_MULTIPLE_KPD(it)) {
1666 WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE);
1667 (void)sprintf(string, "\tptr->");
1668 subindex = "[i]";
1669 close = TRUE;
1670 real_it = it->itElement;
1671 }
1672 else {
1673 (void)sprintf(string, "OutP->%s.", arg->argMsgField);
1674 real_it = it;
1675 }
1676 #ifdef MIG_KERNEL_PORT_CONVERSIONS
1677 if (IsKernelServer && streql(real_it->itTransType, "ipc_port_t"))
1678 recast = "(mach_port_t)";
1679 #endif
1680
1681 if (it->itOutTrans != strNULL && !close)
1682 fprintf(file, "\t%sname = (mach_port_t)%s(%s);\n", string, it->itOutTrans, arg->argVarName);
1683 else
1684 fprintf(file, "\t%sname = %s%s%s;\n", string, recast, arg->argVarName, subindex);
1685 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd)) {
1686 argument_t *poly = arg->argPoly;
1687
1688 if (akCheck(arg->argPoly->argKind, akbVarNeeded))
1689 fprintf(file, "\t%sdisposition = %s;\n", string, poly->argVarName);
1690 else if (close)
1691 fprintf(file, "\t%sdisposition = OutP->%s;\n", string, poly->argSuffix);
1692 }
1693 if (close)
1694 fprintf(file, "\t }\n\t}\n");
1695 fprintf(file, "\n");
1696 }
1697 else if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd|akbVarNeeded))
1698 fprintf(file, "\tOutP->%s.disposition = %s;\n", arg->argMsgField, arg->argPoly->argVarName);
1699 /*
1700 * If this is a KernelServer, and the reply message contains
1701 * a receive right, we must check for the possibility of a
1702 * port/message circularity. If queueing the reply message
1703 * would cause a circularity, we mark the reply message
1704 * with the circular bit.
1705 */
1706 if (IsKernelServer && !(IS_MULTIPLE_KPD(it)) &&
1707 ((arg->argType->itOutName == MACH_MSG_TYPE_PORT_RECEIVE) ||
1708 (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC)))
1709 WriteAdjustMsgCircular(file, arg);
1710 }
1711
1712 /*
1713 * argKPD_Pack discipline for out-of-line types.
1714 */
1715 static void
1716 WriteKPD_ool(FILE *file, argument_t *arg)
1717 {
1718 ipc_type_t *it = arg->argType;
1719 char string[MAX_STR_LEN];
1720 boolean_t VarArray;
1721 argument_t *count;
1722 u_int howbig;
1723 char *subindex;
1724
1725 if (IS_MULTIPLE_KPD(it)) {
1726 WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE);
1727 (void)sprintf(string, "\tptr->");
1728 VarArray = it->itElement->itVarArray;
1729 count = arg->argSubCount;
1730 howbig = it->itElement->itSize;
1731 subindex = "[i]";
1732 }
1733 else {
1734 (void)sprintf(string, "OutP->%s.", arg->argMsgField);
1735 VarArray = it->itVarArray;
1736 count = arg->argCount;
1737 howbig = it->itSize;
1738 subindex = "";
1739 }
1740
1741 if (akCheck(arg->argKind, akbVarNeeded))
1742 fprintf(file, "\t%saddress = (void *)%s%s;\n", string, arg->argMsgField, subindex);
1743 if (arg->argDealloc != argNULL)
1744 if (akCheck(arg->argDealloc->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it))
1745 fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName);
1746 if (VarArray) {
1747 fprintf(file, "\t%ssize = ", string);
1748 if (akCheck(count->argKind, akbVarNeeded))
1749 fprintf(file, "%s%s", count->argName, subindex);
1750 else
1751 fprintf(file, "OutP->%s%s", count->argMsgField, subindex);
1752
1753 if (count->argMultiplier > 1 || howbig > 8)
1754 fprintf(file, " * %d;\n", count->argMultiplier * howbig / 8);
1755 else
1756 fprintf(file, ";\n");
1757 }
1758
1759 if (IS_MULTIPLE_KPD(it)) {
1760 fprintf(file, "\t }\n");
1761 if (it->itVarArray && !it->itElement->itVarArray) {
1762 fprintf(file, "\t for (i = j; i < %d; ptr++, i++)\n", it->itKPD_Number);
1763 /* since subordinate arrays aren't variable, they are initialized from template:
1764 here we must no-op 'em */
1765 fprintf(file, "\t\tptr->size = 0;\n");
1766 }
1767 fprintf(file, "\t}\n");
1768 }
1769 fprintf(file, "\n");
1770 }
1771
1772 /*
1773 * argKPD_Pack discipline for out-of-line Port types.
1774 */
1775 static void
1776 WriteKPD_oolport(FILE *file, argument_t *arg)
1777 {
1778 ipc_type_t *it = arg->argType;
1779 boolean_t VarArray;
1780 argument_t *count;
1781 char *subindex, string[MAX_STR_LEN];
1782
1783 if (IS_MULTIPLE_KPD(it)) {
1784 WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE);
1785 (void)sprintf(string, "\tptr->");
1786 VarArray = it->itElement->itVarArray;
1787 count = arg->argSubCount;
1788 subindex = "[i]";
1789 }
1790 else {
1791 (void)sprintf(string, "OutP->%s.", arg->argMsgField);
1792 VarArray = it->itVarArray;
1793 count = arg->argCount;
1794 subindex = "";
1795 }
1796
1797 if (akCheck(arg->argKind, akbVarNeeded))
1798 fprintf(file, "\t%saddress = (void *)%s%s;\n", string, arg->argMsgField, subindex);
1799 if (arg->argDealloc != argNULL)
1800 if (akCheck(arg->argDealloc->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it))
1801 fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName);
1802 if (VarArray) {
1803 fprintf(file, "\t%scount = ", string);
1804 if (akCheck(count->argKind, akbVarNeeded))
1805 fprintf(file, "%s%s;\n", count->argName, subindex);
1806 else
1807 fprintf(file, "OutP->%s%s;\n", count->argMsgField, subindex);
1808 }
1809 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd))
1810 if (akCheck(arg->argPoly->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it))
1811 fprintf(file, "\t%sdisposition = %s;\n", string, arg->argPoly->argVarName);
1812 if (IS_MULTIPLE_KPD(it)) {
1813 fprintf(file, "\t }\n");
1814 if (it->itVarArray && !it->itElement->itVarArray) {
1815 fprintf(file, "\t for (i = j; i < %d; ptr++, i++)\n", it->itKPD_Number);
1816 /* since subordinate arrays aren't variable, they are initialized from template:
1817 here we must no-op 'em */
1818 fprintf(file, "\t%scount = 0;\n", string);
1819 }
1820 fprintf(file, "\t}\n");
1821 }
1822 fprintf(file, "\n");
1823 }
1824
1825 /*
1826 * argKPD_TypeCheck discipline for Port types.
1827 */
1828 static void
1829 WriteTCheckKPD_port(FILE *file, argument_t *arg)
1830 {
1831 ipc_type_t *it = arg->argType;
1832 char *tab = "";
1833 char string[MAX_STR_LEN];
1834 boolean_t close = FALSE;
1835
1836 if (IS_MULTIPLE_KPD(it)) {
1837 WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE);
1838 (void)sprintf(string, "ptr->");
1839 tab = "\t";
1840 close = TRUE;
1841 }
1842 else
1843 (void)sprintf(string, "In%dP->%s.", arg->argRequestPos, arg->argMsgField);
1844
1845 fprintf(file, "\t%sif (%stype != MACH_MSG_PORT_DESCRIPTOR", tab, string);
1846 /*
1847 * We can't check disposition on varArray
1848 * (because some of the entries could be empty).
1849 */
1850 if (!it->itVarArray) {
1851 if (arg->argPoly != argNULL) {
1852 switch (it->itOutName) {
1853
1854 case MACH_MSG_TYPE_MOVE_RECEIVE:
1855 fprintf(file, " || \n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_RECEIVE", tab, string);
1856 break;
1857
1858 case MACH_MSG_TYPE_MOVE_SEND_ONCE:
1859 fprintf(file, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND_ONCE", tab, string);
1860 fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND_ONCE)", tab, string);
1861 break;
1862
1863 case MACH_MSG_TYPE_MOVE_SEND:
1864 fprintf(file, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND", tab, string);
1865 fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND", tab, string);
1866 fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_COPY_SEND)", tab, string);
1867 break;
1868 }
1869 }
1870 else {
1871 fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, it->itOutNameStr);
1872 }
1873 }
1874 fprintf(file, ")\n");
1875 fprintf(file, "\t\treturn MIG_TYPE_ERROR;\n");
1876 if (close)
1877 fprintf(file, "\t }\n\t}\n");
1878 }
1879
1880 /*
1881 * argKPD_TypeCheck discipline for out-of-line types.
1882 */
1883 static void
1884 WriteTCheckKPD_ool(FILE *file, argument_t *arg)
1885 {
1886 ipc_type_t *it = arg->argType;
1887 char *tab, string[MAX_STR_LEN];
1888 boolean_t test;
1889 u_int howmany, howbig;
1890
1891 if (IS_MULTIPLE_KPD(it)) {
1892 WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE);
1893 tab = "\t\t\t";
1894 sprintf(string, "ptr->");
1895 howmany = it->itElement->itNumber;
1896 howbig = it->itElement->itSize;
1897 test = !it->itVarArray && !it->itElement->itVarArray;
1898 }
1899 else {
1900 tab = "";
1901 sprintf(string, "In%dP->%s.", arg->argRequestPos, arg->argMsgField);
1902 howmany = it->itNumber;
1903 howbig = it->itSize;
1904 test = !it->itVarArray;
1905 }
1906
1907 fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_DESCRIPTOR", tab, string);
1908 if (test) {
1909 /* if VarArray we may use no-op; if itElement->itVarArray size might change */
1910 fprintf(file, " ||\n\t%s %ssize != %d", tab, string, (howmany * howbig + 7)/8);
1911 }
1912
1913 fprintf(file, ")\n");
1914 fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab);
1915
1916 if (IS_MULTIPLE_KPD(it))
1917 fprintf(file, "\t }\n\t}\n");
1918 }
1919
1920 /*
1921 * argKPD_TypeCheck discipline for out-of-line Port types.
1922 */
1923 static void
1924 WriteTCheckKPD_oolport(FILE *file, argument_t *arg)
1925 {
1926 ipc_type_t *it = arg->argType;
1927 char *tab, string[MAX_STR_LEN];
1928 boolean_t test;
1929 u_int howmany;
1930 char *howstr;
1931
1932 if (IS_MULTIPLE_KPD(it)) {
1933 WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE);
1934 tab = "\t";
1935 sprintf(string, "ptr->");
1936 howmany = it->itElement->itNumber;
1937 test = !it->itVarArray && !it->itElement->itVarArray;
1938 howstr = it->itElement->itOutNameStr;
1939 }
1940 else {
1941 tab = "";
1942 sprintf(string, "In%dP->%s.", arg->argRequestPos, arg->argMsgField);
1943 howmany = it->itNumber;
1944 test = !it->itVarArray;
1945 howstr = it->itOutNameStr;
1946 }
1947
1948 fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_PORTS_DESCRIPTOR", tab, string);
1949 if (test)
1950 /* if VarArray we may use no-op; if itElement->itVarArray size might change */
1951 fprintf(file, " ||\n\t%s %scount != %d", tab, string, howmany);
1952 if (arg->argPoly == argNULL)
1953 fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, howstr);
1954 fprintf(file, ")\n");
1955 fprintf(file, "\t\treturn MIG_TYPE_ERROR;\n");
1956
1957 if (IS_MULTIPLE_KPD(it))
1958 fprintf(file, "\t }\n\t}\n");
1959 }
1960
1961 /*************************************************************
1962 * Writes code to check that the type of each of the arguments
1963 * in the reply message is what is expected. Called by
1964 * WriteRoutine for each in && typed argument in the request message.
1965 *************************************************************/
1966 static void
1967 WriteTypeCheck(FILE *file, argument_t *arg)
1968 {
1969 fprintf(file, "#if\t__MigTypeCheck\n");
1970 (*arg->argKPD_TypeCheck)(file, arg);
1971 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
1972 }
1973
1974 static void
1975 WritePackArgValueNormal(FILE *file, argument_t *arg)
1976 {
1977 ipc_type_t *it = arg->argType;
1978
1979 if (IS_VARIABLE_SIZED_UNTYPED(it) || it->itNoOptArray) {
1980 if (it->itString) {
1981 /*
1982 * Copy variable-size C string with mig_strncpy.
1983 * Save the string length (+ 1 for trailing 0)
1984 * in the argument`s count field.
1985 */
1986 fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
1987 fprintf(file, "\tif (mig_strncpy_zerofill != NULL) {\n");
1988 fprintf(file, "\t\tOutP->%s = (%s) mig_strncpy_zerofill(OutP->%s, %s, %d);\n", arg->argCount->argMsgField, arg->argCount->argType->itTransType, arg->argMsgField, arg->argVarName, it->itNumber);
1989 fprintf(file, "\t} else {\n");
1990 fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");
1991
1992 fprintf(file, "\t\tOutP->%s = (%s) mig_strncpy(OutP->%s, %s, %d);\n", arg->argCount->argMsgField, arg->argCount->argType->itTransType, arg->argMsgField, arg->argVarName, it->itNumber);
1993
1994 fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
1995 fprintf(file, "\t}\n");
1996 fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");
1997
1998 fprintf(file, "\tOutP->%sOffset = 0;\n", arg->argMsgField);
1999 }
2000 else if (it->itNoOptArray)
2001 fprintf(file, "\t(void)memcpy((char *) OutP->%s, (const char *) %s, %d);\n", arg->argMsgField, arg->argVarName, it->itTypeSize);
2002 else {
2003 argument_t *count = arg->argCount;
2004 ipc_type_t *btype = it->itElement;
2005 identifier_t newstr;
2006
2007 /* Note btype->itNumber == count->argMultiplier */
2008
2009 fprintf(file, "\t(void)memcpy((char *) OutP->%s, (const char *) %s, ", arg->argMsgField, arg->argVarName);
2010 if (btype->itTypeSize > 1)
2011 fprintf(file, "%d * ", btype->itTypeSize);
2012 /* count is a akbVarNeeded if arg is akbVarNeeded */
2013 if (akCheck(count->argKind, akbVarNeeded))
2014 newstr = count->argVarName;
2015 else
2016 newstr = (identifier_t)strconcat("OutP->", count->argMsgField);
2017 fprintf(file, "%s);\n", newstr);
2018 }
2019 }
2020 else if (it->itOutTrans != strNULL)
2021 WriteCopyType(file, it, TRUE, "OutP->%s", "/* %s */ %s(%s)", arg->argMsgField, it->itOutTrans, arg->argVarName);
2022 else
2023 WriteCopyType(file, it, TRUE, "OutP->%s", "/* %s */ %s", arg->argMsgField, arg->argVarName);
2024
2025 if (arg->argPadName != NULL && it->itPadSize != 0) {
2026 fprintf(file, "\t for (int i = 0; i < %d; i++)\n", it->itPadSize);
2027 fprintf(file, "\t\t OutP->%s[i] = 0;\n", arg->argPadName);
2028 }
2029 }
2030
2031 static void
2032 WritePackArgValueVariable(FILE *file, argument_t *arg)
2033 {
2034 ipc_type_t *it = arg->argType;
2035
2036 /*
2037 * only itString are treated here so far
2038 */
2039 if (it->itString) {
2040 /*
2041 * Emit logic to call strlen to calculate the size of the argument, and ensure that it fits within the 32-bit result field
2042 * in the Reply, when targeting a 64-bit architecture. If a 32-bit architecture is the target, we emit code to just call
2043 * strlen() directly (since it'll return a 32-bit value that is guaranteed to fit).
2044 */
2045 fputs("#ifdef __LP64__\n", file);
2046 fprintf(file, "\t{\n"
2047 "\t\t" "size_t strLength = strlen(OutP->%s) + 1;\n", arg->argMsgField);
2048 fputs( "\t\t" "if (strLength > 0xffffffff)\n"
2049 "\t\t\t" "MIG_RETURN_ERROR(OutP, MIG_BAD_ARGUMENTS);\n", file);
2050 fprintf(file, "\t\t" "OutP->%s = (mach_msg_type_number_t) strLength;\n"
2051 "\t}\n", arg->argCount->argMsgField);
2052 fputs("#else\n", file);
2053 fprintf(file, "\tOutP->%s = (mach_msg_type_number_t) strlen(OutP->%s) + 1;\n", arg->argCount->argMsgField, arg->argMsgField);
2054 fputs("#endif /* __LP64__ */\n", file);
2055
2056 }
2057 }
2058
2059 static void
2060 WriteCopyArgValue(FILE *file, argument_t *arg)
2061 {
2062 fprintf(file, "\n");
2063 WriteCopyType(file, arg->argType, TRUE, "/* %d */ OutP->%s", "In%dP->%s", arg->argRequestPos, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField);
2064 }
2065
2066 static void
2067 WriteInitArgValue(FILE *file, argument_t *arg)
2068 {
2069 fprintf(file, "\n");
2070 fprintf(file, "\tOutP->%s = %s;\n\n", arg->argMsgField, arg->argVarName);
2071 }
2072
2073 /*
2074 * Calculate the size of a variable-length message field.
2075 */
2076 static void
2077 WriteArgSize(FILE *file, argument_t *arg)
2078 {
2079 ipc_type_t *ptype = arg->argType;
2080 int bsize = ptype->itElement->itTypeSize;
2081 argument_t *count = arg->argCount;
2082
2083 /* If the base type size of the data field isn`t a multiple of 4,
2084 we have to round up. */
2085 if (bsize % itWordAlign != 0)
2086 fprintf(file, "_WALIGN_");
2087
2088 /* Here, we generate ((value + %d) & ~%d). We have to put two (( at the
2089 * the beginning.
2090 */
2091 fprintf(file, "((");
2092 if (bsize > 1)
2093 fprintf(file, "%d * ", bsize);
2094 if (ptype->itString || !akCheck(count->argKind, akbVarNeeded))
2095 /* get count from descriptor in message */
2096 fprintf(file, "OutP->%s", count->argMsgField);
2097 else
2098 /* get count from argument */
2099 fprintf(file, "%s", count->argVarName);
2100
2101 /*
2102 * If the base type size is not a multiple of sizeof(natural_t),
2103 * we have to round up.
2104 */
2105 if (bsize % sizeof(natural_t) != 0)
2106 fprintf(file, " + %d) & ~%d)", (int)sizeof(natural_t)-1, (int)sizeof(natural_t)-1);
2107 else
2108 fprintf(file, "))");
2109 }
2110
2111 /*
2112 * Adjust message size and advance reply pointer.
2113 * Called after packing a variable-length argument that
2114 * has more arguments following.
2115 */
2116 static void
2117 WriteAdjustMsgSize(FILE *file, argument_t *arg)
2118 {
2119 routine_t *rt = arg->argRoutine;
2120 ipc_type_t *ptype = arg->argType;
2121
2122 /* There are more Out arguments. We need to adjust msgh_size
2123 and advance OutP, so we save the size of the current field
2124 in msgh_size_delta. */
2125
2126 fprintf(file, "\tmsgh_size_delta = ");
2127 WriteArgSize(file, arg);
2128 fprintf(file, ";\n");
2129
2130 if (rt->rtNumReplyVar == 1) {
2131 /* We can still address the message header directly. Fill
2132 in the size field. */
2133
2134 fprintf(file, "\tOutP->Head.msgh_size = ");
2135 rtMinReplySize(file, rt, "Reply");
2136 fprintf(file, " + msgh_size_delta;\n");
2137 }
2138 else if (arg->argReplyPos == 0) {
2139 /* First variable-length argument. The previous msgh_size value
2140 is the minimum reply size. */
2141
2142 fprintf(file, "\tmsgh_size = ");
2143 rtMinReplySize(file, rt, "Reply");
2144 fprintf(file, " + msgh_size_delta;\n");
2145 }
2146 else
2147 fprintf(file, "\tmsgh_size += msgh_size_delta;\n");
2148
2149 fprintf(file, "\tOutP = (Reply *) ((pointer_t) OutP + msgh_size_delta - %d);\n", ptype->itTypeSize + ptype->itPadSize);
2150 }
2151
2152 /*
2153 * Calculate the size of the message. Called after the
2154 * last argument has been packed.
2155 */
2156 static void
2157 WriteFinishMsgSize(FILE *file, argument_t *arg)
2158 {
2159 /* No more Out arguments. If this is the only variable Out
2160 argument, we can assign to msgh_size directly. */
2161
2162 if (arg->argReplyPos == 0) {
2163 fprintf(file, "\tOutP->Head.msgh_size = ");
2164 rtMinReplySize(file, arg->argRoutine, "Reply");
2165 fprintf(file, " + (");
2166 WriteArgSize(file, arg);
2167 fprintf(file, ");\n");
2168 }
2169 else {
2170 fprintf(file, "\tmsgh_size += ");
2171 WriteArgSize(file, arg);
2172 fprintf(file, ";\n");
2173 }
2174 }
2175
2176 /*
2177 * Handle reply arguments - fill in message types and copy arguments
2178 * that need to be copied.
2179 */
2180 static void
2181 WriteReplyArgs(FILE *file, routine_t *rt)
2182 {
2183 argument_t *arg;
2184 argument_t *lastVarArg;
2185
2186 /*
2187 * 1. The Kernel Processed Data
2188 */
2189 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
2190 if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnKPD))
2191 (*arg->argKPD_Pack)(file, arg);
2192 /*
2193 * 2. The Data Stream
2194 */
2195 lastVarArg = argNULL;
2196 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
2197 /*
2198 * Adjust message size and advance message pointer if
2199 * the last request argument was variable-length and the
2200 * request position will change.
2201 */
2202 if (lastVarArg != argNULL &&
2203 lastVarArg->argReplyPos < arg->argReplyPos) {
2204 WriteAdjustMsgSize(file, lastVarArg);
2205 lastVarArg = argNULL;
2206 }
2207
2208 if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVarNeeded))
2209 WritePackArgValueNormal(file, arg);
2210 else if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVariable))
2211 WritePackArgValueVariable(file, arg);
2212
2213 if (akCheck(arg->argKind, akbReplyCopy))
2214 WriteCopyArgValue(file, arg);
2215 if (akCheck(arg->argKind, akbReplyInit))
2216 WriteInitArgValue(file, arg);
2217 /*
2218 * Remember whether this was variable-length.
2219 */
2220 if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVariable))
2221 lastVarArg = arg;
2222 }
2223 /*
2224 * Finish the message size.
2225 */
2226 if (lastVarArg != argNULL)
2227 WriteFinishMsgSize(file, lastVarArg);
2228 }
2229
2230 static void
2231 WriteFieldDecl(FILE *file, argument_t *arg)
2232 {
2233 if (akCheck(arg->argKind, akbSendKPD) ||
2234 akCheck(arg->argKind, akbReturnKPD))
2235 WriteFieldDeclPrim(file, arg, FetchKPDType);
2236 else
2237 WriteFieldDeclPrim(file, arg, FetchServerType);
2238 }
2239
2240 static void
2241 InitKPD_Disciplines(argument_t *args)
2242 {
2243 argument_t *arg;
2244 extern void KPD_noop(FILE *file, argument_t *arg);
2245 extern void KPD_error(FILE *file, argument_t *arg);
2246 extern void WriteTemplateKPD_port(FILE *file, argument_t *arg, boolean_t in);
2247 extern void WriteTemplateKPD_ool(FILE *file, argument_t *arg, boolean_t in);
2248 extern void WriteTemplateKPD_oolport(FILE *file, argument_t *arg, boolean_t in);
2249
2250 /*
2251 * WriteInitKPD_port, WriteKPD_port, WriteExtractKPD_port,
2252 * WriteInitKPD_ool, WriteKPD_ool, WriteExtractKPD_ool,
2253 * WriteInitKPD_oolport, WriteKPD_oolport, WriteExtractKPD_oolport
2254 * are local to this module (which is the reason why this initialization
2255 * takes place here rather than in utils.c).
2256 * Common routines for user and server will be established SOON, and
2257 * all of them (including the initialization) will be transfert to
2258 * utils.c
2259 * All the KPD disciplines are defaulted to be KPD_error().
2260 * Note that akbSendKPD and akbReturnKPd are not exclusive,
2261 * because of inout type of parameters.
2262 */
2263 for (arg = args; arg != argNULL; arg = arg->argNext)
2264 if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD))
2265 switch (arg->argKPD_Type) {
2266
2267 case MACH_MSG_PORT_DESCRIPTOR:
2268 if akCheck(arg->argKind, akbSendKPD) {
2269 arg->argKPD_Extract =
2270 (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_port : WriteExtractArgValue;
2271 arg->argKPD_TypeCheck = WriteTCheckKPD_port;
2272 }
2273 if akCheck(arg->argKind, akbReturnKPD) {
2274 arg->argKPD_Template = WriteTemplateKPD_port;
2275 arg->argKPD_Init = WriteInitKPD_port;
2276 arg->argKPD_Pack = WriteKPD_port;
2277 }
2278 break;
2279
2280 case MACH_MSG_OOL_DESCRIPTOR:
2281 if akCheck(arg->argKind, akbSendKPD) {
2282 arg->argKPD_Extract =
2283 (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_ool : WriteExtractArgValue;
2284 arg->argKPD_TypeCheck = WriteTCheckKPD_ool;
2285 }
2286 if akCheck(arg->argKind, akbReturnKPD) {
2287 arg->argKPD_Template = WriteTemplateKPD_ool;
2288 arg->argKPD_Init = WriteInitKPD_ool;
2289 arg->argKPD_Pack = WriteKPD_ool;
2290 }
2291 break;
2292
2293 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
2294 if akCheck(arg->argKind, akbSendKPD) {
2295 arg->argKPD_Extract =
2296 (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_oolport : WriteExtractArgValue;
2297 arg->argKPD_TypeCheck = WriteTCheckKPD_oolport;
2298 }
2299 if akCheck(arg->argKind, akbReturnKPD) {
2300 arg->argKPD_Template = WriteTemplateKPD_oolport;
2301 arg->argKPD_Init = WriteInitKPD_oolport;
2302 arg->argKPD_Pack = WriteKPD_oolport;
2303 }
2304 break;
2305
2306 default:
2307 printf("MiG internal error: type of kernel processed data unknown\n");
2308 exit(1);
2309 } /* end of switch */
2310 }
2311
2312 static void WriteStringTerminatorCheck(FILE *file, routine_t *rt)
2313 {
2314 // generate code to verify that the length of a C string is not greater than the size of the
2315 // buffer in which it is stored.
2316 argument_t *argPtr;
2317 int msg_limit_calculated = FALSE;
2318 int found_string_argument = FALSE;
2319 int variable_length_args_present = (rt->rtMaxRequestPos > 0);
2320
2321 // scan through arguments to see if there are any strings
2322 for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) {
2323 if ((argPtr->argKind & akbRequest) && argPtr->argType->itString) {
2324 found_string_argument = TRUE;
2325 break;
2326 }
2327 }
2328
2329 if (found_string_argument) {
2330 // create a new scope, for local variables
2331 fputs("#if __MigTypeCheck\n" "\t" "{" "\n", file);
2332
2333 for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) {
2334 if ((argPtr->argKind & akbRequest) && argPtr->argType->itString) {
2335 //fprintf(stderr, "### found itString: variable name = %s, max length = %d\n", argPtr->argName, argPtr->argType->itNumber);
2336
2337 if (!msg_limit_calculated) {
2338 msg_limit_calculated = TRUE; // only need to do this once
2339 fputs("\t\t" "char * msg_limit = ((char *) In0P) + In0P->Head.msgh_size;\n", file);
2340 if (IsKernelServer) {
2341 fputs("#if __MigKernelSpecificCode\n", file);
2342 fputs("\t\t" "size_t strnlen_limit;" "\n", file);
2343 fputs("#else\n", file);
2344 }
2345 fputs("\t\t" "size_t memchr_limit;" "\n", file);
2346 if (IsKernelServer) {
2347 fputs("#endif /* __MigKernelSpecificCode */" "\n", file);
2348 }
2349 fputc('\n', file);
2350 }
2351
2352 // I would really prefer to use strnlen() here, to ensure that the byte scanning logic does not extend beyond
2353 // the end of the buffer, but it's not necessarily guaranteed to be available. Instead, I'll use memchr(),
2354 // and let it look for the terminating null byte.
2355 // (later...)
2356 // It turns out that the kernel does not have memchr() available, but strnlen() IS available, so we'll just
2357 // have to emit some conditional code to use the appropriate runtime environment scanning function.
2358 //
2359 if (IsKernelServer) {
2360 fputs("#if __MigKernelSpecificCode\n", file);
2361 fputs("\t\t" "strnlen_limit = min((msg_limit - ", file);
2362 // If there are variable-length arguments within the message, the proper (adjusted)
2363 // pointers must be used to access those strings
2364 fprintf(file, "In%dP->%s), %d);" "\n", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName, argPtr->argType->itNumber);
2365 fputs("\t\t" "if (", file);
2366 fprintf(file, "( strnlen(In%dP->%s, strnlen_limit) >= %d + 1 )", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName, argPtr->argType->itNumber);
2367 fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file);
2368 fputs("#else\n", file);
2369 }
2370 // If there are variable-length arguments within the message, the proper (adjusted)
2371 // pointers must be used to access those strings
2372 fprintf(file, "\t\t" "memchr_limit = min((msg_limit - In%dP->%s), %d);" "\n", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName, argPtr->argType->itNumber);
2373 fputs("\t\t" "if (", file);
2374 fprintf(file, "( memchr(In%dP->%s, '\\0', memchr_limit) == NULL )", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName);
2375 fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file);
2376 if (IsKernelServer) {
2377 fputs("#endif /* __MigKernelSpecificCode */" "\n", file);
2378 }
2379 }
2380 }
2381 fputs("\t" "}" "\n" "#endif" "\t" "/* __MigTypeCheck */" "\n\n", file); // terminate new scope
2382 }
2383
2384 return;
2385 }
2386
2387 static void
2388 WriteOOLSizeCheck(FILE *file, routine_t *rt)
2389 {
2390 /* Emit code to validate the actual size of ool data vs. the reported size */
2391
2392 argument_t *argPtr;
2393 boolean_t openedTypeCheckConditional = FALSE;
2394
2395 // scan through arguments to see if there are any ool data blocks
2396 for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) {
2397 if (akCheck(argPtr->argKind, akbSendKPD)) {
2398 ipc_type_t *it = argPtr->argType;
2399 boolean_t multiple_kpd = IS_MULTIPLE_KPD(it);
2400 char string[MAX_STR_LEN];
2401 boolean_t test;
2402 argument_t *argCountPtr;
2403 char *tab;
2404
2405 if (argPtr->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {
2406
2407 if (multiple_kpd) {
2408 if ( !openedTypeCheckConditional ) {
2409 openedTypeCheckConditional = TRUE;
2410 fputs("#if __MigTypeCheck\n", file);
2411 }
2412 WriteKPD_Iterator(file, TRUE, FALSE, argPtr, TRUE);
2413 tab = "\t";
2414 sprintf(string, "ptr->");
2415 test = !it->itVarArray && !it->itElement->itVarArray;
2416 it = it->itElement; // point to element descriptor, so size calculation is correct
2417 argCountPtr = argPtr->argSubCount;
2418 } else {
2419 tab = "";
2420 sprintf(string, "In%dP->%s.", argPtr->argRequestPos, argPtr->argMsgField);
2421 test = !it->itVarArray;
2422 argCountPtr = argPtr->argCount;
2423 }
2424
2425 if (!test) {
2426 int multiplier = (argCountPtr->argMultiplier > 1 || it->itSize > 8) ? argCountPtr->argMultiplier * it->itSize / 8 : 1;
2427 if ( !openedTypeCheckConditional ) {
2428 openedTypeCheckConditional = TRUE;
2429 fputs("#if __MigTypeCheck\n", file);
2430 }
2431
2432 fprintf(file, "\t%s" "if (%ssize ", tab, string);
2433 if (multiplier > 1)
2434 fprintf(file, "/ %d ", multiplier);
2435 fprintf(file,"!= In%dP->%s%s", argCountPtr->argRequestPos, argCountPtr->argVarName, multiple_kpd ? "[i]" : "");
2436 if (it->itOOL_Number) {
2437 fprintf(file," || In%dP->%s%s > %d", argCountPtr->argRequestPos,
2438 argCountPtr->argVarName, multiple_kpd ? "[i]" : "", it->itOOL_Number);
2439 }
2440
2441 fprintf(file,")\n");
2442 fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab);
2443 }
2444
2445 if (multiple_kpd)
2446 fprintf(file, "\t }\n\t}\n");
2447 } else if (argPtr->argKPD_Type == MACH_MSG_OOL_PORTS_DESCRIPTOR) {
2448 if (multiple_kpd) {
2449 if ( !openedTypeCheckConditional ) {
2450 openedTypeCheckConditional = TRUE;
2451 fputs("#if __MigTypeCheck\n", file);
2452 }
2453 WriteKPD_Iterator(file, TRUE, FALSE, argPtr, TRUE);
2454 tab = "\t";
2455 sprintf(string, "ptr->");
2456 test = !it->itVarArray && !it->itElement->itVarArray;
2457 it = it->itElement; // point to element descriptor, so size calculation is correct
2458 argCountPtr = argPtr->argSubCount;
2459 } else {
2460 tab = "";
2461 sprintf(string, "In%dP->%s.", argPtr->argRequestPos, argPtr->argMsgField);
2462 test = !it->itVarArray;
2463 argCountPtr = argPtr->argCount;
2464 }
2465
2466 if (!test) {
2467 if ( !openedTypeCheckConditional ) {
2468 openedTypeCheckConditional = TRUE;
2469 fputs("#if __MigTypeCheck\n", file);
2470 }
2471
2472 fprintf(file, "\t%s" "if (%scount ", tab, string);
2473 fprintf(file,"!= In%dP->%s%s", argCountPtr->argRequestPos, argCountPtr->argVarName, multiple_kpd ? "[i]" : "");
2474 if (it->itOOL_Number) {
2475 fprintf(file," || In%dP->%s%s > %d", argCountPtr->argRequestPos,
2476 argCountPtr->argVarName, multiple_kpd ? "[i]" : "", it->itOOL_Number);
2477 }
2478 fprintf(file,")\n");
2479 fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab);
2480 }
2481
2482 if (multiple_kpd)
2483 fprintf(file, "\t }\n\t}\n");
2484 }
2485 }
2486 }
2487
2488 if ( openedTypeCheckConditional )
2489 fputs("#endif" "\t" "/* __MigTypeCheck */" "\n\n", file);
2490 }
2491
2492
2493 void
2494 WriteCheckRequest(FILE *file, routine_t *rt)
2495 {
2496 int i;
2497
2498 /* initialize the disciplines for the handling of KPDs */
2499 InitKPD_Disciplines(rt->rtArgs);
2500
2501 fprintf(file, "\n");
2502 fprintf(file, "#if ( __MigTypeCheck ");
2503 if (CheckNDR)
2504 fprintf(file, "|| __NDR_convert__ ");
2505 fprintf(file, ")\n");
2506 fprintf(file, "#if __MIG_check__Request__%s_subsystem__\n", SubsystemName);
2507 fprintf(file, "#if !defined(__MIG_check__Request__%s_t__defined)\n", rt->rtName);
2508 fprintf(file, "#define __MIG_check__Request__%s_t__defined\n", rt->rtName);
2509 if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbRequest)) {
2510 WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgDecl, akbSendNdr, "", "");
2511 WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgDecl, akbSendNdr, "", "");
2512 WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgDecl, akbSendNdr, "", "");
2513 }
2514 fprintf(file, "\n");
2515 fprintf(file, "mig_internal kern_return_t __MIG_check__Request__%s_t(__attribute__((__unused__)) __Request__%s_t *In0P", rt->rtName, rt->rtName);
2516 for (i = 1; i <= rt->rtMaxRequestPos; i++)
2517 fprintf(file, ", __attribute__((__unused__)) __Request__%s_t **In%dPP", rt->rtName, i);
2518 fprintf(file, ")\n{\n");
2519
2520 fprintf(file, "\n\ttypedef __Request__%s_t __Request;\n", rt->rtName);
2521 for (i = 1; i <= rt->rtMaxRequestPos; i++)
2522 fprintf(file, "\t__Request *In%dP;\n", i);
2523 if (rt->rtNumRequestVar > 0) {
2524 fprintf(file, "#if\t__MigTypeCheck\n");
2525 fprintf(file, "\tunsigned int msgh_size;\n");
2526 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
2527 }
2528 if (rt->rtMaxRequestPos > 0)
2529 fprintf(file, "\tunsigned int msgh_size_delta;\n");
2530 if (rt->rtNumRequestVar > 0 || rt->rtMaxRequestPos > 0)
2531 fprintf(file, "\n");
2532
2533 WriteCheckHead(file, rt);
2534
2535 WriteList(file, rt->rtArgs, WriteTypeCheck, akbSendKPD, "\n", "\n");
2536
2537 {
2538 argument_t *arg, *lastVarArg;
2539
2540 lastVarArg = argNULL;
2541 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
2542 if (lastVarArg != argNULL &&
2543 lastVarArg->argRequestPos < arg->argRequestPos) {
2544 WriteAdjustRequestMsgPtr(file, lastVarArg);
2545 lastVarArg = argNULL;
2546 }
2547 if (akCheckAll(arg->argKind, akbSendRcv|akbSendBody)) {
2548 if (akCheck(arg->argKind, akbVariable)) {
2549 WriteCheckMsgSize(file, arg);
2550 lastVarArg = arg;
2551 }
2552 }
2553 }
2554 }
2555
2556 if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbRequest)) {
2557 fprintf(file, "#if\t");
2558 WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgCond, akbSendNdr, " || \\\n\t", "\n");
2559 fprintf(file, "\tif (In0P->NDR.int_rep != NDR_record.int_rep) {\n");
2560 WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgUse, akbSendNdr, "", "");
2561 fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__int_rep...) */\n\n");
2562
2563 WriteOOLSizeCheck(file, rt);
2564
2565 fprintf(file, "#if\t");
2566 WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgCond, akbSendNdr, " || \\\n\t", "\n");
2567 fprintf(file, "\tif (In0P->NDR.char_rep != NDR_record.char_rep) {\n");
2568 WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgUse, akbSendNdr, "", "");
2569 fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__char_rep...) */\n\n");
2570
2571 fprintf(file, "#if\t");
2572 WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgCond, akbSendNdr, " || \\\n\t", "\n");
2573 fprintf(file, "\tif (In0P->NDR.float_rep != NDR_record.float_rep) {\n");
2574 WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgUse, akbSendNdr, "", "");
2575 fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__float_rep...) */\n\n");
2576 } else {
2577 WriteOOLSizeCheck(file, rt);
2578 }
2579
2580 WriteStringTerminatorCheck(file, rt);
2581
2582 fprintf(file, "\treturn MACH_MSG_SUCCESS;\n");
2583 fprintf(file, "}\n");
2584 fprintf(file, "#endif /* !defined(__MIG_check__Request__%s_t__defined) */\n", rt->rtName);
2585 fprintf(file, "#endif /* __MIG_check__Request__%s_subsystem__ */\n", SubsystemName);
2586 fprintf(file, "#endif /* ( __MigTypeCheck ");
2587 if (CheckNDR)
2588 fprintf(file, "|| __NDR_convert__ ");
2589 fprintf(file, ") */\n");
2590 fprintf(file, "\n");
2591 }
2592
2593 void
2594 WriteCheckRequestCall(FILE *file, routine_t *rt)
2595 {
2596 int i;
2597
2598 fprintf(file, "\n");
2599 fprintf(file, "#if\tdefined(__MIG_check__Request__%s_t__defined)\n", rt->rtName);
2600 fprintf(file, "\tcheck_result = __MIG_check__Request__%s_t((__Request *)In0P", rt->rtName);
2601 for (i = 1; i <= rt->rtMaxRequestPos; i++)
2602 fprintf(file, ", (__Request **)&In%dP", i);
2603 fprintf(file, ");\n");
2604 fprintf(file, "\tif (check_result != MACH_MSG_SUCCESS)\n");
2605 fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, check_result); }\n");
2606 fprintf(file, "#endif\t/* defined(__MIG_check__Request__%s_t__defined) */\n", rt->rtName);
2607 fprintf(file, "\n");
2608 }
2609
2610 void
2611 WriteCheckRequests(FILE *file, statement_t *stats)
2612 {
2613 statement_t *stat;
2614
2615 for (stat = stats; stat != stNULL; stat = stat->stNext)
2616 if (stat->stKind == skRoutine)
2617 WriteCheckRequest(file, stat->stRoutine);
2618 }
2619
2620 static void
2621 WriteRoutine(FILE *file, routine_t *rt)
2622 {
2623 /* Declare the server work function: */
2624 if (ServerHeaderFileName == strNULL)
2625 WriteServerRoutine(file, rt);
2626
2627 fprintf(file, "\n");
2628
2629 fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
2630 fprintf(file, "mig_internal novalue _X%s\n", rt->rtName);
2631 if (BeAnsiC) {
2632 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
2633 }
2634 else {
2635 fprintf(file, "#if\t%s\n", NewCDecl);
2636 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
2637 fprintf(file, "#else\n");
2638 fprintf(file, "\t(InHeadP, OutHeadP)\n");
2639 fprintf(file, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n");
2640 fprintf(file, "#endif\t/* %s */\n", NewCDecl);
2641 }
2642
2643 fprintf(file, "{\n");
2644 WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request", rt->rtSimpleRequest, TRUE, rt->rtServerImpl, FALSE);
2645 fprintf(file, "\ttypedef __Request__%s_t __Request;\n", rt->rtName);
2646 fprintf(file, "\ttypedef __Reply__%s_t Reply __attribute__((unused));\n\n", rt->rtName);
2647
2648 /*
2649 * Define a Minimal Reply structure to be used in case of errors
2650 */
2651 fprintf(file, "\t/*\n");
2652 fprintf(file, "\t * typedef struct {\n");
2653 fprintf(file, "\t * \tmach_msg_header_t Head;\n");
2654 fprintf(file, "\t * \tNDR_record_t NDR;\n");
2655 fprintf(file, "\t * \tkern_return_t RetCode;\n");
2656 fprintf(file, "\t * } mig_reply_error_t;\n");
2657 fprintf(file, "\t */\n");
2658 fprintf(file, "\n");
2659
2660 WriteVarDecls(file, rt);
2661
2662 if (IsKernelServer) {
2663 fprintf(file, "#if\t__MigKernelSpecificCode\n");
2664 WriteList(file, rt->rtArgs, WriteTemplateDeclOut, akbReturnKPD, "\n", "\n");
2665 fprintf(file, "#else\n");
2666 }
2667 WriteList(file, rt->rtArgs, WriteTemplateDeclIn, akbReturnKPD, "\n", "\n");
2668 if (IsKernelServer) {
2669 fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
2670 }
2671 WriteRetCode(file, rt->rtRetCode);
2672 WriteList(file, rt->rtArgs, WriteLocalVarDecl, akbVarNeeded | akbServerArg, ";\n", ";\n\n");
2673 WriteApplMacro(file, "Rcv", "Declare", rt);
2674 WriteApplMacro(file, "Rcv", "Before", rt);
2675 if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
2676 WriteRetCArgCheckError(file, rt);
2677 if (rt->rtServerImpl)
2678 WriteCheckTrailerHead(file, rt, FALSE);
2679 WriteServerCall(file, rt, WriteConditionalCallArg);
2680 WriteRetCArgFinishError(file, rt);
2681 }
2682
2683 WriteCheckRequestCall(file, rt);
2684 WriteCheckRequestTrailerArgs(file, rt);
2685
2686 /*
2687 * Initialize the KPD records in the Reply structure with the
2688 * templates. We do this beforehand because the call to the procedure
2689 * will overwrite some of the values (after the call it would be impossible
2690 * to initialize the KPD records from the static Templates, because we
2691 * would lose data).
2692 */
2693 WriteList(file, rt->rtArgs, WriteInitKPDValue, akbReturnKPD, "\n", "\n");
2694
2695 WriteList(file, rt->rtArgs, WriteExtractArg, akbNone, "", "");
2696
2697 if (UseEventLogger)
2698 WriteLogMsg(file, rt, LOG_SERVER, LOG_REQUEST);
2699
2700 WriteServerCall(file, rt, WriteServerCallArg);
2701
2702 WriteReverseList(file, rt->rtArgs, WriteDestroyArg, akbDestroy, "", "");
2703
2704 /*
2705 * For one-way routines, it doesn`t make sense to check the return
2706 * code, because we return immediately afterwards. However,
2707 * kernel servers may want to deallocate port arguments - and the
2708 * deallocation must not be done if the return code is not KERN_SUCCESS.
2709 */
2710 if (rt->rtOneWay || rt->rtNoReplyArgs) {
2711 if (IsKernelServer) {
2712 fprintf(file,"#if\t__MigKernelSpecificCode\n");
2713 if (rtCheckMaskFunction(rt->rtArgs, akbSendKPD, CheckDestroyPortArg)) {
2714 WriteCheckReturnValue(file, rt);
2715 }
2716 WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg, akbSendKPD, "", "");
2717 fprintf(file,"#endif /* __MigKernelSpecificCode */\n");
2718 }
2719 /* although we have an empty reply, we still have to make sure that
2720 some fields such as NDR get properly initialized */
2721 if (!rt->rtOneWay)
2722 WriteList(file, rt->rtArgs, WriteInitArgValue, akbReplyInit, "\n", "\n");
2723 }
2724 else {
2725 WriteCheckReturnValue(file, rt);
2726
2727 if (IsKernelServer) {
2728 fprintf(file,"#if\t__MigKernelSpecificCode\n");
2729 WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg, akbSendKPD, "", "");
2730 fprintf(file,"#endif /* __MigKernelSpecificCode */\n");
2731 }
2732 WriteReplyArgs(file, rt);
2733 WriteReplyInit(file, rt);
2734 if (!rt->rtSimpleReply)
2735 fprintf(file, "\tOutP->msgh_body.msgh_descriptor_count = %d;\n", rt->rtReplyKPDs);
2736 }
2737 if (UseEventLogger)
2738 WriteLogMsg(file, rt, LOG_SERVER, LOG_REPLY);
2739
2740 WriteApplMacro(file, "Rcv", "After", rt);
2741 fprintf(file, "}\n");
2742 }
2743
2744 void
2745 WriteServer(FILE *file, statement_t *stats)
2746 {
2747 statement_t *stat;
2748
2749 WriteProlog(file, stats);
2750 if (BeAnsiC)
2751 WriteForwardDeclarations(file, stats);
2752 for (stat = stats; stat != stNULL; stat = stat->stNext)
2753 switch (stat->stKind) {
2754
2755 case skRoutine:
2756 WriteCheckRequest(file, stat->stRoutine);
2757 WriteRoutine(file, stat->stRoutine);
2758 break;
2759
2760 case skIImport:
2761 case skImport:
2762 case skSImport:
2763 case skDImport:
2764 case skUImport:
2765 break;
2766
2767 default:
2768 fatal("WriteServer(): bad statement_kind_t (%d)",
2769 (int) stat->stKind);
2770 }
2771 WriteDispatcher(file, stats);
2772 }