2 * Copyright (c) 1999-2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Mach Operating System
25 * Copyright (c) 1991,1990 Carnegie Mellon University
26 * All Rights Reserved.
28 * Permission to use, copy, modify and distribute this software and its
29 * documentation is hereby granted, provided that both the copyright
30 * notice and this permission notice appear in all copies of the
31 * software, derivative works or modified versions, and any portions
32 * thereof, and that both notices appear in supporting documentation.
34 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
35 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
36 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
38 * Carnegie Mellon requests users of this software to return to
40 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
41 * School of Computer Science
42 * Carnegie Mellon University
43 * Pittsburgh PA 15213-3890
45 * any improvements or extensions that they make and grant Carnegie Mellon
46 * the rights to redistribute these changes.
49 #include <mach/message.h>
58 extern char *MessFreeRoutine
;
61 WriteIdentificationString(FILE *file
)
63 extern char * GenerationDate
;
65 fprintf(file
, "/*\n");
66 fprintf(file
, " * IDENTIFICATION:\n");
67 fprintf(file
, " * stub generated %s", GenerationDate
);
68 fprintf(file
, " * with a MiG generated by " MIG_VERSION
"\n");
69 fprintf(file
, " * OPTIONS: \n");
71 fprintf(file
, " *\tKernelUser\n");
73 fprintf(file
, " *\tKernelServer\n");
75 fprintf(file
, " *\t-R (no RPC calls)\n");
76 fprintf(file
, " */\n");
80 WriteMigExternal(FILE *file
)
82 fprintf(file
, "#ifdef\tmig_external\n");
83 fprintf(file
, "mig_external\n");
84 fprintf(file
, "#else\n");
85 fprintf(file
, "extern\n");
86 fprintf(file
, "#endif\t/* mig_external */\n");
90 WriteMigInternal(FILE *file
)
92 fprintf(file
, "#ifdef\tmig_internal\n");
93 fprintf(file
, "mig_internal\n");
94 fprintf(file
, "#else\n");
95 fprintf(file
, "static\n");
96 fprintf(file
, "#endif\t/* mig_internal */\n");
100 WriteImport(FILE *file
, string_t filename
)
102 fprintf(file
, "#include %s\n", filename
);
106 WriteImplImports(FILE *file
, statement_t
*stats
, boolean_t isuser
)
110 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
111 switch (stat
->stKind
) {
115 WriteImport(file
, stat
->stFileName
);
120 WriteImport(file
, stat
->stFileName
);
125 WriteImport(file
, stat
->stFileName
);
133 fatal("WriteImplImport(): bad statement_kind_t (%d)", (int) stat
->stKind
);
138 WriteRCSDecl(FILE *file
, identifier_t name
, string_t rcs
)
140 fprintf(file
, "#ifndef\tlint\n");
141 fprintf(file
, "#if\tUseExternRCSId\n");
142 fprintf(file
, "%s char %s_rcsid[] = %s;\n", (BeAnsiC
) ? "const" : "", name
, rcs
);
143 fprintf(file
, "#else\t/* UseExternRCSId */\n");
144 fprintf(file
, "static %s char rcsid[] = %s;\n", (BeAnsiC
) ? "const" : "", rcs
);
145 fprintf(file
, "#endif\t/* UseExternRCSId */\n");
146 fprintf(file
, "#endif\t/* lint */\n");
151 WriteOneApplDefault(FILE *file
, char *word1
, char *word2
, char *word3
)
155 sprintf(buf
, "__%s%s%s", word1
, word2
, word3
);
156 fprintf(file
, "#ifndef\t%s\n", buf
);
157 fprintf(file
, "#define\t%s(_NUM_, _NAME_)\n", buf
);
158 fprintf(file
, "#endif\t/* %s */\n", buf
);
163 WriteApplDefaults(FILE *file
, char *dir
)
165 WriteOneApplDefault(file
, "Declare", dir
, "Rpc");
166 WriteOneApplDefault(file
, "Before", dir
, "Rpc");
167 WriteOneApplDefault(file
, "After", dir
, "Rpc");
168 WriteOneApplDefault(file
, "Declare", dir
, "Simple");
169 WriteOneApplDefault(file
, "Before", dir
, "Simple");
170 WriteOneApplDefault(file
, "After", dir
, "Simple");
174 WriteApplMacro(FILE *file
, char *dir
, char *when
, routine_t
*rt
)
176 char *what
= (rt
->rtOneWay
) ? "Simple" : "Rpc";
178 fprintf(file
, "\t__%s%s%s(%d, \"%s\")\n", when
, dir
, what
, SubsystemBase
+ rt
->rtNumber
, rt
->rtName
);
183 WriteBogusDefines(FILE *file
)
185 fprintf(file
, "#ifndef\tmig_internal\n");
186 fprintf(file
, "#define\tmig_internal\tstatic __inline__\n");
187 fprintf(file
, "#endif\t/* mig_internal */\n");
190 fprintf(file
, "#ifndef\tmig_external\n");
191 fprintf(file
, "#define mig_external\n");
192 fprintf(file
, "#endif\t/* mig_external */\n");
195 fprintf(file
, "#if\t!defined(__MigTypeCheck) && defined(TypeCheck)\n");
196 fprintf(file
, "#define\t__MigTypeCheck\t\tTypeCheck\t/* Legacy setting */\n");
197 fprintf(file
, "#endif\t/* !defined(__MigTypeCheck) */\n");
200 fprintf(file
, "#if\t!defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)\n");
201 fprintf(file
, "#define\t__MigKernelSpecificCode\t_MIG_KERNEL_SPECIFIC_CODE_\t/* Legacy setting */\n");
202 fprintf(file
, "#endif\t/* !defined(__MigKernelSpecificCode) */\n");
205 fprintf(file
, "#ifndef\tLimitCheck\n");
206 fprintf(file
, "#define\tLimitCheck 0\n");
207 fprintf(file
, "#endif\t/* LimitCheck */\n");
210 fprintf(file
, "#ifndef\tmin\n");
211 fprintf(file
, "#define\tmin(a,b) ( ((a) < (b))? (a): (b) )\n");
212 fprintf(file
, "#endif\t/* min */\n");
215 fprintf(file
, "#if !defined(_WALIGN_)\n");
216 fprintf(file
, "#define _WALIGN_(x) (((x) + %d) & ~%d)\n", (int)(itWordAlign
- 1), (int)(itWordAlign
- 1));
217 fprintf(file
, "#endif /* !defined(_WALIGN_) */\n");
220 fprintf(file
, "#if !defined(_WALIGNSZ_)\n");
221 fprintf(file
, "#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))\n");
222 fprintf(file
, "#endif /* !defined(_WALIGNSZ_) */\n");
225 fprintf(file
, "#ifndef\tUseStaticTemplates\n");
227 fprintf(file
, "#define\tUseStaticTemplates\t0\n");
230 fprintf(file
, "#if\t%s\n", NewCDecl
);
231 fprintf(file
, "#define\tUseStaticTemplates\t0\n");
232 fprintf(file
, "#endif\t/* %s */\n", NewCDecl
);
234 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
237 WriteBogusServerRoutineAnnotationDefine(file
);
241 WriteList(FILE *file
, argument_t
*args
, void (*func
)(FILE *, argument_t
*), u_int mask
, char *between
, char *after
)
244 boolean_t sawone
= FALSE
;
246 for (arg
= args
; arg
!= argNULL
; arg
= arg
->argNext
)
247 if (akCheckAll(arg
->argKind
, mask
)) {
249 fprintf(file
, "%s", between
);
256 fprintf(file
, "%s", after
);
261 WriteReverseListPrim(FILE *file
, argument_t
*arg
, void (*func
)(FILE *, argument_t
*), u_int mask
, char *between
)
263 boolean_t sawone
= FALSE
;
265 if (arg
!= argNULL
) {
266 sawone
= WriteReverseListPrim(file
, arg
->argNext
, func
, mask
, between
);
268 if (akCheckAll(arg
->argKind
, mask
)) {
270 fprintf(file
, "%s", between
);
281 WriteReverseList(FILE *file
, argument_t
*args
, void (*func
)(FILE *file
, argument_t
*args
), u_int mask
, char *between
, char *after
)
285 sawone
= WriteReverseListPrim(file
, args
, func
, mask
, between
);
288 fprintf(file
, "%s", after
);
292 WriteNameDecl(FILE *file
, argument_t
*arg
)
294 fprintf(file
, "%s", arg
->argVarName
);
298 WriteUserVarDecl(FILE *file
, argument_t
*arg
)
300 boolean_t pointer
= (arg
->argByReferenceUser
||arg
->argType
->itNativePointer
);
301 char *ref
= (pointer
) ? "*" : "";
302 char *cnst
= ((arg
->argFlags
& flConst
) &&
303 (IS_VARIABLE_SIZED_UNTYPED(arg
->argType
) ||
304 arg
->argType
->itNoOptArray
|| arg
->argType
->itString
)) ? "const " : "";
306 fprintf(file
, "\t%s%s %s%s", cnst
, arg
->argType
->itUserType
, ref
, arg
->argVarName
);
310 WriteServerVarDecl(FILE *file
, argument_t
*arg
)
312 char *ref
= (arg
->argByReferenceServer
||
313 arg
->argType
->itNativePointer
) ? "*" : "";
314 char *cnst
= ((arg
->argFlags
& flConst
) &&
315 (IS_VARIABLE_SIZED_UNTYPED(arg
->argType
) ||
316 arg
->argType
->itNoOptArray
|| arg
->argType
->itString
)) ? "const " : "";
318 fprintf(file
, "\t%s%s %s%s", cnst
, arg
->argType
->itTransType
, ref
, arg
->argVarName
);
322 ReturnTypeStr(routine_t
*rt
)
324 return rt
->rtRetCode
->argType
->itUserType
;
328 FetchUserType(ipc_type_t
*it
)
330 return it
->itUserType
;
334 FetchServerType(ipc_type_t
*it
)
336 return it
->itServerType
;
340 FetchKPDType(ipc_type_t
*it
)
342 return it
->itKPDType
;
346 WriteTrailerDecl(FILE *file
, boolean_t trailer
)
349 fprintf(file
, "\t\tmach_msg_max_trailer_t trailer;\n");
351 fprintf(file
, "\t\tmach_msg_trailer_t trailer;\n");
355 WriteFieldDeclPrim(FILE *file
, argument_t
*arg
, char *(*tfunc
)(ipc_type_t
*it
))
357 ipc_type_t
*it
= arg
->argType
;
359 if (IS_VARIABLE_SIZED_UNTYPED(it
) || it
->itNoOptArray
) {
360 argument_t
*count
= arg
->argCount
;
361 ipc_type_t
*btype
= it
->itElement
;
364 * Build our own declaration for a varying array:
365 * use the element type and maximum size specified.
366 * Note arg->argCount->argMultiplier == btype->itNumber.
369 * NDR encoded VarStrings requires the offset field.
370 * Since it is not used, it wasn't worthwhile to create an extra
374 fprintf(file
, "\t\t%s %sOffset; /* MiG doesn't use it */\n", (*tfunc
)(count
->argType
), arg
->argName
);
376 if (!(arg
->argFlags
& flSameCount
) && !it
->itNoOptArray
)
377 /* in these cases we would have a count, which we don't want */
378 fprintf(file
, "\t\t%s %s;\n", (*tfunc
)(count
->argType
), count
->argMsgField
);
379 fprintf(file
, "\t\t%s %s[%d];", (*tfunc
)(btype
), arg
->argMsgField
, it
->itNumber
/btype
->itNumber
);
381 else if (IS_MULTIPLE_KPD(it
))
382 fprintf(file
, "\t\t%s %s[%d];", (*tfunc
)(it
), arg
->argMsgField
, it
->itKPD_Number
);
383 else if (IS_OPTIONAL_NATIVE(it
)) {
384 fprintf(file
, "\t\tboolean_t __Present__%s;\n", arg
->argMsgField
);
385 fprintf(file
, "\t\tunion {\n");
386 fprintf(file
, "\t\t %s __Real__%s;\n", (*tfunc
)(it
), arg
->argMsgField
);
387 fprintf(file
, "\t\t char __Phony__%s[_WALIGNSZ_(%s)];\n", arg
->argMsgField
, (*tfunc
)(it
));
388 fprintf(file
, "\t\t} %s;", arg
->argMsgField
);
391 /* either simple KPD or simple in-line */
392 fprintf(file
, "\t\t%s %s;", (*tfunc
)(it
), arg
->argMsgField
);
395 /* Kernel Processed Data has always PadSize = 0 */
396 if (it
->itPadSize
!= 0)
397 fprintf(file
, "\n\t\tchar %s[%d];", arg
->argPadName
, it
->itPadSize
);
401 WriteKPDFieldDecl(FILE *file
, argument_t
*arg
)
403 if (akCheck(arg
->argKind
, akbSendKPD
) ||
404 akCheck(arg
->argKind
, akbReturnKPD
))
405 WriteFieldDeclPrim(file
, arg
, FetchKPDType
);
407 WriteFieldDeclPrim(file
, arg
, FetchServerType
);
414 void (*func
)(FILE *, argument_t
*),
420 boolean_t template_only
)
422 fprintf(file
, "\n#ifdef __MigPackStructs\n#pragma pack(push, %lu)\n#endif\n",sizeof(natural_t
));
423 fprintf(file
, "\ttypedef struct {\n");
424 fprintf(file
, "\t\tmach_msg_header_t Head;\n");
425 if (simple
== FALSE
) {
426 fprintf(file
, "\t\t/* start of the kernel processed data */\n");
427 fprintf(file
, "\t\tmach_msg_body_t msgh_body;\n");
428 if (mask
== akbRequest
)
429 WriteList(file
, args
, func
, mask
| akbSendKPD
, "\n", "\n");
431 WriteList(file
, args
, func
, mask
| akbReturnKPD
, "\n", "\n");
432 fprintf(file
, "\t\t/* end of the kernel processed data */\n");
434 if (!template_only
) {
435 if (mask
== akbRequest
)
436 WriteList(file
, args
, func
, mask
| akbSendBody
, "\n", "\n");
439 WriteList(file
, args
, func
, mask
| akbReturnBody
, "\n", "\n");
441 WriteTrailerDecl(file
, trailer_t
);
443 fprintf(file
, "\t} %s __attribute__((unused));\n", name
);
444 fprintf(file
, "#ifdef __MigPackStructs\n#pragma pack(pop)\n#endif\n");
448 WriteTemplateDeclIn(FILE *file
, argument_t
*arg
)
450 (*arg
->argKPD_Template
)(file
, arg
, TRUE
);
454 WriteTemplateDeclOut(FILE *file
, argument_t
*arg
)
456 (*arg
->argKPD_Template
)(file
, arg
, FALSE
);
460 WriteTemplateKPD_port(FILE *file
, argument_t
*arg
, boolean_t in
)
462 ipc_type_t
*it
= arg
->argType
;
464 fprintf(file
, "#if\tUseStaticTemplates\n");
465 fprintf(file
, "\tconst static %s %s = {\n", it
->itKPDType
, arg
->argTTName
);
467 fprintf(file
, "\t\t/* name = */\t\tMACH_PORT_NULL,\n");
468 fprintf(file
, "\t\t/* pad1 = */\t\t0,\n");
469 fprintf(file
, "\t\t/* pad2 = */\t\t0,\n");
470 fprintf(file
, "\t\t/* disp = */\t\t%s,\n", in
? it
->itInNameStr
: it
->itOutNameStr
);
471 fprintf(file
, "\t\t/* type = */\t\tMACH_MSG_PORT_DESCRIPTOR,\n");
473 fprintf(file
, "\t};\n");
474 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
478 WriteTemplateKPD_ool(FILE *file
, argument_t
*arg
, boolean_t in
)
480 ipc_type_t
*it
= arg
->argType
;
482 fprintf(file
, "#if\tUseStaticTemplates\n");
483 fprintf(file
, "\tconst static %s %s = {\n", it
->itKPDType
, arg
->argTTName
);
485 if (IS_MULTIPLE_KPD(it
))
488 fprintf(file
, "\t\t/* addr = */\t\t(void *)0,\n");
490 fprintf(file
, "\t\t/* size = */\t\t0,\n");
492 fprintf(file
, "\t\t/* size = */\t\t%d,\n", (it
->itNumber
* it
->itSize
+ 7)/8);
493 fprintf(file
, "\t\t/* deal = */\t\t%s,\n", (arg
->argDeallocate
== d_YES
) ? "TRUE" : "FALSE");
494 /* the d_MAYBE case will be fixed runtime */
495 fprintf(file
, "\t\t/* copy = */\t\t%s,\n", (arg
->argFlags
& flPhysicalCopy
) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY");
496 /* the PHYSICAL COPY flag has not been established yet */
497 fprintf(file
, "\t\t/* pad2 = */\t\t0,\n");
498 fprintf(file
, "\t\t/* type = */\t\tMACH_MSG_OOL_DESCRIPTOR,\n");
500 fprintf(file
, "\t};\n");
501 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
505 WriteTemplateKPD_oolport(FILE *file
, argument_t
*arg
, boolean_t in
)
507 ipc_type_t
*it
= arg
->argType
;
509 fprintf(file
, "#if\tUseStaticTemplates\n");
510 fprintf(file
, "\tconst static %s %s = {\n", it
->itKPDType
, arg
->argTTName
);
512 if (IS_MULTIPLE_KPD(it
))
515 fprintf(file
, "\t\t/* addr = */\t\t(void *)0,\n");
517 fprintf(file
, "\t\t/* coun = */\t\t%d,\n", it
->itNumber
);
519 fprintf(file
, "\t\t/* coun = */\t\t0,\n");
520 fprintf(file
, "\t\t/* deal = */\t\t%s,\n", (arg
->argDeallocate
== d_YES
) ? "TRUE" : "FALSE");
521 fprintf(file
, "\t\t/* copy is meaningful only in overwrite mode */\n");
522 fprintf(file
, "\t\t/* copy = */\t\tMACH_MSG_PHYSICAL_COPY,\n");
523 fprintf(file
, "\t\t/* disp = */\t\t%s,\n", in
? it
->itInNameStr
: it
->itOutNameStr
);
524 fprintf(file
, "\t\t/* type = */\t\tMACH_MSG_OOL_PORTS_DESCRIPTOR,\n");
526 fprintf(file
, "\t};\n");
527 fprintf(file
, "#endif\t/* UseStaticTemplates */\n");
531 WriteReplyTypes(FILE *file
, statement_t
*stats
)
535 fprintf(file
, "/* typedefs for all replies */\n\n");
536 fprintf(file
, "#ifndef __Reply__%s_subsystem__defined\n", SubsystemName
);
537 fprintf(file
, "#define __Reply__%s_subsystem__defined\n", SubsystemName
);
538 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
) {
539 if (stat
->stKind
== skRoutine
) {
541 char str
[MAX_STR_LEN
];
543 rt
= stat
->stRoutine
;
544 sprintf(str
, "__Reply__%s_t", rt
->rtName
);
545 WriteStructDecl(file
, rt
->rtArgs
, WriteKPDFieldDecl
, akbReply
, str
, rt
->rtSimpleReply
, FALSE
, FALSE
, FALSE
);
548 fprintf(file
, "#endif /* !__Reply__%s_subsystem__defined */\n", SubsystemName
);
553 WriteRequestTypes(FILE *file
, statement_t
*stats
)
557 fprintf(file
, "/* typedefs for all requests */\n\n");
558 fprintf(file
, "#ifndef __Request__%s_subsystem__defined\n", SubsystemName
);
559 fprintf(file
, "#define __Request__%s_subsystem__defined\n", SubsystemName
);
560 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
) {
561 if (stat
->stKind
== skRoutine
) {
563 char str
[MAX_STR_LEN
];
565 rt
= stat
->stRoutine
;
566 sprintf(str
, "__Request__%s_t", rt
->rtName
);
567 WriteStructDecl(file
, rt
->rtArgs
, WriteKPDFieldDecl
, akbRequest
, str
, rt
->rtSimpleRequest
, FALSE
, FALSE
, FALSE
);
570 fprintf(file
, "#endif /* !__Request__%s_subsystem__defined */\n", SubsystemName
);
575 WriteNDRConvertArgDecl(FILE *file
, argument_t
*arg
, char *convert
, char *dir
)
577 argument_t
*count
= arg
->argCount
;
578 argument_t
*parent
= arg
->argParent
;
579 char *carg
= (count
) ? ", c" : "";
580 routine_t
*rt
= arg
->argRoutine
;
581 ipc_type_t
*ptype
= arg
->argType
;
584 char domain
[MAX_STR_LEN
];
586 fprintf(file
, "#ifndef __NDR_convert__%s__%s__%s_t__%s__defined\n#", convert
, dir
, rt
->rtName
, arg
->argMsgField
);
588 for (btype
= ptype
, multi
= (!parent
) ? arg
->argMultiplier
: 1, array
= 0;
590 ptype
= btype
, array
+= ptype
->itVarArray
, btype
= btype
->itElement
) {
593 if (btype
->itNumber
< ptype
->itNumber
&& !ptype
->itVarArray
&& !parent
) {
594 multi
*= ptype
->itNumber
/ btype
->itNumber
;
595 if (!btype
->itString
)
598 else if (array
&& ptype
->itVarArray
)
601 fprintf(file
, "#el");
603 bttype
= (multi
> 1 && btype
->itString
) ? "string" : FetchServerType(btype
);
604 sprintf(domain
, "__%s", SubsystemName
);
606 fprintf(file
, "if\tdefined(__NDR_convert__%s%s__%s__defined)\n", convert
, domain
, bttype
);
607 fprintf(file
, "#define\t__NDR_convert__%s__%s__%s_t__%s__defined\n", convert
, dir
, rt
->rtName
, arg
->argMsgField
);
608 fprintf(file
, "#define\t__NDR_convert__%s__%s__%s_t__%s(a, f%s) \\\n\t", convert
, dir
, rt
->rtName
, arg
->argMsgField
, carg
);
612 fprintf(file
, "__NDR_convert__2DARRAY((%s *)(a), f, %d, c, ", bttype
, multi
);
614 fprintf(file
, "__NDR_convert__ARRAY((%s *)(a), f, %d * (c), ", bttype
, multi
);
616 else if (!btype
->itString
)
617 fprintf(file
, "__NDR_convert__ARRAY((%s *)(a), f, %d, ", bttype
, multi
);
620 fprintf(file
, "__NDR_convert__ARRAY((%s *)(a), f, c, ", bttype
);
621 fprintf(file
, "__NDR_convert__%s%s__%s", convert
, domain
, bttype
);
623 if (!array
&& btype
->itString
)
624 fprintf(file
, "(a, f, %d", multi
);
627 fprintf(file
, "((%s *)(a), f%s", bttype
, carg
);
628 fprintf(file
, ")\n");
629 } while (strcmp(domain
, "") && ((void)(domain
[0] = '\0'), fprintf(file
, "#el")));
631 fprintf(file
, "#endif /* defined(__NDR_convert__*__defined) */\n");
632 fprintf(file
, "#endif /* __NDR_convert__%s__%s__%s_t__%s__defined */\n\n", convert
, dir
, rt
->rtName
, arg
->argMsgField
);
636 * Like vfprintf, but omits a leading comment in the format string
637 * and skips the items that would be printed by it. Only %s, %d,
638 * and %f are recognized.
641 SkipVFPrintf(FILE *file
, char *fmt
, va_list pvar
)
644 return; /* degenerate case */
646 if (fmt
[0] == '/' && fmt
[1] == '*') {
647 /* Format string begins with C comment. Scan format
648 string until end-comment delimiter, skipping the
649 items in pvar that the enclosed format items would
658 return; /* nothing to format */
670 (void) va_arg(pvar
, char *);
674 (void) va_arg(pvar
, int);
678 (void) va_arg(pvar
, double);
682 return; /* error - fmt ends with '%' */
689 /* End of comment. To be pretty, skip
690 the space that follows. */
696 /* Now format the string. */
697 (void) vfprintf(file
, fmt
, pvar
);
701 vWriteCopyType(FILE *file
, ipc_type_t
*it
, boolean_t mig_allocated_buf
, char *left
, char *right
, va_list pvar
)
704 va_copy(pvar2
, pvar
);
709 (void) SkipVFPrintf(file
, left
, pvar
);
710 fprintf(file
, " = ");
711 (void) SkipVFPrintf(file
, right
, pvar2
);
712 fprintf(file
, ";\n");
714 else if (it
->itString
) {
715 va_list pvar3
, pvar4
;
716 va_copy(pvar3
, pvar
);
717 va_copy(pvar4
, pvar
);
719 if (mig_allocated_buf
) {
721 * zero-fill MIG allocated buffers: we control the size so there's
722 * no risk of buffer overrun, and we avoid leaking process/kernel
723 * memory on the copy-out
725 fprintf(file
, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
726 fprintf(file
, "\tif (mig_strncpy_zerofill != NULL) {\n");
727 fprintf(file
, "\t\t(void) mig_strncpy_zerofill(");
728 (void) SkipVFPrintf(file
, left
, pvar
);
730 (void) SkipVFPrintf(file
, right
, pvar2
);
731 fprintf(file
, ", %d);\n", it
->itTypeSize
);
732 fprintf(file
, "\t} else {\n");
733 fprintf(file
, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n\t");
735 fprintf(file
, "\t(void) mig_strncpy(");
737 (void) SkipVFPrintf(file
, left
, pvar3
);
739 (void) SkipVFPrintf(file
, right
, pvar4
);
740 fprintf(file
, ", %d);\n", it
->itTypeSize
);
742 if (mig_allocated_buf
) {
743 fprintf(file
, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
744 fprintf(file
, "\t}\n");
745 fprintf(file
, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");
752 fprintf(file
, "\t{ typedef struct { char data[%d]; } *sp;\n", it
->itTypeSize
);
753 fprintf(file
, "\t * (sp) ");
754 (void) SkipVFPrintf(file
, left
, pvar
);
755 fprintf(file
, " = * (sp) ");
756 (void) SkipVFPrintf(file
, right
, pvar2
);
757 fprintf(file
, ";\n\t}\n");
767 WriteCopyType(FILE *file
, ipc_type_t
*it
, boolean_t mig_allocated_buf
, char *left
, char *right
, ...)
770 va_start(pvar
, right
);
772 vWriteCopyType(file
, it
, mig_allocated_buf
, left
, right
, pvar
);
781 WriteCopyArg(FILE *file
, argument_t
*arg
, boolean_t mig_allocated_buf
, char *left
, char *right
, ...)
784 va_start(pvar
, right
);
787 ipc_type_t
*it
= arg
->argType
;
788 if (it
->itVarArray
&& !it
->itString
) {
789 fprintf(file
, "\t (void)memcpy(");
790 (void) SkipVFPrintf(file
, left
, pvar
);
793 va_start(pvar
, right
);
794 (void) SkipVFPrintf(file
, right
, pvar
);
795 fprintf(file
, ", %s);\n", arg
->argCount
->argVarName
);
798 vWriteCopyType(file
, it
, mig_allocated_buf
, left
, right
, pvar
);
806 * Global KPD disciplines
809 KPD_error(FILE *file
, argument_t
*arg
)
811 printf("MiG internal error: argument is %s\n", arg
->argVarName
);
816 KPD_noop(FILE *file
, argument_t
*arg
)
818 /* Nothing to see here, people. Move it along... */
822 WriteStringDynArgs(argument_t
*args
, u_int mask
, string_t InPOutP
, string_t
*str_oolports
, string_t
*str_ool
)
825 char loc
[100], sub
[20];
826 string_t tmp_str1
= "";
827 string_t tmp_str2
= "";
828 int cnt
, multiplier
= 1;
829 boolean_t test
, complex = FALSE
;
831 for (arg
= args
; arg
!= argNULL
; arg
= arg
->argNext
) {
832 ipc_type_t
*it
= arg
->argType
;
834 if (IS_MULTIPLE_KPD(it
)) {
835 test
= it
->itVarArray
|| it
->itElement
->itVarArray
;
837 multiplier
= it
->itKPD_Number
;
843 test
= it
->itVarArray
;
848 sprintf(sub
, "[%d]", multiplier
- cnt
);
849 if (akCheck(arg
->argKind
, mask
) &&
850 it
->itPortType
&& !it
->itInLine
&& test
) {
851 sprintf(loc
, " + %s->%s%s.count", InPOutP
, arg
->argMsgField
, complex ? sub
: "");
852 tmp_str1
= strconcat(tmp_str1
, loc
);
854 if (akCheck(arg
->argKind
, mask
) &&
855 !it
->itInLine
&& !it
->itPortType
&& test
) {
856 sprintf(loc
, " + %s->%s%s.size", InPOutP
, arg
->argMsgField
, complex ? sub
: "");
857 tmp_str2
= strconcat(tmp_str2
, loc
);
862 *str_oolports
= tmp_str1
;
867 * Utilities for Logging Events that happen at the stub level
870 WriteLogMsg(FILE *file
, routine_t
*rt
, int where
, int what
)
873 string_t StringOolPorts
= strNULL
;
874 string_t StringOOL
= strNULL
;
875 u_int ports
, oolports
, ool
;
878 fprintf(file
, "\n#if MIG_DEBUG\n");
879 if (where
== LOG_USER
)
880 fprintf(file
, "\tLOG_TRACE(MACH_MSG_LOG_USER,\n");
882 fprintf(file
, "\tLOG_TRACE(MACH_MSG_LOG_SERVER,\n");
883 if (where
== LOG_USER
&& what
== LOG_REQUEST
) {
885 event
= "MACH_MSG_REQUEST_BEING_SENT";
887 else if (where
== LOG_USER
&& what
== LOG_REPLY
) {
889 event
= "MACH_MSG_REPLY_BEING_RCVD";
891 else if (where
== LOG_SERVER
&& what
== LOG_REQUEST
) {
893 event
= "MACH_MSG_REQUEST_BEING_RCVD";
897 event
= "MACH_MSG_REPLY_BEING_SENT";
899 WriteStringDynArgs(rt
->rtArgs
, (what
== LOG_REQUEST
) ? akbSendKPD
: akbReturnKPD
, ptr_str
, &StringOolPorts
, &StringOOL
);
900 fprintf(file
, "\t\t%s,\n", event
);
901 fprintf(file
, "\t\t%s->Head.msgh_id,\n", ptr_str
);
902 if (where
== LOG_USER
&& what
== LOG_REQUEST
) {
903 if (rt
->rtNumRequestVar
)
904 fprintf(file
, "\t\tmsgh_size,\n");
906 fprintf(file
, "\t\t(mach_msg_size_t)sizeof(Request),\n");
909 fprintf(file
, "\t\t%s->Head.msgh_size,\n", ptr_str
);
910 if ((what
== LOG_REQUEST
&& rt
->rtSimpleRequest
== FALSE
) ||
911 (what
== LOG_REPLY
&& rt
->rtSimpleReply
== FALSE
))
912 fprintf(file
, "\t\t%s->msgh_body.msgh_descriptor_count,\n", ptr_str
);
914 fprintf(file
, "\t\t0, /* Kernel Proc. Data entries */\n");
915 if (what
== LOG_REQUEST
) {
916 fprintf(file
, "\t\t0, /* RetCode */\n");
917 ports
= rt
->rtCountPortsIn
;
918 oolports
= rt
->rtCountOolPortsIn
;
919 ool
= rt
->rtCountOolIn
;
922 if (akCheck(rt
->rtRetCode
->argKind
, akbReply
))
923 fprintf(file
, "\t\t%s->RetCode,\n", ptr_str
);
925 fprintf(file
, "\t\t0, /* RetCode */\n");
926 ports
= rt
->rtCountPortsOut
;
927 oolports
= rt
->rtCountOolPortsOut
;
928 ool
= rt
->rtCountOolOut
;
930 fprintf(file
, "\t\t/* Ports */\n");
931 fprintf(file
, "\t\t%d,\n", ports
);
932 fprintf(file
, "\t\t/* Out-of-Line Ports */\n");
933 fprintf(file
, "\t\t%d", oolports
);
934 if (StringOolPorts
!= strNULL
)
935 fprintf(file
, "%s,\n", StringOolPorts
);
937 fprintf(file
, ",\n");
938 fprintf(file
, "\t\t/* Out-of-Line Bytes */\n");
939 fprintf(file
, "\t\t%d", ool
);
940 if (StringOOL
!= strNULL
)
941 fprintf(file
, "%s,\n", StringOOL
);
943 fprintf(file
, ",\n");
944 fprintf(file
, "\t\t__FILE__, __LINE__);\n");
945 fprintf(file
, "#endif /* MIG_DEBUG */\n\n");
949 WriteLogDefines(FILE *file
, string_t who
)
951 fprintf(file
, "#if MIG_DEBUG\n");
952 fprintf(file
, "#define LOG_W_E(X)\tLOG_ERRORS(%s, \\\n", who
);
953 fprintf(file
, "\t\t\tMACH_MSG_ERROR_WHILE_PARSING, (void *)(X), __FILE__, __LINE__)\n");
954 fprintf(file
, "#else /* MIG_DEBUG */\n");
955 fprintf(file
, "#define LOG_W_E(X)\n");
956 fprintf(file
, "#endif /* MIG_DEBUG */\n");
960 /* common utility to report errors */
962 WriteReturnMsgError(FILE *file
, routine_t
*rt
, boolean_t isuser
, argument_t
*arg
, string_t error
)
964 char space
[MAX_STR_LEN
];
965 string_t string
= &space
[0];
967 if (UseEventLogger
&& arg
!= argNULL
)
968 sprintf(string
, "LOG_W_E(\"%s\"); ", arg
->argVarName
);
972 fprintf(file
, "\t\t{ ");
975 if (! rtMessOnStack(rt
))
976 fprintf(file
, "%s((char *) Mess, (mach_msg_size_t)sizeof(*Mess)); ", MessFreeRoutine
);
978 fprintf(file
, "%sreturn %s; }\n", string
, error
);
981 fprintf(file
, "%sMIG_RETURN_ERROR(OutP, %s); }\n", string
, error
);
984 /* executed iff elements are defined */
986 WriteCheckTrailerHead(FILE *file
, routine_t
*rt
, boolean_t isuser
)
988 string_t who
= (isuser
) ? "Out0P" : "In0P";
990 fprintf(file
, "\tTrailerP = (mach_msg_max_trailer_t *)((vm_offset_t)%s +\n", who
);
991 fprintf(file
, "\t\tround_msg(%s->Head.msgh_size));\n", who
);
992 fprintf(file
, "\tif (TrailerP->msgh_trailer_type != MACH_MSG_TRAILER_FORMAT_0)\n");
994 fprintf(file
, "\t\t{ return MIG_TRAILER_ERROR ; }\n");
996 fprintf(file
, "\t\t{ MIG_RETURN_ERROR(%s, MIG_TRAILER_ERROR); }\n", who
);
998 fprintf(file
, "#if\t__MigTypeCheck\n");
999 fprintf(file
, "\ttrailer_size = TrailerP->msgh_trailer_size -\n");
1000 fprintf(file
, "\t\t(mach_msg_size_t)(sizeof(mach_msg_trailer_type_t) - sizeof(mach_msg_trailer_size_t));\n");
1001 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");
1004 /* executed iff elements are defined */
1006 WriteCheckTrailerSize(FILE *file
, boolean_t isuser
, argument_t
*arg
)
1008 fprintf(file
, "#if\t__MigTypeCheck\n");
1009 if (akIdent(arg
->argKind
) == akeMsgSeqno
) {
1010 fprintf(file
, "\tif (trailer_size < (mach_msg_size_t)sizeof(mach_port_seqno_t))\n");
1012 fprintf(file
, "\t\t{ return MIG_TRAILER_ERROR ; }\n");
1014 fprintf(file
, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n");
1015 fprintf(file
, "\ttrailer_size -= (mach_msg_size_t)sizeof(mach_port_seqno_t);\n");
1017 else if (akIdent(arg
->argKind
) == akeSecToken
) {
1018 fprintf(file
, "\tif (trailer_size < (mach_msg_size_t)sizeof(security_token_t))\n");
1020 fprintf(file
, "\t\t{ return MIG_TRAILER_ERROR ; }\n");
1022 fprintf(file
, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n");
1023 fprintf(file
, "\ttrailer_size -= (mach_msg_size_t)sizeof(security_token_t);\n");
1025 else if (akIdent(arg
->argKind
) == akeAuditToken
) {
1026 fprintf(file
, "\tif (trailer_size < (mach_msg_size_t)sizeof(audit_token_t))\n");
1028 fprintf(file
, "\t\t{ return MIG_TRAILER_ERROR ; }\n");
1030 fprintf(file
, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n");
1031 fprintf(file
, "\ttrailer_size -= (mach_msg_size_t)sizeof(audit_token_t);\n");
1033 else if (akIdent(arg
->argKind
) == akeContextToken
) {
1034 fprintf(file
, "\tif (trailer_size < (mach_msg_size_t)sizeof(mach_vm_address_t))\n");
1036 fprintf(file
, "\t\t{ return MIG_TRAILER_ERROR ; }\n");
1038 fprintf(file
, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n");
1039 fprintf(file
, "\ttrailer_size -= (mach_msg_size_t)sizeof(mach_vm_address_t);\n");
1041 fprintf(file
, "#endif\t/* __MigTypeCheck */\n");