Add migcom tool

This commit is contained in:
William Kent
2021-01-22 18:20:06 -05:00
parent 641f62368b
commit d8fb3c5667
30 changed files with 14357 additions and 0 deletions

View File

@@ -3,4 +3,5 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/prefix)
add_subdirectory(cctools)
add_subdirectory(dtrace_ctf)
add_subdirectory(mig)
add_subdirectory(xar)

34
tools/mig/CMakeLists.txt Normal file
View File

@@ -0,0 +1,34 @@
add_executable(migcom)
target_sources(migcom PRIVATE
error.c
global.c
header.c
mig.c
routine.c
server.c
routine.c
server.c
statement.c
string.c
type.c
user.c
utils.c
${CMAKE_CURRENT_BINARY_DIR}/y.tab.c
${CMAKE_CURRENT_BINARY_DIR}/lexxer.yy.c
)
target_compile_definitions(migcom PRIVATE MIG_VERSION=\"\")
target_include_directories(migcom PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c
COMMAND yacc -d -b "${CMAKE_CURRENT_BINARY_DIR}/y" ${CMAKE_CURRENT_SOURCE_DIR}/parser.y
COMMENT "Yacc parser.y" VERBATIM
)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lexxer.yy.c
COMMAND lex -o "${CMAKE_CURRENT_BINARY_DIR}/lexxer.yy.c" ${CMAKE_CURRENT_SOURCE_DIR}/lexxer.l
COMMENT "Lex lexxer.l" VERBATIM
)
add_executable(mig IMPORTED)
set_property(TARGET mig PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/mig.sh)
add_dependencies(mig migcom)

54
tools/mig/alloc.h Normal file
View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 1999, 2008 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#ifndef _ALLOC_H
#define _ALLOC_H
#include <stdlib.h>
#endif /* _ALLOC_H */

111
tools/mig/error.c Normal file
View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 1999, 2008 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "global.h"
#include "error.h"
extern int lineno;
extern char *yyinname;
static char *program;
__private_extern__
int mig_errors = 0;
/*ARGSUSED*/
/*VARARGS1*/
void
fatal(char *format, ...)
{
va_list pvar;
va_start(pvar, format);
fprintf(stderr, "%s: fatal: \"%s\", line %d: ", program, yyinname, lineno-1);
(void) vfprintf(stderr, format, pvar);
fprintf(stderr, "\n");
va_end(pvar);
exit(1);
}
__private_extern__
/*ARGSUSED*/
/*VARARGS1*/
void
warn(char *format, ...)
{
va_list pvar;
va_start(pvar, format);
if (!BeQuiet && (mig_errors == 0)) {
fprintf(stderr, "\"%s\", line %d: warning: ", yyinname, lineno-1);
(void) vfprintf(stderr, format, pvar);
fprintf(stderr, "\n");
}
va_end(pvar);
}
/*ARGSUSED*/
/*VARARGS1*/
void
error(char *format, ...)
{
va_list pvar;
va_start(pvar, format);
fprintf(stderr, "\"%s\", line %d: ", yyinname, lineno-1);
(void) vfprintf(stderr, format, pvar);
fprintf(stderr, "\n");
va_end(pvar);
mig_errors++;
}
void
set_program_name(char *name)
{
program = name;
}

61
tools/mig/error.h Normal file
View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 1999, 2008 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#ifndef _ERROR_H
#define _ERROR_H
#include <errno.h>
extern void fatal(char *format, ...);
extern void warn(char *format, ...);
extern void error(char *format, ...);
extern int mig_errors;
extern void set_program_name(char *name);
#endif /* _ERROR_H */

151
tools/mig/global.c Normal file
View File

@@ -0,0 +1,151 @@
/*
* Copyright (c) 1999, 2008 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#include "strdefs.h"
#include "global.h"
#include "error.h"
#include "mig_machine.h"
boolean_t PrintVersion = FALSE;
boolean_t BeQuiet = FALSE;
boolean_t BeVerbose = FALSE;
boolean_t UseMsgRPC = TRUE;
boolean_t GenSymTab = FALSE;
boolean_t UseEventLogger = FALSE;
boolean_t BeLint = FALSE;
boolean_t BeAnsiC = TRUE;
boolean_t CheckNDR = FALSE;
boolean_t PackMsg = PACK_MESSAGES;
boolean_t UseSplitHeaders = FALSE;
boolean_t ShortCircuit = FALSE;
boolean_t UseRPCTrap = FALSE;
boolean_t TestRPCTrap= FALSE;
boolean_t IsVoucherCodeAllowed = TRUE;
boolean_t IsKernelUser = FALSE;
boolean_t IsKernelServer = FALSE;
boolean_t UseSpecialReplyPort = FALSE;
boolean_t HasUseSpecialReplyPort = FALSE;
boolean_t HasConsumeOnSendError = FALSE;
u_int ConsumeOnSendError = 0;
string_t RCSId = strNULL;
string_t SubsystemName = strNULL;
u_int SubsystemBase = 0;
string_t MsgOption = strNULL;
string_t WaitTime = strNULL;
string_t SendTime = strNULL;
string_t ErrorProc = "MsgError";
string_t ServerPrefix = "";
string_t UserPrefix = "";
string_t ServerDemux = strNULL;
string_t ServerImpl = strNULL;
string_t ServerSubsys = strNULL;
int MaxMessSizeOnStack = -1; /* by default, always on stack */
int UserTypeLimit = -1; /* by default, assume unlimited size. */
string_t yyinname;
char NewCDecl[] = "(defined(__STDC__) || defined(c_plusplus))";
char LintLib[] = "defined(LINTLIBRARY)";
void
init_global()
{
yyinname = strmake("<no name yet>");
}
string_t UserFilePrefix = strNULL;
string_t UserHeaderFileName = strNULL;
string_t ServerHeaderFileName = strNULL;
string_t InternalHeaderFileName = strNULL;
string_t DefinesHeaderFileName = strNULL;
string_t UserFileName = strNULL;
string_t ServerFileName = strNULL;
string_t GenerationDate = strNULL;
void
more_global()
{
if (SubsystemName == strNULL)
fatal("no SubSystem declaration");
if (UserHeaderFileName == strNULL)
UserHeaderFileName = strconcat(SubsystemName, ".h");
else if (streql(UserHeaderFileName, "/dev/null"))
UserHeaderFileName = strNULL;
if (UserFileName == strNULL)
UserFileName = strconcat(SubsystemName, "User.c");
else if (streql(UserFileName, "/dev/null"))
UserFileName = strNULL;
if (ServerFileName == strNULL)
ServerFileName = strconcat(SubsystemName, "Server.c");
else if (streql(ServerFileName, "/dev/null"))
ServerFileName = strNULL;
if (ServerDemux == strNULL)
ServerDemux = strconcat(SubsystemName, "_server");
if (ServerImpl == strNULL)
ServerImpl = strconcat(SubsystemName, "_impl");
if (ServerSubsys == strNULL) {
if (ServerPrefix != strNULL)
ServerSubsys = strconcat(ServerPrefix, SubsystemName);
else
ServerSubsys = SubsystemName;
ServerSubsys = strconcat(ServerSubsys, "_subsystem");
}
if (HasUseSpecialReplyPort && !BeAnsiC) {
fatal("Cannot use UseSpecialReplyPort in non ANSI mode\n");
}
}

113
tools/mig/global.h Normal file
View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 1999-2018 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#ifndef _GLOBAL_H
#define _GLOBAL_H
#include "type.h"
extern boolean_t PrintVersion; /* print bootstrap_cmds project version and exit */
extern boolean_t BeQuiet; /* no warning messages */
extern boolean_t BeVerbose; /* summarize types, routines */
extern boolean_t BeDebug; /* enters in the debug mode */
extern boolean_t UseMsgRPC;
extern boolean_t GenSymTab;
extern boolean_t UseEventLogger;
extern boolean_t BeLint;
extern boolean_t BeAnsiC;
extern boolean_t CheckNDR;
extern boolean_t PackMsg;
extern boolean_t UseSplitHeaders;
extern boolean_t ShortCircuit;
extern boolean_t UseRPCTrap;
extern boolean_t TestRPCTrap;
extern boolean_t IsVoucherCodeAllowed;
extern boolean_t IsKernelUser;
extern boolean_t IsKernelServer;
extern boolean_t UseSpecialReplyPort;
extern boolean_t HasUseSpecialReplyPort; /* whether UseSpecialReplyPort has ever been set to TRUE */
extern boolean_t HasConsumeOnSendError; /* whether ConsumeOnSendError has ever been set */
extern u_int ConsumeOnSendError;
extern string_t RCSId;
extern string_t SubsystemName;
extern u_int SubsystemBase;
extern string_t MsgOption;
extern string_t WaitTime;
extern string_t SendTime;
extern string_t ErrorProc;
extern string_t ServerPrefix;
extern string_t UserPrefix;
extern string_t ServerDemux;
extern string_t ServerImpl;
extern string_t ServerSubsys;
extern int MaxMessSizeOnStack;
extern int UserTypeLimit;
extern int yylineno;
extern string_t yyinname;
extern void init_global(void);
extern string_t UserFilePrefix;
extern string_t UserHeaderFileName;
extern string_t ServerHeaderFileName;
extern string_t InternalHeaderFileName;
extern string_t DefinesHeaderFileName;
extern string_t UserFileName;
extern string_t ServerFileName;
extern void more_global(void);
extern char NewCDecl[];
extern char LintLib[];
#endif /* _GLOBAL_H */

569
tools/mig/header.c Normal file
View File

@@ -0,0 +1,569 @@
/*
* Copyright (c) 1999-2018 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#include "write.h"
#include "utils.h"
#include "global.h"
#include "strdefs.h"
#include "error.h"
#include <stdlib.h>
void
WriteIncludes(FILE *file, boolean_t isuser, boolean_t isdef)
{
if (isdef) {
fprintf(file, "#include <mach/port.h>\n");
fprintf(file, "#include <mach/machine/kern_return.h>\n");
if (!isuser)
fprintf(file, "#include <mach/mig_errors.h>\n");
}
else {
fprintf(file, "#include <string.h>\n");
fprintf(file, "#include <mach/ndr.h>\n");
fprintf(file, "#include <mach/boolean.h>\n");
fprintf(file, "#include <mach/kern_return.h>\n");
fprintf(file, "#include <mach/notify.h>\n");
fprintf(file, "#include <mach/mach_types.h>\n");
fprintf(file, "#include <mach/message.h>\n");
fprintf(file, "#include <mach/mig_errors.h>\n");
fprintf(file, "#include <mach/port.h>\n");
if (IsVoucherCodeAllowed && !IsKernelUser && !IsKernelServer) {
fprintf(file, "\t\n/* BEGIN VOUCHER CODE */\n\n");
fprintf(file, "#ifndef KERNEL\n");
fprintf(file, "#if defined(__has_include)\n");
fprintf(file, "#if __has_include(<mach/mig_voucher_support.h>)\n");
fprintf(file, "#ifndef USING_VOUCHERS\n");
fprintf(file, "#define USING_VOUCHERS\n");
fprintf(file, "#endif\n");
fprintf(file, "#ifndef __VOUCHER_FORWARD_TYPE_DECLS__\n");
fprintf(file, "#define __VOUCHER_FORWARD_TYPE_DECLS__\n");
fprintf(file, "#ifdef __cplusplus\n");
fprintf(file, "extern \"C\" {\n");
fprintf(file, "#endif\n");
fprintf(file, "\textern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));\n");
fprintf(file, "#ifdef __cplusplus\n");
fprintf(file, "}\n");
fprintf(file, "#endif\n");
fprintf(file, "#endif // __VOUCHER_FORWARD_TYPE_DECLS__\n");
fprintf(file, "#endif // __has_include(<mach/mach_voucher_types.h>)\n");
fprintf(file, "#endif // __has_include\n");
fprintf(file, "#endif // !KERNEL\n");
fprintf(file, "\t\n/* END VOUCHER CODE */\n\n");
}
fprintf(file, "\t\n/* BEGIN MIG_STRNCPY_ZEROFILL CODE */\n\n");
fprintf(file, "#if defined(__has_include)\n");
fprintf(file, "#if __has_include(<mach/mig_strncpy_zerofill_support.h>)\n");
fprintf(file, "#ifndef USING_MIG_STRNCPY_ZEROFILL\n");
fprintf(file, "#define USING_MIG_STRNCPY_ZEROFILL\n");
fprintf(file, "#endif\n");
fprintf(file, "#ifndef __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__\n");
fprintf(file, "#define __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__\n");
fprintf(file, "#ifdef __cplusplus\n");
fprintf(file, "extern \"C\" {\n");
fprintf(file, "#endif\n");
fprintf(file, "\textern int mig_strncpy_zerofill(char *dest, const char *src, int len) __attribute__((weak_import));\n");
fprintf(file, "#ifdef __cplusplus\n");
fprintf(file, "}\n");
fprintf(file, "#endif\n");
fprintf(file, "#endif /* __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ */\n");
fprintf(file, "#endif /* __has_include(<mach/mig_strncpy_zerofill_support.h>) */\n");
fprintf(file, "#endif /* __has_include */\n");
fprintf(file, "\t\n/* END MIG_STRNCPY_ZEROFILL CODE */\n\n");
if (ShortCircuit)
fprintf(file, "#include <mach/rpc.h>\n");
if (isuser && IsKernelUser) {
fprintf(file, "#if\t(__MigKernelSpecificCode) || (_MIG_KERNEL_SPECIFIC_CODE_)\n");
fprintf(file, "#include <kern/ipc_mig.h>\n");
fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
}
}
fprintf(file, "\n");
}
static void
WriteETAPDefines(FILE *file)
{
statement_t *stat;
int fnum;
char *fname;
int first = TRUE;
fprintf(file, "\n#ifndef subsystem_to_name_map_%s\n", SubsystemName);
fprintf(file, "#define subsystem_to_name_map_%s \\\n", SubsystemName);
for (stat = stats; stat != stNULL; stat = stat->stNext)
if (stat->stKind == skRoutine) {
fnum = SubsystemBase + stat->stRoutine->rtNumber;
fname = stat->stRoutine->rtName;
if (! first)
fprintf(file, ",\\\n");
fprintf(file, " { \"%s\", %d }", fname, fnum);
first = FALSE;
}
fprintf(file, "\n#endif\n");
}
static void
WriteProlog(FILE *file, char *protect, boolean_t more, boolean_t isuser)
{
if (protect != strNULL) {
fprintf(file, "#ifndef\t_%s\n", protect);
fprintf(file, "#define\t_%s\n", protect);
fprintf(file, "\n");
}
fprintf(file, "/* Module %s */\n", SubsystemName);
fprintf(file, "\n");
if (more) {
WriteIncludes(file, isuser, UseSplitHeaders);
}
fprintf(file, "#ifdef AUTOTEST\n");
fprintf(file, "#ifndef FUNCTION_PTR_T\n");
fprintf(file, "#define FUNCTION_PTR_T\n");
fprintf(file, "typedef void (*function_ptr_t)");
fprintf(file, "(mach_port_t, char *, mach_msg_type_number_t);\n");
fprintf(file, "typedef struct {\n");
fprintf(file, " char *name;\n");
fprintf(file, " function_ptr_t function;\n");
fprintf(file, "} function_table_entry;\n");
fprintf(file, "typedef function_table_entry *function_table_t;\n");
fprintf(file, "#endif /* FUNCTION_PTR_T */\n");
fprintf(file, "#endif /* AUTOTEST */\n");
fprintf(file, "\n#ifndef\t%s_MSG_COUNT\n", SubsystemName);
fprintf(file, "#define\t%s_MSG_COUNT\t%d\n", SubsystemName, rtNumber);
fprintf(file, "#endif\t/* %s_MSG_COUNT */\n\n", SubsystemName);
}
static void
WriteEpilog(FILE *file, char *protect, boolean_t isuser)
{
char *defname = isuser ? "__AfterMigUserHeader" : "__AfterMigServerHeader";
WriteETAPDefines(file);
fprintf(file, "\n#ifdef %s\n%s\n#endif /* %s */\n", defname, defname, defname);
if (protect != strNULL) {
fprintf(file, "\n");
fprintf(file, "#endif\t /* _%s */\n", protect);
}
}
static void
WriteUserRoutine(FILE *file, routine_t *rt)
{
fprintf(file, "\n");
fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
WriteMigExternal(file);
fprintf(file, "%s %s\n", ReturnTypeStr(rt), rt->rtUserName);
if (BeLint) {
fprintf(file, "#if\t%s\n", LintLib);
fprintf(file, " (");
WriteList(file, rt->rtArgs, WriteNameDecl, akbUserArg, ", " , "");
fprintf(file, ")\n");
WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ";\n", ";\n");
fprintf(file, "{ ");
fprintf(file, "return ");
fprintf(file, "%s(", rt->rtUserName);
WriteList(file, rt->rtArgs, WriteNameDecl, akbUserArg, ", ", "");
fprintf(file, "); }\n");
fprintf(file, "#else\n");
}
if (BeAnsiC) {
fprintf(file, "(\n");
WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n");
fprintf(file, ");\n");
}
else {
fprintf(file, "#if\t%s\n", NewCDecl);
fprintf(file, "(\n");
WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n");
fprintf(file, ");\n");
fprintf(file, "#else\n");
fprintf(file, " ();\n");
fprintf(file, "#endif\t/* %s */\n", NewCDecl);
}
if (BeLint) {
fprintf(file, "#endif\t/* %s */\n", LintLib);
}
}
void
WriteUserRequestUnion(FILE *file, statement_t *stats)
{
statement_t *stat;
fprintf(file, "/* union of all requests */\n\n");
fprintf(file, "#ifndef __RequestUnion__%s%s_subsystem__defined\n", UserPrefix, SubsystemName);
fprintf(file, "#define __RequestUnion__%s%s_subsystem__defined\n", UserPrefix, SubsystemName);
fprintf(file, "union __RequestUnion__%s%s_subsystem {\n", UserPrefix, SubsystemName);
for (stat = stats; stat != stNULL; stat = stat->stNext) {
if (stat->stKind == skRoutine) {
routine_t *rt;
rt = stat->stRoutine;
fprintf(file, "\t__Request__%s_t Request_%s;\n", rt->rtName, rt->rtUserName);
}
}
fprintf(file, "};\n");
fprintf(file, "#endif /* !__RequestUnion__%s%s_subsystem__defined */\n", UserPrefix, SubsystemName);
}
void
WriteUserReplyUnion(FILE *file, statement_t *stats)
{
statement_t *stat;
fprintf(file, "/* union of all replies */\n\n");
fprintf(file, "#ifndef __ReplyUnion__%s%s_subsystem__defined\n", UserPrefix, SubsystemName);
fprintf(file, "#define __ReplyUnion__%s%s_subsystem__defined\n", UserPrefix, SubsystemName);
fprintf(file, "union __ReplyUnion__%s%s_subsystem {\n", UserPrefix, SubsystemName);
for (stat = stats; stat != stNULL; stat = stat->stNext) {
if (stat->stKind == skRoutine) {
routine_t *rt;
rt = stat->stRoutine;
fprintf(file, "\t__Reply__%s_t Reply_%s;\n", rt->rtName, rt->rtUserName);
}
}
fprintf(file, "};\n");
fprintf(file, "#endif /* !__RequestUnion__%s%s_subsystem__defined */\n", UserPrefix, SubsystemName);
}
void
WriteUserHeader(FILE *file, statement_t *stats)
{
statement_t *stat;
char *protect = strconcat(SubsystemName, "_user_");
WriteProlog(file, protect, TRUE, TRUE);
for (stat = stats; stat != stNULL; stat = stat->stNext)
switch (stat->stKind) {
case skImport:
case skUImport:
case skDImport:
WriteImport(file, stat->stFileName);
break;
case skRoutine:
case skSImport:
case skIImport:
break;
default:
fatal("WriteHeader(): bad statement_kind_t (%d)", (int) stat->stKind);
}
fprintf(file, "\n");
fprintf(file, "#ifdef __BeforeMigUserHeader\n");
fprintf(file, "__BeforeMigUserHeader\n");
fprintf(file, "#endif /* __BeforeMigUserHeader */\n");
fprintf(file, "\n");
fprintf(file, "#include <sys/cdefs.h>\n");
fprintf(file, "__BEGIN_DECLS\n");
fprintf(file, "\n");
for (stat = stats; stat != stNULL; stat = stat->stNext) {
if (stat->stKind == skRoutine)
WriteUserRoutine(file, stat->stRoutine);
}
fprintf(file, "\n");
fprintf(file, "__END_DECLS\n");
fprintf(file, "\n");
fprintf(file, "/********************** Caution **************************/\n");
fprintf(file, "/* The following data types should be used to calculate */\n");
fprintf(file, "/* maximum message sizes only. The actual message may be */\n");
fprintf(file, "/* smaller, and the position of the arguments within the */\n");
fprintf(file, "/* message layout may vary from what is presented here. */\n");
fprintf(file, "/* For example, if any of the arguments are variable- */\n");
fprintf(file, "/* sized, and less than the maximum is sent, the data */\n");
fprintf(file, "/* will be packed tight in the actual message to reduce */\n");
fprintf(file, "/* the presence of holes. */\n");
fprintf(file, "/********************** Caution **************************/\n");
fprintf(file, "\n");
WriteRequestTypes(file, stats);
WriteUserRequestUnion(file, stats);
WriteReplyTypes(file, stats);
WriteUserReplyUnion(file, stats);
WriteEpilog(file, protect, TRUE);
}
static void
WriteDefinesRoutine(FILE *file, routine_t *rt)
{
char *up = (char *)malloc(strlen(rt->rtName)+1);
up = toupperstr(strcpy(up, rt->rtName));
fprintf(file, "#define\tMACH_ID_%s\t\t%d\t/* %s() */\n", up, rt->rtNumber + SubsystemBase, rt->rtName);
if (rt->rtKind == rkRoutine)
fprintf(file, "#define\tMACH_ID_%s_REPLY\t\t%d\t/* %s() */\n", up, rt->rtNumber + SubsystemBase + 100, rt->rtName);
fprintf(file, "\n");
}
void
WriteServerRoutine(FILE *file, routine_t *rt)
{
fprintf(file, "\n");
fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
WriteMigExternal(file);
// MIG_SERVER_ROUTINE can be defined by system headers to resolve to an attribute that
// tells the compiler that this is a MIG server routine. Useful for static analysis.
fprintf(file, "MIG_SERVER_ROUTINE\n%s %s\n", ReturnTypeStr(rt), rt->rtServerName);
if (BeLint) {
fprintf(file, "#if\t%s\n", LintLib);
fprintf(file, " (");
WriteList(file, rt->rtArgs, WriteNameDecl, akbServerArg, ", " , "");
fprintf(file, ")\n");
WriteList(file, rt->rtArgs, WriteServerVarDecl, akbServerArg, ";\n", ";\n");
fprintf(file, "{ ");
fprintf(file, "return ");
fprintf(file, "%s(", rt->rtServerName);
WriteList(file, rt->rtArgs, WriteNameDecl, akbServerArg, ", ", "");
fprintf(file, "); }\n");
fprintf(file, "#else /* %s */\n",LintLib);
}
if (BeAnsiC) {
fprintf(file, "(\n");
WriteList(file, rt->rtArgs, WriteServerVarDecl, akbServerArg, ",\n", "\n");
fprintf(file, ");\n");
}
else {
fprintf(file, "#if\t%s\n", NewCDecl);
fprintf(file, "(\n");
WriteList(file, rt->rtArgs, WriteServerVarDecl, akbServerArg, ",\n", "\n");
fprintf(file, ");\n");
fprintf(file, "#else\n");
fprintf(file, " ();\n");
fprintf(file, "#endif\t/* %s */\n", NewCDecl);
}
if (BeLint) {
fprintf(file, "#endif\t/* %s */\n", LintLib);
}
}
static void
WriteDispatcher(FILE *file)
{
statement_t *stat;
int descr_count = 0;
for (stat = stats; stat != stNULL; stat = stat->stNext)
if (stat->stKind == skRoutine) {
routine_t *rt = stat->stRoutine;
descr_count += rtCountArgDescriptors(rt->rtArgs, (int *) 0);
}
fprintf(file, "\n");
WriteMigExternal(file);
fprintf(file, "boolean_t %s(\n", ServerDemux);
fprintf(file, "\t\tmach_msg_header_t *InHeadP,\n");
fprintf(file, "\t\tmach_msg_header_t *OutHeadP);\n\n");
WriteMigExternal(file);
fprintf(file, "mig_routine_t %s_routine(\n", ServerDemux);
fprintf(file, "\t\tmach_msg_header_t *InHeadP);\n\n");
fprintf(file, "\n/* Description of this subsystem, for use in direct RPC */\n");
fprintf(file, "extern const struct %s {\n", ServerSubsys);
if (UseRPCTrap) {
fprintf(file, "\tstruct subsystem *\tsubsystem;\t/* Reserved for system use */\n");
}
else {
fprintf(file, "\tmig_server_routine_t\tserver;\t/* Server routine */\n");
}
fprintf(file, "\tmach_msg_id_t\tstart;\t/* Min routine number */\n");
fprintf(file, "\tmach_msg_id_t\tend;\t/* Max routine number + 1 */\n");
fprintf(file, "\tunsigned int\tmaxsize;\t/* Max msg size */\n");
if (UseRPCTrap) {
fprintf(file, "\tvm_address_t\tbase_addr;\t/* Base address */\n");
fprintf(file, "\tstruct rpc_routine_descriptor\t/*Array of routine descriptors */\n");
}
else {
fprintf(file, "\tvm_address_t\treserved;\t/* Reserved */\n");
fprintf(file, "\tstruct routine_descriptor\t/*Array of routine descriptors */\n");
}
fprintf(file, "\t\troutine[%d];\n", rtNumber);
if (UseRPCTrap) {
fprintf(file, "\tstruct rpc_routine_arg_descriptor\t/*Array of arg descriptors */\n");
fprintf(file, "\t\targ_descriptor[%d];\n", descr_count);
}
fprintf(file, "} %s;\n", ServerSubsys);
fprintf(file, "\n");
}
void
WriteBogusServerRoutineAnnotationDefine(FILE *file) {
// MIG_SERVER_ROUTINE can be defined by system headers to resolve to
// an attribute that tells the compiler that this is a MIG server routine.
// Useful for static analysis.
fprintf(file, "#ifndef MIG_SERVER_ROUTINE\n");
fprintf(file, "#define MIG_SERVER_ROUTINE\n");
fprintf(file, "#endif\n");
fprintf(file, "\n");
}
void
WriteServerHeader(FILE *file, statement_t *stats)
{
statement_t *stat;
char *protect = strconcat(SubsystemName, "_server_");
WriteProlog(file, protect, TRUE, FALSE);
for (stat = stats; stat != stNULL; stat = stat->stNext)
switch (stat->stKind) {
case skImport:
case skSImport:
case skDImport:
WriteImport(file, stat->stFileName);
break;
case skRoutine:
case skUImport:
case skIImport:
break;
default:
fatal("WriteServerHeader(): bad statement_kind_t (%d)", (int) stat->stKind);
}
fprintf(file, "\n#ifdef __BeforeMigServerHeader\n");
fprintf(file, "__BeforeMigServerHeader\n");
fprintf(file, "#endif /* __BeforeMigServerHeader */\n\n");
WriteBogusServerRoutineAnnotationDefine(file);
for (stat = stats; stat != stNULL; stat = stat->stNext) {
if (stat->stKind == skRoutine)
WriteServerRoutine(file, stat->stRoutine);
}
WriteDispatcher(file);
WriteRequestTypes(file, stats);
WriteServerRequestUnion(file, stats);
WriteReplyTypes(file, stats);
WriteServerReplyUnion(file, stats);
WriteEpilog(file, protect, FALSE);
}
static void
WriteInternalRedefine(FILE *file, routine_t *rt)
{
fprintf(file, "#define %s %s_external\n", rt->rtUserName, rt->rtUserName);
}
void
WriteInternalHeader(FILE *file, statement_t *stats)
{
statement_t *stat;
for (stat = stats; stat != stNULL; stat = stat->stNext)
switch (stat->stKind) {
case skRoutine:
WriteInternalRedefine(file, stat->stRoutine);
break;
case skImport:
case skUImport:
case skSImport:
case skDImport:
case skIImport:
break;
default:
fatal("WriteInternalHeader(): bad statement_kind_t (%d)", (int) stat->stKind);
}
}
void
WriteDefinesHeader(FILE *file, statement_t *stats)
{
statement_t *stat;
char *protect = strconcat(SubsystemName, "_defines");
WriteProlog(file, protect, FALSE, FALSE);
fprintf(file, "\n/*\tDefines related to the Subsystem %s\t*/\n\n", SubsystemName);
for (stat = stats; stat != stNULL; stat = stat->stNext)
switch (stat->stKind) {
case skRoutine:
WriteDefinesRoutine(file, stat->stRoutine);
break;
case skImport:
case skSImport:
case skUImport:
break;
default:
fatal("WriteDefinesHeader(): bad statement_kind_t (%d)", (int) stat->stKind);
}
WriteEpilog(file, protect, FALSE);
}

52
tools/mig/lexxer.h Normal file
View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 1999-2018 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
extern void LookFileName(void);
extern void LookString(void);
extern void LookQString(void);
extern void LookNormal(void);

314
tools/mig/lexxer.l Normal file
View File

@@ -0,0 +1,314 @@
%k 10000
%n 5000
%a 20000
%e 10000
%p 25000
Ident ([A-Za-z_][A-Za-z_0-9]*)
Number ([0-9]+)
String ([-/._$A-Za-z0-9]+)
QString (\"[^"\n]*\")
AString (\<[^>\n]*\>)
FileName ({QString}|{AString})
/* new flex syntax to accomplish the same thing as #define YY_NO_UNPUT */
%option nounput
%{
/*
* Copyright (c) 1999-2018 Apple, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* "Portions Copyright (c) 1999, 2008 Apple Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License."
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
#include "strdefs.h"
#include "type.h"
#include <sys/types.h>
#include <mach/message.h>
#include <mach/std_types.h>
#include "statement.h"
#include "global.h"
#include "y.tab.h" // was parser.h
#include "lexxer.h"
#include "mig_machine.h"
#define PortSize (sizeof (mach_port_t) * NBBY)
#ifdef __STDC__
#define stringize(x) #x
#else /* __STDC__ */
#define stringize(x) "x"
#endif /* __STDC__ */
#ifdef LDEBUG
#define RETURN(sym) \
{ \
printf("yylex: returning '%s' (%d)\n", stringize(sym), (sym)); \
return (sym); \
}
#else /* LDEBUG */
#define RETURN(sym) return (sym)
#endif /* LDEBUG */
#define TPRETURN(intype, outtype, tsize) \
{ \
yylval.symtype.innumber = (intype); \
yylval.symtype.instr = stringize(intype); \
yylval.symtype.outnumber = (outtype); \
yylval.symtype.outstr = stringize(outtype); \
yylval.symtype.size = (tsize); \
RETURN(sySymbolicType); \
}
#define TRETURN(type, tsize) TPRETURN(type,type,tsize)
#define SAVE(s) do {oldYYBegin = s; BEGIN s; } while (0)
#define RESTORE BEGIN oldYYBegin
#define FRETURN(val) \
{ \
yylval.flag = (val); \
RETURN(syIPCFlag); \
}
#define YY_NO_UNPUT /* suppress yyunput generation */
static int oldYYBegin = 0;
int lineno = 0; /* Replaces lex yylineno */
static void doSharp(char *); /* process body of # directives */
extern void yyerror(char *);
%}
%Start Normal String FileName QString SkipToEOL
%%
<Normal>[Rr][Oo][Uu][Tt][Ii][Nn][Ee] RETURN(syRoutine);
<Normal>[Ss][Ii][Mm][Pp][Ll][Ee][Rr][Oo][Uu][Tt][Ii][Nn][Ee] RETURN(sySimpleRoutine);
<Normal>[Ss][Uu][Bb][Ss][Yy][Ss][Tt][Ee][Mm] RETURN(sySubsystem);
<Normal>[Mm][Ss][Gg][Oo][Pp][Tt][Ii][Oo][Nn] RETURN(syMsgOption);
<Normal>[Uu][Ss][Ee][Ss][Pp][Ee][Cc][Ii][Aa][Ll][Rr][Ee][Pp][Ll][Yy][Pp][Oo][Rr][Tt] RETURN(syUseSpecialReplyPort);
<Normal>[Cc][Oo][Nn][Ss][Uu][Mm][Ee][Oo][Nn][Ss][Ee][Nn][Dd][Ee][Rr][Rr][Oo][Rr] RETURN(syConsumeOnSendError);
<Normal>[Mm][Ss][Gg][Ss][Ee][Qq][Nn][Oo] RETURN(syMsgSeqno);
<Normal>[Ww][Aa][Ii][Tt][Tt][Ii][Mm][Ee] RETURN(syWaitTime);
<Normal>[Ss][Ee][Nn][Dd][Tt][Ii][Mm][Ee] RETURN(sySendTime);
<Normal>[Nn][Oo][Ww][Aa][Ii][Tt][Tt][Ii][Mm][Ee] RETURN(syNoWaitTime);
<Normal>[Nn][Oo][Ss][Ee][Nn][Dd][Tt][Ii][Mm][Ee] RETURN(syNoSendTime);
<Normal>[Ii][Nn] RETURN(syIn);
<Normal>[Oo][Uu][Tt] RETURN(syOut);
<Normal>[Uu][Ss][Ee][Rr][Ii][Mm][Pp][Ll] RETURN(syUserImpl);
<Normal>[Ss][Ee][Rr][Vv][Ee][Rr][Ii][Mm][Pp][Ll] RETURN(syServerImpl);
<Normal>[Ss][Ee][Cc][Tt][Oo][Kk][Ee][Nn] RETURN(sySecToken);
<Normal>[Ss][Ee][Rr][Vv][Ee][Rr][Ss][Ee][Cc][Tt][Oo][Kk][Ee][Nn] RETURN(syServerSecToken);
<Normal>[Uu][Ss][Ee][Rr][Ss][Ee][Cc][Tt][Oo][Kk][Ee][Nn] RETURN(syUserSecToken);
<Normal>[Aa][Uu][Dd][Ii][Tt][Tt][Oo][Kk][Ee][Nn] RETURN(syAuditToken);
<Normal>[Ss][Ee][Rr][Vv][Ee][Rr][Aa][Uu][Dd][Ii][Tt][Tt][Oo][Kk][Ee][Nn] RETURN(syServerAuditToken);
<Normal>[Uu][Ss][Ee][Rr][Aa][Uu][Dd][Ii][Tt][Tt][Oo][Kk][Ee][Nn] RETURN(syUserAuditToken);
<Normal>[Ss][Ee][Rr][Vv][Ee][Rr][Cc][Oo][Nn][Tt][Ee][Xx][Tt][Tt][Oo][Kk][Ee][Nn] RETURN(syServerContextToken);
<Normal>[Ii][Nn][Oo][Uu][Tt] RETURN(syInOut);
<Normal>[Rr][Ee][Qq][Uu][Ee][Ss][Tt][Pp][Oo][Rr][Tt] RETURN(syRequestPort);
<Normal>[Rr][Ee][Pp][Ll][Yy][Pp][Oo][Rr][Tt] RETURN(syReplyPort);
<Normal>[Uu][Rr][Ee][Pp][Ll][Yy][Pp][Oo][Rr][Tt] RETURN(syUReplyPort);
<Normal>[Ss][Rr][Ee][Pp][Ll][Yy][Pp][Oo][Rr][Tt] RETURN(sySReplyPort);
<Normal>[Aa][Rr][Rr][Aa][Yy] RETURN(syArray);
<Normal>[Oo][Ff] RETURN(syOf);
<Normal>[Ee][Rr][Rr][Oo][Rr] RETURN(syErrorProc);
<Normal>[Ss][Ee][Rr][Vv][Ee][Rr][Pp][Rr][Ee][Ff][Ii][Xx] RETURN(syServerPrefix);
<Normal>[Uu][Ss][Ee][Rr][Pp][Rr][Ee][Ff][Ii][Xx] RETURN(syUserPrefix);
<Normal>[Ss][Ee][Rr][Vv][Ee][Rr][Dd][Ee][Mm][Uu][Xx] RETURN(syServerDemux);
<Normal>[Rr][Cc][Ss][Ii][Dd] RETURN(syRCSId);
<Normal>[Ii][Mm][Pp][Oo][Rr][Tt] RETURN(syImport);
<Normal>[Uu][Ii][Mm][Pp][Oo][Rr][Tt] RETURN(syUImport);
<Normal>[Ss][Ii][Mm][Pp][Oo][Rr][Tt] RETURN(sySImport);
<Normal>[Dd][Ii][Mm][Pp][Oo][Rr][Tt] RETURN(syDImport);
<Normal>[Ii][Ii][Mm][Pp][Oo][Rr][Tt] RETURN(syIImport);
<Normal>[Tt][Yy][Pp][Ee] RETURN(syType);
<Normal>[Kk][Ee][Rr][Nn][Ee][Ll][Ss][Ee][Rr][Vv][Ee][Rr] RETURN(syKernelServer);
<Normal>[Kk][Ee][Rr][Nn][Ee][Ll][Uu][Ss][Ee][Rr] RETURN(syKernelUser);
<Normal>[Ss][Kk][Ii][Pp] RETURN(sySkip);
<Normal>[Ss][Tt][Rr][Uu][Cc][Tt] RETURN(syStruct);
<Normal>[Ii][Nn][Tt][Rr][Aa][Nn] RETURN(syInTran);
<Normal>[Oo][Uu][Tt][Tt][Rr][Aa][Nn] RETURN(syOutTran);
<Normal>[Dd][Ee][Ss][Tt][Rr][Uu][Cc][Tt][Oo][Rr] RETURN(syDestructor);
<Normal>[Cc][Tt][Yy][Pp][Ee] RETURN(syCType);
<Normal>[Cc][Uu][Ss][Ee][Rr][Tt][Yy][Pp][Ee] RETURN(syCUserType);
<Normal>[Cc][Ss][Ee][Rr][Vv][Ee][Rr][Tt][Yy][Pp][Ee] RETURN(syCServerType);
<Normal>[Cc]_[Ss][Tt][Rr][Ii][Nn][Gg] RETURN(syCString);
<Normal>[Ss][Aa][Mm][Ee][Cc][Oo][Uu][Nn][Tt] FRETURN(flSameCount);
<Normal>[Rr][Ee][Tt][Cc][Oo][Dd][Ee] FRETURN(flRetCode);
<Normal>[Pp][Hh][Yy][Ss][Ii][Cc][Aa][Ll][Cc][Oo][Pp][Yy] FRETURN(flPhysicalCopy);
<Normal>[Oo][Vv][Ee][Rr][Ww][Rr][Ii][Tt][Ee] FRETURN(flOverwrite);
<Normal>[Dd][Ee][Aa][Ll][Ll][Oo][Cc] FRETURN(flDealloc);
<Normal>[Nn][Oo][Tt][Dd][Ee][Aa][Ll][Ll][Oo][Cc] FRETURN(flNotDealloc);
<Normal>[Cc][Oo][Uu][Nn][Tt][Ii][Nn][Oo][Uu][Tt] FRETURN(flCountInOut);
<Normal>[Pp][Oo][Ll][Yy][Mm][Oo][Rr][Pp][Hh][Ii][Cc] TPRETURN(MACH_MSG_TYPE_POLYMORPHIC, MACH_MSG_TYPE_POLYMORPHIC, PortSize);
<Normal>[Aa][Uu][Tt][Oo] FRETURN(flAuto);
<Normal>[Cc][Oo][Nn][Ss][Tt] FRETURN(flConst);
<Normal>"PointerTo" RETURN(syPointerTo);
<Normal>"PointerToIfNot" RETURN(syPointerToIfNot);
<Normal>"ValueOf" RETURN(syValueOf);
<Normal>"UserTypeLimit" RETURN(syUserTypeLimit);
<Normal>"OnStackLimit" RETURN(syOnStackLimit);
<Normal>"MACH_MSG_TYPE_UNSTRUCTURED" TRETURN(MACH_MSG_TYPE_UNSTRUCTURED,0);
<Normal>"MACH_MSG_TYPE_BIT" TRETURN(MACH_MSG_TYPE_BIT,1);
<Normal>"MACH_MSG_TYPE_BOOLEAN" TRETURN(MACH_MSG_TYPE_BOOLEAN,32);
<Normal>"MACH_MSG_TYPE_INTEGER_8" TRETURN(MACH_MSG_TYPE_INTEGER_8,8);
<Normal>"MACH_MSG_TYPE_INTEGER_16" TRETURN(MACH_MSG_TYPE_INTEGER_16,16);
<Normal>"MACH_MSG_TYPE_INTEGER_32" TRETURN(MACH_MSG_TYPE_INTEGER_32,32);
<Normal>"MACH_MSG_TYPE_INTEGER_64" TRETURN(MACH_MSG_TYPE_INTEGER_64,64);
<Normal>"MACH_MSG_TYPE_REAL_32" TRETURN(MACH_MSG_TYPE_REAL_32,32);
<Normal>"MACH_MSG_TYPE_REAL_64" TRETURN(MACH_MSG_TYPE_REAL_64,64);
<Normal>"MACH_MSG_TYPE_CHAR" TRETURN(MACH_MSG_TYPE_CHAR,8);
<Normal>"MACH_MSG_TYPE_BYTE" TRETURN(MACH_MSG_TYPE_BYTE,8);
<Normal>"MACH_MSG_TYPE_MOVE_RECEIVE" TPRETURN(MACH_MSG_TYPE_MOVE_RECEIVE,MACH_MSG_TYPE_PORT_RECEIVE,PortSize);
<Normal>"MACH_MSG_TYPE_COPY_SEND" TPRETURN(MACH_MSG_TYPE_COPY_SEND,MACH_MSG_TYPE_PORT_SEND,PortSize);
<Normal>"MACH_MSG_TYPE_MAKE_SEND" TPRETURN(MACH_MSG_TYPE_MAKE_SEND,MACH_MSG_TYPE_PORT_SEND,PortSize);
<Normal>"MACH_MSG_TYPE_MOVE_SEND" TPRETURN(MACH_MSG_TYPE_MOVE_SEND,MACH_MSG_TYPE_PORT_SEND,PortSize);
<Normal>"MACH_MSG_TYPE_MAKE_SEND_ONCE" TPRETURN(MACH_MSG_TYPE_MAKE_SEND_ONCE,MACH_MSG_TYPE_PORT_SEND_ONCE,PortSize);
<Normal>"MACH_MSG_TYPE_MOVE_SEND_ONCE" TPRETURN(MACH_MSG_TYPE_MOVE_SEND_ONCE,MACH_MSG_TYPE_PORT_SEND_ONCE,PortSize);
<Normal>"MACH_MSG_TYPE_PORT_NAME" TRETURN(MACH_MSG_TYPE_PORT_NAME,PortSize);
<Normal>"MACH_MSG_TYPE_PORT_RECEIVE" TPRETURN(MACH_MSG_TYPE_POLYMORPHIC,MACH_MSG_TYPE_PORT_RECEIVE,PortSize);
<Normal>"MACH_MSG_TYPE_PORT_SEND" TPRETURN(MACH_MSG_TYPE_POLYMORPHIC,MACH_MSG_TYPE_PORT_SEND,PortSize);
<Normal>"MACH_MSG_TYPE_PORT_SEND_ONCE" TPRETURN(MACH_MSG_TYPE_POLYMORPHIC,MACH_MSG_TYPE_PORT_SEND_ONCE,PortSize);
<Normal>"MACH_MSG_TYPE_POLYMORPHIC" TPRETURN(MACH_MSG_TYPE_POLYMORPHIC, MACH_MSG_TYPE_POLYMORPHIC, PortSize);
<Normal>":" RETURN(syColon);
<Normal>";" RETURN(sySemi);
<Normal>"," RETURN(syComma);
<Normal>"+" RETURN(syPlus);
<Normal>"-" RETURN(syMinus);
<Normal>"*" RETURN(syStar);
<Normal>"/" RETURN(syDiv);
<Normal>"(" RETURN(syLParen);
<Normal>")" RETURN(syRParen);
<Normal>"=" RETURN(syEqual);
<Normal>"^" RETURN(syCaret);
<Normal>"~" RETURN(syTilde);
<Normal>"<" RETURN(syLAngle);
<Normal>">" RETURN(syRAngle);
<Normal>"[" RETURN(syLBrack);
<Normal>"]" RETURN(syRBrack);
<Normal>"|" RETURN(syBar);
<Normal>{Ident} { yylval.identifier = strmake(yytext);
RETURN(syIdentifier); }
<Normal>{Number} { yylval.number = atoi(yytext); RETURN(syNumber); }
<String>{String} { yylval.string = strmake(yytext);
SAVE(Normal); RETURN(syString); }
<FileName>{FileName} { yylval.string = strmake(yytext);
SAVE(Normal); RETURN(syFileName); }
<QString>{QString} { yylval.string = strmake(yytext);
SAVE(Normal); RETURN(syQString); }
^\#[ \t]*{Number}[ \t]*\"[^"]*\" { doSharp(yytext+1);
BEGIN SkipToEOL; }
^\#\ *{Number} { doSharp(yytext+1);
BEGIN SkipToEOL; }
^\#pragma { BEGIN SkipToEOL; }
^\# { yyerror("illegal # directive");
BEGIN SkipToEOL; }
<SkipToEOL>\n { RESTORE; lineno++; }
<SkipToEOL>. ;
[ \t] ;
\n lineno++;
. { SAVE(Normal); RETURN(syError); }
%%
extern void
LookNormal()
{
SAVE(Normal);
}
extern void
LookString()
{
SAVE(String);
}
extern void
LookQString()
{
SAVE(QString);
}
extern void
LookFileName()
{
SAVE(FileName);
}
static void
doSharp(char *body)
{
char *startName, *endName;
lineno = atoi(body);
startName = strchr(body, '"');
if (startName != NULL) {
endName = strrchr(body, '"');
*endName = '\0';
strfree(yyinname);
yyinname = strmake(startName+1);
}
}
int
yywrap()
{
return 1;
}

88
tools/mig/mig.1 Normal file
View File

@@ -0,0 +1,88 @@
.TH MIG 1 "Nov 20, 2009" "Apple Computer, Inc."
.SH NAME
mig \- Mach Interface Generator
.SH SYNOPSIS
.B mig
[
.I "option \&..."
]
.I "file"
.SH DESCRIPTION
The
.I mig
command invokes the Mach Interface Generator to generate Remote Procedure Call (RPC)
code for client-server style Mach IPC from specification files.
.SH OPTIONS
.TP
.B \-q/-Q
Omit /
.I emit
warning messages.
.TP
.B \-v/-V
Verbose mode ( on /
.I off
) will summarize types and routines as they are processed.
.TP
.B \-l/-L
Controls (
.I off
/ on ) whether or not generated code logs RPC events to system logs.
.TP
.B \-k/-K
Controls (
.I on
/ off ) whether generated code complies with ANSI C standards.
.TP
.B \-s/-S
Controls ( on /
.I off
) whether generated server-side code includes a generated symbol table.
.TP
.BI \-i " prefix"
Specify User file prefix.
.TP
.BI \-user " path"
Specify name of user-side RPC generated source file.
.TP
.BI \-server " path"
Specify name of server-side RPC generated source file.
.TP
.BI \-header " path"
Specify name of user-side generated header file.
.TP
.BI \-sheader " path"
Specify name of server-side generated header file.
.TP
.BI \-iheader " path"
Specify internal header file name.
.TP
.BI \-dheader " path"
Specify defines generated header file.
.TP
.BI \-maxonstack " value"
Specify maximum size of message on stack.
.TP
.B \-split
Use split headers.
.TP
.BI \-arch " arch"
Specify machine architecture for target code.
.TP
.B \-MD
Option is passed to the C compiler for dependency generation.
.TP
.B \-cpp
This option is ignored.
.TP
.BI \-cc " path"
Specify pathname to specific C compiler to use as the preprocessor.
.TP
.BI \-migcom " path"
Specify pathname to specific migcom compiler to use for source code generation.
.TP
.BI \-isysroot " path"
Specify SDK root directory.
.TP
Additional options provided are passed along to the C compiler unchanged.

405
tools/mig/mig.c Normal file
View File

@@ -0,0 +1,405 @@
/*
* Copyright (c) 1999-2018 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* Switches are;
* -[v,Q] verbose or not quiet: prints out type
* and routine information as mig runs.
* -[V,q] not verbose or quiet : don't print
* information during compilation
* (this is the default)
* -[r,R] do or don't use rpc calls instead of
* send/receive pairs. Default is -r.
* -[s,S] generate symbol table or not: generate a
* table of rpc-name, number, routine triplets
* as an external data structure -- main use is
* for protection system's specification of rights
* and for protection dispatch code. Default is -s.
* -[l,L] -L generate code that insert code for logging
* the most important events that happen at the
* stub level (message conception, target routine
* calls). Default is -l.
* -[k,K] -K enforces MIG to generate K&R C language, with the
* addition of ANSI C syntax under #ifdef __STDC__.
* Default is -k.
* -[n,N] -n enforces NDR checking and conversion logic generation.
* Default is -N (no checking).
* -i <prefix>
* Put each user routine in its own file. The
* file is named <prefix><routine-name>.c.
* -user <name>
* Name the user-side file <name>
* -server <name>
* Name the server-side file <name>
* -header <name>
* Name the user-side header file <name>
* -iheader <name>
* Name the user-side internal header file <name>
* -sheader <name>
* Name the server-side header file <name>
* -dheader <name>
* Name the defines (msgh_ids) header file <name>
*
* DESIGN:
* Mig uses a lexxer module created by lex from lexxer.l and
* a parser module created by yacc from parser.y to parse an
* interface definitions module for a mach server.
* The parser module calls routines in statement.c
* and routines.c to build a list of statement structures.
* The most interesting statements are the routine definitions
* which contain information about the name, type, characteristics
* of the routine, an argument list containing information for
* each argument type, and a list of special arguments. The
* argument type structures are build by routines in type.c
* Once parsing is completed, the three code generation modules:
* header.c user.c and server.c are called sequentially. These
* do some code generation directly and also call the routines
* in utils.c for common (parameterized) code generation.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "error.h"
#include "lexxer.h"
#include "global.h"
#include "write.h"
extern int yyparse(void);
static FILE *myfopen(const char *name, const char *mode);
static void
parseArgs(int argc,char *argv[])
{
if (argc == 2 && streql(argv[1], "-version")) {
PrintVersion = TRUE;
return;
}
while (--argc > 0)
if ((++argv)[0][0] == '-') {
switch (argv[0][1]) {
case 'q':
BeQuiet = TRUE;
break;
case 'Q':
BeQuiet = FALSE;
break;
case 'v':
BeVerbose = TRUE;
break;
case 'V':
BeVerbose = FALSE;
break;
case 'r':
UseMsgRPC = TRUE;
break;
case 'R':
UseMsgRPC = FALSE;
break;
case 'l':
UseEventLogger = FALSE;
break;
case 'L':
UseEventLogger = TRUE;
break;
case 'k':
BeAnsiC = TRUE;
break;
case 'K':
BeAnsiC = FALSE;
break;
case 'n':
if (streql(argv[0], "-novouchers")) {
IsVoucherCodeAllowed = FALSE;
} else {
CheckNDR = TRUE;
}
break;
case 'N':
CheckNDR = FALSE;
break;
case 's':
if (streql(argv[0], "-server")) {
--argc; ++argv;
if (argc == 0)
fatal("missing name for -server option");
ServerFileName = strmake(argv[0]);
}
else if (streql(argv[0], "-sheader")) {
--argc; ++argv;
if (argc == 0)
fatal ("missing name for -sheader option");
ServerHeaderFileName = strmake(argv[0]);
}
else if (streql(argv[0], "-split"))
UseSplitHeaders = TRUE;
else
GenSymTab = TRUE;
break;
case 'S':
GenSymTab = FALSE;
break;
case 't':
warn("Mach RPC traps not fully supported");
TestRPCTrap = TRUE;
UseRPCTrap = TRUE;
break;
case 'T':
UseRPCTrap = FALSE;
break;
case 'i':
if (streql(argv[0], "-iheader")) {
--argc; ++argv;
if (argc == 0)
fatal("missing name for -iheader option");
InternalHeaderFileName = strmake(argv[0]);
}
else {
--argc; ++argv;
if (argc == 0)
fatal("missing prefix for -i option");
UserFilePrefix = strmake(argv[0]);
}
break;
case 'u':
if (streql(argv[0], "-user")) {
--argc; ++argv;
if (argc == 0)
fatal("missing name for -user option");
UserFileName = strmake(argv[0]);
}
else
fatal("unknown flag: '%s'", argv[0]);
break;
case 'h':
if (streql(argv[0], "-header")) {
--argc; ++argv;
if (argc == 0)
fatal("missing name for -header option");
UserHeaderFileName = strmake(argv[0]);
}
else
fatal("unknown flag: '%s'", argv[0]);
break;
case 'd':
if (streql(argv[0], "-dheader")) {
--argc; ++argv;
if (argc == 0)
fatal("missing name for -dheader option");
DefinesHeaderFileName = strmake(argv[0]);
}
else
fatal("unknown flag: '%s'", argv[0]);
break;
case 'm':
if (streql(argv[0], "-maxonstack")) {
--argc; ++argv;
if (argc == 0)
fatal("missing size for -maxonstack option");
MaxMessSizeOnStack = atoi(argv[0]);
}
else
fatal("unknown flag: '%s'", argv[0]);
break;
case 'X':
ShortCircuit = FALSE;
break;
case 'x':
ShortCircuit = TRUE;
/* fall thru - no longer supported */
default:
fatal("unknown/unsupported flag: '%s'", argv[0]);
/*NOTREACHED*/
}
}
else
fatal("bad argument: '%s'", *argv);
}
FILE *uheader, *server, *user;
int
main(int argc, char *argv[])
{
FILE *iheader = 0;
FILE *sheader = 0;
FILE *dheader = 0;
time_t loc;
extern string_t GenerationDate;
set_program_name("mig");
parseArgs(argc, argv);
if (PrintVersion) {
printf("%s\n", MIG_VERSION);
fflush(stdout);
exit(0);
}
init_global();
init_type();
loc = time((time_t *)0);
GenerationDate = ctime(&loc);
LookNormal();
(void) yyparse();
if (mig_errors > 0)
fatal("%d errors found. Abort.\n", mig_errors);
more_global();
uheader = myfopen(UserHeaderFileName, "w");
if (!UserFilePrefix)
user = myfopen(UserFileName, "w");
server = myfopen(ServerFileName, "w");
if (ServerHeaderFileName)
sheader = myfopen(ServerHeaderFileName, "w");
if (IsKernelServer) {
iheader = myfopen(InternalHeaderFileName, "w");
}
if (DefinesHeaderFileName)
dheader = myfopen(DefinesHeaderFileName, "w");
if (BeVerbose) {
printf("Writing %s ... ", UserHeaderFileName);
fflush(stdout);
}
WriteUserHeader(uheader, stats);
fclose(uheader);
if (ServerHeaderFileName) {
if (BeVerbose) {
printf ("done.\nWriting %s ...", ServerHeaderFileName);
fflush (stdout);
}
WriteServerHeader(sheader, stats);
fclose(sheader);
}
if (IsKernelServer) {
if (BeVerbose) {
printf("done.\nWriting %s ... ", InternalHeaderFileName);
fflush(stdout);
}
WriteInternalHeader(iheader, stats);
fclose(iheader);
}
if (DefinesHeaderFileName) {
if (BeVerbose) {
printf ("done.\nWriting %s ...", DefinesHeaderFileName);
fflush (stdout);
}
WriteDefinesHeader(dheader, stats);
fclose(dheader);
}
if (UserFilePrefix) {
if (BeVerbose) {
printf("done.\nWriting individual user files ... ");
fflush(stdout);
}
WriteUserIndividual(stats);
}
else {
if (BeVerbose) {
printf("done.\nWriting %s ... ", UserFileName);
fflush(stdout);
}
WriteUser(user, stats);
fclose(user);
}
if (BeVerbose) {
printf("done.\nWriting %s ... ", ServerFileName);
fflush(stdout);
}
WriteServer(server, stats);
fclose(server);
if (BeVerbose)
printf("done.\n");
exit(0);
}
static FILE *
myfopen(const char *name, const char *mode)
{
const char *realname;
FILE *file;
if (name == strNULL)
realname = "/dev/null";
else
realname = name;
file = fopen(realname, mode);
if (file == NULL)
fatal("fopen(%s): %s", realname, strerror(errno));
return file;
}

218
tools/mig/mig.sh Normal file
View File

@@ -0,0 +1,218 @@
#!/bin/bash
#
# Copyright (c) 1999-2008 Apple Inc. All rights reserved.
#
# @APPLE_LICENSE_HEADER_START@
#
# "Portions Copyright (c) 1999, 2008 Apple Inc. All Rights
# Reserved. This file contains Original Code and/or Modifications of
# Original Code as defined in and that are subject to the Apple Public
# Source License Version 1.0 (the 'License'). You may not use this file
# except in compliance with the License. Please obtain a copy of the
# License at http://www.apple.com/publicsource and read it before using
# this file.
#
# The Original Code and all software distributed under the License are
# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
# License for the specific language governing rights and limitations
# under the License."
#
# @APPLE_LICENSE_HEADER_END@
#
# Mach Operating System
# Copyright (c) 1991,1990 Carnegie Mellon University
# All Rights Reserved.
#
# Permission to use, copy, modify and distribute this software and its
# documentation is hereby granted, provided that both the copyright
# notice and this permission notice appear in all copies of the
# software, derivative works or modified versions, and any portions
# thereof, and that both notices appear in supporting documentation.
#
# CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
# CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
# ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
#
# Carnegie Mellon requests users of this software to return to
#
# Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
# School of Computer Science
# Carnegie Mellon University
# Pittsburgh PA 15213-3890
#
# any improvements or extensions that they make and grant Carnegie Mellon
# the rights to redistribute these changes.
#
realpath()
{
local FILE="$1"
local PARENT=$(dirname "$FILE")
local BASE=$(basename "$FILE")
pushd "$PARENT" >/dev/null 2>&1 || return 0
local DIR=$(pwd -P)
popd >/dev/null
if [ "$DIR" == "/" ]; then
echo "/$BASE"
else
echo "$DIR/$BASE"
fi
return 1
}
scriptPath=$(realpath "$0")
scriptRoot=$(dirname "$scriptPath")
migcomPath=$(realpath "${scriptRoot}/../libexec/migcom")
if [ -n "${SDKROOT}" ]; then
sdkRoot="${SDKROOT}";
fi
if [ -z "${MIGCC}" ]; then
xcrunPath="/usr/bin/xcrun"
if [ -x "${xcrunPath}" ]; then
MIGCC=`"${xcrunPath}" -sdk "$sdkRoot" -find cc`
else
MIGCC=$(realpath "${scriptRoot}/cc")
fi
fi
C=${MIGCC}
M=${MIGCOM-${migcomPath}}
if [ $# -eq 1 ] && [ "$1" = "-version" ] ; then
"$M" "$@"
exit $?
fi
cppflags="-D__MACH30__"
files=
arch=`/usr/bin/arch`
WORKTMP=`/usr/bin/mktemp -d "${TMPDIR:-/tmp}/mig.XXXXXX"`
if [ $? -ne 0 ]; then
echo "Failure creating temporary work directory: ${WORKTMP}"
echo "Exiting..."
exit 1
fi
# parse out the arguments until we hit plain file name(s)
until [ $# -eq 0 ]
do
case "$1" in
-[dtqkKQvVtTrRsSlLxXnN] ) migflags=( "${migflags[@]}" "$1" ); shift;;
-i ) sawI=1; migflags=( "${migflags[@]}" "$1" "$2" ); shift; shift;;
-user ) user="$2"; if [ ! "${sawI-}" ]; then migflags=( "${migflags[@]}" "$1" "$2" ); fi; shift; shift;;
-server ) server="$2"; migflags=( "${migflags[@]}" "$1" "$2" ); shift; shift;;
-header ) header="$2"; migflags=( "${migflags[@]}" "$1" "$2"); shift; shift;;
-sheader ) sheader="$2"; migflags=( "${migflags[@]}" "$1" "$2"); shift; shift;;
-iheader ) iheader="$2"; migflags=( "${migflags[@]}" "$1" "$2"); shift; shift;;
-dheader ) dheader="$2"; migflags=( "${migflags[@]}" "$1" "$2"); shift; shift;;
-arch ) arch="$2"; shift; shift;;
-target ) target=( "$1" "$2"); shift; shift;;
-maxonstack ) migflags=( "${migflags[@]}" "$1" "$2"); shift; shift;;
-split ) migflags=( "${migflags[@]}" "$1" ); shift;;
-novouchers ) migflags=( "${migflags[@]}" "$1" ); shift;;
-MD ) sawMD=1; cppflags=( "${cppflags[@]}" "$1"); shift;;
-cpp) shift; shift;;
-cc) C="$2"; shift; shift;;
-migcom) M="$2"; shift; shift;;
-isysroot) sdkRoot=$(realpath "$2"); shift; shift;;
-* ) cppflags=( "${cppflags[@]}" "$1"); shift;;
* ) break;;
esac
done
# process the rest as files
until [ $# -eq 0 ]
do
case "$1" in
-[dtqkKQvVtTrRsSlLxXnN] ) echo "warning: option \"$1\" after filename(s) ignored"; shift; continue;;
-i ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;;
-user ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;;
-server ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;;
-header ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;;
-sheader ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;;
-iheader ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;;
-dheader ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;;
-arch ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift ; shift; continue;;
-target ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift ; shift; continue;;
-maxonstack ) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;;
-split ) echo "warning: option \"$1\" after filename(s) ignored"; shift; continue;;
-novouchers ) echo "warning: option \"$1\" after filename(s) ignored"; shift; continue;;
-MD ) echo "warning: option \"$1\" after filename(s) ignored"; shift; continue;;
-cpp) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;;
-cc) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;;
-migcom) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;;
-isysroot) echo "warning: option \"$1 $2\" after filename(s) ignored"; shift; shift; continue;;
-* ) echo "warning: option \"$1\" after filename(s) ignored"; shift; continue;;
* ) file="$1"; shift;;
esac
base="$(basename "${file}" .defs)"
temp="${WORKTMP}/${base}.$$"
sourcedir="$(dirname "${file}")"
if [ -n "${sdkRoot}" ]
then
iSysRootParm=( "-isysroot" "${sdkRoot}" )
fi
if [ ! -r "${file}" ]
then
echo "error: cannot read file ${file}"
rm -rf ${WORKTMP}
exit 1
fi
rm -f "${temp}.c" "${temp}.d"
(echo '#line 1 '\"${file}\" ; cat "${file}" ) > "${temp}.c"
"$C" -E -arch ${arch} "${target[@]}" "${cppflags[@]}" -I "${sourcedir}" "${iSysRootParm[@]}" "${temp}.c" | "$M" "${migflags[@]}"
if [ $? -ne 0 ]
then
rm -rf "${temp}.c" "${temp}.d" "${WORKTMP}"
exit 1
fi
if [ "${sawMD}" -a -f "${temp}.d" ]
then
deps=
s=
rheader="${header-${base}.h}"
if [ "${rheader}" != /dev/null ]; then
deps="${deps}${s}${rheader}"; s=" "
fi
ruser="${user-${base}User.c}"
if [ "${ruser}" != /dev/null ]; then
deps="${deps}${s}${ruser}"; s=" "
fi
rserver="${server-${base}Server.c}"
if [ "${rserver}" != /dev/null ]; then
deps="${deps}${s}${rserver}"; s=" "
fi
rsheader="${sheader-/dev/null}"
if [ "${rsheader}" != /dev/null ]; then
deps="${deps}${s}${rsheader}"; s=" "
fi
riheader="${iheader-/dev/null}"
if [ "${riheader}" != /dev/null ]; then
deps="${deps}${s}${riheader}"; s=" "
fi
rdheader="${dheader-/dev/null}"
if [ "${rdheader}" != /dev/null ]; then
deps="${deps}${s}${rdheader}"; s=" "
fi
for target in "${deps}"
do
sed -e 's;^'"${temp}"'.o[ ]*:;'"${target}"':;' \
-e 's;: '"${temp}"'.c;: '"$file"';' \
< "${temp}.d" > "${target}.d"
done
rm -f "${temp}.d"
fi
rm -f "${temp}.c"
done
/bin/rmdir "${WORKTMP}"
exit 0

84
tools/mig/mig_errors.h Normal file
View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1987 Carnegie-Mellon University
* All rights reserved. The CMU software License Agreement specifies
* the terms and conditions for use and redistribution.
*/
/*
* Mach Interface Generator errors
*
* $Header: /Users/Shared/bootstrap_cmds/bootstrap_cmds/migcom.tproj/mig_errors.h,v 1.1.1.2 2000/01/11 00:36:18 wsanchez Exp $
*
* HISTORY
* 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
* Extensive revamping. Added polymorphic arguments.
* Allow multiple variable-sized inline arguments in messages.
*
* 28-Apr-88 Bennet Yee (bsy) at Carnegie-Mellon University
* Put mig_symtab back.
*
* 2-Dec-87 David Golub (dbg) at Carnegie-Mellon University
* Added MIG_ARRAY_TOO_LARGE.
*
* 25-May-87 Richard Draves (rpd) at Carnegie-Mellon University
* Added definition of death_pill_t.
*
* 31-Jul-86 Michael Young (mwyoung) at Carnegie-Mellon University
* Created.
*/
#ifndef _MIG_ERRORS_H
#define _MIG_ERRORS_H
#include <mach/kern_return.h>
#include <mach/message.h>
#define MIG_TYPE_ERROR -300 /* Type check failure */
#define MIG_REPLY_MISMATCH -301 /* Wrong return message ID */
#define MIG_REMOTE_ERROR -302 /* Server detected error */
#define MIG_BAD_ID -303 /* Bad message ID */
#define MIG_BAD_ARGUMENTS -304 /* Server found wrong arguments */
#define MIG_NO_REPLY -305 /* Server shouldn't reply */
#define MIG_EXCEPTION -306 /* Server raised exception */
#define MIG_ARRAY_TOO_LARGE -307 /* User specified array not large enough
to hold returned array */
typedef struct {
msg_header_t Head;
msg_type_t RetCodeType;
kern_return_t RetCode;
} death_pill_t;
typedef struct mig_symtab {
char *ms_routine_name;
int ms_routine_number;
#ifdef hc
void
#else
int
#endif
(*ms_routine)();
} mig_symtab_t;
#endif _MIG_ERRORS_H

16
tools/mig/mig_machine.h Normal file
View File

@@ -0,0 +1,16 @@
#if !defined(_MIG_MACHINE_H)
#define _MIG_MACHINE_H
#define machine_alignment(SZ,ESZ) \
(((SZ) = ((SZ) + 3) & ~3), (SZ) += (ESZ))
#define machine_padding(BYTES) \
((BYTES & 3) ? (4 - (BYTES & 3)) : 0)
#ifndef NBBY
#define NBBY 8
#endif
#define PACK_MESSAGES TRUE
#endif

73
tools/mig/migcom.1 Normal file
View File

@@ -0,0 +1,73 @@
.TH MIGCOM 1 "Nov 20, 2009" "Apple Computer, Inc."
.SH NAME
migcom \- Mach Interface Generator COMpiler
.SH SYNOPSIS
.B migcom
[
.I "option \&..."
]
.I "<file"
.SH DESCRIPTION
.I migcom
is the actual compiler used by the
.I mig
command to generate Remote Procedure Call (RPC) source code for
client-server style Mach IPC from specification files. It is not normally
used independently. Rather, it is invoked by the
.I mig
command after pre-processing the provided specifications file with the C
preprocessor. It is only documented here for the sake of completeness.
.SH OPTIONS
.TP
.B \-q/-Q
Omit /
.I emit
warning messages.
.TP
.B \-v/-V
Verbose mode ( on /
.I off
) will summarize types and routines as they are processed.
.TP
.B \-l/-L
Controls (
.I off
/ on ) whether or not generated code logs RPC events to system logs.
.TP
.B \-k/-K
Controls (
.I on
/ off ) whether generated code complies with ANSI C standards.
.TP
.B \-s/-S
Controls ( on /
.I off
) whether generated server-side code includes a generated symbol table.
.TP
.BI \-i " prefix"
Specify User file prefix.
.TP
.BI \-user " path"
Specify name of user-side RPC generated source file.
.TP
.BI \-server " path"
Specify name of server-side RPC generated source file.
.TP
.BI \-header " path"
Specify name of user-side generated header file.
.TP
.BI \-sheader " path"
Specify name of server-side generated header file.
.TP
.BI \-iheader " path"
Specify internal header file name.
.TP
.BI \-dheader " path"
Specify defines generated header file.
.TP
.BI \-maxonstack " value"
Specify maximum size of message on stack.
.TP
.B \-split
Use split headers.

803
tools/mig/parser.y Normal file
View File

@@ -0,0 +1,803 @@
/*
* Copyright (c) 1999-2018 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
%token sySkip
%token syRoutine
%token sySimpleRoutine
%token sySubsystem
%token syKernelUser
%token syKernelServer
%token syMsgOption
%token syUseSpecialReplyPort
%token syConsumeOnSendError
%token syMsgSeqno
%token syWaitTime
%token sySendTime
%token syNoWaitTime
%token syNoSendTime
%token syErrorProc
%token syServerPrefix
%token syUserPrefix
%token syServerDemux
%token syRCSId
%token syImport
%token syUImport
%token sySImport
%token syIImport
%token syDImport
%token syIn
%token syOut
%token syInOut
%token syUserImpl
%token syServerImpl
%token syRequestPort
%token syReplyPort
%token sySReplyPort
%token syUReplyPort
%token syType
%token syArray
%token syStruct
%token syOf
%token syInTran
%token syOutTran
%token syDestructor
%token syCType
%token syCUserType
%token syUserTypeLimit
%token syOnStackLimit
%token syCServerType
%token syPointerTo
%token syPointerToIfNot
%token syValueOf
%token syCString
%token sySecToken
%token syUserSecToken
%token syServerSecToken
%token syAuditToken
%token syUserAuditToken
%token syServerAuditToken
%token syServerContextToken
%token syColon
%token sySemi
%token syComma
%token syPlus
%token syMinus
%token syStar
%token syDiv
%token syLParen
%token syRParen
%token syEqual
%token syCaret
%token syTilde
%token syLAngle
%token syRAngle
%token syLBrack
%token syRBrack
%token syBar
%token syError /* lex error */
%token <number> syNumber
%token <symtype> sySymbolicType
%token <identifier> syIdentifier
%token <string> syString syQString
%token <string> syFileName
%token <flag> syIPCFlag
%left syPlus syMinus
%left syStar syDiv
%type <statement_kind> ImportIndicant
%type <number> VarArrayHead ArrayHead StructHead IntExp
%type <type> NamedTypeSpec TransTypeSpec NativeTypeSpec TypeSpec
%type <type> CStringSpec
%type <type> BasicTypeSpec PrevTypeSpec ArgumentType
%type <identifier> TypePhrase
%type <symtype> PrimIPCType IPCType
%type <routine> RoutineDecl Routine SimpleRoutine
%type <direction> Direction TrImplKeyword
%type <argument> Argument Trailer Arguments ArgumentList
%type <flag> IPCFlags
%{
#include <stdio.h>
#include "lexxer.h"
#include "strdefs.h"
#include "type.h"
#include "routine.h"
#include "statement.h"
#include "global.h"
#include "error.h"
static char *import_name(statement_kind_t sk);
extern int yylex(void);
/* forward declaration */
void yyerror(char *s);
%}
%union
{
u_int number;
identifier_t identifier;
string_t string;
statement_kind_t statement_kind;
ipc_type_t *type;
struct
{
u_int innumber; /* msgt_name value, when sending */
string_t instr;
u_int outnumber; /* msgt_name value, when receiving */
string_t outstr;
u_int size; /* 0 means there is no default size */
} symtype;
routine_t *routine;
arg_kind_t direction;
argument_t *argument;
ipc_flags_t flag;
}
%%
Statements : /* empty */
| Statements Statement
;
Statement : Subsystem sySemi
| WaitTime sySemi
| SendTime sySemi
| MsgOption sySemi
| UseSpecialReplyPort sySemi
| ConsumeOnSendError sySemi
| UserTypeLimit sySemi
| OnStackLimit sySemi
| Error sySemi
| ServerPrefix sySemi
| UserPrefix sySemi
| ServerDemux sySemi
| TypeDecl sySemi
| RoutineDecl sySemi
{
statement_t *st = stAlloc();
st->stKind = skRoutine;
st->stRoutine = $1;
rtCheckRoutine($1);
if (BeVerbose)
rtPrintRoutine($1);
}
| sySkip sySemi
{ rtSkip(); }
| Import sySemi
| RCSDecl sySemi
| sySemi
| error sySemi
{ yyerrok; }
;
Subsystem : SubsystemStart SubsystemMods
SubsystemName SubsystemBase
{
if (BeVerbose) {
printf("Subsystem %s: base = %u%s%s\n\n",
SubsystemName, SubsystemBase,
IsKernelUser ? ", KernelUser" : "",
IsKernelServer ? ", KernelServer" : "");
}
}
;
SubsystemStart : sySubsystem
{
if (SubsystemName != strNULL) {
warn("previous Subsystem decl (of %s) will be ignored", SubsystemName);
IsKernelUser = FALSE;
IsKernelServer = FALSE;
strfree(SubsystemName);
}
}
;
SubsystemMods : /* empty */
| SubsystemMods SubsystemMod
;
SubsystemMod : syKernelUser
{
if (IsKernelUser)
warn("duplicate KernelUser keyword");
if (!UseMsgRPC) {
warn("with KernelUser the -R option is meaningless");
UseMsgRPC = TRUE;
}
IsKernelUser = TRUE;
}
| syKernelServer
{
if (IsKernelServer)
warn("duplicate KernelServer keyword");
IsKernelServer = TRUE;
}
;
SubsystemName : syIdentifier { SubsystemName = $1; }
;
SubsystemBase : syNumber { SubsystemBase = $1; }
;
MsgOption : LookString syMsgOption syString
{
if (streql($3, "MACH_MSG_OPTION_NONE")) {
MsgOption = strNULL;
if (BeVerbose)
printf("MsgOption: canceled\n\n");
}
else {
MsgOption = $3;
if (BeVerbose)
printf("MsgOption %s\n\n",$3);
}
}
;
UseSpecialReplyPort : syUseSpecialReplyPort syNumber
{
UseSpecialReplyPort = ($2 != 0);
HasUseSpecialReplyPort |= UseSpecialReplyPort;
}
;
ConsumeOnSendError : LookString syConsumeOnSendError syString
{
if (strcasecmp($3, "None") == 0) {
ConsumeOnSendError = ConsumeOnSendErrorNone;
} else if (strcasecmp($3, "Timeout") == 0) {
ConsumeOnSendError = ConsumeOnSendErrorTimeout;
HasConsumeOnSendError = TRUE;
} else if (strcasecmp($3, "Any") == 0) {
ConsumeOnSendError = ConsumeOnSendErrorAny;
HasConsumeOnSendError = TRUE;
} else {
error("syntax error");
}
}
;
UserTypeLimit : syUserTypeLimit syNumber
{UserTypeLimit = $2; }
;
OnStackLimit : syOnStackLimit syNumber
{MaxMessSizeOnStack = $2; }
;
WaitTime : LookString syWaitTime syString
{
WaitTime = $3;
if (BeVerbose)
printf("WaitTime %s\n\n", WaitTime);
}
| syNoWaitTime
{
WaitTime = strNULL;
if (BeVerbose)
printf("NoWaitTime\n\n");
}
;
SendTime : LookString sySendTime syString
{
SendTime = $3;
if (BeVerbose)
printf("SendTime %s\n\n", SendTime);
}
| syNoSendTime
{
SendTime = strNULL;
if (BeVerbose)
printf("NoSendTime\n\n");
}
;
Error : syErrorProc syIdentifier
{
ErrorProc = $2;
if (BeVerbose)
printf("ErrorProc %s\n\n", ErrorProc);
}
;
ServerPrefix : syServerPrefix syIdentifier
{
ServerPrefix = $2;
if (BeVerbose)
printf("ServerPrefix %s\n\n", ServerPrefix);
}
;
UserPrefix : syUserPrefix syIdentifier
{
UserPrefix = $2;
if (BeVerbose)
printf("UserPrefix %s\n\n", UserPrefix);
}
;
ServerDemux : syServerDemux syIdentifier
{
ServerDemux = $2;
if (BeVerbose)
printf("ServerDemux %s\n\n", ServerDemux);
}
;
Import : LookFileName ImportIndicant syFileName
{
statement_t *st = stAlloc();
st->stKind = $2;
st->stFileName = $3;
if (BeVerbose)
printf("%s %s\n\n", import_name($2), $3);
}
;
ImportIndicant : syImport { $$ = skImport; }
| syUImport { $$ = skUImport; }
| sySImport { $$ = skSImport; }
| syIImport { $$ = skIImport; }
| syDImport { $$ = skDImport; }
;
RCSDecl : LookQString syRCSId syQString
{
if (RCSId != strNULL)
warn("previous RCS decl will be ignored");
if (BeVerbose)
printf("RCSId %s\n\n", $3);
RCSId = $3;
}
;
TypeDecl : syType NamedTypeSpec
{
identifier_t name = $2->itName;
if (itLookUp(name) != itNULL)
warn("overriding previous definition of %s", name);
itInsert(name, $2);
}
;
NamedTypeSpec : syIdentifier syEqual TransTypeSpec
{ itTypeDecl($1, $$ = $3); }
;
TransTypeSpec : TypeSpec
{ $$ = itResetType($1); }
| TransTypeSpec syInTran syColon syIdentifier
syIdentifier syLParen syIdentifier syRParen
{
$$ = $1;
if (($$->itTransType != strNULL) && !streql($$->itTransType, $4))
warn("conflicting translation types (%s, %s)", $$->itTransType, $4);
$$->itTransType = $4;
if (($$->itInTrans != strNULL) && !streql($$->itInTrans, $5))
warn("conflicting in-translation functions (%s, %s)", $$->itInTrans, $5);
$$->itInTrans = $5;
if (($$->itServerType != strNULL) && !streql($$->itServerType, $7))
warn("conflicting server types (%s, %s)", $$->itServerType, $7);
$$->itServerType = $7;
}
| TransTypeSpec syOutTran syColon syIdentifier
syIdentifier syLParen syIdentifier syRParen
{
$$ = $1;
if (($$->itServerType != strNULL) && !streql($$->itServerType, $4))
warn("conflicting server types (%s, %s)", $$->itServerType, $4);
$$->itServerType = $4;
if (($$->itOutTrans != strNULL) && !streql($$->itOutTrans, $5))
warn("conflicting out-translation functions (%s, %s)", $$->itOutTrans, $5);
$$->itOutTrans = $5;
if (($$->itTransType != strNULL) && !streql($$->itTransType, $7))
warn("conflicting translation types (%s, %s)", $$->itTransType, $7);
$$->itTransType = $7;
}
| TransTypeSpec syDestructor syColon syIdentifier
syLParen syIdentifier syRParen
{
$$ = $1;
if (($$->itDestructor != strNULL) && !streql($$->itDestructor, $4))
warn("conflicting destructor functions (%s, %s)", $$->itDestructor, $4);
$$->itDestructor = $4;
if (($$->itTransType != strNULL) && !streql($$->itTransType, $6))
warn("conflicting translation types (%s, %s)", $$->itTransType, $6);
$$->itTransType = $6;
}
| TransTypeSpec syCType syColon syIdentifier
{
$$ = $1;
if (($$->itUserType != strNULL) && !streql($$->itUserType, $4))
warn("conflicting user types (%s, %s)", $$->itUserType, $4);
$$->itUserType = $4;
if (($$->itServerType != strNULL) && !streql($$->itServerType, $4))
warn("conflicting server types (%s, %s)", $$->itServerType, $4);
$$->itServerType = $4;
}
| TransTypeSpec syCUserType syColon syIdentifier
{
$$ = $1;
if (($$->itUserType != strNULL) && !streql($$->itUserType, $4))
warn("conflicting user types (%s, %s)", $$->itUserType, $4);
$$->itUserType = $4;
}
| TransTypeSpec syCServerType
syColon syIdentifier
{
$$ = $1;
if (($$->itServerType != strNULL) && !streql($$->itServerType, $4))
warn("conflicting server types (%s, %s)",
$$->itServerType, $4);
$$->itServerType = $4;
}
;
TypeSpec : BasicTypeSpec
{ $$ = $1; }
| PrevTypeSpec
{ $$ = $1; }
| VarArrayHead TypeSpec
{ $$ = itVarArrayDecl($1, $2); }
| ArrayHead TypeSpec
{ $$ = itArrayDecl($1, $2); }
| syCaret TypeSpec
{ $$ = itPtrDecl($2); }
| StructHead TypeSpec
{ $$ = itStructDecl($1, $2); }
| CStringSpec
{ $$ = $1; }
| NativeTypeSpec
{ $$ = $1; }
;
NativeTypeSpec : syPointerTo syLParen TypePhrase syRParen
{ $$ = itNativeType($3, TRUE, 0); }
| syPointerToIfNot syLParen TypePhrase syComma
TypePhrase syRParen
{ $$ = itNativeType($3, TRUE, $5); }
| syValueOf syLParen TypePhrase syRParen
{ $$ = itNativeType($3, FALSE, 0); }
;
BasicTypeSpec : IPCType
{
$$ = itShortDecl($1.innumber, $1.instr,
$1.outnumber, $1.outstr,
$1.size);
}
| syLParen IPCType syComma IntExp
IPCFlags syRParen
{
error("Long form type declarations aren't allowed any longer\n");
}
;
PrimIPCType : syNumber
{
$$.innumber = $$.outnumber = $1;
$$.instr = $$.outstr = strNULL;
$$.size = 0;
}
| sySymbolicType
{ $$ = $1; }
;
IPCType : PrimIPCType
{ $$ = $1; }
| PrimIPCType syBar PrimIPCType
{
if ($1.size != $3.size) {
if ($1.size == 0)
$$.size = $3.size;
else if ($3.size == 0)
$$.size = $1.size;
else {
error("sizes in IPCTypes (%d, %d) aren't equal",
$1.size, $3.size);
$$.size = 0;
}
}
else
$$.size = $1.size;
$$.innumber = $1.innumber;
$$.instr = $1.instr;
$$.outnumber = $3.outnumber;
$$.outstr = $3.outstr;
}
;
PrevTypeSpec : syIdentifier
{ $$ = itPrevDecl($1); }
;
VarArrayHead : syArray syLBrack syRBrack syOf
{ $$ = 0; }
| syArray syLBrack syStar syRBrack syOf
{ $$ = 0; }
| syArray syLBrack syStar syColon IntExp
syRBrack syOf
{ $$ = $5; }
;
ArrayHead : syArray syLBrack IntExp syRBrack syOf
{ $$ = $3; }
;
StructHead : syStruct syLBrack IntExp syRBrack syOf
{ $$ = $3; }
;
CStringSpec : syCString syLBrack IntExp syRBrack
{ $$ = itCStringDecl($3, FALSE); }
| syCString syLBrack syStar syColon
IntExp syRBrack
{ $$ = itCStringDecl($5, TRUE); }
;
TypePhrase : syIdentifier
{ $$ = $1; }
| TypePhrase syIdentifier
{ $$ = strphrase($1, $2); strfree($2); }
;
IntExp : IntExp syPlus IntExp
{ $$ = $1 + $3; }
| IntExp syMinus IntExp
{ $$ = $1 - $3; }
| IntExp syStar IntExp
{ $$ = $1 * $3; }
| IntExp syDiv IntExp
{ $$ = $1 / $3; }
| syNumber
{ $$ = $1; }
| syLParen IntExp syRParen
{ $$ = $2; }
;
RoutineDecl : Routine { $$ = $1; }
| SimpleRoutine { $$ = $1; }
;
Routine : syRoutine syIdentifier Arguments
{ $$ = rtMakeRoutine($2, $3); }
;
SimpleRoutine : sySimpleRoutine syIdentifier Arguments
{ $$ = rtMakeSimpleRoutine($2, $3); }
;
Arguments : syLParen syRParen
{ $$ = argNULL; }
| syLParen ArgumentList syRParen
{ $$ = $2; }
;
ArgumentList : Argument
{ $$ = $1; }
| Trailer
{ $$ = $1; }
| Argument sySemi ArgumentList
{
$$ = $1;
$$->argNext = $3;
}
| Trailer sySemi ArgumentList
{
$$ = $1;
$$->argNext = $3;
}
;
Argument : Direction syIdentifier ArgumentType IPCFlags
{
$$ = argAlloc();
$$->argKind = $1;
$$->argName = $2;
$$->argType = $3;
$$->argFlags = $4;
if ($3 && $3->itNative) {
if ($1 != akIn && $1 != akOut && $1 != akInOut)
error("Illegal direction specified");
if (!($3->itNativePointer) && $1 != akIn)
error("ValueOf only valid for in");
if (($3->itBadValue) != NULL && $1 != akIn)
error("PointerToIfNot only valid for in");
}
}
;
Trailer : TrImplKeyword syIdentifier ArgumentType
{
$$ = argAlloc();
$$->argKind = $1;
$$->argName = $2;
$$->argType = $3;
}
;
Direction : /* empty */ { $$ = akNone; }
| syIn { $$ = akIn; }
| syOut { $$ = akOut; }
| syInOut { $$ = akInOut; }
| syRequestPort { $$ = akRequestPort; }
| syReplyPort { $$ = akReplyPort; }
| sySReplyPort { $$ = akSReplyPort; }
| syUReplyPort { $$ = akUReplyPort; }
| syWaitTime { $$ = akWaitTime; }
| sySendTime { $$ = akSendTime; }
| syMsgOption { $$ = akMsgOption; }
| sySecToken { $$ = akSecToken; }
| syServerSecToken { $$ = akServerSecToken; }
| syUserSecToken { $$ = akUserSecToken; }
| syAuditToken { $$ = akAuditToken; }
| syServerAuditToken { $$ = akServerAuditToken; }
| syUserAuditToken { $$ = akUserAuditToken; }
| syServerContextToken { $$ = akServerContextToken; }
| syMsgSeqno { $$ = akMsgSeqno; }
;
TrImplKeyword : syServerImpl { $$ = akServerImpl; }
| syUserImpl { $$ = akUserImpl; }
;
ArgumentType : syColon syIdentifier
{
$$ = itLookUp($2);
if ($$ == itNULL)
error("type '%s' not defined", $2);
}
| syColon NamedTypeSpec
{ $$ = $2; }
| syColon NativeTypeSpec
{ $$ = $2; }
;
IPCFlags : /* empty */
{ $$ = flNone; }
| IPCFlags syComma syIPCFlag
{
if ($1 & $3)
warn("redundant IPC flag ignored");
else
$$ = $1 | $3;
}
| IPCFlags syComma syIPCFlag syLBrack syRBrack
{
if ($3 != flDealloc)
warn("only Dealloc is variable");
else
$$ = $1 | flMaybeDealloc;
}
LookString : /* empty */
{ LookString(); }
;
LookFileName : /* empty */
{ LookFileName(); }
;
LookQString : /* empty */
{ LookQString(); }
;
%%
void
yyerror(char *s)
{
error(s);
}
static char *
import_name(statement_kind_t sk)
{
switch (sk) {
case skImport:
return "Import";
case skSImport:
return "SImport";
case skUImport:
return "UImport";
case skIImport:
return "IImport";
case skDImport:
return "DImport";
default:
fatal("import_name(%d): not import statement", (int) sk);
/*NOTREACHED*/
return strNULL;
}
}

1844
tools/mig/routine.c Normal file

File diff suppressed because it is too large Load Diff

549
tools/mig/routine.h Normal file
View File

@@ -0,0 +1,549 @@
/*
* Copyright (c) 1999-2018 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
#include <assert.h>
#ifndef _ROUTINE_H
#define _ROUTINE_H
#include "type.h"
#include <stdio.h>
#include <mach/message.h>
#include <mach/boolean.h>
#include <sys/types.h>
/* base kind arg */
#define akeNone (0)
#define akeNormal (1) /* a normal, user-defined argument */
#define akeRequestPort (2) /* pointed at by rtRequestPort */
#define akeWaitTime (3) /* pointed at by rtWaitTime */
#define akeReplyPort (4) /* pointed at by rtReplyPort */
#define akeMsgOption (5) /* pointed at by rtMsgOption */
#define akeMsgSeqno (6) /* pointed at by rtMsgSeqno */
#define akeRetCode (7) /* pointed at by rtRetCode */
#define akeNdrCode (8) /* pointed at by rtNdrCode */
#define akeCount (9) /* a count arg for argParent */
#define akePoly (10) /* a poly arg for argParent */
#define akeDealloc (11) /* a deallocate arg for argParent */
#define akeCountInOut (12) /* a count-in-out arg */
#define akeSameCount (13) /* a samecount case: in fact, a no count! */
#define akeSubCount (14) /* a array of array case: subordinate arrays count */
#define akeImplicit (15) /* an implicit argument, from the trailer */
#define akeSecToken (16) /* an argument from the trailer: the security token */
#define akeAuditToken (17) /* an argument from the trailer: the audit token */
#define akeContextToken (18) /* an argument from the trailer: the context token */
#define akeSendTime (19) /* pointed at by rtWaitTime */
#define akeBITS (0x0000003f)
#define akbRequest (0x00000040) /* has a msg_type in request */
#define akbReply (0x00000080) /* has a msg_type in reply */
#define akbUserArg (0x00000100) /* an arg on user-side */
#define akbServerArg (0x00000200) /* an arg on server-side */
#define akbSend (0x00000400) /* value carried in request */
#define akbSendBody (0x00000800) /* value carried in request body */
#define akbSendSnd (0x00001000) /* value stuffed into request */
#define akbSendRcv (0x00002000) /* value grabbed from request */
#define akbReturn (0x00004000) /* value carried in reply */
#define akbReturnBody (0x00008000) /* value carried in reply body */
#define akbReturnSnd (0x00010000) /* value stuffed into reply */
#define akbReturnRcv (0x00020000) /* value grabbed from reply */
#define akbReturnNdr (0x00040000) /* needs NDR conversion in reply */
#define akbReplyInit (0x00080000) /* reply value doesn't come from target routine */
#define akbReplyCopy (0x00200000) /* copy reply value from request */
#define akbVarNeeded (0x00400000) /* may need local var in server */
#define akbDestroy (0x00800000) /* call destructor function */
#define akbVariable (0x01000000) /* variable size inline data */
#define akbSendNdr (0x04000000) /* needs NDR conversion in request */
#define akbSendKPD (0x08000000) /* the arg is sent in the Kernel Processed Data
section of the Request message */
#define akbReturnKPD (0x10000000) /* the arg is sent in the Kernel Processed Data
section of the Reply message */
#define akbUserImplicit (0x20000000) /* the arg is Impl */
#define akbServerImplicit (0x40000000) /* the arg is Impl */
#define akbOverwrite (0x80000000)
/* be careful, there aren't many bits left */
typedef u_int arg_kind_t;
/*
* akbRequest means msg_type/data fields are allocated in the request
* msg. akbReply means msg_type/data fields are allocated in the
* reply msg. These bits * control msg structure declarations packing,
* and checking of mach_msg_type_t fields.
*
* akbUserArg means this argument is an argument to the user-side stub.
* akbServerArg means this argument is an argument to
* the server procedure called by the server-side stub.
*
* The akbSend* and akbReturn* bits control packing/extracting values
* in the request and reply messages.
*
* akbSend means the argument's value is carried in the request msg.
* akbSendBody implies akbSend; the value is carried in the msg body.
* akbSendKPD is the equivalent of akbSendBody for Kernel Processed Data.
* akbSendSnd implies akbSend; the value is stuffed into the request.
* akbSendRcv implies akbSend; the value is pulled out of the request.
*
* akbReturn, akbReturnBody, akbReturnSnd, akbReturnRcv are defined
* similarly but apply to the reply message.
*
* User-side code generation (header.c, user.c) and associated code
* should use akbSendSnd and akbReturnRcv, but not akbSendRcv and
* akbReturnSnd. Server-side code generation (server.c) is reversed.
* Code generation should use the more specific akb{Send,Return}{Snd,Rcv}
* bits when possible, instead of akb{Send,Return}.
*
* Note that akRetCode and akReturn lack any Return bits, although
* there is a value in the msg. These guys are packed/unpacked
* with special code, unlike other arguments.
*
* akbReplyInit implies akbReply. It means the server-side stub
* should initialize the field, because its value does not come
* from the execution of the target routine: the setting of the
* NDR record is the sole example (at the moment) of use of this flag.
*
* akbVariable means the argument has variable-sized inline data.
* It isn't currently used for code generation, but routine.c
* does use it internally. It is added in rtAugmentArgKind.
*
* akbReplyCopy and akbVarNeeded help control code generation in the
* server-side stub. The preferred method of handling data in the
* server-side stub avoids copying into/out-of local variables. In
* arguments get passed directly to the server proc from the request msg.
* Out arguments get stuffed directly into the reply msg by the server proc.
* For InOut arguments, the server proc gets the address of the data in
* the request msg, and the resulting data gets copied to the reply msg.
* Some arguments need a local variable in the server-side stub. The
* code extracts the data from the request msg into the variable, and
* stuff the reply msg from the variable.
*
* akbReplyCopy implies akbReply. It means the data should get copied
* from the request msg to the reply msg after the server proc is called.
* It is only used by akInOut. akTid doesn't need it because the tid
* data in the reply msg is initialized in the server demux function.
*
* akbVarNeeded means the argument needs a local variable in the
* server-side stub. It is added in rtAugmentArgKind and
* rtCheckVariable. An argument shouldn't have all three of
* akbReturnSnd, akbVarNeeded and akbReplyCopy, because this indicates
* the reply msg should be stuffed both ways.
*
* akbDestroy helps control code generation in the server-side stub.
* It means this argument has a destructor function which should be called.
*
* akbOverwrite is used to identify the arguments that have to put an entry in
* the scatter list (the message-template used by the User stub to specify
* where the out-of-line data sent by server has to land).
*
* akbUserImplicit (akbServerImplicit) is used to mark the arguments that
* correspond to implicit data (data generated by the kernel and inserted in
* the trailer).
*
* Header file generation (header.c) uses:
* akbUserArg
*
* User stub generation (user.c) uses:
* akbUserArg, akbRequest, akbReply, akbSendSnd,
* akbSendBody, akbSendKPD, akbReturnRcv, akbOverwrite, akbUserImplicit
*
* Server stub generation (server.c) uses:
* akbServerArg, akbRequest, akbReply, akbSendRcv, akbReturnSnd,
* akbReplyCopy, akbVarNeeded, akbSendBody, akbServerImplicit
*
*
* During code generation, the routine, argument, and type data structures
* are read-only. The code generation functions' output is their only
* side-effect.
*
*
* Style note:
* Code can use logical operators (|, &, ~) on akb values.
* ak values should be manipulated with the ak functions.
*/
/* various useful combinations */
#define akbNone (0)
#define akbAll (~akbNone)
#define akbAllBits (~akeBITS)
#define akbSendBits (akbSend|akbSendBody|akbSendSnd|akbSendRcv)
#define akbReturnBits (akbReturn|akbReturnBody|akbReturnSnd|akbReturnRcv)
#define akbSendReturnBits (akbSendBits|akbReturnBits)
#define akNone akeNone
#define akIn akAddFeature(akeNormal, \
akbUserArg|akbServerArg|akbRequest|akbSendBits)
#define akOut akAddFeature(akeNormal, \
akbUserArg|akbServerArg|akbReply|akbReturnBits)
#define akServerImpl akAddFeature(akeImplicit, \
akbServerArg|akbServerImplicit|akbSend|akbSendRcv)
#define akUserImpl akAddFeature(akeImplicit, \
akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv)
#define akServerSecToken akAddFeature(akeSecToken, \
akbServerArg|akbServerImplicit|akbSend|akbSendRcv)
#define akUserSecToken akAddFeature(akeSecToken, \
akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv)
#define akSecToken akAddFeature(akeSecToken, \
akbServerArg|akbServerImplicit|akbSend|akbSendRcv| \
akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv)
#define akServerAuditToken akAddFeature(akeAuditToken, \
akbServerArg|akbServerImplicit|akbSend|akbSendRcv)
#define akUserAuditToken akAddFeature(akeAuditToken, \
akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv)
#define akAuditToken akAddFeature(akeAuditToken, \
akbServerArg|akbServerImplicit|akbSend|akbSendRcv| \
akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv)
#define akServerContextToken akAddFeature(akeContextToken, \
akbServerArg|akbServerImplicit|akbSend|akbSendRcv)
#define akMsgSeqno akAddFeature(akeMsgSeqno, \
akbServerArg|akbServerImplicit|akbSend|akbSendRcv)
#define akInOut akAddFeature(akeNormal, \
akbUserArg|akbServerArg|akbRequest|akbReply| \
akbSendBits|akbReturnBits|akbReplyCopy)
#define akRequestPort akAddFeature(akeRequestPort, \
akbUserArg|akbServerArg|akbSend|akbSendSnd|akbSendRcv)
#define akWaitTime akAddFeature(akeWaitTime, akbUserArg)
#define akSendTime akAddFeature(akeSendTime, akbUserArg)
#define akMsgOption akAddFeature(akeMsgOption, akbUserArg)
#define akReplyPort akAddFeature(akeReplyPort, \
akbUserArg|akbServerArg|akbSend|akbSendSnd|akbSendRcv)
#define akUReplyPort akAddFeature(akeReplyPort, \
akbUserArg|akbSend|akbSendSnd|akbSendRcv)
#define akSReplyPort akAddFeature(akeReplyPort, \
akbServerArg|akbSend|akbSendSnd|akbSendRcv)
#define akRetCode akAddFeature(akeRetCode, akbReply|akbReturnBody)
#define akCount akAddFeature(akeCount, \
akbUserArg|akbServerArg)
#define akPoly akePoly
#define akDealloc akAddFeature(akeDealloc, akbUserArg)
#define akCountInOut akAddFeature(akeCountInOut, akbRequest|akbSendBits)
#define akCheck(ak, bits) ((ak) & (bits))
#define akCheckAll(ak, bits) (akCheck(ak, bits) == (bits))
#define akAddFeature(ak, bits) ((ak)|(bits))
#define akRemFeature(ak, bits) ((ak)&~(bits))
#define akIdent(ak) ((ak) & akeBITS)
#define argIsIn(arg) (akIdent(arg->argKind) == akeNormal && \
akCheck(arg->argKind, akbRequest))
#define argIsOut(arg) (akIdent(arg->argKind) == akeNormal && \
akCheck(arg->argKind, akbReply))
/*
* The arguments to a routine/function are linked in left-to-right order.
* argName is used for error messages and pretty-printing,
* not code generation. Code generation shouldn't make any assumptions
* about the order of arguments, esp. count and poly arguments.
* (Unfortunately, code generation for inline variable-sized arguments
* does make such assumptions.)
*
* argVarName is the name used in generated code for function arguments
* and local variable names. argMsgField is the name used in generated
* code for the field in msgs where the argument's value lives.
* argTTName is the name used in generated code for msg-type fields and
* static variables used to initialize those fields. argPadName is the
* name used in generated code for a padding field in msgs.
*
* argFlags can be used to override the deallocate bits
* in the argument's type. rtProcessArgFlags sets argDeallocate
* from it and the type. Code generation shouldn't use
* argFlags.
*
* argCount, argPoly, and argDealloc get to the implicit count, poly,
* and dealloc arguments associated with the argument; they should be
* used instead of argNext. In these implicit arguments, argParent is
* a pointer to the "real" arg.
*
* In count arguments, argMultiplier is a scaling factor applied to
* the count arg's value to get msg-type-number. It is equal to
* argParent->argType->itElement->itNumber
*
*/
typedef struct argument
{
/* if argKind == akReturn, then argName is name of the function */
identifier_t argName;
struct argument *argNext;
arg_kind_t argKind;
ipc_type_t *argType;
/* Kernel Processed Data */
mach_msg_descriptor_type_t argKPD_Type; /* KPD type: port, ool, port+ool */
void (* argKPD_Template)(FILE *file, struct argument *arg, boolean_t in); /* KPD discipline for static templates */
void (* argKPD_Init)(FILE *file, struct argument *arg); /* KPD discipline for initializing */
void (* argKPD_Pack)(FILE *file, struct argument *ar); /* KPD discipline for packing */
void (* argKPD_Extract)(FILE *file, struct argument *arg); /* KPD discipline for extracting */
void (* argKPD_TypeCheck)(FILE *file, struct argument *ar); /* KPD discipline for type checking */
string_t argVarName; /* local variable and argument names */
string_t argMsgField; /* message field's name */
string_t argTTName; /* name for msg_type fields, static vars */
string_t argPadName; /* name for pad field in msg */
string_t argSuffix; /* name extension for KPDs */
ipc_flags_t argFlags;
dealloc_t argDeallocate; /* overrides argType->itDeallocate */
boolean_t argCountInOut;
struct routine *argRoutine; /* routine we are part of */
struct argument *argCount; /* our count arg, if present */
struct argument *argSubCount; /* our sub-count arg, if present (variable subordinate arrays) */
struct argument *argCInOut; /* our CountInOut arg, if present */
struct argument *argPoly; /* our poly arg, if present */
struct argument *argDealloc; /* our dealloc arg, if present */
struct argument *argSameCount; /* the arg to take the count from, if present */
struct argument *argParent; /* in a count or poly arg, the base arg */
u_int argMultiplier; /* for Count argument: parent is a multiple
of a basic IPC type. Argument must be
multiplied by Multiplier to get IPC
number-of-elements. */
/* how variable/inline args precede this one, in request and reply */
u_int argRequestPos;
u_int argReplyPos;
/* whether argument is by reference, on user and server side */
boolean_t argByReferenceUser;
boolean_t argByReferenceServer;
boolean_t argTempOnStack; /* A temporary for the short-circuiting
* code when -maxonstack is used.
*/
} argument_t;
/*
* The various routine kinds' peculiarities are abstracted by rtCheckRoutine
* into attributes like rtOneWay, etc. These are what
* code generation should use. It is Bad Form for code generation to
* test rtKind.
*/
typedef enum
{
rkRoutine,
rkSimpleRoutine
} routine_kind_t;
typedef struct routine
{
identifier_t rtName;
routine_kind_t rtKind;
argument_t *rtArgs;
u_int rtNumber; /* used for making msg ids */
identifier_t rtUserName; /* user-visible name (UserPrefix + Name) */
identifier_t rtServerName; /* server-side name (ServerPrefix + Name) */
identifier_t rtErrorName; /* error-handler name */
boolean_t rtOneWay; /* SimpleRoutine */
boolean_t rtSimpleRequest;
boolean_t rtSimpleReply;
boolean_t rtUseSpecialReplyPort;
u_int rtConsumeOnSendError;
u_int rtNumRequestVar; /* number of variable/inline args in request */
u_int rtNumReplyVar; /* number of variable/inline args in reply */
u_int rtMaxRequestPos; /* maximum of argRequestPos */
u_int rtMaxReplyPos; /* maximum of argReplyPos */
u_int rtRequestKPDs; /* number of Kernel Processed Data entries */
u_int rtReplyKPDs; /* number of Kernel Processed Data entries */
u_int rtOverwrite; /* number of Overwrite entries */
u_int rtOverwriteKPDs; /* number of entries in the Overwrite template */
boolean_t rtNoReplyArgs; /* if so, no reply message arguments beyond
what the server dispatch routine inserts */
boolean_t rtRequestFits; /* Request fits within onstack limit */
boolean_t rtReplyFits; /* Reply fits within onstack limit */
boolean_t rtRequestUsedLimit;/* User type limit used in deciding whether
request fits within onstack limit */
boolean_t rtReplyUsedLimit; /* User type limit used in deciding whether
reply fits within onstack limit */
u_int rtRequestSizeKnown; /* Max size of known portion of request */
u_int rtReplySizeKnown; /* Max size of known portion of request */
u_int rtServerImpl; /* Implicit data requested */
u_int rtUserImpl; /* Implicit data requested */
/* distinguished arguments */
argument_t *rtRetCArg; /* the Routine has this argument tagged as RetCode */
argument_t *rtRequestPort; /* always non-NULL, defaults to first arg */
argument_t *rtReplyPort; /* always non-NULL, defaults to Mig-supplied */
argument_t *rtRetCode; /* always non-NULL */
argument_t *rtNdrCode; /* always non-NULL */
argument_t *rtWaitTime; /* if non-NULL, will use MACH_RCV_TIMEOUT */
argument_t *rtMsgOption; /* always non-NULL, defaults to NONE */
/* more info's used only when UseEventLogger is turned on */
u_int rtCountPortsIn; /* how many in-line Ports are sent */
u_int rtCountOolPortsIn; /* how many out_of-line Ports are sent */
u_int rtCountOolIn; /* how many bytes out_of-line are sent */
u_int rtCountPortsOut; /* how many in-line Ports are rcv'd */
u_int rtCountOolPortsOut; /* how many out_of-line Ports are rcv'd */
u_int rtCountOolOut; /* how many bytes out_of-line are rcv'd */
u_int rtTempBytesOnStack; /* A temporary for the short-circuiting
* code when -maxonstack is used.
*/
} routine_t;
#define rtNULL ((routine_t *) 0)
#define argNULL ((argument_t *) 0)
#define argKPD_NULL ((mach_msg_descriptor_type_t) -1)
#define rtMessOnStack(rt) ((rt)->rtRequestFits && (rt)->rtReplyFits)
/*
* These are the ways MiG organizes stub parameters
*/
#define IS_VARIABLE_SIZED_UNTYPED(x) ((x)->itVarArray && \
(x)->itInLine && \
!(x)->itPortType)
#define IS_KERN_PROC_DATA(x) (!(x)->itInLine || (x)->itPortType)
#define IS_OPTIONAL_NATIVE(x) ((x)->itNative && \
(x)->itNativePointer && \
(x)->itBadValue != NULL)
/*
* I consider the case of fixed/variable bounded arrays of ports or ool or oolport
*/
#define IS_MULTIPLE_KPD(x) ((x)->itKPD_Number > 1)
/*
* I consider the case of MiG presenting data as it is inLine, even
* if it is sent/rcvd as out-of-line
*/
#define IS_MIG_INLINE_EMUL(x) ((x)->itMigInLine)
extern u_int rtNumber;
/* rt->rtNumber will be initialized */
extern routine_t *rtAlloc(void);
/* skip a number */
extern void rtSkip(void);
extern argument_t *argAlloc(void);
extern boolean_t
rtCheckMask(argument_t *args, u_int mask);
extern boolean_t
rtCheckMaskFunction(argument_t *args, u_int mask,
boolean_t (*func)(argument_t *arg));
extern routine_t *
rtMakeRoutine(identifier_t name, argument_t *args);
extern routine_t *
rtMakeSimpleRoutine(identifier_t name, argument_t *args);
extern void rtPrintRoutine(routine_t *rt);
extern void rtCheckRoutine(routine_t *rt);
extern char *rtRoutineKindToStr(routine_kind_t rk);
extern int rtCountArgDescriptors(argument_t *args, int *argcount);
extern void rtMinRequestSize(FILE *file, routine_t *rt, char *str);
extern void rtMinReplySize(FILE *file, routine_t *rt, char *str);
#define RPCUserStruct(arg) (arg->argType->itStruct && arg->argType->itInLine)
#define RPCString(arg) (arg->argType->itString && arg->argType->itInLine)
#define RPCOutStruct(arg) (arg->argType->itStruct &&\
argIsOut(arg) && (! arg->argType->itVarArray))
#define RPCOutWord(arg) (RPCUserStruct(arg) &&\
(arg->argType->itSize <= 32) &&\
(arg->argType->itNumber == 1) && argIsOut(arg))
#define RPCPort(arg) (arg->argKPD_Type == MACH_MSG_PORT_DESCRIPTOR)
#define RPCPortArray(arg) (arg->argKPD_Type == MACH_MSG_OOL_PORTS_DESCRIPTOR)
#define RPCVariableArray(arg) ((arg->argType->itVarArray) &&\
!RPCPort(arg) && !RPCPortArray(arg))
#define RPCFixedArray(arg) (((! arg->argType->itVarArray) &&\
!RPCPort(arg) && !RPCPortArray(arg) &&\
(arg->argType->itNumber > 1) &&\
!RPCUserStruct(arg)) ||\
RPCString(arg) ||\
RPCOutWord(arg) ||\
RPCOutStruct(arg))
#endif /* _ROUTINE_H */

2772
tools/mig/server.c Normal file

File diff suppressed because it is too large Load Diff

68
tools/mig/statement.c Normal file
View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 1999-2018 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#include "error.h"
#include "alloc.h"
#include "statement.h"
statement_t *stats = stNULL;
static statement_t **last = &stats;
statement_t *
stAlloc(void)
{
statement_t *new;
new = (statement_t *) malloc(sizeof *new);
if (new == stNULL)
fatal("stAlloc(): %s", strerror(errno));
*last = new;
last = &new->stNext;
new->stNext = stNULL;
return new;
}

98
tools/mig/statement.h Normal file
View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 1999-2018 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
* Extensive revamping. Added polymorphic arguments.
* Allow multiple variable-sized inline arguments in messages.
*
* 27-May-87 Richard Draves (rpd) at Carnegie-Mellon University
* Created.
*/
#ifndef _STATEMENT_H
#define _STATEMENT_H
#include "routine.h"
typedef enum statement_kind
{
skRoutine,
skImport,
skUImport,
skSImport,
skDImport,
skIImport,
skRCSDecl
} statement_kind_t;
typedef struct statement
{
statement_kind_t stKind;
struct statement *stNext;
union
{
/* when stKind == skRoutine */
routine_t *_stRoutine;
/* when stKind == skImport, skUImport, skSImport, skDImport, skIImport */
string_t _stFileName;
} data;
} statement_t;
#define stRoutine data._stRoutine
#define stFileName data._stFileName
#define stNULL ((statement_t *) 0)
/* stNext will be initialized to put the statement in the list */
extern statement_t *stAlloc(void);
/* list of statements, in order they occur in the .defs file */
extern statement_t *stats;
#endif /* _STATEMENT_H */

93
tools/mig/strdefs.h Normal file
View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 1999, 2008 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* 91/02/05 17:55:57 mrt
* Changed to new Mach copyright
* [91/02/01 17:56:03 mrt]
*
* 90/06/02 15:05:49 rpd
* Created for new IPC.
* [90/03/26 21:13:56 rpd]
*
* 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
* Extensive revamping. Added polymorphic arguments.
* Allow multiple variable-sized inline arguments in messages.
*
* 15-Jun-87 David Black (dlb) at Carnegie-Mellon University
* Fixed strNULL to be the null string instead of the null string
* pointer.
*
* 27-May-87 Richard Draves (rpd) at Carnegie-Mellon University
* Created.
*/
#ifndef STRDEFS_H
#define STRDEFS_H
#include <string.h>
#include <mach/boolean.h>
typedef char *string_t;
typedef string_t identifier_t;
#define MAX_STR_LEN 200
#define strNULL ((string_t) 0)
extern string_t strmake( char *string );
extern string_t strconcat( string_t left, string_t right );
extern string_t strphrase( string_t left, string_t right );
extern void strfree( string_t string );
#define streql(a, b) (strcmp((a), (b)) == 0)
extern char *strbool( boolean_t bool );
extern char *strstring( string_t string );
extern char *toupperstr( char *string );
#endif /* STRDEFS_H */

132
tools/mig/string.c Normal file
View File

@@ -0,0 +1,132 @@
/*
* Copyright (c) 1999-2018 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#include <mach/boolean.h>
#include <ctype.h>
#include "error.h"
#include "alloc.h"
#include "strdefs.h"
string_t
strmake(char *string)
{
string_t saved;
saved = malloc(strlen(string) + 1);
if (saved == strNULL)
fatal("strmake('%s'): %s", string, strerror(errno));
return strcpy(saved, string);
}
string_t
strconcat(string_t left, string_t right)
{
string_t saved;
saved = malloc(strlen(left) + strlen(right) + 1);
if (saved == strNULL)
fatal("strconcat('%s', '%s'): %s", left, right, strerror(errno));
return strcat(strcpy(saved, left), right);
}
string_t
strphrase(string_t left, string_t right)
{
string_t saved;
string_t current;
size_t llen;
llen = strlen(left);
saved = malloc(llen + strlen(right) + 2);
if (saved == strNULL)
fatal("strphrase('%s', '%s'): %s", left, right, strerror(errno));
strcpy(saved, left);
current = saved + llen;
*(current++) = ' ';
strcpy(current, right);
free(left);
return(saved);
}
void
strfree(string_t string)
{
free(string);
}
char *
strbool(boolean_t bool)
{
if (bool)
return "TRUE";
else
return "FALSE";
}
char *
strstring(string_t string)
{
if (string == strNULL)
return "NULL";
else
return string;
}
char *
toupperstr(char *p)
{
char *s = p;
char c;
while ((c = *s)) {
if (islower(c))
*s = toupper(c);
s++;
}
return(p);
}

899
tools/mig/type.c Normal file
View File

@@ -0,0 +1,899 @@
/*
* Copyright (c) 1999-2018 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
#include "type.h"
#include <sys/types.h>
#include <mach/message.h>
#include <mach/std_types.h>
#include <mach/ndr.h>
#include "mig_machine.h"
#include "routine.h"
#include "error.h"
#include "alloc.h"
#include "global.h"
#include <stdio.h>
#define PortSize (sizeof (mach_port_t) * NBBY)
ipc_type_t *itRetCodeType; /* used for return codes */
ipc_type_t *itNdrCodeType; /* used for NDR format labels */
ipc_type_t *itDummyType; /* used for camelot dummy args */
ipc_type_t *itTidType; /* used for camelot tids */
ipc_type_t *itRequestPortType; /* used for default Request port arg */
ipc_type_t *itZeroReplyPortType;/* used for dummy Reply port arg */
ipc_type_t *itRealReplyPortType;/* used for default Reply port arg */
ipc_type_t *itWaitTimeType; /* used for dummy WaitTime args */
ipc_type_t *itMsgOptionType; /* used for dummy MsgOption args */
static ipc_type_t *list = itNULL;
static char *machine_integer_name;
static u_int machine_integer_size;
static u_int machine_integer_bits;
/*
* Searches for a named type. We use a simple
* self-organizing linked list.
*/
ipc_type_t *
itLookUp(identifier_t name)
{
ipc_type_t *it, **last;
for (it = *(last = &list); it != itNULL; it = *(last = &it->itNext))
if (streql(name, it->itName)) {
/* move this type to the front of the list */
*last = it->itNext;
it->itNext = list;
list = it;
return it;
}
return itNULL;
}
/*
* Enters a new name-type association into
* our self-organizing linked list.
*/
void
itInsert(identifier_t name, ipc_type_t *it)
{
it->itName = name;
it->itNext = list;
list = it;
}
static ipc_type_t *
itAlloc(void)
{
static ipc_type_t prototype =
{
strNULL, /* identifier_t itName */
0, /* ipc_type_t *itNext */
0, /* u_int itTypeSize */
0, /* u_int itPadSize */
0, /* u_int itMinTypeSize */
0, /* u_int itInName */
0, /* u_int itOutName */
0, /* u_int itSize */
1, /* u_int itNumber */
0, /* u_int itKPD_Number */
TRUE, /* boolean_t itInLine */
FALSE, /* boolean_t itMigInLine */
FALSE, /* boolean_t itPortType */
strNULL, /* string_t itInNameStr */
strNULL, /* string_t itOutNameStr */
TRUE, /* boolean_t itStruct */
FALSE, /* boolean_t itString */
FALSE, /* boolean_t itVarArray */
FALSE, /* boolean_t itNoOptArray */
FALSE, /* boolean_t itNative */
FALSE, /* boolean_t itNativePointer */
itNULL, /* ipc_type_t *itElement */
strNULL, /* identifier_t itUserType */
strNULL, /* identifier_t itServerType */
strNULL, /* identifier_t itTransType */
strNULL, /* identifier_t itUserKPDType */
strNULL, /* identifier_t itServerKPDType */
strNULL, /* identifier_t itInTrans */
strNULL, /* identifier_t itOutTrans */
strNULL, /* identifier_t itDestructor */
};
ipc_type_t *new;
new = (ipc_type_t *) malloc(sizeof *new);
if (new == itNULL)
fatal("itAlloc(): %s", strerror(errno));
*new = prototype;
return new;
}
/*
* Convert an IPC type-name into a string.
*/
static char *
itNameToString(u_int name)
{
char buffer[100];
(void) sprintf(buffer, "%u", name);
return strmake(buffer);
}
/*
* Calculate itTypeSize, itPadSize, itMinTypeSize
* Every type needs this info; it is recalculated
* when itInLine, itNumber, or itSize changes.
*/
static void
itCalculateSizeInfo(ipc_type_t *it)
{
if (!IS_KERN_PROC_DATA(it))
{
u_int bytes = (it->itNumber * it->itSize + 7) / 8;
u_int padding = machine_padding(bytes);
it->itTypeSize = bytes;
it->itPadSize = padding;
if (IS_VARIABLE_SIZED_UNTYPED(it)) {
/*
* for these arrays, the argCount is not a akbRequest|akbReply,
* therefore we need to account here for the space of the count
* (itMinTypeSize is used only in rtFindSize)
*/
it->itMinTypeSize = sizeof (mach_msg_type_number_t);
/*
* NDR encoded VarString carry the extra offset 4-bytes fields
* for MIG, it should be always 0;
*/
if (it->itString)
it->itMinTypeSize += sizeof (mach_msg_type_number_t);
}
else
it->itMinTypeSize = bytes + padding;
}
else {
/*
* 1) ports 2) OOL 3) ports OOL
* all have the same size = sizeof(mach_msg_descriptor_t)
*/
u_int bytes;
if (IS_MULTIPLE_KPD(it))
bytes = it->itKPD_Number * 12 /* sizeof(mach_msg_descriptor_t) */;
else
bytes = 12 /* sizeof(mach_msg_descriptor_t) */;
it->itTypeSize = bytes;
it->itPadSize = 0;
it->itMinTypeSize = bytes;
}
/* Unfortunately, these warning messages can't give a type name;
we haven't seen a name yet (it might stay anonymous.) */
if ((it->itTypeSize == 0) && !it->itVarArray && !it->itNative)
warn("sizeof(%s) == 0");
}
/*
* Fill in default values for some fields used in code generation:
* itInNameStr, itOutNameStr, itUserType, itServerType, itTransType
* Every argument's type should have these values filled in.
*/
static void
itCalculateNameInfo(ipc_type_t *it)
{
if (it->itInNameStr == strNULL)
it->itInNameStr = strmake(itNameToString(it->itInName));
if (it->itOutNameStr == strNULL)
it->itOutNameStr = strmake(itNameToString(it->itOutName));
if (it->itUserType == strNULL)
it->itUserType = it->itName;
if (it->itServerType == strNULL)
it->itServerType = it->itName;
#if 0
/*
* KernelServer and KernelUser interfaces get special treatment here.
* On the kernel side of the interface, ports are really internal
* port pointers (ipc_port_t), not port names (mach_port_t).
* At this point, we don't know if the argument is in or out,
* so we don't know if we should look at itInName or itOutName.
* Looking at both should be OK.
*
* This is definitely a hack, but I think it is cleaner than
* mucking with type declarations throughout the kernel .def files,
* hand-conditionalizing on KERNEL_SERVER and KERNEL_USER.
*/
if (IsKernelServer &&
streql(it->itServerType, "mach_port_t") &&
(((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) &&
(it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) ||
MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
MACH_MSG_TYPE_PORT_ANY(it->itOutName)))
it->itServerType = "ipc_port_t";
if (IsKernelUser &&
streql(it->itUserType, "mach_port_t") &&
(((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) &&
(it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) ||
MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
MACH_MSG_TYPE_PORT_ANY(it->itOutName)))
it->itUserType = "ipc_port_t";
#endif /* 0 */
if (it->itTransType == strNULL)
it->itTransType = it->itServerType;
}
/******************************************************
* Checks for non-implemented types, conflicting type
* flags and whether the long or short form of msg type
* descriptor is appropriate. Called after each type statement
* is parsed.
******************************************************/
static void
itCheckDecl(identifier_t name, ipc_type_t *it)
{
it->itName = name;
itCalculateNameInfo(it);
/* do a bit of error checking, mostly necessary because of
limitations in Mig */
if (it->itVarArray) {
if ((it->itInTrans != strNULL) || (it->itOutTrans != strNULL))
error("%s: can't translate variable-sized arrays", name);
if (it->itDestructor != strNULL)
error("%s: can't destroy variable-sized array", name);
}
}
/*
* Pretty-prints translation/destruction/type information.
*/
static void
itPrintTrans(ipc_type_t *it)
{
if (!streql(it->itName, it->itUserType))
printf("\tCUserType:\t%s\n", it->itUserType);
if (!streql(it->itName, it->itServerType))
printf("\tCServerType:\t%s\n", it->itServerType);
if (it->itInTrans != strNULL)
printf("\tInTran:\t\t%s %s(%s)\n", it->itTransType, it->itInTrans, it->itServerType);
if (it->itOutTrans != strNULL)
printf("\tOutTran:\t%s %s(%s)\n", it->itServerType, it->itOutTrans, it->itTransType);
if (it->itDestructor != strNULL)
printf("\tDestructor:\t%s(%s)\n", it->itDestructor, it->itTransType);
}
/*
* Pretty-prints type declarations.
*/
static void
itPrintDecl(identifier_t name, ipc_type_t *it)
{
printf("Type %s = ", name);
if (!it->itInLine)
printf("^ ");
if (it->itVarArray)
if (it->itNumber == 0 || it->itMigInLine)
printf("array [] of ");
else
printf("array [*:%d] of ", it->itNumber);
else if (it->itStruct && ((it->itNumber != 1) ||
(it->itInName == MACH_MSG_TYPE_STRING_C)))
printf("struct [%d] of ", it->itNumber);
else if (it->itNumber != 1)
printf("array [%d] of ", it->itNumber);
if (streql(it->itInNameStr, it->itOutNameStr))
printf("(%s,", it->itInNameStr);
else
printf("(%s|%s", it->itInNameStr, it->itOutNameStr);
printf(" %d)\n", it->itSize);
itPrintTrans(it);
printf("\n");
}
/*
* Handles named type-specs, which can occur in type
* declarations or in argument lists. For example,
* type foo = type-spec; // itInsert will get called later
* routine foo(arg : bar = type-spec); // itInsert won't get called
*/
void
itTypeDecl(identifier_t name, ipc_type_t *it)
{
itCheckDecl(name, it);
if (BeVerbose)
itPrintDecl(name, it);
}
/*
* Handles declarations like
* type new = name;
* type new = inname|outname;
*/
ipc_type_t *
itShortDecl(u_int inname, string_t instr, u_int outname, string_t outstr, u_int defsize)
{
ipc_type_t *it;
if (defsize == 0)
error("must use full IPC type decl");
it = itAlloc();
it->itInName = inname;
it->itInNameStr = instr;
it->itOutName = outname;
it->itOutNameStr = outstr;
it->itSize = defsize;
if (inname == MACH_MSG_TYPE_STRING_C)
{
it->itStruct = FALSE;
it->itString = TRUE;
}
/*
* I check only inname, because outname
* has to be a port as well (polymorphic types
* are now restricted to port rights)
*/
if (MACH_MSG_TYPE_PORT_ANY(inname) ||
inname == MACH_MSG_TYPE_POLYMORPHIC) {
it->itPortType = TRUE;
it->itKPD_Number = 1;
}
itCalculateSizeInfo(it);
return it;
}
static ipc_type_t *
itCopyType(ipc_type_t *old)
{
ipc_type_t *new = itAlloc();
*new = *old;
new->itName = strNULL;
new->itNext = itNULL;
new->itElement = old;
/* size info still valid */
return new;
}
/*
* A call to itCopyType is almost always followed with itResetType.
* The exception is itPrevDecl. Also called before adding any new
* translation/destruction/type info (see parser.y).
*
* type new = old; // new doesn't get old's info
* type new = array[*:10] of old;
* // new doesn't get old's info, but new->itElement does
* type new = array[*:10] of struct[3] of old;
* // new and new->itElement don't get old's info
*/
ipc_type_t *
itResetType(ipc_type_t *old)
{
/* reset all special translation/destruction/type info */
old->itInTrans = strNULL;
old->itOutTrans = strNULL;
old->itDestructor = strNULL;
old->itUserType = strNULL;
old->itServerType = strNULL;
old->itTransType = strNULL;
return old;
}
/*
* Handles the declaration
* type new = old;
*/
ipc_type_t *
itPrevDecl(identifier_t name)
{
ipc_type_t *old;
old = itLookUp(name);
if (old == itNULL) {
error("type '%s' not defined", name);
return itAlloc();
}
else
return itCopyType(old);
}
/*
* Handles the declarations
* type new = array[] of old; // number is oo
* type new = array[*] of old; // number is oo
* type new = array[*:number] of old;
*/
ipc_type_t *
itVarArrayDecl(u_int number, ipc_type_t *old)
{
ipc_type_t *it = itResetType(itCopyType(old));
if (!it->itInLine) {
/* already an initialized KPD */
if (it->itKPD_Number != 1 || !number)
error("IPC type decl is too complicated for Kernel Processed Data");
it->itKPD_Number *= number;
it->itNumber = 1;
it->itInLine = FALSE;
it->itStruct = FALSE;
it->itOOL_Number = number;
}
else if (it->itVarArray)
error("IPC type decl is too complicated");
else if (number) {
it->itNumber *= number;
/*
* Bounded [Scalar, Port] VarArray: in-line!
*/
it->itInLine = TRUE;
it->itStruct = FALSE;
if (it->itPortType)
it->itKPD_Number *= number;
it->itOOL_Number = number;
}
else {
it->itNumber = 0;
/*
* UnBounded [Scalar, Port] VarArray: always in-line
* interface and out-of-line mechanism!
*/
it->itMigInLine = TRUE;
it->itInLine = FALSE;
it->itStruct = TRUE;
it->itKPD_Number = 1;
it->itOOL_Number = 0;
}
it->itVarArray = TRUE;
it->itString = FALSE;
itCalculateSizeInfo(it);
return it;
}
/*
* Handles the declaration
* type new = array[number] of old;
*/
ipc_type_t *
itArrayDecl(u_int number, ipc_type_t *old)
{
ipc_type_t *it = itResetType(itCopyType(old));
if (!it->itInLine) {
/* already an initialized KPD */
if (it->itKPD_Number != 1)
error("IPC type decl is too complicated for Kernel Processed Data");
it->itKPD_Number *= number;
it->itNumber = 1;
it->itStruct = FALSE;
it->itString = FALSE;
it->itVarArray = FALSE;
}
else if (it->itVarArray)
error("IPC type decl is too complicated");
else {
it->itNumber *= number;
it->itStruct = FALSE;
it->itString = FALSE;
if (it->itPortType)
it->itKPD_Number *= number;
}
itCalculateSizeInfo(it);
return it;
}
/*
* Handles the declaration
* type new = ^ old;
*/
ipc_type_t *
itPtrDecl(ipc_type_t *it)
{
if (!it->itInLine && !it->itMigInLine)
error("IPC type decl is already defined to be Out-Of-Line");
it->itInLine = FALSE;
it->itStruct = TRUE;
it->itString = FALSE;
it->itMigInLine = FALSE;
it->itKPD_Number = 1;
itCalculateSizeInfo(it);
return it;
}
/*
* Handles the declaration
* type new = struct[number] of old;
*/
ipc_type_t *
itStructDecl(u_int number, ipc_type_t *old)
{
ipc_type_t *it = itResetType(itCopyType(old));
if (!it->itInLine || it->itVarArray)
error("IPC type decl is too complicated");
it->itNumber *= number;
it->itStruct = TRUE;
it->itString = FALSE;
itCalculateSizeInfo(it);
return it;
}
/*
* Treat 'c_string[n]' as
* 'array[n] of (MSG_TYPE_STRING_C, 8)'
*/
ipc_type_t *
itCStringDecl(int count, boolean_t varying)
{
ipc_type_t *it;
ipc_type_t *itElement;
itElement = itShortDecl(MACH_MSG_TYPE_STRING_C, "MACH_MSG_TYPE_STRING_C", MACH_MSG_TYPE_STRING_C, "MACH_MSG_TYPE_STRING_C", 8);
itCheckDecl("char", itElement);
it = itResetType(itCopyType(itElement));
it->itNumber = count;
it->itVarArray = varying;
it->itStruct = FALSE;
it->itString = TRUE;
itCalculateSizeInfo(it);
return it;
}
extern ipc_type_t *
itMakeSubCountType(int count, boolean_t varying, string_t name)
{
ipc_type_t *it;
ipc_type_t *itElement;
itElement = itShortDecl(machine_integer_size, machine_integer_name, machine_integer_size, machine_integer_name, machine_integer_bits);
itCheckDecl("mach_msg_type_number_t", itElement);
it = itResetType(itCopyType(itElement));
it->itNumber = count;
/*
* I cannot consider it as a Fixed array, otherwise MiG will try
* to follow the path for efficient copy of arrays
*/
it->itVarArray = FALSE;
it->itStruct = FALSE;
it->itString = FALSE;
it->itInLine = TRUE;
it->itName = "mach_msg_type_number_t *";
if (varying)
it->itVarArray = TRUE;
else
/* to skip the optimized copy of fixed array: in fact we need to
* reference each element and we also miss a user type for it */
it->itNoOptArray = TRUE;
itCalculateSizeInfo(it);
itCalculateNameInfo(it);
return it;
}
extern ipc_type_t *
itMakeCountType(void)
{
ipc_type_t *it = itAlloc();
it->itName = "mach_msg_type_number_t";
it->itInName = machine_integer_size;
it->itInNameStr = machine_integer_name;
it->itOutName = machine_integer_size;
it->itOutNameStr = machine_integer_name;
it->itSize = machine_integer_bits;
itCalculateSizeInfo(it);
itCalculateNameInfo(it);
return it;
}
extern ipc_type_t *
itMakePolyType(void)
{
ipc_type_t *it = itAlloc();
it->itName = "mach_msg_type_name_t";
it->itInName = machine_integer_size;
it->itInNameStr = machine_integer_name;
it->itOutName = machine_integer_size;
it->itOutNameStr = machine_integer_name;
it->itSize = machine_integer_bits;
itCalculateSizeInfo(it);
itCalculateNameInfo(it);
return it;
}
extern ipc_type_t *
itMakeDeallocType(void)
{
ipc_type_t *it = itAlloc();
it->itName = "boolean_t";
it->itInName = MACH_MSG_TYPE_BOOLEAN;
it->itInNameStr = "MACH_MSG_TYPE_BOOLEAN";
it->itOutName = MACH_MSG_TYPE_BOOLEAN;
it->itOutNameStr = "MACH_MSG_TYPE_BOOLEAN";
it->itSize = machine_integer_bits;
itCalculateSizeInfo(it);
itCalculateNameInfo(it);
return it;
}
extern ipc_type_t *
itNativeType(identifier_t id, boolean_t ptr, identifier_t badval)
{
ipc_type_t *it = itAlloc();
it->itInName = MACH_MSG_TYPE_BYTE;
it->itInNameStr = "MACH_MSG_TYPE_BYTE";
it->itOutName = MACH_MSG_TYPE_BYTE;
it->itOutNameStr = "MACH_MSG_TYPE_BYTE";
it->itInLine = TRUE;
it->itNative = TRUE;
it->itNativePointer = ptr;
it->itServerType = id;
it->itUserType = id;
it->itTransType = id;
it->itBadValue = badval;
itCalculateSizeInfo(it);
itCalculateNameInfo(it);
return it;
}
/*
* Initializes the pre-defined types.
*/
void
init_type(void)
{
u_int size;
size = NBBY * sizeof (natural_t);
if (size == 32) {
machine_integer_name = "MACH_MSG_TYPE_INTEGER_32";
machine_integer_size = MACH_MSG_TYPE_INTEGER_32;
}
else if (size == 64) {
machine_integer_name = "MACH_MSG_TYPE_INTEGER_64";
machine_integer_size = MACH_MSG_TYPE_INTEGER_64;
}
else
error("init_type unknown size %d", size);
machine_integer_bits = size;
itRetCodeType = itAlloc();
itRetCodeType->itName = "kern_return_t";
itRetCodeType->itInName = machine_integer_size;
itRetCodeType->itInNameStr = machine_integer_name;
itRetCodeType->itOutName = machine_integer_size;
itRetCodeType->itOutNameStr = machine_integer_name;
itRetCodeType->itSize = machine_integer_bits;
itCalculateSizeInfo(itRetCodeType);
itCalculateNameInfo(itRetCodeType);
itNdrCodeType = itAlloc();
itNdrCodeType->itName = "NDR_record_t";
itNdrCodeType->itInName = 0;
itNdrCodeType->itInNameStr = "NDR_record_t";
itNdrCodeType->itOutName = 0;
itNdrCodeType->itOutNameStr = "NDR_record_t";
itNdrCodeType->itSize = sizeof(NDR_record_t) * 8;
itCalculateSizeInfo(itNdrCodeType);
itCalculateNameInfo(itNdrCodeType);
itDummyType = itAlloc();
itDummyType->itName = "char *";
itDummyType->itInName = MACH_MSG_TYPE_UNSTRUCTURED;
itDummyType->itInNameStr = "MACH_MSG_TYPE_UNSTRUCTURED";
itDummyType->itOutName = MACH_MSG_TYPE_UNSTRUCTURED;
itDummyType->itOutNameStr = "MACH_MSG_TYPE_UNSTRUCTURED";
itDummyType->itSize = PortSize;
itCalculateSizeInfo(itDummyType);
itCalculateNameInfo(itDummyType);
itTidType = itAlloc();
itTidType->itName = "tid_t";
itTidType->itInName = machine_integer_size;
itTidType->itInNameStr = machine_integer_name;
itTidType->itOutName = machine_integer_size;
itTidType->itOutNameStr = machine_integer_name;
itTidType->itSize = machine_integer_bits;
itTidType->itNumber = 6;
itCalculateSizeInfo(itTidType);
itCalculateNameInfo(itTidType);
itRequestPortType = itAlloc();
itRequestPortType->itName = "mach_port_t";
itRequestPortType->itInName = MACH_MSG_TYPE_COPY_SEND;
itRequestPortType->itInNameStr = "MACH_MSG_TYPE_COPY_SEND";
itRequestPortType->itOutName = MACH_MSG_TYPE_PORT_SEND;
itRequestPortType->itOutNameStr = "MACH_MSG_TYPE_PORT_SEND";
itRequestPortType->itSize = PortSize;
itCalculateSizeInfo(itRequestPortType);
itCalculateNameInfo(itRequestPortType);
itZeroReplyPortType = itAlloc();
itZeroReplyPortType->itName = "mach_port_t";
itZeroReplyPortType->itInName = 0;
itZeroReplyPortType->itInNameStr = "0";
itZeroReplyPortType->itOutName = 0;
itZeroReplyPortType->itOutNameStr = "0";
itZeroReplyPortType->itSize = PortSize;
itCalculateSizeInfo(itZeroReplyPortType);
itCalculateNameInfo(itZeroReplyPortType);
itRealReplyPortType = itAlloc();
itRealReplyPortType->itName = "mach_port_t";
itRealReplyPortType->itInName = MACH_MSG_TYPE_MAKE_SEND_ONCE;
itRealReplyPortType->itInNameStr = "MACH_MSG_TYPE_MAKE_SEND_ONCE";
itRealReplyPortType->itOutName = MACH_MSG_TYPE_PORT_SEND_ONCE;
itRealReplyPortType->itOutNameStr = "MACH_MSG_TYPE_PORT_SEND_ONCE";
itRealReplyPortType->itSize = PortSize;
itCalculateSizeInfo(itRealReplyPortType);
itCalculateNameInfo(itRealReplyPortType);
itWaitTimeType = itMakeCountType();
itMsgOptionType = itMakeCountType();
}
/******************************************************
* Make sure return values of functions are assignable.
******************************************************/
void
itCheckReturnType(identifier_t name, ipc_type_t *it)
{
if (!it->itStruct)
error("type of %s is too complicated", name);
if ((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) ||
(it->itOutName == MACH_MSG_TYPE_POLYMORPHIC))
error("type of %s can't be polymorphic", name);
}
/******************************************************
* Called by routine.c to check that request ports are
* simple and correct ports with send rights.
******************************************************/
void
itCheckRequestPortType(identifier_t name, ipc_type_t *it)
{
/* error("Port size = %d %d name = %s\n", PortSize, it->itSize, it->itName);
error("server = %s user = %x\n",it->itServerType, it->itUserType);
*/
if (((it->itOutName != MACH_MSG_TYPE_PORT_SEND) &&
(it->itOutName != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
(it->itOutName != MACH_MSG_TYPE_POLYMORPHIC)) ||
(it->itNumber != 1) ||
(it->itSize != PortSize) ||
!it->itInLine ||
!it->itStruct ||
it->itVarArray)
error("argument %s isn't a proper request port", name);
}
/******************************************************
* Called by routine.c to check that reply ports are
* simple and correct ports with send rights.
******************************************************/
void
itCheckReplyPortType(identifier_t name, ipc_type_t *it)
{
if (((it->itOutName != MACH_MSG_TYPE_PORT_SEND) &&
(it->itOutName != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
(it->itOutName != MACH_MSG_TYPE_POLYMORPHIC) &&
(it->itOutName != 0)) ||
(it->itNumber != 1) ||
(it->itSize != PortSize) ||
!it->itInLine ||
!it->itStruct ||
it->itVarArray)
error("argument %s isn't a proper reply port", name);
}
/******************************************************
* Used by routine.c to check that WaitTime is a
* simple bit machine_integer_bits integer.
******************************************************/
void
itCheckIntType(identifier_t name, ipc_type_t *it)
{
if ((it->itInName != machine_integer_size) ||
(it->itOutName != machine_integer_size) ||
(it->itNumber != 1) ||
(it->itSize != machine_integer_bits) ||
!it->itInLine ||
!it->itStruct ||
it->itVarArray)
error("argument %s isn't a proper integer", name);
}
void
itCheckTokenType(identifier_t name, ipc_type_t *it)
{
if (it->itMigInLine || it->itNoOptArray || it->itString ||
it->itTypeSize != 8 || !it->itInLine || !it->itStruct ||
it->itVarArray || it->itPortType)
error("argument %s isn't a proper Token", name);
}

270
tools/mig/type.h Normal file
View File

@@ -0,0 +1,270 @@
/*
* Copyright (c) 1999-2018 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/* HISTORY
* 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
* Extensive revamping. Added polymorphic arguments.
* Allow multiple variable-sized inline arguments in messages.
*
* 16-Nov-87 David Golub (dbg) at Carnegie-Mellon University
* Changed itVarArrayDecl to take a 'max' parameter.
* Added itDestructor.
*
* 18-Aug-87 Mary Thompson @ Carnegie Mellon
* Added itPortType
* Added itTidType
*/
#ifndef _TYPE_H
#define _TYPE_H
#include <mach/boolean.h>
#include "strdefs.h"
#ifdef linux
#include <linux/types.h>
#else /* linux */
#include <sys/types.h>
#endif /* linux */
typedef u_int ipc_flags_t;
/*
* MIG built-in types
*/
#define MACH_MSG_TYPE_UNSTRUCTURED 0
#define MACH_MSG_TYPE_BIT 0
#define MACH_MSG_TYPE_BOOLEAN 0
#define MACH_MSG_TYPE_INTEGER_8 9
#define MACH_MSG_TYPE_INTEGER_16 1
#define MACH_MSG_TYPE_INTEGER_32 2
#define MACH_MSG_TYPE_INTEGER_64 3
#define MACH_MSG_TYPE_CHAR 8
#define MACH_MSG_TYPE_BYTE 9
#define MACH_MSG_TYPE_REAL_32 10
#define MACH_MSG_TYPE_REAL_64 11
#define MACH_MSG_TYPE_STRING 12
#define MACH_MSG_TYPE_STRING_C 12
#define flNone (0x00)
#define flPhysicalCopy (0x01) /* Physical Copy specified */
#define flOverwrite (0x02) /* Overwrite mode specified */
#define flDealloc (0x04) /* Dealloc specified */
#define flNotDealloc (0x08) /* NotDealloc specified */
#define flMaybeDealloc (0x10) /* Dealloc[] specified */
#define flSameCount (0x20) /* SamCount specified, used by co-bounded arrays */
#define flCountInOut (0x40) /* CountInOut specified */
#define flRetCode (0x80) /* RetCode specified */
#define flAuto (0x100) /* Will not be referenced by server after RPC */
#define flConst (0x200) /* Will not be modified by server during RPC */
typedef enum dealloc {
d_NO, /* do not deallocate */
d_YES, /* always deallocate */
d_MAYBE /* deallocate according to parameter */
} dealloc_t;
/* Convert dealloc_t to TRUE/FALSE */
#define strdealloc(d) (strbool(d == d_YES))
/*
* itName and itNext are internal fields (not used for code generation).
* They are only meaningful for types entered into the symbol table.
* The symbol table is a simple self-organizing linked list.
*
* The function itCheckDecl checks & fills in computed information.
* Every type actually used (pointed at by argType) is so processed.
*
* The itInName, itOutName, itSize, itNumber, fields correspond directly
* to mach_msg_type_t fields.
* For out-of-line variable sized types, itNumber is zero. For
* in-line variable sized types, itNumber is the maximum size of the
* array. itInName is the name value supplied to the kernel,
* and itOutName is the name value received from the kernel.
* When the type describes a MACH port, either or both may be
* MACH_MSG_TYPE_POLYMORPHIC, indicating a "polymorphic" name.
* For itInName, this means the user supplies the value with an argument.
* For itOutName, this means the value is returned in an argument.
*
* The itInNameStr and itOutNameStr fields contain "printing" versions
* of the itInName and itOutName values. The mapping from number->string
* is not into (eg, MACH_MSG_TYPE_UNSTRUCTURED/MACH_MSG_TYPE_BOOLEAN/
* MACH_MSG_TYPE_BIT). These fields are used for code-generation and
* pretty-printing.
*
* itTypeSize is the calculated size of the C type, in bytes.
* itPadSize is the size of any padded needed after the data field.
* itMinTypeSize is the minimum size of the data field, including padding.
* For variable-length inline data, it is zero.
*
* itUserType, itServerType, itTransType are the C types used in
* code generation. itUserType is the C type passed to the user-side stub
* and used for msg declarations in the user-side stub. itServerType
* is the C type used for msg declarations in the server-side stub.
* itTransType is the C type passed to the server function by the
* server-side stub. Normally it differs from itServerType only when
* translation functions are defined.
*
* itInTrans and itOutTrans are translation functions. itInTrans
* takes itServerType values and returns itTransType values. itOutTrans
* takes itTransType vaulues and returns itServerType values.
* itDestructor is a finalization function applied to In arguments
* after the server-side stub calls the server function. It takes
* itTransType values. Any combination of these may be defined.
*
* The following type specification syntax modifies these values:
* type new = old
* ctype: name // itUserType and itServerType
* cusertype: itUserType
* cservertype: itServerType
* intran: itTransType itInTrans(itServerType)
* outtran: itServerType itOutTrans(itTransType)
* destructor: itDestructor(itTransType);
*
* At most one of itStruct and itString should be TRUE. If both are
* false, then this is assumed to be an array type (msg data is passed
* by reference). If itStruct is TRUE, then msg data is passed by value
* and can be assigned with =. If itString is TRUE, then the msg_data
* is a null-terminated string, assigned with strncpy. The itNumber
* value is a maximum length for the string; the msg field always
* takes up this much space.
* NoOptArray has been introduced for the cases where the special
* code generated for array assignments would not work (either because
* there is not a ctype (array of automagically generated MiG variables)
* or because we need to reference the single elements of the array
* (array of variable sized ool regions).
*
* itVarArray means this is a variable-sized array. If it is inline,
* then itStruct and itString are FALSE. If it is out-of-line, then
* itStruct is TRUE (because pointers can be assigned).
*
* itMigInLine means this is an indefinite-length array. Although the
* argument was not specified as out-of-line, MIG will send it anyway
* os an out-of-line.
*
* itUserKPDType (itServerKPDType) identify the type of Kernel Processed
* Data that we must deal with: it can be either "mach_msg_port_descriptor_t"
* or "mach_msg_ool_ports_descriptor_t" or "mach_msg_ool_descriptor_t".
*
* itKPD_Number is used any time a single argument require more than
* one Kernel Processed Data entry: i.e., an in-line array of ports, an array
* of pointers (out-of-line data)
*
* itElement points to any substructure that the type may have.
* It is only used with variable-sized array types.
*/
typedef struct ipc_type
{
identifier_t itName; /* Mig's name for this type */
struct ipc_type *itNext; /* next type in symbol table */
u_int itTypeSize; /* size of the C type */
u_int itPadSize; /* amount of padding after data */
u_int itMinTypeSize; /* minimal amount of space occupied by data */
u_int itInName; /* name supplied to kernel in sent msg */
u_int itOutName; /* name in received msg */
u_int itSize;
u_int itNumber;
u_int itKPD_Number; /* number of Kernel Processed Data entries */
boolean_t itInLine;
boolean_t itMigInLine; /* MiG presents data as InLine, although it is sent OOL */
boolean_t itPortType;
string_t itInNameStr; /* string form of itInName */
string_t itOutNameStr; /* string form of itOutName */
boolean_t itStruct;
boolean_t itString;
boolean_t itVarArray;
boolean_t itNoOptArray;
boolean_t itNative; /* User specified a native (C) type. */
boolean_t itNativePointer;/* The user will pass a pointer to the */
/* native C type. */
struct ipc_type *itElement; /* may be NULL */
identifier_t itUserType;
identifier_t itServerType;
identifier_t itTransType;
identifier_t itKPDType; /* descriptors for KPD type of arguments */
identifier_t itInTrans; /* may be NULL */
identifier_t itOutTrans; /* may be NULL */
identifier_t itDestructor;/* may be NULL */
identifier_t itBadValue; /* Excluded value for PointerToIfNot. May
be NULL. */
u_int itOOL_Number;
} ipc_type_t;
enum {
ConsumeOnSendErrorNone,
ConsumeOnSendErrorTimeout,
ConsumeOnSendErrorAny,
};
#define itNULL ((ipc_type_t *) 0)
#define itWordAlign sizeof(natural_t)
extern ipc_type_t *itLookUp(identifier_t name);
extern void itInsert(identifier_t name, ipc_type_t *it);
extern void itTypeDecl(identifier_t name, ipc_type_t *it);
extern ipc_type_t *itShortDecl(u_int inname, string_t instr,
u_int outname, string_t outstr,
u_int dfault);
extern ipc_type_t *itPrevDecl(identifier_t name);
extern ipc_type_t *itResetType(ipc_type_t *it);
extern ipc_type_t *itVarArrayDecl(u_int number, ipc_type_t *it);
extern ipc_type_t *itArrayDecl(u_int number, ipc_type_t *it);
extern ipc_type_t *itPtrDecl(ipc_type_t *it);
extern ipc_type_t *itStructDecl(u_int number, ipc_type_t *it);
extern ipc_type_t *itCStringDecl(int count, boolean_t varying);
extern ipc_type_t *itNativeType(identifier_t CType, boolean_t pointer,
identifier_t NotVal);
extern ipc_type_t *itRetCodeType;
extern ipc_type_t *itNdrCodeType;
extern ipc_type_t *itDummyType;
extern ipc_type_t *itTidType;
extern ipc_type_t *itRequestPortType;
extern ipc_type_t *itZeroReplyPortType;
extern ipc_type_t *itRealReplyPortType;
extern ipc_type_t *itWaitTimeType;
extern ipc_type_t *itMsgOptionType;
extern ipc_type_t *itMakeCountType(void);
extern ipc_type_t *itMakeSubCountType(int count, boolean_t varying, string_t name);
extern ipc_type_t *itMakePolyType(void);
extern ipc_type_t *itMakeDeallocType(void);
extern void init_type(void);
extern void itCheckReturnType(identifier_t name, ipc_type_t *it);
extern void itCheckRequestPortType(identifier_t name, ipc_type_t *it);
extern void itCheckReplyPortType(identifier_t name, ipc_type_t *it);
extern void itCheckIntType(identifier_t name, ipc_type_t *it);
extern void itCheckTokenType(identifier_t name, ipc_type_t *it);
#endif /* _TYPE_H */

3224
tools/mig/user.c Normal file

File diff suppressed because it is too large Load Diff

1043
tools/mig/utils.c Normal file

File diff suppressed because it is too large Load Diff

140
tools/mig/utils.h Normal file
View File

@@ -0,0 +1,140 @@
/*
* Copyright (c) 1999-2002, 2008 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
* Extensive revamping. Added polymorphic arguments.
* Allow multiple variable-sized inline arguments in messages.
*
* 28-May-87 Richard Draves (rpd) at Carnegie-Mellon University
* Created.
*/
#ifndef _UTILS_H
#define _UTILS_H
/* definitions used by the Event Logger */
#define LOG_USER 0
#define LOG_SERVER 1
#define LOG_REQUEST 0
#define LOG_REPLY 1
/* stuff used by more than one of header.c, user.c, server.c */
extern void WriteMigExternal(FILE *file);
extern void WriteMigInternal(FILE *file);
extern void WriteImport(FILE *file, string_t filename);
extern void WriteRCSDecl( FILE *file, identifier_t name, string_t rcs );
extern void WriteBogusDefines( FILE *file );
extern void WriteList( FILE *file, argument_t *args,
void (*func)(FILE *file, argument_t *arg),
u_int mask, char *between, char *after );
extern void WriteReverseList( FILE *file, argument_t *args,
void (*func)(FILE *file, argument_t *arg),
u_int mask, char *between, char *after );
/* good as arguments to WriteList */
extern void WriteNameDecl( FILE *file, argument_t *arg );
extern void WriteUserVarDecl( FILE *file, argument_t *arg );
extern void WriteServerVarDecl( FILE *file, argument_t *arg );
extern void WriteTemplateDeclIn( FILE *file, argument_t *arg );
extern void WriteTemplateDeclOut( FILE *file, argument_t *arg );
extern void WriteCheckDecl( FILE *file, argument_t *arg );
extern char *ReturnTypeStr( routine_t *rt );
extern char *FetchUserType( ipc_type_t *it );
extern char *FetchServerType( ipc_type_t *it );
extern char *FetchKPDType( ipc_type_t *it );
extern void WriteKPDFieldDecl(FILE *file, argument_t *arg);
extern void WriteFieldDeclPrim( FILE *file, argument_t *arg, char *(*tfunc)(ipc_type_t *it) );
extern void WriteStructDecl( FILE *file, argument_t *args,
void (*func)(FILE *file, argument_t *arg),
u_int mask, char *name,
boolean_t simple, boolean_t trailer,
boolean_t isuser,
boolean_t template_only );
extern void WriteStaticDecl( FILE *file, argument_t *arg );
extern void WriteCopyType(FILE *file, ipc_type_t *it, boolean_t mig_allocated_buf, char *left, char *right, ...);
extern void WriteCopyArg(FILE *file, argument_t *arg, boolean_t mig_allocated_buf, char *left, char *right, ...);
extern void WriteLogMsg( FILE *file, routine_t *rt, int where, int what );
extern void WriteCheckTrailerHead( FILE *file, routine_t *rt, boolean_t isuser );
extern void WriteCheckTrailerSize( FILE *file, boolean_t isuser, argument_t *arg );
extern void WriteReturnMsgError( FILE *file, routine_t *rt, boolean_t isuser, argument_t *arg, string_t error );
extern void WriteRPCRoutineDescriptor( FILE *file, routine_t *rt, int arg_count, int descr_count, string_t stub_routine, string_t sig_array );
extern void WriteRPCRoutineArgDescriptor( FILE *file, routine_t *rt );
extern void WriteRequestTypes( FILE *file, statement_t *stats);
extern void WriteCheckRequests( FILE *file, statement_t *stats);
extern void WriteUserRequestUnion( FILE *file, statement_t *stats );
extern void WriteServerRequestUnion( FILE *file, statement_t *stats );
extern void WriteReplyTypes( FILE *file, statement_t *stats);
extern void WriteCheckReplies( FILE *file, statement_t *stats);
extern void WriteUserReplyUnion( FILE *file, statement_t *stats );
extern void WriteServerReplyUnion( FILE *file, statement_t *stats );
extern void WriteNDRConvertArgDecl( FILE *file, argument_t *arg, char *convert, char *dir);
#endif /* _UTILS_H */

78
tools/mig/write.h Normal file
View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 1999, 2008 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
* Extensive revamping. Added polymorphic arguments.
* Allow multiple variable-sized inline arguments in messages.
*
* 27-May-87 Richard Draves (rpd) at Carnegie-Mellon University
* Created.
*/
#ifndef _WRITE_H
#define _WRITE_H
#include <stdio.h>
#include "statement.h"
extern void WriteUserHeader( FILE *file, statement_t *stats );
extern void WriteServerHeader( FILE *file, statement_t *stats );
extern void WriteServerRoutine( FILE *file, routine_t *rt );
extern void WriteInternalHeader( FILE *file, statement_t *stats );
extern void WriteDefinesHeader( FILE *file, statement_t *stats );
extern void WriteUser( FILE *file, statement_t *stats );
extern void WriteUserIndividual( statement_t *stats );
extern void WriteServer( FILE *file, statement_t *stats );
extern void WriteIncludes( FILE *file, boolean_t isuser, boolean_t is_def );
extern void WriteImplImports( FILE *file, statement_t *stats, boolean_t isuser );
extern void WriteApplDefaults( FILE *file, char *dir );
extern void WriteApplMacro( FILE *file, char *dir, char *when, routine_t *rt );
extern void WriteBogusServerRoutineAnnotationDefine( FILE *file );
#endif /* _WRITE_H */