]>
git.cameronkatri.com Git - apple_cmds.git/blob - bootstrap_cmds/migcom.tproj/header.c
2 * Copyright (c) 1999-2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Mach Operating System
25 * Copyright (c) 1991,1990 Carnegie Mellon University
26 * All Rights Reserved.
28 * Permission to use, copy, modify and distribute this software and its
29 * documentation is hereby granted, provided that both the copyright
30 * notice and this permission notice appear in all copies of the
31 * software, derivative works or modified versions, and any portions
32 * thereof, and that both notices appear in supporting documentation.
34 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
35 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
36 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
38 * Carnegie Mellon requests users of this software to return to
40 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
41 * School of Computer Science
42 * Carnegie Mellon University
43 * Pittsburgh PA 15213-3890
45 * any improvements or extensions that they make and grant Carnegie the
46 * rights to redistribute these changes.
57 WriteIncludes(FILE *file
, boolean_t isuser
, boolean_t isdef
)
60 fprintf(file
, "#include <mach/port.h>\n");
61 fprintf(file
, "#include <mach/machine/kern_return.h>\n");
63 fprintf(file
, "#include <mach/mig_errors.h>\n");
66 fprintf(file
, "#include <string.h>\n");
67 fprintf(file
, "#include <mach/ndr.h>\n");
68 fprintf(file
, "#include <mach/boolean.h>\n");
69 fprintf(file
, "#include <mach/kern_return.h>\n");
70 fprintf(file
, "#include <mach/notify.h>\n");
71 fprintf(file
, "#include <mach/mach_types.h>\n");
72 fprintf(file
, "#include <mach/message.h>\n");
73 fprintf(file
, "#include <mach/mig_errors.h>\n");
74 fprintf(file
, "#include <mach/port.h>\n");
76 if (IsVoucherCodeAllowed
&& !IsKernelUser
&& !IsKernelServer
) {
77 fprintf(file
, "\t\n/* BEGIN VOUCHER CODE */\n\n");
78 fprintf(file
, "#ifndef KERNEL\n");
79 fprintf(file
, "#if defined(__has_include)\n");
80 fprintf(file
, "#if __has_include(<mach/mig_voucher_support.h>)\n");
81 fprintf(file
, "#ifndef USING_VOUCHERS\n");
82 fprintf(file
, "#define USING_VOUCHERS\n");
83 fprintf(file
, "#endif\n");
86 fprintf(file
, "#ifndef __VOUCHER_FORWARD_TYPE_DECLS__\n");
87 fprintf(file
, "#define __VOUCHER_FORWARD_TYPE_DECLS__\n");
89 fprintf(file
, "#ifdef __cplusplus\n");
90 fprintf(file
, "extern \"C\" {\n");
91 fprintf(file
, "#endif\n");
93 fprintf(file
, "\textern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));\n");
95 fprintf(file
, "#ifdef __cplusplus\n");
97 fprintf(file
, "#endif\n");
99 fprintf(file
, "#endif // __VOUCHER_FORWARD_TYPE_DECLS__\n");
100 fprintf(file
, "#endif // __has_include(<mach/mach_voucher_types.h>)\n");
101 fprintf(file
, "#endif // __has_include\n");
102 fprintf(file
, "#endif // !KERNEL\n");
104 fprintf(file
, "\t\n/* END VOUCHER CODE */\n\n");
107 fprintf(file
, "\t\n/* BEGIN MIG_STRNCPY_ZEROFILL CODE */\n\n");
108 fprintf(file
, "#if defined(__has_include)\n");
109 fprintf(file
, "#if __has_include(<mach/mig_strncpy_zerofill_support.h>)\n");
110 fprintf(file
, "#ifndef USING_MIG_STRNCPY_ZEROFILL\n");
111 fprintf(file
, "#define USING_MIG_STRNCPY_ZEROFILL\n");
112 fprintf(file
, "#endif\n");
114 fprintf(file
, "#ifndef __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__\n");
115 fprintf(file
, "#define __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__\n");
117 fprintf(file
, "#ifdef __cplusplus\n");
118 fprintf(file
, "extern \"C\" {\n");
119 fprintf(file
, "#endif\n");
121 fprintf(file
, "\textern int mig_strncpy_zerofill(char *dest, const char *src, int len) __attribute__((weak_import));\n");
123 fprintf(file
, "#ifdef __cplusplus\n");
124 fprintf(file
, "}\n");
125 fprintf(file
, "#endif\n");
127 fprintf(file
, "#endif /* __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ */\n");
128 fprintf(file
, "#endif /* __has_include(<mach/mig_strncpy_zerofill_support.h>) */\n");
129 fprintf(file
, "#endif /* __has_include */\n");
130 fprintf(file
, "\t\n/* END MIG_STRNCPY_ZEROFILL CODE */\n\n");
133 fprintf(file
, "#include <mach/rpc.h>\n");
134 if (isuser
&& IsKernelUser
) {
135 fprintf(file
, "#if\t(__MigKernelSpecificCode) || (_MIG_KERNEL_SPECIFIC_CODE_)\n");
136 fprintf(file
, "#include <kern/ipc_mig.h>\n");
137 fprintf(file
, "#endif /* __MigKernelSpecificCode */\n");
144 WriteETAPDefines(FILE *file
)
151 fprintf(file
, "\n#ifndef subsystem_to_name_map_%s\n", SubsystemName
);
152 fprintf(file
, "#define subsystem_to_name_map_%s \\\n", SubsystemName
);
153 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
154 if (stat
->stKind
== skRoutine
) {
155 fnum
= SubsystemBase
+ stat
->stRoutine
->rtNumber
;
156 fname
= stat
->stRoutine
->rtName
;
158 fprintf(file
, ",\\\n");
159 fprintf(file
, " { \"%s\", %d }", fname
, fnum
);
162 fprintf(file
, "\n#endif\n");
166 WriteProlog(FILE *file
, char *protect
, boolean_t more
, boolean_t isuser
)
168 if (protect
!= strNULL
) {
169 fprintf(file
, "#ifndef\t_%s\n", protect
);
170 fprintf(file
, "#define\t_%s\n", protect
);
174 fprintf(file
, "/* Module %s */\n", SubsystemName
);
178 WriteIncludes(file
, isuser
, UseSplitHeaders
);
180 fprintf(file
, "#ifdef AUTOTEST\n");
181 fprintf(file
, "#ifndef FUNCTION_PTR_T\n");
182 fprintf(file
, "#define FUNCTION_PTR_T\n");
183 fprintf(file
, "typedef void (*function_ptr_t)");
184 fprintf(file
, "(mach_port_t, char *, mach_msg_type_number_t);\n");
185 fprintf(file
, "typedef struct {\n");
186 fprintf(file
, " char *name;\n");
187 fprintf(file
, " function_ptr_t function;\n");
188 fprintf(file
, "} function_table_entry;\n");
189 fprintf(file
, "typedef function_table_entry *function_table_t;\n");
190 fprintf(file
, "#endif /* FUNCTION_PTR_T */\n");
191 fprintf(file
, "#endif /* AUTOTEST */\n");
192 fprintf(file
, "\n#ifndef\t%s_MSG_COUNT\n", SubsystemName
);
193 fprintf(file
, "#define\t%s_MSG_COUNT\t%d\n", SubsystemName
, rtNumber
);
194 fprintf(file
, "#endif\t/* %s_MSG_COUNT */\n\n", SubsystemName
);
198 WriteEpilog(FILE *file
, char *protect
, boolean_t isuser
)
200 char *defname
= isuser
? "__AfterMigUserHeader" : "__AfterMigServerHeader";
202 WriteETAPDefines(file
);
203 fprintf(file
, "\n#ifdef %s\n%s\n#endif /* %s */\n", defname
, defname
, defname
);
204 if (protect
!= strNULL
) {
206 fprintf(file
, "#endif\t /* _%s */\n", protect
);
211 WriteUserRoutine(FILE *file
, routine_t
*rt
)
214 fprintf(file
, "/* %s %s */\n", rtRoutineKindToStr(rt
->rtKind
), rt
->rtName
);
215 WriteMigExternal(file
);
216 fprintf(file
, "%s %s\n", ReturnTypeStr(rt
), rt
->rtUserName
);
218 fprintf(file
, "#if\t%s\n", LintLib
);
220 WriteList(file
, rt
->rtArgs
, WriteNameDecl
, akbUserArg
, ", " , "");
221 fprintf(file
, ")\n");
222 WriteList(file
, rt
->rtArgs
, WriteUserVarDecl
, akbUserArg
, ";\n", ";\n");
224 fprintf(file
, "return ");
225 fprintf(file
, "%s(", rt
->rtUserName
);
226 WriteList(file
, rt
->rtArgs
, WriteNameDecl
, akbUserArg
, ", ", "");
227 fprintf(file
, "); }\n");
228 fprintf(file
, "#else\n");
231 fprintf(file
, "(\n");
232 WriteList(file
, rt
->rtArgs
, WriteUserVarDecl
, akbUserArg
, ",\n", "\n");
233 fprintf(file
, ");\n");
236 fprintf(file
, "#if\t%s\n", NewCDecl
);
237 fprintf(file
, "(\n");
238 WriteList(file
, rt
->rtArgs
, WriteUserVarDecl
, akbUserArg
, ",\n", "\n");
239 fprintf(file
, ");\n");
240 fprintf(file
, "#else\n");
242 fprintf(file
, " ();\n");
243 fprintf(file
, "#endif\t/* %s */\n", NewCDecl
);
246 fprintf(file
, "#endif\t/* %s */\n", LintLib
);
251 WriteUserRequestUnion(FILE *file
, statement_t
*stats
)
255 fprintf(file
, "/* union of all requests */\n\n");
256 fprintf(file
, "#ifndef __RequestUnion__%s%s_subsystem__defined\n", UserPrefix
, SubsystemName
);
257 fprintf(file
, "#define __RequestUnion__%s%s_subsystem__defined\n", UserPrefix
, SubsystemName
);
258 fprintf(file
, "union __RequestUnion__%s%s_subsystem {\n", UserPrefix
, SubsystemName
);
259 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
) {
260 if (stat
->stKind
== skRoutine
) {
263 rt
= stat
->stRoutine
;
264 fprintf(file
, "\t__Request__%s_t Request_%s;\n", rt
->rtName
, rt
->rtUserName
);
267 fprintf(file
, "};\n");
268 fprintf(file
, "#endif /* !__RequestUnion__%s%s_subsystem__defined */\n", UserPrefix
, SubsystemName
);
272 WriteUserReplyUnion(FILE *file
, statement_t
*stats
)
276 fprintf(file
, "/* union of all replies */\n\n");
277 fprintf(file
, "#ifndef __ReplyUnion__%s%s_subsystem__defined\n", UserPrefix
, SubsystemName
);
278 fprintf(file
, "#define __ReplyUnion__%s%s_subsystem__defined\n", UserPrefix
, SubsystemName
);
279 fprintf(file
, "union __ReplyUnion__%s%s_subsystem {\n", UserPrefix
, SubsystemName
);
280 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
) {
281 if (stat
->stKind
== skRoutine
) {
284 rt
= stat
->stRoutine
;
285 fprintf(file
, "\t__Reply__%s_t Reply_%s;\n", rt
->rtName
, rt
->rtUserName
);
288 fprintf(file
, "};\n");
289 fprintf(file
, "#endif /* !__RequestUnion__%s%s_subsystem__defined */\n", UserPrefix
, SubsystemName
);
293 WriteUserHeader(FILE *file
, statement_t
*stats
)
296 char *protect
= strconcat(SubsystemName
, "_user_");
298 WriteProlog(file
, protect
, TRUE
, TRUE
);
299 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
300 switch (stat
->stKind
) {
305 WriteImport(file
, stat
->stFileName
);
314 fatal("WriteHeader(): bad statement_kind_t (%d)", (int) stat
->stKind
);
317 fprintf(file
, "#ifdef __BeforeMigUserHeader\n");
318 fprintf(file
, "__BeforeMigUserHeader\n");
319 fprintf(file
, "#endif /* __BeforeMigUserHeader */\n");
321 fprintf(file
, "#include <sys/cdefs.h>\n");
322 fprintf(file
, "__BEGIN_DECLS\n");
324 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
) {
325 if (stat
->stKind
== skRoutine
)
326 WriteUserRoutine(file
, stat
->stRoutine
);
329 fprintf(file
, "__END_DECLS\n");
332 fprintf(file
, "/********************** Caution **************************/\n");
333 fprintf(file
, "/* The following data types should be used to calculate */\n");
334 fprintf(file
, "/* maximum message sizes only. The actual message may be */\n");
335 fprintf(file
, "/* smaller, and the position of the arguments within the */\n");
336 fprintf(file
, "/* message layout may vary from what is presented here. */\n");
337 fprintf(file
, "/* For example, if any of the arguments are variable- */\n");
338 fprintf(file
, "/* sized, and less than the maximum is sent, the data */\n");
339 fprintf(file
, "/* will be packed tight in the actual message to reduce */\n");
340 fprintf(file
, "/* the presence of holes. */\n");
341 fprintf(file
, "/********************** Caution **************************/\n");
344 WriteRequestTypes(file
, stats
);
345 WriteUserRequestUnion(file
, stats
);
347 WriteReplyTypes(file
, stats
);
348 WriteUserReplyUnion(file
, stats
);
350 WriteEpilog(file
, protect
, TRUE
);
354 WriteDefinesRoutine(FILE *file
, routine_t
*rt
)
356 char *up
= (char *)malloc(strlen(rt
->rtName
)+1);
358 up
= toupperstr(strcpy(up
, rt
->rtName
));
359 fprintf(file
, "#define\tMACH_ID_%s\t\t%d\t/* %s() */\n", up
, rt
->rtNumber
+ SubsystemBase
, rt
->rtName
);
360 if (rt
->rtKind
== rkRoutine
)
361 fprintf(file
, "#define\tMACH_ID_%s_REPLY\t\t%d\t/* %s() */\n", up
, rt
->rtNumber
+ SubsystemBase
+ 100, rt
->rtName
);
366 WriteServerRoutine(FILE *file
, routine_t
*rt
)
369 fprintf(file
, "/* %s %s */\n", rtRoutineKindToStr(rt
->rtKind
), rt
->rtName
);
370 WriteMigExternal(file
);
372 // MIG_SERVER_ROUTINE can be defined by system headers to resolve to an attribute that
373 // tells the compiler that this is a MIG server routine. Useful for static analysis.
374 fprintf(file
, "MIG_SERVER_ROUTINE\n%s %s\n", ReturnTypeStr(rt
), rt
->rtServerName
);
377 fprintf(file
, "#if\t%s\n", LintLib
);
379 WriteList(file
, rt
->rtArgs
, WriteNameDecl
, akbServerArg
, ", " , "");
380 fprintf(file
, ")\n");
381 WriteList(file
, rt
->rtArgs
, WriteServerVarDecl
, akbServerArg
, ";\n", ";\n");
383 fprintf(file
, "return ");
384 fprintf(file
, "%s(", rt
->rtServerName
);
385 WriteList(file
, rt
->rtArgs
, WriteNameDecl
, akbServerArg
, ", ", "");
386 fprintf(file
, "); }\n");
387 fprintf(file
, "#else /* %s */\n",LintLib
);
390 fprintf(file
, "(\n");
391 WriteList(file
, rt
->rtArgs
, WriteServerVarDecl
, akbServerArg
, ",\n", "\n");
392 fprintf(file
, ");\n");
395 fprintf(file
, "#if\t%s\n", NewCDecl
);
396 fprintf(file
, "(\n");
397 WriteList(file
, rt
->rtArgs
, WriteServerVarDecl
, akbServerArg
, ",\n", "\n");
398 fprintf(file
, ");\n");
399 fprintf(file
, "#else\n");
401 fprintf(file
, " ();\n");
402 fprintf(file
, "#endif\t/* %s */\n", NewCDecl
);
405 fprintf(file
, "#endif\t/* %s */\n", LintLib
);
410 WriteDispatcher(FILE *file
)
415 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
416 if (stat
->stKind
== skRoutine
) {
417 routine_t
*rt
= stat
->stRoutine
;
418 descr_count
+= rtCountArgDescriptors(rt
->rtArgs
, (int *) 0);
422 WriteMigExternal(file
);
423 fprintf(file
, "boolean_t %s(\n", ServerDemux
);
424 fprintf(file
, "\t\tmach_msg_header_t *InHeadP,\n");
425 fprintf(file
, "\t\tmach_msg_header_t *OutHeadP);\n\n");
427 WriteMigExternal(file
);
428 fprintf(file
, "mig_routine_t %s_routine(\n", ServerDemux
);
429 fprintf(file
, "\t\tmach_msg_header_t *InHeadP);\n\n");
431 fprintf(file
, "\n/* Description of this subsystem, for use in direct RPC */\n");
432 fprintf(file
, "extern const struct %s {\n", ServerSubsys
);
434 fprintf(file
, "\tstruct subsystem *\tsubsystem;\t/* Reserved for system use */\n");
437 fprintf(file
, "\tmig_server_routine_t\tserver;\t/* Server routine */\n");
439 fprintf(file
, "\tmach_msg_id_t\tstart;\t/* Min routine number */\n");
440 fprintf(file
, "\tmach_msg_id_t\tend;\t/* Max routine number + 1 */\n");
441 fprintf(file
, "\tunsigned int\tmaxsize;\t/* Max msg size */\n");
443 fprintf(file
, "\tvm_address_t\tbase_addr;\t/* Base address */\n");
444 fprintf(file
, "\tstruct rpc_routine_descriptor\t/*Array of routine descriptors */\n");
447 fprintf(file
, "\tvm_address_t\treserved;\t/* Reserved */\n");
448 fprintf(file
, "\tstruct routine_descriptor\t/*Array of routine descriptors */\n");
450 fprintf(file
, "\t\troutine[%d];\n", rtNumber
);
452 fprintf(file
, "\tstruct rpc_routine_arg_descriptor\t/*Array of arg descriptors */\n");
453 fprintf(file
, "\t\targ_descriptor[%d];\n", descr_count
);
455 fprintf(file
, "} %s;\n", ServerSubsys
);
460 WriteBogusServerRoutineAnnotationDefine(FILE *file
) {
461 // MIG_SERVER_ROUTINE can be defined by system headers to resolve to
462 // an attribute that tells the compiler that this is a MIG server routine.
463 // Useful for static analysis.
464 fprintf(file
, "#ifndef MIG_SERVER_ROUTINE\n");
465 fprintf(file
, "#define MIG_SERVER_ROUTINE\n");
466 fprintf(file
, "#endif\n");
471 WriteServerHeader(FILE *file
, statement_t
*stats
)
474 char *protect
= strconcat(SubsystemName
, "_server_");
476 WriteProlog(file
, protect
, TRUE
, FALSE
);
477 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
478 switch (stat
->stKind
) {
483 WriteImport(file
, stat
->stFileName
);
492 fatal("WriteServerHeader(): bad statement_kind_t (%d)", (int) stat
->stKind
);
494 fprintf(file
, "\n#ifdef __BeforeMigServerHeader\n");
495 fprintf(file
, "__BeforeMigServerHeader\n");
496 fprintf(file
, "#endif /* __BeforeMigServerHeader */\n\n");
498 WriteBogusServerRoutineAnnotationDefine(file
);
500 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
) {
501 if (stat
->stKind
== skRoutine
)
502 WriteServerRoutine(file
, stat
->stRoutine
);
504 WriteDispatcher(file
);
506 WriteRequestTypes(file
, stats
);
507 WriteServerRequestUnion(file
, stats
);
509 WriteReplyTypes(file
, stats
);
510 WriteServerReplyUnion(file
, stats
);
512 WriteEpilog(file
, protect
, FALSE
);
516 WriteInternalRedefine(FILE *file
, routine_t
*rt
)
518 fprintf(file
, "#define %s %s_external\n", rt
->rtUserName
, rt
->rtUserName
);
522 WriteInternalHeader(FILE *file
, statement_t
*stats
)
526 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
527 switch (stat
->stKind
) {
530 WriteInternalRedefine(file
, stat
->stRoutine
);
541 fatal("WriteInternalHeader(): bad statement_kind_t (%d)", (int) stat
->stKind
);
546 WriteDefinesHeader(FILE *file
, statement_t
*stats
)
549 char *protect
= strconcat(SubsystemName
, "_defines");
551 WriteProlog(file
, protect
, FALSE
, FALSE
);
552 fprintf(file
, "\n/*\tDefines related to the Subsystem %s\t*/\n\n", SubsystemName
);
553 for (stat
= stats
; stat
!= stNULL
; stat
= stat
->stNext
)
554 switch (stat
->stKind
) {
557 WriteDefinesRoutine(file
, stat
->stRoutine
);
566 fatal("WriteDefinesHeader(): bad statement_kind_t (%d)", (int) stat
->stKind
);
568 WriteEpilog(file
, protect
, FALSE
);