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
;
925 if (arg
->argCount
&& !arg
->argSameCount
)
926 WriteRequestNDRConvertIntRepOneArgUse(file
, arg
->argCount
);
927 if (arg
->argRequestPos
== rt
->rtMaxRequestPos
) {
928 fprintf(file
, "#if\t__MigTypeCheck\n");
930 /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */
931 fprintf(file
, "\t" "if ( In%dP->%s > %d )\n", arg
->argCount
->argRequestPos
, arg
->argCount
->argMsgField
, arg
->argType
->itNumber
);
932 fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file
);
935 WriteCheckArgSize(file
, rt
, arg
, "!=");
937 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
940 /* If there aren't any more variable-sized arguments after this,
941 then we must check for exact msg-size and we don't need to
944 boolean_t LastVarArg
= arg
->argRequestPos
+1 == rt
->rtNumRequestVar
;
946 /* calculate the actual size in bytes of the data field. note
947 that this quantity must be a multiple of four. hence, if
948 the base type size isn't a multiple of four, we have to
949 round up. note also that btype->itNumber must
950 divide btype->itTypeSize (see itCalculateSizeInfo). */
952 fprintf(file
, "\tmsgh_size_delta = ");
953 WriteCalcArgSize(file
, arg
);
954 fprintf(file
, ";\n");
955 fprintf(file
, "#if\t__MigTypeCheck\n");
957 /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */
958 fprintf(file
, "\t" "if ( In%dP->%s > %d )\n", arg
->argCount
->argRequestPos
, arg
->argCount
->argMsgField
, arg
->argType
->itNumber
);
959 fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file
);
962 /* Don't decrement msgh_size until we've checked that
963 it won't underflow. */
964 WriteCheckArgSize(file
, rt
, arg
, LastVarArg
? "!=" : "<");
967 fprintf(file
, "\tmsgh_size -= msgh_size_delta;\n");
969 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
975 InArgMsgField(argument_t
*arg
, char *str
)
977 static char buffer
[MAX_STR_LEN
];
981 * Inside the kernel, the request and reply port fields
982 * really hold ipc_port_t values, not mach_port_t values.
983 * Hence we must cast the values.
986 if (!(arg
->argFlags
& flRetCode
)) {
987 if (akCheck(arg
->argKind
, akbServerImplicit
))
988 sprintf(who
, "TrailerP->");
990 sprintf(who
, "In%dP->", arg
->argRequestPos
);
993 #ifdef MIG_KERNEL_PORT_CONVERSION
994 if (IsKernelServer
&&
995 ((akIdent(arg
->argKind
) == akeRequestPort
) ||
996 (akIdent(arg
->argKind
) == akeReplyPort
)))
997 sprintf(buffer
, "(ipc_port_t) %s%s%s", who
, str
, (arg
->argSuffix
!= strNULL
) ? arg
->argSuffix
: arg
->argMsgField
);
1000 sprintf(buffer
, "%s%s%s", who
, str
, (arg
->argSuffix
!= strNULL
) ? arg
->argSuffix
: arg
->argMsgField
);
1006 WriteExtractArgValue(FILE *file
, argument_t
*arg
)
1008 ipc_type_t
*it
= arg
->argType
;
1011 #ifdef MIG_KERNEL_PORT_CONVERSION
1012 if (IsKernelServer
&& it
->itPortType
&& streql(it
->itServerType
, "ipc_port_t")
1013 && akIdent(arg
->argKind
) != akeRequestPort
1014 && akIdent(arg
->argKind
) != akeReplyPort
)
1015 recast
= "(mach_port_t)";
1019 if (it
->itInTrans
!= strNULL
)
1020 WriteCopyType(file
, it
, FALSE
, "%s", "/* %s */ %s(%s%s)", arg
->argVarName
, it
->itInTrans
, recast
, InArgMsgField(arg
, ""));
1022 WriteCopyType(file
, it
, FALSE
, "%s", "/* %s */ %s%s", arg
->argVarName
, recast
, InArgMsgField(arg
, ""));
1024 fprintf(file
, "\n");
1028 * argKPD_Extract discipline for Port types.
1031 WriteExtractKPD_port(FILE *file
, argument_t
*arg
)
1033 ipc_type_t
*it
= arg
->argType
;
1036 WriteKPD_Iterator(file
, TRUE
, it
->itVarArray
, arg
, FALSE
);
1037 /* translation function do not apply to complex types */
1038 #ifdef MIG_KERNEL_PORT_CONVERSION
1040 recast
= "(mach_port_t)";
1042 fprintf(file
, "\t\t%s[i] = %sptr->name;\n", arg
->argVarName
, recast
);
1043 fprintf(file
, "\t}\n");
1047 * argKPD_Extract discipline for out-of-line types.
1050 WriteExtractKPD_ool(FILE *file
, argument_t
*arg
)
1052 ipc_type_t
*it
= arg
->argType
;
1054 WriteKPD_Iterator(file
, TRUE
, it
->itVarArray
, arg
, FALSE
);
1055 fprintf(file
, "\t\t%s[i] = ptr->address;\n", arg
->argVarName
);
1056 fprintf(file
, "\t}\n");
1060 * argKPD_Extract discipline for out-of-line Port types.
1063 WriteExtractKPD_oolport(FILE *file
, argument_t
*arg
)
1065 ipc_type_t
*it
= arg
->argType
;
1067 WriteKPD_Iterator(file
, TRUE
, it
->itVarArray
, arg
, FALSE
);
1068 fprintf(file
, "\t\t%s[i] = ptr->address;\n", arg
->argVarName
);
1069 fprintf(file
, "\t}\n");
1070 if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbSendRcv
)) {
1071 argument_t
*poly
= arg
->argPoly
;
1072 char *pref
= poly
->argByReferenceServer
? "*" : "";
1074 fprintf(file
, "\t%s%s = In%dP->%s[0].disposition;\n", pref
, poly
->argVarName
, arg
->argRequestPos
, arg
->argMsgField
);
1080 WriteInitializeCount(FILE *file
, argument_t
*arg
)
1082 ipc_type_t
*ptype
= arg
->argParent
->argType
;
1083 ipc_type_t
*btype
= ptype
->itElement
;
1084 identifier_t newstr
;
1087 * Initialize 'count' argument for variable-length inline OUT parameter
1088 * with maximum allowed number of elements.
1091 if (akCheck(arg
->argKind
, akbVarNeeded
))
1092 newstr
= arg
->argMsgField
;
1094 newstr
= (identifier_t
)strconcat("OutP->", arg
->argMsgField
);
1096 fprintf(file
, "\t%s = ", newstr
);
1097 if (IS_MULTIPLE_KPD(ptype
))
1098 fprintf(file
, "%d;\n", ptype
->itKPD_Number
);
1100 fprintf(file
, "%d;\n", btype
->itNumber
? ptype
->itNumber
/btype
->itNumber
: 0);
1103 * If the user passed in a count, then we use the minimum.
1104 * We can't let the user completely override our maximum,
1105 * or the user might convince the server to overwrite the buffer.
1108 if (arg
->argCInOut
!= argNULL
) {
1109 char *msgfield
= InArgMsgField(arg
->argCInOut
, "");
1111 fprintf(file
, "\tif (%s < %s)\n", msgfield
, newstr
);
1112 fprintf(file
, "\t\t%s = %s;\n", newstr
, msgfield
);
1115 fprintf(file
, "\n");
1119 WriteAdjustRequestMsgPtr(FILE *file
, argument_t
*arg
)
1121 ipc_type_t
*ptype
= arg
->argType
;
1123 if (PackMsg
== FALSE
) {
1124 fprintf(file
, "\t*In%dPP = In%dP = (__Request *) ((pointer_t) In%dP);\n\n", arg
->argRequestPos
+1, arg
->argRequestPos
+1, arg
->argRequestPos
);
1128 fprintf(file
, "\t*In%dPP = In%dP = (__Request *) ((pointer_t) In%dP + msgh_size_delta - ", arg
->argRequestPos
+1, arg
->argRequestPos
+1, arg
->argRequestPos
);
1129 if (IS_OPTIONAL_NATIVE(ptype
))
1130 fprintf(file
, "_WALIGNSZ_(%s)", ptype
->itUserType
);
1132 fprintf(file
, "%d", ptype
->itTypeSize
+ ptype
->itPadSize
);
1133 fprintf(file
, ");\n\n");
1137 WriteCheckRequestTrailerArgs(FILE *file
, routine_t
*rt
)
1141 if (rt
->rtServerImpl
)
1142 WriteCheckTrailerHead(file
, rt
, FALSE
);
1144 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
1145 if (akCheck(arg
->argKind
, akbServerImplicit
))
1146 WriteCheckTrailerSize(file
, FALSE
, arg
);
1151 WriteExtractArg(FILE *file
, argument_t
*arg
)
1153 if (akCheckAll(arg
->argKind
, akbSendRcv
|akbVarNeeded
)) {
1154 if (akCheck(arg
->argKind
, akbSendKPD
))
1155 (*arg
->argKPD_Extract
)(file
, arg
);
1157 WriteExtractArgValue(file
, arg
);
1160 if ((akIdent(arg
->argKind
) == akeCount
) &&
1161 akCheck(arg
->argKind
, akbReturnSnd
)) {
1163 ipc_type_t
*ptype
= arg
->argParent
->argType
;
1165 * the count will be initialized to 0 in the case of
1166 * unbounded arrays (MigInLine = TRUE): this is because
1167 * the old interface used to pass to the target procedure
1168 * the maximum in-line size (it was 2048 bytes)
1170 if (IS_VARIABLE_SIZED_UNTYPED(ptype
) ||
1171 IS_MIG_INLINE_EMUL(ptype
) ||
1172 (IS_MULTIPLE_KPD(ptype
) && ptype
->itVarArray
))
1173 WriteInitializeCount(file
, arg
);
1178 WriteServerCallArg(FILE *file
, argument_t
*arg
)
1180 ipc_type_t
*it
= arg
->argType
;
1181 boolean_t NeedClose
= FALSE
;
1183 string_t at
= (arg
->argByReferenceServer
||
1184 it
->itNativePointer
) ? "&" : "";
1185 string_t star
= (arg
->argByReferenceServer
) ? " *" : "";
1187 (arg
->argSuffix
!= strNULL
) ? arg
->argSuffix
: arg
->argMsgField
;
1189 if ((it
->itInTrans
!= strNULL
) &&
1190 akCheck(arg
->argKind
, akbSendRcv
) &&
1191 !akCheck(arg
->argKind
, akbVarNeeded
)) {
1192 fprintf(file
, "%s%s(", at
, it
->itInTrans
);
1196 if (akCheckAll(arg
->argKind
, akbVarNeeded
|akbServerArg
))
1197 fprintf(file
, "%s%s", at
, arg
->argVarName
);
1198 else if (akCheckAll(arg
->argKind
, akbSendRcv
|akbSendKPD
)) {
1200 /* recast the void *, although it is not necessary */
1201 fprintf(file
, "(%s%s)%s(%s)", it
->itTransType
, star
, at
, InArgMsgField(arg
, ""));
1203 #ifdef MIG_KERNEL_PORT_CONVERSION
1204 if (IsKernelServer
&& streql(it
->itServerType
, "ipc_port_t"))
1205 /* recast the port to the kernel internal form value */
1206 fprintf(file
, "(ipc_port_t%s)%s(%s)", star
, at
, InArgMsgField(arg
, ""));
1209 fprintf(file
, "%s%s", at
, InArgMsgField(arg
, ""));
1211 else if (akCheck(arg
->argKind
, akbSendRcv
)) {
1212 if (IS_OPTIONAL_NATIVE(it
)) {
1213 fprintf(file
, "(%s ? ", InArgMsgField(arg
, "__Present__"));
1214 fprintf(file
, "%s%s.__Real__%s : %s)", at
, InArgMsgField(arg
, ""), arg
->argMsgField
, it
->itBadValue
);
1217 if (akIdent(arg
->argKind
) == akeCount
&& arg
->argParent
) {
1218 char *suffix
= arg
->argParent
->argSuffix
;
1219 ipc_type_t
*elemType
= arg
->argParent
->argType
->itElement
;
1220 /* temporarily squash any name suffix such as ".address" (we'll be adding our own) */
1221 arg
->argParent
->argSuffix
= NULL
;
1222 switch (arg
->argParent
->argKPD_Type
) {
1223 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
1224 /* count of the number of descriptors */
1225 fprintf(file
, "%s%s.count", at
, InArgMsgField(arg
->argParent
, ""));
1227 case MACH_MSG_OOL_DESCRIPTOR
:
1228 /* descriptor buffer size / element size */
1229 if (!(arg
->argByReferenceServer
|| it
->itNativePointer
)) {
1230 fprintf(file
, "%s%s.size", at
, InArgMsgField(arg
->argParent
, ""));
1231 elemsize
= ((elemType
->itNumber
* elemType
->itSize
) + 7) / 8;
1233 fprintf(file
, " / %d", elemsize
);
1236 fprintf(file
, "%s%s", at
, InArgMsgField(arg
, ""));
1240 fprintf(file
, "%s%s", at
, InArgMsgField(arg
, ""));
1243 arg
->argParent
->argSuffix
= suffix
;
1245 fprintf(file
, "%s%s", at
, InArgMsgField(arg
, ""));
1249 else if (akCheckAll(arg
->argKind
, akbReturnSnd
|akbReturnKPD
)) {
1251 /* recast the void *, although it is not necessary */
1252 fprintf(file
, "(%s%s)%s(OutP->%s)", it
->itTransType
, star
, at
, msgfield
);
1254 #ifdef MIG_KERNEL_PORT_CONVERSION
1255 if (IsKernelServer
&& streql(it
->itServerType
, "ipc_port_t"))
1256 /* recast the port to the kernel internal form value */
1257 fprintf(file
, "(mach_port_t%s)%s(OutP->%s)", star
, at
, msgfield
);
1260 fprintf(file
, "%sOutP->%s", at
, msgfield
);
1263 else if (akCheck(arg
->argKind
, akbReturnSnd
))
1264 fprintf(file
, "%sOutP->%s", at
, msgfield
);
1271 * Shrunk version of WriteServerCallArg, to implement the RetCode functionality:
1272 * we have received a mig_reply_error_t, therefore we want to call the target
1273 * routine with all 0s except for the error code (and the implicit data).
1274 * We know that we are a SimpleRoutine.
1277 WriteConditionalCallArg(FILE *file
, argument_t
*arg
)
1279 ipc_type_t
*it
= arg
->argType
;
1280 boolean_t NeedClose
= FALSE
;
1282 if ((it
->itInTrans
!= strNULL
) &&
1283 akCheck(arg
->argKind
, akbSendRcv
) &&
1284 !akCheck(arg
->argKind
, akbVarNeeded
)) {
1285 fprintf(file
, "%s(", it
->itInTrans
);
1289 if (akCheck(arg
->argKind
, akbSendRcv
)) {
1290 if (akIdent(arg
->argKind
) == akeRequestPort
||
1291 akCheck(arg
->argKind
, akbServerImplicit
))
1292 fprintf(file
, "%s", InArgMsgField(arg
, ""));
1293 else if (akIdent(arg
->argKind
) == akeRetCode
)
1294 fprintf(file
, "((mig_reply_error_t *)In0P)->RetCode");
1296 fprintf(file
, "(%s)(0)", it
->itTransType
);
1304 WriteDestroyArg(FILE *file
, argument_t
*arg
)
1306 ipc_type_t
*it
= arg
->argType
;
1309 * Deallocate IN/INOUT out-of-line args if specified by "auto" flag.
1311 * We also have to deallocate in the cases where the target routine
1312 * is given a itInLine semantic whereas the underlying transmission
1315 if ((argIsIn(arg
) && akCheck(arg
->argKind
, akbSendKPD
|akbReturnKPD
) &&
1316 arg
->argKPD_Type
== MACH_MSG_OOL_DESCRIPTOR
&&
1317 (arg
->argFlags
& flAuto
))
1319 IS_MIG_INLINE_EMUL(it
)
1322 * Deallocate only if out-of-line.
1324 argument_t
*count
= arg
->argCount
;
1325 ipc_type_t
*btype
= it
->itElement
;
1326 int multiplier
= btype
->itNumber
? btype
->itSize
/ (8 * btype
->itNumber
) : 0;
1328 if (IsKernelServer
) {
1329 fprintf(file
, "#if __MigKernelSpecificCode\n");
1330 fprintf(file
, "\tvm_map_copy_discard(%s);\n", InArgMsgField(arg
, ""));
1331 fprintf(file
, "#else\n");
1333 fprintf(file
, "\tmig_deallocate((vm_offset_t) %s, ", InArgMsgField(arg
, ""));
1334 if (it
->itVarArray
) {
1335 char *suffix
= arg
->argSuffix
;
1337 * temporarily squash any name suffix such as ".address"
1338 * (we'll be adding our own)
1340 arg
->argSuffix
= NULL
;
1341 switch (arg
->argKPD_Type
) {
1342 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
1343 if (multiplier
> 1) {
1344 fprintf(file
, "%d * ", multiplier
);
1346 fprintf(file
, "%s.count);\n", InArgMsgField(arg
, ""));
1348 case MACH_MSG_OOL_DESCRIPTOR
:
1349 fprintf(file
, "%s.size);\n", InArgMsgField(arg
, ""));
1352 if (multiplier
> 1) {
1353 fprintf(file
, "%d * ", multiplier
);
1355 fprintf(file
, "%s);\n", InArgMsgField(count
, ""));
1358 arg
->argSuffix
= suffix
;
1361 fprintf(file
, "%d);\n", (it
->itNumber
* it
->itSize
+ 7) / 8);
1362 if (IsKernelServer
) {
1363 fprintf(file
, "#endif /* __MigKernelSpecificCode */\n");
1365 fprintf(file
, "\t%s = (void *) 0;\n", InArgMsgField(arg
, ""));
1366 fprintf(file
, "\tIn%dP->%s.%s = (mach_msg_size_t) 0;\n", arg
->argRequestPos
, arg
->argMsgField
, (RPCPortArray(arg
) ? "count" : "size"));
1369 if (akCheck(arg
->argKind
, akbVarNeeded
))
1370 fprintf(file
, "\t%s(%s);\n", it
->itDestructor
, arg
->argVarName
);
1372 fprintf(file
, "\t%s(%s);\n", it
->itDestructor
, InArgMsgField(arg
, ""));
1377 WriteDestroyPortArg(FILE *file
, argument_t
*arg
)
1379 ipc_type_t
*it
= arg
->argType
;
1382 * If a translated port argument occurs in the body of a request
1383 * message, and the message is successfully processed, then the
1384 * port right should be deallocated. However, the called function
1385 * didn't see the port right; it saw the translation. So we have
1386 * to release the port right for it.
1388 * The test over it->itInTrans will exclude any complex type
1391 if ((it
->itInTrans
!= strNULL
) &&
1392 (it
->itOutName
== MACH_MSG_TYPE_PORT_SEND
)) {
1393 fprintf(file
, "\n");
1394 fprintf(file
, "\tif (IP_VALID((ipc_port_t)%s))\n", InArgMsgField(arg
, ""));
1395 fprintf(file
, "\t\tipc_port_release_send((ipc_port_t)%s);\n", InArgMsgField(arg
, ""));
1400 * Check whether WriteDestroyPortArg would generate any code for arg.
1403 CheckDestroyPortArg(argument_t
*arg
)
1405 ipc_type_t
*it
= arg
->argType
;
1407 if ((it
->itInTrans
!= strNULL
) &&
1408 (it
->itOutName
== MACH_MSG_TYPE_PORT_SEND
)) {
1415 WriteServerCall(FILE *file
, routine_t
*rt
, void (*func
)(FILE *, argument_t
*))
1417 argument_t
*arg
= rt
->rtRetCode
;
1418 ipc_type_t
*it
= arg
->argType
;
1419 boolean_t NeedClose
= FALSE
;
1421 fprintf(file
, "\t");
1422 if (akCheck(arg
->argKind
, akbVarNeeded
))
1423 fprintf(file
, "%s = ", arg
->argMsgField
);
1425 fprintf(file
, "OutP->%s = ", arg
->argMsgField
);
1426 if (it
->itOutTrans
!= strNULL
) {
1427 fprintf(file
, "%s(", it
->itOutTrans
);
1430 fprintf(file
, "%s(", rt
->rtServerName
);
1431 WriteList(file
, rt
->rtArgs
, func
, akbServerArg
, ", ", "");
1434 fprintf(file
, ");\n");
1438 WriteCheckReturnValue(FILE *file
, routine_t
*rt
)
1440 argument_t
*arg
= rt
->rtRetCode
;
1441 char string
[MAX_STR_LEN
];
1443 if (akCheck(arg
->argKind
, akbVarNeeded
))
1444 sprintf(string
, "%s", arg
->argMsgField
);
1446 sprintf(string
, "OutP->%s", arg
->argMsgField
);
1447 fprintf(file
, "\tif (%s != KERN_SUCCESS) {\n", string
);
1448 fprintf(file
, "\t\tMIG_RETURN_ERROR(OutP, %s);\n", string
);
1449 fprintf(file
, "\t}\n");
1453 * WriteInitKPD_port, WriteInitKPD_ool, WriteInitKPD_oolport
1454 * initializes the OutP KPD fields (this job cannot be done once
1455 * the target routine has been called, otherwise informations
1459 * argKPD_Init discipline for Port types.
1462 WriteInitKPD_port(FILE *file
, argument_t
*arg
)
1464 ipc_type_t
*it
= arg
->argType
;
1465 char *subindex
= "";
1466 boolean_t close
= FALSE
;
1467 char firststring
[MAX_STR_LEN
];
1468 char string
[MAX_STR_LEN
];
1470 if (IS_MULTIPLE_KPD(it
)) {
1471 WriteKPD_Iterator(file
, FALSE
, FALSE
, arg
, TRUE
);
1472 (void)sprintf(firststring
, "\t*ptr");
1473 (void)sprintf(string
, "\tptr->");
1478 (void)sprintf(firststring
, "OutP->%s", arg
->argMsgField
);
1479 (void)sprintf(string
, "OutP->%s.", arg
->argMsgField
);
1482 fprintf(file
, "#if\tUseStaticTemplates\n");
1483 fprintf(file
, "\t%s = %s;\n", firststring
, arg
->argTTName
);
1484 fprintf(file
, "#else\t/* UseStaticTemplates */\n");
1485 if (IS_MULTIPLE_KPD(it
) && it
->itVarArray
)
1486 fprintf(file
, "\t%sname = MACH_PORT_NULL;\n", string
);
1487 if (arg
->argPoly
== argNULL
) {
1488 if (IsKernelServer
) {
1489 fprintf(file
, "#if __MigKernelSpecificCode\n");
1490 fprintf(file
, "\t%sdisposition = %s;\n", string
, it
->itOutNameStr
);
1491 fprintf(file
, "#else\n");
1493 fprintf(file
, "\t%sdisposition = %s;\n", string
, it
->itInNameStr
);
1495 fprintf(file
, "#endif /* __MigKernelSpecificCode */\n");
1497 fprintf(file
, "#if !(defined(KERNEL) && defined(__LP64__))\n");
1498 fprintf(file
, "\t%spad1 = 0;\n", string
);
1499 fprintf(file
, "#endif\n");
1500 fprintf(file
, "\t%spad2 = 0;\n", string
);
1501 fprintf(file
, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string
);
1502 fprintf(file
, "#if defined(KERNEL)\n");
1503 fprintf(file
, "\t%spad_end = 0;\n", string
);
1504 fprintf(file
, "#endif\n");
1505 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
1507 fprintf(file
, "\t }\n\t}\n");
1508 fprintf(file
, "\n");
1512 * argKPD_Init discipline for out-of-line types.
1515 WriteInitKPD_ool(FILE *file
, argument_t
*arg
)
1517 ipc_type_t
*it
= arg
->argType
;
1518 char firststring
[MAX_STR_LEN
];
1519 char string
[MAX_STR_LEN
];
1521 u_int howmany
, howbig
;
1523 if (IS_MULTIPLE_KPD(it
)) {
1524 WriteKPD_Iterator(file
, FALSE
, FALSE
, arg
, TRUE
);
1525 (void)sprintf(firststring
, "\t*ptr");
1526 (void)sprintf(string
, "\tptr->");
1527 VarArray
= it
->itElement
->itVarArray
;
1528 howmany
= it
->itElement
->itNumber
;
1529 howbig
= it
->itElement
->itSize
;
1532 (void)sprintf(firststring
, "OutP->%s", arg
->argMsgField
);
1533 (void)sprintf(string
, "OutP->%s.", arg
->argMsgField
);
1534 VarArray
= it
->itVarArray
;
1535 howmany
= it
->itNumber
;
1536 howbig
= it
->itSize
;
1539 fprintf(file
, "#if\tUseStaticTemplates\n");
1540 fprintf(file
, "\t%s = %s;\n", firststring
, arg
->argTTName
);
1541 fprintf(file
, "#else\t/* UseStaticTemplates */\n");
1543 fprintf(file
, "\t%ssize = %d;\n", string
, (howmany
* howbig
+ 7)/8);
1544 if (arg
->argDeallocate
!= d_MAYBE
)
1545 fprintf(file
, "\t%sdeallocate = %s;\n", string
, (arg
->argDeallocate
== d_YES
) ? "TRUE" : "FALSE");
1546 fprintf(file
, "\t%scopy = %s;\n", string
, (arg
->argFlags
& flPhysicalCopy
) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY");
1548 fprintf(file
, "\t%salignment = MACH_MSG_ALIGN_%d;\n", string
, arg
->argMsgField
, (howbig
< 8) ? 1 : howbig
/ 8);
1550 fprintf(file
, "\t%spad1 = 0;\n", string
);
1551 fprintf(file
, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string
);
1552 fprintf(file
, "#if defined(KERNEL) && !defined(__LP64__)\n");
1553 fprintf(file
, "\t%spad_end = 0;\n", string
);
1554 fprintf(file
, "#endif\n");
1555 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
1557 if (IS_MULTIPLE_KPD(it
))
1558 fprintf(file
, "\t }\n\t}\n");
1559 fprintf(file
, "\n");
1563 * argKPD_Init discipline for out-of-line Port types.
1566 WriteInitKPD_oolport(FILE *file
, argument_t
*arg
)
1568 ipc_type_t
*it
= arg
->argType
;
1572 char firststring
[MAX_STR_LEN
];
1573 char string
[MAX_STR_LEN
];
1575 if (IS_MULTIPLE_KPD(it
)) {
1576 WriteKPD_Iterator(file
, FALSE
, FALSE
, arg
, TRUE
);
1577 (void)sprintf(firststring
, "\t*ptr");
1578 (void)sprintf(string
, "\tptr->");
1579 VarArray
= it
->itElement
->itVarArray
;
1580 howmany
= it
->itElement
->itNumber
;
1581 howit
= it
->itElement
;
1584 (void)sprintf(firststring
, "OutP->%s", arg
->argMsgField
);
1585 (void)sprintf(string
, "OutP->%s.", arg
->argMsgField
);
1586 VarArray
= it
->itVarArray
;
1587 howmany
= it
->itNumber
;
1591 fprintf(file
, "#if\tUseStaticTemplates\n");
1592 fprintf(file
, "\t%s = %s;\n", firststring
, arg
->argTTName
);
1593 fprintf(file
, "#else\t/* UseStaticTemplates */\n");
1596 fprintf(file
, "\t%scount = %d;\n", string
, howmany
);
1597 if (arg
->argPoly
== argNULL
) {
1598 if (IsKernelServer
) {
1599 fprintf(file
, "#if\t__MigKernelSpecificCode\n");
1600 fprintf(file
, "\t%sdisposition = %s;\n", string
, howit
->itOutNameStr
);
1601 fprintf(file
, "#else\n");
1603 fprintf(file
, "\t%sdisposition = %s;\n", string
, howit
->itInNameStr
);
1605 fprintf(file
, "#endif /* __MigKernelSpecificCode */\n");
1607 if (arg
->argDeallocate
!= d_MAYBE
)
1608 fprintf(file
, "\t%sdeallocate = %s;\n", string
, (arg
->argDeallocate
== d_YES
) ? "TRUE" : "FALSE");
1609 fprintf(file
, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string
);
1610 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
1612 if (IS_MULTIPLE_KPD(it
))
1613 fprintf(file
, "\t }\n\t}\n");
1614 fprintf(file
, "\n");
1618 WriteInitKPDValue(FILE *file
, argument_t
*arg
)
1620 (*arg
->argKPD_Init
)(file
, arg
);
1624 WriteAdjustMsgCircular(FILE *file
, argument_t
*arg
)
1626 fprintf(file
, "\n");
1628 fprintf(file
,"#if\t__MigKernelSpecificCode\n");
1629 if (arg
->argType
->itOutName
== MACH_MSG_TYPE_POLYMORPHIC
)
1630 fprintf(file
, "\tif (%s == MACH_MSG_TYPE_PORT_RECEIVE)\n", arg
->argPoly
->argVarName
);
1633 * The carried port right can be accessed in OutP->XXXX. Normally
1634 * the server function stuffs it directly there. If it is InOut,
1635 * then it has already been copied into the reply message.
1636 * If the server function deposited it into a variable (perhaps
1637 * because the reply message is variable-sized) then it has already
1638 * been copied into the reply message.
1640 * The old MiG does not check for circularity in the case of
1641 * array of ports. So do I ...
1644 fprintf(file
, "\t if (IP_VALID((ipc_port_t) In0P->Head.msgh_reply_port) &&\n");
1645 fprintf(file
, "\t IP_VALID((ipc_port_t) OutP->%s.name) &&\n", arg
->argMsgField
);
1646 fprintf(file
, "\t ipc_port_check_circularity((ipc_port_t) OutP->%s.name, (ipc_port_t) In0P->Head.msgh_reply_port))\n", arg
->argMsgField
);
1647 fprintf(file
, "\t\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_CIRCULAR;\n");
1648 fprintf(file
, "#endif /* __MigKernelSpecificCode */\n");
1652 * argKPD_Pack discipline for Port types.
1655 WriteKPD_port(FILE *file
, argument_t
*arg
)
1657 ipc_type_t
*it
= arg
->argType
;
1658 char *subindex
= "";
1660 boolean_t close
= FALSE
;
1661 char string
[MAX_STR_LEN
];
1662 ipc_type_t
*real_it
;
1664 if (akCheck(arg
->argKind
, akbVarNeeded
)) {
1665 if (IS_MULTIPLE_KPD(it
)) {
1666 WriteKPD_Iterator(file
, FALSE
, it
->itVarArray
, arg
, TRUE
);
1667 (void)sprintf(string
, "\tptr->");
1670 real_it
= it
->itElement
;
1673 (void)sprintf(string
, "OutP->%s.", arg
->argMsgField
);
1676 #ifdef MIG_KERNEL_PORT_CONVERSIONS
1677 if (IsKernelServer
&& streql(real_it
->itTransType
, "ipc_port_t"))
1678 recast
= "(mach_port_t)";
1681 if (it
->itOutTrans
!= strNULL
&& !close
)
1682 fprintf(file
, "\t%sname = (mach_port_t)%s(%s);\n", string
, it
->itOutTrans
, arg
->argVarName
);
1684 fprintf(file
, "\t%sname = %s%s%s;\n", string
, recast
, arg
->argVarName
, subindex
);
1685 if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbReturnSnd
)) {
1686 argument_t
*poly
= arg
->argPoly
;
1688 if (akCheck(arg
->argPoly
->argKind
, akbVarNeeded
))
1689 fprintf(file
, "\t%sdisposition = %s;\n", string
, poly
->argVarName
);
1691 fprintf(file
, "\t%sdisposition = OutP->%s;\n", string
, poly
->argSuffix
);
1694 fprintf(file
, "\t }\n\t}\n");
1695 fprintf(file
, "\n");
1697 else if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbReturnSnd
|akbVarNeeded
))
1698 fprintf(file
, "\tOutP->%s.disposition = %s;\n", arg
->argMsgField
, arg
->argPoly
->argVarName
);
1700 * If this is a KernelServer, and the reply message contains
1701 * a receive right, we must check for the possibility of a
1702 * port/message circularity. If queueing the reply message
1703 * would cause a circularity, we mark the reply message
1704 * with the circular bit.
1706 if (IsKernelServer
&& !(IS_MULTIPLE_KPD(it
)) &&
1707 ((arg
->argType
->itOutName
== MACH_MSG_TYPE_PORT_RECEIVE
) ||
1708 (arg
->argType
->itOutName
== MACH_MSG_TYPE_POLYMORPHIC
)))
1709 WriteAdjustMsgCircular(file
, arg
);
1713 * argKPD_Pack discipline for out-of-line types.
1716 WriteKPD_ool(FILE *file
, argument_t
*arg
)
1718 ipc_type_t
*it
= arg
->argType
;
1719 char string
[MAX_STR_LEN
];
1725 if (IS_MULTIPLE_KPD(it
)) {
1726 WriteKPD_Iterator(file
, FALSE
, it
->itVarArray
, arg
, TRUE
);
1727 (void)sprintf(string
, "\tptr->");
1728 VarArray
= it
->itElement
->itVarArray
;
1729 count
= arg
->argSubCount
;
1730 howbig
= it
->itElement
->itSize
;
1734 (void)sprintf(string
, "OutP->%s.", arg
->argMsgField
);
1735 VarArray
= it
->itVarArray
;
1736 count
= arg
->argCount
;
1737 howbig
= it
->itSize
;
1741 if (akCheck(arg
->argKind
, akbVarNeeded
))
1742 fprintf(file
, "\t%saddress = (void *)%s%s;\n", string
, arg
->argMsgField
, subindex
);
1743 if (arg
->argDealloc
!= argNULL
)
1744 if (akCheck(arg
->argDealloc
->argKind
, akbVarNeeded
) || IS_MULTIPLE_KPD(it
))
1745 fprintf(file
, "\t%sdeallocate = %s;\n", string
, arg
->argDealloc
->argVarName
);
1747 fprintf(file
, "\t%ssize = ", string
);
1748 if (akCheck(count
->argKind
, akbVarNeeded
))
1749 fprintf(file
, "%s%s", count
->argName
, subindex
);
1751 fprintf(file
, "OutP->%s%s", count
->argMsgField
, subindex
);
1753 if (count
->argMultiplier
> 1 || howbig
> 8)
1754 fprintf(file
, " * %d;\n", count
->argMultiplier
* howbig
/ 8);
1756 fprintf(file
, ";\n");
1759 if (IS_MULTIPLE_KPD(it
)) {
1760 fprintf(file
, "\t }\n");
1761 if (it
->itVarArray
&& !it
->itElement
->itVarArray
) {
1762 fprintf(file
, "\t for (i = j; i < %d; ptr++, i++)\n", it
->itKPD_Number
);
1763 /* since subordinate arrays aren't variable, they are initialized from template:
1764 here we must no-op 'em */
1765 fprintf(file
, "\t\tptr->size = 0;\n");
1767 fprintf(file
, "\t}\n");
1769 fprintf(file
, "\n");
1773 * argKPD_Pack discipline for out-of-line Port types.
1776 WriteKPD_oolport(FILE *file
, argument_t
*arg
)
1778 ipc_type_t
*it
= arg
->argType
;
1781 char *subindex
, string
[MAX_STR_LEN
];
1783 if (IS_MULTIPLE_KPD(it
)) {
1784 WriteKPD_Iterator(file
, FALSE
, it
->itVarArray
, arg
, TRUE
);
1785 (void)sprintf(string
, "\tptr->");
1786 VarArray
= it
->itElement
->itVarArray
;
1787 count
= arg
->argSubCount
;
1791 (void)sprintf(string
, "OutP->%s.", arg
->argMsgField
);
1792 VarArray
= it
->itVarArray
;
1793 count
= arg
->argCount
;
1797 if (akCheck(arg
->argKind
, akbVarNeeded
))
1798 fprintf(file
, "\t%saddress = (void *)%s%s;\n", string
, arg
->argMsgField
, subindex
);
1799 if (arg
->argDealloc
!= argNULL
)
1800 if (akCheck(arg
->argDealloc
->argKind
, akbVarNeeded
) || IS_MULTIPLE_KPD(it
))
1801 fprintf(file
, "\t%sdeallocate = %s;\n", string
, arg
->argDealloc
->argVarName
);
1803 fprintf(file
, "\t%scount = ", string
);
1804 if (akCheck(count
->argKind
, akbVarNeeded
))
1805 fprintf(file
, "%s%s;\n", count
->argName
, subindex
);
1807 fprintf(file
, "OutP->%s%s;\n", count
->argMsgField
, subindex
);
1809 if (arg
->argPoly
!= argNULL
&& akCheckAll(arg
->argPoly
->argKind
, akbReturnSnd
))
1810 if (akCheck(arg
->argPoly
->argKind
, akbVarNeeded
) || IS_MULTIPLE_KPD(it
))
1811 fprintf(file
, "\t%sdisposition = %s;\n", string
, arg
->argPoly
->argVarName
);
1812 if (IS_MULTIPLE_KPD(it
)) {
1813 fprintf(file
, "\t }\n");
1814 if (it
->itVarArray
&& !it
->itElement
->itVarArray
) {
1815 fprintf(file
, "\t for (i = j; i < %d; ptr++, i++)\n", it
->itKPD_Number
);
1816 /* since subordinate arrays aren't variable, they are initialized from template:
1817 here we must no-op 'em */
1818 fprintf(file
, "\t%scount = 0;\n", string
);
1820 fprintf(file
, "\t}\n");
1822 fprintf(file
, "\n");
1826 * argKPD_TypeCheck discipline for Port types.
1829 WriteTCheckKPD_port(FILE *file
, argument_t
*arg
)
1831 ipc_type_t
*it
= arg
->argType
;
1833 char string
[MAX_STR_LEN
];
1834 boolean_t close
= FALSE
;
1836 if (IS_MULTIPLE_KPD(it
)) {
1837 WriteKPD_Iterator(file
, TRUE
, FALSE
, arg
, TRUE
);
1838 (void)sprintf(string
, "ptr->");
1843 (void)sprintf(string
, "In%dP->%s.", arg
->argRequestPos
, arg
->argMsgField
);
1845 fprintf(file
, "\t%sif (%stype != MACH_MSG_PORT_DESCRIPTOR", tab
, string
);
1847 * We can't check disposition on varArray
1848 * (because some of the entries could be empty).
1850 if (!it
->itVarArray
) {
1851 if (arg
->argPoly
!= argNULL
) {
1852 switch (it
->itOutName
) {
1854 case MACH_MSG_TYPE_MOVE_RECEIVE
:
1855 fprintf(file
, " || \n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_RECEIVE", tab
, string
);
1858 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
1859 fprintf(file
, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND_ONCE", tab
, string
);
1860 fprintf(file
, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND_ONCE)", tab
, string
);
1863 case MACH_MSG_TYPE_MOVE_SEND
:
1864 fprintf(file
, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND", tab
, string
);
1865 fprintf(file
, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND", tab
, string
);
1866 fprintf(file
, " && \n\t%s %sdisposition != MACH_MSG_TYPE_COPY_SEND)", tab
, string
);
1871 fprintf(file
, " ||\n\t%s %sdisposition != %s", tab
, string
, it
->itOutNameStr
);
1874 fprintf(file
, ")\n");
1875 fprintf(file
, "\t\treturn MIG_TYPE_ERROR;\n");
1877 fprintf(file
, "\t }\n\t}\n");
1881 * argKPD_TypeCheck discipline for out-of-line types.
1884 WriteTCheckKPD_ool(FILE *file
, argument_t
*arg
)
1886 ipc_type_t
*it
= arg
->argType
;
1887 char *tab
, string
[MAX_STR_LEN
];
1889 u_int howmany
, howbig
;
1891 if (IS_MULTIPLE_KPD(it
)) {
1892 WriteKPD_Iterator(file
, TRUE
, FALSE
, arg
, TRUE
);
1894 sprintf(string
, "ptr->");
1895 howmany
= it
->itElement
->itNumber
;
1896 howbig
= it
->itElement
->itSize
;
1897 test
= !it
->itVarArray
&& !it
->itElement
->itVarArray
;
1901 sprintf(string
, "In%dP->%s.", arg
->argRequestPos
, arg
->argMsgField
);
1902 howmany
= it
->itNumber
;
1903 howbig
= it
->itSize
;
1904 test
= !it
->itVarArray
;
1907 fprintf(file
, "\t%sif (%stype != MACH_MSG_OOL_DESCRIPTOR", tab
, string
);
1909 /* if VarArray we may use no-op; if itElement->itVarArray size might change */
1910 fprintf(file
, " ||\n\t%s %ssize != %d", tab
, string
, (howmany
* howbig
+ 7)/8);
1913 fprintf(file
, ")\n");
1914 fprintf(file
, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab
);
1916 if (IS_MULTIPLE_KPD(it
))
1917 fprintf(file
, "\t }\n\t}\n");
1921 * argKPD_TypeCheck discipline for out-of-line Port types.
1924 WriteTCheckKPD_oolport(FILE *file
, argument_t
*arg
)
1926 ipc_type_t
*it
= arg
->argType
;
1927 char *tab
, string
[MAX_STR_LEN
];
1932 if (IS_MULTIPLE_KPD(it
)) {
1933 WriteKPD_Iterator(file
, TRUE
, FALSE
, arg
, TRUE
);
1935 sprintf(string
, "ptr->");
1936 howmany
= it
->itElement
->itNumber
;
1937 test
= !it
->itVarArray
&& !it
->itElement
->itVarArray
;
1938 howstr
= it
->itElement
->itOutNameStr
;
1942 sprintf(string
, "In%dP->%s.", arg
->argRequestPos
, arg
->argMsgField
);
1943 howmany
= it
->itNumber
;
1944 test
= !it
->itVarArray
;
1945 howstr
= it
->itOutNameStr
;
1948 fprintf(file
, "\t%sif (%stype != MACH_MSG_OOL_PORTS_DESCRIPTOR", tab
, string
);
1950 /* if VarArray we may use no-op; if itElement->itVarArray size might change */
1951 fprintf(file
, " ||\n\t%s %scount != %d", tab
, string
, howmany
);
1952 if (arg
->argPoly
== argNULL
)
1953 fprintf(file
, " ||\n\t%s %sdisposition != %s", tab
, string
, howstr
);
1954 fprintf(file
, ")\n");
1955 fprintf(file
, "\t\treturn MIG_TYPE_ERROR;\n");
1957 if (IS_MULTIPLE_KPD(it
))
1958 fprintf(file
, "\t }\n\t}\n");
1961 /*************************************************************
1962 * Writes code to check that the type of each of the arguments
1963 * in the reply message is what is expected. Called by
1964 * WriteRoutine for each in && typed argument in the request message.
1965 *************************************************************/
1967 WriteTypeCheck(FILE *file
, argument_t
*arg
)
1969 fprintf(file
, "#if\t__MigTypeCheck\n");
1970 (*arg
->argKPD_TypeCheck
)(file
, arg
);
1971 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
1975 WritePackArgValueNormal(FILE *file
, argument_t
*arg
)
1977 ipc_type_t
*it
= arg
->argType
;
1979 if (IS_VARIABLE_SIZED_UNTYPED(it
) || it
->itNoOptArray
) {
1982 * Copy variable-size C string with mig_strncpy.
1983 * Save the string length (+ 1 for trailing 0)
1984 * in the argument`s count field.
1986 fprintf(file
, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
1987 fprintf(file
, "\tif (mig_strncpy_zerofill != NULL) {\n");
1988 fprintf(file
, "\t\tOutP->%s = (%s) mig_strncpy_zerofill(OutP->%s, %s, %d);\n", arg
->argCount
->argMsgField
, arg
->argCount
->argType
->itTransType
, arg
->argMsgField
, arg
->argVarName
, it
->itNumber
);
1989 fprintf(file
, "\t} else {\n");
1990 fprintf(file
, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");
1992 fprintf(file
, "\t\tOutP->%s = (%s) mig_strncpy(OutP->%s, %s, %d);\n", arg
->argCount
->argMsgField
, arg
->argCount
->argType
->itTransType
, arg
->argMsgField
, arg
->argVarName
, it
->itNumber
);
1994 fprintf(file
, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
1995 fprintf(file
, "\t}\n");
1996 fprintf(file
, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");
1998 fprintf(file
, "\tOutP->%sOffset = 0;\n", arg
->argMsgField
);
2000 else if (it
->itNoOptArray
)
2001 fprintf(file
, "\t(void)memcpy((char *) OutP->%s, (const char *) %s, %d);\n", arg
->argMsgField
, arg
->argVarName
, it
->itTypeSize
);
2003 argument_t
*count
= arg
->argCount
;
2004 ipc_type_t
*btype
= it
->itElement
;
2005 identifier_t newstr
;
2007 /* Note btype->itNumber == count->argMultiplier */
2009 fprintf(file
, "\t(void)memcpy((char *) OutP->%s, (const char *) %s, ", arg
->argMsgField
, arg
->argVarName
);
2010 if (btype
->itTypeSize
> 1)
2011 fprintf(file
, "%d * ", btype
->itTypeSize
);
2012 /* count is a akbVarNeeded if arg is akbVarNeeded */
2013 if (akCheck(count
->argKind
, akbVarNeeded
))
2014 newstr
= count
->argVarName
;
2016 newstr
= (identifier_t
)strconcat("OutP->", count
->argMsgField
);
2017 fprintf(file
, "%s);\n", newstr
);
2020 else if (it
->itOutTrans
!= strNULL
)
2021 WriteCopyType(file
, it
, TRUE
, "OutP->%s", "/* %s */ %s(%s)", arg
->argMsgField
, it
->itOutTrans
, arg
->argVarName
);
2023 WriteCopyType(file
, it
, TRUE
, "OutP->%s", "/* %s */ %s", arg
->argMsgField
, arg
->argVarName
);
2025 if (arg
->argPadName
!= NULL
&& it
->itPadSize
!= 0) {
2026 fprintf(file
, "\t for (int i = 0; i < %d; i++)\n", it
->itPadSize
);
2027 fprintf(file
, "\t\t OutP->%s[i] = 0;\n", arg
->argPadName
);
2032 WritePackArgValueVariable(FILE *file
, argument_t
*arg
)
2034 ipc_type_t
*it
= arg
->argType
;
2037 * only itString are treated here so far
2041 * Emit logic to call strlen to calculate the size of the argument, and ensure that it fits within the 32-bit result field
2042 * in the Reply, when targeting a 64-bit architecture. If a 32-bit architecture is the target, we emit code to just call
2043 * strlen() directly (since it'll return a 32-bit value that is guaranteed to fit).
2045 fputs("#ifdef __LP64__\n", file
);
2046 fprintf(file
, "\t{\n"
2047 "\t\t" "size_t strLength = strlen(OutP->%s) + 1;\n", arg
->argMsgField
);
2048 fputs( "\t\t" "if (strLength > 0xffffffff)\n"
2049 "\t\t\t" "MIG_RETURN_ERROR(OutP, MIG_BAD_ARGUMENTS);\n", file
);
2050 fprintf(file
, "\t\t" "OutP->%s = (mach_msg_type_number_t) strLength;\n"
2051 "\t}\n", arg
->argCount
->argMsgField
);
2052 fputs("#else\n", file
);
2053 fprintf(file
, "\tOutP->%s = (mach_msg_type_number_t) strlen(OutP->%s) + 1;\n", arg
->argCount
->argMsgField
, arg
->argMsgField
);
2054 fputs("#endif /* __LP64__ */\n", file
);
2060 WriteCopyArgValue(FILE *file
, argument_t
*arg
)
2062 fprintf(file
, "\n");
2063 WriteCopyType(file
, arg
->argType
, TRUE
, "/* %d */ OutP->%s", "In%dP->%s", arg
->argRequestPos
, (arg
->argSuffix
!= strNULL
) ? arg
->argSuffix
: arg
->argMsgField
);
2067 WriteInitArgValue(FILE *file
, argument_t
*arg
)
2069 fprintf(file
, "\n");
2070 fprintf(file
, "\tOutP->%s = %s;\n\n", arg
->argMsgField
, arg
->argVarName
);
2074 * Calculate the size of a variable-length message field.
2077 WriteArgSize(FILE *file
, argument_t
*arg
)
2079 ipc_type_t
*ptype
= arg
->argType
;
2080 int bsize
= ptype
->itElement
->itTypeSize
;
2081 argument_t
*count
= arg
->argCount
;
2083 /* If the base type size of the data field isn`t a multiple of 4,
2084 we have to round up. */
2085 if (bsize
% itWordAlign
!= 0)
2086 fprintf(file
, "_WALIGN_");
2088 /* Here, we generate ((value + %d) & ~%d). We have to put two (( at the
2091 fprintf(file
, "((");
2093 fprintf(file
, "%d * ", bsize
);
2094 if (ptype
->itString
|| !akCheck(count
->argKind
, akbVarNeeded
))
2095 /* get count from descriptor in message */
2096 fprintf(file
, "OutP->%s", count
->argMsgField
);
2098 /* get count from argument */
2099 fprintf(file
, "%s", count
->argVarName
);
2102 * If the base type size is not a multiple of sizeof(natural_t),
2103 * we have to round up.
2105 if (bsize
% sizeof(natural_t
) != 0)
2106 fprintf(file
, " + %d) & ~%d)", (int)sizeof(natural_t
)-1, (int)sizeof(natural_t
)-1);
2108 fprintf(file
, "))");
2112 * Adjust message size and advance reply pointer.
2113 * Called after packing a variable-length argument that
2114 * has more arguments following.
2117 WriteAdjustMsgSize(FILE *file
, argument_t
*arg
)
2119 routine_t
*rt
= arg
->argRoutine
;
2120 ipc_type_t
*ptype
= arg
->argType
;
2122 /* There are more Out arguments. We need to adjust msgh_size
2123 and advance OutP, so we save the size of the current field
2124 in msgh_size_delta. */
2126 fprintf(file
, "\tmsgh_size_delta = ");
2127 WriteArgSize(file
, arg
);
2128 fprintf(file
, ";\n");
2130 if (rt
->rtNumReplyVar
== 1) {
2131 /* We can still address the message header directly. Fill
2132 in the size field. */
2134 fprintf(file
, "\tOutP->Head.msgh_size = ");
2135 rtMinReplySize(file
, rt
, "Reply");
2136 fprintf(file
, " + msgh_size_delta;\n");
2138 else if (arg
->argReplyPos
== 0) {
2139 /* First variable-length argument. The previous msgh_size value
2140 is the minimum reply size. */
2142 fprintf(file
, "\tmsgh_size = ");
2143 rtMinReplySize(file
, rt
, "Reply");
2144 fprintf(file
, " + msgh_size_delta;\n");
2147 fprintf(file
, "\tmsgh_size += msgh_size_delta;\n");
2149 fprintf(file
, "\tOutP = (Reply *) ((pointer_t) OutP + msgh_size_delta - %d);\n", ptype
->itTypeSize
+ ptype
->itPadSize
);
2153 * Calculate the size of the message. Called after the
2154 * last argument has been packed.
2157 WriteFinishMsgSize(FILE *file
, argument_t
*arg
)
2159 /* No more Out arguments. If this is the only variable Out
2160 argument, we can assign to msgh_size directly. */
2162 if (arg
->argReplyPos
== 0) {
2163 fprintf(file
, "\tOutP->Head.msgh_size = ");
2164 rtMinReplySize(file
, arg
->argRoutine
, "Reply");
2165 fprintf(file
, " + (");
2166 WriteArgSize(file
, arg
);
2167 fprintf(file
, ");\n");
2170 fprintf(file
, "\tmsgh_size += ");
2171 WriteArgSize(file
, arg
);
2172 fprintf(file
, ";\n");
2177 * Handle reply arguments - fill in message types and copy arguments
2178 * that need to be copied.
2181 WriteReplyArgs(FILE *file
, routine_t
*rt
)
2184 argument_t
*lastVarArg
;
2187 * 1. The Kernel Processed Data
2189 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
)
2190 if (akCheckAll(arg
->argKind
, akbReturnSnd
|akbReturnKPD
))
2191 (*arg
->argKPD_Pack
)(file
, arg
);
2193 * 2. The Data Stream
2195 lastVarArg
= argNULL
;
2196 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2198 * Adjust message size and advance message pointer if
2199 * the last request argument was variable-length and the
2200 * request position will change.
2202 if (lastVarArg
!= argNULL
&&
2203 lastVarArg
->argReplyPos
< arg
->argReplyPos
) {
2204 WriteAdjustMsgSize(file
, lastVarArg
);
2205 lastVarArg
= argNULL
;
2208 if (akCheckAll(arg
->argKind
, akbReturnSnd
|akbReturnBody
|akbVarNeeded
))
2209 WritePackArgValueNormal(file
, arg
);
2210 else if (akCheckAll(arg
->argKind
, akbReturnSnd
|akbReturnBody
|akbVariable
))
2211 WritePackArgValueVariable(file
, arg
);
2213 if (akCheck(arg
->argKind
, akbReplyCopy
))
2214 WriteCopyArgValue(file
, arg
);
2215 if (akCheck(arg
->argKind
, akbReplyInit
))
2216 WriteInitArgValue(file
, arg
);
2218 * Remember whether this was variable-length.
2220 if (akCheckAll(arg
->argKind
, akbReturnSnd
|akbReturnBody
|akbVariable
))
2224 * Finish the message size.
2226 if (lastVarArg
!= argNULL
)
2227 WriteFinishMsgSize(file
, lastVarArg
);
2231 WriteFieldDecl(FILE *file
, argument_t
*arg
)
2233 if (akCheck(arg
->argKind
, akbSendKPD
) ||
2234 akCheck(arg
->argKind
, akbReturnKPD
))
2235 WriteFieldDeclPrim(file
, arg
, FetchKPDType
);
2237 WriteFieldDeclPrim(file
, arg
, FetchServerType
);
2241 InitKPD_Disciplines(argument_t
*args
)
2244 extern void KPD_noop(FILE *file
, argument_t
*arg
);
2245 extern void KPD_error(FILE *file
, argument_t
*arg
);
2246 extern void WriteTemplateKPD_port(FILE *file
, argument_t
*arg
, boolean_t in
);
2247 extern void WriteTemplateKPD_ool(FILE *file
, argument_t
*arg
, boolean_t in
);
2248 extern void WriteTemplateKPD_oolport(FILE *file
, argument_t
*arg
, boolean_t in
);
2251 * WriteInitKPD_port, WriteKPD_port, WriteExtractKPD_port,
2252 * WriteInitKPD_ool, WriteKPD_ool, WriteExtractKPD_ool,
2253 * WriteInitKPD_oolport, WriteKPD_oolport, WriteExtractKPD_oolport
2254 * are local to this module (which is the reason why this initialization
2255 * takes place here rather than in utils.c).
2256 * Common routines for user and server will be established SOON, and
2257 * all of them (including the initialization) will be transfert to
2259 * All the KPD disciplines are defaulted to be KPD_error().
2260 * Note that akbSendKPD and akbReturnKPd are not exclusive,
2261 * because of inout type of parameters.
2263 for (arg
= args
; arg
!= argNULL
; arg
= arg
->argNext
)
2264 if (akCheck(arg
->argKind
, akbSendKPD
|akbReturnKPD
))
2265 switch (arg
->argKPD_Type
) {
2267 case MACH_MSG_PORT_DESCRIPTOR
:
2268 if akCheck(arg
->argKind
, akbSendKPD
) {
2269 arg
->argKPD_Extract
=
2270 (IS_MULTIPLE_KPD(arg
->argType
)) ? WriteExtractKPD_port
: WriteExtractArgValue
;
2271 arg
->argKPD_TypeCheck
= WriteTCheckKPD_port
;
2273 if akCheck(arg
->argKind
, akbReturnKPD
) {
2274 arg
->argKPD_Template
= WriteTemplateKPD_port
;
2275 arg
->argKPD_Init
= WriteInitKPD_port
;
2276 arg
->argKPD_Pack
= WriteKPD_port
;
2280 case MACH_MSG_OOL_DESCRIPTOR
:
2281 if akCheck(arg
->argKind
, akbSendKPD
) {
2282 arg
->argKPD_Extract
=
2283 (IS_MULTIPLE_KPD(arg
->argType
)) ? WriteExtractKPD_ool
: WriteExtractArgValue
;
2284 arg
->argKPD_TypeCheck
= WriteTCheckKPD_ool
;
2286 if akCheck(arg
->argKind
, akbReturnKPD
) {
2287 arg
->argKPD_Template
= WriteTemplateKPD_ool
;
2288 arg
->argKPD_Init
= WriteInitKPD_ool
;
2289 arg
->argKPD_Pack
= WriteKPD_ool
;
2293 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
2294 if akCheck(arg
->argKind
, akbSendKPD
) {
2295 arg
->argKPD_Extract
=
2296 (IS_MULTIPLE_KPD(arg
->argType
)) ? WriteExtractKPD_oolport
: WriteExtractArgValue
;
2297 arg
->argKPD_TypeCheck
= WriteTCheckKPD_oolport
;
2299 if akCheck(arg
->argKind
, akbReturnKPD
) {
2300 arg
->argKPD_Template
= WriteTemplateKPD_oolport
;
2301 arg
->argKPD_Init
= WriteInitKPD_oolport
;
2302 arg
->argKPD_Pack
= WriteKPD_oolport
;
2307 printf("MiG internal error: type of kernel processed data unknown\n");
2309 } /* end of switch */
2312 static void WriteStringTerminatorCheck(FILE *file
, routine_t
*rt
)
2314 // generate code to verify that the length of a C string is not greater than the size of the
2315 // buffer in which it is stored.
2317 int msg_limit_calculated
= FALSE
;
2318 int found_string_argument
= FALSE
;
2319 int variable_length_args_present
= (rt
->rtMaxRequestPos
> 0);
2321 // scan through arguments to see if there are any strings
2322 for (argPtr
= rt
->rtArgs
; argPtr
!= NULL
; argPtr
= argPtr
->argNext
) {
2323 if ((argPtr
->argKind
& akbRequest
) && argPtr
->argType
->itString
) {
2324 found_string_argument
= TRUE
;
2329 if (found_string_argument
) {
2330 // create a new scope, for local variables
2331 fputs("#if __MigTypeCheck\n" "\t" "{" "\n", file
);
2333 for (argPtr
= rt
->rtArgs
; argPtr
!= NULL
; argPtr
= argPtr
->argNext
) {
2334 if ((argPtr
->argKind
& akbRequest
) && argPtr
->argType
->itString
) {
2335 //fprintf(stderr, "### found itString: variable name = %s, max length = %d\n", argPtr->argName, argPtr->argType->itNumber);
2337 if (!msg_limit_calculated
) {
2338 msg_limit_calculated
= TRUE
; // only need to do this once
2339 fputs("\t\t" "char * msg_limit = ((char *) In0P) + In0P->Head.msgh_size;\n", file
);
2340 if (IsKernelServer
) {
2341 fputs("#if __MigKernelSpecificCode\n", file
);
2342 fputs("\t\t" "size_t strnlen_limit;" "\n", file
);
2343 fputs("#else\n", file
);
2345 fputs("\t\t" "size_t memchr_limit;" "\n", file
);
2346 if (IsKernelServer
) {
2347 fputs("#endif /* __MigKernelSpecificCode */" "\n", file
);
2352 // I would really prefer to use strnlen() here, to ensure that the byte scanning logic does not extend beyond
2353 // the end of the buffer, but it's not necessarily guaranteed to be available. Instead, I'll use memchr(),
2354 // and let it look for the terminating null byte.
2356 // It turns out that the kernel does not have memchr() available, but strnlen() IS available, so we'll just
2357 // have to emit some conditional code to use the appropriate runtime environment scanning function.
2359 if (IsKernelServer
) {
2360 fputs("#if __MigKernelSpecificCode\n", file
);
2361 fputs("\t\t" "strnlen_limit = min((msg_limit - ", file
);
2362 // If there are variable-length arguments within the message, the proper (adjusted)
2363 // pointers must be used to access those strings
2364 fprintf(file
, "In%dP->%s), %d);" "\n", (variable_length_args_present
? argPtr
->argRequestPos
: 0), argPtr
->argName
, argPtr
->argType
->itNumber
);
2365 fputs("\t\t" "if (", file
);
2366 fprintf(file
, "( strnlen(In%dP->%s, strnlen_limit) >= %d + 1 )", (variable_length_args_present
? argPtr
->argRequestPos
: 0), argPtr
->argName
, argPtr
->argType
->itNumber
);
2367 fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file
);
2368 fputs("#else\n", file
);
2370 // If there are variable-length arguments within the message, the proper (adjusted)
2371 // pointers must be used to access those strings
2372 fprintf(file
, "\t\t" "memchr_limit = min((msg_limit - In%dP->%s), %d);" "\n", (variable_length_args_present
? argPtr
->argRequestPos
: 0), argPtr
->argName
, argPtr
->argType
->itNumber
);
2373 fputs("\t\t" "if (", file
);
2374 fprintf(file
, "( memchr(In%dP->%s, '\\0', memchr_limit) == NULL )", (variable_length_args_present
? argPtr
->argRequestPos
: 0), argPtr
->argName
);
2375 fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file
);
2376 if (IsKernelServer
) {
2377 fputs("#endif /* __MigKernelSpecificCode */" "\n", file
);
2381 fputs("\t" "}" "\n" "#endif" "\t" "/* __MigTypeCheck */" "\n\n", file
); // terminate new scope
2388 WriteOOLSizeCheck(FILE *file
, routine_t
*rt
)
2390 /* Emit code to validate the actual size of ool data vs. the reported size */
2393 boolean_t openedTypeCheckConditional
= FALSE
;
2395 // scan through arguments to see if there are any ool data blocks
2396 for (argPtr
= rt
->rtArgs
; argPtr
!= NULL
; argPtr
= argPtr
->argNext
) {
2397 if (akCheck(argPtr
->argKind
, akbSendKPD
)) {
2398 ipc_type_t
*it
= argPtr
->argType
;
2399 boolean_t multiple_kpd
= IS_MULTIPLE_KPD(it
);
2400 char string
[MAX_STR_LEN
];
2402 argument_t
*argCountPtr
;
2405 if (argPtr
->argKPD_Type
== MACH_MSG_OOL_DESCRIPTOR
) {
2408 if ( !openedTypeCheckConditional
) {
2409 openedTypeCheckConditional
= TRUE
;
2410 fputs("#if __MigTypeCheck\n", file
);
2412 WriteKPD_Iterator(file
, TRUE
, FALSE
, argPtr
, TRUE
);
2414 sprintf(string
, "ptr->");
2415 test
= !it
->itVarArray
&& !it
->itElement
->itVarArray
;
2416 it
= it
->itElement
; // point to element descriptor, so size calculation is correct
2417 argCountPtr
= argPtr
->argSubCount
;
2420 sprintf(string
, "In%dP->%s.", argPtr
->argRequestPos
, argPtr
->argMsgField
);
2421 test
= !it
->itVarArray
;
2422 argCountPtr
= argPtr
->argCount
;
2426 int multiplier
= (argCountPtr
->argMultiplier
> 1 || it
->itSize
> 8) ? argCountPtr
->argMultiplier
* it
->itSize
/ 8 : 1;
2427 if ( !openedTypeCheckConditional
) {
2428 openedTypeCheckConditional
= TRUE
;
2429 fputs("#if __MigTypeCheck\n", file
);
2432 fprintf(file
, "\t%s" "if (%ssize ", tab
, string
);
2434 fprintf(file
, "/ %d ", multiplier
);
2435 fprintf(file
,"!= In%dP->%s%s", argCountPtr
->argRequestPos
, argCountPtr
->argVarName
, multiple_kpd
? "[i]" : "");
2436 if (it
->itOOL_Number
) {
2437 fprintf(file
," || In%dP->%s%s > %d", argCountPtr
->argRequestPos
,
2438 argCountPtr
->argVarName
, multiple_kpd
? "[i]" : "", it
->itOOL_Number
);
2441 fprintf(file
,")\n");
2442 fprintf(file
, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab
);
2446 fprintf(file
, "\t }\n\t}\n");
2447 } else if (argPtr
->argKPD_Type
== MACH_MSG_OOL_PORTS_DESCRIPTOR
) {
2449 if ( !openedTypeCheckConditional
) {
2450 openedTypeCheckConditional
= TRUE
;
2451 fputs("#if __MigTypeCheck\n", file
);
2453 WriteKPD_Iterator(file
, TRUE
, FALSE
, argPtr
, TRUE
);
2455 sprintf(string
, "ptr->");
2456 test
= !it
->itVarArray
&& !it
->itElement
->itVarArray
;
2457 it
= it
->itElement
; // point to element descriptor, so size calculation is correct
2458 argCountPtr
= argPtr
->argSubCount
;
2461 sprintf(string
, "In%dP->%s.", argPtr
->argRequestPos
, argPtr
->argMsgField
);
2462 test
= !it
->itVarArray
;
2463 argCountPtr
= argPtr
->argCount
;
2467 if ( !openedTypeCheckConditional
) {
2468 openedTypeCheckConditional
= TRUE
;
2469 fputs("#if __MigTypeCheck\n", file
);
2472 fprintf(file
, "\t%s" "if (%scount ", tab
, string
);
2473 fprintf(file
,"!= In%dP->%s%s", argCountPtr
->argRequestPos
, argCountPtr
->argVarName
, multiple_kpd
? "[i]" : "");
2474 if (it
->itOOL_Number
) {
2475 fprintf(file
," || In%dP->%s%s > %d", argCountPtr
->argRequestPos
,
2476 argCountPtr
->argVarName
, multiple_kpd
? "[i]" : "", it
->itOOL_Number
);
2478 fprintf(file
,")\n");
2479 fprintf(file
, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab
);
2483 fprintf(file
, "\t }\n\t}\n");
2488 if ( openedTypeCheckConditional
)
2489 fputs("#endif" "\t" "/* __MigTypeCheck */" "\n\n", file
);
2494 WriteCheckRequest(FILE *file
, routine_t
*rt
)
2498 /* initialize the disciplines for the handling of KPDs */
2499 InitKPD_Disciplines(rt
->rtArgs
);
2501 fprintf(file
, "\n");
2502 fprintf(file
, "#if ( __MigTypeCheck ");
2504 fprintf(file
, "|| __NDR_convert__ ");
2505 fprintf(file
, ")\n");
2506 fprintf(file
, "#if __MIG_check__Request__%s_subsystem__\n", SubsystemName
);
2507 fprintf(file
, "#if !defined(__MIG_check__Request__%s_t__defined)\n", rt
->rtName
);
2508 fprintf(file
, "#define __MIG_check__Request__%s_t__defined\n", rt
->rtName
);
2509 if (CheckNDR
&& akCheck(rt
->rtNdrCode
->argKind
, akbRequest
)) {
2510 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertIntRepArgDecl
, akbSendNdr
, "", "");
2511 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertCharRepArgDecl
, akbSendNdr
, "", "");
2512 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertFloatRepArgDecl
, akbSendNdr
, "", "");
2514 fprintf(file
, "\n");
2515 fprintf(file
, "mig_internal kern_return_t __MIG_check__Request__%s_t(__attribute__((__unused__)) __Request__%s_t *In0P", rt
->rtName
, rt
->rtName
);
2516 for (i
= 1; i
<= rt
->rtMaxRequestPos
; i
++)
2517 fprintf(file
, ", __attribute__((__unused__)) __Request__%s_t **In%dPP", rt
->rtName
, i
);
2518 fprintf(file
, ")\n{\n");
2520 fprintf(file
, "\n\ttypedef __Request__%s_t __Request;\n", rt
->rtName
);
2521 for (i
= 1; i
<= rt
->rtMaxRequestPos
; i
++)
2522 fprintf(file
, "\t__Request *In%dP;\n", i
);
2523 if (rt
->rtNumRequestVar
> 0) {
2524 fprintf(file
, "#if\t__MigTypeCheck\n");
2525 fprintf(file
, "\tunsigned int msgh_size;\n");
2526 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
2528 if (rt
->rtMaxRequestPos
> 0)
2529 fprintf(file
, "\tunsigned int msgh_size_delta;\n");
2530 if (rt
->rtNumRequestVar
> 0 || rt
->rtMaxRequestPos
> 0)
2531 fprintf(file
, "\n");
2533 WriteCheckHead(file
, rt
);
2535 WriteList(file
, rt
->rtArgs
, WriteTypeCheck
, akbSendKPD
, "\n", "\n");
2538 argument_t
*arg
, *lastVarArg
;
2540 lastVarArg
= argNULL
;
2541 for (arg
= rt
->rtArgs
; arg
!= argNULL
; arg
= arg
->argNext
) {
2542 if (lastVarArg
!= argNULL
&&
2543 lastVarArg
->argRequestPos
< arg
->argRequestPos
) {
2544 WriteAdjustRequestMsgPtr(file
, lastVarArg
);
2545 lastVarArg
= argNULL
;
2547 if (akCheckAll(arg
->argKind
, akbSendRcv
|akbSendBody
)) {
2548 if (akCheck(arg
->argKind
, akbVariable
)) {
2549 WriteCheckMsgSize(file
, arg
);
2556 if (CheckNDR
&& akCheck(rt
->rtNdrCode
->argKind
, akbRequest
)) {
2557 fprintf(file
, "#if\t");
2558 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertIntRepArgCond
, akbSendNdr
, " || \\\n\t", "\n");
2559 fprintf(file
, "\tif (In0P->NDR.int_rep != NDR_record.int_rep) {\n");
2560 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertIntRepArgUse
, akbSendNdr
, "", "");
2561 fprintf(file
, "\t}\n#endif\t/* defined(__NDR_convert__int_rep...) */\n\n");
2563 WriteOOLSizeCheck(file
, rt
);
2565 fprintf(file
, "#if\t");
2566 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertCharRepArgCond
, akbSendNdr
, " || \\\n\t", "\n");
2567 fprintf(file
, "\tif (In0P->NDR.char_rep != NDR_record.char_rep) {\n");
2568 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertCharRepArgUse
, akbSendNdr
, "", "");
2569 fprintf(file
, "\t}\n#endif\t/* defined(__NDR_convert__char_rep...) */\n\n");
2571 fprintf(file
, "#if\t");
2572 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertFloatRepArgCond
, akbSendNdr
, " || \\\n\t", "\n");
2573 fprintf(file
, "\tif (In0P->NDR.float_rep != NDR_record.float_rep) {\n");
2574 WriteList(file
, rt
->rtArgs
, WriteRequestNDRConvertFloatRepArgUse
, akbSendNdr
, "", "");
2575 fprintf(file
, "\t}\n#endif\t/* defined(__NDR_convert__float_rep...) */\n\n");
2577 WriteOOLSizeCheck(file
, rt
);
2580 WriteStringTerminatorCheck(file
, rt
);
2582 fprintf(file
, "\treturn MACH_MSG_SUCCESS;\n");
2583 fprintf(file
, "}\n");
2584 fprintf(file
, "#endif /* !defined(__MIG_check__Request__%s_t__defined) */\n", rt
->rtName
);
2585 fprintf(file
, "#endif /* __MIG_check__Request__%s_subsystem__ */\n", SubsystemName
);
2586 fprintf(file
, "#endif /* ( __MigTypeCheck ");
2588 fprintf(file
, "|| __NDR_convert__ ");
2589 fprintf(file
, ") */\n");
2590 fprintf(file
, "\n");
2594 WriteCheckRequestCall(FILE *file
, routine_t
*rt
)
2598 fprintf(file
, "\n");
2599 fprintf(file
, "#if\tdefined(__MIG_check__Request__%s_t__defined)\n", rt
->rtName
);
2600 fprintf(file
, "\tcheck_result = __MIG_check__Request__%s_t((__Request *)In0P", rt
->rtName
);
2601 for (i
= 1; i
<= rt
->rtMaxRequestPos
; i
++)
2602 fprintf(file
, ", (__Request **)&In%dP", i
);
2603 fprintf(file
, ");\n");
2604 fprintf(file
, "\tif (check_result != MACH_MSG_SUCCESS)\n");
2605 fprintf(file
, "\t\t{ MIG_RETURN_ERROR(OutP, check_result); }\n");
2606 fprintf(file
, "#endif\t/* defined(__MIG_check__Request__%s_t__defined) */\n", rt
->rtName
);
2607 fprintf(file
, "\n");
2611 WriteCheckRequests(FILE *file
, statement_t
*stats
)
2615 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
2616 if (stat
->stKind
== skRoutine
)
2617 WriteCheckRequest(file
, stat
->stRoutine
);
2621 WriteRoutine(FILE *file
, routine_t
*rt
)
2623 /* Declare the server work function: */
2624 if (ServerHeaderFileName
== strNULL
)
2625 WriteServerRoutine(file
, rt
);
2627 fprintf(file
, "\n");
2629 fprintf(file
, "/* %s %s */\n", rtRoutineKindToStr(rt
->rtKind
), rt
->rtName
);
2630 fprintf(file
, "mig_internal novalue _X%s\n", rt
->rtName
);
2632 fprintf(file
, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
2635 fprintf(file
, "#if\t%s\n", NewCDecl
);
2636 fprintf(file
, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
2637 fprintf(file
, "#else\n");
2638 fprintf(file
, "\t(InHeadP, OutHeadP)\n");
2639 fprintf(file
, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n");
2640 fprintf(file
, "#endif\t/* %s */\n", NewCDecl
);
2643 fprintf(file
, "{\n");
2644 WriteStructDecl(file
, rt
->rtArgs
, WriteFieldDecl
, akbRequest
, "Request", rt
->rtSimpleRequest
, TRUE
, rt
->rtServerImpl
, FALSE
);
2645 fprintf(file
, "\ttypedef __Request__%s_t __Request;\n", rt
->rtName
);
2646 fprintf(file
, "\ttypedef __Reply__%s_t Reply __attribute__((unused));\n\n", rt
->rtName
);
2649 * Define a Minimal Reply structure to be used in case of errors
2651 fprintf(file
, "\t/*\n");
2652 fprintf(file
, "\t * typedef struct {\n");
2653 fprintf(file
, "\t * \tmach_msg_header_t Head;\n");
2654 fprintf(file
, "\t * \tNDR_record_t NDR;\n");
2655 fprintf(file
, "\t * \tkern_return_t RetCode;\n");
2656 fprintf(file
, "\t * } mig_reply_error_t;\n");
2657 fprintf(file
, "\t */\n");
2658 fprintf(file
, "\n");
2660 WriteVarDecls(file
, rt
);
2662 if (IsKernelServer
) {
2663 fprintf(file
, "#if\t__MigKernelSpecificCode\n");
2664 WriteList(file
, rt
->rtArgs
, WriteTemplateDeclOut
, akbReturnKPD
, "\n", "\n");
2665 fprintf(file
, "#else\n");
2667 WriteList(file
, rt
->rtArgs
, WriteTemplateDeclIn
, akbReturnKPD
, "\n", "\n");
2668 if (IsKernelServer
) {
2669 fprintf(file
, "#endif /* __MigKernelSpecificCode */\n");
2671 WriteRetCode(file
, rt
->rtRetCode
);
2672 WriteList(file
, rt
->rtArgs
, WriteLocalVarDecl
, akbVarNeeded
| akbServerArg
, ";\n", ";\n\n");
2673 WriteApplMacro(file
, "Rcv", "Declare", rt
);
2674 WriteApplMacro(file
, "Rcv", "Before", rt
);
2675 if (rt
->rtRetCArg
!= argNULL
&& !rt
->rtSimpleRequest
) {
2676 WriteRetCArgCheckError(file
, rt
);
2677 if (rt
->rtServerImpl
)
2678 WriteCheckTrailerHead(file
, rt
, FALSE
);
2679 WriteServerCall(file
, rt
, WriteConditionalCallArg
);
2680 WriteRetCArgFinishError(file
, rt
);
2683 WriteCheckRequestCall(file
, rt
);
2684 WriteCheckRequestTrailerArgs(file
, rt
);
2687 * Initialize the KPD records in the Reply structure with the
2688 * templates. We do this beforehand because the call to the procedure
2689 * will overwrite some of the values (after the call it would be impossible
2690 * to initialize the KPD records from the static Templates, because we
2693 WriteList(file
, rt
->rtArgs
, WriteInitKPDValue
, akbReturnKPD
, "\n", "\n");
2695 WriteList(file
, rt
->rtArgs
, WriteExtractArg
, akbNone
, "", "");
2698 WriteLogMsg(file
, rt
, LOG_SERVER
, LOG_REQUEST
);
2700 WriteServerCall(file
, rt
, WriteServerCallArg
);
2702 WriteReverseList(file
, rt
->rtArgs
, WriteDestroyArg
, akbDestroy
, "", "");
2705 * For one-way routines, it doesn`t make sense to check the return
2706 * code, because we return immediately afterwards. However,
2707 * kernel servers may want to deallocate port arguments - and the
2708 * deallocation must not be done if the return code is not KERN_SUCCESS.
2710 if (rt
->rtOneWay
|| rt
->rtNoReplyArgs
) {
2711 if (IsKernelServer
) {
2712 fprintf(file
,"#if\t__MigKernelSpecificCode\n");
2713 if (rtCheckMaskFunction(rt
->rtArgs
, akbSendKPD
, CheckDestroyPortArg
)) {
2714 WriteCheckReturnValue(file
, rt
);
2716 WriteReverseList(file
, rt
->rtArgs
, WriteDestroyPortArg
, akbSendKPD
, "", "");
2717 fprintf(file
,"#endif /* __MigKernelSpecificCode */\n");
2719 /* although we have an empty reply, we still have to make sure that
2720 some fields such as NDR get properly initialized */
2722 WriteList(file
, rt
->rtArgs
, WriteInitArgValue
, akbReplyInit
, "\n", "\n");
2725 WriteCheckReturnValue(file
, rt
);
2727 if (IsKernelServer
) {
2728 fprintf(file
,"#if\t__MigKernelSpecificCode\n");
2729 WriteReverseList(file
, rt
->rtArgs
, WriteDestroyPortArg
, akbSendKPD
, "", "");
2730 fprintf(file
,"#endif /* __MigKernelSpecificCode */\n");
2732 WriteReplyArgs(file
, rt
);
2733 WriteReplyInit(file
, rt
);
2734 if (!rt
->rtSimpleReply
)
2735 fprintf(file
, "\tOutP->msgh_body.msgh_descriptor_count = %d;\n", rt
->rtReplyKPDs
);
2738 WriteLogMsg(file
, rt
, LOG_SERVER
, LOG_REPLY
);
2740 WriteApplMacro(file
, "Rcv", "After", rt
);
2741 fprintf(file
, "}\n");
2745 WriteServer(FILE *file
, statement_t
*stats
)
2749 WriteProlog(file
, stats
);
2751 WriteForwardDeclarations(file
, stats
);
2752 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
2753 switch (stat
->stKind
) {
2756 WriteCheckRequest(file
, stat
->stRoutine
);
2757 WriteRoutine(file
, stat
->stRoutine
);
2768 fatal("WriteServer(): bad statement_kind_t (%d)",
2769 (int) stat
->stKind
);
2771 WriteDispatcher(file
, stats
);