2 * Copyright (c) 1999-2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 * Mach Operating System
25 * Copyright (c) 1991,1990 Carnegie Mellon University
26 * All Rights Reserved.
28 * Permission to use, copy, modify and distribute this software and its
29 * documentation is hereby granted, provided that both the copyright
30 * notice and this permission notice appear in all copies of the
31 * software, derivative works or modified versions, and any portions
32 * thereof, and that both notices appear in supporting documentation.
34 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
35 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
36 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
38 * Carnegie Mellon requests users of this software to return to
40 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
41 * School of Computer Science
42 * Carnegie Mellon University
43 * Pittsburgh PA 15213-3890
45 * any improvements or extensions that they make and grant Carnegie the
46 * rights to redistribute these changes.
52 #include <mach/message.h>
58 #ifndef USE_IMMEDIATE_SEND_TIMEOUT
59 #define USE_IMMEDIATE_SEND_TIMEOUT 0
62 char *MessAllocRoutine
= "mig_user_allocate";
63 char *MessFreeRoutine
= "mig_user_deallocate";
65 char stRetCode
[] = "ReturnValue";
66 char stRetNone
[] = "";
68 void WriteLogDefines(FILE *file
, string_t who
);
69 void WriteIdentificationString(FILE *file
);
72 WriteKPD_Iterator(FILE *file
, boolean_t in
, boolean_t overwrite
, boolean_t varying
, argument_t
*arg
, boolean_t bracket
)
74 ipc_type_t
*it
= arg
->argType
;
75 char string
[MAX_STR_LEN
];
77 fprintf(file
, "\t{\n");
78 fprintf(file
, "\t %s\t*ptr;\n", it
->itKPDType
);
79 fprintf(file
, "\t int\ti");
82 fprintf(file
, ";\n\n");
85 sprintf(string
, "InP");
87 sprintf(string
, "InOvTemplate");
89 sprintf(string
, "Out%dP", arg
->argRequestPos
);
91 fprintf(file
, "\t ptr = &%s->%s[0];\n", string
, arg
->argMsgField
);
94 argument_t
*count
= arg
->argCount
;
95 char *cref
= count
->argByReferenceUser
? "*" : "";
97 if (in
|| overwrite
) {
98 fprintf(file
, "\t if (%s%s > %d)\n", cref
, count
->argVarName
, it
->itKPD_Number
);
99 WriteReturnMsgError(file
, arg
->argRoutine
, TRUE
, arg
, "MIG_ARRAY_TOO_LARGE");
100 fprintf(file
, "\t for (i = 0; i < %s%s; ptr++, i++) %s\n", cref
, count
->argVarName
, (bracket
) ? "{" : "");
103 fprintf(file
, "\t j = min(Out%dP->%s, %s%s);\n", count
->argReplyPos
, count
->argVarName
, cref
, count
->argVarName
);
104 fprintf(file
, "\t for (i = 0; i < j; ptr++, i++) %s\n",(bracket
) ? "{" : "");
108 fprintf(file
, "\t for (i = 0; i < %d; ptr++, i++) %s\n", it
->itKPD_Number
, (bracket
) ? "{" : "");
111 /*************************************************************
112 * Writes the standard includes. The subsystem specific
113 * includes are in <SubsystemName>.h and writen by
114 * header:WriteHeader. Called by WriteProlog.
115 *************************************************************/
117 WriteMyIncludes(FILE *file
, statement_t
*stats
)
119 #ifdef MIG_KERNEL_PORT_CONVERSION
123 * We want to get the user-side definitions of types
124 * like task_t, ipc_space_t, etc. in mach/mach_types.h.
127 fprintf(file
, "#undef\tMACH_KERNEL\n");
129 if (InternalHeaderFileName
!= strNULL
)
133 /* Strip any leading path from InternalHeaderFileName. */
134 cp
= strrchr(InternalHeaderFileName
, '/');
136 cp
= InternalHeaderFileName
;
139 fprintf(file
, "#include \"%s\"\n", cp
);
144 if (UserHeaderFileName
== strNULL
|| UseSplitHeaders
)
145 WriteIncludes(file
, TRUE
, FALSE
);
146 if (UserHeaderFileName
!= strNULL
)
150 /* Strip any leading path from UserHeaderFileName. */
151 cp
= strrchr(UserHeaderFileName
, '/');
153 cp
= UserHeaderFileName
;
156 fprintf(file
, "#include \"%s\"\n", cp
);
159 WriteImplImports(file
, stats
, TRUE
);
161 if (UseEventLogger
) {
163 fprintf(file
, "#if\t__MigKernelSpecificCode\n");
164 fprintf(file
, "#include <mig_debug.h>\n");
165 fprintf(file
, "#endif\t/* __MigKernelSpecificCode */\n");
167 fprintf(file
, "#if MIG_DEBUG\n");
168 fprintf(file
, "#include <mach/mig_log.h>\n");
169 fprintf(file
, "#endif /* MIG_DEBUG */\n");
171 if (HasConsumeOnSendError
&& !IsKernelUser
) {
172 fprintf(file
, "#include <mach/mach.h>\n");
175 fprintf(file
, "/* LINTLIBRARY */\n");
179 fprintf(file
, "#if\t%s\n", NewCDecl
);
180 fprintf(file
, "#else\t/* %s */\n", NewCDecl
);
181 fprintf(file
, "extern mach_port_t mig_get_reply_port();\n");
182 fprintf(file
, "extern void mig_dealloc_reply_port();\n");
183 fprintf(file
, "extern char *%s();\n", MessAllocRoutine
);
184 fprintf(file
, "extern void %s();\n", MessFreeRoutine
);
185 fprintf(file
, "#endif\t/* %s */\n", NewCDecl
);
187 if (HasUseSpecialReplyPort
) {
189 fprintf(file
, "#include <TargetConditionals.h>\n");
190 fprintf(file
, "#include <mach/mach_sync_ipc.h>\n");
191 fprintf(file
, "#ifndef __MigSpecialReplyPortMsgOption\n");
192 fprintf(file
, "#define __MigSpecialReplyPortMsgOption "
193 "(MACH_SEND_SYNC_OVERRIDE|MACH_SEND_SYNC_USE_THRPRI|MACH_RCV_SYNC_WAIT)\n");
194 fprintf(file
, "#endif /* __MigSpecialReplyPortMsgOption */\n");
197 * extern the definition of mach_msg_destroy
198 * (to avoid inserting mach/mach.h everywhere)
200 fprintf(file
, "/* TODO: #include <mach/mach.h> */\n");
201 fprintf(file
, "#ifdef __cplusplus\nextern \"C\" {\n#endif /* __cplusplus */\n");
202 fprintf(file
, "extern void mach_msg_destroy(mach_msg_header_t *);\n");
203 fprintf(file
, "#ifdef __cplusplus\n}\n#endif /* __cplusplus */\n");
209 WriteGlobalDecls(FILE *file
)
211 if (RCSId
!= strNULL
)
212 WriteRCSDecl(file
, strconcat(SubsystemName
, "_user"), RCSId
);
214 fprintf(file
, "#define msgh_request_port\tmsgh_remote_port\n");
215 fprintf(file
, "#define msgh_reply_port\t\tmsgh_local_port\n");
218 WriteLogDefines(file
, "MACH_MSG_LOG_USER");
223 WriteOneMachErrorDefine(FILE *file
, char *name
, boolean_t timeout
, boolean_t SpecialReplyPort
)
225 fprintf(file
, "#ifndef\t%s\n", name
);
226 fprintf(file
, "#define\t%s(_R_) { \\\n", name
);
227 fprintf(file
, "\tswitch (_R_) { \\\n");
228 fprintf(file
, "\tcase MACH_SEND_INVALID_DATA: \\\n");
229 fprintf(file
, "\tcase MACH_SEND_INVALID_DEST: \\\n");
230 fprintf(file
, "\tcase MACH_SEND_INVALID_HEADER: \\\n");
231 if (!SpecialReplyPort
) {
232 fprintf(file
, "\t\tmig_put_reply_port(InP->Head.msgh_reply_port); \\\n");
234 fprintf(file
, "\t\tbreak; \\\n");
236 fprintf(file
, "\tcase MACH_SEND_TIMED_OUT: \\\n");
237 fprintf(file
, "\tcase MACH_RCV_TIMED_OUT: \\\n");
239 fprintf(file
, "\tdefault: \\\n");
240 if (SpecialReplyPort
) {
241 fprintf(file
, "\t\tmig_dealloc_special_reply_port(InP->Head.msgh_reply_port); \\\n");
243 fprintf(file
, "\t\tmig_dealloc_reply_port(InP->Head.msgh_reply_port); \\\n");
245 fprintf(file
, "\t} \\\n}\n");
246 fprintf(file
, "#endif\t/* %s */\n", name
);
251 WriteMachErrorDefines(FILE *file
)
253 WriteOneMachErrorDefine(file
, "__MachMsgErrorWithTimeout", TRUE
, FALSE
);
254 WriteOneMachErrorDefine(file
, "__MachMsgErrorWithoutTimeout", FALSE
, FALSE
);
255 if (HasUseSpecialReplyPort
) {
256 WriteOneMachErrorDefine(file
, "__MachMsgErrorWithTimeoutSRP", TRUE
, TRUE
);
257 WriteOneMachErrorDefine(file
, "__MachMsgErrorWithoutTimeoutSRP", FALSE
, TRUE
);
262 WriteMIGCheckDefines(FILE *file
)
264 fprintf(file
, "#define\t__MIG_check__Reply__%s_subsystem__ 1\n", SubsystemName
);
269 WriteNDRDefines(FILE *file
)
271 fprintf(file
, "#define\t__NDR_convert__Reply__%s_subsystem__ 1\n", SubsystemName
);
272 fprintf(file
, "#define\t__NDR_convert__mig_reply_error_subsystem__ 1\n");
276 /*************************************************************
277 * Writes the standard #includes, #defines, and
278 * RCS declaration. Called by WriteUser.
279 *************************************************************/
281 WriteProlog(FILE *file
, statement_t
*stats
)
283 WriteIdentificationString(file
);
284 WriteMIGCheckDefines(file
);
286 WriteNDRDefines(file
);
287 WriteMyIncludes(file
, stats
);
288 WriteBogusDefines(file
);
289 WriteMachErrorDefines(file
);
290 WriteApplDefaults(file
, "Send");
291 WriteGlobalDecls(file
);
296 WriteEpilog(FILE *file
)
298 /* nothing to see here, move along... */
302 WriteHeaderPortType(argument_t
*arg
)
304 if (arg
->argType
->itInName
== MACH_MSG_TYPE_POLYMORPHIC
)
305 return arg
->argPoly
->argVarName
;
307 return arg
->argType
->itInNameStr
;
311 WriteRequestHead(FILE *file
, routine_t
*rt
)
313 if (rt
->rtRetCArg
!= argNULL
&& !rt
->rtSimpleRequest
)
314 fprintf(file
, "ready_to_send:\n");
316 if (rt
->rtMaxRequestPos
> 0) {
318 fprintf(file
, "\tInP = &MessRequest;\n");
320 fprintf(file
, "\tInP = &Mess%sIn;\n", (rtMessOnStack(rt
) ? "." : "->"));
323 fprintf(file
, "\tInP->Head.msgh_bits =");
324 if (rt
->rtRetCArg
== argNULL
&& !rt
->rtSimpleRequest
)
325 fprintf(file
, " MACH_MSGH_BITS_COMPLEX|");
327 fprintf(file
, "\t\tMACH_MSGH_BITS(%s, %s);\n", WriteHeaderPortType(rt
->rtRequestPort
), WriteHeaderPortType(rt
->rtReplyPort
));
328 if (rt
->rtRetCArg
!= argNULL
&& !rt
->rtSimpleRequest
) {
329 fprintf(file
, "\tif (!%s)\n", rt
->rtRetCArg
->argVarName
);
330 fprintf(file
, "\t\tInP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n");
334 fprintf(file
, "\t/* msgh_size passed as argument */\n");
337 * KernelUser stubs need to cast the request and reply ports
338 * from ipc_port_t to mach_port_t.
341 #ifdef MIG_KERNEL_PORT_CONVERSION
343 fprintf(file
, "\tInP->%s = (mach_port_t) %s;\n", rt
->rtRequestPort
->argMsgField
, rt
->rtRequestPort
->argVarName
);
346 fprintf(file
, "\tInP->%s = %s;\n", rt
->rtRequestPort
->argMsgField
, rt
->rtRequestPort
->argVarName
);
348 if (akCheck(rt
->rtReplyPort
->argKind
, akbUserArg
)) {
349 #ifdef MIG_KERNEL_PORT_CONVERSION
351 fprintf(file
, "\tInP->%s = (mach_port_t) %s;\n", rt
->rtReplyPort
->argMsgField
, rt
->rtReplyPort
->argVarName
);
354 fprintf(file
, "\tInP->%s = %s;\n", rt
->rtReplyPort
->argMsgField
, rt
->rtReplyPort
->argVarName
);
356 else if (rt
->rtOneWay
)
357 fprintf(file
, "\tInP->%s = MACH_PORT_NULL;\n", rt
->rtReplyPort
->argMsgField
);
358 else if (rt
->rtUseSpecialReplyPort
)
359 fprintf(file
, "\tInP->%s = mig_get_special_reply_port();\n", rt
->rtReplyPort
->argMsgField
);
361 fprintf(file
, "\tInP->%s = mig_get_reply_port();\n", rt
->rtReplyPort
->argMsgField
);
363 fprintf(file
, "\tInP->Head.msgh_id = %d;\n", rt
->rtNumber
+ SubsystemBase
);
364 fprintf(file
, "\tInP->Head.msgh_reserved = 0;\n");
367 if (IsVoucherCodeAllowed
&& !IsKernelUser
&& !IsKernelServer
) {
368 fprintf(file
, "\t\n/* BEGIN VOUCHER CODE */\n\n");
369 fprintf(file
, "#ifdef USING_VOUCHERS\n");
370 fprintf(file
, "\tif (voucher_mach_msg_set != NULL) {\n");
371 fprintf(file
, "\t\tvoucher_mach_msg_set(&InP->Head);\n");
372 fprintf(file
, "\t}\n");
373 fprintf(file
, "#endif // USING_VOUCHERS\n");
374 fprintf(file
, "\t\n/* END VOUCHER CODE */\n");
378 /*************************************************************
379 * Writes declarations for the message types, variables
380 * and return variable if needed. Called by WriteRoutine.
381 *************************************************************/
383 WriteVarDecls(FILE *file
, routine_t
*rt
)
387 if (rt
->rtOverwrite
) {
388 fprintf(file
, "\tRequest MessRequest;\n");
389 fprintf(file
, "\tRequest *InP = &MessRequest;\n\n");
391 fprintf(file
, "\tunion {\n");
392 fprintf(file
, "\t\tOverwriteTemplate In;\n");
393 fprintf(file
, "\t\tReply Out;\n");
394 fprintf(file
, "\t} MessReply;\n");
396 fprintf(file
, "\tOverwriteTemplate *InOvTemplate = &MessReply.In;\n");
397 fprintf(file
, "\tReply *Out0P = &MessReply.Out;\n");
398 for (i
= 1; i
<= rt
->rtMaxReplyPos
; i
++)
399 fprintf(file
, "\t" "Reply *Out%dP = NULL;\n", i
);
402 if (rtMessOnStack(rt
))
403 fprintf(file
, "\tunion {\n");
405 fprintf(file
, "\tunion %sMessU {\n", rt
->rtName
);
406 fprintf(file
, "\t\tRequest In;\n");
408 fprintf(file
, "\t\tReply Out;\n");
409 if (rtMessOnStack(rt
))
410 fprintf(file
, "\t} Mess;\n");
412 fprintf(file
, "\t} *Mess = (union %sMessU *) %s(sizeof(*Mess));\n",
413 rt
->rtName
, MessAllocRoutine
);
416 fprintf(file
, "\tRequest *InP = &Mess%sIn;\n", (rtMessOnStack(rt
) ? "." : "->"));
418 fprintf(file
, "\tReply *Out0P = &Mess%sOut;\n", (rtMessOnStack(rt
) ? "." : "->"));
419 for (i
= 1; i
<= rt
->rtMaxReplyPos
; i
++)
420 fprintf(file
, "\t" "Reply *Out%dP = NULL;\n", i
);
426 fprintf(file
, "\tmach_msg_return_t msg_result;\n");
428 /* if request is variable, we need msgh_size_delta and msgh_size */
429 if (rt
->rtNumRequestVar
> 0)
430 fprintf(file
, "\tunsigned int msgh_size;\n");
431 if (rt
->rtMaxRequestPos
> 0)
432 fprintf(file
, "\tunsigned int msgh_size_delta;\n");
433 if (rt
->rtNumRequestVar
> 1 || rt
->rtMaxRequestPos
> 0)
436 if (rt
->rtUserImpl
) {
437 fprintf(file
, "\tmach_msg_max_trailer_t *TrailerP;\n");
438 fprintf(file
, "#if\t__MigTypeCheck\n");
439 fprintf(file
, "\tunsigned int trailer_size __attribute__((unused));\n");
440 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
443 fprintf(file
, "#ifdef\t__MIG_check__Reply__%s_t__defined\n", rt
->rtName
);
444 fprintf(file
, "\tkern_return_t check_result;\n");
445 fprintf(file
, "#endif\t/* __MIG_check__Reply__%s_t__defined */\n", rt
->rtName
);
447 WriteApplMacro(file
, "Send", "Declare", rt
);
452 WriteReturn(FILE *file
, routine_t
*rt
, char *before
, char *value
, char *after
, boolean_t deallocate_mess
)
454 if (rtMessOnStack(rt
)) {
455 if (value
!= stRetCode
) {
456 /* get the easy case (no braces needed) out of the way */
457 fprintf(file
, "%sreturn%s%s;%s", before
, (*value
? " " : ""), value
, after
);
461 fprintf(file
, "%s{\n", before
);
462 fprintf(file
, "%s\treturn Out0P->RetCode;\n%s}%s", before
, before
, after
);
467 if (value
== stRetCode
) {
468 fprintf(file
, "%s{\n%s\t%s ReturnValue;\n", before
, before
, ReturnTypeStr(rt
));
469 fprintf(file
, "%s\tReturnValue = Out0P->RetCode;\n%s\t", before
, before
);
472 fprintf(file
, "%s{ ", before
);
475 if (deallocate_mess
) {
476 fprintf(file
, "%s((char *) Mess, sizeof(*Mess)); ", MessFreeRoutine
);
479 if (value
== stRetCode
)
480 fprintf(file
, "return ReturnValue;\n%s}%s", before
, after
);
481 else if (value
== stRetNone
)
482 fprintf(file
, "return; }%s", after
);
484 fprintf(file
, "return %s; }%s", value
, after
);
488 WriteRetCodeArg(FILE *file
, routine_t
*rt
)
490 if (rt
->rtRetCArg
!= argNULL
&& !rt
->rtSimpleRequest
) {
491 argument_t
*arg
= rt
->rtRetCArg
;
493 fprintf(file
, "\tif (%s) {\n", arg
->argVarName
);
494 fprintf(file
, "\t\t((mig_reply_error_t *)InP)->RetCode = %s;\n", arg
->argVarName
);
495 fprintf(file
, "\t\t((mig_reply_error_t *)InP)->NDR = NDR_record;\n");
496 fprintf(file
, "\t\tgoto ready_to_send;\n");
497 fprintf(file
, "\t}\n\n");
501 /*************************************************************
502 * Writes the logic to check for a message send timeout, and
503 * deallocate any relocated ool data so as not to leak.
504 *************************************************************/
506 WriteMsgCheckForSendErrors(FILE *file
, routine_t
*rt
)
508 if (rt
->rtConsumeOnSendError
!= ConsumeOnSendErrorAny
&& rt
->rtWaitTime
== argNULL
) {
512 if (rt
->rtConsumeOnSendError
== ConsumeOnSendErrorAny
) {
513 // other errors mean the kernel consumed some of the rights
514 // and we can't possibly know if there's something left to destroy
516 "\t" "if (msg_result == MACH_SEND_INVALID_DEST ||" "\n"
517 "\t\t" "msg_result == MACH_SEND_TIMED_OUT) {" "\n", file
);
520 "\t" "if (msg_result == MACH_SEND_TIMED_OUT) {" "\n", file
);
523 if (rt
->rtConsumeOnSendError
== ConsumeOnSendErrorNone
) {
526 // iterate over arg list
527 for (arg_ptr
= rt
->rtArgs
; arg_ptr
!= NULL
; arg_ptr
= arg_ptr
->argNext
) {
529 // if argument contains ool data
530 if (akCheck(arg_ptr
->argKind
, akbSendKPD
) && arg_ptr
->argKPD_Type
== MACH_MSG_OOL_DESCRIPTOR
) {
531 // generate code to test current arg address vs. address before the msg_send call
532 // if not at the same address, mig_deallocate the argument
533 fprintf(file
, "\t\t" "if((vm_offset_t) InP->%s.address != (vm_offset_t) %s)\n",
534 arg_ptr
->argVarName
, arg_ptr
->argVarName
);
535 fprintf(file
, "\t\t\t" "mig_deallocate((vm_offset_t) InP->%s.address, "
536 "(vm_size_t) InP->%s.size);\n", arg_ptr
->argVarName
, arg_ptr
->argVarName
);
541 * The original MIG would leak most resources on send timeout without
542 * leaving a chance for callers to know how to dispose of most of the
543 * resources, as the caller can't possibly guess the new names
544 * picked during pseudo-receive.
547 fputs("#if\t__MigKernelSpecificCode" "\n", file
);
548 fputs("\t\t" "mach_msg_destroy_from_kernel(&InP->Head);" "\n", file
);
549 fputs("#endif\t/* __MigKernelSpecificCode */" "\n", file
);
551 fputs("\t\t" "/* mach_msg_destroy doesn't handle the local port */" "\n", file
);
552 fputs("\t\t" "switch (MACH_MSGH_BITS_LOCAL(InP->Head.msgh_bits)) {" "\n", file
);
553 fputs("\t\t" "case MACH_MSG_TYPE_MOVE_SEND:" "\n", file
);
554 fputs("\t\t\t" "mach_port_deallocate(mach_task_self(), InP->Head.msgh_local_port);" "\n", file
);
555 fputs("\t\t\t" "break;" "\n", file
);
556 fputs("\t\t" "}" "\n", file
);
557 fputs("\t\t" "mach_msg_destroy(&InP->Head);" "\n", file
);
561 fputs("\t" "}" "\n\n", file
);
565 /*************************************************************
566 * Writes the send call when there is to be no subsequent
567 * receive. Called by WriteRoutine SimpleRoutines
568 *************************************************************/
570 WriteMsgSend(FILE *file
, routine_t
*rt
)
573 char string
[MAX_STR_LEN
];
575 if (rt
->rtNumRequestVar
== 0)
576 SendSize
= "(mach_msg_size_t)sizeof(Request)";
578 SendSize
= "msgh_size";
580 if (rt
->rtRetCArg
!= argNULL
&& !rt
->rtSimpleRequest
) {
581 sprintf(string
, "(%s) ? (mach_msg_size_t)sizeof(mig_reply_error_t) : ", rt
->rtRetCArg
->argVarName
);
582 SendSize
= strconcat(string
, SendSize
);
586 fprintf(file
, "#if\t__MigKernelSpecificCode\n");
587 fprintf(file
, "\tmsg_result = mach_msg_send_from_kernel(");
588 fprintf(file
, "&InP->Head, %s);\n", SendSize
);
589 fprintf(file
, "#else\n");
591 fprintf(file
, "\tmsg_result = mach_msg("
592 "&InP->Head, MACH_SEND_MSG|%s%s, %s, 0, MACH_PORT_NULL, %s, MACH_PORT_NULL);\n",
593 rt
->rtWaitTime
!=argNULL
? "MACH_SEND_TIMEOUT|" : "",
594 rt
->rtMsgOption
->argVarName
,
596 rt
->rtWaitTime
!= argNULL
? rt
->rtWaitTime
->argVarName
:"MACH_MSG_TIMEOUT_NONE");
599 fprintf(file
, "#endif /* __MigKernelSpecificCode */\n");
602 WriteApplMacro(file
, "Send", "After", rt
);
604 WriteMsgCheckForSendErrors(file
, rt
);
606 WriteReturn(file
, rt
, "\t", "msg_result", "\n", TRUE
);
609 /*************************************************************
610 * Writes to code to check for error returns from receive.
611 * Called by WriteMsgSendReceive and WriteMsgRPC
612 *************************************************************/
614 WriteMsgCheckReceiveCleanupMigReplyPort(FILE *file
, routine_t
*rt
, char *success
)
616 if (!akCheck(rt
->rtReplyPort
->argKind
, akbUserArg
))
618 /* If we aren't using a user-supplied reply port, then
619 deallocate the reply port when it is invalid or
620 for TIMED_OUT errors. */
621 fprintf(file
, "\tif (msg_result != %s) {\n", success
);
622 if (rt
->rtWaitTime
!= argNULL
) {
623 fprintf(file
, "\t\t__MachMsgErrorWithTimeout%s(msg_result);\n",
624 rt
->rtUseSpecialReplyPort
? "SRP" : "");
626 fprintf(file
, "\t\t__MachMsgErrorWithoutTimeout%s(msg_result);\n",
627 rt
->rtUseSpecialReplyPort
? "SRP" : "");
629 fprintf(file
, "\t}\n");
634 WriteMsgCheckReceive(FILE *file
, routine_t
*rt
, char *success
)
636 fprintf(file
, "\tif (msg_result != %s) {\n", success
);
637 WriteReturnMsgError(file
, rt
, TRUE
, argNULL
, "msg_result");
638 fprintf(file
, "\t}\n");
641 /*************************************************************
642 * Writes the send and receive calls and code to check
643 * for errors. Normally the rpc code is generated instead
644 * although, the subsytem can be compiled with the -R option
645 * which will cause this code to be generated. Called by
646 * WriteRoutine if UseMsgRPC option is false.
647 *************************************************************/
649 WriteMsgSendReceive(FILE *file
, routine_t
*rt
)
652 char string
[MAX_STR_LEN
];
654 if (rt
->rtNumRequestVar
== 0)
655 SendSize
= "(mach_msg_size_t)sizeof(Request)";
657 SendSize
= "msgh_size";
659 if (rt
->rtRetCArg
!= argNULL
&& !rt
->rtSimpleRequest
) {
660 sprintf(string
, "(%s) ? (mach_msg_size_t)sizeof(mig_reply_error_t) : ", rt
->rtRetCArg
->argVarName
);
661 SendSize
= strconcat(string
, SendSize
);
664 /* IsKernelUser to be done! */
665 fprintf(file
, "\tmsg_result = mach_msg(&InP->Head, MACH_SEND_MSG|%s%s, %s, 0, ", rt
->rtWaitTime
!= argNULL
? "MACH_SEND_TIMEOUT|" : "", rt
->rtMsgOption
->argVarName
, SendSize
);
666 fprintf(file
, " MACH_PORT_NULL, %s, MACH_PORT_NULL);\n",
667 #if !USE_IMMEDIATE_SEND_TIMEOUT
668 (rt
->rtWaitTime
!= argNULL
) ? rt
->rtWaitTime
->argVarName
:
670 "MACH_MSG_TIMEOUT_NONE");
671 fprintf(file
, "\tif (msg_result != MACH_MSG_SUCCESS)\n");
672 WriteReturnMsgError(file
, rt
, TRUE
, argNULL
, "msg_result");
675 fprintf(file
, "\tmsg_result = mach_msg(&Out0P->Head, MACH_RCV_MSG|%s%s%s, 0, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_local_port, %s, MACH_PORT_NULL);\n",
676 rt
->rtUserImpl
!= 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "",
677 (rt
->rtWaitTime
!= argNULL
&& akIdent(rt
->rtWaitTime
->argKind
) == akeWaitTime
) ? "MACH_RCV_TIMEOUT|" : "",
678 rt
->rtMsgOption
->argVarName
,
679 (rt
->rtWaitTime
!= argNULL
&& akIdent(rt
->rtWaitTime
->argKind
) == akeWaitTime
) ? rt
->rtWaitTime
->argVarName
: "MACH_MSG_TIMEOUT_NONE");
680 WriteApplMacro(file
, "Send", "After", rt
);
681 WriteMsgCheckReceiveCleanupMigReplyPort(file
, rt
, "MACH_MSG_SUCCESS");
682 WriteMsgCheckReceive(file
, rt
, "MACH_MSG_SUCCESS");
686 /*************************************************************
687 * Writes the rpc call and the code to check for errors.
688 * This is the default code to be generated. Called by WriteRoutine
689 * for all routine types except SimpleRoutine.
690 *************************************************************/
692 WriteMsgRPC(FILE *file
, routine_t
*rt
)
695 char string
[MAX_STR_LEN
];
697 if (rt
->rtNumRequestVar
== 0)
698 SendSize
= "(mach_msg_size_t)sizeof(Request)";
700 SendSize
= "msgh_size";
702 if (rt
->rtRetCArg
!= argNULL
&& !rt
->rtSimpleRequest
) {
703 sprintf(string
, "(%s) ? (mach_msg_size_t)sizeof(mig_reply_error_t) : ", rt
->rtRetCArg
->argVarName
);
704 SendSize
= strconcat(string
, SendSize
);
708 fprintf(file
, "#if\t(__MigKernelSpecificCode) || (_MIG_KERNELSPECIFIC_CODE_)\n");
709 fprintf(file
, "\tmsg_result = mach_msg_rpc_from_kernel(&InP->Head, %s, (mach_msg_size_t)sizeof(Reply));\n", SendSize
);
710 fprintf(file
, "#else\n");
712 if (rt
->rtOverwrite
) {
713 fprintf(file
, "\tmsg_result = mach_msg_overwrite(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_RCV_OVERWRITE|%s%s%s, %s, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, %s, MACH_PORT_NULL, ",
714 rt
->rtUserImpl
!= 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "",
715 rt
->rtWaitTime
!= argNULL
?
716 (akIdent(rt
->rtWaitTime
->argKind
) == akeWaitTime
? "MACH_SEND_TIMEOUT|MACH_RCV_TIMEOUT|" : "MACH_SEND_TIMEOUT|") : "",
717 rt
->rtMsgOption
->argVarName
,
719 rt
->rtWaitTime
!= argNULL
? rt
->rtWaitTime
->argVarName
: "MACH_MSG_TIMEOUT_NONE");
720 fprintf(file
, " &InOvTemplate->Head, (mach_msg_size_t)sizeof(OverwriteTemplate));\n");
723 fprintf(file
, "\tmsg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|%s%s%s, %s, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, %s, MACH_PORT_NULL);\n",
724 rt
->rtUserImpl
!= 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "",
725 rt
->rtWaitTime
!= argNULL
?
726 (akIdent(rt
->rtWaitTime
->argKind
) == akeWaitTime
? "MACH_SEND_TIMEOUT|MACH_RCV_TIMEOUT|" : "MACH_SEND_TIMEOUT|") : "",
727 rt
->rtMsgOption
->argVarName
,
729 rt
->rtWaitTime
!= argNULL
? rt
->rtWaitTime
->argVarName
: "MACH_MSG_TIMEOUT_NONE");
732 fprintf(file
,"#endif /* __MigKernelSpecificCode */\n");
733 WriteApplMacro(file
, "Send", "After", rt
);
735 WriteMsgCheckReceiveCleanupMigReplyPort(file
, rt
, "MACH_MSG_SUCCESS");
736 WriteMsgCheckForSendErrors(file
, rt
);
738 WriteMsgCheckReceive(file
, rt
, "MACH_MSG_SUCCESS");
743 * argKPD_Pack discipline for Port types.
746 WriteKPD_port(FILE *file
, argument_t
*arg
)
748 ipc_type_t
*it
= arg
->argType
;
751 char firststring
[MAX_STR_LEN
];
752 char string
[MAX_STR_LEN
];
753 char *ref
= arg
->argByReferenceUser
? "*" : "";
756 if (IS_MULTIPLE_KPD(it
)) {
757 WriteKPD_Iterator(file
, TRUE
, FALSE
, it
->itVarArray
, arg
, TRUE
);
758 (void)sprintf(firststring
, "\t*ptr");
759 (void)sprintf(string
, "\tptr->");
761 real_it
= it
->itElement
;
764 (void)sprintf(firststring
, "InP->%s", arg
->argMsgField
);
765 (void)sprintf(string
, "InP->%s.", arg
->argMsgField
);
769 #ifdef MIG_KERNEL_PORT_CONVERSION
770 if (IsKernelUser
&& streql(real_it
->itUserType
, "ipc_port_t"))
771 recast
= "(mach_port_t)";
773 fprintf(file
, "#if\tUseStaticTemplates\n");
774 fprintf(file
, "\t%s = %s;\n", firststring
, arg
->argTTName
);
775 /* ref is required also in the Request part, because of inout parameters */
776 fprintf(file
, "\t%sname = %s%s%s%s;\n", string
, recast
, ref
, arg
->argVarName
, subindex
);
777 if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbSendSnd
)) {
778 argument_t
*poly
= arg
->argPoly
;
780 fprintf(file
, "\t%sdisposition = %s%s;\n", string
, poly
->argByReferenceUser
? "*" : "", poly
->argVarName
);
782 fprintf(file
, "#else\t/* UseStaticTemplates */\n");
783 fprintf(file
, "\t%sname = %s%s%s%s;\n", string
, recast
, ref
, arg
->argVarName
, subindex
);
784 if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbSendSnd
)) {
785 argument_t
*poly
= arg
->argPoly
;
787 fprintf(file
, "\t%sdisposition = %s%s;\n", string
, poly
->argByReferenceUser
? "*" : "", poly
->argVarName
);
790 fprintf(file
, "\t%sdisposition = %s;\n", string
, it
->itInNameStr
);
791 fprintf(file
, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string
);
792 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
793 if (IS_MULTIPLE_KPD(it
)) {
794 fprintf(file
, "\t }\n");
795 if (it
->itVarArray
) {
796 fprintf(file
, "\t for (i = %s; i < %d; ptr++, i++) {\n", arg
->argCount
->argVarName
, it
->itKPD_Number
);
797 /* fill the rest of the statically allocated KPD entries with MACH_PORT_NULL */
798 fprintf(file
, "#if\tUseStaticTemplates\n");
799 fprintf(file
, "\t%s = %s;\n", firststring
, arg
->argTTName
);
800 fprintf(file
, "#else\t/* UseStaticTemplates */\n");
801 fprintf(file
, "\t%sname = MACH_PORT_NULL;\n", string
);
802 fprintf(file
, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string
);
803 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
804 fprintf(file
, "\t }\n");
806 fprintf(file
, "\t}\n");
812 WriteKPD_ool_varsize(FILE *file
, argument_t
*arg
, char *who
, char *where
, boolean_t iscomplex
)
814 ipc_type_t
*it
= arg
->argType
;
820 count
= arg
->argSubCount
;
823 count
= arg
->argCount
;
824 cref
= count
->argByReferenceUser
? "*" : "";
826 /* size has to be expressed in bytes! */
827 if (count
->argMultiplier
> 1 || it
->itSize
> 8)
828 fprintf(file
, "\t%s->%s = %s%s%s * %d;\n", who
, where
, cref
, count
->argVarName
, (iscomplex
)? "[i]" : "", count
->argMultiplier
* it
->itSize
/ 8);
830 fprintf(file
, "\t%s->%s = %s%s%s;\n", who
, where
, cref
, count
->argVarName
, (iscomplex
)? "[i]" : "");
834 * argKPD_Pack discipline for out-of-line types.
837 WriteKPD_ool(FILE *file
, argument_t
*arg
)
839 ipc_type_t
*it
= arg
->argType
;
840 char *ref
= arg
->argByReferenceUser
? "*" : "";
841 char firststring
[MAX_STR_LEN
];
842 char string
[MAX_STR_LEN
];
844 u_int howmany
, howbig
;
847 if (IS_MULTIPLE_KPD(it
)) {
848 WriteKPD_Iterator(file
, TRUE
, FALSE
, it
->itVarArray
, arg
, TRUE
);
849 (void)sprintf(firststring
, "\t*ptr");
850 (void)sprintf(string
, "\tptr->");
851 VarArray
= it
->itElement
->itVarArray
;
852 howmany
= it
->itElement
->itNumber
;
853 howbig
= it
->itElement
->itSize
;
857 (void)sprintf(firststring
, "InP->%s", arg
->argMsgField
);
858 (void)sprintf(string
, "InP->%s.", arg
->argMsgField
);
859 VarArray
= it
->itVarArray
;
860 howmany
= it
->itNumber
;
865 fprintf(file
, "#if\tUseStaticTemplates\n");
867 fprintf(file
, "\t%s = %s;\n", firststring
, arg
->argTTName
);
868 fprintf(file
, "\t%saddress = (void *)(%s%s%s);\n", string
, ref
, arg
->argVarName
, subindex
);
870 if (IS_MULTIPLE_KPD(it
))
871 WriteKPD_ool_varsize(file
, arg
, "\tptr", "size", TRUE
);
873 WriteKPD_ool_varsize(file
, arg
, "InP", strconcat(arg
->argMsgField
, ".size"), FALSE
);
876 if (arg
->argDeallocate
== d_MAYBE
)
877 fprintf(file
, "\t%sdeallocate = %s;\n", string
, arg
->argDealloc
->argVarName
);
879 fprintf(file
, "#else\t/* UseStaticTemplates */\n");
881 fprintf(file
, "\t%saddress = (void *)(%s%s%s);\n", string
, ref
, arg
->argVarName
, subindex
);
883 if (IS_MULTIPLE_KPD(it
))
884 WriteKPD_ool_varsize(file
, arg
, "\tptr", "size", TRUE
);
886 WriteKPD_ool_varsize(file
, arg
, "InP", strconcat(arg
->argMsgField
, ".size"), FALSE
);
888 fprintf(file
, "\t%ssize = %d;\n", string
, (howmany
* howbig
+ 7)/8);
889 if (arg
->argDeallocate
== d_MAYBE
)
890 fprintf(file
, "\t%sdeallocate = %s;\n", string
, arg
->argDealloc
->argVarName
);
892 fprintf(file
, "\t%sdeallocate = %s;\n", string
, (arg
->argDeallocate
== d_YES
) ? "TRUE" : "FALSE");
893 fprintf(file
, "\t%scopy = %s;\n", string
, (arg
->argFlags
& flPhysicalCopy
) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY");
895 fprintf(file
, "\t%salignment = MACH_MSG_ALIGN_%d;\n", string
, (it
->itElement
->itSize
< 8) ? 1 : it
->itElement
->itSize
/ 8);
897 fprintf(file
, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string
);
899 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
900 if (IS_MULTIPLE_KPD(it
)) {
901 fprintf(file
, "\t }\n");
902 if (it
->itVarArray
) {
903 fprintf(file
, "\t for (i = %s; i < %d; ptr++, i++) {\n", arg
->argCount
->argVarName
, it
->itKPD_Number
);
904 /* fill the rest of the statically allocated KPD entries with size NULL */
905 fprintf(file
, "#if\tUseStaticTemplates\n");
906 fprintf(file
, "\t%s = %s;\n", firststring
, arg
->argTTName
);
908 fprintf(file
, "\t%ssize = 0;\n", string
);
909 /* otherwise the size in the template would be != 0! */
910 fprintf(file
, "#else\t/* UseStaticTemplates */\n");
911 fprintf(file
, "\t%ssize = 0;\n", string
);
912 fprintf(file
, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string
);
913 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
914 fprintf(file
, "\t }\n");
916 fprintf(file
, "\t}\n");
922 * argKPD_Pack discipline for out-of-line Port types.
925 WriteKPD_oolport(FILE *file
, argument_t
*arg
)
927 ipc_type_t
*it
= arg
->argType
;
928 char *ref
= arg
->argByReferenceUser
? "*" : "";
934 char firststring
[MAX_STR_LEN
];
935 char string
[MAX_STR_LEN
];
937 if (IS_MULTIPLE_KPD(it
)) {
938 WriteKPD_Iterator(file
, TRUE
, FALSE
, it
->itVarArray
, arg
, TRUE
);
939 (void)sprintf(firststring
, "\t*ptr");
940 (void)sprintf(string
, "\tptr->");
941 VarArray
= it
->itElement
->itVarArray
;
942 howmany
= it
->itElement
->itNumber
;
943 howstr
= it
->itElement
->itInNameStr
;
944 count
= arg
->argSubCount
;
948 (void)sprintf(firststring
, "InP->%s", arg
->argMsgField
);
949 (void)sprintf(string
, "InP->%s.", arg
->argMsgField
);
950 VarArray
= it
->itVarArray
;
951 howmany
= it
->itNumber
;
952 howstr
= it
->itInNameStr
;
953 count
= arg
->argCount
;
957 fprintf(file
, "#if\tUseStaticTemplates\n");
959 fprintf(file
, "\t%s = %s;\n", firststring
, arg
->argTTName
);
960 fprintf(file
, "\t%saddress = (void *)(%s%s%s);\n", string
, ref
, arg
->argVarName
, subindex
);
962 fprintf(file
, "\t%scount = %s%s%s;\n", string
, count
->argByReferenceUser
? "*" : "", count
->argVarName
, subindex
);
963 if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbSendSnd
)) {
964 argument_t
*poly
= arg
->argPoly
;
965 char *pref
= poly
->argByReferenceUser
? "*" : "";
967 fprintf(file
, "\t%sdisposition = %s%s;\n", string
, pref
, poly
->argVarName
);
969 if (arg
->argDeallocate
== d_MAYBE
)
970 fprintf(file
, "\t%sdeallocate = %s;\n", string
, arg
->argDealloc
->argVarName
);
972 fprintf(file
, "#else\t/* UseStaticTemplates */\n");
974 fprintf(file
, "\t%saddress = (void *)(%s%s%s);\n", string
, ref
, arg
->argVarName
, subindex
);
976 fprintf(file
, "\t%scount = %s%s%s;\n", string
, count
->argByReferenceUser
? "*" : "", count
->argVarName
, subindex
);
978 fprintf(file
, "\t%scount = %d;\n", string
, howmany
);
979 if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbSendSnd
)) {
980 argument_t
*poly
= arg
->argPoly
;
981 char *pref
= poly
->argByReferenceUser
? "*" : "";
983 fprintf(file
, "\t%sdisposition = %s%s;\n", string
, pref
, poly
->argVarName
);
986 fprintf(file
, "\t%sdisposition = %s;\n", string
, howstr
);
987 if (arg
->argDeallocate
== d_MAYBE
)
988 fprintf(file
, "\t%sdeallocate = %s;\n", string
, arg
->argDealloc
->argVarName
);
990 fprintf(file
, "\t%sdeallocate = %s;\n", string
, (arg
->argDeallocate
== d_YES
) ? "TRUE" : "FALSE");
991 fprintf(file
, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string
);
993 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
996 if (IS_MULTIPLE_KPD(it
)) {
997 fprintf(file
, "\t }\n");
998 if (it
->itVarArray
) {
999 fprintf(file
, "\t for (i = %s; i < %d; ptr++, i++) {\n", arg
->argCount
->argVarName
, it
->itKPD_Number
);
1000 /* fill the rest of the statically allocated KPD entries with size NULL */
1001 fprintf(file
, "#if\tUseStaticTemplates\n");
1002 fprintf(file
, "\t%s = %s;\n", firststring
, arg
->argTTName
);
1004 fprintf(file
, "\t%scount = 0;\n", string
);
1005 /* otherwise the size in the template would be != 0! */
1006 fprintf(file
, "#else\t/* UseStaticTemplates */\n");
1007 fprintf(file
, "\t%scount = 0;\n", string
);
1008 fprintf(file
, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string
);
1009 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
1010 fprintf(file
, "\t }\n");
1012 fprintf(file
, "\t}\n");
1014 fprintf(file
, "\n");
1018 WriteOverwriteTemplate(FILE *file
, routine_t
*rt
)
1021 char string
[MAX_STR_LEN
];
1022 char *subindex
= "";
1023 boolean_t finish
= FALSE
;
1025 fprintf(file
, "\t/* Initialize the template for overwrite */\n");
1026 fprintf(file
, "\tInOvTemplate->msgh_body.msgh_descriptor_count = %d;\n", rt
->rtOverwriteKPDs
);
1027 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
1028 ipc_type_t
*it
= arg
->argType
;
1029 char *ref
= arg
->argByReferenceUser
? "*" : "";
1033 u_int howmany
, howbig
;
1035 if (akCheck(arg
->argKind
, akbOverwrite
)) {
1036 if (arg
->argFlags
& flOverwrite
) {
1037 if (IS_MULTIPLE_KPD(it
)) {
1038 WriteKPD_Iterator(file
, FALSE
, TRUE
, it
->itVarArray
, arg
, TRUE
);
1041 sprintf(string
, "\tptr->");
1043 count
= arg
->argSubCount
;
1044 VarIndex
= it
->itElement
->itVarArray
;
1045 howmany
= it
->itElement
->itNumber
;
1046 howbig
= it
->itElement
->itSize
;
1049 sprintf(string
, "InOvTemplate->%s.", arg
->argMsgField
);
1051 count
= arg
->argCount
;
1052 VarIndex
= it
->itVarArray
;
1053 howmany
= it
->itNumber
;
1054 howbig
= it
->itSize
;
1057 fprintf(file
, "\t%saddress = (void *) %s%s%s;\n", string
, ref
, arg
->argVarName
, subindex
);
1059 if (it
->itPortType
) {
1060 fprintf(file
, "\t%scount = ", string
);
1062 cref
= count
->argByReferenceUser
? "*" : "";
1063 fprintf(file
, "%s%s%s;\n", cref
, count
->argVarName
, subindex
);
1066 fprintf(file
, "%d;\n", howmany
);
1069 fprintf(file
, "\t%ssize = ", string
);
1071 cref
= count
->argByReferenceUser
? "*" : "";
1072 if (count
->argMultiplier
> 1 || howbig
> 8)
1073 fprintf(file
, "%s%s%s * %d;\n", cref
, count
->argVarName
, subindex
, count
->argMultiplier
* howbig
/ 8);
1075 fprintf(file
, "%s%s%s;\n", cref
, count
->argVarName
, subindex
);
1078 fprintf(file
, "\t%ssize = %d;\n", string
, (howmany
* howbig
+ 7)/8);
1080 fprintf(file
, "\t%scopy = MACH_MSG_OVERWRITE;\n", string
);
1081 fprintf(file
, "\t%stype = MACH_MSG_OOL_%sDESCRIPTOR;\n", string
, (it
->itPortType
) ? "PORTS_" : "");
1082 if (IS_MULTIPLE_KPD(it
))
1083 fprintf(file
, "\t }\n");
1085 fprintf(file
, "\t for (i = %s%s; i < %d; ptr++, i++) {\n", (arg
->argCount
->argByReferenceUser
) ? "*" : "", arg
->argCount
->argVarName
, it
->itKPD_Number
);
1086 fprintf(file
, "\t\tptr->copy = MACH_MSG_ALLOCATE;\n");
1087 fprintf(file
, "\t\tptr->type = MACH_MSG_OOL_%sDESCRIPTOR;\n", (it
->itPortType
) ? "PORTS_" : "");
1088 fprintf(file
, "\t }\n");
1090 if (IS_MULTIPLE_KPD(it
))
1091 fprintf(file
, "\t}\n");
1094 /* just a placeholder */
1095 if (IS_MULTIPLE_KPD(it
)) {
1096 WriteKPD_Iterator(file
, FALSE
, TRUE
, FALSE
, arg
, TRUE
);
1097 fprintf(file
, "\t\tptr->copy = MACH_MSG_ALLOCATE;\n");
1098 fprintf(file
, "\t\tptr->type = MACH_MSG_OOL_%sDESCRIPTOR;\n", (it
->itPortType
) ? "PORTS_" : "");
1099 fprintf(file
, "\t }\n\t}\n");
1102 fprintf(file
, "\tInOvTemplate->%s.copy = MACH_MSG_ALLOCATE;\n", arg
->argMsgField
);
1103 /* not sure whether this is needed */
1104 fprintf(file
, "\tInOvTemplate->%s.type = MACH_MSG_OOL_%sDESCRIPTOR;\n", arg
->argMsgField
, (it
->itPortType
) ? "PORTS_" : "");
1109 fprintf(file
, "\n");
1112 /*************************************************************
1113 * Writes code to copy an argument into the request message.
1114 * Called by WriteRoutine for each argument that is to placed
1115 * in the request message.
1116 *************************************************************/
1119 WritePackArgValueNormal(FILE *file
, argument_t
*arg
)
1121 ipc_type_t
*it
= arg
->argType
;
1122 char *ref
= (arg
->argByReferenceUser
||
1123 it
->itNativePointer
) ? "*" : "";
1125 if (IS_VARIABLE_SIZED_UNTYPED(it
) || it
->itNoOptArray
) {
1128 * Copy variable-size C string with mig_strncpy.
1129 * Save the string length (+ 1 for trailing 0)
1130 * in the argument`s count field.
1132 fprintf(file
, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
1133 fprintf(file
, "\tif (mig_strncpy_zerofill != NULL) {\n");
1134 fprintf(file
, "\t\tInP->%s = (%s) mig_strncpy_zerofill(InP->%s, %s, %d);\n", arg
->argCount
->argMsgField
, arg
->argCount
->argType
->itTransType
, arg
->argMsgField
, arg
->argVarName
, it
->itNumber
);
1135 fprintf(file
, "\t} else {\n");
1136 fprintf(file
, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");
1138 fprintf(file
, "\t\tInP->%s = (%s) mig_strncpy(InP->%s, %s, %d);\n", arg
->argCount
->argMsgField
, arg
->argCount
->argType
->itTransType
, arg
->argMsgField
, arg
->argVarName
, it
->itNumber
);
1140 fprintf(file
, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
1141 fprintf(file
, "\t}\n");
1142 fprintf(file
, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");
1144 fprintf(file
, "\tInP->%sOffset = 0;\n", arg
->argMsgField
);
1146 else if (it
->itNoOptArray
)
1147 fprintf(file
, "\t(void)memcpy((char *) InP->%s, (const char *) %s%s, %d);\n", arg
->argMsgField
, ref
, arg
->argVarName
, it
->itTypeSize
);
1151 * Copy in variable-size inline array with (void)memcpy,
1152 * after checking that number of elements doesn`t
1153 * exceed declared maximum.
1155 argument_t
*count
= arg
->argCount
;
1156 char *countRef
= count
->argByReferenceUser
? "*" : "";
1157 ipc_type_t
*btype
= it
->itElement
;
1159 /* Note btype->itNumber == count->argMultiplier */
1161 if (akIdent(arg
->argKind
) != akeSubCount
) {
1162 /* we skip the SubCount case, as we have already taken care of */
1163 fprintf(file
, "\tif (%s%s > %d) {\n", countRef
, count
->argVarName
, it
->itNumber
/btype
->itNumber
);
1164 WriteReturnMsgError(file
, arg
->argRoutine
, TRUE
, arg
, "MIG_ARRAY_TOO_LARGE");
1165 fprintf(file
, "\t}\n");
1168 fprintf(file
, "\t(void)memcpy((char *) InP->%s, (const char *) %s%s, ", arg
->argMsgField
, ref
, arg
->argVarName
);
1169 if (btype
->itTypeSize
> 1)
1170 fprintf(file
, "%d * ", btype
->itTypeSize
);
1171 fprintf(file
, "%s%s);\n", countRef
, count
->argVarName
);
1174 else if (IS_OPTIONAL_NATIVE(it
)) {
1175 fprintf(file
, "\tif ((InP->__Present__%s = (%s != %s))) {\n", arg
->argMsgField
, arg
->argVarName
, it
->itBadValue
);
1176 WriteCopyType(file
, it
, TRUE
, "\tInP->%s.__Real__%s", "/* %s%s */ %s%s", arg
->argMsgField
, arg
->argMsgField
, ref
, arg
->argVarName
);
1177 fprintf(file
, "\t}\n");
1180 WriteCopyType(file
, it
, TRUE
, "InP->%s", "/* %s */ %s%s", arg
->argMsgField
, ref
, arg
->argVarName
);
1182 if (arg
->argPadName
!= NULL
&& it
->itPadSize
!= 0) {
1183 fprintf(file
, "\t for (int i = 0; i < %d; i++)\n", it
->itPadSize
);
1184 fprintf(file
, "\t\t InP->%s[i] = 0;\n", arg
->argPadName
);
1186 fprintf(file
, "\n");
1190 * Calculate the size of a variable-length message field.
1193 WriteArgSizeVariable(FILE *file
, argument_t
*arg
, ipc_type_t
*ptype
)
1195 int bsize
= ptype
->itElement
->itTypeSize
;
1196 argument_t
*count
= arg
->argCount
;
1198 if (PackMsg
== FALSE
) {
1199 fprintf(file
, "%d", ptype
->itTypeSize
+ ptype
->itPadSize
);
1203 /* If the base type size of the data field isn`t a multiple of 4,
1204 we have to round up. */
1205 if (bsize
% itWordAlign
!= 0)
1206 fprintf(file
, "_WALIGN_");
1209 fprintf(file
, "%d * ", bsize
);
1210 if (ptype
->itString
)
1211 /* get count from descriptor in message */
1212 fprintf(file
, "InP->%s", count
->argMsgField
);
1214 /* get count from argument */
1215 fprintf(file
, "%s%s", count
->argByReferenceUser
? "*" : "", count
->argVarName
);
1220 WriteArgSizeOptional(FILE *file
, argument_t
*arg
, ipc_type_t
*ptype
)
1222 fprintf(file
, "(InP->__Present__%s ? _WALIGNSZ_(%s) : 0)", arg
->argVarName
, ptype
->itUserType
);
1226 WriteArgSize(FILE *file
, argument_t
*arg
)
1229 ipc_type_t
*ptype
= arg
->argType
;
1231 if (IS_OPTIONAL_NATIVE(ptype
))
1232 WriteArgSizeOptional(file
, arg
, ptype
);
1234 WriteArgSizeVariable(file
, arg
, ptype
);
1238 * Adjust message size and advance request pointer.
1239 * Called after packing a variable-length argument that
1240 * has more arguments following.
1243 WriteAdjustMsgSize(FILE *file
, argument_t
*arg
)
1245 ipc_type_t
*ptype
= arg
->argType
;
1247 /* There are more In arguments. We need to adjust msgh_size
1248 and advance InP, so we save the size of the current field
1249 in msgh_size_delta. */
1251 fprintf(file
, "\tmsgh_size_delta = ");
1252 WriteArgSize(file
, arg
);
1253 fprintf(file
, ";\n");
1255 if (arg
->argRequestPos
== 0) {
1256 /* First variable-length argument. The previous msgh_size value
1257 is the minimum request size. */
1259 fprintf(file
, "\tmsgh_size = ");
1260 rtMinRequestSize(file
, arg
->argRoutine
, "Request");
1261 fprintf(file
, " + msgh_size_delta;\n");
1264 fprintf(file
, "\tmsgh_size += msgh_size_delta;\n");
1266 if (PackMsg
== TRUE
) {
1267 fprintf(file
, "\tInP = (Request *) ((pointer_t) InP + msgh_size_delta - ");
1268 if (IS_OPTIONAL_NATIVE(ptype
))
1269 fprintf(file
, "_WALIGNSZ_(%s)", ptype
->itUserType
);
1271 fprintf(file
, "%d", ptype
->itTypeSize
+ ptype
->itPadSize
);
1272 fprintf(file
, ");\n\n");
1277 * Calculate the size of the message. Called after the
1278 * last argument has been packed.
1281 WriteFinishMsgSize(FILE *file
, argument_t
*arg
)
1283 /* No more In arguments. If this is the only variable In
1284 argument, the previous msgh_size value is the minimum
1287 if (arg
->argRequestPos
== 0) {
1288 fprintf(file
, "\tmsgh_size = ");
1289 rtMinRequestSize(file
, arg
->argRoutine
, "Request");
1290 fprintf(file
, " + (");
1291 WriteArgSize(file
, arg
);
1292 fprintf(file
, ");\n");
1295 fprintf(file
, "\tmsgh_size += ");
1296 WriteArgSize(file
, arg
);
1297 fprintf(file
, ";\n");
1302 WriteInitializeCount(FILE *file
, argument_t
*arg
)
1304 ipc_type_t
*ptype
= arg
->argCInOut
->argParent
->argType
;
1305 ipc_type_t
*btype
= ptype
->itElement
;
1307 fprintf(file
, "\tif (%s%s < %d)\n", arg
->argByReferenceUser
? "*" : "", arg
->argVarName
, ptype
->itNumber
/btype
->itNumber
);
1308 fprintf(file
, "\t\tInP->%s = %s%s;\n", arg
->argMsgField
, arg
->argByReferenceUser
? "*" : "", arg
->argVarName
);
1309 fprintf(file
, "\telse\n");
1310 fprintf(file
, "\t\tInP->%s = %d;\n", arg
->argMsgField
, ptype
->itNumber
/btype
->itNumber
);
1311 fprintf(file
, "\n");
1315 * Generate code to fill in all of the request arguments and their
1319 WriteRequestArgs(FILE *file
, routine_t
*rt
)
1322 argument_t
*lastVarArg
;
1325 * 1. The Kernel Processed Data
1327 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
)
1328 if (akCheckAll(arg
->argKind
, akbSendSnd
|akbSendKPD
))
1329 (*arg
->argKPD_Pack
)(file
, arg
);
1332 * 2. The Data Stream
1334 lastVarArg
= argNULL
;
1335 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
1337 * Adjust message size and advance message pointer if
1338 * the last request argument was variable-length and the
1339 * request position will change.
1341 if (lastVarArg
!= argNULL
&&
1342 lastVarArg
->argRequestPos
< arg
->argRequestPos
) {
1343 WriteAdjustMsgSize(file
, lastVarArg
);
1344 lastVarArg
= argNULL
;
1347 if ((akIdent(arg
->argKind
) == akeCountInOut
) &&
1348 akCheck(arg
->argKind
, akbSendSnd
))
1349 WriteInitializeCount(file
, arg
);
1350 else if (akCheckAll(arg
->argKind
, akbSendSnd
|akbSendBody
))
1351 WritePackArgValueNormal(file
, arg
);
1353 * Remember whether this was variable-length.
1355 if (akCheckAll(arg
->argKind
, akbSendSnd
|akbSendBody
|akbVariable
))
1359 * Finish the message size.
1361 if (lastVarArg
!= argNULL
)
1362 WriteFinishMsgSize(file
, lastVarArg
);
1365 /*************************************************************
1366 * Writes code to check that the return msgh_id is correct and that
1367 * the size of the return message is correct. Called by
1369 *************************************************************/
1371 WriteCheckIdentity(FILE *file
, routine_t
*rt
)
1373 fprintf(file
, "\tif (Out0P->Head.msgh_id != %d) {\n", rt
->rtNumber
+ SubsystemBase
+ 100);
1374 fprintf(file
, "\t if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)\n");
1375 fprintf(file
, "\t\t{ return MIG_SERVER_DIED; }\n");
1376 fprintf(file
, "\t else\n");
1377 fprintf(file
, "\t\t{ return MIG_REPLY_MISMATCH; }\n");
1378 fprintf(file
, "\t}\n");
1379 fprintf(file
, "\n");
1380 if (!rt
->rtSimpleReply
)
1381 fprintf(file
, "\tmsgh_simple = !(Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);\n");
1382 fprintf(file
, "#if\t__MigTypeCheck\n");
1384 if (!rt
->rtNoReplyArgs
)
1385 fprintf(file
, "\tmsgh_size = Out0P->Head.msgh_size;\n\n");
1387 if (rt
->rtSimpleReply
) {
1388 /* Expecting a simple message. We can factor out the check for
1389 * a simple message, since the error reply message is also simple.
1391 fprintf(file
, "\tif ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
1392 if (rt
->rtNoReplyArgs
)
1393 fprintf(file
, "\t (Out0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Reply)))\n");
1396 * We have an error iff:
1397 * 1) the message size is not the one expected AND
1398 * 2) the message size is also different from sizeof(mig_reply_error_t)
1399 * or the RetCode == KERN_SUCCESS
1401 if (rt
->rtNumReplyVar
> 0) {
1402 fprintf(file
, "\t ((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < ");
1403 rtMinReplySize(file
, rt
, "__Reply");
1404 fprintf(file
, ") &&\n");
1407 fprintf(file
, "\t ((msgh_size != (mach_msg_size_t)sizeof(__Reply)) &&\n");
1408 fprintf(file
, "\t (msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||\n");
1409 fprintf(file
, "\t Out0P->RetCode == KERN_SUCCESS)))\n");
1413 /* Expecting a complex message. */
1415 fprintf(file
, "\t" "if ((msgh_simple || Out0P->msgh_body.msgh_descriptor_count != %d ||\n", rt
->rtReplyKPDs
);
1416 if (rt
->rtNumReplyVar
> 0) {
1417 fprintf(file
, "\t msgh_size < ");
1418 rtMinReplySize(file
, rt
, "__Reply");
1419 fprintf(file
, " || msgh_size > (mach_msg_size_t)sizeof(__Reply)) &&\n");
1422 fprintf(file
, "\t msgh_size != (mach_msg_size_t)sizeof(__Reply)) &&\n");
1423 fprintf(file
, "\t (!msgh_simple || msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||\n");
1424 fprintf(file
, "\t ((mig_reply_error_t *)Out0P)->RetCode == KERN_SUCCESS))\n");
1426 fprintf(file
, "\t\t{ return MIG_TYPE_ERROR ; }\n");
1427 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
1428 fprintf(file
, "\n");
1431 /*************************************************************
1432 * Write code to generate error handling code if the RetCode
1433 * argument of a Routine is not KERN_SUCCESS.
1434 *************************************************************/
1436 WriteRetCodeCheck(FILE *file
, routine_t
*rt
)
1438 if (rt
->rtSimpleReply
)
1439 fprintf(file
, "\tif (Out0P->RetCode != KERN_SUCCESS) {\n");
1441 fprintf(file
, "\tif (msgh_simple) {\n");
1443 fprintf(file
, "#ifdef\t__NDR_convert__mig_reply_error_t__defined\n");
1444 fprintf(file
, "\t\t__NDR_convert__mig_reply_error_t((mig_reply_error_t *)Out0P);\n");
1445 fprintf(file
, "#endif\t/* __NDR_convert__mig_reply_error_t__defined */\n");
1447 fprintf(file
, "\t\treturn ((mig_reply_error_t *)Out0P)->RetCode;\n");
1448 fprintf(file
, "\t}\n");
1449 fprintf(file
, "\n");
1453 * argKPD_TypeCheck discipline for Port types.
1456 WriteTCheckKPD_port(FILE *file
, argument_t
*arg
)
1458 ipc_type_t
*it
= arg
->argType
;
1460 char string
[MAX_STR_LEN
];
1461 boolean_t close
= FALSE
;
1463 if (IS_MULTIPLE_KPD(it
)) {
1464 WriteKPD_Iterator(file
, FALSE
, FALSE
, FALSE
, arg
, TRUE
);
1465 (void)sprintf(string
, "ptr->");
1470 (void)sprintf(string
, "Out%dP->%s.", arg
->argReplyPos
, arg
->argMsgField
);
1471 fprintf(file
, "\t%sif (%stype != MACH_MSG_PORT_DESCRIPTOR", tab
, string
);
1472 if (arg
->argPoly
== argNULL
&& !it
->itVarArray
)
1473 /* we can't check disposition when poly or VarArray,
1474 (because some of the entries could be empty) */
1475 fprintf(file
, " ||\n\t%s %sdisposition != %s", tab
, string
, it
->itOutNameStr
);
1478 "\t\t%s" "return MIG_TYPE_ERROR;\n"
1482 fprintf(file
, "\t }\n\t}\n");
1486 * argKPD_TypeCheck discipline for out-of-line types.
1489 WriteTCheckKPD_ool(FILE *file
, argument_t
*arg
)
1491 ipc_type_t
*it
= arg
->argType
;
1492 char *tab
, string
[MAX_STR_LEN
];
1494 u_int howmany
, howbig
;
1496 if (IS_MULTIPLE_KPD(it
)) {
1497 WriteKPD_Iterator(file
, FALSE
, FALSE
, FALSE
, arg
, TRUE
);
1499 sprintf(string
, "ptr->");
1500 howmany
= it
->itElement
->itNumber
;
1501 howbig
= it
->itElement
->itSize
;
1502 test
= !it
->itVarArray
&& !it
->itElement
->itVarArray
;
1506 sprintf(string
, "Out%dP->%s.", arg
->argReplyPos
, arg
->argMsgField
);
1507 howmany
= it
->itNumber
;
1508 howbig
= it
->itSize
;
1509 test
= !it
->itVarArray
;
1512 fprintf(file
, "\t%sif (%stype != MACH_MSG_OOL_DESCRIPTOR", tab
, string
);
1514 /* if VarArray we may use no-op; if itElement->itVarArray size might change */
1515 fprintf(file
, " ||\n\t%s %ssize != %d", tab
, string
, (howmany
* howbig
+ 7)/8);
1518 "\t\t%s" "return MIG_TYPE_ERROR;\n"
1521 if (IS_MULTIPLE_KPD(it
))
1522 fprintf(file
, "\t }\n\t}\n");
1526 * argKPD_TypeCheck discipline for out-of-line Port types.
1529 WriteTCheckKPD_oolport(FILE *file
, argument_t
*arg
)
1531 ipc_type_t
*it
= arg
->argType
;
1532 char *tab
, string
[MAX_STR_LEN
];
1537 if (IS_MULTIPLE_KPD(it
)) {
1538 WriteKPD_Iterator(file
, FALSE
, FALSE
, FALSE
, arg
, TRUE
);
1540 sprintf(string
, "ptr->");
1541 howmany
= it
->itElement
->itNumber
;
1542 test
= !it
->itVarArray
&& !it
->itElement
->itVarArray
;
1543 howstr
= it
->itElement
->itOutNameStr
;
1547 sprintf(string
, "Out%dP->%s.", arg
->argReplyPos
, arg
->argMsgField
);
1548 howmany
= it
->itNumber
;
1549 test
= !it
->itVarArray
;
1550 howstr
= it
->itOutNameStr
;
1553 fprintf(file
, "\t%sif (%stype != MACH_MSG_OOL_PORTS_DESCRIPTOR", tab
, string
);
1555 /* if VarArray we may use no-op; if itElement->itVarArray size might change */
1556 fprintf(file
, " ||\n\t%s %scount != %d", tab
, string
, howmany
);
1557 if (arg
->argPoly
== argNULL
)
1558 fprintf(file
, " ||\n\t%s %sdisposition != %s", tab
, string
, howstr
);
1559 fprintf(file
, ") {\n"
1560 "\t\t%s" "return MIG_TYPE_ERROR;\n"
1563 if (IS_MULTIPLE_KPD(it
))
1564 fprintf(file
, "\t }\n\t}\n");
1567 /*************************************************************
1568 * Writes code to check that the type of each of the arguments
1569 * in the reply message is what is expected. Called by
1570 * WriteRoutine for each out && typed argument in the reply message.
1571 *************************************************************/
1573 WriteTypeCheck(FILE *file
, argument_t
*arg
)
1575 fprintf(file
, "#if\t__MigTypeCheck\n");
1576 (*arg
->argKPD_TypeCheck
)(file
, arg
);
1577 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
1582 * argKPD_Extract discipline for Port types.
1585 WriteExtractKPD_port(FILE *file
, argument_t
*arg
)
1587 ipc_type_t
*it
= arg
->argType
;
1588 char *ref
= arg
->argByReferenceUser
? "*" : "";
1591 ipc_type_t
*real_it
;
1593 real_it
= (IS_MULTIPLE_KPD(it
)) ? it
->itElement
: it
;
1594 #ifdef MIG_KERNEL_PORT_CONVERSION
1595 if (IsKernelUser
&& streql(real_it
->itUserType
, "ipc_port_t"))
1596 recast
= "(mach_port_t)";
1598 if (IS_MULTIPLE_KPD(it
)) {
1599 WriteKPD_Iterator(file
, FALSE
, FALSE
, it
->itVarArray
, arg
, FALSE
);
1601 fprintf(file
, "\t\t%s[i] = %sptr->name;\n", arg
->argVarName
, recast
);
1602 if (it
->itVarArray
) {
1603 argument_t
*count
= arg
->argCount
;
1604 char *cref
= count
->argByReferenceUser
? "*" : "";
1606 fprintf(file
, "\t if (Out%dP->%s >",count
->argReplyPos
, count
->argVarName
);
1607 if (arg
->argCountInOut
) {
1608 fprintf(file
, " %s%s)\n", cref
, count
->argVarName
);
1611 fprintf(file
, " %d)\n", it
->itNumber
/it
->itElement
->itNumber
);
1613 WriteReturnMsgError(file
, arg
->argRoutine
, TRUE
, arg
, "MIG_ARRAY_TOO_LARGE");
1615 fprintf(file
, "\t}\n");
1619 fprintf(file
, "\t%s%s = %sOut%dP->%s.name;\n", ref
, arg
->argVarName
, recast
, arg
->argReplyPos
, arg
->argMsgField
);
1623 if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbReturnRcv
)) {
1624 argument_t
*poly
= arg
->argPoly
;
1625 char *pref
= poly
->argByReferenceUser
? "*" : "";
1627 fprintf(file
, "\t%s%s = Out%dP->%s%s.disposition;\n", pref
, poly
->argVarName
, arg
->argReplyPos
, arg
->argMsgField
, subindex
);
1632 * argKPD_Extract discipline for out-of-line types.
1635 WriteExtractKPD_ool(FILE *file
, argument_t
*arg
)
1637 char *ref
= arg
->argByReferenceUser
? "*" : "";
1638 ipc_type_t
*it
= arg
->argType
;
1640 if (IS_MULTIPLE_KPD(it
)) {
1641 WriteKPD_Iterator(file
, FALSE
, FALSE
, it
->itVarArray
, arg
, FALSE
);
1642 fprintf(file
, "\t\t%s[i] = ptr->address;\n", arg
->argVarName
);
1643 fprintf(file
, "\t}\n");
1646 fprintf(file
, "\t%s%s = (%s)(Out%dP->%s.address);\n", ref
, arg
->argVarName
, arg
->argType
->itUserType
, arg
->argReplyPos
, arg
->argMsgField
);
1648 * In case of variable sized arrays,
1649 * the count field will be retrieved from the untyped
1650 * section of the message
1655 * argKPD_Extract discipline for out-of-line Port types.
1658 WriteExtractKPD_oolport(FILE *file
, argument_t
*arg
)
1660 char *ref
= arg
->argByReferenceUser
? "*" : "";
1661 ipc_type_t
*it
= arg
->argType
;
1664 if (IS_MULTIPLE_KPD(it
)) {
1665 WriteKPD_Iterator(file
, FALSE
, FALSE
, it
->itVarArray
, arg
, FALSE
);
1666 fprintf(file
, "\t\t%s[i] = ptr->address;\n", arg
->argVarName
);
1667 fprintf(file
, "\t}\n");
1671 fprintf(file
, "\t%s%s = (%s)(Out%dP->%s.address);\n", ref
, arg
->argVarName
, arg
->argType
->itUserType
, arg
->argReplyPos
, arg
->argMsgField
);
1675 * In case of variable sized arrays,
1676 * the count field will be retrieved from the untyped
1677 * section of the message
1679 if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbReturnRcv
)) {
1680 argument_t
*poly
= arg
->argPoly
;
1681 char *pref
= poly
->argByReferenceUser
? "*" : "";
1683 fprintf(file
, "\t%s%s = Out%dP->%s%s.disposition;\n", pref
, poly
->argVarName
, arg
->argReplyPos
, arg
->argMsgField
, subindex
);
1687 /*************************************************************
1688 * Write code to copy an argument from the reply message
1689 * to the parameter. Called by WriteRoutine for each argument
1690 * in the reply message.
1691 *************************************************************/
1694 WriteExtractArgValueNormal(FILE *file
, argument_t
*arg
)
1696 ipc_type_t
*argType
= arg
->argType
;
1697 char *ref
= arg
->argByReferenceUser
? "*" : "";
1700 if (akCheck(arg
->argKind
, akbUserImplicit
))
1701 sprintf(who
, "TrailerP");
1703 sprintf(who
, "Out%dP", arg
->argReplyPos
);
1705 if (IS_VARIABLE_SIZED_UNTYPED(argType
) || argType
->itNoOptArray
) {
1706 if (argType
->itString
) {
1708 * Copy out variable-size C string with mig_strncpy, not the zerofill variant.
1709 * We don't risk leaking process / kernel memory on this copy-out because
1710 * we've already zero-filled the buffer on copy-in.
1712 fprintf(file
, "\t(void) mig_strncpy(%s%s, %s->%s, %d);\n", ref
, arg
->argVarName
, who
, arg
->argMsgField
, argType
->itNumber
);
1714 else if (argType
->itNoOptArray
)
1715 fprintf(file
, "\t(void)memcpy((char *) %s%s, (const char *) %s->%s, %d);\n", ref
, arg
->argVarName
, who
, arg
->argMsgField
, argType
->itTypeSize
);
1719 * Copy out variable-size inline array with (void)memcpy,
1720 * after checking that number of elements doesn`t
1721 * exceed user`s maximum.
1723 argument_t
*count
= arg
->argCount
;
1724 char *countRef
= count
->argByReferenceUser
? "*" : "";
1725 ipc_type_t
*btype
= argType
->itElement
;
1727 /* Note count->argMultiplier == btype->itNumber */
1728 /* Note II: trailer logic isn't supported in this case */
1729 fprintf(file
, "\tif (Out%dP->%s", count
->argReplyPos
, count
->argMsgField
);
1730 if (arg
->argCountInOut
) {
1731 fprintf(file
, " > %s%s) {\n", countRef
, count
->argVarName
);
1734 fprintf(file
, " > %d) {\n", argType
->itNumber
/btype
->itNumber
);
1738 * If number of elements is too many for user receiving area,
1739 * fill user`s area as much as possible. Return the correct
1740 * number of elements.
1742 fprintf(file
, "\t\t(void)memcpy((char *) %s%s, (const char *) Out%dP->%s, ", ref
, arg
->argVarName
, arg
->argReplyPos
, arg
->argMsgField
);
1743 if (btype
->itTypeSize
> 1)
1744 fprintf(file
, "%d * ", btype
->itTypeSize
);
1745 if (arg
->argCountInOut
) {
1746 fprintf(file
, " %s%s);\n", countRef
, count
->argVarName
);
1749 fprintf(file
, " %d);\n", argType
->itNumber
/btype
->itNumber
);
1751 fprintf(file
, "\t\t%s%s = Out%dP->%s", countRef
, count
->argVarName
, count
->argReplyPos
, count
->argMsgField
);
1752 fprintf(file
, ";\n");
1753 WriteReturnMsgError(file
, arg
->argRoutine
, TRUE
, arg
, "MIG_ARRAY_TOO_LARGE");
1755 fprintf(file
, "\t}\n");
1757 fprintf(file
, "\t(void)memcpy((char *) %s%s, (const char *) Out%dP->%s, ", ref
, arg
->argVarName
, arg
->argReplyPos
, arg
->argMsgField
);
1758 if (btype
->itTypeSize
> 1)
1759 fprintf(file
, "%d * ", btype
->itTypeSize
);
1760 fprintf(file
, "Out%dP->%s);\n", count
->argReplyPos
, count
->argMsgField
);
1764 WriteCopyType(file
, argType
, FALSE
, "%s%s", "/* %s%s */ %s->%s", ref
, arg
->argVarName
, who
, arg
->argMsgField
);
1765 fprintf(file
, "\n");
1769 WriteCalcArgSize(FILE *file
, argument_t
*arg
)
1771 ipc_type_t
*ptype
= arg
->argType
;
1772 ipc_type_t
*btype
= ptype
->itElement
;
1773 argument_t
*count
= arg
->argCount
;
1774 int multiplier
= btype
->itTypeSize
;
1776 /* If the base type size of the data field isn`t a multiple of 4,
1777 we have to round up. */
1778 if (btype
->itTypeSize
% itWordAlign
!= 0)
1779 fprintf(file
, "_WALIGN_(");
1781 fprintf(file
, "Out%dP->%s", count
->argReplyPos
, count
->argMsgField
);
1783 fprintf(file
, " * %d", multiplier
);
1785 if (btype
->itTypeSize
% itWordAlign
!= 0)
1790 WriteCheckArgSize(FILE *file
, routine_t
*rt
, argument_t
*arg
, const char *comparator
)
1792 ipc_type_t
*ptype
= arg
->argType
;
1793 ipc_type_t
*btype
= ptype
->itElement
;
1794 argument_t
*count
= arg
->argCount
;
1795 int multiplier
= btype
->itTypeSize
;
1797 fprintf(file
, "\tif (((msgh_size - ");
1798 rtMinReplySize(file
, rt
, "__Reply");
1801 fprintf(file
, " / %d", multiplier
);
1802 fprintf(file
, "< Out%dP->%s) ||\n", count
->argReplyPos
, count
->argMsgField
);
1803 fprintf(file
, "\t (msgh_size %s ", comparator
);
1804 rtMinReplySize(file
, rt
, "__Reply");
1805 fprintf(file
, " + ");
1806 WriteCalcArgSize(file
, arg
);
1808 fprintf(file
, ")\n\t\t{ return MIG_TYPE_ERROR ; }\n");
1812 /* NDR Conversion routines */
1816 WriteReplyNDRConvertIntRepArgCond(FILE *file
, argument_t
*arg
)
1818 routine_t
*rt
= arg
->argRoutine
;
1820 fprintf(file
, "defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)", rt
->rtName
, arg
->argMsgField
);
1824 WriteReplyNDRConvertCharRepArgCond(FILE *file
, argument_t
*arg
)
1826 routine_t
*rt
= arg
->argRoutine
;
1828 if (akIdent(arg
->argKind
) != akeCount
&& akIdent(arg
->argKind
) !=akeCountInOut
&& akIdent(arg
->argKind
) != akeRetCode
)
1829 fprintf(file
, "defined(__NDR_convert__char_rep__Reply__%s_t__%s__defined)", rt
->rtName
, arg
->argMsgField
);
1835 WriteReplyNDRConvertFloatRepArgCond(FILE *file
, argument_t
*arg
)
1837 routine_t
*rt
= arg
->argRoutine
;
1839 if (akIdent(arg
->argKind
) != akeCount
&& akIdent(arg
->argKind
) !=akeCountInOut
&& akIdent(arg
->argKind
) != akeRetCode
)
1840 fprintf(file
, "defined(__NDR_convert__float_rep__Reply__%s_t__%s__defined)", rt
->rtName
, arg
->argMsgField
);
1846 WriteReplyNDRConvertIntRepArgDecl(FILE *file
, argument_t
*arg
)
1848 WriteNDRConvertArgDecl(file
, arg
, "int_rep", "Reply");
1852 WriteReplyNDRConvertCharRepArgDecl(FILE *file
, argument_t
*arg
)
1854 if (akIdent(arg
->argKind
) != akeCount
&& akIdent(arg
->argKind
) !=akeCountInOut
&& akIdent(arg
->argKind
) != akeRetCode
)
1855 WriteNDRConvertArgDecl(file
, arg
, "char_rep", "Reply");
1859 WriteReplyNDRConvertFloatRepArgDecl(FILE *file
, argument_t
*arg
)
1861 if (akIdent(arg
->argKind
) != akeCount
&& akIdent(arg
->argKind
) !=akeCountInOut
&& akIdent(arg
->argKind
) != akeRetCode
)
1862 WriteNDRConvertArgDecl(file
, arg
, "float_rep", "Reply");
1868 WriteReplyNDRConvertArgUse(FILE *file
, argument_t
*arg
, char *convert
)
1870 routine_t
*rt
= arg
->argRoutine
;
1871 argument_t
*count
= arg
->argCount
;
1872 char argname
[MAX_STR_LEN
];
1874 if ((akIdent(arg
->argKind
) == akeCount
|| akIdent(arg
->argKind
) == akeCountInOut
) &&
1875 (arg
->argParent
&& akCheck(arg
->argParent
->argKind
, akbReturnNdr
)))
1878 if (arg
->argKPD_Type
== MACH_MSG_OOL_DESCRIPTOR
) {
1879 if (count
&& !arg
->argSameCount
&& !strcmp(convert
, "int_rep")) {
1880 fprintf(file
, "#if defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)\n", rt
->rtName
, count
->argMsgField
);
1881 fprintf(file
, "\t\t__NDR_convert__int_rep__Reply__%s_t__%s(&Out%dP->%s, Out%dP->NDR.int_rep);\n", rt
->rtName
, count
->argMsgField
, count
->argReplyPos
, count
->argMsgField
, count
->argReplyPos
);
1882 fprintf(file
, "#endif\t/* __NDR_convert__int_rep__Reply__%s_t__%s__defined */\n", rt
->rtName
, count
->argMsgField
);
1885 sprintf(argname
, "(%s)(Out%dP->%s.address)", FetchServerType(arg
->argType
), arg
->argReplyPos
, arg
->argMsgField
);
1888 sprintf(argname
, "&Out%dP->%s", arg
->argReplyPos
, arg
->argMsgField
);
1891 fprintf(file
, "#if defined(__NDR_convert__%s__Reply__%s_t__%s__defined)\n", convert
, rt
->rtName
, arg
->argMsgField
);
1892 fprintf(file
, "\t\t__NDR_convert__%s__Reply__%s_t__%s(%s, Out0P->NDR.%s", convert
, rt
->rtName
, arg
->argMsgField
, argname
, convert
);
1894 fprintf(file
, ", Out%dP->%s", count
->argReplyPos
, count
->argMsgField
);
1895 fprintf(file
, ");\n");
1896 fprintf(file
, "#endif /* __NDR_convert__%s__Reply__%s_t__%s__defined */\n", convert
, rt
->rtName
, arg
->argMsgField
);
1900 WriteReplyNDRConvertIntRepOneArgUse(FILE *file
, argument_t
*arg
)
1902 routine_t
*rt
= arg
->argRoutine
;
1904 fprintf(file
, "#if defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)\n", rt
->rtName
, arg
->argMsgField
);
1905 fprintf(file
, "\tif (Out0P->NDR.int_rep != NDR_record.int_rep)\n");
1906 fprintf(file
, "\t\t__NDR_convert__int_rep__Reply__%s_t__%s(&Out%dP->%s, Out%dP->NDR.int_rep);\n", rt
->rtName
, arg
->argMsgField
, arg
->argReplyPos
, arg
->argMsgField
, arg
->argReplyPos
);
1907 fprintf(file
, "#endif\t/* __NDR_convert__int_rep__Reply__%s_t__%s__defined */\n", rt
->rtName
, arg
->argMsgField
);
1911 WriteReplyNDRConvertIntRepArgUse(FILE *file
, argument_t
*arg
)
1913 WriteReplyNDRConvertArgUse(file
, arg
, "int_rep");
1917 WriteReplyNDRConvertCharRepArgUse(FILE *file
, argument_t
*arg
)
1919 if (akIdent(arg
->argKind
) != akeCount
&& akIdent(arg
->argKind
) !=akeCountInOut
&& akIdent(arg
->argKind
) != akeRetCode
)
1920 WriteReplyNDRConvertArgUse(file
, arg
, "char_rep");
1924 WriteReplyNDRConvertFloatRepArgUse(FILE *file
, argument_t
*arg
)
1926 if (akIdent(arg
->argKind
) != akeCount
&& akIdent(arg
->argKind
) !=akeCountInOut
&& akIdent(arg
->argKind
) != akeRetCode
)
1927 WriteReplyNDRConvertArgUse(file
, arg
, "float_rep");
1931 WriteCheckMsgSize(FILE *file
, argument_t
*arg
)
1933 routine_t
*rt
= arg
->argRoutine
;
1934 ipc_type_t
*it
= arg
->argType
;
1935 ipc_type_t
*btype
= it
->itElement
;
1937 /* If there aren't any more Out args after this, then
1938 we can use the msgh_size_delta value directly in
1939 the TypeCheck conditional. */
1941 if (CheckNDR
&& arg
->argCount
&& !arg
->argSameCount
)
1942 WriteReplyNDRConvertIntRepOneArgUse(file
, arg
->argCount
);
1944 if (arg
->argReplyPos
== rt
->rtMaxReplyPos
) {
1945 fprintf(file
, "#if\t__MigTypeCheck\n");
1948 * emit code to verify that the server-code-provided count does not exceed the maximum count allowed by the type.
1950 fprintf(file
, "\t" "if ( Out%dP->%s > %d )\n", arg
->argCount
->argReplyPos
,
1951 arg
->argCount
->argMsgField
, it
->itNumber
/btype
->itNumber
);
1952 fputs("\t\t" "return MIG_TYPE_ERROR;\n", file
);
1955 WriteCheckArgSize(file
, rt
, arg
, "!=");
1957 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
1960 /* If there aren't any more variable-sized arguments after this,
1961 then we must check for exact msg-size and we don't need
1962 to update msgh_size. */
1964 boolean_t LastVarArg
= arg
->argReplyPos
+1 == rt
->rtNumReplyVar
;
1966 /* calculate the actual size in bytes of the data field. note
1967 that this quantity must be a multiple of four. hence, if
1968 the base type size isn't a multiple of four, we have to
1969 round up. note also that btype->itNumber must
1970 divide btype->itTypeSize (see itCalculateSizeInfo). */
1972 fprintf(file
, "\tmsgh_size_delta = ");
1973 WriteCalcArgSize(file
, arg
);
1974 fprintf(file
, ";\n");
1975 fprintf(file
, "#if\t__MigTypeCheck\n");
1978 * emit code to verify that the server-code-provided count does not exceed the maximum count allowed by the type.
1980 fprintf(file
, "\t" "if ( Out%dP->%s > %d )\n", arg
->argCount
->argReplyPos
,
1981 arg
->argCount
->argMsgField
, it
->itNumber
/btype
->itNumber
);
1982 fputs("\t\t" "return MIG_TYPE_ERROR;\n", file
);
1985 WriteCheckArgSize(file
, rt
, arg
, LastVarArg
? "!=" : "<");
1988 fprintf(file
, "\tmsgh_size -= msgh_size_delta;\n");
1990 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
1992 fprintf(file
, "\n");
1996 WriteAdjustReplyMsgPtr(FILE *file
, argument_t
*arg
)
1998 ipc_type_t
*ptype
= arg
->argType
;
2000 fprintf(file
, "\t*Out%dPP = Out%dP = (__Reply *) ((pointer_t) Out%dP + msgh_size_delta - %d);\n\n",
2001 arg
->argReplyPos
+1, arg
->argReplyPos
+1, arg
->argReplyPos
, ptype
->itTypeSize
+ ptype
->itPadSize
);
2005 WriteReplyArgs(FILE *file
, routine_t
*rt
)
2009 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2010 if (akCheckAll(arg
->argKind
, akbReturnRcv
|akbReturnBody
)) {
2011 WriteExtractArgValueNormal(file
, arg
);
2013 else if (akCheckAll(arg
->argKind
, akbReturnRcv
|akbReturnKPD
)) {
2015 * KPDs have argReplyPos 0, therefore they escape the above logic
2017 (*arg
->argKPD_Extract
)(file
, arg
);
2019 else if (akCheck(arg
->argKind
, akbUserImplicit
)) {
2020 WriteExtractArgValueNormal(file
, arg
);
2025 /*************************************************************
2026 * Writes code to return the return value. Called by WriteRoutine
2027 * for routines and functions.
2028 *************************************************************/
2030 WriteReturnValue(FILE *file
, routine_t
*rt
)
2032 /* If returning RetCode, we have already checked that it is KERN_SUCCESS */
2033 WriteReturn(file
, rt
, "\t", "KERN_SUCCESS", "\n", TRUE
);
2036 /*************************************************************
2037 * Writes the elements of the message type declaration: the
2038 * msg_type structure, the argument itself and any padding
2039 * that is required to make the argument a multiple of 4 bytes.
2040 * Called by WriteRoutine for all the arguments in the request
2041 * message first and then the reply message.
2042 *************************************************************/
2044 WriteFieldDecl(FILE *file
, argument_t
*arg
)
2046 if (akCheck(arg
->argKind
, akbSendKPD
) ||
2047 akCheck(arg
->argKind
, akbReturnKPD
))
2048 WriteFieldDeclPrim(file
, arg
, FetchKPDType
);
2050 WriteFieldDeclPrim(file
, arg
, FetchUserType
);
2053 /* Fill in the string with an expression that refers to the size
2054 * of the specified array:
2057 GetArraySize(argument_t
*arg
, char *size
)
2059 ipc_type_t
*it
= arg
->argType
;
2061 if (it
->itVarArray
) {
2062 if (arg
->argCount
->argByReferenceUser
) {
2063 sprintf(size
, "*%s", arg
->argCount
->argVarName
);
2066 sprintf(size
, "%s", arg
->argCount
->argVarName
);
2069 sprintf(size
, "%d", (it
->itNumber
* it
->itSize
+ 7) / 8);
2075 WriteRPCPortDisposition(FILE *file
, argument_t
*arg
)
2078 * According to the MIG specification, the port disposition could be different
2079 * on input and output. If we stay with this then a new bitfield will have
2080 * to be added. Right now the port disposition is the same for in and out cases.
2082 switch(arg
->argType
->itInName
) {
2084 case MACH_MSG_TYPE_MOVE_RECEIVE
:
2085 fprintf(file
, " | MACH_RPC_MOVE_RECEIVE");
2088 case MACH_MSG_TYPE_MOVE_SEND
:
2089 fprintf(file
, " | MACH_RPC_MOVE_SEND");
2092 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
2093 fprintf(file
, " | MACH_RPC_MOVE_SEND_ONCE");
2096 case MACH_MSG_TYPE_COPY_SEND
:
2097 fprintf(file
, " | MACH_RPC_COPY_SEND");
2100 case MACH_MSG_TYPE_MAKE_SEND
:
2101 fprintf(file
, " | MACH_RPC_MAKE_SEND");
2104 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
2105 fprintf(file
, " | MACH_RPC_MAKE_SEND_ONCE");
2111 WriteRPCArgDescriptor(FILE *file
, argument_t
*arg
, int offset
)
2113 fprintf(file
, " {\n 0 ");
2115 fprintf(file
, "| MACH_RPC_PORT ");
2116 if (arg
->argType
->itNumber
> 1)
2117 fprintf(file
, "| MACH_RPC_ARRAY ");
2118 if (arg
->argType
->itVarArray
)
2119 fprintf(file
, "| MACH_RPC_VARIABLE ");
2120 WriteRPCPortDisposition(file
, arg
);
2122 else if (RPCPortArray(arg
)) {
2123 fprintf(file
, "| MACH_RPC_PORT_ARRAY ");
2124 if (arg
->argType
->itVarArray
)
2125 fprintf(file
, "| MACH_RPC_VARIABLE ");
2126 WriteRPCPortDisposition(file
, arg
);
2128 else if (RPCFixedArray(arg
))
2129 fprintf(file
, "| MACH_RPC_ARRAY_FIXED ");
2130 else if (RPCVariableArray(arg
))
2131 fprintf(file
, "| MACH_RPC_ARRAY_VARIABLE ");
2133 fprintf(file
, " | MACH_RPC_IN ");
2135 fprintf(file
, " | MACH_RPC_OUT ");
2136 if ((! arg
->argType
->itInLine
) && (! arg
->argType
->itMigInLine
))
2137 fprintf(file
, " | MACH_RPC_POINTER ");
2138 if (arg
->argFlags
& flDealloc
)
2139 fprintf(file
, " | MACH_RPC_DEALLOCATE ");
2140 if (arg
->argFlags
& flPhysicalCopy
)
2141 fprintf(file
, " | MACH_RPC_PHYSICAL_COPY ");
2142 fprintf(file
, ",\n");
2143 fprintf(file
, " %d,\n", (arg
->argType
->itSize
/ 8));
2144 fprintf(file
, " %d,\n", arg
->argType
->itNumber
);
2145 fprintf(file
, " %d,\n },\n", offset
);
2149 WriteRPCRoutineDescriptor(FILE *file
, routine_t
*rt
, int arg_count
, int descr_count
, string_t stub_routine
, string_t sig_array
)
2151 fprintf(file
, " { (mig_impl_routine_t) 0,\n\
2152 (mig_stub_routine_t) %s, ", stub_routine
);
2153 fprintf(file
, "%d, %d, %s}", arg_count
, descr_count
, sig_array
);
2157 WriteRPCRoutineArgDescriptor(FILE *file
, routine_t
*rt
)
2163 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2164 boolean_t compound
= arg
->argType
->itStruct
&& arg
->argType
->itInLine
;
2166 if (RPCPort(arg
) || RPCPortArray(arg
) ||
2167 RPCFixedArray(arg
) || RPCVariableArray(arg
)) {
2168 WriteRPCArgDescriptor(file
, arg
, offset
);
2173 size
= arg
->argType
->itNumber
* (arg
->argType
->itSize
/ 8);
2175 size
= (arg
->argType
->itSize
/ 8);
2177 if (akCheck(arg
->argKind
, akbServerArg
))
2185 WriteRPCSignature(FILE *file
, routine_t
*rt
)
2188 int descr_count
= 0;
2190 fprintf(file
, " kern_return_t rtn;\n");
2191 descr_count
= rtCountArgDescriptors(rt
->rtArgs
, &arg_count
);
2192 fprintf(file
, " const static struct\n {\n");
2193 fprintf(file
, " struct rpc_routine_descriptor rd;\n");
2194 fprintf(file
, " struct rpc_routine_arg_descriptor rad[%d];\n", descr_count
);
2195 fprintf(file
, " } sig =\n {\n");
2196 WriteRPCRoutineDescriptor(file
, rt
, arg_count
, descr_count
, "0", "sig.rad, 0");
2197 fprintf(file
, ",\n");
2198 fprintf(file
, " {\n");
2199 WriteRPCRoutineArgDescriptor(file
, rt
);
2200 fprintf(file
, "\n }\n");
2201 fprintf(file
, "\n };\n\n");
2205 WriteRPCCall(FILE *file
, routine_t
*rt
)
2211 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2212 if (akIdent(arg
->argKind
) == akeRequestPort
) {
2213 fprintf(file
, " rtn = (MACH_RPC(&sig, (mach_msg_size_t)sizeof(sig), %d, %s,\n", rt
->rtNumber
+ SubsystemBase
, arg
->argVarName
);
2214 fprintf(file
, " (%s", arg
->argVarName
);
2216 else if (akCheck(arg
->argKind
, akbServerArg
)) {
2217 if (i
&& (i
++ % 6 == 0))
2218 fprintf(file
, ",\n ");
2220 fprintf(file
, ", ");
2221 fprintf(file
, "%s", arg
->argVarName
);
2224 fprintf(file
, ")));\n");
2225 fprintf(file
, "\n");
2226 fprintf(file
, " if (rtn != KERN_NO_ACCESS) return rtn;\n\n");
2227 fprintf(file
, "/* The following message rpc code is generated for the network case */\n\n");
2231 CheckRPCCall(routine_t
*rt
)
2237 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2238 if (akCheck(arg
->argKind
, akbUserArg
) &&
2239 ((arg
->argType
->itOutName
== -1) || (arg
->argType
->itInName
== -1))) {
2242 if (arg
->argFlags
& flMaybeDealloc
) {
2250 WriteRPCRoutine(FILE *file
, routine_t
*rt
)
2252 if (CheckRPCCall(rt
)) {
2253 WriteRPCSignature(file
, rt
);
2254 WriteRPCCall(file
, rt
);
2258 /********************** End UserRPCTrap Routines*************************/
2260 /* Process an IN/INOUT arg before the short-circuited RPC */
2262 WriteShortCircInArgBefore(FILE *file
, argument_t
*arg
)
2264 ipc_type_t
*it
= arg
->argType
;
2267 fprintf(file
, "\n\t/* IN %s: */\n", arg
->argVarName
);
2269 if (akCheck(arg
->argKind
, akbSendKPD
|akbReturnKPD
)) {
2270 switch (arg
->argKPD_Type
) {
2272 case MACH_MSG_PORT_DESCRIPTOR
:
2275 case MACH_MSG_OOL_DESCRIPTOR
:
2276 /* Arg is an out-of-line array: */
2277 if (!(arg
->argFlags
& flDealloc
) &&
2278 (!(arg
->argFlags
& flAuto
) || !(arg
->argFlags
& flConst
))) {
2279 /* Need to map a copy of the array: */
2280 GetArraySize(arg
, size
);
2281 fprintf(file
, "\t(void)vm_read(mach_task_self(),\n");
2282 fprintf(file
, "\t\t (vm_address_t) %s%s, %s, (vm_address_t *) &_%sTemp_, &_MIG_Ignore_Count_);\n", (arg
->argByReferenceUser
? "*" : ""), arg
->argVarName
, size
, arg
->argVarName
);
2283 /* Point argument at the copy: */
2284 fprintf(file
, "\t*(char **)&%s%s = _%sTemp_;\n", (arg
->argByReferenceUser
? "*" : ""), arg
->argVarName
, arg
->argVarName
);
2286 else if ((arg
->argFlags
& flDealloc
) &&
2287 ((arg
->argFlags
& flAuto
) || it
->itMigInLine
)) {
2288 /* Point the temp var at the original argument: */
2289 fprintf(file
, "\t_%sTemp_ = (char *) %s%s;\n", arg
->argVarName
, (arg
->argByReferenceUser
? "*" : ""), arg
->argVarName
);
2293 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
2297 printf("MiG internal error: type of kernel processed data unknown\n");
2299 } /* end of switch */
2301 else if (it
->itNumber
> 1) {
2303 /* Arg is a struct -- nothing to do. */
2306 /* Arg is a C string or an in-line array: */
2307 if (!argIsOut(arg
) && !(arg
->argFlags
& flConst
)) {
2308 /* Have to copy it into a temp. Use a stack var, if this would
2309 * not overflow the -maxonstack specification:
2310 * Conservatively assume ILP32 thresholds
2312 if (it
->itTypeSize
<= sizeof(natural_t
) ||
2313 rtMessOnStack(arg
->argRoutine
) ||
2314 arg
->argRoutine
->rtTempBytesOnStack
+
2315 it
->itTypeSize
<= MaxMessSizeOnStack
) {
2316 fprintf(file
, "\t{ char _%sTemp_[%d];\n", arg
->argVarName
, it
->itTypeSize
);
2317 arg
->argRoutine
->rtTempBytesOnStack
+= it
->itTypeSize
;
2318 arg
->argTempOnStack
= TRUE
;
2321 fprintf(file
, "\t{ _%sTemp_ = (char *) %s(%d);\n", arg
->argVarName
, MessAllocRoutine
, it
->itTypeSize
);
2322 arg
->argTempOnStack
= FALSE
;
2324 WriteCopyArg(file
, arg
, TRUE
, "_%sTemp_", "/* %s */ (char *) %s", arg
->argVarName
, arg
->argVarName
);
2325 /* Point argument at temp: */
2326 fprintf(file
, "\t *(char **)&%s%s = _%sTemp_;\n", (arg
->argByReferenceUser
? "*" : ""), arg
->argVarName
, arg
->argVarName
);
2327 fprintf(file
, "\t}\n");
2334 /* Process an INOUT/OUT arg before the short-circuited RPC */
2336 WriteShortCircOutArgBefore(FILE *file
, argument_t
*arg
)
2338 ipc_type_t
*it
= arg
->argType
;
2340 fprintf(file
, "\n\t/* OUT %s: */\n", arg
->argVarName
);
2342 if (akCheck(arg
->argKind
, akbSendKPD
|akbReturnKPD
)) {
2343 switch (arg
->argKPD_Type
) {
2345 case MACH_MSG_PORT_DESCRIPTOR
:
2348 case MACH_MSG_OOL_DESCRIPTOR
:
2349 /* Arg is an out-of-line array: */
2350 if (!argIsIn(arg
) && (arg
->argFlags
& flOverwrite
)) {
2351 /* Point the temp var at the original argument: */
2352 fprintf(file
, "\t _%sTemp_ = (char *) %s%s;\n", arg
->argVarName
, (arg
->argByReferenceUser
? "*" : ""), arg
->argVarName
);
2356 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
2360 printf("MiG internal error: type of kernel processed data unknown\n");
2362 } /* end of switch */
2364 else if (it
->itNumber
> 1) {
2365 /* Arg is an in-line array: */
2371 /* Process an IN arg after the short-circuited RPC */
2373 WriteShortCircInArgAfter(FILE *file
, argument_t
*arg
)
2375 ipc_type_t
*it
= arg
->argType
;
2378 fprintf(file
, "\n\t/* IN %s: */\n", arg
->argVarName
);
2380 if (akCheck(arg
->argKind
, akbSendKPD
|akbReturnKPD
)) {
2381 switch (arg
->argKPD_Type
) {
2383 case MACH_MSG_PORT_DESCRIPTOR
:
2386 case MACH_MSG_OOL_DESCRIPTOR
:
2387 /* Arg is an out-of-line array: */
2388 GetArraySize(arg
, size
);
2389 if ((!(arg
->argFlags
& flAuto
) && it
->itMigInLine
) ||
2390 ((arg
->argFlags
& flAuto
) &&
2391 ((arg
->argFlags
& flDealloc
) ||
2392 !(arg
->argFlags
& flConst
))
2394 /* Need to dealloc the temporary: */
2395 fprintf(file
, "\t(void)vm_deallocate(mach_task_self(),");
2396 fprintf(file
, " (vm_address_t *) _%sTemp_, %s);\n", arg
->argVarName
, size
);
2400 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
2404 printf("MiG internal error: type of kernel processed data unknown\n");
2406 } /* end of switch */
2408 else if (it
->itNumber
> 1) {
2410 /* Arg is a struct -- nothing to do. */
2413 /* Arg is a C string or an in-line array: */
2414 if (!argIsOut(arg
) && !(arg
->argFlags
& flConst
)) {
2415 /* A temp needs to be deallocated, if not on stack: */
2416 if (!arg
->argTempOnStack
) {
2417 fprintf(file
, "\t%s(_%sTemp_, %d);\n", MessFreeRoutine
, arg
->argVarName
, it
->itTypeSize
);
2425 WriteShortCircOutArgAfter(FILE *file
, argument_t
*arg
)
2427 ipc_type_t
*it
= arg
->argType
;
2430 fprintf(file
, "\n\t/* OUT %s: */\n", arg
->argVarName
);
2432 if (akCheck(arg
->argKind
, akbSendKPD
|akbReturnKPD
)) {
2433 switch (arg
->argKPD_Type
) {
2435 case MACH_MSG_PORT_DESCRIPTOR
:
2438 case MACH_MSG_OOL_DESCRIPTOR
:
2439 /* Arg is an out-of-line array: */
2441 /* Calculate size of array: */
2442 GetArraySize(arg
, size
);
2443 if (!(arg
->argFlags
& flDealloc
) || (arg
->argFlags
& flOverwrite
)) {
2444 /* Copy argument to vm_allocated Temp: */
2445 fprintf(file
, "\t(void)vm_read(mach_task_self(),\n");
2446 fprintf(file
, "\t\t (vm_address_t) %s%s, %s, (vm_address_t *) &_%sTemp_, &_MIG_Ignore_Count_);\n", (arg
->argByReferenceUser
? "*" : ""), arg
->argVarName
, size
, arg
->argVarName
);
2447 if (!argIsIn(arg
) && (arg
->argFlags
& flDealloc
) &&
2448 (arg
->argFlags
& flOverwrite
)) {
2449 /* Deallocate argument returned by server */
2450 fprintf(file
, "\t(void)vm_deallocate(mach_task_self(),");
2451 fprintf(file
, " (vm_address_t *) %s%s, %s);\n", (arg
->argByReferenceUser
? "*" : ""), arg
->argVarName
, size
);
2453 /* Point argument at new temporary: */
2454 fprintf(file
, "\t*(char **)&%s%s = _%sTemp_;\n", (arg
->argByReferenceUser
? "*" : ""), arg
->argVarName
, arg
->argVarName
);
2458 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
2462 printf("MiG internal error: type of kernel processed data unknown\n");
2464 } /* end of switch */
2466 else if (it
->itNumber
!= 1) {
2467 /* Arg is an in-line array: */
2473 WriteShortCircRPC(FILE *file
, routine_t
*rt
)
2477 boolean_t ShortCircOkay
= TRUE
;
2478 boolean_t first_OOL_arg
= TRUE
;
2480 fprintf(file
, " if (0 /* Should be: !(%s & 0x3) XXX */) {\n", rt
->rtRequestPort
->argVarName
);
2483 /* Do not short-circuit simple routines: */
2484 ShortCircOkay
= FALSE
;
2487 /* Scan for any types we can't yet handle. If found, give up on short-
2488 * circuiting and fall back to mach_msg:
2490 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2491 if (arg
->argFlags
& flMaybeDealloc
) {
2492 ShortCircOkay
= FALSE
;
2495 /* Can't yet handle ports: */
2496 if (akCheck(arg
->argKind
, akbSendKPD
|akbReturnKPD
) &&
2497 (arg
->argKPD_Type
== MACH_MSG_PORT_DESCRIPTOR
||
2498 arg
->argKPD_Type
== MACH_MSG_OOL_PORTS_DESCRIPTOR
)) {
2499 ShortCircOkay
= FALSE
;
2505 if (ShortCircOkay
) {
2507 fprintf(file
," rpc_subsystem_t subsystem = ((rpc_port_t)%s)->rp_subsystem;\n", rt
->rtRequestPort
->argVarName
);
2508 fprintf(file
, "\n");
2509 fprintf(file
, " if (subsystem && subsystem->start == %d) {\n", SubsystemBase
);
2510 fprintf(file
, "\tkern_return_t rtn;\n");
2511 fprintf(file
, "\n");
2513 /* Declare temp vars for out-of-line array args, and for all array
2514 * args, if -maxonstack has forced us to allocate in-line arrays
2517 rt
->rtTempBytesOnStack
= 0;
2518 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2519 arg
->argTempOnStack
= FALSE
;
2520 if (akCheck(arg
->argKind
, akbSendKPD
|akbReturnKPD
) &&
2521 arg
->argKPD_Type
== MACH_MSG_OOL_DESCRIPTOR
) {
2522 if (first_OOL_arg
) {
2523 /* Need a garbage temporary to hold the datacount
2524 * returned by vm_read, which we always ignore:
2526 fprintf(file
, "\tmach_msg_type_number_t _MIG_Ignore_Count_;\n");
2527 first_OOL_arg
= FALSE
;
2530 else if (!rtMessOnStack(rt
) &&
2531 arg
->argType
->itNumber
> 1 && !arg
->argType
->itStruct
) {
2535 fprintf(file
, "\tchar *_%sTemp_;\n", arg
->argVarName
);
2536 /* Conservatively assume ILP32 thresholds */
2537 rt
->rtTempBytesOnStack
+= sizeof(natural_t
);
2540 /* Process the IN arguments, in order: */
2542 fprintf(file
, "\t/* Pre-Process the IN arguments: */\n");
2543 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2545 WriteShortCircInArgBefore(file
, arg
);
2547 WriteShortCircOutArgBefore(file
, arg
);
2549 fprintf(file
, "\n");
2551 /* Count the number of server args: */
2553 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
)
2554 if (akCheck(arg
->argKind
, akbServerArg
))
2557 /* Call RPC_SIMPLE to switch to server stack and function: */
2559 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2560 if (akIdent(arg
->argKind
) == akeRequestPort
) {
2561 fprintf(file
, "\trtn = RPC_SIMPLE(%s, %d, %d, (", arg
->argVarName
, rt
->rtNumber
+ SubsystemBase
, server_argc
);
2562 fprintf(file
, "%s", arg
->argVarName
);
2564 else if (akCheck(arg
->argKind
, akbServerArg
)) {
2566 fprintf(file
, ",\n\t\t");
2568 fprintf(file
, ", ");
2569 fprintf(file
, "%s", arg
->argVarName
);
2572 fprintf(file
, "));\n");
2573 fprintf(file
, "\n");
2575 /* Process the IN and OUT arguments, in order: */
2576 fprintf(file
, "\t/* Post-Process the IN and OUT arguments: */\n");
2577 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2579 WriteShortCircInArgAfter(file
, arg
);
2581 WriteShortCircOutArgAfter(file
, arg
);
2583 fprintf(file
, "\n");
2585 fprintf(file
, "\treturn rtn;\n");
2586 fprintf(file
, " }\n");
2589 /* In latest design, the following is not necessary, because in
2590 * kernel-loaded tasks, the Mach port name is the same as the handle
2591 * used by the RPC mechanism, namely a pointer to the ipc_port, and
2592 * in user-mode tasks, the Mach port name gets renamed to be a pointer
2593 * to the user-mode rpc_port_t struct.
2597 fprintf(file
, " %s = (ipc_port_t)%s->rp_receiver_name;\n", rt
->rtRequestPort
->argVarName
, rt
->rtRequestPort
->argVarName
);
2599 fprintf(file
, " %s = ((rpc_port_t)%s)->rp_receiver_name;\n", rt
->rtRequestPort
->argVarName
, rt
->rtRequestPort
->argVarName
);
2602 fprintf(file
, " }\n");
2606 WriteStubDecl(FILE *file
, routine_t
*rt
)
2608 fprintf(file
, "\n");
2609 fprintf(file
, "/* %s %s */\n", rtRoutineKindToStr(rt
->rtKind
), rt
->rtName
);
2610 fprintf(file
, "mig_external %s %s\n", ReturnTypeStr(rt
), rt
->rtUserName
);
2612 fprintf(file
, "(\n");
2613 WriteList(file
, rt
->rtArgs
, WriteUserVarDecl
, akbUserArg
, ",\n", "\n");
2614 fprintf(file
, ")\n");
2617 fprintf(file
, "#if\t%s\n", NewCDecl
);
2618 fprintf(file
, "(\n");
2619 WriteList(file
, rt
->rtArgs
, WriteUserVarDecl
, akbUserArg
, ",\n", "\n");
2620 fprintf(file
, ")\n");
2621 fprintf(file
, "#else\n");
2622 fprintf(file
, "\t(");
2623 WriteList(file
, rt
->rtArgs
, WriteNameDecl
, akbUserArg
, ", ", "");
2624 fprintf(file
, ")\n");
2625 WriteList(file
, rt
->rtArgs
, WriteUserVarDecl
, akbUserArg
, ";\n", ";\n");
2626 fprintf(file
, "#endif\t/* %s */\n", NewCDecl
);
2628 fprintf(file
, "{\n");
2632 InitKPD_Disciplines(argument_t
*args
)
2635 extern void KPD_noop(FILE *file
, argument_t
*arg
);
2636 extern void KPD_error(FILE *file
, argument_t
*arg
);
2637 extern void WriteTemplateKPD_port(FILE *file
, argument_t
*arg
, boolean_t in
);
2638 extern void WriteTemplateKPD_ool(FILE *file
, argument_t
*arg
, boolean_t in
);
2639 extern void WriteTemplateKPD_oolport(FILE *file
, argument_t
*arg
, boolean_t in
);
2642 * WriteKPD_port, WriteExtractKPD_port,
2643 * WriteKPD_ool, WriteExtractKPD_ool,
2644 * WriteKPD_oolport, WriteExtractKPD_oolport
2645 * are local to this module (which is the reason why this initialization
2646 * takes place here rather than in utils.c).
2647 * Common routines for user and server will be established SOON, and
2648 * all of them (including the initialization) will be transfert to
2650 * All the KPD disciplines are defaulted to be KPD_error().
2651 * Note that akbSendKPD and akbReturnKPd are not exclusive,
2652 * because of inout type of parameters.
2654 for (arg
= args
; arg
!= argNULL
; arg
= arg
->argNext
)
2655 if (akCheck(arg
->argKind
, akbSendKPD
|akbReturnKPD
))
2656 switch (arg
->argKPD_Type
) {
2658 case MACH_MSG_PORT_DESCRIPTOR
:
2659 arg
->argKPD_Init
= KPD_noop
;
2660 if akCheck(arg
->argKind
, akbSendKPD
) {
2661 arg
->argKPD_Template
= WriteTemplateKPD_port
;
2662 arg
->argKPD_Pack
= WriteKPD_port
;
2664 if akCheck(arg
->argKind
, akbReturnKPD
) {
2665 arg
->argKPD_Extract
= WriteExtractKPD_port
;
2666 arg
->argKPD_TypeCheck
= WriteTCheckKPD_port
;
2670 case MACH_MSG_OOL_DESCRIPTOR
:
2671 arg
->argKPD_Init
= KPD_noop
;
2672 if akCheck(arg
->argKind
, akbSendKPD
) {
2673 arg
->argKPD_Template
= WriteTemplateKPD_ool
;
2674 arg
->argKPD_Pack
= WriteKPD_ool
;
2676 if akCheck(arg
->argKind
, akbReturnKPD
) {
2677 arg
->argKPD_TypeCheck
= WriteTCheckKPD_ool
;
2678 arg
->argKPD_Extract
= WriteExtractKPD_ool
;
2682 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
2683 arg
->argKPD_Init
= KPD_noop
;
2684 if akCheck(arg
->argKind
, akbSendKPD
) {
2685 arg
->argKPD_Template
= WriteTemplateKPD_oolport
;
2686 arg
->argKPD_Pack
= WriteKPD_oolport
;
2688 if akCheck(arg
->argKind
, akbReturnKPD
) {
2689 arg
->argKPD_TypeCheck
= WriteTCheckKPD_oolport
;
2690 arg
->argKPD_Extract
= WriteExtractKPD_oolport
;
2695 printf("MiG internal error: type of kernel processed data unknown\n");
2697 } /* end of switch */
2701 WriteLimitCheck(FILE *file
, routine_t
*rt
)
2703 if (MaxMessSizeOnStack
== -1 || UserTypeLimit
== -1)
2705 if (!rt
->rtRequestUsedLimit
&& !rt
->rtReplyUsedLimit
)
2707 fprintf(file
, "#if LimitCheck\n");
2708 if (rt
->rtRequestUsedLimit
) {
2709 if (rt
->rtRequestFits
) {
2710 fprintf(file
, "\tif ((sizeof(Request) - %d) > %d)\n", rt
->rtRequestSizeKnown
, UserTypeLimit
);
2711 fprintf(file
, "\t __RequestOnStackAbort(%d, \"%s\");\n", SubsystemBase
+ rt
->rtNumber
, rt
->rtName
);
2713 else if (rt
->rtReplyFits
) {
2714 fprintf(file
, "\tif (sizeof(Request) < %d)\n", MaxMessSizeOnStack
);
2715 fprintf(file
, "\t __MessageOffStackNote(%d, \"%s\");\n", SubsystemBase
+ rt
->rtNumber
, rt
->rtName
);
2718 if (rt
->rtReplyUsedLimit
) {
2719 if (rt
->rtReplyFits
) {
2720 fprintf(file
, "\tif ((sizeof(Reply) - %d) > %d)\n", rt
->rtReplySizeKnown
, UserTypeLimit
);
2721 fprintf(file
, "\t __ReplyOnStackAbort(%d, \"%s\");\n", SubsystemBase
+ rt
->rtNumber
, rt
->rtName
);
2723 else if (rt
->rtRequestFits
) {
2724 fprintf(file
, "\tif (sizeof(Reply) < %d)\n", MaxMessSizeOnStack
);
2725 fprintf(file
, "\t __MessageOffStackNote(%d, \"%s\");\n", SubsystemBase
+ rt
->rtNumber
, rt
->rtName
);
2728 if (rt
->rtRequestUsedLimit
&& rt
->rtReplyUsedLimit
&&
2729 ! (rt
->rtRequestFits
|| rt
->rtReplyFits
)) {
2730 fprintf(file
, "\tif (sizeof(Request) < %d \n", MaxMessSizeOnStack
);
2731 fprintf(file
, "&& sizeof(Reply) < %d)\n", MaxMessSizeOnStack
);
2732 fprintf(file
, "\t __MessageOffStackNote(%d, \"%s\");\n", SubsystemBase
+ rt
->rtNumber
, rt
->rtName
);
2734 fprintf(file
, "#endif /* LimitCheck */\n");
2738 WriteOOLSizeCheck(FILE *file
, routine_t
*rt
)
2740 /* Emit code to validate the actual size of ool data vs. the reported size */
2742 boolean_t openedTypeCheckConditional
= FALSE
;
2744 // scan through arguments to see if there are any ool data blocks
2745 for (argPtr
= rt
->rtArgs
; argPtr
!= NULL
; argPtr
= argPtr
->argNext
) {
2746 if (akCheck(argPtr
->argKind
, akbReturnKPD
)) {
2747 ipc_type_t
*it
= argPtr
->argType
;
2748 boolean_t multiple_kpd
= IS_MULTIPLE_KPD(it
);
2749 char string
[MAX_STR_LEN
];
2751 argument_t
*argCountPtr
;
2754 if (argPtr
->argKPD_Type
== MACH_MSG_OOL_DESCRIPTOR
) {
2757 if ( !openedTypeCheckConditional
) {
2758 openedTypeCheckConditional
= TRUE
;
2759 fputs("#if __MigTypeCheck\n", file
);
2762 WriteKPD_Iterator(file
, FALSE
, FALSE
, FALSE
, argPtr
, TRUE
);
2764 sprintf(string
, "ptr->");
2765 test
= !it
->itVarArray
&& !it
->itElement
->itVarArray
;
2766 it
= it
->itElement
; // point to element descriptor, so size calculation is correct
2767 argCountPtr
= argPtr
->argSubCount
;
2770 sprintf(string
, "Out%dP->%s.", argPtr
->argReplyPos
, argPtr
->argMsgField
);
2771 test
= !it
->itVarArray
;
2772 argCountPtr
= argPtr
->argCount
;
2776 int multiplier
= (argCountPtr
->argMultiplier
> 1 || it
->itSize
> 8) ? argCountPtr
->argMultiplier
* it
->itSize
/ 8 : 1;
2778 if ( !openedTypeCheckConditional
) {
2779 openedTypeCheckConditional
= TRUE
;
2780 fputs("#if __MigTypeCheck\n", file
);
2783 fprintf(file
, "\t%s" "if (%ssize ", tab
, string
);
2785 fprintf(file
, "/ %d ", multiplier
);
2786 fprintf(file
,"!= Out%dP->%s%s", argCountPtr
->argReplyPos
, argCountPtr
->argVarName
, multiple_kpd
? "[i]" : "");
2787 if (it
->itOOL_Number
) {
2788 fprintf(file
," || Out%dP->%s%s > %d", argCountPtr
->argReplyPos
,
2789 argCountPtr
->argVarName
, multiple_kpd
? "[i]" : "", it
->itOOL_Number
);
2791 fprintf(file
,")\n");
2792 fprintf(file
, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab
);
2796 fprintf(file
, "\t }\n\t}\n");
2797 } else if (argPtr
->argKPD_Type
== MACH_MSG_OOL_PORTS_DESCRIPTOR
) {
2799 if ( !openedTypeCheckConditional
) {
2800 openedTypeCheckConditional
= TRUE
;
2801 fputs("#if __MigTypeCheck\n", file
);
2804 WriteKPD_Iterator(file
, FALSE
, FALSE
, FALSE
, argPtr
, TRUE
);
2806 sprintf(string
, "ptr->");
2807 test
= !it
->itVarArray
&& !it
->itElement
->itVarArray
;
2808 it
= it
->itElement
; // point to element descriptor, so size calculation is correct
2809 argCountPtr
= argPtr
->argSubCount
;
2812 sprintf(string
, "Out%dP->%s.", argPtr
->argReplyPos
, argPtr
->argMsgField
);
2813 test
= !it
->itVarArray
;
2814 argCountPtr
= argPtr
->argCount
;
2818 if ( !openedTypeCheckConditional
) {
2819 openedTypeCheckConditional
= TRUE
;
2820 fputs("#if __MigTypeCheck\n", file
);
2823 fprintf(file
, "\t%s" "if (%scount ", tab
, string
);
2824 fprintf(file
,"!= Out%dP->%s%s", argCountPtr
->argReplyPos
, argCountPtr
->argVarName
, multiple_kpd
? "[i]" : "");
2825 if (it
->itOOL_Number
) {
2826 fprintf(file
," || Out%dP->%s%s > %d", argCountPtr
->argReplyPos
,
2827 argCountPtr
->argVarName
, multiple_kpd
? "[i]" : "", it
->itOOL_Number
);
2829 fprintf(file
,")\n");
2830 fprintf(file
, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab
);
2834 fprintf(file
, "\t }\n\t}\n");
2839 if ( openedTypeCheckConditional
)
2840 fputs("#endif" "\t" "/* __MigTypeCheck */" "\n\n", file
);
2844 WriteCheckReply(FILE *file
, routine_t
*rt
)
2848 /* initialize the disciplines for the handling of KPDs */
2849 InitKPD_Disciplines(rt
->rtArgs
);
2854 fprintf(file
, "\n");
2855 fprintf(file
, "#if ( __MigTypeCheck ");
2857 fprintf(file
, "|| __NDR_convert__ ");
2858 fprintf(file
, ")\n");
2859 fprintf(file
, "#if __MIG_check__Reply__%s_subsystem__\n", SubsystemName
);
2860 fprintf(file
, "#if !defined(__MIG_check__Reply__%s_t__defined)\n", rt
->rtName
);
2861 fprintf(file
, "#define __MIG_check__Reply__%s_t__defined\n", rt
->rtName
);
2862 if (CheckNDR
&& akCheck(rt
->rtNdrCode
->argKind
, akbReply
)) {
2863 WriteList(file
, rt
->rtArgs
, WriteReplyNDRConvertIntRepArgDecl
, akbReturnNdr
, "\n", "\n");
2864 WriteList(file
, rt
->rtArgs
, WriteReplyNDRConvertCharRepArgDecl
, akbReturnNdr
, "\n", "\n");
2865 WriteList(file
, rt
->rtArgs
, WriteReplyNDRConvertFloatRepArgDecl
, akbReturnNdr
, "\n", "\n");
2867 fprintf(file
, "\n");
2868 fprintf(file
, "mig_internal kern_return_t __MIG_check__Reply__%s_t(__Reply__%s_t *Out0P", rt
->rtName
, rt
->rtName
);
2869 for (i
= 1; i
<= rt
->rtMaxReplyPos
; i
++)
2870 fprintf(file
, ", __Reply__%s_t **Out%dPP", rt
->rtName
, i
);
2871 fprintf(file
, ")\n{\n");
2874 fprintf(file
, "\n\ttypedef __Reply__%s_t __Reply __attribute__((unused));\n", rt
->rtName
);
2875 for (i
= 1; i
<= rt
->rtMaxReplyPos
; i
++)
2876 fprintf(file
, "\t__Reply *Out%dP;\n", i
);
2877 if (!rt
->rtSimpleReply
)
2878 fprintf(file
, "\tboolean_t msgh_simple;\n");
2879 if (!rt
->rtNoReplyArgs
) {
2880 fprintf(file
, "#if\t__MigTypeCheck\n");
2881 fprintf(file
, "\tunsigned int msgh_size;\n");
2882 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
2884 if (rt
->rtMaxReplyPos
> 0)
2885 fprintf(file
, "\tunsigned int msgh_size_delta;\n");
2886 if (rt
->rtNumReplyVar
> 0 || rt
->rtMaxReplyPos
> 0)
2887 fprintf(file
, "\n");
2889 /* Check the values that are returned in the reply message */
2891 WriteCheckIdentity(file
, rt
);
2893 /* Check the remote port is NULL */
2894 fprintf(file
, "#if\t__MigTypeCheck\n");
2895 fprintf(file
, "\tif (Out0P->Head.msgh_request_port != MACH_PORT_NULL) {\n");
2896 fprintf(file
, "\t\treturn MIG_TYPE_ERROR;\n");
2897 fprintf(file
, "\t}\n");
2898 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
2900 /* If the reply message has no Out parameters or return values
2901 other than the return code, we can type-check it and
2902 return it directly. */
2904 if (rt
->rtNoReplyArgs
&& !rt
->rtUserImpl
) {
2905 if (CheckNDR
&& akCheck(rt
->rtNdrCode
->argKind
, akbReply
) && rt
->rtRetCode
)
2906 WriteReplyNDRConvertIntRepOneArgUse(file
, rt
->rtRetCode
);
2907 WriteReturn(file
, rt
, "\t", stRetCode
, "\n", FALSE
);
2911 WriteLogMsg(file
, rt
, LOG_USER
, LOG_REPLY
);
2913 WriteRetCodeCheck(file
, rt
);
2915 /* Type Checking for the Out parameters which are typed */
2916 WriteList(file
, rt
->rtArgs
, WriteTypeCheck
, akbReturnKPD
, "\n", "\n");
2919 argument_t
*arg
, *lastVarArg
;
2921 lastVarArg
= argNULL
;
2922 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2924 * Advance message pointer if the last reply argument was
2925 * variable-length and the reply position will change.
2927 if (lastVarArg
!= argNULL
&&
2928 lastVarArg
->argReplyPos
< arg
->argReplyPos
) {
2929 WriteAdjustReplyMsgPtr(file
, lastVarArg
);
2930 lastVarArg
= argNULL
;
2933 if (akCheckAll(arg
->argKind
, akbReturnRcv
|akbReturnBody
)) {
2934 if (akCheck(arg
->argKind
, akbVariable
)) {
2935 WriteCheckMsgSize(file
, arg
);
2942 if (CheckNDR
&& akCheck(rt
->rtNdrCode
->argKind
, akbReply
)) {
2943 fprintf(file
, "#if\t");
2944 WriteList(file
, rt
->rtArgs
, WriteReplyNDRConvertIntRepArgCond
, akbReturnNdr
, " || \\\n\t", "\n");
2945 fprintf(file
, "\tif (Out0P->NDR.int_rep != NDR_record.int_rep) {\n");
2946 WriteList(file
, rt
->rtArgs
, WriteReplyNDRConvertIntRepArgUse
, akbReturnNdr
, "", "");
2947 fprintf(file
, "\t}\n#endif\t/* defined(__NDR_convert__int_rep...) */\n\n");
2949 WriteOOLSizeCheck(file
, rt
);
2951 fprintf(file
, "#if\t");
2952 WriteList(file
, rt
->rtArgs
, WriteReplyNDRConvertCharRepArgCond
, akbReturnNdr
, " || \\\n\t", "\n");
2953 fprintf(file
, "\tif (Out0P->NDR.char_rep != NDR_record.char_rep) {\n");
2954 WriteList(file
, rt
->rtArgs
, WriteReplyNDRConvertCharRepArgUse
, akbReturnNdr
, "", "");
2955 fprintf(file
, "\t}\n#endif\t/* defined(__NDR_convert__char_rep...) */\n\n");
2957 fprintf(file
, "#if\t");
2958 WriteList(file
, rt
->rtArgs
, WriteReplyNDRConvertFloatRepArgCond
, akbReturnNdr
, " || \\\n\t", "\n");
2959 fprintf(file
, "\tif (Out0P->NDR.float_rep != NDR_record.float_rep) {\n");
2960 WriteList(file
, rt
->rtArgs
, WriteReplyNDRConvertFloatRepArgUse
, akbReturnNdr
, "", "");
2961 fprintf(file
, "\t}\n#endif\t/* defined(__NDR_convert__float_rep...) */\n\n");
2963 WriteOOLSizeCheck(file
, rt
);
2965 fprintf(file
, "\treturn MACH_MSG_SUCCESS;\n");
2967 fprintf(file
, "}\n");
2968 fprintf(file
, "#endif /* !defined(__MIG_check__Reply__%s_t__defined) */\n", rt
->rtName
);
2969 fprintf(file
, "#endif /* __MIG_check__Reply__%s_subsystem__ */\n", SubsystemName
);
2970 fprintf(file
, "#endif /* ( __MigTypeCheck ");
2972 fprintf(file
, "|| __NDR_convert__ ");
2973 fprintf(file
, ") */\n\n");
2977 WriteCheckReplyCall(FILE *file
, routine_t
*rt
)
2981 fprintf(file
, "\n");
2982 fprintf(file
, "#if\tdefined(__MIG_check__Reply__%s_t__defined)\n", rt
->rtName
);
2983 fprintf(file
, "\tcheck_result = __MIG_check__Reply__%s_t((__Reply__%s_t *)Out0P", rt
->rtName
, rt
->rtName
);
2984 for (i
= 1; i
<= rt
->rtMaxReplyPos
; i
++)
2985 fprintf(file
, ", (__Reply__%s_t **)&Out%dP", rt
->rtName
, i
);
2986 fprintf(file
, ");\n");
2987 fprintf(file
, "\tif (check_result != MACH_MSG_SUCCESS) {\n");
2989 fprintf(file
, "#if\t__MigKernelSpecificCode\n");
2990 fprintf(file
, "\t\tmach_msg_destroy_from_kernel(&Out0P->Head);\n");
2991 fprintf(file
, "#endif\t/* __MigKernelSpecificCode */\n");
2993 fprintf(file
, "\t\tmach_msg_destroy(&Out0P->Head);\n");
2995 WriteReturnMsgError(file
, rt
, TRUE
, argNULL
, "check_result");
2996 fprintf(file
, "\t}\n");
2997 fprintf(file
, "#endif\t/* defined(__MIG_check__Reply__%s_t__defined) */\n", rt
->rtName
);
2998 fprintf(file
, "\n");
3002 WriteCheckReplies(FILE *file
, statement_t
*stats
)
3006 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
3007 if (stat
->stKind
== skRoutine
)
3008 WriteCheckReply(file
, stat
->stRoutine
);
3012 WriteCheckReplyTrailerArgs(FILE *file
, routine_t
*rt
)
3017 WriteCheckTrailerHead(file
, rt
, TRUE
);
3019 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
3020 if (akCheck(arg
->argKind
, akbUserImplicit
))
3021 WriteCheckTrailerSize(file
, TRUE
, arg
);
3024 fprintf(file
, "\n");
3028 /*************************************************************
3029 * Writes all the code comprising a routine body. Called by
3030 * WriteUser for each routine.
3031 *************************************************************/
3033 WriteRoutine(FILE *file
, routine_t
*rt
)
3035 /* write the stub's declaration */
3036 WriteStubDecl(file
, rt
);
3038 /* Use the RPC trap for user-user and user-kernel RPC */
3040 WriteRPCRoutine(file
, rt
);
3042 /* write the code for doing a short-circuited RPC: */
3044 WriteShortCircRPC(file
, rt
);
3046 /* typedef of structure for Request and Reply messages */
3047 WriteStructDecl(file
, rt
->rtArgs
, WriteFieldDecl
, akbRequest
, "Request", rt
->rtSimpleRequest
, FALSE
, FALSE
, FALSE
);
3048 if (!rt
->rtOneWay
) {
3049 WriteStructDecl(file
, rt
->rtArgs
, WriteFieldDecl
, akbReply
, "Reply", rt
->rtSimpleReply
, TRUE
, rt
->rtUserImpl
, FALSE
);
3050 WriteStructDecl(file
, rt
->rtArgs
, WriteFieldDecl
, akbReply
, "__Reply", rt
->rtSimpleReply
, FALSE
, FALSE
, FALSE
);
3052 if (rt
->rtOverwrite
)
3053 WriteStructDecl(file
, rt
->rtArgs
, WriteFieldDecl
, akbReply
|akbOverwrite
, "OverwriteTemplate", FALSE
, TRUE
, FALSE
, TRUE
);
3055 * Define a Minimal Reply structure to be used in case of errors
3057 fprintf(file
, "\t/*\n");
3058 fprintf(file
, "\t * typedef struct {\n");
3059 fprintf(file
, "\t * \tmach_msg_header_t Head;\n");
3060 fprintf(file
, "\t * \tNDR_record_t NDR;\n");
3061 fprintf(file
, "\t * \tkern_return_t RetCode;\n");
3062 fprintf(file
, "\t * } mig_reply_error_t;\n");
3063 fprintf(file
, "\t */\n");
3064 fprintf(file
, "\n");
3067 /* declarations for local vars: Union of Request and Reply messages,
3068 InP, OutP and return value */
3070 WriteVarDecls(file
, rt
);
3072 /* declarations and initializations of the mach_msg_type_descriptor_t variables
3073 for each argument that is a Kernel Processed Data */
3075 WriteList(file
, rt
->rtArgs
, WriteTemplateDeclIn
, akbRequest
| akbSendKPD
, "\n", "\n");
3077 WriteLimitCheck(file
, rt
);
3078 WriteRetCodeArg(file
, rt
);
3080 /* fill in the fields that are non related to parameters */
3082 if (!rt
->rtSimpleRequest
)
3083 fprintf(file
, "\tInP->msgh_body.msgh_descriptor_count = %d;\n", rt
->rtRequestKPDs
);
3085 /* fill in all the request message types and then arguments */
3087 WriteRequestArgs(file
, rt
);
3089 /* fill in request message head */
3091 WriteRequestHead(file
, rt
);
3092 fprintf(file
, "\n");
3094 /* give the application a chance to do some stuff. */
3095 WriteApplMacro(file
, "Send", "Before", rt
);
3097 /* Write the send/receive or rpc call */
3100 WriteLogMsg(file
, rt
, LOG_USER
, LOG_REQUEST
);
3104 WriteMsgSend(file
, rt
);
3108 #if USE_IMMEDIATE_SEND_TIMEOUT
3109 && (rt
->rtWaitTime
== argNULL
)
3112 /* overwrite mode meaningful only when UseMsgRPC is enabled */
3113 if (rt
->rtOverwrite
)
3114 WriteOverwriteTemplate(file
, rt
);
3115 WriteMsgRPC(file
, rt
);
3118 WriteMsgSendReceive(file
, rt
);
3120 WriteCheckReplyCall(file
, rt
);
3121 WriteCheckReplyTrailerArgs(file
, rt
);
3124 WriteLogMsg(file
, rt
, LOG_USER
, LOG_REPLY
);
3126 WriteReplyArgs(file
, rt
);
3128 /* return the return value, if any */
3129 if (!rt
->rtOneWay
) // WriteMsgSend() already wrote the 'return'
3130 WriteReturnValue(file
, rt
);
3131 fprintf(file
, "}\n");
3135 WriteRPCClientFunctions(FILE *file
, statement_t
*stats
)
3139 char *argfmt
= "(mach_port_t, char *, mach_msg_type_number_t)";
3141 fprintf(file
, "#ifdef AUTOTEST\n");
3142 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
3143 if (stat
->stKind
== skRoutine
) {
3144 fname
= stat
->stRoutine
->rtName
;
3145 fprintf(file
, "extern void client_%s%s;\n", fname
, argfmt
);
3147 fprintf(file
, "function_table_entry %s_client_functions[] =\n", SubsystemName
);
3148 fprintf(file
, "{\n");
3149 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
3150 if (stat
->stKind
== skRoutine
) {
3151 fname
= stat
->stRoutine
->rtName
;
3152 fprintf(file
, " { \"%s\", client_%s },\n", fname
, fname
);
3154 fprintf(file
, " { (char *) 0, (function_ptr_t) 0 }\n");
3155 fprintf(file
, "};\n");
3156 fprintf(file
, "#endif /* AUTOTEST */\n");
3159 /*************************************************************
3160 * Writes out the xxxUser.c file. Called by mig.c
3161 *************************************************************/
3163 WriteUser(FILE *file
, statement_t
*stats
)
3167 WriteProlog(file
, stats
);
3169 WriteRPCClientFunctions(file
, stats
);
3170 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
3171 switch (stat
->stKind
) {
3174 WriteCheckReply(file
, stat
->stRoutine
);
3175 WriteRoutine(file
, stat
->stRoutine
);
3186 fatal("WriteUser(): bad statement_kind_t (%d)", (int) stat
->stKind
);
3191 /*************************************************************
3192 * Writes out individual .c user files for each routine. Called by mig.c
3193 *************************************************************/
3195 WriteUserIndividual(statement_t
*stats
)
3199 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
3200 switch (stat
->stKind
) {
3206 filename
= strconcat(UserFilePrefix
, strconcat(stat
->stRoutine
->rtName
, ".c"));
3207 file
= fopen(filename
, "w");
3209 fatal("fopen(%s): %s", filename
, strerror(errno
));
3210 WriteProlog(file
, stats
);
3211 WriteRoutine(file
, stat
->stRoutine
);
3226 fatal("WriteUserIndividual(): bad statement_kind_t (%d)", (int) stat
->stKind
);