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@
27 * Mach Operating System
28 * Copyright (c) 1991,1990 Carnegie Mellon University
29 * All Rights Reserved.
31 * Permission to use, copy, modify and distribute this software and its
32 * documentation is hereby granted, provided that both the copyright
33 * notice and this permission notice appear in all copies of the
34 * software, derivative works or modified versions, and any portions
35 * thereof, and that both notices appear in supporting documentation.
37 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
38 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
39 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
41 * Carnegie Mellon requests users of this software to return to
43 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
44 * School of Computer Science
45 * Carnegie Mellon University
46 * Pittsburgh PA 15213-3890
48 * any improvements or extensions that they make and grant Carnegie Mellon
49 * the rights to redistribute these changes.
55 #include <mach/message.h>
62 #define max(a,b) (((a) > (b)) ? (a) : (b))
65 void WriteLogDefines(FILE *file
, string_t who
);
66 void WriteIdentificationString(FILE *file
);
67 static void WriteFieldDecl(FILE *file
, argument_t
*arg
);
70 WriteKPD_Iterator(FILE *file
, boolean_t in
, boolean_t varying
, argument_t
*arg
, boolean_t bracket
)
72 ipc_type_t
*it
= arg
->argType
;
73 char string
[MAX_STR_LEN
];
75 fprintf(file
, "\t{\n");
76 fprintf(file
, "\t %s\t*ptr;\n", it
->itKPDType
);
77 fprintf(file
, "\t int\ti");
80 fprintf(file
, ";\n\n");
83 sprintf(string
, "In%dP", arg
->argRequestPos
);
85 sprintf(string
, "OutP");
87 fprintf(file
, "\t ptr = &%s->%s[0];\n", string
, arg
->argMsgField
);
90 argument_t
*count
= arg
->argCount
;
93 fprintf(file
, "\t for (i = 0; i < In%dP->%s; ptr++, i++) %s\n", count
->argRequestPos
, count
->argMsgField
, (bracket
) ? "{" : "");
95 fprintf(file
, "\t j = min(%d, ", it
->itKPD_Number
);
96 if (akCheck(count
->argKind
, akbVarNeeded
))
97 fprintf(file
, "%s);\n", count
->argName
);
99 fprintf(file
, "%s->%s);\n", string
, count
->argMsgField
);
100 fprintf(file
, "\t for (i = 0; i < j; ptr++, i++) %s\n", (bracket
) ? "{" : "");
104 fprintf(file
, "\t for (i = 0; i < %d; ptr++, i++) %s\n", it
->itKPD_Number
, (bracket
) ? "{" : "");
108 WriteMyIncludes(FILE *file
, statement_t
*stats
)
110 if (ServerHeaderFileName
== strNULL
|| UseSplitHeaders
)
111 WriteIncludes(file
, FALSE
, FALSE
);
112 if (ServerHeaderFileName
!= strNULL
)
116 /* Strip any leading path from ServerHeaderFileName. */
117 cp
= strrchr(ServerHeaderFileName
, '/');
119 cp
= ServerHeaderFileName
;
122 fprintf(file
, "#include \"%s\"\n", cp
);
124 if (ServerHeaderFileName
== strNULL
|| UseSplitHeaders
)
125 WriteImplImports(file
, stats
, FALSE
);
126 if (UseEventLogger
) {
127 if (IsKernelServer
) {
128 fprintf(file
, "#if\t__MigKernelSpecificCode\n");
129 fprintf(file
, "#include <mig_debug.h>\n");
130 fprintf(file
, "#endif\t/* __MigKernelSpecificCode */\n");
132 fprintf(file
, "#if MIG_DEBUG\n");
133 fprintf(file
, "#include <mach/mig_log.h>\n");
134 fprintf(file
, "#endif /* MIG_DEBUG */\n");
141 WriteGlobalDecls(FILE *file
)
144 fprintf(file
, "#define novalue void\n");
147 fprintf(file
, "#if\t%s\n", NewCDecl
);
148 fprintf(file
, "#define novalue void\n");
149 fprintf(file
, "#else\n");
150 fprintf(file
, "#define novalue int\n");
151 fprintf(file
, "#endif\t/* %s */\n", NewCDecl
);
155 if (RCSId
!= strNULL
)
156 WriteRCSDecl(file
, strconcat(SubsystemName
, "_server"), RCSId
);
158 /* Used for locations in the request message, *not* reply message.
159 Reply message locations aren't dependent on IsKernelServer. */
161 if (IsKernelServer
) {
162 fprintf(file
, "#if\t__MigKernelSpecificCode\n");
163 fprintf(file
, "#define msgh_request_port\tmsgh_remote_port\n");
164 fprintf(file
, "#define MACH_MSGH_BITS_REQUEST(bits)");
165 fprintf(file
, "\tMACH_MSGH_BITS_REMOTE(bits)\n");
166 fprintf(file
, "#define msgh_reply_port\t\tmsgh_local_port\n");
167 fprintf(file
, "#define MACH_MSGH_BITS_REPLY(bits)");
168 fprintf(file
, "\tMACH_MSGH_BITS_LOCAL(bits)\n");
169 fprintf(file
, "#else\n");
171 fprintf(file
, "#define msgh_request_port\tmsgh_local_port\n");
172 fprintf(file
, "#define MACH_MSGH_BITS_REQUEST(bits)");
173 fprintf(file
, "\tMACH_MSGH_BITS_LOCAL(bits)\n");
174 fprintf(file
, "#define msgh_reply_port\t\tmsgh_remote_port\n");
175 fprintf(file
, "#define MACH_MSGH_BITS_REPLY(bits)");
176 fprintf(file
, "\tMACH_MSGH_BITS_REMOTE(bits)\n");
177 if (IsKernelServer
) {
178 fprintf(file
, "#endif /* __MigKernelSpecificCode */\n");
182 WriteLogDefines(file
, "MACH_MSG_LOG_SERVER");
183 fprintf(file
, "#define MIG_RETURN_ERROR(X, code)\t{\\\n");
184 fprintf(file
, "\t\t\t\t((mig_reply_error_t *)X)->RetCode = code;\\\n");
185 fprintf(file
, "\t\t\t\t((mig_reply_error_t *)X)->NDR = NDR_record;\\\n");
186 fprintf(file
, "\t\t\t\treturn;\\\n");
187 fprintf(file
, "\t\t\t\t}\n");
193 WriteForwardDeclarations(FILE *file
, statement_t
*stats
)
197 fprintf(file
, "/* Forward Declarations */\n\n");
198 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
199 if (stat
->stKind
== skRoutine
) {
200 fprintf(file
, "\nmig_internal novalue _X%s\n", stat
->stRoutine
->rtName
);
201 fprintf(file
, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);\n");
207 WriteMIGCheckDefines(FILE *file
)
209 fprintf(file
, "#define\t__MIG_check__Request__%s_subsystem__ 1\n", SubsystemName
);
214 WriteNDRDefines(FILE *file
)
216 fprintf(file
, "#define\t__NDR_convert__Request__%s_subsystem__ 1\n", SubsystemName
);
221 WriteProlog(FILE *file
, statement_t
*stats
)
223 WriteIdentificationString(file
);
225 fprintf(file
, "/* Module %s */\n", SubsystemName
);
227 WriteMIGCheckDefines(file
);
229 WriteNDRDefines(file
);
230 WriteMyIncludes(file
, stats
);
231 WriteBogusDefines(file
);
232 WriteApplDefaults(file
, "Rcv");
233 WriteGlobalDecls(file
);
234 if (ServerHeaderFileName
== strNULL
) {
235 WriteRequestTypes(file
, stats
);
236 WriteReplyTypes(file
, stats
);
237 WriteServerReplyUnion(file
, stats
);
242 WriteSymTabEntries(FILE *file
, statement_t
*stats
)
247 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
248 if (stat
->stKind
== skRoutine
) {
249 int num
= stat
->stRoutine
->rtNumber
;
250 char *name
= stat
->stRoutine
->rtName
;
251 while (++current
<= num
)
252 fprintf(file
,"\t\t\t{ \"\", 0, 0 },\n");
253 fprintf(file
, "\t{ \"%s\", %d, _X%s },\n", name
, SubsystemBase
+ current
- 1, name
);
255 while (++current
<= rtNumber
)
256 fprintf(file
,"\t{ \"\", 0, 0 },\n");
260 WriteRoutineEntries(FILE *file
, statement_t
*stats
)
264 char *sig_array
, *rt_name
;
265 int arg_count
, descr_count
;
267 size_t serverSubsysNameLen
= strlen(ServerSubsys
);
269 fprintf(file
, "\t{\n");
270 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
271 if (stat
->stKind
== skRoutine
) {
272 routine_t
*rt
= stat
->stRoutine
;
273 size_t rtNameLen
= strlen(rt
->rtName
);
275 // Include length of rt->rtName in calculation of necessary buffer size, since that string
276 // is actually written into the buffer along with the Server Subsystem name.
277 sig_array
= (char *) malloc(serverSubsysNameLen
+ rtNameLen
+ 80);
278 rt_name
= (char *) malloc(rtNameLen
+ 5);
279 while (current
++ < rt
->rtNumber
)
280 fprintf(file
, "\t\t{0, 0, 0, 0, 0, 0},\n");
281 // NOTE: if either of the two string constants in the sprintf() function calls below get
282 // much longer, be sure to increase the constant '80' (in the first malloc() call) to ensure
283 // that the allocated buffer is large enough. (Currently, I count 66 characters in the first
284 // string constant, 65 in the second. 80 ought to be enough for now...)
286 sprintf(sig_array
, "&%s.arg_descriptor[%d], (mach_msg_size_t)sizeof(__Reply__%s_t)", ServerSubsys
, offset
, rt
->rtName
);
289 sprintf(sig_array
, "(routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__%s_t)", rt
->rtName
);
291 sprintf(rt_name
, "_X%s", rt
->rtName
);
292 descr_count
= rtCountArgDescriptors(rt
->rtArgs
, &arg_count
);
293 offset
+= descr_count
;
294 WriteRPCRoutineDescriptor(file
, rt
, arg_count
, (UseRPCTrap
) ? descr_count
: 0, rt_name
, sig_array
);
295 fprintf(file
, ",\n");
299 while (current
++ < rtNumber
)
300 fprintf(file
, "\t\t{0, 0, 0, 0, 0, 0},\n");
302 fprintf(file
, "\t}");
306 WriteArgDescriptorEntries(FILE *file
, statement_t
*stats
)
310 fprintf(file
, ",\n\n\t{\n");
311 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
312 if (stat
->stKind
== skRoutine
) {
313 routine_t
*rt
= stat
->stRoutine
;
315 /* For each arg of the routine, write an arg descriptor:
317 WriteRPCRoutineArgDescriptor(file
, rt
);
319 fprintf(file
, "\t},\n\n");
324 * Write out the description of this subsystem, for use in direct RPC
327 WriteSubsystem(FILE *file
, statement_t
*stats
)
332 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
333 if (stat
->stKind
== skRoutine
) {
334 routine_t
*rt
= stat
->stRoutine
;
335 descr_count
+= rtCountArgDescriptors(rt
->rtArgs
, (int *) 0);
338 if (ServerHeaderFileName
== strNULL
) {
339 WriteMigExternal(file
);
340 fprintf(file
, "boolean_t %s(", ServerDemux
);
342 fprintf(file
, "\n\t\tmach_msg_header_t *InHeadP,");
343 fprintf(file
, "\n\t\tmach_msg_header_t *OutHeadP");
345 fprintf(file
, ");\n\n");
347 WriteMigExternal(file
);
348 fprintf(file
, "mig_routine_t %s_routine(", ServerDemux
);
350 fprintf(file
, "\n\t\tmach_msg_header_t *InHeadP");
352 fprintf(file
, ");\n\n");
354 fprintf(file
, "\n/* Description of this subsystem, for use in direct RPC */\n");
355 if (ServerHeaderFileName
== strNULL
) {
356 fprintf(file
, "const struct %s {\n", ServerSubsys
);
358 fprintf(file
, "\tstruct subsystem *\tsubsystem;\t/* Reserved for system use */\n");
361 fprintf(file
, "\tmig_server_routine_t \tserver;\t/* Server routine */\n");
363 fprintf(file
, "\tmach_msg_id_t\tstart;\t/* Min routine number */\n");
364 fprintf(file
, "\tmach_msg_id_t\tend;\t/* Max routine number + 1 */\n");
365 fprintf(file
, "\tunsigned int\tmaxsize;\t/* Max msg size */\n");
367 fprintf(file
, "\tvm_address_t\tbase_addr;\t/* Base address */\n");
368 fprintf(file
, "\tstruct rpc_routine_descriptor\t/*Array of routine descriptors */\n");
371 fprintf(file
, "\tvm_address_t\treserved;\t/* Reserved */\n");
372 fprintf(file
, "\tstruct routine_descriptor\t/*Array of routine descriptors */\n");
374 fprintf(file
, "\t\troutine[%d];\n", rtNumber
);
376 fprintf(file
, "\tstruct rpc_routine_arg_descriptor\t/*Array of arg descriptors */\n");
377 fprintf(file
, "\t\targ_descriptor[%d];\n", descr_count
);
379 fprintf(file
, "} %s = {\n", ServerSubsys
);
382 fprintf(file
, "const struct %s %s = {\n", ServerSubsys
, ServerSubsys
);
385 fprintf(file
, "\t0,\n");
388 fprintf(file
, "\t%s_routine,\n", ServerDemux
);
390 fprintf(file
, "\t%d,\n", SubsystemBase
);
391 fprintf(file
, "\t%d,\n", SubsystemBase
+ rtNumber
);
392 fprintf(file
, "\t(mach_msg_size_t)sizeof(union __ReplyUnion__%s),\n", ServerSubsys
);
394 fprintf(file
, "\t(vm_address_t)&%s,\n", ServerSubsys
);
397 fprintf(file
, "\t(vm_address_t)0,\n");
399 WriteRoutineEntries(file
, stats
);
402 WriteArgDescriptorEntries(file
, stats
);
406 fprintf(file
, "};\n\n");
409 #if NOT_CURRENTLY_USED
412 WriteArraySizes(FILE *file
, statement_t
*stats
)
417 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
418 if (stat
->stKind
== skRoutine
) {
419 routine_t
*rt
= stat
->stRoutine
;
421 while (current
++ < rt
->rtNumber
)
422 fprintf(file
, "\t\t0,\n");
423 fprintf(file
, "\t\t(mach_msg_size_t)sizeof(__Reply__%s_t),\n", rt
->rtName
);
425 while (current
++ < rtNumber
)
426 fprintf(file
, "\t\t\t0,\n");
429 #endif /* NOT_CURRENTLY_USED */
432 WriteServerRequestUnion(FILE *file
, statement_t
*stats
)
437 fprintf(file
, "/* union of all requests */\n\n");
438 fprintf(file
, "#ifndef __RequestUnion__%s__defined\n", ServerSubsys
);
439 fprintf(file
, "#define __RequestUnion__%s__defined\n", ServerSubsys
);
440 fprintf(file
, "union __RequestUnion__%s {\n", ServerSubsys
);
441 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
) {
442 if (stat
->stKind
== skRoutine
) {
445 rt
= stat
->stRoutine
;
446 fprintf(file
, "\t__Request__%s_t Request_%s;\n", rt
->rtName
, rt
->rtName
);
449 fprintf(file
, "};\n");
450 fprintf(file
, "#endif /* __RequestUnion__%s__defined */\n", ServerSubsys
);
454 WriteServerReplyUnion(FILE *file
, statement_t
*stats
)
459 fprintf(file
, "/* union of all replies */\n\n");
460 fprintf(file
, "#ifndef __ReplyUnion__%s__defined\n", ServerSubsys
);
461 fprintf(file
, "#define __ReplyUnion__%s__defined\n", ServerSubsys
);
462 fprintf(file
, "union __ReplyUnion__%s {\n", ServerSubsys
);
463 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
) {
464 if (stat
->stKind
== skRoutine
) {
467 rt
= stat
->stRoutine
;
468 fprintf(file
, "\t__Reply__%s_t Reply_%s;\n", rt
->rtName
, rt
->rtName
);
471 fprintf(file
, "};\n");
472 fprintf(file
, "#endif /* __ReplyUnion__%s__defined */\n", ServerSubsys
);
476 WriteDispatcher(FILE *file
, statement_t
*stats
)
479 * Write the subsystem stuff.
482 WriteSubsystem(file
, stats
);
485 * Then, the server routine
487 fprintf(file
, "mig_external boolean_t %s\n", ServerDemux
);
489 fprintf(file
, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
492 fprintf(file
, "#if\t%s\n", NewCDecl
);
493 fprintf(file
, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
494 fprintf(file
, "#else\n");
495 fprintf(file
, "\t(InHeadP, OutHeadP)\n");
496 fprintf(file
, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n");
497 fprintf(file
, "#endif\t/* %s */\n", NewCDecl
);
500 fprintf(file
, "{\n");
501 fprintf(file
, "\t/*\n");
502 fprintf(file
, "\t * typedef struct {\n");
503 fprintf(file
, "\t * \tmach_msg_header_t Head;\n");
504 fprintf(file
, "\t * \tNDR_record_t NDR;\n");
505 fprintf(file
, "\t * \tkern_return_t RetCode;\n");
506 fprintf(file
, "\t * } mig_reply_error_t;\n");
507 fprintf(file
, "\t */\n");
510 fprintf(file
, "\tmig_routine_t routine;\n");
513 fprintf(file
, "\tOutHeadP->msgh_bits = ");
514 fprintf(file
, "MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0);\n");
515 fprintf(file
, "\tOutHeadP->msgh_remote_port = InHeadP->msgh_reply_port;\n");
516 fprintf(file
, "\t/* Minimal size: routine() will update it if different */\n");
517 fprintf(file
, "\tOutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);\n");
518 fprintf(file
, "\tOutHeadP->msgh_local_port = MACH_PORT_NULL;\n");
519 fprintf(file
, "\tOutHeadP->msgh_id = InHeadP->msgh_id + 100;\n");
520 fprintf(file
, "\tOutHeadP->msgh_reserved = 0;\n");
523 fprintf(file
, "\tif ((InHeadP->msgh_id > %d) || (InHeadP->msgh_id < %d) ||\n", SubsystemBase
+ rtNumber
- 1, SubsystemBase
);
524 fprintf(file
, "\t ((routine = %s.routine[InHeadP->msgh_id - %d].stub_routine) == 0)) {\n", ServerSubsys
, SubsystemBase
);
525 fprintf(file
, "\t\t((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;\n");
526 fprintf(file
, "\t\t((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;\n");
527 if (UseEventLogger
) {
528 fprintf(file
, "#if MIG_DEBUG\n");
529 fprintf(file
, "\t\tLOG_ERRORS(MACH_MSG_LOG_SERVER, MACH_MSG_ERROR_UNKNOWN_ID,\n");
530 fprintf(file
, "\t\t\t&InHeadP->msgh_id, __FILE__, __LINE__);\n");
531 fprintf(file
, "#endif /* MIG_DEBUG */\n");
533 fprintf(file
, "\t\treturn FALSE;\n");
534 fprintf(file
, "\t}\n");
536 /* Call appropriate routine */
537 fprintf(file
, "\t(*routine) (InHeadP, OutHeadP);\n");
538 fprintf(file
, "\treturn TRUE;\n");
539 fprintf(file
, "}\n");
543 * Then, the <subsystem>_server_routine routine
545 fprintf(file
, "mig_external mig_routine_t %s_routine\n", ServerDemux
);
547 fprintf(file
, "\t(mach_msg_header_t *InHeadP)\n");
550 fprintf(file
, "#if\t%s\n", NewCDecl
);
551 fprintf(file
, "\t(mach_msg_header_t *InHeadP)\n");
552 fprintf(file
, "#else\n");
553 fprintf(file
, "\t(InHeadP)\n");
554 fprintf(file
, "\tmach_msg_header_t *InHeadP;\n");
555 fprintf(file
, "#endif\t/* %s */\n", NewCDecl
);
558 fprintf(file
, "{\n");
559 fprintf(file
, "\tint msgh_id;\n");
561 fprintf(file
, "\tmsgh_id = InHeadP->msgh_id - %d;\n", SubsystemBase
);
563 fprintf(file
, "\tif ((msgh_id > %d) || (msgh_id < 0))\n", rtNumber
- 1);
564 fprintf(file
, "\t\treturn 0;\n");
566 fprintf(file
, "\treturn %s.routine[msgh_id].stub_routine;\n", ServerSubsys
);
567 fprintf(file
, "}\n");
572 fprintf(file
,"\nmig_symtab_t _%sSymTab[] = {\n",SubsystemName
);
573 WriteSymTabEntries(file
,stats
);
574 fprintf(file
,"};\n");
575 fprintf(file
,"int _%sSymTabBase = %d;\n",SubsystemName
,SubsystemBase
);
576 fprintf(file
,"int _%sSymTabEnd = %d;\n",SubsystemName
,SubsystemBase
+rtNumber
);
580 #if NOT_CURRENTLY_USED
582 * Returns the return type of the server-side work function.
583 * Suitable for "extern %s serverfunc()".
586 ServerSideType(routine_t
*rt
)
588 return rt
->rtRetCode
->argType
->itTransType
;
590 #endif /* NOT_CURRENTLY_USED */
593 WriteRetCode(FILE *file
, argument_t
*ret
)
595 ipc_type_t
*it
= ret
->argType
;
597 if (akCheck(ret
->argKind
, akbVarNeeded
)) {
598 fprintf(file
, "\t%s %s;\n", it
->itTransType
, ret
->argVarName
);
603 WriteLocalVarDecl(FILE *file
, argument_t
*arg
)
605 ipc_type_t
*it
= arg
->argType
;
606 ipc_type_t
*btype
= it
->itElement
;
608 if (IS_VARIABLE_SIZED_UNTYPED(it
))
609 fprintf(file
, "\t%s %s[%d]", btype
->itTransType
, arg
->argVarName
, btype
->itNumber
? it
->itNumber
/btype
->itNumber
: 0);
610 else if (IS_MULTIPLE_KPD(it
)) {
611 if (btype
->itTransType
!= strNULL
)
612 fprintf(file
, "\t%s %s[%d]", btype
->itTransType
, arg
->argVarName
, it
->itKPD_Number
);
614 /* arrays of ool or oolport */
615 fprintf(file
, "\tvoid *%s[%d]", arg
->argVarName
, it
->itKPD_Number
);
618 fprintf(file
, "\t%s %s", it
->itTransType
, arg
->argVarName
);
621 #if NOT_CURRENTLY_USED
623 WriteServerArgDecl(FILE *file
, argument_t
*arg
)
625 fprintf(file
, "%s %s%s", arg
->argType
->itTransType
, arg
->argByReferenceServer
? "*" : "", arg
->argVarName
);
627 #endif /* NOT_CURRENTLY_USED */
630 * Writes the local variable declarations which are always
631 * present: InP, OutP, the server-side work function.
634 WriteVarDecls(FILE *file
, routine_t
*rt
)
638 fprintf(file
, "\tRequest *In0P = (Request *) InHeadP;\n");
639 for (i
= 1; i
<= rt
->rtMaxRequestPos
; i
++)
640 fprintf(file
, "\tRequest *In%dP;\n", i
);
641 fprintf(file
, "\tReply *OutP = (Reply *) OutHeadP;\n");
643 /* if reply is variable, we may need msgh_size_delta and msgh_size */
644 if (rt
->rtNumReplyVar
> 1)
645 fprintf(file
, "\tunsigned int msgh_size;\n");
646 if (rt
->rtMaxReplyPos
> 0)
647 fprintf(file
, "\tunsigned int msgh_size_delta;\n");
648 if (rt
->rtNumReplyVar
> 1 || rt
->rtMaxReplyPos
> 0)
651 if (rt
->rtServerImpl
) {
652 fprintf(file
, "\tmach_msg_max_trailer_t *TrailerP;\n");
653 fprintf(file
, "#if\t__MigTypeCheck\n");
654 fprintf(file
, "\tunsigned int trailer_size __attribute__((unused));\n");
655 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
657 fprintf(file
, "#ifdef\t__MIG_check__Request__%s_t__defined\n", rt
->rtName
);
658 fprintf(file
, "\tkern_return_t check_result;\n");
659 fprintf(file
, "#endif\t/* __MIG_check__Request__%s_t__defined */\n", rt
->rtName
);
664 WriteReplyInit(FILE *file
, routine_t
*rt
)
667 if (rt
->rtNumReplyVar
> 1 || rt
->rtMaxReplyPos
)
668 /* WritheAdjustMsgSize() has been executed at least once! */
669 fprintf(file
, "\tOutP = (Reply *) OutHeadP;\n");
671 if (!rt
->rtSimpleReply
) /* complex reply message */
672 fprintf(file
, "\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n");
674 if (rt
->rtNumReplyVar
== 0) {
675 fprintf(file
, "\tOutP->Head.msgh_size = ");
676 rtMinReplySize(file
, rt
, "Reply");
677 fprintf(file
, ";\n");
679 else if (rt
->rtNumReplyVar
> 1)
680 fprintf(file
, "\tOutP->Head.msgh_size = msgh_size;\n");
681 /* the case rt->rtNumReplyVar = 1 is taken care of in WriteAdjustMsgSize() */
685 WriteRetCArgCheckError(FILE *file
, routine_t
*rt
)
687 fprintf(file
, "\tif (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&\n");
688 fprintf(file
, "\t (In0P->Head.msgh_size == (mach_msg_size_t)sizeof(mig_reply_error_t)))\n");
689 fprintf(file
, "\t{\n");
693 WriteRetCArgFinishError(FILE *file
, routine_t
*rt
)
695 argument_t
*retcode
= rt
->rtRetCArg
;
697 fprintf(file
, "\treturn;\n");
698 fprintf(file
, "\t}\n");
699 retcode
->argMsgField
= "KERN_SUCCESS";
703 WriteCheckHead(FILE *file
, routine_t
*rt
)
705 fprintf(file
, "#if\t__MigTypeCheck\n");
706 if (rt
->rtNumRequestVar
> 0)
707 fprintf(file
, "\tmsgh_size = In0P->Head.msgh_size;\n");
709 if (rt
->rtSimpleRequest
) {
710 /* Expecting a simple message. */
711 fprintf(file
, "\tif ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
712 if (rt
->rtNumRequestVar
> 0) {
713 fprintf(file
, "\t (msgh_size < ");
714 rtMinRequestSize(file
, rt
, "__Request");
715 fprintf(file
, ") || (msgh_size > (mach_msg_size_t)sizeof(__Request)))\n");
718 fprintf(file
, "\t (In0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Request)))\n");
721 /* Expecting a complex message. */
723 fprintf(file
, "\tif (");
724 if (rt
->rtRetCArg
!= argNULL
)
726 fprintf(file
, "!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
727 fprintf(file
, "\t (In0P->msgh_body.msgh_descriptor_count != %d) ||\n", rt
->rtRequestKPDs
);
728 if (rt
->rtNumRequestVar
> 0) {
729 fprintf(file
, "\t (msgh_size < ");
730 rtMinRequestSize(file
, rt
, "__Request");
731 fprintf(file
, ") || (msgh_size > (mach_msg_size_t)sizeof(__Request))");
734 fprintf(file
, "\t (In0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Request))");
735 if (rt
->rtRetCArg
== argNULL
)
736 fprintf(file
, ")\n");
738 fprintf(file
, ") &&\n");
739 fprintf(file
, "\t ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
740 fprintf(file
, "\t In0P->Head.msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||\n");
741 fprintf(file
, "\t ((mig_reply_error_t *)In0P)->RetCode == KERN_SUCCESS))\n");
744 fprintf(file
, "\t\treturn MIG_BAD_ARGUMENTS;\n");
745 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
750 WriteRequestNDRConvertIntRepArgCond(FILE *file
, argument_t
*arg
)
752 routine_t
*rt
= arg
->argRoutine
;
754 fprintf(file
, "defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)", rt
->rtName
, arg
->argMsgField
);
758 WriteRequestNDRConvertCharRepArgCond(FILE *file
, argument_t
*arg
)
760 routine_t
*rt
= arg
->argRoutine
;
762 if (akIdent(arg
->argKind
) != akeCount
&& akIdent(arg
->argKind
) != akeCountInOut
)
763 fprintf(file
, "defined(__NDR_convert__char_rep__Request__%s_t__%s__defined)", rt
->rtName
, arg
->argMsgField
);
769 WriteRequestNDRConvertFloatRepArgCond(FILE *file
, argument_t
*arg
)
771 routine_t
*rt
= arg
->argRoutine
;
773 if (akIdent(arg
->argKind
) != akeCount
&& akIdent(arg
->argKind
) != akeCountInOut
)
774 fprintf(file
, "defined(__NDR_convert__float_rep__Request__%s_t__%s__defined)", rt
->rtName
, arg
->argMsgField
);
780 WriteRequestNDRConvertIntRepArgDecl(FILE *file
, argument_t
*arg
)
782 WriteNDRConvertArgDecl(file
, arg
, "int_rep", "Request");
786 WriteRequestNDRConvertCharRepArgDecl(FILE *file
, argument_t
*arg
)
788 if (akIdent(arg
->argKind
) != akeCount
&& akIdent(arg
->argKind
) != akeCountInOut
)
789 WriteNDRConvertArgDecl(file
, arg
, "char_rep", "Request");
793 WriteRequestNDRConvertFloatRepArgDecl(FILE *file
, argument_t
*arg
)
795 if (akIdent(arg
->argKind
) != akeCount
&& akIdent(arg
->argKind
) != akeCountInOut
)
796 WriteNDRConvertArgDecl(file
, arg
, "float_rep", "Request");
800 WriteRequestNDRConvertArgUse(FILE *file
, argument_t
*arg
, char *convert
)
802 routine_t
*rt
= arg
->argRoutine
;
803 argument_t
*count
= arg
->argCount
;
804 char argname
[MAX_STR_LEN
];
806 if ((akIdent(arg
->argKind
) == akeCount
|| akIdent(arg
->argKind
) == akeCountInOut
) &&
807 (arg
->argParent
&& akCheck(arg
->argParent
->argKind
, akbSendNdr
)))
810 if (arg
->argKPD_Type
== MACH_MSG_OOL_DESCRIPTOR
) {
811 if (count
&& !arg
->argSameCount
&& !strcmp(convert
, "int_rep")) {
812 fprintf(file
, "#if defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)\n", rt
->rtName
, count
->argMsgField
);
813 fprintf(file
, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&In%dP->%s, In%dP->NDR.int_rep);\n", rt
->rtName
, count
->argMsgField
, count
->argRequestPos
, count
->argMsgField
, count
->argRequestPos
);
814 fprintf(file
, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt
->rtName
, count
->argMsgField
);
817 sprintf(argname
, "(%s)(In%dP->%s.address)", FetchServerType(arg
->argType
), arg
->argRequestPos
, arg
->argMsgField
);
820 sprintf(argname
, "&In%dP->%s", arg
->argRequestPos
, arg
->argMsgField
);
823 fprintf(file
, "#if defined(__NDR_convert__%s__Request__%s_t__%s__defined)\n", convert
, rt
->rtName
, arg
->argMsgField
);
824 fprintf(file
, "\t\t__NDR_convert__%s__Request__%s_t__%s(%s, In0P->NDR.%s", convert
, rt
->rtName
, arg
->argMsgField
, argname
, convert
);
826 fprintf(file
, ", In%dP->%s", count
->argRequestPos
, count
->argMsgField
);
827 fprintf(file
, ");\n");
828 fprintf(file
, "#endif\t/* __NDR_convert__%s__Request__%s_t__%s__defined */\n", convert
, rt
->rtName
, arg
->argMsgField
);
832 WriteRequestNDRConvertIntRepOneArgUse(FILE *file
, argument_t
*arg
)
834 routine_t
*rt
= arg
->argRoutine
;
836 fprintf(file
, "#if defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)\n", rt
->rtName
, arg
->argMsgField
);
837 fprintf(file
, "\tif (In0P->NDR.int_rep != NDR_record.int_rep)\n");
838 fprintf(file
, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&In%dP->%s, In%dP->NDR.int_rep);\n", rt
->rtName
, arg
->argMsgField
, arg
->argRequestPos
, arg
->argMsgField
, arg
->argRequestPos
);
839 fprintf(file
, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt
->rtName
, arg
->argMsgField
);
843 WriteRequestNDRConvertIntRepArgUse(FILE *file
, argument_t
*arg
)
845 WriteRequestNDRConvertArgUse(file
, arg
, "int_rep");
849 WriteRequestNDRConvertCharRepArgUse(FILE *file
, argument_t
*arg
)
851 if (akIdent(arg
->argKind
) != akeCount
&& akIdent(arg
->argKind
) != akeCountInOut
)
852 WriteRequestNDRConvertArgUse(file
, arg
, "char_rep");
856 WriteRequestNDRConvertFloatRepArgUse(FILE *file
, argument_t
*arg
)
858 if (akIdent(arg
->argKind
) != akeCount
&& akIdent(arg
->argKind
) != akeCountInOut
)
859 WriteRequestNDRConvertArgUse(file
, arg
, "float_rep");
863 WriteCalcArgSize(FILE *file
, argument_t
*arg
)
865 ipc_type_t
*ptype
= arg
->argType
;
867 if (PackMsg
== FALSE
) {
868 fprintf(file
, "%d", ptype
->itTypeSize
+ ptype
->itPadSize
);
872 if (IS_OPTIONAL_NATIVE(ptype
))
873 fprintf(file
, "(In%dP->__Present__%s ? _WALIGNSZ_(%s) : 0)" , arg
->argRequestPos
, arg
->argMsgField
, ptype
->itServerType
);
875 ipc_type_t
*btype
= ptype
->itElement
;
876 argument_t
*count
= arg
->argCount
;
877 int multiplier
= btype
->itTypeSize
;
879 if (btype
->itTypeSize
% itWordAlign
!= 0)
880 fprintf(file
, "_WALIGN_");
884 fprintf(file
, "%d * ", multiplier
);
885 fprintf(file
, "In%dP->%s", count
->argRequestPos
, count
->argMsgField
);
891 WriteCheckArgSize(FILE *file
, routine_t
*rt
, argument_t
*arg
, const char *comparator
)
893 ipc_type_t
*ptype
= arg
->argType
;
896 fprintf(file
, "\tif (((msgh_size - ");
897 rtMinRequestSize(file
, rt
, "__Request");
899 if (PackMsg
== FALSE
) {
900 fprintf(file
, "%s %d)", comparator
, ptype
->itTypeSize
+ ptype
->itPadSize
);
901 } else if (IS_OPTIONAL_NATIVE(ptype
)) {
902 fprintf(file
, "%s (In%dP->__Present__%s ? _WALIGNSZ_(%s) : 0))" , comparator
, arg
->argRequestPos
, arg
->argMsgField
, ptype
->itServerType
);
904 ipc_type_t
*btype
= ptype
->itElement
;
905 argument_t
*count
= arg
->argCount
;
906 int multiplier
= btype
->itTypeSize
;
909 fprintf(file
, "/ %d ", multiplier
);
910 fprintf(file
, "< In%dP->%s) ||\n", count
->argRequestPos
, count
->argMsgField
);
911 fprintf(file
, "\t (msgh_size %s ", comparator
);
912 rtMinRequestSize(file
, rt
, "__Request");
913 fprintf(file
, " + ");
914 WriteCalcArgSize(file
, arg
);
917 fprintf(file
, ")\n\t\treturn MIG_BAD_ARGUMENTS;\n");
921 WriteCheckMsgSize(FILE *file
, argument_t
*arg
)
923 routine_t
*rt
= arg
->argRoutine
;
924 ipc_type_t
*it
= arg
->argType
;
925 ipc_type_t
*btype
= it
->itElement
;
927 if (arg
->argCount
&& !arg
->argSameCount
)
928 WriteRequestNDRConvertIntRepOneArgUse(file
, arg
->argCount
);
929 if (arg
->argRequestPos
== rt
->rtMaxRequestPos
) {
930 fprintf(file
, "#if\t__MigTypeCheck\n");
932 /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */
933 fprintf(file
, "\t" "if ( In%dP->%s > %d )\n", arg
->argCount
->argRequestPos
,
934 arg
->argCount
->argMsgField
, it
->itNumber
/btype
->itNumber
);
935 fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file
);
938 WriteCheckArgSize(file
, rt
, arg
, "!=");
940 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
943 /* If there aren't any more variable-sized arguments after this,
944 then we must check for exact msg-size and we don't need to
947 boolean_t LastVarArg
= arg
->argRequestPos
+1 == rt
->rtNumRequestVar
;
949 /* calculate the actual size in bytes of the data field. note
950 that this quantity must be a multiple of four. hence, if
951 the base type size isn't a multiple of four, we have to
952 round up. note also that btype->itNumber must
953 divide btype->itTypeSize (see itCalculateSizeInfo). */
955 fprintf(file
, "\tmsgh_size_delta = ");
956 WriteCalcArgSize(file
, arg
);
957 fprintf(file
, ";\n");
958 fprintf(file
, "#if\t__MigTypeCheck\n");
960 /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */
961 fprintf(file
, "\t" "if ( In%dP->%s > %d )\n", arg
->argCount
->argRequestPos
,
962 arg
->argCount
->argMsgField
, it
->itNumber
/btype
->itNumber
);
963 fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file
);
966 /* Don't decrement msgh_size until we've checked that
967 it won't underflow. */
968 WriteCheckArgSize(file
, rt
, arg
, LastVarArg
? "!=" : "<");
971 fprintf(file
, "\tmsgh_size -= msgh_size_delta;\n");
973 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
979 InArgMsgField(argument_t
*arg
, char *str
)
981 static char buffer
[MAX_STR_LEN
];
985 * Inside the kernel, the request and reply port fields
986 * really hold ipc_port_t values, not mach_port_t values.
987 * Hence we must cast the values.
990 if (!(arg
->argFlags
& flRetCode
)) {
991 if (akCheck(arg
->argKind
, akbServerImplicit
))
992 sprintf(who
, "TrailerP->");
994 sprintf(who
, "In%dP->", arg
->argRequestPos
);
997 #ifdef MIG_KERNEL_PORT_CONVERSION
998 if (IsKernelServer
&&
999 ((akIdent(arg
->argKind
) == akeRequestPort
) ||
1000 (akIdent(arg
->argKind
) == akeReplyPort
)))
1001 sprintf(buffer
, "(ipc_port_t) %s%s%s", who
, str
, (arg
->argSuffix
!= strNULL
) ? arg
->argSuffix
: arg
->argMsgField
);
1004 sprintf(buffer
, "%s%s%s", who
, str
, (arg
->argSuffix
!= strNULL
) ? arg
->argSuffix
: arg
->argMsgField
);
1010 WriteExtractArgValue(FILE *file
, argument_t
*arg
)
1012 ipc_type_t
*it
= arg
->argType
;
1015 #ifdef MIG_KERNEL_PORT_CONVERSION
1016 if (IsKernelServer
&& it
->itPortType
&& streql(it
->itServerType
, "ipc_port_t")
1017 && akIdent(arg
->argKind
) != akeRequestPort
1018 && akIdent(arg
->argKind
) != akeReplyPort
)
1019 recast
= "(mach_port_t)";
1023 if (it
->itInTrans
!= strNULL
)
1024 WriteCopyType(file
, it
, FALSE
, "%s", "/* %s */ %s(%s%s)", arg
->argVarName
, it
->itInTrans
, recast
, InArgMsgField(arg
, ""));
1026 WriteCopyType(file
, it
, FALSE
, "%s", "/* %s */ %s%s", arg
->argVarName
, recast
, InArgMsgField(arg
, ""));
1028 fprintf(file
, "\n");
1032 * argKPD_Extract discipline for Port types.
1035 WriteExtractKPD_port(FILE *file
, argument_t
*arg
)
1037 ipc_type_t
*it
= arg
->argType
;
1040 WriteKPD_Iterator(file
, TRUE
, it
->itVarArray
, arg
, FALSE
);
1041 /* translation function do not apply to complex types */
1042 #ifdef MIG_KERNEL_PORT_CONVERSION
1044 recast
= "(mach_port_t)";
1046 fprintf(file
, "\t\t%s[i] = %sptr->name;\n", arg
->argVarName
, recast
);
1047 fprintf(file
, "\t}\n");
1051 * argKPD_Extract discipline for out-of-line types.
1054 WriteExtractKPD_ool(FILE *file
, argument_t
*arg
)
1056 ipc_type_t
*it
= arg
->argType
;
1058 WriteKPD_Iterator(file
, TRUE
, it
->itVarArray
, arg
, FALSE
);
1059 fprintf(file
, "\t\t%s[i] = ptr->address;\n", arg
->argVarName
);
1060 fprintf(file
, "\t}\n");
1064 * argKPD_Extract discipline for out-of-line Port types.
1067 WriteExtractKPD_oolport(FILE *file
, argument_t
*arg
)
1069 ipc_type_t
*it
= arg
->argType
;
1071 WriteKPD_Iterator(file
, TRUE
, it
->itVarArray
, arg
, FALSE
);
1072 fprintf(file
, "\t\t%s[i] = ptr->address;\n", arg
->argVarName
);
1073 fprintf(file
, "\t}\n");
1074 if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbSendRcv
)) {
1075 argument_t
*poly
= arg
->argPoly
;
1076 char *pref
= poly
->argByReferenceServer
? "*" : "";
1078 fprintf(file
, "\t%s%s = In%dP->%s[0].disposition;\n", pref
, poly
->argVarName
, arg
->argRequestPos
, arg
->argMsgField
);
1084 WriteInitializeCount(FILE *file
, argument_t
*arg
)
1086 ipc_type_t
*ptype
= arg
->argParent
->argType
;
1087 ipc_type_t
*btype
= ptype
->itElement
;
1088 identifier_t newstr
;
1091 * Initialize 'count' argument for variable-length inline OUT parameter
1092 * with maximum allowed number of elements.
1095 if (akCheck(arg
->argKind
, akbVarNeeded
))
1096 newstr
= arg
->argMsgField
;
1098 newstr
= (identifier_t
)strconcat("OutP->", arg
->argMsgField
);
1100 fprintf(file
, "\t%s = ", newstr
);
1101 if (IS_MULTIPLE_KPD(ptype
))
1102 fprintf(file
, "%d;\n", ptype
->itKPD_Number
);
1104 fprintf(file
, "%d;\n", btype
->itNumber
? ptype
->itNumber
/btype
->itNumber
: 0);
1107 * If the user passed in a count, then we use the minimum.
1108 * We can't let the user completely override our maximum,
1109 * or the user might convince the server to overwrite the buffer.
1112 if (arg
->argCInOut
!= argNULL
) {
1113 char *msgfield
= InArgMsgField(arg
->argCInOut
, "");
1115 fprintf(file
, "\tif (%s < %s)\n", msgfield
, newstr
);
1116 fprintf(file
, "\t\t%s = %s;\n", newstr
, msgfield
);
1119 fprintf(file
, "\n");
1123 WriteAdjustRequestMsgPtr(FILE *file
, argument_t
*arg
)
1125 ipc_type_t
*ptype
= arg
->argType
;
1127 if (PackMsg
== FALSE
) {
1128 fprintf(file
, "\t*In%dPP = In%dP = (__Request *) ((pointer_t) In%dP);\n\n", arg
->argRequestPos
+1, arg
->argRequestPos
+1, arg
->argRequestPos
);
1132 fprintf(file
, "\t*In%dPP = In%dP = (__Request *) ((pointer_t) In%dP + msgh_size_delta - ", arg
->argRequestPos
+1, arg
->argRequestPos
+1, arg
->argRequestPos
);
1133 if (IS_OPTIONAL_NATIVE(ptype
))
1134 fprintf(file
, "_WALIGNSZ_(%s)", ptype
->itUserType
);
1136 fprintf(file
, "%d", ptype
->itTypeSize
+ ptype
->itPadSize
);
1137 fprintf(file
, ");\n\n");
1141 WriteCheckRequestTrailerArgs(FILE *file
, routine_t
*rt
)
1145 if (rt
->rtServerImpl
)
1146 WriteCheckTrailerHead(file
, rt
, FALSE
);
1148 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
1149 if (akCheck(arg
->argKind
, akbServerImplicit
))
1150 WriteCheckTrailerSize(file
, FALSE
, arg
);
1155 WriteExtractArg(FILE *file
, argument_t
*arg
)
1157 if (akCheckAll(arg
->argKind
, akbSendRcv
|akbVarNeeded
)) {
1158 if (akCheck(arg
->argKind
, akbSendKPD
))
1159 (*arg
->argKPD_Extract
)(file
, arg
);
1161 WriteExtractArgValue(file
, arg
);
1164 if ((akIdent(arg
->argKind
) == akeCount
) &&
1165 akCheck(arg
->argKind
, akbReturnSnd
)) {
1167 ipc_type_t
*ptype
= arg
->argParent
->argType
;
1169 * the count will be initialized to 0 in the case of
1170 * unbounded arrays (MigInLine = TRUE): this is because
1171 * the old interface used to pass to the target procedure
1172 * the maximum in-line size (it was 2048 bytes)
1174 if (IS_VARIABLE_SIZED_UNTYPED(ptype
) ||
1175 IS_MIG_INLINE_EMUL(ptype
) ||
1176 (IS_MULTIPLE_KPD(ptype
) && ptype
->itVarArray
))
1177 WriteInitializeCount(file
, arg
);
1182 WriteServerCallArg(FILE *file
, argument_t
*arg
)
1184 ipc_type_t
*it
= arg
->argType
;
1185 boolean_t NeedClose
= FALSE
;
1187 string_t at
= (arg
->argByReferenceServer
||
1188 it
->itNativePointer
) ? "&" : "";
1189 string_t star
= (arg
->argByReferenceServer
) ? " *" : "";
1191 (arg
->argSuffix
!= strNULL
) ? arg
->argSuffix
: arg
->argMsgField
;
1193 if ((it
->itInTrans
!= strNULL
) &&
1194 akCheck(arg
->argKind
, akbSendRcv
) &&
1195 !akCheck(arg
->argKind
, akbVarNeeded
)) {
1196 fprintf(file
, "%s%s(", at
, it
->itInTrans
);
1200 if (akCheckAll(arg
->argKind
, akbVarNeeded
|akbServerArg
))
1201 fprintf(file
, "%s%s", at
, arg
->argVarName
);
1202 else if (akCheckAll(arg
->argKind
, akbSendRcv
|akbSendKPD
)) {
1204 /* recast the void *, although it is not necessary */
1205 fprintf(file
, "(%s%s)%s(%s)", it
->itTransType
, star
, at
, InArgMsgField(arg
, ""));
1207 #ifdef MIG_KERNEL_PORT_CONVERSION
1208 if (IsKernelServer
&& streql(it
->itServerType
, "ipc_port_t"))
1209 /* recast the port to the kernel internal form value */
1210 fprintf(file
, "(ipc_port_t%s)%s(%s)", star
, at
, InArgMsgField(arg
, ""));
1213 fprintf(file
, "%s%s", at
, InArgMsgField(arg
, ""));
1215 else if (akCheck(arg
->argKind
, akbSendRcv
)) {
1216 if (IS_OPTIONAL_NATIVE(it
)) {
1217 fprintf(file
, "(%s ? ", InArgMsgField(arg
, "__Present__"));
1218 fprintf(file
, "%s%s.__Real__%s : %s)", at
, InArgMsgField(arg
, ""), arg
->argMsgField
, it
->itBadValue
);
1221 if (akIdent(arg
->argKind
) == akeCount
&& arg
->argParent
) {
1222 char *suffix
= arg
->argParent
->argSuffix
;
1223 ipc_type_t
*elemType
= arg
->argParent
->argType
->itElement
;
1224 /* temporarily squash any name suffix such as ".address" (we'll be adding our own) */
1225 arg
->argParent
->argSuffix
= NULL
;
1226 switch (arg
->argParent
->argKPD_Type
) {
1227 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
1228 /* count of the number of descriptors */
1229 fprintf(file
, "%s%s.count", at
, InArgMsgField(arg
->argParent
, ""));
1231 case MACH_MSG_OOL_DESCRIPTOR
:
1232 /* descriptor buffer size / element size */
1233 if (!(arg
->argByReferenceServer
|| it
->itNativePointer
)) {
1234 fprintf(file
, "%s%s.size", at
, InArgMsgField(arg
->argParent
, ""));
1235 elemsize
= ((elemType
->itNumber
* elemType
->itSize
) + 7) / 8;
1237 fprintf(file
, " / %d", elemsize
);
1240 fprintf(file
, "%s%s", at
, InArgMsgField(arg
, ""));
1244 fprintf(file
, "%s%s", at
, InArgMsgField(arg
, ""));
1247 arg
->argParent
->argSuffix
= suffix
;
1249 fprintf(file
, "%s%s", at
, InArgMsgField(arg
, ""));
1253 else if (akCheckAll(arg
->argKind
, akbReturnSnd
|akbReturnKPD
)) {
1255 /* recast the void *, although it is not necessary */
1256 fprintf(file
, "(%s%s)%s(OutP->%s)", it
->itTransType
, star
, at
, msgfield
);
1258 #ifdef MIG_KERNEL_PORT_CONVERSION
1259 if (IsKernelServer
&& streql(it
->itServerType
, "ipc_port_t"))
1260 /* recast the port to the kernel internal form value */
1261 fprintf(file
, "(mach_port_t%s)%s(OutP->%s)", star
, at
, msgfield
);
1264 fprintf(file
, "%sOutP->%s", at
, msgfield
);
1267 else if (akCheck(arg
->argKind
, akbReturnSnd
))
1268 fprintf(file
, "%sOutP->%s", at
, msgfield
);
1275 * Shrunk version of WriteServerCallArg, to implement the RetCode functionality:
1276 * we have received a mig_reply_error_t, therefore we want to call the target
1277 * routine with all 0s except for the error code (and the implicit data).
1278 * We know that we are a SimpleRoutine.
1281 WriteConditionalCallArg(FILE *file
, argument_t
*arg
)
1283 ipc_type_t
*it
= arg
->argType
;
1284 boolean_t NeedClose
= FALSE
;
1286 if ((it
->itInTrans
!= strNULL
) &&
1287 akCheck(arg
->argKind
, akbSendRcv
) &&
1288 !akCheck(arg
->argKind
, akbVarNeeded
)) {
1289 fprintf(file
, "%s(", it
->itInTrans
);
1293 if (akCheck(arg
->argKind
, akbSendRcv
)) {
1294 if (akIdent(arg
->argKind
) == akeRequestPort
||
1295 akCheck(arg
->argKind
, akbServerImplicit
))
1296 fprintf(file
, "%s", InArgMsgField(arg
, ""));
1297 else if (akIdent(arg
->argKind
) == akeRetCode
)
1298 fprintf(file
, "((mig_reply_error_t *)In0P)->RetCode");
1300 fprintf(file
, "(%s)(0)", it
->itTransType
);
1308 WriteDestroyArg(FILE *file
, argument_t
*arg
)
1310 ipc_type_t
*it
= arg
->argType
;
1313 * Deallocate IN/INOUT out-of-line args if specified by "auto" flag.
1315 * We also have to deallocate in the cases where the target routine
1316 * is given a itInLine semantic whereas the underlying transmission
1319 if ((argIsIn(arg
) && akCheck(arg
->argKind
, akbSendKPD
|akbReturnKPD
) &&
1320 arg
->argKPD_Type
== MACH_MSG_OOL_DESCRIPTOR
&&
1321 (arg
->argFlags
& flAuto
))
1323 IS_MIG_INLINE_EMUL(it
)
1326 * Deallocate only if out-of-line.
1328 argument_t
*count
= arg
->argCount
;
1329 ipc_type_t
*btype
= it
->itElement
;
1330 int multiplier
= btype
->itNumber
? btype
->itSize
/ (8 * btype
->itNumber
) : 0;
1332 if (IsKernelServer
) {
1333 fprintf(file
, "#if __MigKernelSpecificCode\n");
1334 fprintf(file
, "\tvm_map_copy_discard(%s);\n", InArgMsgField(arg
, ""));
1335 fprintf(file
, "#else\n");
1337 fprintf(file
, "\tmig_deallocate((vm_offset_t) %s, ", InArgMsgField(arg
, ""));
1338 if (it
->itVarArray
) {
1339 char *suffix
= arg
->argSuffix
;
1341 * temporarily squash any name suffix such as ".address"
1342 * (we'll be adding our own)
1344 arg
->argSuffix
= NULL
;
1345 switch (arg
->argKPD_Type
) {
1346 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
1347 if (multiplier
> 1) {
1348 fprintf(file
, "%d * ", multiplier
);
1350 fprintf(file
, "%s.count);\n", InArgMsgField(arg
, ""));
1352 case MACH_MSG_OOL_DESCRIPTOR
:
1353 fprintf(file
, "%s.size);\n", InArgMsgField(arg
, ""));
1356 if (multiplier
> 1) {
1357 fprintf(file
, "%d * ", multiplier
);
1359 fprintf(file
, "%s);\n", InArgMsgField(count
, ""));
1362 arg
->argSuffix
= suffix
;
1365 fprintf(file
, "%d);\n", (it
->itNumber
* it
->itSize
+ 7) / 8);
1366 if (IsKernelServer
) {
1367 fprintf(file
, "#endif /* __MigKernelSpecificCode */\n");
1369 fprintf(file
, "\t%s = (void *) 0;\n", InArgMsgField(arg
, ""));
1370 fprintf(file
, "\tIn%dP->%s.%s = (mach_msg_size_t) 0;\n", arg
->argRequestPos
, arg
->argMsgField
, (RPCPortArray(arg
) ? "count" : "size"));
1373 if (akCheck(arg
->argKind
, akbVarNeeded
))
1374 fprintf(file
, "\t%s(%s);\n", it
->itDestructor
, arg
->argVarName
);
1376 fprintf(file
, "\t%s(%s);\n", it
->itDestructor
, InArgMsgField(arg
, ""));
1381 WriteDestroyPortArg(FILE *file
, argument_t
*arg
)
1383 ipc_type_t
*it
= arg
->argType
;
1386 * If a translated port argument occurs in the body of a request
1387 * message, and the message is successfully processed, then the
1388 * port right should be deallocated. However, the called function
1389 * didn't see the port right; it saw the translation. So we have
1390 * to release the port right for it.
1392 * The test over it->itInTrans will exclude any complex type
1395 if ((it
->itInTrans
!= strNULL
) &&
1396 (it
->itOutName
== MACH_MSG_TYPE_PORT_SEND
)) {
1397 fprintf(file
, "\n");
1398 fprintf(file
, "\tif (IP_VALID((ipc_port_t)%s))\n", InArgMsgField(arg
, ""));
1399 fprintf(file
, "\t\tipc_port_release_send((ipc_port_t)%s);\n", InArgMsgField(arg
, ""));
1404 * Check whether WriteDestroyPortArg would generate any code for arg.
1407 CheckDestroyPortArg(argument_t
*arg
)
1409 ipc_type_t
*it
= arg
->argType
;
1411 if ((it
->itInTrans
!= strNULL
) &&
1412 (it
->itOutName
== MACH_MSG_TYPE_PORT_SEND
)) {
1419 WriteServerCall(FILE *file
, routine_t
*rt
, void (*func
)(FILE *, argument_t
*))
1421 argument_t
*arg
= rt
->rtRetCode
;
1422 ipc_type_t
*it
= arg
->argType
;
1423 boolean_t NeedClose
= FALSE
;
1425 fprintf(file
, "\t");
1426 if (akCheck(arg
->argKind
, akbVarNeeded
))
1427 fprintf(file
, "%s = ", arg
->argMsgField
);
1429 fprintf(file
, "OutP->%s = ", arg
->argMsgField
);
1430 if (it
->itOutTrans
!= strNULL
) {
1431 fprintf(file
, "%s(", it
->itOutTrans
);
1434 fprintf(file
, "%s(", rt
->rtServerName
);
1435 WriteList(file
, rt
->rtArgs
, func
, akbServerArg
, ", ", "");
1438 fprintf(file
, ");\n");
1442 WriteCheckReturnValue(FILE *file
, routine_t
*rt
)
1444 argument_t
*arg
= rt
->rtRetCode
;
1445 char string
[MAX_STR_LEN
];
1447 if (akCheck(arg
->argKind
, akbVarNeeded
))
1448 sprintf(string
, "%s", arg
->argMsgField
);
1450 sprintf(string
, "OutP->%s", arg
->argMsgField
);
1451 fprintf(file
, "\tif (%s != KERN_SUCCESS) {\n", string
);
1452 fprintf(file
, "\t\tMIG_RETURN_ERROR(OutP, %s);\n", string
);
1453 fprintf(file
, "\t}\n");
1457 * WriteInitKPD_port, WriteInitKPD_ool, WriteInitKPD_oolport
1458 * initializes the OutP KPD fields (this job cannot be done once
1459 * the target routine has been called, otherwise informations
1463 * argKPD_Init discipline for Port types.
1466 WriteInitKPD_port(FILE *file
, argument_t
*arg
)
1468 ipc_type_t
*it
= arg
->argType
;
1469 char *subindex
= "";
1470 boolean_t close
= FALSE
;
1471 char firststring
[MAX_STR_LEN
];
1472 char string
[MAX_STR_LEN
];
1474 if (IS_MULTIPLE_KPD(it
)) {
1475 WriteKPD_Iterator(file
, FALSE
, FALSE
, arg
, TRUE
);
1476 (void)sprintf(firststring
, "\t*ptr");
1477 (void)sprintf(string
, "\tptr->");
1482 (void)sprintf(firststring
, "OutP->%s", arg
->argMsgField
);
1483 (void)sprintf(string
, "OutP->%s.", arg
->argMsgField
);
1486 fprintf(file
, "#if\tUseStaticTemplates\n");
1487 fprintf(file
, "\t%s = %s;\n", firststring
, arg
->argTTName
);
1488 fprintf(file
, "#else\t/* UseStaticTemplates */\n");
1489 if (IS_MULTIPLE_KPD(it
) && it
->itVarArray
)
1490 fprintf(file
, "\t%sname = MACH_PORT_NULL;\n", string
);
1491 if (arg
->argPoly
== argNULL
) {
1492 if (IsKernelServer
) {
1493 fprintf(file
, "#if __MigKernelSpecificCode\n");
1494 fprintf(file
, "\t%sdisposition = %s;\n", string
, it
->itOutNameStr
);
1495 fprintf(file
, "#else\n");
1497 fprintf(file
, "\t%sdisposition = %s;\n", string
, it
->itInNameStr
);
1499 fprintf(file
, "#endif /* __MigKernelSpecificCode */\n");
1501 fprintf(file
, "#if !(defined(KERNEL) && defined(__LP64__))\n");
1502 fprintf(file
, "\t%spad1 = 0;\n", string
);
1503 fprintf(file
, "#endif\n");
1504 fprintf(file
, "\t%spad2 = 0;\n", string
);
1505 fprintf(file
, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string
);
1506 fprintf(file
, "#if defined(KERNEL)\n");
1507 fprintf(file
, "\t%spad_end = 0;\n", string
);
1508 fprintf(file
, "#endif\n");
1509 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
1511 fprintf(file
, "\t }\n\t}\n");
1512 fprintf(file
, "\n");
1516 * argKPD_Init discipline for out-of-line types.
1519 WriteInitKPD_ool(FILE *file
, argument_t
*arg
)
1521 ipc_type_t
*it
= arg
->argType
;
1522 char firststring
[MAX_STR_LEN
];
1523 char string
[MAX_STR_LEN
];
1525 u_int howmany
, howbig
;
1527 if (IS_MULTIPLE_KPD(it
)) {
1528 WriteKPD_Iterator(file
, FALSE
, FALSE
, arg
, TRUE
);
1529 (void)sprintf(firststring
, "\t*ptr");
1530 (void)sprintf(string
, "\tptr->");
1531 VarArray
= it
->itElement
->itVarArray
;
1532 howmany
= it
->itElement
->itNumber
;
1533 howbig
= it
->itElement
->itSize
;
1536 (void)sprintf(firststring
, "OutP->%s", arg
->argMsgField
);
1537 (void)sprintf(string
, "OutP->%s.", arg
->argMsgField
);
1538 VarArray
= it
->itVarArray
;
1539 howmany
= it
->itNumber
;
1540 howbig
= it
->itSize
;
1543 fprintf(file
, "#if\tUseStaticTemplates\n");
1544 fprintf(file
, "\t%s = %s;\n", firststring
, arg
->argTTName
);
1545 fprintf(file
, "#else\t/* UseStaticTemplates */\n");
1547 fprintf(file
, "\t%ssize = %d;\n", string
, (howmany
* howbig
+ 7)/8);
1548 if (arg
->argDeallocate
!= d_MAYBE
)
1549 fprintf(file
, "\t%sdeallocate = %s;\n", string
, (arg
->argDeallocate
== d_YES
) ? "TRUE" : "FALSE");
1550 fprintf(file
, "\t%scopy = %s;\n", string
, (arg
->argFlags
& flPhysicalCopy
) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY");
1552 fprintf(file
, "\t%salignment = MACH_MSG_ALIGN_%d;\n", string
, arg
->argMsgField
, (howbig
< 8) ? 1 : howbig
/ 8);
1554 fprintf(file
, "\t%spad1 = 0;\n", string
);
1555 fprintf(file
, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string
);
1556 fprintf(file
, "#if defined(KERNEL) && !defined(__LP64__)\n");
1557 fprintf(file
, "\t%spad_end = 0;\n", string
);
1558 fprintf(file
, "#endif\n");
1559 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
1561 if (IS_MULTIPLE_KPD(it
))
1562 fprintf(file
, "\t }\n\t}\n");
1563 fprintf(file
, "\n");
1567 * argKPD_Init discipline for out-of-line Port types.
1570 WriteInitKPD_oolport(FILE *file
, argument_t
*arg
)
1572 ipc_type_t
*it
= arg
->argType
;
1576 char firststring
[MAX_STR_LEN
];
1577 char string
[MAX_STR_LEN
];
1579 if (IS_MULTIPLE_KPD(it
)) {
1580 WriteKPD_Iterator(file
, FALSE
, FALSE
, arg
, TRUE
);
1581 (void)sprintf(firststring
, "\t*ptr");
1582 (void)sprintf(string
, "\tptr->");
1583 VarArray
= it
->itElement
->itVarArray
;
1584 howmany
= it
->itElement
->itNumber
;
1585 howit
= it
->itElement
;
1588 (void)sprintf(firststring
, "OutP->%s", arg
->argMsgField
);
1589 (void)sprintf(string
, "OutP->%s.", arg
->argMsgField
);
1590 VarArray
= it
->itVarArray
;
1591 howmany
= it
->itNumber
;
1595 fprintf(file
, "#if\tUseStaticTemplates\n");
1596 fprintf(file
, "\t%s = %s;\n", firststring
, arg
->argTTName
);
1597 fprintf(file
, "#else\t/* UseStaticTemplates */\n");
1600 fprintf(file
, "\t%scount = %d;\n", string
, howmany
);
1601 if (arg
->argPoly
== argNULL
) {
1602 if (IsKernelServer
) {
1603 fprintf(file
, "#if\t__MigKernelSpecificCode\n");
1604 fprintf(file
, "\t%sdisposition = %s;\n", string
, howit
->itOutNameStr
);
1605 fprintf(file
, "#else\n");
1607 fprintf(file
, "\t%sdisposition = %s;\n", string
, howit
->itInNameStr
);
1609 fprintf(file
, "#endif /* __MigKernelSpecificCode */\n");
1611 if (arg
->argDeallocate
!= d_MAYBE
)
1612 fprintf(file
, "\t%sdeallocate = %s;\n", string
, (arg
->argDeallocate
== d_YES
) ? "TRUE" : "FALSE");
1613 fprintf(file
, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string
);
1614 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
1616 if (IS_MULTIPLE_KPD(it
))
1617 fprintf(file
, "\t }\n\t}\n");
1618 fprintf(file
, "\n");
1622 WriteInitKPDValue(FILE *file
, argument_t
*arg
)
1624 (*arg
->argKPD_Init
)(file
, arg
);
1628 WriteAdjustMsgCircular(FILE *file
, argument_t
*arg
)
1630 fprintf(file
, "\n");
1632 fprintf(file
,"#if\t__MigKernelSpecificCode\n");
1633 if (arg
->argType
->itOutName
== MACH_MSG_TYPE_POLYMORPHIC
)
1634 fprintf(file
, "\tif (%s == MACH_MSG_TYPE_PORT_RECEIVE)\n", arg
->argPoly
->argVarName
);
1637 * The carried port right can be accessed in OutP->XXXX. Normally
1638 * the server function stuffs it directly there. If it is InOut,
1639 * then it has already been copied into the reply message.
1640 * If the server function deposited it into a variable (perhaps
1641 * because the reply message is variable-sized) then it has already
1642 * been copied into the reply message.
1644 * The old MiG does not check for circularity in the case of
1645 * array of ports. So do I ...
1648 fprintf(file
, "\t if (IP_VALID((ipc_port_t) In0P->Head.msgh_reply_port) &&\n");
1649 fprintf(file
, "\t IP_VALID((ipc_port_t) OutP->%s.name) &&\n", arg
->argMsgField
);
1650 fprintf(file
, "\t ipc_port_check_circularity((ipc_port_t) OutP->%s.name, (ipc_port_t) In0P->Head.msgh_reply_port))\n", arg
->argMsgField
);
1651 fprintf(file
, "\t\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_CIRCULAR;\n");
1652 fprintf(file
, "#endif /* __MigKernelSpecificCode */\n");
1656 * argKPD_Pack discipline for Port types.
1659 WriteKPD_port(FILE *file
, argument_t
*arg
)
1661 ipc_type_t
*it
= arg
->argType
;
1662 char *subindex
= "";
1664 boolean_t close
= FALSE
;
1665 char string
[MAX_STR_LEN
];
1666 ipc_type_t
*real_it
;
1668 if (akCheck(arg
->argKind
, akbVarNeeded
)) {
1669 if (IS_MULTIPLE_KPD(it
)) {
1670 WriteKPD_Iterator(file
, FALSE
, it
->itVarArray
, arg
, TRUE
);
1671 (void)sprintf(string
, "\tptr->");
1674 real_it
= it
->itElement
;
1677 (void)sprintf(string
, "OutP->%s.", arg
->argMsgField
);
1680 #ifdef MIG_KERNEL_PORT_CONVERSIONS
1681 if (IsKernelServer
&& streql(real_it
->itTransType
, "ipc_port_t"))
1682 recast
= "(mach_port_t)";
1685 if (it
->itOutTrans
!= strNULL
&& !close
)
1686 fprintf(file
, "\t%sname = (mach_port_t)%s(%s);\n", string
, it
->itOutTrans
, arg
->argVarName
);
1688 fprintf(file
, "\t%sname = %s%s%s;\n", string
, recast
, arg
->argVarName
, subindex
);
1689 if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbReturnSnd
)) {
1690 argument_t
*poly
= arg
->argPoly
;
1692 if (akCheck(arg
->argPoly
->argKind
, akbVarNeeded
))
1693 fprintf(file
, "\t%sdisposition = %s;\n", string
, poly
->argVarName
);
1695 fprintf(file
, "\t%sdisposition = OutP->%s;\n", string
, poly
->argSuffix
);
1698 fprintf(file
, "\t }\n\t}\n");
1699 fprintf(file
, "\n");
1701 else if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbReturnSnd
|akbVarNeeded
))
1702 fprintf(file
, "\tOutP->%s.disposition = %s;\n", arg
->argMsgField
, arg
->argPoly
->argVarName
);
1704 * If this is a KernelServer, and the reply message contains
1705 * a receive right, we must check for the possibility of a
1706 * port/message circularity. If queueing the reply message
1707 * would cause a circularity, we mark the reply message
1708 * with the circular bit.
1710 if (IsKernelServer
&& !(IS_MULTIPLE_KPD(it
)) &&
1711 ((arg
->argType
->itOutName
== MACH_MSG_TYPE_PORT_RECEIVE
) ||
1712 (arg
->argType
->itOutName
== MACH_MSG_TYPE_POLYMORPHIC
)))
1713 WriteAdjustMsgCircular(file
, arg
);
1717 * argKPD_Pack discipline for out-of-line types.
1720 WriteKPD_ool(FILE *file
, argument_t
*arg
)
1722 ipc_type_t
*it
= arg
->argType
;
1723 char string
[MAX_STR_LEN
];
1729 if (IS_MULTIPLE_KPD(it
)) {
1730 WriteKPD_Iterator(file
, FALSE
, it
->itVarArray
, arg
, TRUE
);
1731 (void)sprintf(string
, "\tptr->");
1732 VarArray
= it
->itElement
->itVarArray
;
1733 count
= arg
->argSubCount
;
1734 howbig
= it
->itElement
->itSize
;
1738 (void)sprintf(string
, "OutP->%s.", arg
->argMsgField
);
1739 VarArray
= it
->itVarArray
;
1740 count
= arg
->argCount
;
1741 howbig
= it
->itSize
;
1745 if (akCheck(arg
->argKind
, akbVarNeeded
))
1746 fprintf(file
, "\t%saddress = (void *)%s%s;\n", string
, arg
->argMsgField
, subindex
);
1747 if (arg
->argDealloc
!= argNULL
)
1748 if (akCheck(arg
->argDealloc
->argKind
, akbVarNeeded
) || IS_MULTIPLE_KPD(it
))
1749 fprintf(file
, "\t%sdeallocate = %s;\n", string
, arg
->argDealloc
->argVarName
);
1751 fprintf(file
, "\t%ssize = ", string
);
1752 if (akCheck(count
->argKind
, akbVarNeeded
))
1753 fprintf(file
, "%s%s", count
->argName
, subindex
);
1755 fprintf(file
, "OutP->%s%s", count
->argMsgField
, subindex
);
1757 if (count
->argMultiplier
> 1 || howbig
> 8)
1758 fprintf(file
, " * %d;\n", count
->argMultiplier
* howbig
/ 8);
1760 fprintf(file
, ";\n");
1763 if (IS_MULTIPLE_KPD(it
)) {
1764 fprintf(file
, "\t }\n");
1765 if (it
->itVarArray
&& !it
->itElement
->itVarArray
) {
1766 fprintf(file
, "\t for (i = j; i < %d; ptr++, i++)\n", it
->itKPD_Number
);
1767 /* since subordinate arrays aren't variable, they are initialized from template:
1768 here we must no-op 'em */
1769 fprintf(file
, "\t\tptr->size = 0;\n");
1771 fprintf(file
, "\t}\n");
1773 fprintf(file
, "\n");
1777 * argKPD_Pack discipline for out-of-line Port types.
1780 WriteKPD_oolport(FILE *file
, argument_t
*arg
)
1782 ipc_type_t
*it
= arg
->argType
;
1785 char *subindex
, string
[MAX_STR_LEN
];
1787 if (IS_MULTIPLE_KPD(it
)) {
1788 WriteKPD_Iterator(file
, FALSE
, it
->itVarArray
, arg
, TRUE
);
1789 (void)sprintf(string
, "\tptr->");
1790 VarArray
= it
->itElement
->itVarArray
;
1791 count
= arg
->argSubCount
;
1795 (void)sprintf(string
, "OutP->%s.", arg
->argMsgField
);
1796 VarArray
= it
->itVarArray
;
1797 count
= arg
->argCount
;
1801 if (akCheck(arg
->argKind
, akbVarNeeded
))
1802 fprintf(file
, "\t%saddress = (void *)%s%s;\n", string
, arg
->argMsgField
, subindex
);
1803 if (arg
->argDealloc
!= argNULL
)
1804 if (akCheck(arg
->argDealloc
->argKind
, akbVarNeeded
) || IS_MULTIPLE_KPD(it
))
1805 fprintf(file
, "\t%sdeallocate = %s;\n", string
, arg
->argDealloc
->argVarName
);
1807 fprintf(file
, "\t%scount = ", string
);
1808 if (akCheck(count
->argKind
, akbVarNeeded
))
1809 fprintf(file
, "%s%s;\n", count
->argName
, subindex
);
1811 fprintf(file
, "OutP->%s%s;\n", count
->argMsgField
, subindex
);
1813 if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbReturnSnd
))
1814 if (akCheck(arg
->argPoly
->argKind
, akbVarNeeded
) || IS_MULTIPLE_KPD(it
))
1815 fprintf(file
, "\t%sdisposition = %s;\n", string
, arg
->argPoly
->argVarName
);
1816 if (IS_MULTIPLE_KPD(it
)) {
1817 fprintf(file
, "\t }\n");
1818 if (it
->itVarArray
&& !it
->itElement
->itVarArray
) {
1819 fprintf(file
, "\t for (i = j; i < %d; ptr++, i++)\n", it
->itKPD_Number
);
1820 /* since subordinate arrays aren't variable, they are initialized from template:
1821 here we must no-op 'em */
1822 fprintf(file
, "\t%scount = 0;\n", string
);
1824 fprintf(file
, "\t}\n");
1826 fprintf(file
, "\n");
1830 * argKPD_TypeCheck discipline for Port types.
1833 WriteTCheckKPD_port(FILE *file
, argument_t
*arg
)
1835 ipc_type_t
*it
= arg
->argType
;
1837 char string
[MAX_STR_LEN
];
1838 boolean_t close
= FALSE
;
1840 if (IS_MULTIPLE_KPD(it
)) {
1841 WriteKPD_Iterator(file
, TRUE
, FALSE
, arg
, TRUE
);
1842 (void)sprintf(string
, "ptr->");
1847 (void)sprintf(string
, "In%dP->%s.", arg
->argRequestPos
, arg
->argMsgField
);
1849 fprintf(file
, "\t%sif (%stype != MACH_MSG_PORT_DESCRIPTOR", tab
, string
);
1851 * We can't check disposition on varArray
1852 * (because some of the entries could be empty).
1854 if (!it
->itVarArray
) {
1855 if (arg
->argPoly
!= argNULL
) {
1856 switch (it
->itOutName
) {
1858 case MACH_MSG_TYPE_MOVE_RECEIVE
:
1859 fprintf(file
, " || \n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_RECEIVE", tab
, string
);
1862 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
1863 fprintf(file
, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND_ONCE", tab
, string
);
1864 fprintf(file
, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND_ONCE)", tab
, string
);
1867 case MACH_MSG_TYPE_MOVE_SEND
:
1868 fprintf(file
, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND", tab
, string
);
1869 fprintf(file
, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND", tab
, string
);
1870 fprintf(file
, " && \n\t%s %sdisposition != MACH_MSG_TYPE_COPY_SEND)", tab
, string
);
1875 fprintf(file
, " ||\n\t%s %sdisposition != %s", tab
, string
, it
->itOutNameStr
);
1878 fprintf(file
, ")\n");
1879 fprintf(file
, "\t\treturn MIG_TYPE_ERROR;\n");
1881 fprintf(file
, "\t }\n\t}\n");
1885 * argKPD_TypeCheck discipline for out-of-line types.
1888 WriteTCheckKPD_ool(FILE *file
, argument_t
*arg
)
1890 ipc_type_t
*it
= arg
->argType
;
1891 char *tab
, string
[MAX_STR_LEN
];
1893 u_int howmany
, howbig
;
1895 if (IS_MULTIPLE_KPD(it
)) {
1896 WriteKPD_Iterator(file
, TRUE
, FALSE
, arg
, TRUE
);
1898 sprintf(string
, "ptr->");
1899 howmany
= it
->itElement
->itNumber
;
1900 howbig
= it
->itElement
->itSize
;
1901 test
= !it
->itVarArray
&& !it
->itElement
->itVarArray
;
1905 sprintf(string
, "In%dP->%s.", arg
->argRequestPos
, arg
->argMsgField
);
1906 howmany
= it
->itNumber
;
1907 howbig
= it
->itSize
;
1908 test
= !it
->itVarArray
;
1911 fprintf(file
, "\t%sif (%stype != MACH_MSG_OOL_DESCRIPTOR", tab
, string
);
1913 /* if VarArray we may use no-op; if itElement->itVarArray size might change */
1914 fprintf(file
, " ||\n\t%s %ssize != %d", tab
, string
, (howmany
* howbig
+ 7)/8);
1917 fprintf(file
, ")\n");
1918 fprintf(file
, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab
);
1920 if (IS_MULTIPLE_KPD(it
))
1921 fprintf(file
, "\t }\n\t}\n");
1925 * argKPD_TypeCheck discipline for out-of-line Port types.
1928 WriteTCheckKPD_oolport(FILE *file
, argument_t
*arg
)
1930 ipc_type_t
*it
= arg
->argType
;
1931 char *tab
, string
[MAX_STR_LEN
];
1936 if (IS_MULTIPLE_KPD(it
)) {
1937 WriteKPD_Iterator(file
, TRUE
, FALSE
, arg
, TRUE
);
1939 sprintf(string
, "ptr->");
1940 howmany
= it
->itElement
->itNumber
;
1941 test
= !it
->itVarArray
&& !it
->itElement
->itVarArray
;
1942 howstr
= it
->itElement
->itOutNameStr
;
1946 sprintf(string
, "In%dP->%s.", arg
->argRequestPos
, arg
->argMsgField
);
1947 howmany
= it
->itNumber
;
1948 test
= !it
->itVarArray
;
1949 howstr
= it
->itOutNameStr
;
1952 fprintf(file
, "\t%sif (%stype != MACH_MSG_OOL_PORTS_DESCRIPTOR", tab
, string
);
1954 /* if VarArray we may use no-op; if itElement->itVarArray size might change */
1955 fprintf(file
, " ||\n\t%s %scount != %d", tab
, string
, howmany
);
1956 if (arg
->argPoly
== argNULL
)
1957 fprintf(file
, " ||\n\t%s %sdisposition != %s", tab
, string
, howstr
);
1958 fprintf(file
, ")\n");
1959 fprintf(file
, "\t\treturn MIG_TYPE_ERROR;\n");
1961 if (IS_MULTIPLE_KPD(it
))
1962 fprintf(file
, "\t }\n\t}\n");
1965 /*************************************************************
1966 * Writes code to check that the type of each of the arguments
1967 * in the reply message is what is expected. Called by
1968 * WriteRoutine for each in && typed argument in the request message.
1969 *************************************************************/
1971 WriteTypeCheck(FILE *file
, argument_t
*arg
)
1973 fprintf(file
, "#if\t__MigTypeCheck\n");
1974 (*arg
->argKPD_TypeCheck
)(file
, arg
);
1975 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
1979 WritePackArgValueNormal(FILE *file
, argument_t
*arg
)
1981 ipc_type_t
*it
= arg
->argType
;
1983 if (IS_VARIABLE_SIZED_UNTYPED(it
) || it
->itNoOptArray
) {
1986 * Copy variable-size C string with mig_strncpy.
1987 * Save the string length (+ 1 for trailing 0)
1988 * in the argument`s count field.
1990 fprintf(file
, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
1991 fprintf(file
, "\tif (mig_strncpy_zerofill != NULL) {\n");
1992 fprintf(file
, "\t\tOutP->%s = (%s) mig_strncpy_zerofill(OutP->%s, %s, %d);\n", arg
->argCount
->argMsgField
, arg
->argCount
->argType
->itTransType
, arg
->argMsgField
, arg
->argVarName
, it
->itNumber
);
1993 fprintf(file
, "\t} else {\n");
1994 fprintf(file
, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");
1996 fprintf(file
, "\t\tOutP->%s = (%s) mig_strncpy(OutP->%s, %s, %d);\n", arg
->argCount
->argMsgField
, arg
->argCount
->argType
->itTransType
, arg
->argMsgField
, arg
->argVarName
, it
->itNumber
);
1998 fprintf(file
, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
1999 fprintf(file
, "\t}\n");
2000 fprintf(file
, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");
2002 fprintf(file
, "\tOutP->%sOffset = 0;\n", arg
->argMsgField
);
2004 else if (it
->itNoOptArray
)
2005 fprintf(file
, "\t(void)memcpy((char *) OutP->%s, (const char *) %s, %d);\n", arg
->argMsgField
, arg
->argVarName
, it
->itTypeSize
);
2007 argument_t
*count
= arg
->argCount
;
2008 ipc_type_t
*btype
= it
->itElement
;
2009 identifier_t newstr
;
2011 /* Note btype->itNumber == count->argMultiplier */
2013 fprintf(file
, "\t(void)memcpy((char *) OutP->%s, (const char *) %s, ", arg
->argMsgField
, arg
->argVarName
);
2014 if (btype
->itTypeSize
> 1)
2015 fprintf(file
, "%d * ", btype
->itTypeSize
);
2016 /* count is a akbVarNeeded if arg is akbVarNeeded */
2017 if (akCheck(count
->argKind
, akbVarNeeded
))
2018 newstr
= count
->argVarName
;
2020 newstr
= (identifier_t
)strconcat("OutP->", count
->argMsgField
);
2021 fprintf(file
, "%s);\n", newstr
);
2024 else if (it
->itOutTrans
!= strNULL
)
2025 WriteCopyType(file
, it
, TRUE
, "OutP->%s", "/* %s */ %s(%s)", arg
->argMsgField
, it
->itOutTrans
, arg
->argVarName
);
2027 WriteCopyType(file
, it
, TRUE
, "OutP->%s", "/* %s */ %s", arg
->argMsgField
, arg
->argVarName
);
2029 if (arg
->argPadName
!= NULL
&& it
->itPadSize
!= 0) {
2030 fprintf(file
, "\t for (int i = 0; i < %d; i++)\n", it
->itPadSize
);
2031 fprintf(file
, "\t\t OutP->%s[i] = 0;\n", arg
->argPadName
);
2036 WritePackArgValueVariable(FILE *file
, argument_t
*arg
)
2038 ipc_type_t
*it
= arg
->argType
;
2041 * only itString are treated here so far
2045 * Emit logic to call strlen to calculate the size of the argument, and ensure that it fits within the 32-bit result field
2046 * in the Reply, when targeting a 64-bit architecture. If a 32-bit architecture is the target, we emit code to just call
2047 * strlen() directly (since it'll return a 32-bit value that is guaranteed to fit).
2049 fputs("#ifdef __LP64__\n", file
);
2050 fprintf(file
, "\t{\n"
2051 "\t\t" "size_t strLength = strlen(OutP->%s) + 1;\n", arg
->argMsgField
);
2052 fputs( "\t\t" "if (strLength > 0xffffffff)\n"
2053 "\t\t\t" "MIG_RETURN_ERROR(OutP, MIG_BAD_ARGUMENTS);\n", file
);
2054 fprintf(file
, "\t\t" "OutP->%s = (mach_msg_type_number_t) strLength;\n"
2055 "\t}\n", arg
->argCount
->argMsgField
);
2056 fputs("#else\n", file
);
2057 fprintf(file
, "\tOutP->%s = (mach_msg_type_number_t) strlen(OutP->%s) + 1;\n", arg
->argCount
->argMsgField
, arg
->argMsgField
);
2058 fputs("#endif /* __LP64__ */\n", file
);
2064 WriteCopyArgValue(FILE *file
, argument_t
*arg
)
2066 fprintf(file
, "\n");
2067 WriteCopyType(file
, arg
->argType
, TRUE
, "/* %d */ OutP->%s", "In%dP->%s", arg
->argRequestPos
, (arg
->argSuffix
!= strNULL
) ? arg
->argSuffix
: arg
->argMsgField
);
2071 WriteInitArgValue(FILE *file
, argument_t
*arg
)
2073 fprintf(file
, "\n");
2074 fprintf(file
, "\tOutP->%s = %s;\n\n", arg
->argMsgField
, arg
->argVarName
);
2078 * Calculate the size of a variable-length message field.
2081 WriteArgSize(FILE *file
, argument_t
*arg
)
2083 ipc_type_t
*ptype
= arg
->argType
;
2084 int bsize
= ptype
->itElement
->itTypeSize
;
2085 argument_t
*count
= arg
->argCount
;
2087 /* If the base type size of the data field isn`t a multiple of 4,
2088 we have to round up. */
2089 if (bsize
% itWordAlign
!= 0)
2090 fprintf(file
, "_WALIGN_");
2092 /* Here, we generate ((value + %d) & ~%d). We have to put two (( at the
2095 fprintf(file
, "((");
2097 fprintf(file
, "%d * ", bsize
);
2098 if (ptype
->itString
|| !akCheck(count
->argKind
, akbVarNeeded
))
2099 /* get count from descriptor in message */
2100 fprintf(file
, "OutP->%s", count
->argMsgField
);
2102 /* get count from argument */
2103 fprintf(file
, "%s", count
->argVarName
);
2106 * If the base type size is not a multiple of sizeof(natural_t),
2107 * we have to round up.
2109 if (bsize
% sizeof(natural_t
) != 0)
2110 fprintf(file
, " + %d) & ~%d)", (int)sizeof(natural_t
)-1, (int)sizeof(natural_t
)-1);
2112 fprintf(file
, "))");
2116 * Adjust message size and advance reply pointer.
2117 * Called after packing a variable-length argument that
2118 * has more arguments following.
2121 WriteAdjustMsgSize(FILE *file
, argument_t
*arg
)
2123 routine_t
*rt
= arg
->argRoutine
;
2124 ipc_type_t
*ptype
= arg
->argType
;
2126 /* There are more Out arguments. We need to adjust msgh_size
2127 and advance OutP, so we save the size of the current field
2128 in msgh_size_delta. */
2130 fprintf(file
, "\tmsgh_size_delta = ");
2131 WriteArgSize(file
, arg
);
2132 fprintf(file
, ";\n");
2134 if (rt
->rtNumReplyVar
== 1) {
2135 /* We can still address the message header directly. Fill
2136 in the size field. */
2138 fprintf(file
, "\tOutP->Head.msgh_size = ");
2139 rtMinReplySize(file
, rt
, "Reply");
2140 fprintf(file
, " + msgh_size_delta;\n");
2142 else if (arg
->argReplyPos
== 0) {
2143 /* First variable-length argument. The previous msgh_size value
2144 is the minimum reply size. */
2146 fprintf(file
, "\tmsgh_size = ");
2147 rtMinReplySize(file
, rt
, "Reply");
2148 fprintf(file
, " + msgh_size_delta;\n");
2151 fprintf(file
, "\tmsgh_size += msgh_size_delta;\n");
2153 fprintf(file
, "\tOutP = (Reply *) ((pointer_t) OutP + msgh_size_delta - %d);\n", ptype
->itTypeSize
+ ptype
->itPadSize
);
2157 * Calculate the size of the message. Called after the
2158 * last argument has been packed.
2161 WriteFinishMsgSize(FILE *file
, argument_t
*arg
)
2163 /* No more Out arguments. If this is the only variable Out
2164 argument, we can assign to msgh_size directly. */
2166 if (arg
->argReplyPos
== 0) {
2167 fprintf(file
, "\tOutP->Head.msgh_size = ");
2168 rtMinReplySize(file
, arg
->argRoutine
, "Reply");
2169 fprintf(file
, " + (");
2170 WriteArgSize(file
, arg
);
2171 fprintf(file
, ");\n");
2174 fprintf(file
, "\tmsgh_size += ");
2175 WriteArgSize(file
, arg
);
2176 fprintf(file
, ";\n");
2181 * Handle reply arguments - fill in message types and copy arguments
2182 * that need to be copied.
2185 WriteReplyArgs(FILE *file
, routine_t
*rt
)
2188 argument_t
*lastVarArg
;
2191 * 1. The Kernel Processed Data
2193 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
)
2194 if (akCheckAll(arg
->argKind
, akbReturnSnd
|akbReturnKPD
))
2195 (*arg
->argKPD_Pack
)(file
, arg
);
2197 * 2. The Data Stream
2199 lastVarArg
= argNULL
;
2200 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2202 * Adjust message size and advance message pointer if
2203 * the last request argument was variable-length and the
2204 * request position will change.
2206 if (lastVarArg
!= argNULL
&&
2207 lastVarArg
->argReplyPos
< arg
->argReplyPos
) {
2208 WriteAdjustMsgSize(file
, lastVarArg
);
2209 lastVarArg
= argNULL
;
2212 if (akCheckAll(arg
->argKind
, akbReturnSnd
|akbReturnBody
|akbVarNeeded
))
2213 WritePackArgValueNormal(file
, arg
);
2214 else if (akCheckAll(arg
->argKind
, akbReturnSnd
|akbReturnBody
|akbVariable
))
2215 WritePackArgValueVariable(file
, arg
);
2217 if (akCheck(arg
->argKind
, akbReplyCopy
))
2218 WriteCopyArgValue(file
, arg
);
2219 if (akCheck(arg
->argKind
, akbReplyInit
))
2220 WriteInitArgValue(file
, arg
);
2222 * Remember whether this was variable-length.
2224 if (akCheckAll(arg
->argKind
, akbReturnSnd
|akbReturnBody
|akbVariable
))
2228 * Finish the message size.
2230 if (lastVarArg
!= argNULL
)
2231 WriteFinishMsgSize(file
, lastVarArg
);
2235 WriteFieldDecl(FILE *file
, argument_t
*arg
)
2237 if (akCheck(arg
->argKind
, akbSendKPD
) ||
2238 akCheck(arg
->argKind
, akbReturnKPD
))
2239 WriteFieldDeclPrim(file
, arg
, FetchKPDType
);
2241 WriteFieldDeclPrim(file
, arg
, FetchServerType
);
2245 InitKPD_Disciplines(argument_t
*args
)
2248 extern void KPD_noop(FILE *file
, argument_t
*arg
);
2249 extern void KPD_error(FILE *file
, argument_t
*arg
);
2250 extern void WriteTemplateKPD_port(FILE *file
, argument_t
*arg
, boolean_t in
);
2251 extern void WriteTemplateKPD_ool(FILE *file
, argument_t
*arg
, boolean_t in
);
2252 extern void WriteTemplateKPD_oolport(FILE *file
, argument_t
*arg
, boolean_t in
);
2255 * WriteInitKPD_port, WriteKPD_port, WriteExtractKPD_port,
2256 * WriteInitKPD_ool, WriteKPD_ool, WriteExtractKPD_ool,
2257 * WriteInitKPD_oolport, WriteKPD_oolport, WriteExtractKPD_oolport
2258 * are local to this module (which is the reason why this initialization
2259 * takes place here rather than in utils.c).
2260 * Common routines for user and server will be established SOON, and
2261 * all of them (including the initialization) will be transfert to
2263 * All the KPD disciplines are defaulted to be KPD_error().
2264 * Note that akbSendKPD and akbReturnKPd are not exclusive,
2265 * because of inout type of parameters.
2267 for (arg
= args
; arg
!= argNULL
; arg
= arg
->argNext
)
2268 if (akCheck(arg
->argKind
, akbSendKPD
|akbReturnKPD
))
2269 switch (arg
->argKPD_Type
) {
2271 case MACH_MSG_PORT_DESCRIPTOR
:
2272 if akCheck(arg
->argKind
, akbSendKPD
) {
2273 arg
->argKPD_Extract
=
2274 (IS_MULTIPLE_KPD(arg
->argType
)) ? WriteExtractKPD_port
: WriteExtractArgValue
;
2275 arg
->argKPD_TypeCheck
= WriteTCheckKPD_port
;
2277 if akCheck(arg
->argKind
, akbReturnKPD
) {
2278 arg
->argKPD_Template
= WriteTemplateKPD_port
;
2279 arg
->argKPD_Init
= WriteInitKPD_port
;
2280 arg
->argKPD_Pack
= WriteKPD_port
;
2284 case MACH_MSG_OOL_DESCRIPTOR
:
2285 if akCheck(arg
->argKind
, akbSendKPD
) {
2286 arg
->argKPD_Extract
=
2287 (IS_MULTIPLE_KPD(arg
->argType
)) ? WriteExtractKPD_ool
: WriteExtractArgValue
;
2288 arg
->argKPD_TypeCheck
= WriteTCheckKPD_ool
;
2290 if akCheck(arg
->argKind
, akbReturnKPD
) {
2291 arg
->argKPD_Template
= WriteTemplateKPD_ool
;
2292 arg
->argKPD_Init
= WriteInitKPD_ool
;
2293 arg
->argKPD_Pack
= WriteKPD_ool
;
2297 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
2298 if akCheck(arg
->argKind
, akbSendKPD
) {
2299 arg
->argKPD_Extract
=
2300 (IS_MULTIPLE_KPD(arg
->argType
)) ? WriteExtractKPD_oolport
: WriteExtractArgValue
;
2301 arg
->argKPD_TypeCheck
= WriteTCheckKPD_oolport
;
2303 if akCheck(arg
->argKind
, akbReturnKPD
) {
2304 arg
->argKPD_Template
= WriteTemplateKPD_oolport
;
2305 arg
->argKPD_Init
= WriteInitKPD_oolport
;
2306 arg
->argKPD_Pack
= WriteKPD_oolport
;
2311 printf("MiG internal error: type of kernel processed data unknown\n");
2313 } /* end of switch */
2316 static void WriteStringTerminatorCheck(FILE *file
, routine_t
*rt
)
2318 // generate code to verify that the length of a C string is not greater than the size of the
2319 // buffer in which it is stored.
2321 int msg_limit_calculated
= FALSE
;
2322 int found_string_argument
= FALSE
;
2323 int variable_length_args_present
= (rt
->rtMaxRequestPos
> 0);
2325 // scan through arguments to see if there are any strings
2326 for (argPtr
= rt
->rtArgs
; argPtr
!= NULL
; argPtr
= argPtr
->argNext
) {
2327 if ((argPtr
->argKind
& akbRequest
) && argPtr
->argType
->itString
) {
2328 found_string_argument
= TRUE
;
2333 if (found_string_argument
) {
2334 // create a new scope, for local variables
2335 fputs("#if __MigTypeCheck\n" "\t" "{" "\n", file
);
2337 for (argPtr
= rt
->rtArgs
; argPtr
!= NULL
; argPtr
= argPtr
->argNext
) {
2338 if ((argPtr
->argKind
& akbRequest
) && argPtr
->argType
->itString
) {
2339 //fprintf(stderr, "### found itString: variable name = %s, max length = %d\n", argPtr->argName, argPtr->argType->itNumber);
2341 if (!msg_limit_calculated
) {
2342 msg_limit_calculated
= TRUE
; // only need to do this once
2343 fputs("\t\t" "char * msg_limit = ((char *) In0P) + In0P->Head.msgh_size;\n", file
);
2344 if (IsKernelServer
) {
2345 fputs("#if __MigKernelSpecificCode\n", file
);
2346 fputs("\t\t" "size_t strnlen_limit;" "\n", file
);
2347 fputs("#else\n", file
);
2349 fputs("\t\t" "size_t memchr_limit;" "\n", file
);
2350 if (IsKernelServer
) {
2351 fputs("#endif /* __MigKernelSpecificCode */" "\n", file
);
2356 // I would really prefer to use strnlen() here, to ensure that the byte scanning logic does not extend beyond
2357 // the end of the buffer, but it's not necessarily guaranteed to be available. Instead, I'll use memchr(),
2358 // and let it look for the terminating null byte.
2360 // It turns out that the kernel does not have memchr() available, but strnlen() IS available, so we'll just
2361 // have to emit some conditional code to use the appropriate runtime environment scanning function.
2363 if (IsKernelServer
) {
2364 fputs("#if __MigKernelSpecificCode\n", file
);
2365 fputs("\t\t" "strnlen_limit = min((msg_limit - ", file
);
2366 // If there are variable-length arguments within the message, the proper (adjusted)
2367 // pointers must be used to access those strings
2368 fprintf(file
, "In%dP->%s), %d);" "\n", (variable_length_args_present
? argPtr
->argRequestPos
: 0), argPtr
->argName
, argPtr
->argType
->itNumber
);
2369 fputs("\t\t" "if (", file
);
2370 fprintf(file
, "( strnlen(In%dP->%s, strnlen_limit) >= %d + 1 )", (variable_length_args_present
? argPtr
->argRequestPos
: 0), argPtr
->argName
, argPtr
->argType
->itNumber
);
2371 fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file
);
2372 fputs("#else\n", file
);
2374 // If there are variable-length arguments within the message, the proper (adjusted)
2375 // pointers must be used to access those strings
2376 fprintf(file
, "\t\t" "memchr_limit = min((msg_limit - In%dP->%s), %d);" "\n", (variable_length_args_present
? argPtr
->argRequestPos
: 0), argPtr
->argName
, argPtr
->argType
->itNumber
);
2377 fputs("\t\t" "if (", file
);
2378 fprintf(file
, "( memchr(In%dP->%s, '\\0', memchr_limit) == NULL )", (variable_length_args_present
? argPtr
->argRequestPos
: 0), argPtr
->argName
);
2379 fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file
);
2380 if (IsKernelServer
) {
2381 fputs("#endif /* __MigKernelSpecificCode */" "\n", file
);
2385 fputs("\t" "}" "\n" "#endif" "\t" "/* __MigTypeCheck */" "\n\n", file
); // terminate new scope
2392 WriteOOLSizeCheck(FILE *file
, routine_t
*rt
)
2394 /* Emit code to validate the actual size of ool data vs. the reported size */
2397 boolean_t openedTypeCheckConditional
= FALSE
;
2399 // scan through arguments to see if there are any ool data blocks
2400 for (argPtr
= rt
->rtArgs
; argPtr
!= NULL
; argPtr
= argPtr
->argNext
) {
2401 if (akCheck(argPtr
->argKind
, akbSendKPD
)) {
2402 ipc_type_t
*it
= argPtr
->argType
;
2403 boolean_t multiple_kpd
= IS_MULTIPLE_KPD(it
);
2404 char string
[MAX_STR_LEN
];
2406 argument_t
*argCountPtr
;
2409 if (argPtr
->argKPD_Type
== MACH_MSG_OOL_DESCRIPTOR
) {
2412 if ( !openedTypeCheckConditional
) {
2413 openedTypeCheckConditional
= TRUE
;
2414 fputs("#if __MigTypeCheck\n", file
);
2416 WriteKPD_Iterator(file
, TRUE
, FALSE
, argPtr
, TRUE
);
2418 sprintf(string
, "ptr->");
2419 test
= !it
->itVarArray
&& !it
->itElement
->itVarArray
;
2420 it
= it
->itElement
; // point to element descriptor, so size calculation is correct
2421 argCountPtr
= argPtr
->argSubCount
;
2424 sprintf(string
, "In%dP->%s.", argPtr
->argRequestPos
, argPtr
->argMsgField
);
2425 test
= !it
->itVarArray
;
2426 argCountPtr
= argPtr
->argCount
;
2430 int multiplier
= (argCountPtr
->argMultiplier
> 1 || it
->itSize
> 8) ? argCountPtr
->argMultiplier
* it
->itSize
/ 8 : 1;
2431 if ( !openedTypeCheckConditional
) {
2432 openedTypeCheckConditional
= TRUE
;
2433 fputs("#if __MigTypeCheck\n", file
);
2436 fprintf(file
, "\t%s" "if (%ssize ", tab
, string
);
2438 fprintf(file
, "/ %d ", multiplier
);
2439 fprintf(file
,"!= In%dP->%s%s", argCountPtr
->argRequestPos
, argCountPtr
->argVarName
, multiple_kpd
? "[i]" : "");
2440 if (it
->itOOL_Number
) {
2441 fprintf(file
," || In%dP->%s%s > %d", argCountPtr
->argRequestPos
,
2442 argCountPtr
->argVarName
, multiple_kpd
? "[i]" : "", it
->itOOL_Number
);
2445 fprintf(file
,")\n");
2446 fprintf(file
, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab
);
2450 fprintf(file
, "\t }\n\t}\n");
2451 } else if (argPtr
->argKPD_Type
== MACH_MSG_OOL_PORTS_DESCRIPTOR
) {
2453 if ( !openedTypeCheckConditional
) {
2454 openedTypeCheckConditional
= TRUE
;
2455 fputs("#if __MigTypeCheck\n", file
);
2457 WriteKPD_Iterator(file
, TRUE
, FALSE
, argPtr
, TRUE
);
2459 sprintf(string
, "ptr->");
2460 test
= !it
->itVarArray
&& !it
->itElement
->itVarArray
;
2461 it
= it
->itElement
; // point to element descriptor, so size calculation is correct
2462 argCountPtr
= argPtr
->argSubCount
;
2465 sprintf(string
, "In%dP->%s.", argPtr
->argRequestPos
, argPtr
->argMsgField
);
2466 test
= !it
->itVarArray
;
2467 argCountPtr
= argPtr
->argCount
;
2471 if ( !openedTypeCheckConditional
) {
2472 openedTypeCheckConditional
= TRUE
;
2473 fputs("#if __MigTypeCheck\n", file
);
2476 fprintf(file
, "\t%s" "if (%scount ", tab
, string
);
2477 fprintf(file
,"!= In%dP->%s%s", argCountPtr
->argRequestPos
, argCountPtr
->argVarName
, multiple_kpd
? "[i]" : "");
2478 if (it
->itOOL_Number
) {
2479 fprintf(file
," || In%dP->%s%s > %d", argCountPtr
->argRequestPos
,
2480 argCountPtr
->argVarName
, multiple_kpd
? "[i]" : "", it
->itOOL_Number
);
2482 fprintf(file
,")\n");
2483 fprintf(file
, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab
);
2487 fprintf(file
, "\t }\n\t}\n");
2492 if ( openedTypeCheckConditional
)
2493 fputs("#endif" "\t" "/* __MigTypeCheck */" "\n\n", file
);
2498 WriteCheckRequest(FILE *file
, routine_t
*rt
)
2502 /* initialize the disciplines for the handling of KPDs */
2503 InitKPD_Disciplines(rt
->rtArgs
);
2505 fprintf(file
, "\n");
2506 fprintf(file
, "#if ( __MigTypeCheck ");
2508 fprintf(file
, "|| __NDR_convert__ ");
2509 fprintf(file
, ")\n");
2510 fprintf(file
, "#if __MIG_check__Request__%s_subsystem__\n", SubsystemName
);
2511 fprintf(file
, "#if !defined(__MIG_check__Request__%s_t__defined)\n", rt
->rtName
);
2512 fprintf(file
, "#define __MIG_check__Request__%s_t__defined\n", rt
->rtName
);
2513 if (CheckNDR
&& akCheck(rt
->rtNdrCode
->argKind
, akbRequest
)) {
2514 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertIntRepArgDecl
, akbSendNdr
, "", "");
2515 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertCharRepArgDecl
, akbSendNdr
, "", "");
2516 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertFloatRepArgDecl
, akbSendNdr
, "", "");
2518 fprintf(file
, "\n");
2519 fprintf(file
, "mig_internal kern_return_t __MIG_check__Request__%s_t(__attribute__((__unused__)) __Request__%s_t *In0P", rt
->rtName
, rt
->rtName
);
2520 for (i
= 1; i
<= rt
->rtMaxRequestPos
; i
++)
2521 fprintf(file
, ", __attribute__((__unused__)) __Request__%s_t **In%dPP", rt
->rtName
, i
);
2522 fprintf(file
, ")\n{\n");
2524 fprintf(file
, "\n\ttypedef __Request__%s_t __Request;\n", rt
->rtName
);
2525 for (i
= 1; i
<= rt
->rtMaxRequestPos
; i
++)
2526 fprintf(file
, "\t__Request *In%dP;\n", i
);
2527 if (rt
->rtNumRequestVar
> 0) {
2528 fprintf(file
, "#if\t__MigTypeCheck\n");
2529 fprintf(file
, "\tunsigned int msgh_size;\n");
2530 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
2532 if (rt
->rtMaxRequestPos
> 0)
2533 fprintf(file
, "\tunsigned int msgh_size_delta;\n");
2534 if (rt
->rtNumRequestVar
> 0 || rt
->rtMaxRequestPos
> 0)
2535 fprintf(file
, "\n");
2537 WriteCheckHead(file
, rt
);
2539 WriteList(file
, rt
->rtArgs
, WriteTypeCheck
, akbSendKPD
, "\n", "\n");
2542 argument_t
*arg
, *lastVarArg
;
2544 lastVarArg
= argNULL
;
2545 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2546 if (lastVarArg
!= argNULL
&&
2547 lastVarArg
->argRequestPos
< arg
->argRequestPos
) {
2548 WriteAdjustRequestMsgPtr(file
, lastVarArg
);
2549 lastVarArg
= argNULL
;
2551 if (akCheckAll(arg
->argKind
, akbSendRcv
|akbSendBody
)) {
2552 if (akCheck(arg
->argKind
, akbVariable
)) {
2553 WriteCheckMsgSize(file
, arg
);
2560 if (CheckNDR
&& akCheck(rt
->rtNdrCode
->argKind
, akbRequest
)) {
2561 fprintf(file
, "#if\t");
2562 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertIntRepArgCond
, akbSendNdr
, " || \\\n\t", "\n");
2563 fprintf(file
, "\tif (In0P->NDR.int_rep != NDR_record.int_rep) {\n");
2564 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertIntRepArgUse
, akbSendNdr
, "", "");
2565 fprintf(file
, "\t}\n#endif\t/* defined(__NDR_convert__int_rep...) */\n\n");
2567 WriteOOLSizeCheck(file
, rt
);
2569 fprintf(file
, "#if\t");
2570 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertCharRepArgCond
, akbSendNdr
, " || \\\n\t", "\n");
2571 fprintf(file
, "\tif (In0P->NDR.char_rep != NDR_record.char_rep) {\n");
2572 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertCharRepArgUse
, akbSendNdr
, "", "");
2573 fprintf(file
, "\t}\n#endif\t/* defined(__NDR_convert__char_rep...) */\n\n");
2575 fprintf(file
, "#if\t");
2576 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertFloatRepArgCond
, akbSendNdr
, " || \\\n\t", "\n");
2577 fprintf(file
, "\tif (In0P->NDR.float_rep != NDR_record.float_rep) {\n");
2578 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertFloatRepArgUse
, akbSendNdr
, "", "");
2579 fprintf(file
, "\t}\n#endif\t/* defined(__NDR_convert__float_rep...) */\n\n");
2581 WriteOOLSizeCheck(file
, rt
);
2584 WriteStringTerminatorCheck(file
, rt
);
2586 fprintf(file
, "\treturn MACH_MSG_SUCCESS;\n");
2587 fprintf(file
, "}\n");
2588 fprintf(file
, "#endif /* !defined(__MIG_check__Request__%s_t__defined) */\n", rt
->rtName
);
2589 fprintf(file
, "#endif /* __MIG_check__Request__%s_subsystem__ */\n", SubsystemName
);
2590 fprintf(file
, "#endif /* ( __MigTypeCheck ");
2592 fprintf(file
, "|| __NDR_convert__ ");
2593 fprintf(file
, ") */\n");
2594 fprintf(file
, "\n");
2598 WriteCheckRequestCall(FILE *file
, routine_t
*rt
)
2602 fprintf(file
, "\n");
2603 fprintf(file
, "#if\tdefined(__MIG_check__Request__%s_t__defined)\n", rt
->rtName
);
2604 fprintf(file
, "\tcheck_result = __MIG_check__Request__%s_t((__Request *)In0P", rt
->rtName
);
2605 for (i
= 1; i
<= rt
->rtMaxRequestPos
; i
++)
2606 fprintf(file
, ", (__Request **)&In%dP", i
);
2607 fprintf(file
, ");\n");
2608 fprintf(file
, "\tif (check_result != MACH_MSG_SUCCESS)\n");
2609 fprintf(file
, "\t\t{ MIG_RETURN_ERROR(OutP, check_result); }\n");
2610 fprintf(file
, "#endif\t/* defined(__MIG_check__Request__%s_t__defined) */\n", rt
->rtName
);
2611 fprintf(file
, "\n");
2615 WriteCheckRequests(FILE *file
, statement_t
*stats
)
2619 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
2620 if (stat
->stKind
== skRoutine
)
2621 WriteCheckRequest(file
, stat
->stRoutine
);
2625 WriteRoutine(FILE *file
, routine_t
*rt
)
2627 /* Declare the server work function: */
2628 if (ServerHeaderFileName
== strNULL
)
2629 WriteServerRoutine(file
, rt
);
2631 fprintf(file
, "\n");
2633 fprintf(file
, "/* %s %s */\n", rtRoutineKindToStr(rt
->rtKind
), rt
->rtName
);
2634 fprintf(file
, "mig_internal novalue _X%s\n", rt
->rtName
);
2636 fprintf(file
, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
2639 fprintf(file
, "#if\t%s\n", NewCDecl
);
2640 fprintf(file
, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
2641 fprintf(file
, "#else\n");
2642 fprintf(file
, "\t(InHeadP, OutHeadP)\n");
2643 fprintf(file
, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n");
2644 fprintf(file
, "#endif\t/* %s */\n", NewCDecl
);
2647 fprintf(file
, "{\n");
2648 WriteStructDecl(file
, rt
->rtArgs
, WriteFieldDecl
, akbRequest
, "Request", rt
->rtSimpleRequest
, TRUE
, rt
->rtServerImpl
, FALSE
);
2649 fprintf(file
, "\ttypedef __Request__%s_t __Request;\n", rt
->rtName
);
2650 fprintf(file
, "\ttypedef __Reply__%s_t Reply __attribute__((unused));\n\n", rt
->rtName
);
2653 * Define a Minimal Reply structure to be used in case of errors
2655 fprintf(file
, "\t/*\n");
2656 fprintf(file
, "\t * typedef struct {\n");
2657 fprintf(file
, "\t * \tmach_msg_header_t Head;\n");
2658 fprintf(file
, "\t * \tNDR_record_t NDR;\n");
2659 fprintf(file
, "\t * \tkern_return_t RetCode;\n");
2660 fprintf(file
, "\t * } mig_reply_error_t;\n");
2661 fprintf(file
, "\t */\n");
2662 fprintf(file
, "\n");
2664 WriteVarDecls(file
, rt
);
2666 if (IsKernelServer
) {
2667 fprintf(file
, "#if\t__MigKernelSpecificCode\n");
2668 WriteList(file
, rt
->rtArgs
, WriteTemplateDeclOut
, akbReturnKPD
, "\n", "\n");
2669 fprintf(file
, "#else\n");
2671 WriteList(file
, rt
->rtArgs
, WriteTemplateDeclIn
, akbReturnKPD
, "\n", "\n");
2672 if (IsKernelServer
) {
2673 fprintf(file
, "#endif /* __MigKernelSpecificCode */\n");
2675 WriteRetCode(file
, rt
->rtRetCode
);
2676 WriteList(file
, rt
->rtArgs
, WriteLocalVarDecl
, akbVarNeeded
| akbServerArg
, ";\n", ";\n\n");
2677 WriteApplMacro(file
, "Rcv", "Declare", rt
);
2678 WriteApplMacro(file
, "Rcv", "Before", rt
);
2679 if (rt
->rtRetCArg
!= argNULL
&& !rt
->rtSimpleRequest
) {
2680 WriteRetCArgCheckError(file
, rt
);
2681 if (rt
->rtServerImpl
)
2682 WriteCheckTrailerHead(file
, rt
, FALSE
);
2683 WriteServerCall(file
, rt
, WriteConditionalCallArg
);
2684 WriteRetCArgFinishError(file
, rt
);
2687 WriteCheckRequestCall(file
, rt
);
2688 WriteCheckRequestTrailerArgs(file
, rt
);
2691 * Initialize the KPD records in the Reply structure with the
2692 * templates. We do this beforehand because the call to the procedure
2693 * will overwrite some of the values (after the call it would be impossible
2694 * to initialize the KPD records from the static Templates, because we
2697 WriteList(file
, rt
->rtArgs
, WriteInitKPDValue
, akbReturnKPD
, "\n", "\n");
2699 WriteList(file
, rt
->rtArgs
, WriteExtractArg
, akbNone
, "", "");
2702 WriteLogMsg(file
, rt
, LOG_SERVER
, LOG_REQUEST
);
2704 WriteServerCall(file
, rt
, WriteServerCallArg
);
2706 WriteReverseList(file
, rt
->rtArgs
, WriteDestroyArg
, akbDestroy
, "", "");
2709 * For one-way routines, it doesn`t make sense to check the return
2710 * code, because we return immediately afterwards. However,
2711 * kernel servers may want to deallocate port arguments - and the
2712 * deallocation must not be done if the return code is not KERN_SUCCESS.
2714 if (rt
->rtOneWay
|| rt
->rtNoReplyArgs
) {
2715 if (IsKernelServer
) {
2716 fprintf(file
,"#if\t__MigKernelSpecificCode\n");
2717 if (rtCheckMaskFunction(rt
->rtArgs
, akbSendKPD
, CheckDestroyPortArg
)) {
2718 WriteCheckReturnValue(file
, rt
);
2720 WriteReverseList(file
, rt
->rtArgs
, WriteDestroyPortArg
, akbSendKPD
, "", "");
2721 fprintf(file
,"#endif /* __MigKernelSpecificCode */\n");
2723 /* although we have an empty reply, we still have to make sure that
2724 some fields such as NDR get properly initialized */
2726 WriteList(file
, rt
->rtArgs
, WriteInitArgValue
, akbReplyInit
, "\n", "\n");
2729 WriteCheckReturnValue(file
, rt
);
2731 if (IsKernelServer
) {
2732 fprintf(file
,"#if\t__MigKernelSpecificCode\n");
2733 WriteReverseList(file
, rt
->rtArgs
, WriteDestroyPortArg
, akbSendKPD
, "", "");
2734 fprintf(file
,"#endif /* __MigKernelSpecificCode */\n");
2736 WriteReplyArgs(file
, rt
);
2737 WriteReplyInit(file
, rt
);
2738 if (!rt
->rtSimpleReply
)
2739 fprintf(file
, "\tOutP->msgh_body.msgh_descriptor_count = %d;\n", rt
->rtReplyKPDs
);
2742 WriteLogMsg(file
, rt
, LOG_SERVER
, LOG_REPLY
);
2744 WriteApplMacro(file
, "Rcv", "After", rt
);
2745 fprintf(file
, "}\n");
2749 WriteServer(FILE *file
, statement_t
*stats
)
2753 WriteProlog(file
, stats
);
2755 WriteForwardDeclarations(file
, stats
);
2756 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
2757 switch (stat
->stKind
) {
2760 WriteCheckRequest(file
, stat
->stRoutine
);
2761 WriteRoutine(file
, stat
->stRoutine
);
2772 fatal("WriteServer(): bad statement_kind_t (%d)",
2773 (int) stat
->stKind
);
2775 WriteDispatcher(file
, stats
);