[Midnightbsd-cvs] src [7395] trunk/usr.bin/migcom: add migcom(1)
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sun Jan 3 12:31:37 EST 2016
Revision: 7395
http://svnweb.midnightbsd.org/src/?rev=7395
Author: laffer1
Date: 2016-01-03 12:31:36 -0500 (Sun, 03 Jan 2016)
Log Message:
-----------
add migcom(1)
Added Paths:
-----------
trunk/usr.bin/migcom/
trunk/usr.bin/migcom/Makefile
trunk/usr.bin/migcom/POWERMAC/
trunk/usr.bin/migcom/POWERMAC/machdep.mk
trunk/usr.bin/migcom/alloc.h
trunk/usr.bin/migcom/alpha/
trunk/usr.bin/migcom/alpha/mig_machine.h
trunk/usr.bin/migcom/error.c
trunk/usr.bin/migcom/error.h
trunk/usr.bin/migcom/global.c
trunk/usr.bin/migcom/global.h
trunk/usr.bin/migcom/header.c
trunk/usr.bin/migcom/hp_pa/
trunk/usr.bin/migcom/hp_pa/mig_machine.h
trunk/usr.bin/migcom/i386/
trunk/usr.bin/migcom/i386/mig_machine.h
trunk/usr.bin/migcom/include/
trunk/usr.bin/migcom/lexxer.h
trunk/usr.bin/migcom/lexxer.l
trunk/usr.bin/migcom/mig.c
trunk/usr.bin/migcom/mig.sh
trunk/usr.bin/migcom/migcom.1
trunk/usr.bin/migcom/parser.y
trunk/usr.bin/migcom/ppc/
trunk/usr.bin/migcom/ppc/mig_machine.h
trunk/usr.bin/migcom/routine.c
trunk/usr.bin/migcom/routine.h
trunk/usr.bin/migcom/server.c
trunk/usr.bin/migcom/shims/
trunk/usr.bin/migcom/shims/errno.h
trunk/usr.bin/migcom/shims/stdarg.h
trunk/usr.bin/migcom/shims/stdint.h
trunk/usr.bin/migcom/statement.c
trunk/usr.bin/migcom/statement.h
trunk/usr.bin/migcom/strdefs.h
trunk/usr.bin/migcom/string.c
trunk/usr.bin/migcom/test.c
trunk/usr.bin/migcom/type.c
trunk/usr.bin/migcom/type.h
trunk/usr.bin/migcom/user.c
trunk/usr.bin/migcom/utils.c
trunk/usr.bin/migcom/utils.h
trunk/usr.bin/migcom/write.h
Added: trunk/usr.bin/migcom/Makefile
===================================================================
--- trunk/usr.bin/migcom/Makefile (rev 0)
+++ trunk/usr.bin/migcom/Makefile 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,55 @@
+# $MidnightBSD$
+#
+# Copyright 1991-1998 by Open Software Foundation, Inc.
+# All Rights Reserved
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appears in all copies and
+# that both the copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+# IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+# NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+#
+# cmk1.1
+
+.include <bsd.own.mk>
+PROG= migcom
+SCRIPTS=mig.sh
+SRCS= ident.c error.c global.c header.c \
+ lexxer.l mig.c parser.y routine.c server.c \
+ statement.c string.c type.c user.c utils.c
+
+
+CFLAGS+= -nostdinc -I./include -I${.CURDIR} -I${.CURDIR}/shims -I./include
+CFLAGS+= -I${.CURDIR}/../../include -I${.CURDIR}/../../sys
+CFLAGS+= -I${.CURDIR} -DYY_NO_UNPUT -DYY_NO_INPUT -I${.CURDIR}/../../apsl/include
+
+
+.PATH: i386
+CFLAGS+= -I${.CURDIR}/i386
+include/x86: ${.CURDIR}/Makefile
+ mkdir -p include
+ ln -sf ${.CURDIR}/../../sys/x86/include include/x86
+
+include/machine: ${.CURDIR}/Makefile
+ mkdir -p include
+ ln -sf ${.CURDIR}/../../sys/${MACHINE_CPUARCH}/include include/machine
+
+ident.c: include/machine include/x86
+ echo "#include \"alloc.h\" " >${.TARGET}
+ echo "const char *MigGenerationDate = \""`date`"\";" >>${.TARGET}
+ echo "const char *MigMoreData = \""`whoami`"@"`hostname`"\";" >>${.TARGET}
+
+CLEANFILES+= ident.c *.o *~ *.gz cscope.* include/machine include/x86
+
+.include <bsd.prog.mk>
Property changes on: trunk/usr.bin/migcom/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/POWERMAC/machdep.mk
===================================================================
--- trunk/usr.bin/migcom/POWERMAC/machdep.mk (rev 0)
+++ trunk/usr.bin/migcom/POWERMAC/machdep.mk 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,38 @@
+#
+# Copyright 1991-1998 by Open Software Foundation, Inc.
+# All Rights Reserved
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appears in all copies and
+# that both the copyright notice and this permission notice appear in
+# supporting documentation.
+#
+# OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+# IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+# NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+#
+# cmk1.1
+
+# PowerMac work is done by cross compiling from a HP host. We must
+# use the host compiler with the target's include files when
+# generating migcom
+
+CCTYPE=host
+INCFLAGS+=-I.
+
+
+${TARGET_MACHINE}_VPATH = ${TARGET_MACHINE}
+${TARGET_MACHINE}_INCDIRS = ${TARGET_MACHINE}
+
+LOCAL_CFLAGS = -msoft-float -fno-omit-frame-pointer
+
+LEX = flex
+LIBS = -lfl
Property changes on: trunk/usr.bin/migcom/POWERMAC/machdep.mk
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/alloc.h
===================================================================
--- trunk/usr.bin/migcom/alloc.h (rev 0)
+++ trunk/usr.bin/migcom/alloc.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,78 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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:54:07 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:53:36 mrt]
+ *
+ * 90/06/02 15:04:21 rpd
+ * Created for new IPC.
+ * [90/03/26 21:09:59 rpd]
+ *
+ * 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 _ALLOC_H
+#define _ALLOC_H
+
+#include <stdlib.h>
+
+extern const char *MessFreeRoutine;
+extern const char *MessAllocRoutine;
+extern const char * GenerationDate;
+extern const char * MigGenerationDate;
+extern const char * MigMoreData;
+
+#endif /* _ALLOC_H */
Property changes on: trunk/usr.bin/migcom/alloc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/alpha/mig_machine.h
===================================================================
--- trunk/usr.bin/migcom/alpha/mig_machine.h (rev 0)
+++ trunk/usr.bin/migcom/alpha/mig_machine.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,33 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+
+#define machine_alignment(SZ,ESZ) \
+ (((((ESZ) > 4) && ((SZ) & 7)) ? \
+ (SZ) = ((SZ) + 7) & ~7 : (((ESZ == 4) && ((SZ) & 3)) ? \
+ (SZ) = ((SZ) + 3) & ~3 : 0)), (SZ) += (ESZ))
+
+#define machine_padding(BYTES) \
+ ((bytes & 3) ? (4 - (bytes & 3)) : 0)
+
+#define PACK_MESSAGES FALSE
Property changes on: trunk/usr.bin/migcom/alpha/mig_machine.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/error.c
===================================================================
--- trunk/usr.bin/migcom/error.c (rev 0)
+++ trunk/usr.bin/migcom/error.c 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,127 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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:54:11 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:53:53 mrt]
+ *
+ * 90/06/02 15:04:25 rpd
+ * Created for new IPC.
+ * [90/03/26 21:10:17 rpd]
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "global.h"
+#include "error.h"
+
+extern int lineno;
+extern const char *yyinname;
+
+static const char *program;
+int errors = 0;
+
+/*ARGSUSED*/
+/*VARARGS1*/
+void
+fatal(const 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);
+}
+
+/*ARGSUSED*/
+/*VARARGS1*/
+void
+warn(const char *format, ...)
+{
+ va_list pvar;
+ va_start(pvar, format);
+ if (!BeQuiet && (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(const 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);
+ errors++;
+}
+
+void
+set_program_name(const char *name)
+{
+ program = name;
+}
Property changes on: trunk/usr.bin/migcom/error.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/error.h
===================================================================
--- trunk/usr.bin/migcom/error.h (rev 0)
+++ trunk/usr.bin/migcom/error.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,87 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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.
+ */
+/*
+ * 92/03/03 16:24:58 jeffreyh
+ * Changes from TRUNK
+ * [92/02/26 12:31:12 jeffreyh]
+ *
+ * 92/01/14 16:46:17 rpd
+ * Removed <mach_error.h>.
+ * [92/01/06 rpd]
+ *
+ * 91/02/05 17:54:14 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:54:00 mrt]
+ *
+ * 90/06/02 15:04:33 rpd
+ * Created for new IPC.
+ * [90/03/26 21:10:30 rpd]
+ *
+ * 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 _ERROR_H
+#define _ERROR_H
+
+#include <sys/errno.h>
+extern int lineno;
+extern void fatal(const char *format, ...);
+extern void warn(const char *format, ...);
+extern void error(const char *format, ...);
+
+extern int errors;
+extern void set_program_name(const char *name);
+
+#endif /* _ERROR_H */
Property changes on: trunk/usr.bin/migcom/error.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/global.c
===================================================================
--- trunk/usr.bin/migcom/global.c (rev 0)
+++ trunk/usr.bin/migcom/global.c 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,209 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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/08/28 11:16:53 jsb
+ * Replaced ServerProcName with ServerDemux.
+ * [91/08/13 rpd]
+ *
+ * Removed Camelot and TrapRoutine support.
+ * Changed MsgKind to MsgSeqno.
+ * [91/08/12 rpd]
+ *
+ * 91/06/26 14:39:24 rpd
+ * Removed InitRoutineName.
+ * [91/06/26 rpd]
+ *
+ * 91/06/25 10:30:59 rpd
+ * Added ServerHeaderFileName.
+ * [91/05/22 rpd]
+ *
+ * 91/02/05 17:54:23 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:54:07 mrt]
+ *
+ * 90/06/19 23:00:47 rpd
+ * Added UserFilePrefix.
+ * [90/06/03 rpd]
+ *
+ * 90/06/02 15:04:38 rpd
+ * Created for new IPC.
+ * [90/03/26 21:10:43 rpd]
+ *
+ * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
+ * Extensive revamping. Added polymorphic arguments.
+ * Allow multiple variable-sized inline arguments in messages.
+ *
+ * 8-Feb-89 David Golub (dbg) at Carnegie-Mellon University
+ * Use default values for output file names only if they have not
+ * yet been set.
+ *
+ * 17-Sep-87 Bennet Yee (bsy) at Carnegie-Mellon University
+ * Added GenSymTab
+ *
+ * 25-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Changed CamelotPrefix to op_
+ *
+ * 12-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Initialized CamelotPrefix
+ *
+ * 10-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Changed UseRPC to TRUE
+ *
+ * 3-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Removed reference to UseThreads.
+ *
+ * 16-Jul-87 Robert Sansom (rds) at Carnegie Mellon University
+ * Added MsgType.
+ *
+ * 28-May-87 Richard Draves (rpd) at Carnegie-Mellon University
+ * Created.
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mach/message.h>
+#include "strdefs.h"
+#include "global.h"
+#include "error.h"
+#include "mig_machine.h"
+
+
+
+boolean_t BeQuiet = FALSE;
+boolean_t BeVerbose = FALSE;
+boolean_t UseMsgRPC = TRUE;
+boolean_t GenSymTab = FALSE;
+boolean_t UseEventLogger = 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;
+
+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(void)
+{
+ 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(void)
+{
+ 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");
+ }
+}
Property changes on: trunk/usr.bin/migcom/global.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/global.h
===================================================================
--- trunk/usr.bin/migcom/global.h (rev 0)
+++ trunk/usr.bin/migcom/global.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,159 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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/08/28 11:16:56 jsb
+ * Replaced ServerProcName with ServerDemux.
+ * [91/08/13 rpd]
+ *
+ * Removed Camelot and TrapRoutine support.
+ * Changed MsgKind to MsgSeqno.
+ * [91/08/12 rpd]
+ *
+ * 91/06/26 14:39:32 rpd
+ * Removed InitRoutineName.
+ * [91/06/26 rpd]
+ *
+ * 91/06/25 10:31:12 rpd
+ * Added ServerHeaderFileName.
+ * [91/05/22 rpd]
+ *
+ * 91/02/05 17:54:29 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:54:12 mrt]
+ *
+ * 90/06/19 23:00:54 rpd
+ * Added UserFilePrefix.
+ * [90/06/03 rpd]
+ *
+ * 90/06/02 15:04:42 rpd
+ * Created for new IPC.
+ * [90/03/26 21:10:53 rpd]
+ *
+ * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
+ * Extensive revamping. Added polymorphic arguments.
+ * Allow multiple variable-sized inline arguments in messages.
+ *
+ * 17-Sep-87 Bennet Yee (bsy) at Carnegie-Mellon University
+ * Added GenSymTab
+ *
+ * 16-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Added CamelotPrefix
+ *
+ * 28-May-87 Richard Draves (rpd) at Carnegie-Mellon University
+ * Created.
+ */
+
+#ifndef _GLOBAL_H
+#define _GLOBAL_H
+
+#include "type.h"
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+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 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 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 string_t GenerationDate;
+
+extern void more_global(void);
+
+extern char NewCDecl[];
+extern char LintLib[];
+
+#endif /* _GLOBAL_H */
Property changes on: trunk/usr.bin/migcom/global.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/header.c
===================================================================
--- trunk/usr.bin/migcom/header.c (rev 0)
+++ trunk/usr.bin/migcom/header.c 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,600 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014, Matthew Macy <kmacy at FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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/08/28 11:16:58 jsb
+ * Removed TrapRoutine support.
+ * [91/08/12 rpd]
+ *
+ * 91/06/26 14:39:37 rpd
+ * Removed the user initialization function and InitRoutineName.
+ * Fixed to use different symbolic constants to protect
+ * the user and server header files against multiple inclusion.
+ * [91/06/26 rpd]
+ *
+ * 91/06/25 10:31:21 rpd
+ * Restored prototype generation.
+ * Changed WriteHeader to WriteUserHeader.
+ * Added WriteServerHeader.
+ * [91/05/23 rpd]
+ *
+ * 91/02/05 17:54:33 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:54:19 mrt]
+ *
+ * 90/12/20 17:04:47 jeffreyh
+ * Commented out code for prototype generation. This is a temporary solution
+ * to the longer term problem of the need
+ * for the generation of both a client and a server header file
+ * that have correct prototypes for strict ansi c and c++. The
+ * prototypes generated before anly were for the client and broke kernel
+ * files that included them if compiled under standard gcc
+ * [90/12/07 jeffreyh]
+ *
+ * 90/06/02 15:04:46 rpd
+ * Created for new IPC.
+ * [90/03/26 21:11:06 rpd]
+ *
+ * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
+ * Extensive revamping. Added polymorphic arguments.
+ * Allow multiple variable-sized inline arguments in messages.
+ *
+ * 8-Jul-88 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Conditionally defined mig_external to be extern and then defined
+ * all functions with the storage class mig_external.
+ * Mig_external can be changed
+ * when the generated code is compiled.
+ *
+ * 18-Jan-88 David Detlefs (dld) at Carnegie-Mellon University
+ * Modified to produce C++ compatible code via #ifdefs.
+ * All changes have to do with argument declarations.
+ *
+ * 3-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Revision to make multi-threaded use work. Removed definitions for
+ * alloc_reply_port and init_msg_type as these routines are
+ * no longer generated.
+ *
+ * 30-Jul-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Made changes to generate conditional code for C++ parameter lists
+ *
+ * 29-Jul-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Changed WriteRoutine to produce conditional argument
+ * lists for C++
+ *
+ * 8-Jun-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Changed the KERNEL include from ../h to sys/
+ * Removed extern from WriteHeader to make hi-c happy
+ *
+ * 28-May-87 Richard Draves (rpd) at Carnegie-Mellon University
+ * Created.
+ */
+
+#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 <machine/mach/kern_return.h>\n");
+ if (!isuser)
+ fprintf(file, "#include <mach/mig_errors.h>\n");
+ }
+ else {
+ fprintf(file, "#include <sys/cdefs.h>\n");
+ fprintf(file, "#include <sys/types.h>\n");
+ fprintf(file, "#ifdef _KERNEL\n");
+ fprintf(file, "#include <sys/mach/ndr.h>\n");
+ fprintf(file, "#include <sys/mach/kern_return.h>\n");
+ fprintf(file, "#include <sys/mach/notify.h>\n");
+ fprintf(file, "#include <sys/mach/mach_types.h>\n");
+ fprintf(file, "#include <sys/mach/message.h>\n");
+ fprintf(file, "#include <sys/mach/mig_errors.h>\n");
+ fprintf(file, "#else /* !_KERNEL */\n");
+ 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, "#endif /*_KERNEL */\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)
+{
+ register statement_t *stat;
+ int fnum;
+ const 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 = defs_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, const 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, const char *protect, boolean_t isuser)
+{
+ const 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);
+ 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);
+ }
+ fprintf(file, "#endif\t/* %s */\n", LintLib);
+}
+
+void
+WriteUserRequestUnion(FILE *file, statement_t *stats)
+{
+ register 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) {
+ register 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)
+{
+ register 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) {
+ register 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)
+{
+ register statement_t *stat;
+ const 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#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);
+ fprintf(file, "%s %s\n", ReturnTypeStr(rt), rt->rtServerName);
+ 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\n");
+ 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);
+ }
+ fprintf(file, "#endif\t/* %s */\n", LintLib);
+}
+
+static void
+WriteDispatcher(FILE *file)
+{
+ register statement_t *stat;
+ int descr_count = 0;
+
+ for (stat = defs_stats; stat != stNULL; stat = stat->stNext)
+ if (stat->stKind == skRoutine)
+ {
+ register 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
+WriteServerHeader(FILE *file, statement_t *stats)
+{
+ register statement_t *stat;
+ const 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");
+ for (stat = stats; stat != stNULL; stat = stat->stNext) {
+ if (stat->stKind == skRoutine)
+ WriteServerRoutine(file, stat->stRoutine);
+ }
+
+ 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, register routine_t *rt)
+{
+ fprintf(file, "#define %s %s_external\n",
+ rt->rtUserName, rt->rtUserName);
+}
+
+void
+WriteInternalHeader(FILE *file, statement_t *stats)
+{
+ register 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)
+{
+ register statement_t *stat;
+ const 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);
+}
Property changes on: trunk/usr.bin/migcom/header.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/hp_pa/mig_machine.h
===================================================================
--- trunk/usr.bin/migcom/hp_pa/mig_machine.h (rev 0)
+++ trunk/usr.bin/migcom/hp_pa/mig_machine.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,35 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+
+#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
Property changes on: trunk/usr.bin/migcom/hp_pa/mig_machine.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/i386/mig_machine.h
===================================================================
--- trunk/usr.bin/migcom/i386/mig_machine.h (rev 0)
+++ trunk/usr.bin/migcom/i386/mig_machine.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,35 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+
+#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
Property changes on: trunk/usr.bin/migcom/i386/mig_machine.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/lexxer.h
===================================================================
--- trunk/usr.bin/migcom/lexxer.h (rev 0)
+++ trunk/usr.bin/migcom/lexxer.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,70 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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:54:38 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:54:28 mrt]
+ *
+ * 90/06/02 15:04:50 rpd
+ * Created for new IPC.
+ * [90/03/26 21:11:15 rpd]
+ *
+ * 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.
+ */
+
+extern void LookFileName(void);
+extern void LookString(void);
+extern void LookQString(void);
+extern void LookNormal(void);
Property changes on: trunk/usr.bin/migcom/lexxer.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/lexxer.l
===================================================================
--- trunk/usr.bin/migcom/lexxer.l (rev 0)
+++ trunk/usr.bin/migcom/lexxer.l 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,353 @@
+/* $MidnightBSD$ */
+%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})
+
+%{
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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.
+ */
+/*
+ * 92/03/03 16:25:00 jeffreyh
+ * Changes from TRUNK
+ * [92/02/26 12:31:19 jeffreyh]
+ *
+ * 92/01/23 15:21:24 rpd
+ * Fixed macros for STDC.
+ * [92/01/16 rpd]
+ *
+ * 92/01/03 20:29:25 dbg
+ * Add 'CountInOut' flag.
+ * [91/11/11 dbg]
+ *
+ * 91/08/28 11:17:01 jsb
+ * Added syServerDemux.
+ * [91/08/13 rpd]
+ *
+ * Removed syMsgKind, syCamelot, syCamelotRoutine, syTrapRoutine,
+ * syTrapSimpleRoutine. Added syMsgSeqno.
+ * [91/08/11 rpd]
+ *
+ * 91/07/31 18:09:31 dbg
+ * Add 'serverCopy' keyword.
+ * [91/06/05 dbg]
+ *
+ * Add 'c_string' keyword.
+ * [91/04/03 dbg]
+ *
+ * 91/02/05 17:54:51 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:54:35 mrt]
+ *
+ * 90/06/02 15:04:54 rpd
+ * Created for new IPC.
+ * [90/03/26 21:11:34 rpd]
+ *
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <mach/message.h>
+#include <mach/std_types.h>
+#include "strdefs.h"
+#include "type.h"
+#include "error.h"
+#include "statement.h"
+#include "global.h"
+#include "parser.h"
+#include "lexxer.h"
+#include "mig_machine.h"
+
+
+#undef yywrap
+#define yywrap() 1
+#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); \
+}
+
+static int oldYYBegin = 0;
+
+int lineno = 0; /* Replaces lex yylineno */
+
+static void doSharp(); /* process body of # directives */
+extern void yyerror(const char *);
+%}
+
+%option noyywrap
+
+%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>[Mm][Ss][Gg][Ss][Ee][Qq][Nn][Oo] RETURN(syMsgSeqno);
+<Normal>[Ww][Aa][Ii][Tt][Tt][Ii][Mm][Ee] RETURN(syWaitTime);
+<Normal>[Nn][Oo][Ww][Aa][Ii][Tt][Tt][Ii][Mm][Ee] RETURN(syNoWaitTime);
+<Normal>[Ss][Ee][Nn][Dd][Tt][Ii][Mm][Ee] RETURN(sySendTime);
+<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; }
+^\# { yyerror("illegal # directive");
+ BEGIN SkipToEOL; }
+^\#pragma { BEGIN SkipToEOL; }
+<SkipToEOL>\n { RESTORE; lineno++; }
+<SkipToEOL>. ;
+
+[ \t] ;
+\n lineno++;
+. { SAVE(Normal); RETURN(syError); }
+
+%%
+
+extern void
+LookNormal(void)
+{
+ SAVE(Normal);
+}
+
+extern void
+LookString(void)
+{
+ SAVE(String);
+}
+
+extern void
+LookQString()
+{
+ SAVE(QString);
+}
+
+extern void
+LookFileName()
+{
+ SAVE(FileName);
+}
+
+static void
+doSharp(body)
+ char *body;
+{
+ register char *startName, *endName;
+
+ lineno = atoi(body);
+ startName = strchr(body, '"');
+ if (startName != NULL)
+ {
+ endName = strrchr(body, '"');
+ *endName = '\0';
+ strfree(__DECONST(char *,yyinname));
+ yyinname = strmake(startName+1);
+ }
+}
+
Added: trunk/usr.bin/migcom/mig.c
===================================================================
--- trunk/usr.bin/migcom/mig.c (rev 0)
+++ trunk/usr.bin/migcom/mig.c 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,463 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014, Matthew Macy <kmacy at FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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/08/28 11:17:04 jsb
+ * Removed TrapRoutine support.
+ * [91/08/12 rpd]
+ *
+ * 91/06/25 10:31:32 rpd
+ * Added ServerHeaderFileName and -sheader.
+ * [91/05/22 rpd]
+ *
+ * 91/02/05 17:55:02 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:54:42 mrt]
+ *
+ * 90/06/19 23:01:01 rpd
+ * Added prefix argument to -i option.
+ * Replaced GenIndividualUser with UserFilePrefix.
+ * [90/06/03 rpd]
+ *
+ * 90/06/02 15:04:59 rpd
+ * Created for new IPC.
+ * [90/03/26 21:11:47 rpd]
+ *
+ * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
+ * Extensive revamping. Added polymorphic arguments.
+ * Allow multiple variable-sized inline arguments in messages.
+ *
+ * 8-Feb-89 David Golub (dbg) at Carnegie-Mellon University
+ * Added -user, -server, and -header switches to name output files.
+ * Added -i switch to write individual files for user routines.
+ *
+ * 17-Aug-87 Bennet Yee (bsy) at Carnegie-Mellon University
+ * Added -s,-S switches for generating a SymTab
+ *
+ * 3-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Removed -t,-T switch as code is now the same for
+ * multi and single threaded use.
+ *
+ * 28-May-87 Richard Draves (rpd) at Carnegie-Mellon University
+ * Created.
+ */
+
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include "error.h"
+#include "lexxer.h"
+#include "global.h"
+#include "write.h"
+
+extern int yyparse();
+static FILE *myfopen();
+
+static void
+parseArgs(int argc,char *argv[])
+{
+ 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':
+ 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 = TRUE;
+ break;
+ case 'X':
+ ShortCircuit = FALSE;
+ break;
+ default:
+ fatal("unknown flag: '%s'", argv[0]);
+ /*NOTREACHED*/
+ }
+ }
+ else
+ fatal("bad argument: '%s'", *argv);
+}
+
+static FILE *uheader, *server, *user;
+
+int
+main(int argc, char *argv[])
+{
+ FILE *iheader, *sheader, *dheader;
+ time_t loc;
+ extern time_t time();
+ extern string_t ctime();
+ extern string_t GenerationDate;
+
+ set_program_name("mig");
+ parseArgs(argc, argv);
+ init_global();
+ init_type();
+ loc = time((time_t *)0);
+
+ GenerationDate = ctime(&loc);
+
+ LookNormal();
+ (void) yyparse();
+
+ if (errors > 0)
+ fatal("%d errors found. Abort.\n", 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, defs_stats);
+ fclose(uheader);
+ if (ServerHeaderFileName)
+ {
+ if (BeVerbose)
+ {
+ printf ("done.\nWriting %s ...", ServerHeaderFileName);
+ fflush (stdout);
+ }
+ WriteServerHeader(sheader, defs_stats);
+ fclose(sheader);
+ }
+ if (IsKernelServer)
+ {
+ if (BeVerbose)
+ {
+ printf("done.\nWriting %s ... ", InternalHeaderFileName);
+ fflush(stdout);
+ }
+ WriteInternalHeader(iheader, defs_stats);
+ fclose(iheader);
+ }
+ if (DefinesHeaderFileName)
+ {
+ if (BeVerbose)
+ {
+ printf ("done.\nWriting %s ...", DefinesHeaderFileName);
+ fflush (stdout);
+ }
+ WriteDefinesHeader(dheader, defs_stats);
+ fclose(dheader);
+ }
+ if (UserFilePrefix)
+ {
+ if (BeVerbose)
+ {
+ printf("done.\nWriting individual user files ... ");
+ fflush(stdout);
+ }
+ WriteUserIndividual(defs_stats);
+ }
+ else
+ {
+ if (BeVerbose)
+ {
+ printf("done.\nWriting %s ... ", UserFileName);
+ fflush(stdout);
+ }
+ WriteUser(user, defs_stats);
+ fclose(user);
+ }
+ if (BeVerbose)
+ {
+ printf("done.\nWriting %s ... ", ServerFileName);
+ fflush(stdout);
+ }
+ WriteServer(server, defs_stats);
+ fclose(server);
+ if (BeVerbose)
+ printf("done.\n");
+
+ return (0);
+}
+
+static FILE *
+myfopen(char *name, 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;
+}
Property changes on: trunk/usr.bin/migcom/mig.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/mig.sh
===================================================================
--- trunk/usr.bin/migcom/mig.sh (rev 0)
+++ trunk/usr.bin/migcom/mig.sh 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,88 @@
+#!/bin/sh
+# Front-end to migcom.
+# Since migcom only deals with stdin, we need to
+# run things through the pre-processor.
+#
+# This is based on the Mac OS man page for mig.
+# Which is annoying, because the options aren't
+# parsable using getopts
+PROG="$0"
+
+QUIET="-Q" # -q or -Q
+VERBOSE="" # -v or -V
+EVLOG="-l" # -l or -L
+ANSI="-k" # -k or -K
+SERVSYM="-S" # -S or -s
+USERPREFIX="" # -i <prefix>
+USERRPC="" # -user <path>
+SRVRPC="" # -server <path>
+USRHDR="" # -header <path>
+SYSHDR="" # -sheader <path>
+IHDR="" # -iheader <path>
+GHDR="" # -dheader <path>
+STACKMAX="" # -maxonstack <value>
+SPLIT="" # -split
+ARCH="" # -arch <arch>, ignored
+MD="" # -MD, passed to cc
+CPP="" # -cpp <path>, ignored
+CC="/usr/bin/cc" # -cc <path>
+MIGCOM="/usr/bin/migcom" # -migcom <path>
+# This is a hack, and I'm not entirely sure it's
+# valid.
+SYSROOT=$(expr $(dirname $0) : "\(.*\)/usr/bin") || SYSROOT=""
+
+while [ $# -gt 1 ]
+do
+ case "$1" in
+ -q) QUIET="-q" ; shift ;;
+ -Q) QUIET="-Q" ; shift ;;
+ -l) EVLOG="-l" ; shift ;;
+ -L) EVLOG="-L" ; shift ;;
+ -k) ANSI="-k" ; shift ;;
+ -K) ANSI="-K" ; shift ;;
+ -s) SERVSYM="-s" ; shift ;;
+ -S) SERVSYM="-S" ; shift ;;
+ -V) VERBOSE="-V" ; shift ;;
+ -v) VERBOSE="-v" ; shift ;;
+ -split) SPLIT="-split" ; shift ;;
+ -MD) MD="-MD" ; shift ;;
+ -i) if [ $# -le 2 ] ; then usage ; fi ; USERPREFIX="-i $2" ; shift 2 ;;
+ -user) if [ $# -le 2 ] ; then usage ; fi ; USERRPC="-user $2" ; shift 2 ;;
+ -server) if [ $# -le 2 ]; then usage ; fi ; SRVRPC="-server $2" ; shift 2 ;;
+ -header) if [ $# -le 2 ]; then usage ; fi ; USRHDR="-header $2" ; shift 2 ;;
+ -sheader) if [ $# -le 2 ]; then usage ; fi ; SYSHDR="-sheader $2" ; shift 2 ;;
+ -iheader) if [ $# -le 2 ]; then usage ; fi ; IHDR="-iheader $2" ; shift 2 ;;
+ -dheader) if [ $# -le 2 ]; then usage ; fi ; GHDR="-dheader $2" ; shift 2 ;;
+ -maxonstack) if [ $# -le 2 ]; then usage ; fi ; STACKMAX="-maxonstack $2" ; shift 2 ;;
+ -cpp) if [ $# -le 2 ]; then usage ; fi ; shift 2 ;;
+ -cc) if [ $# -le 2 ]; then usage ; fi ; CC="$2" ; shift 2 ;;
+ -migcom) if [ $# -le 2 ]; then usage ; fi ; MIGCOM="$2" ; shift 2 ;;
+ -isysroot) if [ $# -le 2 ]; then usage ; fi ; SYSROOT="$2" ; shift 2 ;;
+ -*) CFLAGS="${CFLAGS} $1" ; shift ;;
+ esac
+done
+
+CC="${CC}"
+MIGCOM="${SYSROOT}${MIGCOM}"
+
+if [ $# -ne 1 ]; then
+ usage
+fi
+
+input_file="$1"
+
+tmpfile=${TMPDIR:-/tmp}/migcom-$$.c
+
+( echo "#line 1 \"${input_file}\"" ; cat ${input_file} ) > ${tmpfile}
+if ! ${CC} ${MD} ${CFLAGS} -E ${tmpfile} |
+ ${MIGCOM} ${QUIET} ${EVLOG} ${ANSI} ${SERVSYM} \
+ ${SPLIT} ${USERPREFIX} ${VERBOSE} \
+ ${USERRPC} ${SRVRPC} \
+ ${USRHDR} ${SYSHDR} \
+ ${IHDR} ${GHDR} \
+ ${STACKMAX}
+then
+ rm -f ${tmpfile}
+ exit 1
+fi
+exit 0
Property changes on: trunk/usr.bin/migcom/mig.sh
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/migcom.1
===================================================================
--- trunk/usr.bin/migcom/migcom.1 (rev 0)
+++ trunk/usr.bin/migcom/migcom.1 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,91 @@
+.TH MIG 1
+.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.
+.SH NOTES
+This man page is courtesy of Apple Computer, Inc. migcom(1) is from the
+original osfmk sources.
Property changes on: trunk/usr.bin/migcom/migcom.1
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/parser.y
===================================================================
--- trunk/usr.bin/migcom/parser.y (rev 0)
+++ trunk/usr.bin/migcom/parser.y 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,833 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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/08/28 11:17:06 jsb
+ * Added ServerDemux.
+ * [91/08/13 rpd]
+ *
+ * Removed Camelot, TrapRoutine support.
+ * Removed obsolete translation and destructor specs.
+ * Replaced MsgKind with MsgSeqno.
+ * [91/08/12 rpd]
+ *
+ * 91/07/31 18:10:00 dbg
+ * Allow 'dealloc[]' to mean user-specified deallocate flag.
+ *
+ * Added c_string.
+ * [91/04/03 dbg]
+ *
+ * 91/02/05 17:55:12 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:54:54 mrt]
+ *
+ * 90/06/02 15:05:11 rpd
+ * Created for new IPC.
+ * [90/03/26 21:12:20 rpd]
+ *
+ * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
+ * Extensive revamping. Added polymorphic arguments.
+ * Allow multiple variable-sized inline arguments in messages.
+ *
+ * 17-Feb-87 Mary Thompson (mrt) at Carnegie Mellon
+ * Simplied syntax for translation and destructor functions.
+ * Also allowed any combination of these functions.
+ *
+ * 16-Nov-87 David Golub (dbg) at Carnegie-Mellon University
+ * Added maximum-size notation for arrays. Added destructor
+ * for server-side.
+ *
+ * 27-May-87 Richard Draves (rpd) at Carnegie-Mellon University
+ * Created.
+ */
+
+%token sySkip
+%token syRoutine
+%token sySimpleRoutine
+
+%token sySubsystem
+%token syKernelUser
+%token syKernelServer
+
+%token syMsgOption
+%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 const char *import_name(statement_kind_t);
+int yylex(void);
+extern int yydebug;
+extern int yynerrs;
+extern int yyerrflag;
+extern int yychar;
+union migyys;
+extern union migyys yyval;
+extern union migyys yylval;
+%}
+
+%union migyys
+{
+ 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
+ | UserTypeLimit sySemi
+ | OnStackLimit sySemi
+ | Error sySemi
+ | ServerPrefix sySemi
+ | UserPrefix sySemi
+ | ServerDemux sySemi
+ | TypeDecl sySemi
+ | RoutineDecl sySemi
+{
+ register 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(__DECONST(char *, 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);
+ }
+}
+ ;
+
+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
+{
+ register 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
+{
+ register 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 anylonger\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(const char *s);
+
+void
+yyerror(const char *s)
+{
+ error(s);
+}
+
+static const 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;
+ }
+}
Added: trunk/usr.bin/migcom/ppc/mig_machine.h
===================================================================
--- trunk/usr.bin/migcom/ppc/mig_machine.h (rev 0)
+++ trunk/usr.bin/migcom/ppc/mig_machine.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,37 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+
+#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
+
+#ifndef PACK_MESSAGES
+#define PACK_MESSAGES TRUE
+#endif
Property changes on: trunk/usr.bin/migcom/ppc/mig_machine.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/routine.c
===================================================================
--- trunk/usr.bin/migcom/routine.c (rev 0)
+++ trunk/usr.bin/migcom/routine.c 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,1861 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014, Matthew Macy <kmacy at FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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.
+ */
+
+/*
+ * ABSTRACT:
+ * Provides the routine used by parser.c to generate
+ * routine structures for each routine statement.
+ * The parser generates a threaded list of statements
+ * of which the most interesting are the various kinds
+ * routine statments. The routine structure is defined
+ * in routine.h which includes it name, kind of routine
+ * and other information,
+ * a pointer to an argument list which contains the name
+ * and type information for each argument, and a list
+ * of distinguished arguments, eg. Request and Reply
+ * ports, waittime, retcode etc.
+ */
+#include <stdio.h>
+
+#include "type.h"
+#include <mach/message.h>
+#include <mach/kern_return.h>
+#include "mig_machine.h"
+#include "error.h"
+#include "alloc.h"
+#include "global.h"
+#include "routine.h"
+#include "write.h"
+#include "utils.h"
+
+u_int rtNumber = 0;
+
+static void rtSizeDelta();
+
+routine_t *
+rtAlloc(void)
+{
+ register routine_t *new;
+
+ new = (routine_t *) calloc(1, sizeof *new);
+ if (new == rtNULL)
+ fatal("rtAlloc(): %s", strerror(errno));
+ new->rtNumber = rtNumber++;
+ new->rtName = strNULL;
+ new->rtErrorName = strNULL;
+ new->rtUserName = strNULL;
+ new->rtServerName = strNULL;
+
+ return new;
+}
+
+void
+rtSkip(void)
+{
+ rtNumber++;
+}
+
+argument_t *
+argAlloc(void)
+{
+ static argument_t prototype =
+ {
+ strNULL, /* identifier_t argName */
+ argNULL, /* argument_t *argNext */
+ akNone, /* arg_kind_t argKind */
+ itNULL, /* ipc_type_t *argType */
+ argKPD_NULL, /* mach_msg_descriptor_type_t argKPD_Type */
+ KPD_error, /* KPD discipline for templates */
+ KPD_error, /* KPD discipline for initializing */
+ KPD_error, /* KPD discipline for packing */
+ KPD_error, /* KPD discipline for extracting */
+ KPD_error, /* KPD discipline for type checking */
+ strNULL, /* string_t argVarName */
+ strNULL, /* string_t argMsgField */
+ strNULL, /* string_t argTTName */
+ strNULL, /* string_t argPadName */
+ strNULL, /* string_t argSuffix */
+ flNone, /* ipc_flags_t argFlags */
+ d_NO, /* dealloc_t argDeallocate */
+ FALSE, /* boolean_t argCountInOut */
+ rtNULL, /* routine_t *argRoutine */
+ argNULL, /* argument_t *argCount */
+ argNULL, /* argument_t *argSubCount */
+ argNULL, /* argument_t *argCInOut */
+ argNULL, /* argument_t *argPoly */
+ argNULL, /* argument_t *argDealloc */
+ argNULL, /* argument_t *argSameCount */
+ argNULL, /* argument_t *argParent */
+ 1, /* int argMultiplier */
+ 0, /* int argRequestPos */
+ 0, /* int argReplyPos */
+ FALSE, /* boolean_t argByReferenceUser */
+ FALSE, /* boolean_t argByReferenceServer */
+ FALSE /* boolean_t argTempOnStack */
+ };
+ register argument_t *new;
+
+ new = (argument_t *) malloc(sizeof *new);
+ if (new == argNULL)
+ fatal("argAlloc(): %s", strerror(errno));
+ *new = prototype;
+ return new;
+}
+
+routine_t *
+rtMakeRoutine(identifier_t name, argument_t *args)
+{
+ register routine_t *rt = rtAlloc();
+
+ rt->rtName = name;
+ rt->rtKind = rkRoutine;
+ rt->rtArgs = args;
+
+ return rt;
+}
+
+routine_t *
+rtMakeSimpleRoutine(identifier_t name, argument_t *args)
+{
+ register routine_t *rt = rtAlloc();
+
+ rt->rtName = name;
+ rt->rtKind = rkSimpleRoutine;
+ rt->rtArgs = args;
+
+ return rt;
+}
+
+const char *
+rtRoutineKindToStr(routine_kind_t rk)
+{
+ switch (rk)
+ {
+ case rkRoutine:
+ return "Routine";
+ case rkSimpleRoutine:
+ return "SimpleRoutine";
+ default:
+ fatal("rtRoutineKindToStr(%d): not a routine_kind_t", rk);
+ /*NOTREACHED*/
+ return strNULL;
+ }
+
+}
+
+static void
+rtPrintArg(register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+
+ if (!akCheck(arg->argKind, akbUserArg|akbServerArg) ||
+ (akIdent(arg->argKind) == akeCount) ||
+ (akIdent(arg->argKind) == akeDealloc) ||
+ (akIdent(arg->argKind) == akeNdrCode) ||
+ (akIdent(arg->argKind) == akePoly))
+ return;
+
+ printf("\n\t");
+
+ switch (akIdent(arg->argKind))
+ {
+ case akeRequestPort:
+ printf("RequestPort");
+ break;
+ case akeReplyPort:
+ printf("ReplyPort");
+ break;
+ case akeWaitTime:
+ printf("WaitTime");
+ break;
+
+ case akeSendTime:
+ printf("SendTime");
+ break;
+
+ case akeMsgOption:
+ printf("MsgOption");
+ break;
+ case akeMsgSeqno:
+ printf("MsgSeqno\t");
+ break;
+ case akeSecToken:
+ printf("SecToken\t");
+ break;
+
+ case akeAuditToken:
+ printf("AuditToken\t");
+ break;
+
+ case akeContextToken:
+ printf("ContextToken\t");
+ break;
+
+ case akeImplicit:
+ printf("Implicit\t");
+ break;
+ default:
+ if (akCheck(arg->argKind, akbRequest)) {
+ if (akCheck(arg->argKind, akbSend))
+ printf("In");
+ else
+ printf("(In)");
+ }
+ if (akCheck(arg->argKind, akbReply)) {
+ if (akCheck(arg->argKind, akbReturn))
+ printf("Out");
+ else
+ printf("(Out)");
+ }
+ printf("\t");
+ }
+
+ printf("\t%s: %s", arg->argName, it->itName);
+
+ if (arg->argDeallocate == d_YES)
+ printf(", Dealloc");
+ else if (arg->argDeallocate == d_MAYBE)
+ printf(", Dealloc[]");
+
+ if (arg->argCountInOut)
+ printf(", CountInOut");
+
+ if (arg->argFlags & flSameCount)
+ printf(", SameCount");
+
+ if (arg->argFlags & flPhysicalCopy)
+ printf(", PhysicalCopy");
+
+ if (arg->argFlags & flRetCode)
+ printf(", PhysicalCopy");
+
+ if (arg->argFlags & flOverwrite)
+ printf(", Overwrite");
+
+ if (arg->argFlags & flAuto)
+ printf(", Auto");
+
+ if (arg->argFlags & flConst)
+ printf(", Const");
+}
+
+void
+rtPrintRoutine(register routine_t *rt)
+{
+ register argument_t *arg;
+
+ printf("%s (%d) %s(", rtRoutineKindToStr(rt->rtKind),
+ rt->rtNumber, rt->rtName);
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
+ rtPrintArg(arg);
+
+ printf(")\n");
+ printf("\n");
+}
+
+/*
+ * Determines appropriate value of msg-simple for the message.
+ * One version for both In & Out.
+ */
+
+static void
+rtCheckSimple(argument_t *args, u_int mask, boolean_t *simple)
+{
+ register argument_t *arg;
+ boolean_t MustBeComplex = FALSE;
+
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (akCheck(arg->argKind, mask)) {
+ ipc_type_t *it = arg->argType;
+
+ if (IS_KERN_PROC_DATA(it))
+ MustBeComplex = TRUE;
+ }
+
+ *simple = !MustBeComplex;
+}
+
+static void
+rtCheckFit(routine_t *rt, u_int mask, boolean_t *fitp, boolean_t *uselimp, u_int *knownp)
+{
+ boolean_t uselim = FALSE;
+ argument_t *arg;
+ int size = sizeof(mach_msg_header_t);
+
+ if (!rt->rtSimpleRequest)
+ machine_alignment(size,sizeof(mach_msg_body_t));
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
+ if (akCheck(arg->argKind, mask)) {
+ register ipc_type_t *it = arg->argType;
+
+ machine_alignment(size, it->itMinTypeSize);
+ if (it->itNative)
+ uselim = TRUE;
+ else if (IS_VARIABLE_SIZED_UNTYPED(it)) {
+ machine_alignment(size, it->itTypeSize);
+ size += it->itPadSize;
+ }
+ }
+ *knownp = size;
+ if (MaxMessSizeOnStack == -1) {
+ *fitp = TRUE;
+ *uselimp = FALSE;
+ } else if (size > MaxMessSizeOnStack) {
+ *fitp = FALSE;
+ *uselimp = FALSE;
+ } else if (!uselim) {
+ *fitp = TRUE;
+ *uselimp = FALSE;
+ } else if (UserTypeLimit == -1) {
+ *fitp = FALSE;
+ *uselimp = FALSE;
+ } else if (size + UserTypeLimit > MaxMessSizeOnStack) {
+ *fitp = FALSE;
+ *uselimp = TRUE;
+ } else {
+ *fitp = TRUE;
+ *uselimp = TRUE;
+ }
+}
+
+static void
+rtFindHowMany(routine_t *rt)
+{
+ register argument_t *arg;
+ int multiplier = 1;
+ boolean_t test;
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ register ipc_type_t *it = arg->argType;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ if (!it->itVarArray)
+ multiplier = it->itKPD_Number;
+ test = !it->itVarArray && !it->itElement->itVarArray;
+ it = it->itElement;
+ } else
+ test = !it->itVarArray;
+
+ if (akCheck(arg->argKind, akbSendKPD)) {
+
+ if (it->itInLine)
+ rt->rtCountPortsIn += it->itNumber * multiplier;
+ else if (it->itPortType) {
+ if (test)
+ rt->rtCountOolPortsIn += it->itNumber * multiplier;
+ } else {
+ if (test)
+ rt->rtCountOolIn += (it->itNumber * it->itSize + 7)/8 * multiplier;
+ }
+ }
+ if (akCheckAll(arg->argKind, akbReturnKPD)) {
+ if (it->itInLine)
+ rt->rtCountPortsOut += it->itNumber * multiplier;
+ else if (it->itPortType) {
+ if (test)
+ rt->rtCountOolPortsOut += it->itNumber * multiplier;
+ } else {
+ if (test)
+ rt->rtCountOolOut += ((it->itNumber * it->itSize + 7)/8) * multiplier;
+ }
+ }
+ }
+}
+
+boolean_t
+rtCheckMask(argument_t *args, u_int mask)
+{
+ register argument_t *arg;
+
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (akCheckAll(arg->argKind, mask))
+ return TRUE;
+ return FALSE;
+}
+
+boolean_t
+rtCheckMaskFunction(argument_t *args, u_int mask, boolean_t (*func)(/* argument_t *arg */))
+{
+ register argument_t *arg;
+
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (akCheckAll(arg->argKind, mask))
+ if ((*func)(arg))
+ return TRUE;
+ return FALSE;
+}
+
+
+static int
+rtCountKPDs(argument_t *args, u_int mask)
+{
+ register argument_t *arg;
+ int count = 0;
+
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (akCheckAll(arg->argKind, mask))
+ count += arg->argType->itKPD_Number;
+ return count;
+}
+
+static int
+rtCountFlags(args, flag)
+ argument_t *args;
+ u_int flag;
+{
+ register argument_t *arg;
+ int count = 0;
+
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (arg->argFlags & flag)
+ count++;
+ return count;
+}
+
+int
+rtCountArgDescriptors(argument_t *args, int *argcount)
+{
+ register argument_t *arg;
+ int count = 0;
+
+ if (argcount)
+ *argcount = 0;
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (akCheck(arg->argKind, akbServerArg)) {
+ if (RPCFixedArray(arg) ||
+ RPCPort(arg) ||
+ RPCVariableArray(arg) ||
+ RPCPortArray(arg)) {
+ count++;
+ if (argcount)
+ (*argcount)++;
+ }
+ else {
+ if (argcount) {
+ if (arg->argType->itStruct && arg->argType->itNumber &&
+ (arg->argType->itSize >= 32))
+ *argcount += arg->argType->itNumber * (arg->argType->itSize / 32);
+ else
+ (*argcount)++;
+ }
+ }
+ }
+ return count;
+}
+
+static int
+rtCountMask(argument_t *args, u_int mask)
+{
+ register argument_t *arg;
+ int count = 0;
+
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (akCheckAll(arg->argKind, mask))
+ count++;
+ return count;
+}
+
+/* arg->argType may be NULL in this function */
+
+static void
+rtDefaultArgKind(routine_t *rt, argument_t *arg)
+{
+ if ((arg->argKind == akNone) && (rt->rtRequestPort == argNULL))
+ arg->argKind = akRequestPort;
+
+ if (arg->argKind == akNone)
+ arg->argKind = akIn;
+}
+
+/*
+ * Initializes arg->argDeallocate,
+ * arg->argCountInOut from arg->argFlags
+ * and perform consistency check over the
+ * flags.
+ */
+
+static ipc_flags_t
+rtProcessDeallocFlag(register ipc_type_t *it, register ipc_flags_t flags, register arg_kind_t kind, dealloc_t *what, string_t name)
+{
+
+ /* only one of flDealloc, flNotDealloc, flMaybeDealloc */
+
+ if (flags & flMaybeDealloc) {
+ if (flags & (flDealloc|flNotDealloc)) {
+ warn("%s: Dealloc and NotDealloc ignored with Dealloc[]", name);
+ flags &= ~(flDealloc|flNotDealloc);
+ }
+ }
+
+ if ((flags&(flDealloc|flNotDealloc)) == (flDealloc|flNotDealloc)) {
+ warn("%s: Dealloc and NotDealloc cancel out", name);
+ flags &= ~(flDealloc|flNotDealloc);
+ }
+
+ if (((IsKernelServer && akCheck(kind, akbReturn)) ||
+ (IsKernelUser && akCheck(kind, akbSend))) &&
+ (flags & flDealloc)) {
+ /*
+ * For a KernelServer interface and an Out argument,
+ * or a KernelUser interface and an In argument,
+ * we avoid a possible spurious warning about the deallocate bit.
+ * For compatibility with Mach 2.5, the deallocate bit
+ * may need to be enabled on some inline arguments.
+ */
+
+ *what= d_YES;
+ } else if (flags & (flMaybeDealloc|flDealloc)) {
+ /* only give semantic warnings if the user specified something */
+ if (it->itInLine && !it->itPortType) {
+ warn("%s: Dealloc is ignored: it is meaningless for that type of argument", name);
+ flags &= ~(flMaybeDealloc|flDealloc);
+ } else
+ *what = (flags & flMaybeDealloc) ? d_MAYBE : d_YES;
+ }
+ return flags;
+}
+
+static void
+rtProcessSameCountFlag(register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ register ipc_flags_t flags = arg->argFlags;
+ string_t name = arg->argVarName;
+ static argument_t *old_arg;
+
+ if (flags & flSameCount) {
+ if (!it->itVarArray) {
+ warn("%s: SameCount is ignored - the argument is not variable", name);
+ flags &= ~flSameCount;
+ }
+ if (old_arg) {
+ if (old_arg->argParent)
+ old_arg = old_arg->argParent;
+ if (old_arg->argSameCount)
+ old_arg = old_arg->argSameCount;
+
+ if (!old_arg->argType->itVarArray) {
+ warn("%s: SameCount is ignored - adjacent argument is not variable", name);
+ flags &= ~flSameCount;
+ }
+
+#define SAMECOUNT_MASK akeBITS|akbSend|akbReturn|akbRequest|akbReply|akbUserArg|akbServerArg
+ if (akCheck(old_arg->argKind, SAMECOUNT_MASK) !=
+ akCheck(arg->argKind, SAMECOUNT_MASK) ||
+ old_arg->argCountInOut != arg->argCountInOut) {
+ warn("%s: SameCount is ignored - inconsistencies with the adjacent argument\n", name);
+ flags &= ~flSameCount;
+ }
+ arg->argSameCount = old_arg;
+ }
+ arg->argFlags = flags;
+ }
+ old_arg = arg;
+}
+
+static ipc_flags_t
+rtProcessCountInOutFlag(ipc_type_t *it, ipc_flags_t flags, arg_kind_t kind, boolean_t *what, string_t name)
+{
+ if (flags & flCountInOut) {
+ if (!akCheck(kind, akbReply)) {
+ warn("%s: CountInOut is ignored: argument must be Out\n", name);
+ flags &= ~flCountInOut;
+ } else if (!it->itVarArray || !it->itInLine) {
+ warn("%s: CountInOut is ignored: argument isn't variable or in-line\n", name);
+ flags &= ~flCountInOut;
+ } else
+ *what = TRUE;
+ }
+ return flags;
+}
+
+static ipc_flags_t
+rtProcessPhysicalCopyFlag(register ipc_type_t *it, register ipc_flags_t flags, register arg_kind_t kind __unused, string_t name)
+{
+ if (flags & flPhysicalCopy) {
+ if (it->itInLine) {
+ warn("%s: PhysicalCopy is ignored, argument copied inline anyway", name);
+ flags &= ~flPhysicalCopy;
+ }
+ if (it->itPortType) {
+ warn("%s: PhysicalCopy is ignored, it does not apply to ports and array of ports", name);
+ flags &= ~flPhysicalCopy;
+ }
+ }
+ return flags;
+}
+
+static void
+rtProcessRetCodeFlag(register argument_t *thisarg)
+{
+ register ipc_type_t *it = thisarg->argType;
+ register ipc_flags_t flags = thisarg->argFlags;
+ string_t name = thisarg->argVarName;
+ routine_t *thisrout = thisarg->argRoutine;
+
+ if (flags & flRetCode) {
+ if (!it->itInLine || !it->itStruct ||
+ it->itSize != 32 || it->itNumber != 1) {
+ warn("%s: RetCode is ignored - the type doesn't match a MIG RetCode", name);
+ flags &= ~flRetCode;
+ } else if (thisrout->rtKind != rkSimpleRoutine) {
+ fatal("%s: RetCode is allowed only for SimpleRoutines", name);
+ } else if (thisrout->rtRetCArg != argNULL) {
+ warn("%s: RetCode is ignored - only one argument can be flagged as RetCode", name);
+ flags &= ~flRetCode;
+ } else {
+ thisrout->rtRetCArg = thisarg;
+ }
+ thisarg->argFlags = flags;
+ }
+}
+
+static ipc_flags_t
+rtProcessOverwriteFlag(register ipc_type_t *it, register ipc_flags_t flags, register arg_kind_t kind, string_t name)
+{
+ if (flags & flOverwrite)
+ if (it->itInLine || it->itMigInLine ||
+ /* among In, Out, InOut, we want only the Out! */
+ !akCheck(kind, akbReturn) || akCheck(kind, akbSend)) {
+ warn("%s: Overwrite is ignored - it must be Out AND Ool!", name);
+ flags &= ~flOverwrite;
+ }
+ return flags;
+}
+
+static void
+rtDetectKPDArg(argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *string;
+
+ if (IS_KERN_PROC_DATA(it)) {
+ if (akCheck(arg->argKind, akbSendBody)) {
+ arg->argKind = akRemFeature(arg->argKind, akbSendBody);
+ arg->argKind = akAddFeature(arg->argKind, akbSendKPD);
+ }
+ if (akCheck(arg->argKind, akbReturnBody)) {
+ arg->argKind = akRemFeature(arg->argKind, akbReturnBody);
+ arg->argKind = akAddFeature(arg->argKind, akbReturnKPD);
+ }
+ if (it->itInLine) {
+ string = "mach_msg_port_descriptor_t";
+ arg->argKPD_Type = MACH_MSG_PORT_DESCRIPTOR;
+ } else if (it->itPortType) {
+ string = "mach_msg_ool_ports_descriptor_t";
+ arg->argKPD_Type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
+ } else {
+ string = "mach_msg_ool_descriptor_t";
+ arg->argKPD_Type = MACH_MSG_OOL_DESCRIPTOR;
+ }
+ it->itKPDType = string;
+ }
+}
+
+static void
+rtAugmentArgKind(argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+
+ /* akbVariable means variable-sized inline */
+
+ if (IS_VARIABLE_SIZED_UNTYPED(it)) {
+ if (akCheckAll(arg->argKind, akbRequest|akbReply))
+ error("%s: Inline variable-sized arguments can't be InOut",
+ arg->argName);
+ arg->argKind = akAddFeature(arg->argKind, akbVariable);
+ }
+ if (IS_OPTIONAL_NATIVE(it))
+ arg->argKind = akAddFeature(arg->argKind, akbVariable);
+
+ /*
+ * Need to use a local variable in the following cases:
+ * 1) There is a translate-out function & the argument is being
+ * returned. We need to translate it before it hits the message.
+ * 2) There is a translate-in function & the argument is
+ * sent and returned. We need a local variable for its address.
+ * 3) There is a destructor function, which will be used
+ * (SendRcv and not ReturnSnd), and there is a translate-in
+ * function whose value must be saved for the destructor.
+ * 4) This is Complex KPD (array of KPD), and as such it has to
+ * be copied to a local array in input and output
+ * 5) Both poly and dealloc generate warnings compile time, because
+ * we attempt to take address of bit-field structure member
+ */
+
+ if (((it->itOutTrans != strNULL) &&
+ akCheck(arg->argKind, akbReturnSnd)) ||
+ ((it->itInTrans != strNULL) &&
+ akCheckAll(arg->argKind, akbSendRcv|akbReturnSnd)) ||
+ ((it->itDestructor != strNULL) &&
+ akCheck(arg->argKind, akbSendRcv) &&
+ !akCheck(arg->argKind, akbReturnSnd) &&
+ (it->itInTrans != strNULL)) ||
+ (IS_MULTIPLE_KPD(it)) ||
+ ((akIdent(arg->argKind) == akePoly) &&
+ akCheck(arg->argKind, akbReturnSnd)) ||
+ ((akIdent(arg->argKind) == akeDealloc) &&
+ akCheck(arg->argKind, akbReturnSnd))
+ )
+ {
+ arg->argKind = akRemFeature(arg->argKind, akbReplyCopy);
+ arg->argKind = akAddFeature(arg->argKind, akbVarNeeded);
+ }
+}
+
+/*
+ * The Suffix allows to handle KPDs as normal data.
+ * it is used in InArgMsgField.
+ */
+static void
+rtSuffixExtArg(register argument_t *args)
+{
+ register argument_t *arg;
+ register const char *subindex;
+ char string[MAX_STR_LEN];
+
+ for (arg = args; arg != argNULL; arg = arg->argNext) {
+ if (akCheck(arg->argKind, akbSendKPD | akbReturnKPD)) {
+ if (IS_MULTIPLE_KPD(arg->argType))
+ subindex = "[0]";
+ else
+ subindex = "";
+ switch (arg->argKPD_Type) {
+
+ case MACH_MSG_PORT_DESCRIPTOR:
+ (void)sprintf(string, "%s.name", subindex);
+ break;
+
+ case MACH_MSG_OOL_DESCRIPTOR:
+ case MACH_MSG_OOL_PORTS_DESCRIPTOR:
+ (void)sprintf(string, "%s.address", subindex);
+ break;
+
+ default:
+ error("Type of kernel processed data unknown\n");
+ }
+ arg->argSuffix = strconcat(arg->argMsgField, string);
+ /* see above the list of VarNeeded cases */
+ /*
+ * argCount has been removed from the VarNeeded list,
+ * because VarSize arrays have their Count in the untyped
+ * section of the message, and because it is not possible
+ * to move anything in-line/out-of-line
+ */
+ } else if (akIdent(arg->argKind) == akePoly &&
+ akCheck(arg->argParent->argKind, akbSendKPD | akbReturnKPD)) {
+ register argument_t *par_arg = arg->argParent;
+
+ if (IS_MULTIPLE_KPD(par_arg->argType))
+ subindex = "[0]";
+ else
+ subindex = "";
+ switch (par_arg->argKPD_Type) {
+
+ case MACH_MSG_PORT_DESCRIPTOR:
+ case MACH_MSG_OOL_PORTS_DESCRIPTOR:
+ (void)sprintf(string, "%s.disposition", subindex);
+ arg->argSuffix = strconcat(par_arg->argMsgField, string);
+ break;
+ default:
+ error("Type of kernel processed data inconsistent\n");
+ }
+ } else if (akIdent(arg->argKind) == akeDealloc &&
+ akCheck(arg->argParent->argKind, akbSendKPD | akbReturnKPD)) {
+ register argument_t *par_arg = arg->argParent;
+
+ if (IS_MULTIPLE_KPD(par_arg->argType))
+ subindex = "[0]";
+ else
+ subindex = "";
+ switch (par_arg->argKPD_Type) {
+
+ case MACH_MSG_OOL_DESCRIPTOR:
+ case MACH_MSG_OOL_PORTS_DESCRIPTOR:
+ (void)sprintf(string, "%s.deallocate", subindex);
+ arg->argSuffix = strconcat(par_arg->argMsgField, string);
+ break;
+
+ default:
+ error("Type of kernel processed data inconsistent\n");
+ }
+ }
+ }
+}
+
+/* arg->argType may be NULL in this function */
+
+static void
+rtCheckRoutineArg(routine_t *rt, argument_t *arg)
+{
+ switch (akIdent(arg->argKind))
+ {
+ case akeRequestPort:
+ if (rt->rtRequestPort != argNULL)
+ warn("multiple RequestPort args in %s; %s won't be used",
+ rt->rtName, rt->rtRequestPort->argName);
+ rt->rtRequestPort = arg;
+ break;
+
+ case akeReplyPort:
+ if (rt->rtReplyPort != argNULL)
+ warn("multiple ReplyPort args in %s; %s won't be used",
+ rt->rtName, rt->rtReplyPort->argName);
+ rt->rtReplyPort = arg;
+ break;
+
+ case akeWaitTime:
+ if (rt->rtWaitTime != argNULL)
+ warn("multiple WaitTime/SendTime type args in %s; %s won't be used", rt->rtName, rt->rtWaitTime->argName);
+ rt->rtWaitTime = arg;
+ break;
+
+ case akeSendTime:
+ if (rt->rtWaitTime != argNULL) {
+ if (akIdent(rt->rtWaitTime->argKind) == akeWaitTime) {
+ warn("SendTime type argument after a WaitTime in %s; SendTime %s won't be used", rt->rtName, arg->argName);
+ break;
+ } else
+ warn("multiple SendTime type args in %s; %s won't be used", rt->rtName, rt->rtWaitTime->argName);
+ }
+ rt->rtWaitTime = arg;
+ break;
+
+ case akeMsgOption:
+ if (rt->rtMsgOption != argNULL)
+ warn("multiple MsgOption args in %s; %s won't be used",
+ rt->rtName, rt->rtMsgOption->argName);
+ rt->rtMsgOption = arg;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* arg->argType may be NULL in this function */
+
+static void
+rtSetArgDefaults(routine_t *rt, register argument_t *arg)
+{
+ arg->argRoutine = rt;
+ if (arg->argVarName == strNULL)
+ arg->argVarName = arg->argName;
+ if (arg->argMsgField == strNULL)
+ switch(akIdent(arg->argKind)) {
+ case akeRequestPort:
+ arg->argMsgField = "Head.msgh_request_port";
+ break;
+ case akeReplyPort:
+ arg->argMsgField = "Head.msgh_reply_port";
+ break;
+ case akeNdrCode:
+ arg->argMsgField = "NDR";
+ break;
+ case akeSecToken:
+ arg->argMsgField = "msgh_sender";
+ break;
+
+ case akeAuditToken:
+ arg->argMsgField = "msgh_audit";
+ break;
+
+ case akeContextToken:
+ arg->argMsgField = "msgh_context";
+ break;
+
+ case akeMsgSeqno:
+ arg->argMsgField = "msgh_seqno";
+ break;
+ case akeImplicit:
+ /* the field is set directly by Yacc */
+ break;
+ default:
+ arg->argMsgField = arg->argName;
+ break;
+ }
+
+ if (arg->argTTName == strNULL)
+ arg->argTTName = strconcat(arg->argName, "Template");
+ if (arg->argPadName == strNULL)
+ arg->argPadName = strconcat(arg->argName, "Pad");
+
+ /*
+ * The poly args for the request and reply ports have special defaults,
+ * because their msg-type-name values aren't stored in normal fields.
+ */
+
+ if ((rt->rtRequestPort != argNULL) &&
+ (rt->rtRequestPort->argPoly == arg) &&
+ (arg->argType != itNULL)) {
+ arg->argMsgField = "Head.msgh_bits";
+ arg->argType->itInTrans = "MACH_MSGH_BITS_REQUEST";
+ }
+
+ if ((rt->rtReplyPort != argNULL) &&
+ (rt->rtReplyPort->argPoly == arg) &&
+ (arg->argType != itNULL)) {
+ arg->argMsgField = "Head.msgh_bits";
+ arg->argType->itInTrans = "MACH_MSGH_BITS_REPLY";
+ }
+}
+
+static void
+rtAddCountArg(register argument_t *arg)
+{
+ register argument_t *count, *master;
+ register ipc_type_t *it = arg->argType;
+
+ count = argAlloc();
+
+ if (IS_MULTIPLE_KPD(it) && it->itElement->itVarArray) {
+ count->argName = strconcat(arg->argName, "Subs");
+ count->argType = itMakeSubCountType(it->itKPD_Number, it->itVarArray, arg->argVarName);
+ count->argKind = akeSubCount;
+ arg->argSubCount = count;
+ } else {
+ count->argName = strconcat(arg->argName, "Cnt");
+ count->argType = itMakeCountType();
+ count->argKind = akeCount;
+ arg->argCount = count;
+ if (arg->argParent != argNULL) {
+ /* this is the case where we are at the second level of recursion:
+ we want the Parent to access it through argCount */
+ arg->argParent->argCount = count;
+ }
+ }
+ master = (arg->argParent != argNULL) ? arg->argParent : arg;
+ if (IS_MULTIPLE_KPD(master->argType))
+ count->argMultiplier = 1;
+ else
+ count->argMultiplier = it->itElement->itNumber;
+ count->argParent = arg;
+ count->argNext = arg->argNext;
+ arg->argNext = count;
+
+ if (arg->argType->itString) {
+ /* C String gets no Count argument on either side. */
+ count->argKind = akAddFeature(count->argKind, akCheck(arg->argKind, akbSend) ? akbSendRcv : akbReturnRcv);
+ count->argVarName = (char *)0;
+ } else {
+ /*
+ * Count arguments have to be present on the message body (NDR encoded)
+ * akbVariable has to be turned down, has it foul the algorithm
+ * for detecting the in-line variable sized arrays
+ */
+ count->argKind |= akAddFeature(akbUserArg|akbServerArg, (arg->argKind) & ~akeBITS);
+ count->argKind = akRemFeature(count->argKind, akbVariable|akbVarNeeded);
+ if (IS_VARIABLE_SIZED_UNTYPED(arg->argType))
+ /*
+ * Count arguments for the above types are explicitly declared
+ * BEFORE the variable (with those bits, they would come afterwards)
+ */
+ count->argKind = akRemFeature(count->argKind, akbRequest|akbReply);
+ }
+}
+
+static void
+rtAddCountInOutArg(register argument_t *arg)
+{
+ register argument_t *count;
+
+ /*
+ * The user sees a single count variable. However, to get the
+ * count passed from user to server for variable-sized inline OUT
+ * arrays, we need two count arguments internally. This is
+ * because the count value lives in different message fields (and
+ * is scaled differently) in the request and reply messages.
+ *
+ * The two variables have the same name to simplify code generation.
+ *
+ * This variable has a null argParent field because it has akbRequest.
+ * For example, see rtCheckVariable.
+ */
+
+ count = argAlloc();
+ count->argName = strconcat(arg->argName, "Cnt");
+ count->argType = itMakeCountType();
+ count->argParent = argNULL;
+ count->argNext = arg->argNext;
+ arg->argNext = count;
+ (count->argCInOut = arg->argCount)->argCInOut = count;
+ count->argKind = akCountInOut;
+}
+
+static void
+rtAddPolyArg(register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ register argument_t *poly;
+ arg_kind_t akbsend, akbreturn;
+
+ poly = argAlloc();
+ poly->argName = strconcat(arg->argName, "Poly");
+ poly->argType = itMakePolyType();
+ poly->argParent = arg;
+ poly->argNext = arg->argNext;
+ arg->argNext = poly;
+ arg->argPoly = poly;
+
+ /*
+ * akbsend is bits added if the arg is In;
+ * akbreturn is bits added if the arg is Out.
+ * The mysterious business with KernelServer subsystems:
+ * when packing Out arguments, they use OutNames instead
+ * of InNames, and the OutName determines if they are poly-in
+ * as well as poly-out.
+ */
+
+ akbsend = akbSend;
+ akbreturn = akbReturn;
+
+ if (it->itInName == MACH_MSG_TYPE_POLYMORPHIC)
+ {
+ akbsend |= akbUserArg|akbSendSnd;
+ if (!IsKernelServer)
+ akbreturn |= akbServerArg|akbReturnSnd;
+ }
+ if (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
+ {
+ akbsend |= akbServerArg|akbSendRcv;
+ akbreturn |= akbUserArg|akbReturnRcv;
+ if (IsKernelServer)
+ akbreturn |= akbServerArg|akbReturnSnd;
+ }
+
+ poly->argKind = akPoly;
+ if (akCheck(arg->argKind, akbSend))
+ poly->argKind = akAddFeature(poly->argKind,
+ akCheck(arg->argKind, akbsend));
+ if (akCheck(arg->argKind, akbReturn))
+ poly->argKind = akAddFeature(poly->argKind,
+ akCheck(arg->argKind, akbreturn));
+}
+
+static void
+rtAddDeallocArg(register argument_t *arg)
+{
+ register argument_t *dealloc;
+
+ dealloc = argAlloc();
+ dealloc->argName = strconcat(arg->argName, "Dealloc");
+ dealloc->argType = itMakeDeallocType();
+ dealloc->argParent = arg;
+ dealloc->argNext = arg->argNext;
+ arg->argNext = dealloc;
+ arg->argDealloc = dealloc;
+
+ /*
+ * Dealloc flag can only be associated to KPDs.
+ */
+
+ dealloc->argKind = akeDealloc;
+ if (akCheck(arg->argKind, akbSend))
+ dealloc->argKind = akAddFeature(dealloc->argKind,
+ akCheck(arg->argKind, akbUserArg|akbSend|akbSendSnd));
+ if (akCheck(arg->argKind, akbReturn)) {
+ dealloc->argKind = akAddFeature(dealloc->argKind,
+ akCheck(arg->argKind, akbServerArg|akbReturn|akbReturnSnd));
+
+ dealloc->argByReferenceServer = TRUE;
+ }
+}
+
+static void
+rtCheckRoutineArgs(routine_t *rt)
+{
+ register argument_t *arg;
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
+ {
+ register ipc_type_t *it = arg->argType;
+
+ rtDefaultArgKind(rt, arg);
+ rtCheckRoutineArg(rt, arg);
+
+ /* need to set argTTName before adding implicit args */
+ rtSetArgDefaults(rt, arg);
+
+ /* the arg may not have a type (if there was some error in parsing it),
+ in which case we don't want to do these steps. */
+
+ if (it != itNULL) {
+ arg->argFlags = rtProcessDeallocFlag(it, arg->argFlags, arg->argKind, &arg->argDeallocate, arg->argVarName);
+ arg->argFlags = rtProcessCountInOutFlag(it, arg->argFlags, arg->argKind, &arg->argCountInOut, arg->argVarName);
+ rtProcessSameCountFlag(arg);
+ arg->argFlags = rtProcessPhysicalCopyFlag(it, arg->argFlags, arg->argKind, arg->argVarName);
+ rtProcessRetCodeFlag(arg);
+ arg->argFlags = rtProcessOverwriteFlag(it, arg->argFlags, arg->argKind, arg->argVarName);
+ rtAugmentArgKind(arg);
+
+ /* args added here will get processed in later iterations */
+ /* order of args is 'arg poly countinout count dealloc' */
+
+ if (arg->argDeallocate == d_MAYBE)
+ rtAddDeallocArg(arg);
+ if (it->itVarArray || (IS_MULTIPLE_KPD(it) && it->itElement->itVarArray))
+ rtAddCountArg(arg);
+ if (arg->argCountInOut)
+ rtAddCountInOutArg(arg);
+ if ((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) ||
+ (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC))
+ rtAddPolyArg(arg);
+ /*
+ * Detects whether the arg has to become part of the
+ * Kernel Processed Data section; if yes, define the proper
+ * itUserKPDType, itServerKPDType
+ */
+ rtDetectKPDArg(arg);
+ }
+ }
+}
+
+static boolean_t
+rtCheckTrailerType(register argument_t *arg)
+{
+ if (akIdent(arg->argKind) == akeSecToken ||
+ akIdent(arg->argKind) == akeAuditToken ||
+ akIdent(arg->argKind) == akeContextToken)
+ itCheckTokenType(arg->argVarName, arg->argType);
+
+ if (akIdent(arg->argKind) == akeMsgSeqno)
+ itCheckIntType(arg->argVarName, arg->argType);
+ /*
+ * if the built-in are not used, we cannot match
+ * the type/size of the desciption provided by the user
+ * with the one defined in message.h.
+ */
+ return (TRUE);
+}
+
+static void
+rtCheckArgTypes(routine_t *rt)
+{
+ if (rt->rtRequestPort == argNULL)
+ error("%s %s doesn't have a server port argument",
+ rtRoutineKindToStr(rt->rtKind), rt->rtName);
+
+ if ((rt->rtRequestPort != argNULL) &&
+ (rt->rtRequestPort->argType != itNULL))
+ itCheckRequestPortType(rt->rtRequestPort->argName,
+ rt->rtRequestPort->argType);
+
+ if ((rt->rtReplyPort != argNULL) &&
+ (rt->rtReplyPort->argType != itNULL))
+ itCheckReplyPortType(rt->rtReplyPort->argName,
+ rt->rtReplyPort->argType);
+
+ if ((rt->rtWaitTime != argNULL) &&
+ (rt->rtWaitTime->argType != itNULL))
+ itCheckIntType(rt->rtWaitTime->argName,
+ rt->rtWaitTime->argType);
+
+ if ((rt->rtMsgOption != argNULL) &&
+ (rt->rtMsgOption->argType != itNULL))
+ itCheckIntType(rt->rtMsgOption->argName,
+ rt->rtMsgOption->argType);
+
+ if ((IsKernelServer && rt->rtServerImpl) ||
+ (IsKernelUser && rt->rtUserImpl))
+ fatal("Implicit data is not supported in the KernelUser and KernelServer modes");
+ /* rtCheckTrailerType will hit a fatal() if something goes wrong */
+ if (rt->rtServerImpl)
+ rtCheckMaskFunction(rt->rtArgs, akbServerImplicit, rtCheckTrailerType);
+ if (rt->rtUserImpl)
+ rtCheckMaskFunction(rt->rtArgs, akbUserImplicit, rtCheckTrailerType);
+}
+
+/*
+ * Check for arguments which are missing seemingly needed functions.
+ * We make this check here instead of in itCheckDecl, because here
+ * we can take into account what kind of argument the type is
+ * being used with.
+ *
+ * These are warnings, not hard errors, because mig will generate
+ * reasonable code in any case. The generated code will work fine
+ * if the ServerType and TransType are really the same, even though
+ * they have different names.
+ */
+
+static void
+rtCheckArgTrans(routine_t *rt)
+{
+ argument_t *arg;
+
+ /* the arg may not have a type (if there was some error in parsing it) */
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ ipc_type_t *it = arg->argType;
+
+ if ((it != itNULL) && !streql(it->itServerType, it->itTransType)) {
+ if (akCheck(arg->argKind, akbSendRcv) && (it->itInTrans == strNULL))
+ warn("%s: argument has no in-translation function", arg->argName);
+
+ if (akCheck(arg->argKind, akbReturnSnd) && (it->itOutTrans == strNULL))
+ warn("%s: argument has no out-translation function", arg->argName);
+ }
+ }
+}
+
+/*
+ * Adds an implicit return-code argument. It exists in the reply message,
+ * where it is the first piece of data (After the NDR format label)..
+ */
+
+static void
+rtAddRetCode(routine_t *rt)
+{
+ register argument_t *arg = argAlloc();
+
+ arg->argName = "RetCode";
+ arg->argType = itRetCodeType;
+ arg->argKind = akRetCode;
+ rt->rtRetCode = arg;
+
+ arg->argNext = rt->rtArgs;
+ rt->rtArgs = arg;
+}
+
+/*
+ * Process the Return Code.
+ * The MIG protocol says that RetCode != 0 are only sent through
+ * mig_reply_error_t structures. Therefore, there is no need
+ * for reserving a RetCode in a complex Reply message.
+ */
+static void
+rtProcessRetCode(routine_t *rt)
+{
+
+ if (!rt->rtOneWay && !rt->rtSimpleReply) {
+ register argument_t *arg = rt->rtRetCode;
+
+ arg->argKind = akRemFeature(arg->argKind, akbReply);
+ /* we want the RetCode to be a local variable instead */
+ arg->argKind = akAddFeature(arg->argKind, akbVarNeeded);
+ }
+ if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
+ register argument_t *arg = rt->rtRetCArg;
+
+ arg->argKind = akeRetCode|akbUserArg|akbServerArg|akbSendRcv;
+ }
+}
+
+/*
+ * Adds an implicit NDR argument. It exists in the reply message,
+ * where it is the first piece of data.
+ */
+
+static void
+rtAddNdrCode(routine_t *rt)
+{
+ register argument_t *arg = argAlloc();
+
+ arg->argName = "NDR_record";
+ arg->argType = itNdrCodeType;
+ arg->argKind = akeNdrCode;
+ rt->rtNdrCode = arg;
+
+ /* add at beginning, so ndr-code is first in the reply message */
+ arg->argNext = rt->rtArgs;
+ rt->rtArgs = arg;
+}
+
+/*
+ * Process the NDR Code.
+ * We stick a NDR format label iff there is untyped data
+ */
+static void
+rtProcessNdrCode(routine_t *rt)
+{
+ register argument_t *ndr = rt->rtNdrCode;
+ argument_t *arg;
+ boolean_t found;
+
+ /* akbSendSnd|akbSendBody initialize the NDR format label */
+#define ndr_send akbRequest|akbSend|akbSendSnd|akbSendBody
+ /* akbReplyInit initializes the NDR format label */
+#define ndr_rcv akbReply|akbReplyInit|akbReturn|akbReturnBody
+
+ ndr->argKind = akAddFeature(ndr->argKind, ndr_send|ndr_rcv);
+
+ for (found = FALSE, arg = ndr->argNext; arg != argNULL; arg = arg->argNext)
+ if (akCheck(arg->argKind, akbSendRcv|akbSendBody) &&
+ !akCheck(arg->argKind, akbServerImplicit) && !arg->argType->itPortType &&
+ (!arg->argParent || akIdent(arg->argKind) == akeCount ||
+ akIdent(arg->argKind) == akeCountInOut)) {
+ arg->argKind = akAddFeature(arg->argKind, akbSendNdr);
+ found = TRUE;
+ }
+ if (!found)
+ ndr->argKind = akRemFeature(ndr->argKind, ndr_send);
+
+ found = FALSE;
+ if (!rt->rtOneWay)
+ for (arg = ndr->argNext; arg != argNULL; arg = arg->argNext)
+ if ((arg == rt->rtRetCode && akCheck(arg->argKind, akbReply)) ||
+ (arg != rt->rtRetCode &&
+ akCheck(arg->argKind, akbReturnRcv|akbReturnBody) &&
+ !akCheck(arg->argKind, akbUserImplicit) && !arg->argType->itPortType &&
+ (!arg->argParent || akIdent(arg->argKind) == akeCount ||
+ akIdent(arg->argKind) == akeCountInOut))) {
+ arg->argKind = akAddFeature(arg->argKind, akbReturnNdr);
+ found = TRUE;
+ }
+ if (!found && !akCheck(rt->rtRetCode->argKind, akbReply))
+ ndr->argKind = akRemFeature(ndr->argKind, ndr_rcv);
+}
+
+/*
+ * Adds a dummy WaitTime argument to the function.
+ * This argument doesn't show up in any C argument lists;
+ * it implements the global WaitTime statement.
+ */
+
+static void
+rtAddWaitTime(routine_t *rt, identifier_t name, arg_kind_t kind)
+{
+ register argument_t *arg = argAlloc();
+ argument_t **loc;
+
+ arg->argName = "dummy WaitTime arg";
+ arg->argVarName = name;
+ arg->argType = itWaitTimeType;
+ arg->argKind = kind;
+ rt->rtWaitTime = arg;
+
+ /* add wait-time after msg-option, if possible */
+
+ if (rt->rtMsgOption != argNULL)
+ loc = &rt->rtMsgOption->argNext;
+ else
+ loc = &rt->rtArgs;
+
+ arg->argNext = *loc;
+ *loc = arg;
+
+ rtSetArgDefaults(rt, arg);
+}
+
+/*
+ * Adds a dummy MsgOption argument to the function.
+ * This argument doesn't show up in any C argument lists;
+ * it implements the global MsgOption statement.
+ */
+
+static void
+rtAddMsgOption(routine_t *rt, identifier_t name)
+{
+ register argument_t *arg = argAlloc();
+ argument_t **loc;
+
+ arg->argName = "dummy MsgOption arg";
+ arg->argVarName = name;
+ arg->argType = itMsgOptionType;
+ arg->argKind = akeMsgOption;
+ rt->rtMsgOption = arg;
+
+ /* add msg-option after msg-seqno */
+
+ loc = &rt->rtArgs;
+
+ arg->argNext = *loc;
+ *loc = arg;
+
+ rtSetArgDefaults(rt, arg);
+}
+
+/*
+ * Process the MsgOption Code.
+ * We must add the information to post a receive with the right
+ * Trailer options.
+ */
+static void
+rtProcessMsgOption(routine_t *rt)
+{
+ register argument_t *msgop = rt->rtMsgOption;
+ register argument_t *arg;
+ boolean_t sectoken = FALSE;
+ boolean_t audittoken = FALSE;
+ boolean_t contexttoken = FALSE;
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
+ if (akCheckAll(arg->argKind, akbReturn|akbUserImplicit)) {
+ if (akIdent(arg->argKind) == akeSecToken)
+ sectoken = TRUE;
+ else if (akIdent(arg->argKind) == akeAuditToken)
+ audittoken = TRUE;
+ else if (akIdent(arg->argKind) == akeContextToken)
+ contexttoken = TRUE;
+ }
+
+ if (contexttoken == TRUE)
+ msgop->argVarName = strconcat(msgop->argVarName, "|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_CTX)");
+ else if (audittoken == TRUE)
+ msgop->argVarName = strconcat(msgop->argVarName, "|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT)");
+ else if (sectoken == TRUE)
+ msgop->argVarName = strconcat(msgop->argVarName, "|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_SENDER)");
+ /* other implicit data received by the user will be handled here */
+}
+
+
+/*
+ * Adds a dummy reply port argument to the function.
+ */
+
+static void
+rtAddDummyReplyPort(routine_t *rt, ipc_type_t *type)
+{
+ register argument_t *arg = argAlloc();
+ argument_t **loc;
+
+ arg->argName = "dummy ReplyPort arg";
+ arg->argVarName = "dummy ReplyPort arg";
+ arg->argType = type;
+ arg->argKind = akeReplyPort;
+ rt->rtReplyPort = arg;
+
+ /* add the reply port after the request port */
+
+ if (rt->rtRequestPort != argNULL)
+ loc = &rt->rtRequestPort->argNext;
+ else
+ loc = &rt->rtArgs;
+
+ arg->argNext = *loc;
+ *loc = arg;
+
+ rtSetArgDefaults(rt, arg);
+}
+
+
+/*
+ * At least one overwrite keyword has been detected:
+ * we tag all the OOL entries (ports + data) with
+ * akbOverwrite which will tell us that we have to
+ * fill a KPD entry in the message-template
+ */
+static void
+rtCheckOverwrite(register routine_t *rt)
+{
+ register argument_t *arg;
+ register int howmany = rt->rtOverwrite;
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ register ipc_type_t *it = arg->argType;
+
+ if (akCheck(arg->argKind, akbReturnKPD) && !it->itInLine) {
+ /* among OUT args, we want OOL, OOL ports and MigInLine */
+ arg->argKind = akAddFeature(arg->argKind, akbOverwrite);
+ if (arg->argFlags & flOverwrite)
+ howmany--;
+ if (!howmany)
+ return;
+ }
+ }
+}
+
+/*
+ * Initializes argRequestPos, argReplyPos, rtMaxRequestPos, rtMaxReplyPos,
+ * rtNumRequestVar, rtNumReplyVar, and adds akbVarNeeded to those arguments
+ * that need it because of variable-sized inline considerations.
+ *
+ * argRequestPos and argReplyPos get -1 if the value shouldn't be used.
+ */
+static void
+rtCheckVariable(register routine_t *rt)
+{
+ register argument_t *arg;
+ int NumRequestVar = 0;
+ int NumReplyVar = 0;
+ int MaxRequestPos = 0;
+ int MaxReplyPos = 0;
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ register argument_t *parent = arg->argParent;
+
+ /*
+ * We skip KPDs. We have to make sure that the KPDs count
+ * present in the message body follow the RequestPos/ReplyPos logic
+ * The rest of the parameters are defaulted to have
+ * Arg{Request, Reply}Pos = 0
+ */
+ if (parent == argNULL || akCheck(parent->argKind, akbSendKPD|akbReturnKPD)) {
+ if (akCheckAll(arg->argKind, akbSend|akbSendBody)) {
+ arg->argRequestPos = NumRequestVar;
+ MaxRequestPos = NumRequestVar;
+ if (akCheck(arg->argKind, akbVariable))
+ NumRequestVar++;
+ }
+ if (akCheckAll(arg->argKind, akbReturn|akbReturnBody)) {
+ arg->argReplyPos = NumReplyVar;
+ MaxReplyPos = NumReplyVar;
+ if (akCheck(arg->argKind, akbVariable))
+ NumReplyVar++;
+ }
+ } else {
+ arg->argRequestPos = parent->argRequestPos;
+ arg->argReplyPos = parent->argReplyPos;
+ }
+ /*
+ printf("Var %s Kind %x RequestPos %d\n", arg->argVarName, arg->argKind, arg->argRequestPos);
+ printf("* Var %s Kind %x ReplyPos %d\n", arg->argVarName, arg->argKind, arg->argReplyPos);
+ */
+
+ /* Out variables that follow a variable-sized field
+ need VarNeeded or ReplyCopy; they can't be stored
+ directly into the reply message. */
+
+ if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody) &&
+ !akCheck(arg->argKind, akbReplyCopy|akbVarNeeded) &&
+ (arg->argReplyPos > 0))
+ arg->argKind = akAddFeature(arg->argKind, akbVarNeeded);
+ }
+
+ rt->rtNumRequestVar = NumRequestVar;
+ rt->rtNumReplyVar = NumReplyVar;
+ rt->rtMaxRequestPos = MaxRequestPos;
+ rt->rtMaxReplyPos = MaxReplyPos;
+}
+
+/*
+ * Adds akbDestroy where needed.
+ */
+
+static void
+rtCheckDestroy(register routine_t *rt)
+{
+ register argument_t *arg;
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ register ipc_type_t *it = arg->argType;
+
+ if(akCheck(arg->argKind, akbSendRcv) &&
+ !akCheck(arg->argKind, akbReturnSnd) &&
+ (it->itDestructor != strNULL || IS_MIG_INLINE_EMUL(it))) {
+ arg->argKind = akAddFeature(arg->argKind, akbDestroy);
+ }
+ if (argIsIn(arg) && akCheck(arg->argKind, akbSendKPD|akbReturnKPD) &&
+ arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR &&
+ (arg->argFlags & flAuto))
+ arg->argKind = akAddFeature(arg->argKind, akbDestroy);
+ }
+}
+
+/*
+ * Sets ByReferenceUser and ByReferenceServer.
+ */
+
+static void
+rtAddByReference(register routine_t *rt)
+{
+ register argument_t *arg;
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ register ipc_type_t *it = arg->argType;
+
+ if (akCheck(arg->argKind, akbReturnRcv) && it->itStruct) {
+ arg->argByReferenceUser = TRUE;
+
+ /*
+ * A CountInOut arg itself is not akbReturnRcv,
+ * so we need to set argByReferenceUser specially.
+ */
+
+ if (arg->argCInOut != argNULL)
+ arg->argCInOut->argByReferenceUser = TRUE;
+ }
+
+ if ((akCheck(arg->argKind, akbReturnSnd) ||
+ (akCheck(arg->argKind, akbServerImplicit) &&
+ akCheck(arg->argKind, akbReturnRcv) &&
+ akCheck(arg->argKind, akbSendRcv)))
+ && it->itStruct) {
+ arg->argByReferenceServer = TRUE;
+ }
+ }
+}
+
+/*
+ * This procedure can be executed only when all the akb* and ake* have
+ * been set properly (when rtAddCountArg is executed, akbVarNeeded
+ * might not be set yet - see rtCheckVariable)
+ */
+static void
+rtAddSameCount(register routine_t *rt)
+{
+ register argument_t *arg;
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
+ if (arg->argFlags & flSameCount) {
+ register ipc_type_t *it = arg->argType;
+ register argument_t *tmp_count;
+ register argument_t *my_count = arg->argCount;
+ register argument_t *ref_count = arg->argSameCount->argCount;
+
+ tmp_count = argAlloc();
+ *tmp_count = *ref_count;
+ /*
+ * if our count is a akbVarNeeded, we need to copy this
+ * attribute to the master count!
+ */
+ tmp_count->argKind = akeSameCount;
+ ref_count->argKind = akAddFeature(ref_count->argKind, akCheck(my_count->argKind, akbVarNeeded));
+ tmp_count->argKind = akAddFeature(tmp_count->argKind, akCheck(my_count->argKind, akbVarNeeded));
+ tmp_count->argNext = my_count->argNext;
+ tmp_count->argMultiplier = my_count->argMultiplier;
+ tmp_count->argType = my_count->argType;
+ tmp_count->argParent = arg;
+ /* we don't need more */
+ arg->argCount = tmp_count;
+ arg->argNext = tmp_count;
+ /* for these args, Cnt is not akbRequest, and therefore size is embedded */
+ if (IS_VARIABLE_SIZED_UNTYPED(it))
+ it->itMinTypeSize = 0;
+ tmp_count->argType->itMinTypeSize = 0;
+ tmp_count->argType->itTypeSize = 0;
+ }
+}
+
+void
+rtCheckRoutine(register routine_t *rt)
+{
+ /* Initialize random fields. */
+
+ rt->rtErrorName = ErrorProc;
+ rt->rtOneWay = (rt->rtKind == rkSimpleRoutine);
+ rt->rtServerName = strconcat(ServerPrefix, rt->rtName);
+ rt->rtUserName = strconcat(UserPrefix, rt->rtName);
+
+ /* Add implicit arguments. */
+
+ rtAddRetCode(rt);
+ rtAddNdrCode(rt);
+
+ /* Check out the arguments and their types. Add count, poly
+ implicit args. Any arguments added after rtCheckRoutineArgs
+ should have rtSetArgDefaults called on them. */
+
+ rtCheckRoutineArgs(rt);
+
+ /* Add dummy WaitTime and MsgOption arguments, if the routine
+ doesn't have its own args and the user specified global values. */
+
+ if (rt->rtReplyPort == argNULL) {
+ if (rt->rtOneWay)
+ rtAddDummyReplyPort(rt, itZeroReplyPortType);
+ else
+ rtAddDummyReplyPort(rt, itRealReplyPortType);
+ }
+ if (rt->rtMsgOption == argNULL) {
+ if (MsgOption == strNULL)
+ rtAddMsgOption(rt, "MACH_MSG_OPTION_NONE");
+ else
+ rtAddMsgOption(rt, MsgOption);
+ }
+ if (rt->rtWaitTime == argNULL) {
+ if (WaitTime != strNULL)
+ rtAddWaitTime(rt, WaitTime, akeWaitTime);
+ else if (SendTime != strNULL)
+ rtAddWaitTime(rt, SendTime, akeSendTime);
+ }
+
+
+ /* Now that all the arguments are in place, do more checking. */
+
+ rtCheckArgTypes(rt);
+ rtCheckArgTrans(rt);
+
+ if (rt->rtOneWay &&
+ (rtCheckMask(rt->rtArgs, akbReturn) || rt->rtUserImpl))
+ error("%s %s has OUT argument",
+ rtRoutineKindToStr(rt->rtKind), rt->rtName);
+
+ /* If there were any errors, don't bother calculating more info
+ that is only used in code generation anyway. Therefore,
+ the following functions don't have to worry about null types. */
+
+ if (errors > 0)
+ fatal("%d errors found. Abort.\n", errors);
+
+ rt->rtServerImpl = rtCountMask(rt->rtArgs, akbServerImplicit);
+ rt->rtUserImpl = rtCountMask(rt->rtArgs, akbUserImplicit);
+ /*
+ * ASSUMPTION:
+ * kernel cannot change a message from simple to complex,
+ * therefore SimpleSendReply and SimpleRcvReply become SimpleReply
+ */
+#ifdef notyet
+ /* Setting this to true causes MIG to generate incorrect code */
+ rtCheckSimple(rt->rtArgs, akbRequest, &rt->rtSimpleRequest);
+#endif
+ rtCheckSimple(rt->rtArgs, akbReply, &rt->rtSimpleReply);
+
+ rt->rtRequestKPDs = rtCountKPDs(rt->rtArgs, akbSendKPD);
+ rt->rtReplyKPDs = rtCountKPDs(rt->rtArgs, akbReturnKPD);
+ /*
+ * Determine how many overwrite parameters we have:
+ * # of Overwrite args -> rt->rtOverwrite
+ * flOverwrite -> the arg has to be overwritten
+ * akbOverwrite -> the arg has to be declared in the message-template
+ * (only as a placeholder if !flOverwrite).
+ */
+ if ((rt->rtOverwrite = rtCountFlags(rt->rtArgs, flOverwrite))) {
+ rtCheckOverwrite(rt);
+ rt->rtOverwriteKPDs = rtCountKPDs(rt->rtArgs, akbReturnKPD|akbOverwrite);
+ if (IsKernelUser)
+ fatal("Overwrite option(s) do not match with the KernelUser personality\n");
+ }
+
+ rtCheckFit(rt, akbRequest, &rt->rtRequestFits, &rt->rtRequestUsedLimit, &rt->rtRequestSizeKnown);
+ rtCheckFit(rt, akbReply, &rt->rtReplyFits, &rt->rtReplyUsedLimit, &rt->rtReplySizeKnown);
+
+ rtCheckVariable(rt);
+ rtCheckDestroy(rt);
+ rtAddByReference(rt);
+ rtSuffixExtArg(rt->rtArgs);
+ rtAddSameCount(rt);
+ rtProcessRetCode(rt);
+ rtProcessNdrCode(rt);
+ if (rt->rtUserImpl)
+ rtProcessMsgOption(rt);
+
+ rt->rtNoReplyArgs = !rtCheckMask(rt->rtArgs, akbReturnSnd);
+
+ if (UseEventLogger)
+ /* some more info's are needed for Event logging/Stats */
+ rtFindHowMany(rt);
+}
+
+void
+rtMinRequestSize(FILE *file, routine_t *rt, const char *str)
+{
+ fprintf(file, "(sizeof(%s)", str);
+ rtSizeDelta(file, akbRequest, rt);
+ fprintf(file, ")");
+}
+
+void
+rtMinReplySize(FILE *file, routine_t *rt, const char *str)
+{
+ fprintf(file, "(sizeof(%s)", str);
+ rtSizeDelta(file, akbReply, rt);
+ fprintf(file, ")");
+}
+
+static void
+rtSizeDelta(FILE *file, u_int mask, routine_t *rt)
+{
+ argument_t *arg;
+ u_int min_size = sizeof(mach_msg_header_t);
+ u_int max_size;
+ boolean_t output = FALSE;
+
+ if (!rt->rtSimpleRequest)
+ machine_alignment(min_size, sizeof(mach_msg_body_t));
+ max_size = min_size;
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
+ if (akCheck(arg->argKind, mask)) {
+ register ipc_type_t *it = arg->argType;
+
+ machine_alignment(min_size, it->itMinTypeSize);
+ machine_alignment(max_size, it->itMinTypeSize);
+
+ if (IS_VARIABLE_SIZED_UNTYPED(it)) {
+ machine_alignment(max_size, it->itTypeSize);
+ max_size += it->itPadSize;
+ }
+ if (IS_OPTIONAL_NATIVE(it)) {
+ if (output)
+ fprintf(file, " + ");
+ else {
+ output = TRUE;
+ fprintf(file, " - (");
+ }
+ fprintf(file, "_WALIGNSZ_(%s)", it->itUserType);
+ }
+ }
+ if (min_size != max_size) {
+ if (output)
+ fprintf(file, " + ");
+ else
+ fprintf(file, " - ");
+ fprintf(file, "%d", max_size - min_size);
+ }
+ if (output)
+ fprintf(file, ")");
+}
+
Property changes on: trunk/usr.bin/migcom/routine.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/routine.h
===================================================================
--- trunk/usr.bin/migcom/routine.h (rev 0)
+++ trunk/usr.bin/migcom/routine.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,615 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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.
+ */
+/*
+ * 92/03/03 16:25:12 jeffreyh
+ * Changes from TRUNK
+ * [92/02/26 12:32:23 jeffreyh]
+ *
+ * 92/01/14 16:46:34 rpd
+ * Removed akbWasInOut. Added akeCountInOut, argCInOut.
+ * [92/01/08 rpd]
+ *
+ * 92/01/03 20:29:52 dbg
+ * Add byReferenceUser and byReferenceServer to each argument, so
+ * they can be individually set. Add akbPointer.
+ * [91/09/04 dbg]
+ *
+ * 91/08/28 11:17:17 jsb
+ * Removed Camelot and TrapRoutine support.
+ * Changed MsgKind to MsgSeqno.
+ * [91/08/12 rpd]
+ *
+ * 91/07/31 18:10:37 dbg
+ * Add akbIndefinite, argServerCopy.
+ * [91/04/10 dbg]
+ *
+ * Change argDeallocate to an enumerated type, to allow for
+ * user-specified deallocate flag.
+ *
+ * Add rtCheckMaskFunction. Add rtNoReplyArgs to routine
+ * structure.
+ * [91/04/03 dbg]
+ *
+ * 91/02/05 17:55:28 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:55:21 mrt]
+ *
+ * 90/06/02 15:05:23 rpd
+ * Created for new IPC.
+ * [90/03/26 21:12:57 rpd]
+ *
+ * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
+ * Extensive revamping. Added polymorphic arguments.
+ * Allow multiple variable-sized inline arguments in messages.
+ *
+ * 20-Dec-87 David Golub (dbg) at Carnegie-Mellon University
+ * Added pointers to last Request and Reply arguments.
+ * Added flag to show that (only) last argument is variable-sized.
+ * Added argMultiplier field for count arguments, where parent
+ * argument is itself a multiple of an IPC type.
+ *
+ * 16-Nov-87 David Golub (dbg) at Carnegie-Mellon University
+ * Don't add akbVarNeeded attribute here - server.c can
+ * better determine whether it is needed.
+ *
+ * 21-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Added argFlag field to argument_t
+ *
+ * 18-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Changed akTid to omit akServerArg
+ * Changed arg_kind_t to u_int to make code more obvious and
+ * to get rid of compiler warnings and to give hc a chance.
+ * Changed flags on akTid, akDummy.
+ *
+ * 10-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Added defines need to make MsgType a legitimate argument type
+ *
+ * 28-May-87 Richard Draves (rpd) at Carnegie-Mellon University
+ * Created.
+ */
+
+#ifndef _ROUTINE_H
+#define _ROUTINE_H
+
+#include "type.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 akbSendNdr (0x04000000) /* needs NDR conversion in request */
+#define akbVariable (0x01000000) /* variable size inline data */
+#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)(); /* KPD discipline for static templates */
+ void (* argKPD_Init)(); /* KPD discipline for initializing */
+ void (* argKPD_Pack)(); /* KPD discipline for packing */
+ void (* argKPD_Extract)(); /* KPD discipline for extracting */
+ void (* argKPD_TypeCheck)(); /* 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;
+
+ 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 const char *rtRoutineKindToStr(routine_kind_t rk);
+
+extern int rtCountArgDescriptors(argument_t *args, int *argcount);
+
+extern void rtMinRequestSize(FILE *file, routine_t *rt, const char *str);
+extern void rtMinReplySize(FILE *file, routine_t *rt, const 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 */
+
+
+
Property changes on: trunk/usr.bin/migcom/routine.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/server.c
===================================================================
--- trunk/usr.bin/migcom/server.c (rev 0)
+++ trunk/usr.bin/migcom/server.c 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,2843 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014, Matthew Macy <kmacy at FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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.
+ */
+/*
+ * 92/03/03 16:25:17 jeffreyh
+ * Changes from TRUNK
+ * [92/02/26 12:32:30 jeffreyh]
+ *
+ * 92/01/14 16:46:39 rpd
+ * Modified WriteInitializeCount, WriteExtractArg
+ * for the revised CountInOut implementation.
+ * Fixed Indefinite code generation, to allow short type descriptors.
+ * Added deallocate bit handling to Indefinite code generation.
+ * [92/01/08 rpd]
+ *
+ * 92/01/03 20:30:09 dbg
+ * Generate <subsystem>_server_routine to return unpacking function
+ * pointer.
+ * [91/11/11 dbg]
+ *
+ * For inline variable-length arrays that are Out parameters, allow
+ * passing the user's count argument to the server as an InOut
+ * parameter.
+ * [91/11/11 dbg]
+ *
+ * Redo handling of OUT arrays that are passed in-line or
+ * out-of-line. Treat more like out-of-line arrays:
+ * user allocates buffer and pointer
+ * fills in pointer with buffer address
+ * passes pointer to stub
+ * stub copies data to *pointer, or changes pointer
+ * User can always use *pointer.
+ *
+ * Change argByReferenceUser to a field in argument_t.
+ * [91/09/04 dbg]
+ *
+ * 91/08/28 11:17:21 jsb
+ * Replaced ServerProcName with ServerDemux.
+ * [91/08/13 rpd]
+ *
+ * Removed Camelot and TrapRoutine support.
+ * Changed MsgKind to MsgSeqno.
+ * [91/08/12 rpd]
+ *
+ * 91/07/31 18:10:51 dbg
+ * Allow indefinite-length variable arrays. They may be copied
+ * either in-line or out-of-line, depending on size.
+ *
+ * Copy variable-length C Strings with mig_strncpy, to combine
+ * 'strcpy' and 'strlen' operations.
+ *
+ * New method for advancing request message pointer past
+ * variable-length arguments. We no longer have to know the order
+ * of variable-length arguments and their count arguments.
+ *
+ * Remove redundant assignments (to msgh_simple, msgh_size) in
+ * generated code.
+ * [91/07/17 dbg]
+ *
+ * 91/06/25 10:31:51 rpd
+ * Cast request and reply ports to ipc_port_t in KernelServer stubs.
+ * [91/05/27 rpd]
+ *
+ * 91/02/05 17:55:37 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:55:30 mrt]
+ *
+ * 90/06/02 15:05:29 rpd
+ * Created for new IPC.
+ * [90/03/26 21:13:12 rpd]
+ *
+ * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
+ * Extensive revamping. Added polymorphic arguments.
+ * Allow multiple variable-sized inline arguments in messages.
+ *
+ * 18-Oct-88 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Set the local port in the server reply message to
+ * MACH_PORT_NULL for greater efficiency and to make Camelot
+ * happy.
+ *
+ * 18-Apr-88 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Changed call to WriteLocalVarDecl in WriteMsgVarDecl
+ * to write out the parameters for the C++ code to a call
+ * a new routine WriteServerVarDecl which includes the *
+ * for reference variable, but uses the transType if it
+ * exists.
+ *
+ * 27-Feb-88 Richard Draves (rpd) at Carnegie-Mellon University
+ * Changed reply message initialization for camelot interfaces.
+ * Now we assume camelot interfaces are all camelotroutines and
+ * always initialize the dummy field & tid field. This fixes
+ * the wrapper-server-call bug in distributed transactions.
+ *
+ * 23-Feb-88 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Changed the include of camelot_types.h to cam/camelot_types.h
+ *
+ * 19-Feb-88 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Fixed WriteDestroyArg to not call the destructor
+ * function on any in/out args.
+ *
+ * 4-Feb-88 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Fixed dld's code to write out parameter list to
+ * use WriteLocalVarDecl to get transType or ServType if
+ * they exist.
+ *
+ * 19-Jan-88 David Golub (dbg) at Carnegie-Mellon University
+ * Change variable-length inline array declarations to use
+ * maximum size specified to Mig. Make message variable
+ * length if the last item in the message is variable-length
+ * and inline. Use argMultipler field to convert between
+ * argument and IPC element counts.
+ *
+ * 18-Jan-88 David Detlefs (dld) at Carnegie-Mellon University
+ * Modified to produce C++ compatible code via #ifdefs.
+ * All changes have to do with argument declarations.
+ *
+ * 2-Dec-87 David Golub (dbg) at Carnegie-Mellon University
+ * Added destructor function for IN arguments to server.
+ *
+ * 18-Nov-87 Jeffrey Eppinger (jle) at Carnegie-Mellon University
+ * Changed to typedef "novalue" as "void" if we're using hc.
+ *
+ * 17-Sep-87 Bennet Yee (bsy) at Carnegie-Mellon University
+ * Added _<system>SymTab{Base|End} for use with security
+ * dispatch routine. It is neccessary for the authorization
+ * system to know the operations by symbolic names.
+ * It is harmless to user code as it only means an extra
+ * array if it is accidentally turned on.
+ *
+ * 24-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Corrected the setting of retcode for CamelotRoutines.
+ *
+ * 21-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Added deallocflag to call to WritePackArgType.
+ *
+ * 14-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Moved type declarations and assignments for DummyType
+ * and tidType to server demux routine. Automatically
+ * include camelot_types.h and msg_types.h for interfaces
+ * containing camelotRoutines.
+ *
+ * 8-Jun-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Removed #include of sys/types.h and strings.h from WriteIncludes.
+ * Changed the KERNEL include from ../h to sys/
+ * Removed extern from WriteServer to make hi-c happy
+ *
+ * 28-May-87 Richard Draves (rpd) at Carnegie-Mellon University
+ * Created.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <mach/message.h>
+#include "write.h"
+#include "utils.h"
+#include "global.h"
+#include "error.h"
+
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif /* max */
+
+void WriteLogDefines();
+void WriteIdentificationString();
+static void WriteFieldDecl();
+
+static void
+WriteKPD_Iterator(FILE *file, boolean_t in, boolean_t varying, argument_t *arg, boolean_t bracket)
+{
+ register ipc_type_t *it = arg->argType;
+ char string[MAX_STR_LEN];
+
+ fprintf(file, "\t{\n");
+ fprintf(file, "\t register\t%s\t*ptr;\n", it->itKPDType);
+ fprintf(file, "\t register int\ti");
+ if (varying && !in)
+ fprintf(file, ", j");
+ fprintf(file, ";\n\n");
+
+ if (in)
+ sprintf(string, "In%dP", arg->argRequestPos);
+ else
+ sprintf(string, "OutP");
+
+ fprintf(file, "\t ptr = &%s->%s[0];\n", string, arg->argMsgField);
+
+ if (varying) {
+ register argument_t *count = arg->argCount;
+
+ if (in)
+ fprintf(file, "\t for (i = 0; i < In%dP->%s; ptr++, i++) %s\n",
+ count->argRequestPos, count->argMsgField,
+ (bracket) ? "{" : "");
+ else {
+ fprintf(file, "\t j = min(%d, ", it->itKPD_Number);
+ if (akCheck(count->argKind, akbVarNeeded))
+ fprintf(file, "%s);\n", count->argName);
+ else
+ fprintf(file, "%s->%s);\n", string, count->argMsgField);
+ fprintf(file, "\t for (i = 0; i < j; ptr++, i++) %s\n",
+ (bracket) ? "{" : "");
+ }
+ } else
+ fprintf(file, "\t for (i = 0; i < %d; ptr++, i++) %s\n", it->itKPD_Number,
+ (bracket) ? "{" : "");
+}
+
+static void
+WriteMyIncludes(FILE *file, statement_t *stats)
+{
+ if (ServerHeaderFileName == strNULL || UseSplitHeaders)
+ WriteIncludes(file, FALSE, FALSE);
+ if (ServerHeaderFileName != strNULL)
+ {
+ register const char *cp;
+
+ /* Strip any leading path from ServerHeaderFileName. */
+ cp = strrchr(ServerHeaderFileName, '/');
+ if (cp == 0)
+ cp = ServerHeaderFileName;
+ else
+ cp++; /* skip '/' */
+ fprintf(file, "#include \"%s\"\n", cp);
+ }
+ if (ServerHeaderFileName == strNULL || UseSplitHeaders)
+ WriteImplImports(file, stats, FALSE);
+ if (UseEventLogger) {
+ if (IsKernelServer) {
+ fprintf(file, "#if\t__MigKernelSpecificCode\n");
+ fprintf(file, "#include <mig_debug.h>\n");
+ fprintf(file, "#endif\t/* __MigKernelSpecificCode */\n");
+ }
+ fprintf(file, "#if MIG_DEBUG\n");
+ fprintf(file, "#include <mach/mig_log.h>\n");
+ fprintf(file, "#endif /* MIG_DEBUG */\n");
+ }
+ fprintf(file, "\n");
+}
+
+static void
+WriteGlobalDecls(FILE *file)
+{
+ if (BeAnsiC) {
+ fprintf(file, "#define novalue void\n");
+ } else {
+ fprintf(file, "#if\t%s\n", NewCDecl);
+ fprintf(file, "#define novalue void\n");
+ fprintf(file, "#else\n");
+ fprintf(file, "#define novalue int\n");
+ fprintf(file, "#endif\t/* %s */\n", NewCDecl);
+ WriteRCSDecl(file, strconcat(SubsystemName, "_server"), RCSId);
+ }
+ /* Used for locations in the request message, *not* reply message.
+ Reply message locations aren't dependent on IsKernelServer. */
+
+ if (IsKernelServer) {
+ fprintf(file, "#if\t__MigKernelSpecificCode\n");
+ fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n");
+ fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)");
+ fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n");
+ fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n");
+ fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)");
+ fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n");
+ fprintf(file, "#else\n");
+ }
+ fprintf(file, "#define msgh_request_port\tmsgh_local_port\n");
+ fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)");
+ fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n");
+ fprintf(file, "#define msgh_reply_port\t\tmsgh_remote_port\n");
+ fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)");
+ fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n");
+ if (IsKernelServer) {
+ fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
+ }
+ fprintf(file, "\n");
+ if (UseEventLogger)
+ WriteLogDefines(file, "MACH_MSG_LOG_SERVER");
+ fprintf(file, "#define MIG_RETURN_ERROR(X, code)\t{\\\n");
+ fprintf(file, "\t\t\t\t((mig_reply_error_t *)X)->RetCode = code;\\\n");
+ fprintf(file, "\t\t\t\t((mig_reply_error_t *)X)->NDR = NDR_record;\\\n");
+ fprintf(file, "\t\t\t\treturn;\\\n");
+ fprintf(file, "\t\t\t\t}\n");
+ fprintf(file, "\n");
+}
+
+static void
+WriteForwardDeclarations(FILE *file, statement_t *stats)
+{
+ register statement_t *stat;
+
+ fprintf(file, "/* Forward Declarations */\n\n");
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ if (stat->stKind == skRoutine) {
+ fprintf(file, "\nmig_internal novalue _X%s\n", stat->stRoutine->rtName);
+ fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);\n");
+ }
+ fprintf(file, "\n");
+}
+
+static void
+WriteMIGCheckDefines(FILE *file)
+{
+ fprintf(file, "#define\t__MIG_check__Request__%s_subsystem__ 1\n", SubsystemName);
+ fprintf(file, "\n");
+}
+
+static void
+WriteNDRDefines(FILE *file)
+{
+ fprintf(file, "#define\t__NDR_convert__Request__%s_subsystem__ 1\n", SubsystemName);
+ fprintf(file, "\n");
+}
+
+static void
+WriteProlog(FILE *file, statement_t *stats)
+{
+ WriteIdentificationString(file);
+ fprintf(file, "\n");
+ fprintf(file, "/* Module %s */\n", SubsystemName);
+ fprintf(file, "\n");
+ WriteMIGCheckDefines(file);
+ if (CheckNDR)
+ WriteNDRDefines(file);
+ WriteMyIncludes(file, stats);
+ WriteBogusDefines(file);
+ WriteApplDefaults(file, "Rcv");
+ WriteGlobalDecls(file);
+ if (ServerHeaderFileName == strNULL) {
+ WriteRequestTypes(file, stats);
+ WriteReplyTypes(file, stats);
+ WriteServerReplyUnion(file, stats);
+ }
+}
+
+static void
+WriteSymTabEntries(FILE *file, statement_t *stats)
+{
+ register statement_t *stat;
+ register u_int current = 0;
+
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ if (stat->stKind == skRoutine) {
+ register u_int num = stat->stRoutine->rtNumber;
+ const char *name = stat->stRoutine->rtName;
+ while (++current <= num)
+ fprintf(file,"\t\t\t{ \"\", 0, 0 },\n");
+ fprintf(file, "\t{ \"%s\", %d, _X%s },\n", name, SubsystemBase + current - 1, name);
+ }
+ while (++current <= rtNumber)
+ fprintf(file,"\t{ \"\", 0, 0 },\n");
+}
+
+static void
+WriteRoutineEntries(FILE *file, statement_t *stats)
+{
+ register u_int current = 0;
+ register statement_t *stat;
+ char *sig_array, *rt_name;
+ int arg_count, descr_count;
+ int offset = 0;
+ size_t serverSubsysNameLen = strlen(ServerSubsys);
+
+ fprintf(file, "\t{\n");
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ if (stat->stKind == skRoutine)
+ {
+ register routine_t *rt = stat->stRoutine;
+ size_t rtNameLen = strlen(rt->rtName);
+
+ // Include length of rt->rtName in calculation of necessary buffer size, since that string
+ // is actually written into the buffer along with the Server Subsystem name.
+ sig_array = (char *) malloc(serverSubsysNameLen + rtNameLen + 80);
+ rt_name = (char *) malloc(rtNameLen + 5);
+ while (current++ < rt->rtNumber)
+ fprintf(file, "\t\t{0, 0, 0, 0, 0, 0},\n");
+ // NOTE: if either of the two string constants in the sprintf() function calls below get
+ // much longer, be sure to increase the constant '80' (in the first malloc() call) to ensure
+ // that the allocated buffer is large enough. (Currently, I count 66 characters in the first
+ // string constant, 65 in the second. 80 ought to be enough for now...)
+ if (UseRPCTrap) {
+ sprintf(sig_array, "&%s.arg_descriptor[%d], (mach_msg_size_t)sizeof(__Reply__%s_t)", ServerSubsys, offset, rt->rtName);
+ }
+ else {
+ sprintf(sig_array, "(routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__%s_t)", rt->rtName);
+ }
+ sprintf(rt_name, "_X%s", rt->rtName);
+ descr_count = rtCountArgDescriptors(rt->rtArgs, &arg_count);
+ offset += descr_count;
+ WriteRPCRoutineDescriptor(file, rt, arg_count, (UseRPCTrap) ? descr_count : 0, rt_name, sig_array);
+ fprintf(file, ",\n");
+ free(sig_array);
+ free(rt_name);
+ }
+ while (current++ < rtNumber)
+ fprintf(file, "\t\t{0, 0, 0, 0, 0, 0},\n");
+
+ fprintf(file, "\t}");
+}
+
+static void
+WriteArgDescriptorEntries(FILE *file, statement_t *stats)
+{
+ register statement_t *stat;
+
+ fprintf(file, ",\n\n\t{\n");
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ if (stat->stKind == skRoutine)
+ {
+ register routine_t *rt = stat->stRoutine;
+
+ /* For each arg of the routine, write an arg descriptor:
+ */
+ WriteRPCRoutineArgDescriptor(file, rt);
+ }
+ fprintf(file, "\t},\n\n");
+}
+
+
+/*
+ * Write out the description of this subsystem, for use in direct RPC
+ */
+static void
+WriteSubsystem(FILE *file, statement_t *stats)
+{
+ register statement_t *stat;
+ int descr_count = 0;
+
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ if (stat->stKind == skRoutine)
+ {
+ register routine_t *rt = stat->stRoutine;
+ descr_count += rtCountArgDescriptors(rt->rtArgs, (int *) 0);
+ }
+ fprintf(file, "\n");
+ if (ServerHeaderFileName == strNULL) {
+ WriteMigExternal(file);
+ fprintf(file, "boolean_t %s(", ServerDemux);
+ if (BeAnsiC) {
+ fprintf(file, "\n\t\tmach_msg_header_t *InHeadP,");
+ fprintf(file, "\n\t\tmach_msg_header_t *OutHeadP");
+ }
+ fprintf(file, ");\n\n");
+
+ WriteMigExternal(file);
+ fprintf(file, "mig_routine_t %s_routine(", ServerDemux);
+ if (BeAnsiC) {
+ fprintf(file, "\n\t\tmach_msg_header_t *InHeadP");
+ }
+ fprintf(file, ");\n\n");
+ }
+ fprintf(file, "\n/* Description of this subsystem, for use in direct RPC */\n");
+ if (ServerHeaderFileName == strNULL) {
+ fprintf(file, "extern const struct %s %s;\n", ServerSubsys, ServerSubsys);
+ fprintf(file, "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);
+ }
+ else {
+ fprintf(file, "const struct %s %s = {\n", ServerSubsys, ServerSubsys);
+ }
+ if (UseRPCTrap) {
+ fprintf(file, "\t0,\n");
+ }
+ else {
+ fprintf(file, "\t%s_routine,\n", ServerDemux);
+ }
+ fprintf(file, "\t%d,\n", SubsystemBase);
+ fprintf(file, "\t%d,\n", SubsystemBase + rtNumber);
+ fprintf(file, "\t(mach_msg_size_t)sizeof(union __ReplyUnion__%s),\n", ServerSubsys);
+ if (UseRPCTrap) {
+ fprintf(file, "\t(vm_address_t)&%s,\n", ServerSubsys);
+ }
+ else {
+ fprintf(file, "\t(vm_address_t)0,\n");
+ }
+ WriteRoutineEntries(file, stats);
+
+ if (UseRPCTrap)
+ WriteArgDescriptorEntries(file, stats);
+ else
+ fprintf(file, "\n");
+
+ fprintf(file, "};\n\n");
+}
+#if 0
+static void
+WriteArraySizes(file, stats)
+ FILE *file;
+ statement_t *stats;
+{
+ register u_int current = 0;
+ register statement_t *stat;
+
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ if (stat->stKind == skRoutine)
+ {
+ register routine_t *rt = stat->stRoutine;
+
+ while (current++ < rt->rtNumber)
+ fprintf(file, "\t\t0,\n");
+ fprintf(file, "\t\tsizeof(__Reply__%s_t),\n", rt->rtName);
+ }
+ while (current++ < rtNumber)
+ fprintf(file, "\t\t\t0,\n");
+}
+
+#endif /* NOT_CURRENTLY_USED */
+
+void
+WriteServerRequestUnion(FILE *file, statement_t *stats)
+{
+ register statement_t *stat;
+
+ fprintf(file, "\n");
+ fprintf(file, "/* union of all requests */\n\n");
+ fprintf(file, "#ifndef __RequestUnion__%s__defined\n", ServerSubsys);
+ fprintf(file, "#define __RequestUnion__%s__defined\n", ServerSubsys);
+ fprintf(file, "union __RequestUnion__%s {\n", ServerSubsys);
+ for (stat = stats; stat != stNULL; stat = stat->stNext) {
+ if (stat->stKind == skRoutine) {
+ register routine_t *rt;
+
+ rt = stat->stRoutine;
+ fprintf(file, "\t__Request__%s_t Request_%s;\n", rt->rtName, rt->rtName);
+ }
+ }
+ fprintf(file, "};\n");
+ fprintf(file, "#endif /* __RequestUnion__%s__defined */\n", ServerSubsys);
+}
+
+void
+WriteServerReplyUnion(FILE *file, statement_t *stats)
+{
+ register statement_t *stat;
+
+ fprintf(file, "\n");
+ fprintf(file, "/* union of all replies */\n\n");
+ fprintf(file, "#ifndef __ReplyUnion__%s__defined\n", ServerSubsys);
+ fprintf(file, "#define __ReplyUnion__%s__defined\n", ServerSubsys);
+ fprintf(file, "union __ReplyUnion__%s {\n", ServerSubsys);
+ for (stat = stats; stat != stNULL; stat = stat->stNext) {
+ if (stat->stKind == skRoutine) {
+ register routine_t *rt;
+
+ rt = stat->stRoutine;
+ fprintf(file, "\t__Reply__%s_t Reply_%s;\n", rt->rtName, rt->rtName);
+ }
+ }
+ fprintf(file, "};\n");
+ fprintf(file, "#endif /* __RequestUnion__%s__defined */\n", ServerSubsys);
+}
+
+static void
+WriteDispatcher(FILE *file, statement_t *stats)
+{
+ /*
+ * Write the subsystem stuff.
+ */
+ fprintf(file, "\n");
+ WriteSubsystem(file, stats);
+
+ /*
+ * Then, the server routine
+ */
+ fprintf(file, "mig_external boolean_t %s\n", ServerDemux);
+ if (BeAnsiC) {
+ fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
+ } else {
+ fprintf(file, "#if\t%s\n", NewCDecl);
+ fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
+ fprintf(file, "#else\n");
+ fprintf(file, "\t(InHeadP, OutHeadP)\n");
+ fprintf(file, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n");
+ fprintf(file, "#endif\t/* %s */\n", NewCDecl);
+ }
+
+ fprintf(file, "{\n");
+ fprintf(file, "\t/*\n");
+ fprintf(file, "\t * typedef struct {\n");
+ fprintf(file, "\t * \tmach_msg_header_t Head;\n");
+ fprintf(file, "\t * \tNDR_record_t NDR;\n");
+ fprintf(file, "\t * \tkern_return_t RetCode;\n");
+ fprintf(file, "\t * } mig_reply_error_t;\n");
+ fprintf(file, "\t */\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "\tregister mig_routine_t routine;\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "\tOutHeadP->msgh_bits = ");
+ fprintf(file, "MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0);\n");
+ fprintf(file, "\tOutHeadP->msgh_remote_port = InHeadP->msgh_reply_port;\n");
+ fprintf(file, "\t/* Minimal size: routine() will update it if different */\n");
+ fprintf(file, "\tOutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);\n");
+ fprintf(file, "\tOutHeadP->msgh_local_port = MACH_PORT_NULL;\n");
+ fprintf(file, "\tOutHeadP->msgh_id = InHeadP->msgh_id + 100;\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "\tif ((InHeadP->msgh_id > %d) || (InHeadP->msgh_id < %d) ||\n", SubsystemBase + rtNumber - 1, SubsystemBase);
+ fprintf(file, "\t ((routine = %s.routine[InHeadP->msgh_id - %d].stub_routine) == 0)) {\n", ServerSubsys, SubsystemBase);
+ fprintf(file, "\t\t((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;\n");
+ fprintf(file, "\t\t((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;\n");
+ if (UseEventLogger) {
+ fprintf(file, "#if MIG_DEBUG\n");
+ fprintf(file, "\t\tLOG_ERRORS(MACH_MSG_LOG_SERVER, MACH_MSG_ERROR_UNKNOWN_ID,\n");
+ fprintf(file, "\t\t\t&InHeadP->msgh_id, __FILE__, __LINE__);\n");
+ fprintf(file, "#endif /* MIG_DEBUG */\n");
+ }
+ fprintf(file, "\t\treturn FALSE;\n");
+ fprintf(file, "\t}\n");
+
+ /* Call appropriate routine */
+ fprintf(file, "\t(*routine) (InHeadP, OutHeadP);\n");
+ fprintf(file, "\treturn TRUE;\n");
+ fprintf(file, "}\n");
+ fprintf(file, "\n");
+
+ /*
+ * Then, the <subsystem>_server_routine routine
+ */
+ fprintf(file, "mig_external mig_routine_t %s_routine\n", ServerDemux);
+ if (BeAnsiC) {
+ fprintf(file, "\t(mach_msg_header_t *InHeadP)\n");
+ } else {
+ fprintf(file, "#if\t%s\n", NewCDecl);
+ fprintf(file, "\t(mach_msg_header_t *InHeadP)\n");
+ fprintf(file, "#else\n");
+ fprintf(file, "\t(InHeadP)\n");
+ fprintf(file, "\tmach_msg_header_t *InHeadP;\n");
+ fprintf(file, "#endif\t/* %s */\n", NewCDecl);
+ }
+
+ fprintf(file, "{\n");
+ fprintf(file, "\tregister int msgh_id;\n");
+ fprintf(file, "\n");
+ fprintf(file, "\tmsgh_id = InHeadP->msgh_id - %d;\n", SubsystemBase);
+ fprintf(file, "\n");
+ fprintf(file, "\tif ((msgh_id > %d) || (msgh_id < 0))\n", rtNumber - 1);
+ fprintf(file, "\t\treturn 0;\n");
+ fprintf(file, "\n");
+ fprintf(file, "\treturn %s.routine[msgh_id].stub_routine;\n", ServerSubsys);
+ fprintf(file, "}\n");
+
+ /* symtab */
+
+ if (GenSymTab) {
+ fprintf(file,"\nmig_symtab_t _%sSymTab[] = {\n",SubsystemName);
+ WriteSymTabEntries(file,stats);
+ fprintf(file,"};\n");
+ fprintf(file,"int _%sSymTabBase = %d;\n",SubsystemName,SubsystemBase);
+ fprintf(file,"int _%sSymTabEnd = %d;\n",SubsystemName,SubsystemBase+rtNumber);
+ }
+}
+
+/*
+ * Returns the return type of the server-side work function.
+ * Suitable for "extern %s serverfunc()".
+ */
+#if 0
+static const char *
+ServerSideType(rt)
+ routine_t *rt;
+{
+ return rt->rtRetCode->argType->itTransType;
+}
+#endif
+static void
+WriteRetCode(file, ret)
+ FILE *file;
+ register argument_t *ret;
+{
+ register ipc_type_t *it = ret->argType;
+
+ if (akCheck(ret->argKind, akbVarNeeded)) {
+ fprintf(file, "\t%s %s;\n", it->itTransType, ret->argVarName);
+ }
+}
+
+static void
+WriteLocalVarDecl(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ register ipc_type_t *btype = it->itElement;
+
+ if (IS_VARIABLE_SIZED_UNTYPED(it))
+ fprintf(file, "\t%s %s[%d]", btype->itTransType, arg->argVarName, btype->itNumber ? it->itNumber/btype->itNumber : 0);
+ else if (IS_MULTIPLE_KPD(it)) {
+ if (btype->itTransType != strNULL)
+ fprintf(file, "\t%s %s[%d]", btype->itTransType, arg->argVarName, it->itKPD_Number);
+ else
+ /* arrays of ool or oolport */
+ fprintf(file, "\tvoid *%s[%d]", arg->argVarName, it->itKPD_Number);
+ } else
+ fprintf(file, "\t%s %s", it->itTransType, arg->argVarName);
+}
+
+#if 0
+static void
+WriteServerArgDecl(file, arg)
+ FILE *file;
+ argument_t *arg;
+{
+ fprintf(file, "%s %s%s",
+ arg->argType->itTransType,
+ arg->argByReferenceServer ? "*" : "",
+ arg->argVarName);
+}
+#endif
+/*
+ * Writes the local variable declarations which are always
+ * present: InP, OutP, the server-side work function.
+ */
+static void
+WriteVarDecls(FILE *file, routine_t *rt)
+{
+ u_int i;
+
+ fprintf(file, "\tRequest *In0P = (Request *) InHeadP;\n");
+ for (i = 1; i <= rt->rtMaxRequestPos; i++)
+ fprintf(file, "\tRequest *In%dP = NULL;\n", i);
+ fprintf(file, "\tReply *OutP = (Reply *) OutHeadP;\n");
+
+ /* if reply is variable, we may need msgh_size_delta and msgh_size */
+ if (rt->rtNumReplyVar > 1)
+ fprintf(file, "\tunsigned int msgh_size;\n");
+ if (rt->rtMaxReplyPos > 0)
+ fprintf(file, "\tunsigned int msgh_size_delta;\n");
+ if (rt->rtNumReplyVar > 1 || rt->rtMaxReplyPos > 0)
+ fprintf(file, "\n");
+
+ if (rt->rtServerImpl) {
+ fprintf(file, "\tmach_msg_max_trailer_t *TrailerP;\n");
+ fprintf(file, "#if\t__MigTypeCheck\n");
+ fprintf(file, "\tunsigned int trailer_size;\n");
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+ }
+ fprintf(file, "#ifdef\t__MIG_check__Request__%s_t__defined\n", rt->rtName);
+ fprintf(file, "\tkern_return_t check_result;\n");
+ fprintf(file, "#endif\t/* __MIG_check__Request__%s_t__defined */\n", rt->rtName);
+ fprintf(file, "\n");
+}
+
+static void
+WriteReplyInit(FILE *file, routine_t *rt)
+{
+ fprintf(file, "\n");
+ if (rt->rtNumReplyVar > 1 || rt->rtMaxReplyPos)
+ /* WritheAdjustMsgSize() has been executed at least once! */
+ fprintf(file, "\tOutP = (Reply *) OutHeadP;\n");
+
+ if (!rt->rtSimpleReply) /* complex reply message */
+ fprintf(file,
+ "\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n");
+
+ if (rt->rtNumReplyVar == 0) {
+ fprintf(file, "\tOutP->Head.msgh_size = ");
+ rtMinReplySize(file, rt, "Reply");
+ fprintf(file, ";\n");
+ } else if (rt->rtNumReplyVar > 1)
+ fprintf(file, "\tOutP->Head.msgh_size = msgh_size;\n");
+ /* the case rt->rtNumReplyVar = 1 is taken care of in WriteAdjustMsgSize() */
+}
+
+static void
+WriteRetCArgCheckError(FILE *file, routine_t *rt __unused)
+{
+ fprintf(file, "\tif (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&\n");
+ fprintf(file, "\t (In0P->Head.msgh_size == sizeof(mig_reply_error_t)))\n");
+ fprintf(file, "\t{\n");
+}
+
+static void
+WriteRetCArgFinishError(FILE *file, routine_t *rt)
+{
+ argument_t *retcode = rt->rtRetCArg;
+
+ fprintf(file, "\treturn;\n");
+ fprintf(file, "\t}\n");
+ retcode->argMsgField = "KERN_SUCCESS";
+}
+
+static void
+WriteCheckHead(FILE *file, routine_t *rt)
+{
+ fprintf(file, "#if\t__MigTypeCheck\n");
+ if (rt->rtNumRequestVar > 0)
+ fprintf(file, "\tmsgh_size = In0P->Head.msgh_size;\n");
+
+ if (rt->rtSimpleRequest) {
+ /* Expecting a simple message. */
+ fprintf(file, "\tif ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
+ if (rt->rtNumRequestVar > 0) {
+ fprintf(file, "\t (msgh_size < ");
+ rtMinRequestSize(file, rt, "__Request");
+ fprintf(file, ") || (msgh_size > (mach_msg_size_t)sizeof(__Request)))\n");
+ }
+ else
+ fprintf(file, "\t (In0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Request)))\n");
+ }
+ else {
+ /* Expecting a complex message. */
+
+ fprintf(file, "\tif (");
+ if (rt->rtRetCArg != argNULL)
+ fprintf(file, "(");
+ fprintf(file, "!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
+ fprintf(file, "\t (In0P->msgh_body.msgh_descriptor_count != %d) ||\n", rt->rtRequestKPDs);
+ if (rt->rtNumRequestVar > 0) {
+ fprintf(file, "\t (msgh_size < ");
+ rtMinRequestSize(file, rt, "__Request");
+ fprintf(file, ") || (msgh_size > (mach_msg_size_t)sizeof(__Request))");
+ }
+ else
+ fprintf(file, "\t (In0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Request))");
+ if (rt->rtRetCArg == argNULL)
+ fprintf(file, ")\n");
+ else {
+ fprintf(file, ") &&\n");
+ fprintf(file, "\t ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
+ fprintf(file, "\t In0P->Head.msgh_size != sizeof(mig_reply_error_t) ||\n");
+ fprintf(file, "\t ((mig_reply_error_t *)In0P)->RetCode == KERN_SUCCESS))\n");
+ }
+ }
+ fprintf(file, "\t\treturn MIG_BAD_ARGUMENTS;\n");
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+ fprintf(file, "\n");
+}
+
+static void
+WriteRequestNDRConvertIntRepArgCond(FILE *file, argument_t *arg)
+{
+ routine_t *rt = arg->argRoutine;
+
+ fprintf(file, "defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
+}
+
+static void
+WriteRequestNDRConvertCharRepArgCond(FILE *file, argument_t *arg)
+{
+ routine_t *rt = arg->argRoutine;
+
+ if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
+ fprintf(file, "defined(__NDR_convert__char_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
+ else
+ fprintf(file, "0");
+}
+
+static void
+WriteRequestNDRConvertFloatRepArgCond(FILE *file, argument_t *arg)
+{
+ routine_t *rt = arg->argRoutine;
+
+ if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
+ fprintf(file, "defined(__NDR_convert__float_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
+ else
+ fprintf(file, "0");
+}
+
+static void
+WriteRequestNDRConvertIntRepArgDecl(FILE *file, argument_t *arg)
+{
+ WriteNDRConvertArgDecl(file, arg, "int_rep", "Request");
+}
+
+static void
+WriteRequestNDRConvertCharRepArgDecl(FILE *file, argument_t *arg)
+{
+ if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
+ WriteNDRConvertArgDecl(file, arg, "char_rep", "Request");
+}
+
+static void
+WriteRequestNDRConvertFloatRepArgDecl(FILE *file, argument_t *arg)
+{
+ if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
+ WriteNDRConvertArgDecl(file, arg, "float_rep", "Request");
+}
+
+static void
+WriteRequestNDRConvertArgUse(FILE *file, argument_t *arg, const char *convert)
+{
+ routine_t *rt = arg->argRoutine;
+ argument_t *count = arg->argCount;
+ char argname[MAX_STR_LEN];
+
+ if ((akIdent(arg->argKind) == akeCount || akIdent(arg->argKind) == akeCountInOut) &&
+ (arg->argParent && akCheck(arg->argParent->argKind, akbSendNdr)))
+ return;
+
+ if (arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {
+ if (count && !arg->argSameCount && !strcmp(convert, "int_rep")) {
+ fprintf(file, "#if defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)\n", rt->rtName, count->argMsgField);
+ fprintf(file, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&In%dP->%s, In%dP->NDR.int_rep);\n", rt->rtName, count->argMsgField, count->argRequestPos, count->argMsgField, count->argRequestPos);
+ fprintf(file, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt->rtName, count->argMsgField);
+ }
+
+ sprintf(argname, "(%s)(In%dP->%s.address)", FetchServerType(arg->argType), arg->argRequestPos, arg->argMsgField);
+ }
+ else {
+ sprintf(argname, "&In%dP->%s", arg->argRequestPos, arg->argMsgField);
+ }
+
+ fprintf(file, "#if defined(__NDR_convert__%s__Request__%s_t__%s__defined)\n", convert, rt->rtName, arg->argMsgField);
+ fprintf(file, "\t\t__NDR_convert__%s__Request__%s_t__%s(%s, In0P->NDR.%s", convert, rt->rtName, arg->argMsgField, argname, convert);
+ if (count)
+ fprintf(file, ", In%dP->%s", count->argRequestPos, count->argMsgField);
+ fprintf(file, ");\n");
+ fprintf(file, "#endif\t/* __NDR_convert__%s__Request__%s_t__%s__defined */\n", convert, rt->rtName, arg->argMsgField);
+}
+
+static void
+WriteRequestNDRConvertIntRepOneArgUse(FILE *file, argument_t *arg)
+{
+ routine_t *rt = arg->argRoutine;
+
+ fprintf(file, "#if defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)\n", rt->rtName, arg->argMsgField);
+ fprintf(file, "\tif (In0P->NDR.int_rep != NDR_record.int_rep)\n");
+ fprintf(file, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&In%dP->%s, In%dP->NDR.int_rep);\n", rt->rtName, arg->argMsgField, arg->argRequestPos, arg->argMsgField, arg->argRequestPos);
+ fprintf(file, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt->rtName, arg->argMsgField);
+}
+
+static void
+WriteRequestNDRConvertIntRepArgUse(FILE *file, argument_t *arg)
+{
+ WriteRequestNDRConvertArgUse(file, arg, "int_rep");
+}
+
+static void
+WriteRequestNDRConvertCharRepArgUse(FILE *file, argument_t *arg)
+{
+ if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
+ WriteRequestNDRConvertArgUse(file, arg, "char_rep");
+}
+
+static void
+WriteRequestNDRConvertFloatRepArgUse(FILE *file, argument_t *arg)
+{
+ if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
+ WriteRequestNDRConvertArgUse(file, arg, "float_rep");
+}
+
+static void
+WriteCalcArgSize(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *ptype = arg->argType;
+
+ if (PackMsg == FALSE) {
+ fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize);
+ return;
+ }
+
+ if (IS_OPTIONAL_NATIVE(ptype))
+ fprintf(file, "(In%dP->__Present__%s ? _WALIGNSZ_(%s) : 0)" ,
+ arg->argRequestPos, arg->argMsgField, ptype->itServerType);
+ else
+ {
+ register ipc_type_t *btype = ptype->itElement;
+ argument_t *count = arg->argCount;
+ int multiplier = btype->itTypeSize;
+
+ if (btype->itTypeSize % itWordAlign != 0)
+ fprintf(file, "_WALIGN_");
+ fprintf(file, "(");
+
+ if (multiplier > 1)
+ fprintf(file, "%d * ", multiplier);
+ fprintf(file, "In%dP->%s", count->argRequestPos, count->argMsgField);
+ fprintf(file, ")");
+ }
+}
+
+static void
+WriteCheckArgSize(FILE *file, routine_t *rt, argument_t *arg, const char *comparator)
+{
+ register ipc_type_t *ptype = arg->argType;
+
+
+ fprintf(file, "\tif (((msgh_size - ");
+ rtMinRequestSize(file, rt, "__Request");
+ fprintf(file, ") ");
+ if (PackMsg == FALSE) {
+ fprintf(file, "%s %d)", comparator, ptype->itTypeSize + ptype->itPadSize);
+ } else if (IS_OPTIONAL_NATIVE(ptype)) {
+ fprintf(file, "%s (In%dP->__Present__%s ? _WALIGNSZ_(%s) : 0))" , comparator, arg->argRequestPos, arg->argMsgField, ptype->itServerType);
+ } else {
+ register ipc_type_t *btype = ptype->itElement;
+ argument_t *count = arg->argCount;
+ int multiplier = btype->itTypeSize;
+
+ if (multiplier > 1)
+ fprintf(file, "/ %d ", multiplier);
+ fprintf(file, "< In%dP->%s) ||\n", count->argRequestPos, count->argMsgField);
+ fprintf(file, "\t (msgh_size %s ", comparator);
+ rtMinRequestSize(file, rt, "__Request");
+ fprintf(file, " + ");
+ WriteCalcArgSize(file, arg);
+ fprintf(file, ")");
+ }
+ fprintf(file, ")\n\t\treturn MIG_BAD_ARGUMENTS;\n");
+}
+
+static void
+WriteCheckMsgSize(FILE *file, register argument_t *arg)
+{
+ register routine_t *rt = arg->argRoutine;
+
+ if (arg->argCount && !arg->argSameCount)
+ WriteRequestNDRConvertIntRepOneArgUse(file, arg->argCount);
+ if (arg->argRequestPos == rt->rtMaxRequestPos) {
+ fprintf(file, "#if\t__MigTypeCheck\n");
+
+ /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */
+ fprintf(file, "\t" "if ( In%dP->%s > %d )\n", arg->argCount->argRequestPos, arg->argCount->argMsgField, arg->argType->itNumber);
+ fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file);
+ /* ...end... */
+
+ WriteCheckArgSize(file, rt, arg, "!=");
+
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+ }
+ else {
+ /* If there aren't any more variable-sized arguments after this,
+ then we must check for exact msg-size and we don't need to
+ update msgh_size. */
+
+ boolean_t LastVarArg = arg->argRequestPos+1 == rt->rtNumRequestVar;
+
+ /* calculate the actual size in bytes of the data field. note
+ that this quantity must be a multiple of four. hence, if
+ the base type size isn't a multiple of four, we have to
+ round up. note also that btype->itNumber must
+ divide btype->itTypeSize (see itCalculateSizeInfo). */
+
+ fprintf(file, "\tmsgh_size_delta = ");
+ WriteCalcArgSize(file, arg);
+ fprintf(file, ";\n");
+ fprintf(file, "#if\t__MigTypeCheck\n");
+
+ /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */
+ fprintf(file, "\t" "if ( In%dP->%s > %d )\n", arg->argCount->argRequestPos, arg->argCount->argMsgField, arg->argType->itNumber);
+ fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file);
+ /* ...end... */
+
+ /* Don't decrement msgh_size until we've checked that
+ it won't underflow. */
+ WriteCheckArgSize(file, rt, arg, LastVarArg ? "!=" : "<");
+
+ if (!LastVarArg)
+ fprintf(file, "\tmsgh_size -= msgh_size_delta;\n");
+
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+ }
+ fprintf(file, "\n");
+}
+
+static char *
+InArgMsgField(register argument_t *arg, const char *str)
+{
+ static char buffer[MAX_STR_LEN];
+ char who[20] = {0};
+
+ /*
+ * Inside the kernel, the request and reply port fields
+ * really hold ipc_port_t values, not mach_port_t values.
+ * Hence we must cast the values.
+ */
+
+ if (!(arg->argFlags & flRetCode)) {
+ if (akCheck(arg->argKind, akbServerImplicit))
+ sprintf(who, "TrailerP->");
+ else
+ sprintf(who, "In%dP->", arg->argRequestPos);
+ }
+
+#ifdef MIG_KERNEL_PORT_CONVERSION
+ if (IsKernelServer &&
+ ((akIdent(arg->argKind) == akeRequestPort) ||
+ (akIdent(arg->argKind) == akeReplyPort)))
+ sprintf(buffer, "(ipc_port_t) %s%s%s", who, str, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField);
+ else
+#endif
+ sprintf(buffer, "%s%s%s", who, str, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField);
+
+ return buffer;
+}
+
+static void
+WriteExtractArgValue(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ string_t recast;
+
+#ifdef MIG_KERNEL_PORT_CONVERSION
+ if (IsKernelServer && it->itPortType && streql(it->itServerType, "ipc_port_t")
+ && akIdent(arg->argKind) != akeRequestPort
+ && akIdent(arg->argKind) != akeReplyPort)
+ recast = "(mach_port_t)";
+ else
+#endif
+ recast = "";
+ if (it->itInTrans != strNULL)
+ WriteCopyType(file, it, "%s", "/* %s */ %s(%s%s)", arg->argVarName, it->itInTrans, recast, InArgMsgField(arg, ""));
+ else
+ WriteCopyType(file, it, "%s", "/* %s */ %s%s", arg->argVarName, recast, InArgMsgField(arg, ""));
+
+ fprintf(file, "\n");
+}
+
+/*
+ * argKPD_Extract discipline for Port types.
+ */
+static void
+WriteExtractKPD_port(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *recast = "";
+
+ WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE);
+ /* translation function do not apply to complex types */
+#ifdef MIG_KERNEL_PORT_CONVERSION
+ if (IsKernelServer)
+ recast = "(mach_port_t)";
+#endif
+ fprintf(file, "\t\t%s[i] = %sptr->name;\n", arg->argVarName, recast);
+ fprintf(file, "\t}\n");
+}
+
+/*
+ * argKPD_Extract discipline for out-of-line types.
+ */
+static void
+WriteExtractKPD_ool(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+
+ WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE);
+ fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName);
+ fprintf(file, "\t}\n");
+}
+
+/*
+ * argKPD_Extract discipline for out-of-line Port types.
+ */
+static void
+WriteExtractKPD_oolport(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+
+ WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE);
+ fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName);
+ fprintf(file, "\t}\n");
+ if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendRcv)) {
+ register argument_t *poly = arg->argPoly;
+ register const char *pref = poly->argByReferenceServer ? "*" : "";
+
+ fprintf(file, "\t%s%s = In%dP->%s[0].disposition;\n",
+ pref, poly->argVarName, arg->argRequestPos, arg->argMsgField);
+ }
+}
+
+static void
+WriteInitializeCount(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *ptype = arg->argParent->argType;
+ register ipc_type_t *btype = ptype->itElement;
+ identifier_t newstr;
+
+ /*
+ * Initialize 'count' argument for variable-length inline OUT parameter
+ * with maximum allowed number of elements.
+ */
+
+ if (akCheck(arg->argKind, akbVarNeeded))
+ newstr = arg->argMsgField;
+ else
+ newstr = (identifier_t)strconcat("OutP->", arg->argMsgField);
+
+ fprintf(file, "\t%s = ", newstr);
+ if (IS_MULTIPLE_KPD(ptype))
+ fprintf(file, "%d;\n", ptype->itKPD_Number);
+ else
+ fprintf(file, "%d;\n", btype->itNumber? ptype->itNumber/btype->itNumber : 0);
+
+ /*
+ * If the user passed in a count, then we use the minimum.
+ * We can't let the user completely override our maximum,
+ * or the user might convince the server to overwrite the buffer.
+ */
+
+ if (arg->argCInOut != argNULL) {
+ const char *msgfield = InArgMsgField(arg->argCInOut, "");
+
+ fprintf(file, "\tif (%s < %s)\n", msgfield, newstr);
+ fprintf(file, "\t\t%s = %s;\n", newstr, msgfield);
+ }
+
+ fprintf(file, "\n");
+}
+
+static void
+WriteAdjustRequestMsgPtr(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *ptype = arg->argType;
+
+ if (PackMsg == FALSE) {
+ fprintf(file, "\t*In%dPP = In%dP = (__Request *) ((pointer_t) In%dP);\n\n", arg->argRequestPos+1, arg->argRequestPos+1, arg->argRequestPos);
+ return;
+ }
+
+ fprintf(file, "\t*In%dPP = In%dP = (__Request *) ((pointer_t) In%dP + msgh_size_delta - ", arg->argRequestPos+1, arg->argRequestPos+1, arg->argRequestPos);
+ if (IS_OPTIONAL_NATIVE(ptype))
+ fprintf(file, "_WALIGNSZ_(%s)", ptype->itUserType);
+ else
+ fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize);
+ fprintf(file, ");\n\n");
+}
+
+static void
+WriteCheckRequestTrailerArgs(FILE *file, routine_t *rt)
+{
+ register argument_t *arg;
+
+ if (rt->rtServerImpl)
+ WriteCheckTrailerHead(file, rt, FALSE);
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ if (akCheck(arg->argKind, akbServerImplicit))
+ WriteCheckTrailerSize(file, FALSE, arg);
+ }
+}
+
+static void
+WriteExtractArg(FILE *file, register argument_t *arg)
+{
+ if (akCheckAll(arg->argKind, akbSendRcv|akbVarNeeded)) {
+ if (akCheck(arg->argKind, akbSendKPD))
+ (*arg->argKPD_Extract)(file, arg);
+ else
+ WriteExtractArgValue(file, arg);
+ }
+
+ if ((akIdent(arg->argKind) == akeCount) &&
+ akCheck(arg->argKind, akbReturnSnd)) {
+
+ register ipc_type_t *ptype = arg->argParent->argType;
+ /*
+ * the count will be initialized to 0 in the case of
+ * unbounded arrays (MigInLine = TRUE): this is because
+ * the old interface used to pass to the target procedure
+ * the maximum in-line size (it was 2048 bytes)
+ */
+ if (IS_VARIABLE_SIZED_UNTYPED(ptype) ||
+ IS_MIG_INLINE_EMUL(ptype) ||
+ (IS_MULTIPLE_KPD(ptype) && ptype->itVarArray))
+ WriteInitializeCount(file, arg);
+ }
+}
+
+static void
+WriteServerCallArg(FILE *file, register argument_t *arg)
+{
+ ipc_type_t *it = arg->argType;
+ boolean_t NeedClose = FALSE;
+ string_t at = (arg->argByReferenceServer ||
+ it->itNativePointer) ? "&" : "";
+ string_t star = (arg->argByReferenceServer) ? " *" : "";
+ string_t msgfield =
+ (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField;
+
+ if (BeVerbose)
+ fprintf(file, "\n/* begin WriteServerCallArg */\n");
+ if ((it->itInTrans != strNULL) &&
+ akCheck(arg->argKind, akbSendRcv) &&
+ !akCheck(arg->argKind, akbVarNeeded)) {
+ fprintf(file, "%s%s(", at, it->itInTrans);
+ NeedClose = TRUE;
+ }
+
+ if (akCheckAll(arg->argKind, akbVarNeeded|akbServerArg)) {
+ fprintf(file, "%s%s", at, arg->argVarName);
+ } else if (akCheckAll(arg->argKind, akbSendRcv|akbSendKPD)) {
+ if (!it->itInLine)
+ /* recast the void *, although it is not necessary */
+ fprintf(file, "(%s%s)%s(%s)", it->itTransType, star, at, InArgMsgField(arg, ""));
+ else
+#ifdef MIG_KERNEL_PORT_CONVERSION
+ if (IsKernelServer && streql(it->itServerType, "ipc_port_t"))
+ /* recast the port to the kernel internal form value */
+ fprintf(file, "(ipc_port_t%s)%s(%s)", star, at, InArgMsgField(arg, ""));
+ else
+#endif
+ {
+ fprintf(file, "%s%s", at, InArgMsgField(arg, ""));
+ }
+ }
+ else if (akCheck(arg->argKind, akbSendRcv)) {
+ if (IS_OPTIONAL_NATIVE(it)) {
+ fprintf(file, "(%s ? ", InArgMsgField(arg, "__Present__"));
+ fprintf(file, "%s%s.__Real__%s : %s)", at, InArgMsgField(arg, ""), arg->argMsgField, it->itBadValue);
+ }
+ else {
+ fprintf(file, "%s%s", at, InArgMsgField(arg, ""));
+ }
+ }
+ else if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnKPD)) {
+ if (!it->itInLine)
+ /* recast the void *, although it is not necessary */
+ fprintf(file, "(%s%s)%s(OutP->%s)", it->itTransType, star, at, msgfield);
+ else
+#ifdef MIG_KERNEL_PORT_CONVERSION
+ if (IsKernelServer && streql(it->itServerType, "ipc_port_t"))
+ /* recast the port to the kernel internal form value */
+ fprintf(file, "(mach_port_t%s)%s(OutP->%s)", star, at, msgfield);
+ else
+#endif
+ fprintf(file, "%sOutP->%s", at, msgfield);
+
+ }
+ else if (akCheck(arg->argKind, akbReturnSnd))
+ fprintf(file, "%sOutP->%s", at, msgfield);
+
+ if (NeedClose)
+ fprintf(file, ")");
+ if (BeVerbose)
+ fprintf(file, "\n/* end WriteServerCallArg */\n");
+}
+
+/*
+ * Shrunk version of WriteServerCallArg, to implement the RetCode functionality:
+ * we have received a mig_reply_error_t, therefore we want to call the target
+ * routine with all 0s except for the error code (and the implicit data).
+ * We know that we are a SimpleRoutine.
+ */
+static void
+WriteConditionalCallArg(FILE *file, register argument_t *arg)
+{
+ ipc_type_t *it = arg->argType;
+ boolean_t NeedClose = FALSE;
+
+ if (BeVerbose)
+ fprintf(file, "/* begin WriteConditionalCallArg */\n");
+ if ((it->itInTrans != strNULL) &&
+ akCheck(arg->argKind, akbSendRcv) &&
+ !akCheck(arg->argKind, akbVarNeeded))
+ {
+ fprintf(file, "%s(", it->itInTrans);
+ NeedClose = TRUE;
+ }
+
+ if (akCheck(arg->argKind, akbSendRcv)) {
+ if (akIdent(arg->argKind) == akeRequestPort ||
+ akCheck(arg->argKind, akbServerImplicit))
+ fprintf(file, "%s", InArgMsgField(arg, ""));
+ else if (akIdent(arg->argKind) == akeRetCode)
+ fprintf(file, "((mig_reply_error_t *)In0P)->RetCode");
+ else
+ fprintf(file, "(%s)(0)", it->itTransType);
+ }
+
+ if (NeedClose)
+ fprintf(file, ")");
+ if (BeVerbose)
+ fprintf(file, "/* end WriteConditionalCallArg */\n");
+}
+
+static void
+WriteDestroyArg(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+
+ /*
+ * Deallocate IN/INOUT out-of-line args if specified by "auto" flag.
+ *
+ * We also have to deallocate in the cases where the target routine
+ * is given a itInLine semantic whereas the underlying transmission
+ * was out-of-line
+ */
+ if ((argIsIn(arg) && akCheck(arg->argKind, akbSendKPD|akbReturnKPD) &&
+ arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR &&
+ (arg->argFlags & flAuto))
+ ||
+ IS_MIG_INLINE_EMUL(it)
+ ) {
+ /*
+ * Deallocate only if out-of-line.
+ */
+ argument_t *count = arg->argCount;
+ ipc_type_t *btype = it->itElement;
+ int multiplier = btype->itNumber ? btype->itSize / (8 * btype->itNumber) : 0;
+
+ if (IsKernelServer) {
+ fprintf(file, "#if __MigKernelSpecificCode\n");
+ fprintf(file, "\tvm_map_copy_discard(%s);\n", InArgMsgField(arg, ""));
+ fprintf(file, "#else\n");
+ }
+ fprintf(file, "\tmig_deallocate((vm_offset_t) %s, ", InArgMsgField(arg, ""));
+ if (it->itVarArray) {
+ if (multiplier > 1)
+ fprintf(file, "%d * ", multiplier);
+ fprintf(file, "%s);\n", InArgMsgField(count, ""));
+ } else
+ fprintf(file, "%d);\n", (it->itNumber * it->itSize + 7) / 8);
+ if (IsKernelServer) {
+ fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
+ }
+ fprintf(file, "\t%s = (void *) 0;\n", InArgMsgField(arg, ""));
+ fprintf(file, "\tIn%dP->%s.%s = (mach_msg_size_t) 0;\n", arg->argRequestPos, arg->argMsgField, (RPCPortArray(arg) ? "count" : "size"));
+ }
+ else {
+ if (akCheck(arg->argKind, akbVarNeeded))
+ fprintf(file, "\t%s(%s);\n", it->itDestructor, arg->argVarName);
+ else
+ fprintf(file, "\t%s(%s);\n", it->itDestructor, InArgMsgField(arg, ""));
+ }
+}
+
+static void
+WriteDestroyPortArg(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+
+ /*
+ * If a translated port argument occurs in the body of a request
+ * message, and the message is successfully processed, then the
+ * port right should be deallocated. However, the called function
+ * didn't see the port right; it saw the translation. So we have
+ * to release the port right for it.
+ *
+ * The test over it->itInTrans will exclude any complex type
+ * made out of ports
+ */
+ if ((it->itInTrans != strNULL) &&
+ (it->itOutName == MACH_MSG_TYPE_PORT_SEND)) {
+ fprintf(file, "\n");
+ fprintf(file, "\tif (IP_VALID((ipc_port_t)%s))\n", InArgMsgField(arg, ""));
+ fprintf(file, "\t\tipc_port_release_send((ipc_port_t)%s);\n", InArgMsgField(arg, ""));
+ }
+}
+
+/*
+ * Check whether WriteDestroyPortArg would generate any code for arg.
+ */
+static boolean_t
+CheckDestroyPortArg(argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+
+ if ((it->itInTrans != strNULL) &&
+ (it->itOutName == MACH_MSG_TYPE_PORT_SEND))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+WriteServerCall(FILE *file, routine_t *rt, void (*func)())
+{
+ argument_t *arg = rt->rtRetCode;
+ ipc_type_t *it = arg->argType;
+ boolean_t NeedClose = FALSE;
+
+ fprintf(file, "\t");
+ if (akCheck(arg->argKind, akbVarNeeded))
+ fprintf(file, "%s = ", arg->argMsgField);
+ else
+ fprintf(file, "OutP->%s = ", arg->argMsgField);
+ if (it->itOutTrans != strNULL) {
+ fprintf(file, "%s(", it->itOutTrans);
+ NeedClose = TRUE;
+ }
+ fprintf(file, "%s(", rt->rtServerName);
+ if (BeVerbose)
+ fprintf(file, "\n/* before WriteServerCall's WriteList func=%p mask=%x */\n", func, akbServerArg);
+ WriteList(file, rt->rtArgs, func, akbServerArg, ", ", "");
+ if (BeVerbose)
+ fprintf(file, "\n/* after WriteServerCall's WriteList */\n");
+ if (NeedClose)
+ fprintf(file, ")");
+ fprintf(file, ");\n");
+}
+
+static void
+WriteCheckReturnValue(FILE *file, register routine_t *rt)
+{
+ argument_t *arg = rt->rtRetCode;
+ char string[MAX_STR_LEN];
+
+ if (akCheck(arg->argKind, akbVarNeeded))
+ sprintf(string, "%s", arg->argMsgField);
+ else
+ sprintf(string, "OutP->%s", arg->argMsgField);
+ fprintf(file, "\tif (%s != KERN_SUCCESS) {\n", string);
+ fprintf(file, "\t\tMIG_RETURN_ERROR(OutP, %s);\n", string);
+ fprintf(file, "\t}\n");
+}
+
+/*
+ * WriteInitKPD_port, WriteInitKPD_ool, WriteInitKPD_oolport
+ * initializes the OutP KPD fields (this job cannot be done once
+ * the target routine has been called, otherwise informations
+ * would be lost)
+ */
+/*
+ * argKPD_Init discipline for Port types.
+ */
+static void
+WriteInitKPD_port(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *subindex = "";
+ boolean_t close = FALSE;
+ char firststring[MAX_STR_LEN];
+ char string[MAX_STR_LEN];
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE);
+ (void)sprintf(firststring, "\t*ptr");
+ (void)sprintf(string, "\tptr->");
+ subindex = "[i]";
+ close = TRUE;
+ } else {
+ (void)sprintf(firststring, "OutP->%s", arg->argMsgField);
+ (void)sprintf(string, "OutP->%s.", arg->argMsgField);
+ }
+
+ fprintf(file, "#if\tUseStaticTemplates\n");
+ fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
+ fprintf(file, "#else\t/* UseStaticTemplates */\n");
+ if (IS_MULTIPLE_KPD(it) && it->itVarArray)
+ fprintf(file, "\t%sname = MACH_PORT_NULL;\n", string);
+ if (arg->argPoly == argNULL) {
+ if (IsKernelServer) {
+ fprintf(file, "#if __MigKernelSpecificCode\n");
+ fprintf(file, "\t%sdisposition = %s;\n", string, it->itOutNameStr);
+ fprintf(file, "#else\n");
+ }
+ fprintf(file, "\t%sdisposition = %s;\n", string, it->itInNameStr);
+ if (IsKernelServer)
+ fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
+ }
+ fprintf(file, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string);
+ fprintf(file, "#endif\t/* UseStaticTemplates */\n");
+ if (close)
+ fprintf(file, "\t }\n\t}\n");
+ fprintf(file, "\n");
+}
+
+/*
+ * argKPD_Init discipline for out-of-line types.
+ */
+static void
+WriteInitKPD_ool(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ char firststring[MAX_STR_LEN];
+ char string[MAX_STR_LEN];
+ boolean_t VarArray;
+ u_int howmany, howbig;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE);
+ (void)sprintf(firststring, "\t*ptr");
+ (void)sprintf(string, "\tptr->");
+ VarArray = it->itElement->itVarArray;
+ howmany = it->itElement->itNumber;
+ howbig = it->itElement->itSize;
+ } else {
+ (void)sprintf(firststring, "OutP->%s", arg->argMsgField);
+ (void)sprintf(string, "OutP->%s.", arg->argMsgField);
+ VarArray = it->itVarArray;
+ howmany = it->itNumber;
+ howbig = it->itSize;
+ }
+
+ fprintf(file, "#if\tUseStaticTemplates\n");
+ fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
+ fprintf(file, "#else\t/* UseStaticTemplates */\n");
+ if (!VarArray)
+ fprintf(file, "\t%ssize = %d;\n", string,
+ (howmany * howbig + 7)/8);
+ if (arg->argDeallocate != d_MAYBE)
+ fprintf(file, "\t%sdeallocate = %s;\n", string,
+ (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE");
+ fprintf(file, "\t%scopy = %s;\n", string,
+ (arg->argFlags & flPhysicalCopy) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY");
+#ifdef ALIGNMENT
+ fprintf(file, "\t%salignment = MACH_MSG_ALIGN_%d;\n", string, arg->argMsgField,
+ (howbig < 8) ? 1 : howbig / 8);
+#endif
+ fprintf(file, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string);
+ fprintf(file, "#endif\t/* UseStaticTemplates */\n");
+
+ if (IS_MULTIPLE_KPD(it))
+ fprintf(file, "\t }\n\t}\n");
+ fprintf(file, "\n");
+}
+
+/*
+ * argKPD_Init discipline for out-of-line Port types.
+ */
+static void
+WriteInitKPD_oolport(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ boolean_t VarArray;
+ ipc_type_t *howit;
+ u_int howmany;
+ char firststring[MAX_STR_LEN];
+ char string[MAX_STR_LEN];
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE);
+ (void)sprintf(firststring, "\t*ptr");
+ (void)sprintf(string, "\tptr->");
+ VarArray = it->itElement->itVarArray;
+ howmany = it->itElement->itNumber;
+ howit = it->itElement;
+ } else {
+ (void)sprintf(firststring, "OutP->%s", arg->argMsgField);
+ (void)sprintf(string, "OutP->%s.", arg->argMsgField);
+ VarArray = it->itVarArray;
+ howmany = it->itNumber;
+ howit = it;
+ }
+
+ fprintf(file, "#if\tUseStaticTemplates\n");
+ fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
+ fprintf(file, "#else\t/* UseStaticTemplates */\n");
+
+ if (!VarArray)
+ fprintf(file, "\t%scount = %d;\n", string, howmany);
+ if (arg->argPoly == argNULL) {
+ if (IsKernelServer) {
+ fprintf(file, "#if\t__MigKernelSpecificCode\n");
+ fprintf(file, "\t%sdisposition = %s;\n", string, howit->itOutNameStr);
+ fprintf(file, "#else\n");
+ }
+ fprintf(file, "\t%sdisposition = %s;\n", string, howit->itInNameStr);
+ if (IsKernelServer)
+ fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
+ }
+ if (arg->argDeallocate != d_MAYBE)
+ fprintf(file, "\t%sdeallocate = %s;\n", string,
+ (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE");
+ fprintf(file, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string);
+ fprintf(file, "#endif\t/* UseStaticTemplates */\n");
+
+ if (IS_MULTIPLE_KPD(it))
+ fprintf(file, "\t }\n\t}\n");
+ fprintf(file, "\n");
+}
+
+static void
+WriteInitKPDValue(FILE *file, register argument_t *arg)
+{
+ (*arg->argKPD_Init)(file, arg);
+}
+
+static void
+WriteAdjustMsgCircular(FILE *file, register argument_t *arg)
+{
+ fprintf(file, "\n");
+
+ fprintf(file,"#if\t__MigKernelSpecificCode\n");
+ if (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
+ fprintf(file, "\tif (%s == MACH_MSG_TYPE_PORT_RECEIVE)\n",
+ arg->argPoly->argVarName);
+
+ /*
+ * The carried port right can be accessed in OutP->XXXX. Normally
+ * the server function stuffs it directly there. If it is InOut,
+ * then it has already been copied into the reply message.
+ * If the server function deposited it into a variable (perhaps
+ * because the reply message is variable-sized) then it has already
+ * been copied into the reply message.
+ *
+ * The old MiG does not check for circularity in the case of
+ * array of ports. So do I ...
+ */
+
+ fprintf(file, "\t if (IP_VALID((ipc_port_t) In0P->Head.msgh_reply_port) &&\n");
+ fprintf(file, "\t IP_VALID((ipc_port_t) OutP->%s.name) &&\n", arg->argMsgField);
+ fprintf(file, "\t ipc_port_check_circularity((ipc_port_t) OutP->%s.name, (ipc_port_t) In0P->Head.msgh_reply_port))\n", arg->argMsgField);
+ fprintf(file, "\t\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_CIRCULAR;\n");
+ fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
+}
+
+/*
+ * argKPD_Pack discipline for Port types.
+ */
+static void
+WriteKPD_port(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *subindex = "";
+ const char *recast = "";
+ boolean_t close = FALSE;
+ char string[MAX_STR_LEN];
+ ipc_type_t *real_it;
+
+ if (akCheck(arg->argKind, akbVarNeeded)) {
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE);
+ (void)sprintf(string, "\tptr->");
+ subindex = "[i]";
+ close = TRUE;
+ real_it = it->itElement;
+ } else {
+ (void)sprintf(string, "OutP->%s.", arg->argMsgField);
+ real_it = it;
+ }
+#ifdef MIG_KERNEL_PORT_CONVERSIONS
+ if (IsKernelServer && streql(real_it->itTransType, "ipc_port_t"))
+ recast = "(mach_port_t)";
+#endif
+
+ if (it->itOutTrans != strNULL && !close)
+ fprintf(file, "\t%sname = (mach_port_t)%s(%s);\n", string, it->itOutTrans, arg->argVarName);
+ else
+ fprintf(file, "\t%sname = %s%s%s;\n", string, recast, arg->argVarName, subindex);
+ if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd)) {
+ register argument_t *poly = arg->argPoly;
+
+ if (akCheck(arg->argPoly->argKind, akbVarNeeded))
+ fprintf(file, "\t%sdisposition = %s;\n", string, poly->argVarName);
+ else if (close)
+ fprintf(file, "\t%sdisposition = OutP->%s;\n", string, poly->argSuffix);
+ }
+ if (close)
+ fprintf(file, "\t }\n\t}\n");
+ fprintf(file, "\n");
+ }
+ else if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd|akbVarNeeded))
+ fprintf(file, "\tOutP->%s.disposition = %s;\n", arg->argMsgField, arg->argPoly->argVarName);
+ /*
+ * If this is a KernelServer, and the reply message contains
+ * a receive right, we must check for the possibility of a
+ * port/message circularity. If queueing the reply message
+ * would cause a circularity, we mark the reply message
+ * with the circular bit.
+ */
+ if (IsKernelServer && !(IS_MULTIPLE_KPD(it)) &&
+ ((arg->argType->itOutName == MACH_MSG_TYPE_PORT_RECEIVE) ||
+ (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC)))
+ WriteAdjustMsgCircular(file, arg);
+}
+
+/*
+ * argKPD_Pack discipline for out-of-line types.
+ */
+static void
+WriteKPD_ool(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ char string[MAX_STR_LEN];
+ boolean_t VarArray;
+ argument_t *count;
+ u_int howbig;
+ const char *subindex;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE);
+ (void)sprintf(string, "\tptr->");
+ VarArray = it->itElement->itVarArray;
+ count = arg->argSubCount;
+ howbig = it->itElement->itSize;
+ subindex = "[i]";
+ } else {
+ (void)sprintf(string, "OutP->%s.", arg->argMsgField);
+ VarArray = it->itVarArray;
+ count = arg->argCount;
+ howbig = it->itSize;
+ subindex = "";
+ }
+
+ if (akCheck(arg->argKind, akbVarNeeded))
+ fprintf(file, "\t%saddress = (void *)%s%s;\n", string,
+ arg->argMsgField, subindex);
+ if (arg->argDealloc != argNULL)
+ if (akCheck(arg->argDealloc->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it))
+ fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName);
+ if (VarArray) {
+ fprintf(file, "\t%ssize = ", string);
+ if (akCheck(count->argKind, akbVarNeeded))
+ fprintf(file, "%s%s", count->argName, subindex);
+ else
+ fprintf(file, "OutP->%s%s", count->argMsgField, subindex);
+
+ if (count->argMultiplier > 1 || howbig > 8)
+ fprintf(file, " * %d;\n", count->argMultiplier * howbig / 8);
+ else
+ fprintf(file, ";\n");
+ }
+
+ if (IS_MULTIPLE_KPD(it)) {
+ fprintf(file, "\t }\n");
+ if (it->itVarArray && !it->itElement->itVarArray) {
+ fprintf(file, "\t for (i = j; i < %d; ptr++, i++)\n", it->itKPD_Number);
+ /* since subordinate arrays aren't variable, they are initialized from template:
+ here we must no-op 'em */
+ fprintf(file, "\t\tptr->size = 0;\n");
+ }
+ fprintf(file, "\t}\n");
+ }
+ fprintf(file, "\n");
+}
+
+/*
+ * argKPD_Pack discipline for out-of-line Port types.
+ */
+static void
+WriteKPD_oolport(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ boolean_t VarArray;
+ argument_t *count;
+ const char *subindex;
+ char string[MAX_STR_LEN];
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE);
+ (void)sprintf(string, "\tptr->");
+ VarArray = it->itElement->itVarArray;
+ count = arg->argSubCount;
+ subindex = "[i]";
+ } else {
+ (void)sprintf(string, "OutP->%s.", arg->argMsgField);
+ VarArray = it->itVarArray;
+ count = arg->argCount;
+ subindex = "";
+ }
+
+ if (akCheck(arg->argKind, akbVarNeeded))
+ fprintf(file, "\t%saddress = (void *)%s%s;\n", string,
+ arg->argMsgField, subindex);
+ if (arg->argDealloc != argNULL)
+ if (akCheck(arg->argDealloc->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it))
+ fprintf(file, "\t%sdeallocate = %s;\n", string,
+ arg->argDealloc->argVarName);
+ if (VarArray) {
+ fprintf(file, "\t%scount = ", string);
+ if (akCheck(count->argKind, akbVarNeeded))
+ fprintf(file, "%s%s;\n", count->argName, subindex);
+ else
+ fprintf(file, "OutP->%s%s;\n", count->argMsgField, subindex);
+ }
+ if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd))
+ if (akCheck(arg->argPoly->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it))
+ fprintf(file, "\t%sdisposition = %s;\n", string,
+ arg->argPoly->argVarName);
+ if (IS_MULTIPLE_KPD(it)) {
+ fprintf(file, "\t }\n");
+ if (it->itVarArray && !it->itElement->itVarArray) {
+ fprintf(file, "\t for (i = j; i < %d; ptr++, i++)\n", it->itKPD_Number);
+ /* since subordinate arrays aren't variable, they are initialized from template:
+ here we must no-op 'em */
+ fprintf(file, "\t%scount = 0;\n", string);
+ }
+ fprintf(file, "\t}\n");
+ }
+ fprintf(file, "\n");
+}
+
+/*
+ * argKPD_TypeCheck discipline for Port types.
+ */
+static void
+WriteTCheckKPD_port(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *tab = "";
+ char string[MAX_STR_LEN];
+ boolean_t close = FALSE;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE);
+ (void)sprintf(string, "ptr->");
+ tab = "\t";
+ close = TRUE;
+ } else
+ (void)sprintf(string, "In%dP->%s.", arg->argRequestPos, arg->argMsgField);
+
+ fprintf(file, "\t%sif (%stype != MACH_MSG_PORT_DESCRIPTOR", tab, string);
+ /*
+ * We can't check disposition on varArray
+ * (because some of the entries could be empty).
+ */
+ if (!it->itVarArray) {
+ if (arg->argPoly != argNULL) {
+ switch (it->itOutName) {
+
+ case MACH_MSG_TYPE_MOVE_RECEIVE:
+ fprintf(file, " || \n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_RECEIVE", tab, string);
+ break;
+
+ case MACH_MSG_TYPE_MOVE_SEND_ONCE:
+ fprintf(file, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND_ONCE", tab, string);
+ fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND_ONCE)", tab, string);
+ break;
+
+ case MACH_MSG_TYPE_MOVE_SEND:
+ fprintf(file, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND", tab, string);
+ fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND", tab, string);
+ fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_COPY_SEND)", tab, string);
+ break;
+ }
+ }
+ else {
+ fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, it->itOutNameStr);
+ }
+ }
+ fprintf(file, ")\n");
+ fprintf(file, "\t\treturn MIG_TYPE_ERROR;\n");
+ if (close)
+ fprintf(file, "\t }\n\t}\n");
+}
+
+/*
+ * argKPD_TypeCheck discipline for out-of-line types.
+ */
+static void
+WriteTCheckKPD_ool(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *tab;
+ char string[MAX_STR_LEN];
+ boolean_t test;
+ u_int howmany, howbig;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE);
+ tab = "\t\t\t";
+ sprintf(string, "ptr->");
+ howmany = it->itElement->itNumber;
+ howbig = it->itElement->itSize;
+ test = !it->itVarArray && !it->itElement->itVarArray;
+ } else {
+ tab = "";
+ sprintf(string, "In%dP->%s.", arg->argRequestPos, arg->argMsgField);
+ howmany = it->itNumber;
+ howbig = it->itSize;
+ test = !it->itVarArray;
+ }
+
+ fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_DESCRIPTOR", tab, string);
+ if (test)
+ /* if VarArray we may use no-op; if itElement->itVarArray size might change */
+ fprintf(file, " ||\n\t%s %ssize != %d", tab, string,
+ (howmany * howbig + 7)/8);
+ fprintf(file, ")\n");
+ fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab);
+
+ if (IS_MULTIPLE_KPD(it))
+ fprintf(file, "\t }\n\t}\n");
+}
+
+/*
+ * argKPD_TypeCheck discipline for out-of-line Port types.
+ */
+static void
+WriteTCheckKPD_oolport(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *tab;
+ char string[MAX_STR_LEN];
+ boolean_t test;
+ u_int howmany;
+ const char *howstr;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE);
+ tab = "\t";
+ sprintf(string, "ptr->");
+ howmany = it->itElement->itNumber;
+ test = !it->itVarArray && !it->itElement->itVarArray;
+ howstr = it->itElement->itOutNameStr;
+ } else {
+ tab = "";
+ sprintf(string, "In%dP->%s.", arg->argRequestPos, arg->argMsgField);
+ howmany = it->itNumber;
+ test = !it->itVarArray;
+ howstr = it->itOutNameStr;
+ }
+
+ fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_PORTS_DESCRIPTOR", tab, string);
+ if (test)
+ /* if VarArray we may use no-op; if itElement->itVarArray size might change */
+ fprintf(file, " ||\n\t%s %scount != %d", tab, string,
+ howmany);
+ if (arg->argPoly == argNULL)
+ fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string,
+ howstr);
+ fprintf(file, ")\n");
+ fprintf(file, "\t\treturn MIG_TYPE_ERROR;\n");
+
+ if (IS_MULTIPLE_KPD(it))
+ fprintf(file, "\t }\n\t}\n");
+}
+
+/*************************************************************
+ * Writes code to check that the type of each of the arguments
+ * in the reply message is what is expected. Called by
+ * WriteRoutine for each in && typed argument in the request message.
+ *************************************************************/
+static void
+WriteTypeCheck(FILE *file, register argument_t *arg)
+{
+ fprintf(file, "#if\t__MigTypeCheck\n");
+ (*arg->argKPD_TypeCheck)(file, arg);
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+}
+
+static void
+WritePackArgValueNormal(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+
+ if (IS_VARIABLE_SIZED_UNTYPED(it) || it->itNoOptArray) {
+ if (it->itString) {
+ /*
+ * Copy variable-size C string with mig_strncpy.
+ * Save the string length (+ 1 for trailing 0)
+ * in the argument`s count field.
+ */
+ fprintf(file, "\tOutP->%s = mig_strncpy(OutP->%s, %s, %d);\n", arg->argCount->argMsgField, arg->argMsgField, arg->argVarName, it->itNumber);
+ }
+ else if (it->itNoOptArray)
+ fprintf(file, "\t(void)memcpy((char *) OutP->%s, (const char *) %s, %d);\n", arg->argMsgField, arg->argVarName, it->itTypeSize);
+ else {
+ register argument_t *count = arg->argCount;
+ register ipc_type_t *btype = it->itElement;
+ identifier_t newstr;
+
+ /* Note btype->itNumber == count->argMultiplier */
+
+ fprintf(file, "\t(void)memcpy((char *) OutP->%s, (const char *) %s, ", arg->argMsgField, arg->argVarName);
+ if (btype->itTypeSize > 1)
+ fprintf(file, "%d * ", btype->itTypeSize);
+ /* count is a akbVarNeeded if arg is akbVarNeeded */
+ if (akCheck(count->argKind, akbVarNeeded))
+ newstr = count->argVarName;
+ else
+ newstr = (identifier_t)strconcat("OutP->", count->argMsgField);
+ fprintf(file, "%s);\n", newstr);
+ }
+ }
+ else if (it->itOutTrans != strNULL)
+ WriteCopyType(file, it, "OutP->%s", "/* %s */ %s(%s)", arg->argMsgField, it->itOutTrans, arg->argVarName);
+ else
+ WriteCopyType(file, it, "OutP->%s", "/* %s */ %s", arg->argMsgField, arg->argVarName);
+}
+
+static void
+WritePackArgValueVariable(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+
+ /*
+ * only itString are treated here so far
+ */
+ if (it->itString) {
+ /*
+ * Emit logic to call strlen to calculate the size of the argument, and ensure that it fits within the 32-bit result field
+ * in the Reply, when targeting a 64-bit architecture. If a 32-bit architecture is the target, we emit code to just call
+ * strlen() directly (since it'll return a 32-bit value that is guaranteed to fit).
+ */
+ fputs("#ifdef __LP64__\n", file);
+ fprintf(file, "\t{\n"
+ "\t\t" "size_t strLength = strlen(OutP->%s) + 1;\n", arg->argMsgField);
+ fputs( "\t\t" "if (strLength > 0xffffffff)\n"
+ "\t\t\t" "MIG_RETURN_ERROR(OutP, MIG_BAD_ARGUMENTS);\n", file);
+ fprintf(file, "\t\t" "OutP->%s = (mach_msg_type_number_t) strLength;\n"
+ "\t}\n", arg->argCount->argMsgField);
+ fputs("#else\n", file);
+ fprintf(file, "\tOutP->%s = (mach_msg_type_number_t) strlen(OutP->%s) + 1;\n", arg->argCount->argMsgField, arg->argMsgField);
+ fputs("#endif /* __LP64__ */\n", file);
+
+ }
+}
+
+static void
+WriteCopyArgValue(FILE *file, argument_t *arg)
+{
+ fprintf(file, "\n");
+ WriteCopyType(file, arg->argType, "/* %d */ OutP->%s", "In%dP->%s", arg->argRequestPos, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField);
+}
+
+static void
+WriteInitArgValue(FILE *file, argument_t *arg)
+{
+ fprintf(file, "\n");
+ fprintf(file, "\tOutP->%s = %s;\n\n", arg->argMsgField, arg->argVarName);
+}
+
+/*
+ * Calculate the size of a variable-length message field.
+ */
+static void
+WriteArgSize(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *ptype = arg->argType;
+ register int bsize = ptype->itElement->itTypeSize;
+ register argument_t *count = arg->argCount;
+
+ /* If the base type size of the data field isn`t a multiple of 4,
+ we have to round up. */
+ if (bsize % itWordAlign != 0)
+ fprintf(file, "_WALIGN_");
+
+ /* Here, we generate ((value + %d) & ~%d). We have to put two (( at the
+ * the beginning.
+ */
+ fprintf(file, "((");
+ if (bsize > 1)
+ fprintf(file, "%d * ", bsize);
+ if (ptype->itString || !akCheck(count->argKind, akbVarNeeded))
+ /* get count from descriptor in message */
+ fprintf(file, "OutP->%s", count->argMsgField);
+ else
+ /* get count from argument */
+ fprintf(file, "%s", count->argVarName);
+
+ /*
+ * If the base type size is not a multiple of sizeof(natural_t),
+ * we have to round up.
+ */
+ if (bsize % sizeof(natural_t) != 0)
+ fprintf(file, " + %ld) & ~%ld)", sizeof(natural_t)-1, sizeof(natural_t)-1);
+ else
+ fprintf(file, "))");
+}
+
+/*
+ * Adjust message size and advance reply pointer.
+ * Called after packing a variable-length argument that
+ * has more arguments following.
+ */
+static void
+WriteAdjustMsgSize(FILE *file, register argument_t *arg)
+{
+ register routine_t *rt = arg->argRoutine;
+ register ipc_type_t *ptype = arg->argType;
+
+ /* There are more Out arguments. We need to adjust msgh_size
+ and advance OutP, so we save the size of the current field
+ in msgh_size_delta. */
+
+ fprintf(file, "\tmsgh_size_delta = ");
+ WriteArgSize(file, arg);
+ fprintf(file, ";\n");
+
+ if (rt->rtNumReplyVar == 1) {
+ /* We can still address the message header directly. Fill
+ in the size field. */
+
+ fprintf(file, "\tOutP->Head.msgh_size = ");
+ rtMinReplySize(file, rt, "Reply");
+ fprintf(file, " + msgh_size_delta;\n");
+ } else if (arg->argReplyPos == 0) {
+ /* First variable-length argument. The previous msgh_size value
+ is the minimum reply size. */
+
+ fprintf(file, "\tmsgh_size = ");
+ rtMinReplySize(file, rt, "Reply");
+ fprintf(file, " + msgh_size_delta;\n");
+ } else
+ fprintf(file, "\tmsgh_size += msgh_size_delta;\n");
+
+ fprintf(file,
+ "\tOutP = (Reply *) ((pointer_t) OutP + msgh_size_delta - %d);\n",
+ ptype->itTypeSize + ptype->itPadSize);
+}
+
+/*
+ * Calculate the size of the message. Called after the
+ * last argument has been packed.
+ */
+static void
+WriteFinishMsgSize(FILE *file, register argument_t *arg)
+{
+ /* No more Out arguments. If this is the only variable Out
+ argument, we can assign to msgh_size directly. */
+
+ if (arg->argReplyPos == 0) {
+ fprintf(file, "\tOutP->Head.msgh_size = ");
+ rtMinReplySize(file, arg->argRoutine, "Reply");
+ fprintf(file, " + (");
+ WriteArgSize(file, arg);
+ fprintf(file, ");\n");
+ }
+ else {
+ fprintf(file, "\tmsgh_size += ");
+ WriteArgSize(file, arg);
+ fprintf(file, ";\n");
+ }
+}
+
+/*
+ * Handle reply arguments - fill in message types and copy arguments
+ * that need to be copied.
+ */
+static void
+WriteReplyArgs(FILE *file, register routine_t *rt)
+{
+ register argument_t *arg;
+ register argument_t *lastVarArg;
+
+ /*
+ * 1. The Kernel Processed Data
+ */
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
+ if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnKPD))
+ (*arg->argKPD_Pack)(file, arg);
+ /*
+ * 2. The Data Stream
+ */
+ lastVarArg = argNULL;
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ /*
+ * Adjust message size and advance message pointer if
+ * the last request argument was variable-length and the
+ * request position will change.
+ */
+ if (lastVarArg != argNULL &&
+ lastVarArg->argReplyPos < arg->argReplyPos) {
+ WriteAdjustMsgSize(file, lastVarArg);
+ lastVarArg = argNULL;
+ }
+
+ if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVarNeeded))
+ WritePackArgValueNormal(file, arg);
+ else if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVariable))
+ WritePackArgValueVariable(file, arg);
+
+ if (akCheck(arg->argKind, akbReplyCopy))
+ WriteCopyArgValue(file, arg);
+ if (akCheck(arg->argKind, akbReplyInit))
+ WriteInitArgValue(file, arg);
+ /*
+ * Remember whether this was variable-length.
+ */
+ if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVariable))
+ lastVarArg = arg;
+ }
+ /*
+ * Finish the message size.
+ */
+ if (lastVarArg != argNULL)
+ WriteFinishMsgSize(file, lastVarArg);
+}
+
+static void
+WriteFieldDecl(FILE *file, argument_t *arg)
+{
+ if (akCheck(arg->argKind, akbSendKPD) ||
+ akCheck(arg->argKind, akbReturnKPD))
+ WriteFieldDeclPrim(file, arg, FetchKPDType);
+ else
+ WriteFieldDeclPrim(file, arg, FetchServerType);
+}
+
+static void
+InitKPD_Disciplines(argument_t *args)
+{
+ argument_t *arg;
+ extern void KPD_noop();
+ extern void KPD_error();
+ extern void WriteTemplateKPD_port();
+ extern void WriteTemplateKPD_ool();
+ extern void WriteTemplateKPD_oolport();
+
+ /*
+ * WriteInitKPD_port, WriteKPD_port, WriteExtractKPD_port,
+ * WriteInitKPD_ool, WriteKPD_ool, WriteExtractKPD_ool,
+ * WriteInitKPD_oolport, WriteKPD_oolport, WriteExtractKPD_oolport
+ * are local to this module (which is the reason why this initialization
+ * takes place here rather than in utils.c).
+ * Common routines for user and server will be established SOON, and
+ * all of them (including the initialization) will be transfert to
+ * utils.c
+ * All the KPD disciplines are defaulted to be KPD_error().
+ * Note that akbSendKPD and akbReturnKPd are not exclusive,
+ * because of inout type of parameters.
+ */
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD))
+ switch (arg->argKPD_Type) {
+
+ case MACH_MSG_PORT_DESCRIPTOR:
+ if akCheck(arg->argKind, akbSendKPD) {
+ arg->argKPD_Extract =
+ (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_port : WriteExtractArgValue;
+ arg->argKPD_TypeCheck = WriteTCheckKPD_port;
+ }
+ if akCheck(arg->argKind, akbReturnKPD) {
+ arg->argKPD_Template = WriteTemplateKPD_port;
+ arg->argKPD_Init = WriteInitKPD_port;
+ arg->argKPD_Pack = WriteKPD_port;
+ }
+ break;
+
+ case MACH_MSG_OOL_DESCRIPTOR:
+ if akCheck(arg->argKind, akbSendKPD) {
+ arg->argKPD_Extract =
+ (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_ool : WriteExtractArgValue;
+ arg->argKPD_TypeCheck = WriteTCheckKPD_ool;
+ }
+ if akCheck(arg->argKind, akbReturnKPD) {
+ arg->argKPD_Template = WriteTemplateKPD_ool;
+ arg->argKPD_Init = WriteInitKPD_ool;
+ arg->argKPD_Pack = WriteKPD_ool;
+ }
+ break;
+
+ case MACH_MSG_OOL_PORTS_DESCRIPTOR:
+ if akCheck(arg->argKind, akbSendKPD) {
+ arg->argKPD_Extract =
+ (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_oolport : WriteExtractArgValue;
+ arg->argKPD_TypeCheck = WriteTCheckKPD_oolport;
+ }
+ if akCheck(arg->argKind, akbReturnKPD) {
+ arg->argKPD_Template = WriteTemplateKPD_oolport;
+ arg->argKPD_Init = WriteInitKPD_oolport;
+ arg->argKPD_Pack = WriteKPD_oolport;
+ }
+ break;
+
+ default:
+ printf("MiG internal error: type of kernel processed data unknown\n");
+ exit(1);
+ } /* end of switch */
+}
+
+static void WriteStringTerminatorCheck(FILE *file, routine_t *rt)
+{
+ // generate code to verify that the length of a C string is not greater than the size of the
+ // buffer in which it is stored.
+ argument_t *argPtr;
+ int msg_limit_calculated = FALSE;
+ int found_string_argument = FALSE;
+ int variable_length_args_present = (rt->rtMaxRequestPos > 0);
+
+ // scan through arguments to see if there are any strings
+ for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) {
+ if ((argPtr->argKind & akbRequest) && argPtr->argType->itString) {
+ found_string_argument = TRUE;
+ break;
+ }
+ }
+
+ if (found_string_argument) {
+ // create a new scope, for local variables
+ fputs("#if __MigTypeCheck\n" "\t" "{" "\n", file);
+
+ for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) {
+ if ((argPtr->argKind & akbRequest) && argPtr->argType->itString) {
+ //fprintf(stderr, "### found itString: variable name = %s, max length = %d\n", argPtr->argName, argPtr->argType->itNumber);
+
+ if (!msg_limit_calculated) {
+ msg_limit_calculated = TRUE; // only need to do this once
+ fputs("\t\t" "char * msg_limit = ((char *) In0P) + In0P->Head.msgh_size;\n", file);
+ if (IsKernelServer) {
+ fputs("#if __MigKernelSpecificCode\n", file);
+ fputs("\t\t" "size_t strnlen_limit;" "\n", file);
+ fputs("#else\n", file);
+ }
+ fputs("\t\t" "size_t memchr_limit;" "\n", file);
+ if (IsKernelServer) {
+ fputs("#endif /* __MigKernelSpecificCode */" "\n", file);
+ }
+ fputc('\n', file);
+ }
+
+ // I would really prefer to use strnlen() here, to ensure that the byte scanning logic does not extend beyond
+ // the end of the buffer, but it's not necessarily guaranteed to be available. Instead, I'll use memchr(),
+ // and let it look for the terminating null byte.
+ // (later...)
+ // It turns out that the kernel does not have memchr() available, but strnlen() IS available, so we'll just
+ // have to emit some conditional code to use the appropriate runtime environment scanning function.
+ //
+ if (IsKernelServer) {
+ fputs("#if __MigKernelSpecificCode\n", file);
+ fputs("\t\t" "strnlen_limit = min((msg_limit - ", file);
+ // If there are variable-length arguments within the message, the proper (adjusted)
+ // pointers must be used to access those strings
+ fprintf(file, "In%dP->%s), %d);" "\n", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName, argPtr->argType->itNumber);
+ fputs("\t\t" "if (", file);
+ fprintf(file, "( strnlen(In%dP->%s, strnlen_limit) >= %d + 1 )", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName, argPtr->argType->itNumber);
+ fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file);
+ fputs("#else\n", file);
+ }
+ // If there are variable-length arguments within the message, the proper (adjusted)
+ // pointers must be used to access those strings
+ fprintf(file, "\t\t" "memchr_limit = min((msg_limit - In%dP->%s), %d);" "\n", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName, argPtr->argType->itNumber);
+ fputs("\t\t" "if (", file);
+ fprintf(file, "( memchr(In%dP->%s, '\\0', memchr_limit) == NULL )", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName);
+ fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file);
+ if (IsKernelServer) {
+ fputs("#endif /* __MigKernelSpecificCode */" "\n", file);
+ }
+ }
+ }
+ fputs("\t" "}" "\n" "#endif" "\t" "/* __MigTypeCheck */" "\n\n", file); // terminate new scope
+ }
+
+ return;
+}
+
+static void
+WriteOOLSizeCheck(FILE *file, routine_t *rt)
+{
+ /* Emit code to validate the actual size of ool data vs. the reported size */
+
+ argument_t *argPtr;
+ boolean_t openedTypeCheckConditional = FALSE;
+
+ // scan through arguments to see if there are any ool data blocks
+ for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) {
+ if (akCheck(argPtr->argKind, akbSendKPD) && (argPtr->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR)) {
+ register ipc_type_t *it = argPtr->argType;
+ const char *tab;
+ char string[MAX_STR_LEN];
+ boolean_t test;
+ argument_t *argCountPtr;
+
+ if ( !openedTypeCheckConditional ) {
+ openedTypeCheckConditional = TRUE;
+ fputs("#if __MigTypeCheck\n", file);
+ }
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, TRUE, FALSE, argPtr, TRUE);
+ tab = "\t\t\t";
+ sprintf(string, "ptr->");
+ test = !it->itVarArray && !it->itElement->itVarArray;
+ it = it->itElement; // point to element descriptor, so size calculation is correct
+ argCountPtr = argPtr->argSubCount;
+ }
+ else {
+ tab = "";
+ sprintf(string, "In%dP->%s.", argPtr->argRequestPos, argPtr->argMsgField);
+ test = !it->itVarArray;
+ argCountPtr = argPtr->argCount;
+ }
+
+ if (!test) {
+ int multiplier = (argCountPtr->argMultiplier > 1 || it->itSize > 8) ? argCountPtr->argMultiplier * it->itSize / 8 : 1;
+ fprintf(file, "\t%s" "if (%ssize ", tab, string);
+ if (multiplier > 1)
+ fprintf(file, "/ %d ", multiplier);
+ fprintf(file,"!= In%dP->%s%s)\n", argCountPtr->argRequestPos, argCountPtr->argVarName, IS_MULTIPLE_KPD(it) ? "[i]" : "");
+
+ fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab);
+ }
+
+ if (IS_MULTIPLE_KPD(it))
+ fprintf(file, "\t }\n\t}\n");
+
+ }
+ }
+
+ if ( openedTypeCheckConditional )
+ fputs("#endif" "\t" "/* __MigTypeCheck */" "\n\n", file);
+}
+
+
+static void
+WriteCheckRequest(FILE *file, routine_t *rt)
+{
+ u_int i;
+
+ /* initialize the disciplines for the handling of KPDs */
+ InitKPD_Disciplines(rt->rtArgs);
+
+ fprintf(file, "\n");
+ fprintf(file, "#if ( __MigTypeCheck ");
+ if (CheckNDR)
+ fprintf(file, "|| __NDR_convert__ ");
+ fprintf(file, ")\n");
+ fprintf(file, "#if __MIG_check__Request__%s_subsystem__\n", SubsystemName);
+ fprintf(file, "#if !defined(__MIG_check__Request__%s_t__defined)\n", rt->rtName);
+ fprintf(file, "#define __MIG_check__Request__%s_t__defined\n", rt->rtName);
+ if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbRequest)) {
+ WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgDecl, akbSendNdr, "", "");
+ WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgDecl, akbSendNdr, "", "");
+ WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgDecl, akbSendNdr, "", "");
+ }
+ fprintf(file, "\n");
+ fprintf(file, "mig_internal kern_return_t __MIG_check__Request__%s_t(__attribute__((__unused__)) __Request__%s_t *In0P", rt->rtName, rt->rtName);
+ for (i = 1; i <= rt->rtMaxRequestPos; i++)
+ fprintf(file, ", __attribute__((__unused__)) __Request__%s_t **In%dPP", rt->rtName, i);
+ fprintf(file, ")\n{\n");
+
+ fprintf(file, "\n\ttypedef __Request__%s_t __Request;\n", rt->rtName);
+ for (i = 1; i <= rt->rtMaxRequestPos; i++)
+ fprintf(file, "\t__Request *In%dP;\n", i);
+ if (rt->rtNumRequestVar > 0) {
+ fprintf(file, "#if\t__MigTypeCheck\n");
+ fprintf(file, "\tunsigned int msgh_size;\n");
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+ }
+ if (rt->rtMaxRequestPos > 0)
+ fprintf(file, "\tunsigned int msgh_size_delta;\n");
+ if (rt->rtNumRequestVar > 0 || rt->rtMaxRequestPos > 0)
+ fprintf(file, "\n");
+
+ WriteCheckHead(file, rt);
+
+ WriteList(file, rt->rtArgs, WriteTypeCheck, akbSendKPD, "\n", "\n");
+
+ {
+ argument_t *arg, *lastVarArg;
+
+ lastVarArg = argNULL;
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ if (lastVarArg != argNULL &&
+ lastVarArg->argRequestPos < arg->argRequestPos) {
+ WriteAdjustRequestMsgPtr(file, lastVarArg);
+ lastVarArg = argNULL;
+ }
+ if (akCheckAll(arg->argKind, akbSendRcv|akbSendBody)) {
+ if (akCheck(arg->argKind, akbVariable)) {
+ WriteCheckMsgSize(file, arg);
+ lastVarArg = arg;
+ }
+ }
+ }
+ }
+
+ if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbRequest)) {
+ fprintf(file, "#if\t");
+ WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgCond, akbSendNdr, " || \\\n\t", "\n");
+ fprintf(file, "\tif (In0P->NDR.int_rep != NDR_record.int_rep) {\n");
+ WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgUse, akbSendNdr, "", "");
+ fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__int_rep...) */\n\n");
+
+ WriteOOLSizeCheck(file, rt);
+
+ fprintf(file, "#if\t");
+ WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgCond, akbSendNdr, " || \\\n\t", "\n");
+ fprintf(file, "\tif (In0P->NDR.char_rep != NDR_record.char_rep) {\n");
+ WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgUse, akbSendNdr, "", "");
+ fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__char_rep...) */\n\n");
+
+ fprintf(file, "#if\t");
+ WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgCond, akbSendNdr, " || \\\n\t", "\n");
+ fprintf(file, "\tif (In0P->NDR.float_rep != NDR_record.float_rep) {\n");
+ WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgUse, akbSendNdr, "", "");
+ fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__float_rep...) */\n\n");
+ } else {
+ WriteOOLSizeCheck(file, rt);
+ }
+
+ WriteStringTerminatorCheck(file, rt);
+
+ fprintf(file, "\treturn MACH_MSG_SUCCESS;\n");
+ fprintf(file, "}\n");
+ fprintf(file, "#endif /* !defined(__MIG_check__Request__%s_t__defined) */\n", rt->rtName);
+ fprintf(file, "#endif /* __MIG_check__Request__%s_subsystem__ */\n", SubsystemName);
+ fprintf(file, "#endif /* ( __MigTypeCheck ");
+ if (CheckNDR)
+ fprintf(file, "|| __NDR_convert__ ");
+ fprintf(file, ") */\n");
+ fprintf(file, "\n");
+}
+
+static void
+WriteCheckRequestCall(FILE *file, routine_t *rt)
+{
+ u_int i;
+
+ fprintf(file, "\n");
+ fprintf(file, "#if\tdefined(__MIG_check__Request__%s_t__defined)\n", rt->rtName);
+ fprintf(file, "\tcheck_result = __MIG_check__Request__%s_t((__Request *)In0P", rt->rtName);
+ for (i = 1; i <= rt->rtMaxRequestPos; i++)
+ fprintf(file, ", (__Request **)&In%dP", i);
+ fprintf(file, ");\n");
+ fprintf(file, "\tif (check_result != MACH_MSG_SUCCESS)\n");
+ fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, check_result); }\n");
+ fprintf(file, "#endif\t/* defined(__MIG_check__Request__%s_t__defined) */\n", rt->rtName);
+ fprintf(file, "\n");
+}
+
+void
+WriteCheckRequests(FILE *file, statement_t *stats)
+{
+ statement_t *stat;
+
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ if (stat->stKind == skRoutine)
+ WriteCheckRequest(file, stat->stRoutine);
+}
+
+static void
+WriteRoutine(FILE *file, register routine_t *rt)
+{
+ /* Declare the server work function: */
+ if (ServerHeaderFileName == strNULL)
+ WriteServerRoutine(file, rt);
+
+ fprintf(file, "\n");
+
+ fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
+ fprintf(file, "mig_internal novalue _X%s\n", rt->rtName);
+ if (BeAnsiC) {
+ fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
+ } else {
+ fprintf(file, "#if\t%s\n", NewCDecl);
+ fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
+ fprintf(file, "#else\n");
+ fprintf(file, "\t(InHeadP, OutHeadP)\n");
+ fprintf(file, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n");
+ fprintf(file, "#endif\t/* %s */\n", NewCDecl);
+ }
+
+ fprintf(file, "{\n");
+ WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request", rt->rtSimpleRequest, TRUE, rt->rtServerImpl, FALSE);
+ fprintf(file, "\ttypedef __Request__%s_t __Request;\n", rt->rtName);
+ fprintf(file, "\ttypedef __Reply__%s_t Reply;\n\n", rt->rtName);
+
+ /*
+ * Define a Minimal Reply structure to be used in case of errors
+ */
+ fprintf(file, "\t/*\n");
+ fprintf(file, "\t * typedef struct {\n");
+ fprintf(file, "\t * \tmach_msg_header_t Head;\n");
+ fprintf(file, "\t * \tNDR_record_t NDR;\n");
+ fprintf(file, "\t * \tkern_return_t RetCode;\n");
+ fprintf(file, "\t * } mig_reply_error_t;\n");
+ fprintf(file, "\t */\n");
+ fprintf(file, "\n");
+
+ WriteVarDecls(file, rt);
+
+ if (IsKernelServer) {
+ fprintf(file, "#if\t__MigKernelSpecificCode\n");
+ WriteList(file, rt->rtArgs, WriteTemplateDeclOut, akbReturnKPD, "\n", "\n");
+ fprintf(file, "#else\n");
+ }
+ WriteList(file, rt->rtArgs, WriteTemplateDeclIn, akbReturnKPD, "\n", "\n");
+ if (IsKernelServer) {
+ fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
+ }
+ WriteRetCode(file, rt->rtRetCode);
+ WriteList(file, rt->rtArgs, WriteLocalVarDecl, akbVarNeeded | akbServerArg, ";\n", ";\n\n");
+ WriteApplMacro(file, "Rcv", "Declare", rt);
+ WriteApplMacro(file, "Rcv", "Before", rt);
+ if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
+ WriteRetCArgCheckError(file, rt);
+ if (rt->rtServerImpl)
+ WriteCheckTrailerHead(file, rt, FALSE);
+ WriteServerCall(file, rt, WriteConditionalCallArg);
+ WriteRetCArgFinishError(file, rt);
+ } else
+ fprintf(file, "/* RetCArg=%p rtSimpleRequest=%u */\n", rt->rtRetCArg, rt->rtSimpleRequest);
+
+ WriteCheckRequestCall(file, rt);
+
+ WriteCheckRequestTrailerArgs(file, rt);
+
+
+ /*
+ * Initialize the KPD records in the Reply structure with the
+ * templates. We do this beforehand because the call to the procedure
+ * will overwrite some of the values (after the call it would be impossible
+ * to initialize the KPD records from the static Templates, because we
+ * would lose data).
+ */
+ WriteList(file, rt->rtArgs, WriteInitKPDValue, akbReturnKPD, "\n", "\n");
+
+ WriteList(file, rt->rtArgs, WriteExtractArg, akbNone, "", "");
+
+ if (UseEventLogger)
+ WriteLogMsg(file, rt, LOG_SERVER, LOG_REQUEST);
+
+
+ WriteServerCall(file, rt, WriteServerCallArg);
+
+
+ WriteReverseList(file, rt->rtArgs, WriteDestroyArg, akbDestroy, "", "");
+
+ /*
+ * For one-way routines, it doesn`t make sense to check the return
+ * code, because we return immediately afterwards. However,
+ * kernel servers may want to deallocate port arguments - and the
+ * deallocation must not be done if the return code is not KERN_SUCCESS.
+ */
+ if (rt->rtOneWay || rt->rtNoReplyArgs) {
+ if (IsKernelServer) {
+ fprintf(file,"#if\t__MigKernelSpecificCode\n");
+ if (rtCheckMaskFunction(rt->rtArgs, akbSendKPD, CheckDestroyPortArg)) {
+ WriteCheckReturnValue(file, rt);
+ }
+ WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg, akbSendKPD, "", "");
+ fprintf(file,"#endif /* __MigKernelSpecificCode */\n");
+ }
+ /* although we have an empty reply, we still have to make sure that
+ some fields such as NDR get properly initialized */
+ if (!rt->rtOneWay)
+ WriteList(file, rt->rtArgs, WriteInitArgValue, akbReplyInit, "\n", "\n");
+ } else {
+ WriteCheckReturnValue(file, rt);
+
+ if (IsKernelServer) {
+ fprintf(file,"#if\t__MigKernelSpecificCode\n");
+ WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg, akbSendKPD, "", "");
+ fprintf(file,"#endif /* __MigKernelSpecificCode */\n");
+ }
+ WriteReplyArgs(file, rt);
+ WriteReplyInit(file, rt);
+ if (!rt->rtSimpleReply)
+ fprintf(file, "\tOutP->msgh_body.msgh_descriptor_count = %d;\n", rt->rtReplyKPDs);
+ }
+ if (UseEventLogger)
+ WriteLogMsg(file, rt, LOG_SERVER, LOG_REPLY);
+
+ WriteApplMacro(file, "Rcv", "After", rt);
+ fprintf(file, "}\n");
+}
+
+void
+WriteServer(FILE *file, statement_t *stats)
+{
+ register statement_t *stat;
+
+ WriteProlog(file, stats);
+ if (BeAnsiC)
+ WriteForwardDeclarations(file, stats);
+ for (stat = stats; stat != stNULL; stat = stat->stNext) {
+ switch (stat->stKind) {
+ case skRoutine:
+ WriteCheckRequest(file, stat->stRoutine);
+ WriteRoutine(file, stat->stRoutine);
+ break;
+ case skIImport:
+ case skImport:
+ case skSImport:
+ case skDImport:
+ case skUImport:
+ break;
+
+ default:
+ fatal("WriteServer(): bad statement_kind_t (%d)",
+ (int) stat->stKind);
+ }
+ }
+ WriteDispatcher(file, stats);
+}
Property changes on: trunk/usr.bin/migcom/server.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/shims/errno.h
===================================================================
--- trunk/usr.bin/migcom/shims/errno.h (rev 0)
+++ trunk/usr.bin/migcom/shims/errno.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1 @@
+#include <sys/errno.h>
Property changes on: trunk/usr.bin/migcom/shims/errno.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/shims/stdarg.h
===================================================================
--- trunk/usr.bin/migcom/shims/stdarg.h (rev 0)
+++ trunk/usr.bin/migcom/shims/stdarg.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1 @@
+#include <machine/stdarg.h>
Property changes on: trunk/usr.bin/migcom/shims/stdarg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/shims/stdint.h
===================================================================
--- trunk/usr.bin/migcom/shims/stdint.h (rev 0)
+++ trunk/usr.bin/migcom/shims/stdint.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1 @@
+#include <sys/stdint.h>
Property changes on: trunk/usr.bin/migcom/shims/stdint.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/statement.c
===================================================================
--- trunk/usr.bin/migcom/statement.c (rev 0)
+++ trunk/usr.bin/migcom/statement.c 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,87 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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:44 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:55:45 mrt]
+ *
+ * 90/06/02 15:05:37 rpd
+ * Created for new IPC.
+ * [90/03/26 21:13:24 rpd]
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include "error.h"
+#include "alloc.h"
+#include "statement.h"
+
+statement_t *defs_stats = stNULL;
+static statement_t **last = &defs_stats;
+
+statement_t *
+stAlloc(void)
+{
+ register 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;
+}
Property changes on: trunk/usr.bin/migcom/statement.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/statement.h
===================================================================
--- trunk/usr.bin/migcom/statement.h (rev 0)
+++ trunk/usr.bin/migcom/statement.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,108 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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:47 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:55:51 mrt]
+ *
+ * 90/06/02 15:05:41 rpd
+ * Created for new IPC.
+ * [90/03/26 21:13:34 rpd]
+ *
+ * 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 *defs_stats;
+
+#endif /* _STATEMENT_H */
Property changes on: trunk/usr.bin/migcom/statement.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/strdefs.h
===================================================================
--- trunk/usr.bin/migcom/strdefs.h (rev 0)
+++ trunk/usr.bin/migcom/strdefs.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,95 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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 <mach/message.h>
+#include <string.h>
+
+typedef const char *string_t;
+typedef string_t identifier_t;
+
+#define MAX_STR_LEN 200
+
+#define strNULL ((string_t) 0)
+
+extern string_t strmake(string_t 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 const char *strbool(boolean_t bool);
+extern const char *strstring(string_t string);
+extern char *toupperstr(char *string);
+
+#endif /* STRDEFS_H */
Property changes on: trunk/usr.bin/migcom/strdefs.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/string.c
===================================================================
--- trunk/usr.bin/migcom/string.c (rev 0)
+++ trunk/usr.bin/migcom/string.c 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,186 @@
+/* $MidnightBSD$ */
+
+/*-
+ * Copyright (c) 2014, Matthew Macy <kmacy at FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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:52 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:55:57 mrt]
+ *
+ * 90/06/02 15:05:46 rpd
+ * Created for new IPC.
+ * [90/03/26 21:13:46 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
+ * Declare and initialize charNULL here for strNull def in string.h
+ *
+ * 27-May-87 Richard Draves (rpd) at Carnegie-Mellon University
+ * Created.
+ */
+
+#include <mach/boolean.h>
+#include <ctype.h>
+#include "error.h"
+#include "alloc.h"
+#include "strdefs.h"
+
+string_t
+strmake(const char *string)
+{
+ register char *saved;
+
+ saved = malloc(strlen(string) + 1);
+ if (saved == strNULL)
+ fatal("strmake('%s'): %s", string, strerror(errno));
+ return strcpy(saved, string);
+}
+
+string_t
+strconcat(left, right)
+ string_t left, right;
+{
+ register char *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(left, right)
+ string_t left, right;
+{
+ char *saved;
+ char *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(__DECONST(char *, left));
+ return(saved);
+}
+
+void
+strfree(string_t string)
+{
+ free(__DECONST(char *,string));
+}
+
+const char *
+strbool(bool)
+ boolean_t bool;
+{
+ if (bool)
+ return "TRUE";
+ else
+ return "FALSE";
+}
+
+const char *
+strstring(string)
+ string_t string;
+{
+ if (string == strNULL)
+ return "NULL";
+ else
+ return string;
+}
+
+char *
+toupperstr(char *p)
+{
+ register char *s = p;
+ char c;
+
+ while ((c = *s)) {
+ if (islower(c))
+ *s = toupper(c);
+ s++;
+ }
+ return(p);
+}
Property changes on: trunk/usr.bin/migcom/string.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/test.c
===================================================================
--- trunk/usr.bin/migcom/test.c (rev 0)
+++ trunk/usr.bin/migcom/test.c 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,26 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+
+/* comment */
Property changes on: trunk/usr.bin/migcom/test.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/type.c
===================================================================
--- trunk/usr.bin/migcom/type.c (rev 0)
+++ trunk/usr.bin/migcom/type.c 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,1014 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014, Matthew Macy <kmacy at FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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.
+ */
+/*
+ * 92/03/03 16:25:23 jeffreyh
+ * Changes from TRUNK
+ * [92/02/26 12:32:39 jeffreyh]
+ *
+ * 92/01/14 16:46:47 rpd
+ * Changed Indefinite types from MustBeLong to ShouldBeLong.
+ * Added itCheckFlags, itCheckDeallocate, itCheckIsLong.
+ * Removed itServerCopy.
+ * [92/01/09 rpd]
+ *
+ * 91/08/28 11:17:27 jsb
+ * Removed itMsgKindType.
+ * [91/08/12 rpd]
+ *
+ * 91/07/31 18:11:12 dbg
+ * Indefinite-length inline arrays.
+ *
+ * Change itDeallocate to an enumerated type, to allow for
+ * user-specified deallocate flag.
+ *
+ * Add itCStringDecl.
+ * [91/07/17 dbg]
+ *
+ * 91/06/25 10:32:09 rpd
+ * Changed itCalculateNameInfo to change type names from mach_port_t
+ * to ipc_port_t for KernelServer and KernelUser interfaces.
+ * [91/05/28 rpd]
+ *
+ * 91/02/05 17:56:02 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:56:12 mrt]
+ *
+ * 90/06/02 15:05:54 rpd
+ * Created for new IPC.
+ * [90/03/26 21:14:07 rpd]
+ *
+ * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
+ * Extensive revamping. Added polymorphic arguments.
+ * Allow multiple variable-sized inline arguments in messages.
+ *
+ * 17-Aug-88 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Removed translation of MSG_TYPE_INVALID as that type
+ * is no longer defined by the kernel.
+ *
+ * 19-Feb-88 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Changed itPrintTrans and itPrintDecl to reflect new translation syntax.
+ * Changed itCheckDecl to set itServerType to itType if is is strNULL.
+ *
+ * 4-Feb-88 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Added a check to itCheckDecl to make sure that in-line
+ * variable length arrays have a non-zero maximum length.
+ *
+ * 22-Dec-87 David Golub (dbg) at Carnegie-Mellon University
+ * Removed warning message for translation.
+ *
+ * 16-Nov-87 David Golub (dbg) at Carnegie-Mellon University
+ * Changed itVarArrayDecl to take a 'max' parameter for maximum
+ * number of elements, and to make type not be 'struct'.
+ * Added itDestructor.
+ *
+ * 18-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Added initialization of itPortType
+ *
+ * 14-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Added initialization for itTidType
+ *
+ * 15-Jun-87 David Black (dlb) at Carnegie-Mellon University
+ * Fixed prototype for itAlloc; was missing itServerType field.
+ *
+ * 10-Jun-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Removed extern from procedure definitions to make hi-c happy
+ * Changed the c type names of itDummyType from caddr_t to
+ * char * and of itCountType from u_int to unsigned int to
+ * eliminate the need to import sys/types.h into the mig generated
+ * code.
+ *
+ * 28-May-87 Richard Draves (rpd) at Carnegie-Mellon University
+ * Created.
+ */
+
+#include <stdio.h>
+
+#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 "strdefs.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 string_t 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)
+{
+ register 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 */
+ };
+ register 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 const 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(register 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 * sizeof(mach_msg_descriptor_t);
+ else
+ bytes = 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(register 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, register 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(register 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)
+{
+ register 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)
+{
+ register 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)
+{
+ register 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, register ipc_type_t *old)
+{
+ register 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;
+ } 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;
+ } 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->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)
+{
+ register 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)
+{
+ register 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(u_int count, boolean_t varying)
+{
+ register ipc_type_t *it;
+ register 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(u_int count, boolean_t varying, string_t name __unused)
+{
+ register ipc_type_t *it;
+ register 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(id, ptr, badval)
+ 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);
+}
Property changes on: trunk/usr.bin/migcom/type.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/type.h
===================================================================
--- trunk/usr.bin/migcom/type.h (rev 0)
+++ trunk/usr.bin/migcom/type.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,327 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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.
+ */
+/*
+ * 92/03/03 16:25:29 jeffreyh
+ * Changes from TRUNK
+ * [92/02/26 12:32:47 jeffreyh]
+ *
+ * 92/01/14 16:46:51 rpd
+ * Added itCheckFlags, itCheckDeallocate, itCheckIsLong.
+ * Removed itServerCopy.
+ * [92/01/09 rpd]
+ *
+ * 92/01/03 20:30:23 dbg
+ * Add flCountInOut.
+ * [91/11/11 dbg]
+ *
+ * 91/08/28 11:17:30 jsb
+ * Removed itMsgKindType.
+ * [91/08/12 rpd]
+ *
+ * 91/07/31 18:11:22 dbg
+ * Add flServerCopy.
+ * [91/06/05 dbg]
+ *
+ * Add itIndefinite.
+ * [91/04/10 dbg]
+ *
+ * Change itDeallocate to an enumerated type, to allow for
+ * user-specified deallocate flag.
+ *
+ * Add itCStringDecl.
+ * [91/04/03 dbg]
+ *
+ * 91/02/05 17:56:13 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:56:19 mrt]
+ *
+ * 90/06/02 15:05:59 rpd
+ * Created for new IPC.
+ * [90/03/26 21:14:28 rpd]
+ *
+ * 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 <sys/types.h>
+#include <sys/param.h>
+typedef u_int ipc_flags_t;
+#include "strdefs.h"
+
+
+/*
+ * 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. */
+} ipc_type_t;
+
+#define itNULL ((ipc_type_t *) 0)
+
+#define itWordAlign (sizeof(void *))
+
+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(u_int number, 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(u_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);
+
+#include "statement.h"
+
+#endif /* _TYPE_H */
Property changes on: trunk/usr.bin/migcom/type.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/user.c
===================================================================
--- trunk/usr.bin/migcom/user.c (rev 0)
+++ trunk/usr.bin/migcom/user.c 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,3341 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014, Matthew Macy <kmacy at FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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.
+ */
+/*
+ * 29-Sep-92 John Loverso (loverso) at Open Software Foundation
+ * Changes to deallocate memory on various error codes
+ *
+ * 92/03/03 16:25:33 jeffreyh
+ * Changes from TRUNK
+ * [92/02/26 12:32:55 jeffreyh]
+ *
+ * 92/01/14 16:46:59 rpd
+ * Changed CountInOut code generation, to send the minimum
+ * of the reply msg buffer size and the user's buffer size.
+ * [92/01/13 rpd]
+ *
+ * Fixed WriteExtractArgValue/itIndefinite, in the case when
+ * the data is in-line but doesn't fit.
+ * Fixed Indefinite code generation, to allow short type descriptors.
+ * Added deallocate bit handling to Indefinite code generation.
+ * [92/01/08 rpd]
+ *
+ * 92/01/03 20:30:38 dbg
+ * Redo handling of OUT arrays that are passed in-line or
+ * out-of-line. Treat more like out-of-line arrays:
+ * user allocates buffer and pointer
+ * fills in pointer with buffer address
+ * passes pointer to stub
+ * stub copies data to *pointer, or changes pointer
+ * User can always use *pointer.
+ *
+ * Change argByReferenceUser to a field in argument_t.
+ * [91/09/04 dbg]
+ *
+ * 91/08/28 11:17:34 jsb
+ * Added MIG_SERVER_DIED.
+ * [91/08/21 rpd]
+ * Removed Camelot and TrapRoutine support.
+ * Changed MsgKind to MsgSeqno.
+ * [91/08/12 rpd]
+ *
+ * 91/07/31 18:11:31 dbg
+ * Allow indefinite-length variable arrays. They may be copied
+ * either in-line or out-of-line, depending on size.
+ *
+ * Copy variable-length C Strings with mig_strncpy, to combine
+ * 'strcpy' and 'strlen' operations.
+ *
+ * New method for advancing request message pointer past
+ * variable-length arguments. We no longer have to know the order
+ * of variable-length arguments and their count arguments.
+ *
+ * Remove redundant assignments (to msgh_simple, msgh_size) in
+ * generated code.
+ * [91/07/17 dbg]
+ *
+ * 91/06/26 14:39:44 rpd
+ * Removed the dummy user initialization function,
+ * which was kept for backwards-compatibility.
+ * [91/06/26 rpd]
+ *
+ * 91/06/25 10:32:22 rpd
+ * Cast request and reply ports to mach_port_t in KernelUser stubs.
+ * [91/05/27 rpd]
+ *
+ * Changed HeaderFileName to UserHeaderFileName.
+ * Changed WriteVarDecl to WriteUserVarDecl.
+ * [91/05/23 rpd]
+ *
+ * 91/02/05 17:56:20 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:56:28 mrt]
+ *
+ * 90/06/19 23:01:20 rpd
+ * Added UserFilePrefix support.
+ * [90/06/03 rpd]
+ *
+ * 90/06/02 15:06:03 rpd
+ * Created for new IPC.
+ * [90/03/26 21:14:40 rpd]
+ *
+ * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
+ * Extensive revamping. Added polymorphic arguments.
+ * Allow multiple variable-sized inline arguments in messages.
+ *
+ * 21-Feb-89 David Golub (dbg) at Carnegie-Mellon University
+ * Get name for header file from HeaderFileName, since it can
+ * change.
+ *
+ * 8-Feb-89 David Golub (dbg) at Carnegie-Mellon University
+ * Added WriteUserIndividual to put each user-side routine in its
+ * own file.
+ *
+ * 8-Jul-88 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Declared routines to be mig_external instead of extern,
+ * where mig_external is conditionally defined in <subsystem>.h.
+ * The Avalon folks want to define mig_external to be static
+ * in their compilations because they inlcude the User.c code in
+ * their programs.
+ *
+ * 23-Feb-88 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Changed the include of camelot_types.h to cam/camelot_types.h
+ *
+ * 19-Feb-88 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Added comments for each routine. Called WriteMsgError
+ * for MIG_ARRAY_TOO_LARGE errors.
+ *
+ * 19-Jan-88 David Golub (dbg) at Carnegie-Mellon University
+ * Change variable-length inline array declarations to use
+ * maximum size specified to Mig. Make message variable
+ * length if the last item in the message is variable-length
+ * and inline. Use argMultiplier field to convert between
+ * argument and IPC element counts.
+ *
+ * 19-Jan-88 Mary Thompson (mrt) at Carnegie-Mellon University
+ * In WriteInitRoutine changed reference from reply_port; to reply_port++;
+ * for lint code.
+ *
+ * 17-Jan-88 David Detlefs (dld) at Carnegie-Mellon University
+ * Modified to produce C++ compatible code via #ifdefs.
+ * All changes have to do with argument declarations.
+ *
+ * 16-Nov-87 David Golub (dbg) at Carnegie-Mellon University
+ * Handle variable-length inline arrays.
+ *
+ * 22-Oct-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Added a reference to rep_port in the InitRoutine
+ * with an ifdef lint conditional.
+ *
+ * 22-Sep-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Fixed check for TransId to be a not equal test
+ * rather than an equal test.
+ *
+ * 2-Sep-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Changed WriteCheckIdentity to check TransId instead
+ * of msgh_id for a returned camelot reply
+ *
+ * 24-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Added a LINTLIBRARY line to keep lint
+ * from complaining about routines that are not used.
+ *
+ * 21-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Added Flag parameter to WritePackMsgType.
+ *
+ * 12-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Made various camelot changes: include of camelot_types.h
+ * Check for death_pill before correct msg-id.
+ *
+ * 10-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Renamed get_reply_port and dealloc_reply_port to
+ * mig_get_reply_port and mig_dealloc_reply_port.
+ * Fixed WriteRequestHead to handle MsgType parameter.
+ *
+ * 3-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Fixed to generate code that is the same for multi-threaded and
+ * single threaded use. Gets reply port from library routine
+ * get_reply_port and deallocates with routine
+ * dealloc_reply_port. Removed all routines in mig interface code
+ * to keep track of the reply port. The init routine still exists
+ * but does nothing.
+ *
+ * 29-Jul_87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Fixed call to WriteVarDecl to use correspond to
+ * the changes that were made in that routine.
+ *
+ * 16-Jul-87 Robert Sansom (rds) at Carnegie Mellon University
+ * Added write of MsgType to WriteSetMsgTypeRoutine.
+ *
+ * 8-Jun-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Removed #include of sys/types.h from WriteIncludes.
+ * Changed the KERNEL include from ../h to sys/
+ * Removed extern from WriteUser to make hi-c happy
+ *
+ * 28-May-87 Richard Draves (rpd) at Carnegie-Mellon University
+ * Created.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <mach/message.h>
+#include "write.h"
+#include "error.h"
+#include "utils.h"
+#include "global.h"
+#include "alloc.h"
+
+const char *MessAllocRoutine = "mig_user_allocate";
+const char *MessFreeRoutine = "mig_user_deallocate";
+
+static char stRetCode[] = "ReturnValue";
+static char stRetNone[] = "";
+
+void WriteLogDefines();
+void WriteIdentificationString();
+
+static void
+WriteKPD_Iterator(FILE *file, boolean_t in, boolean_t overwrite, boolean_t varying, argument_t *arg, boolean_t bracket)
+{
+ register ipc_type_t *it = arg->argType;
+ char string[MAX_STR_LEN];
+
+ fprintf(file, "\t{\n");
+ fprintf(file, "\t register\t%s\t*ptr;\n", it->itKPDType);
+ fprintf(file, "\t register int\ti");
+ if (varying && !in)
+ fprintf(file, ", j");
+ fprintf(file, ";\n\n");
+
+ if (in)
+ sprintf(string, "InP");
+ else if (overwrite)
+ sprintf(string, "InOvTemplate");
+ else
+ sprintf(string, "Out%dP", arg->argRequestPos);
+
+ fprintf(file, "\t ptr = &%s->%s[0];\n", string, arg->argMsgField);
+
+ if (varying) {
+ register argument_t *count = arg->argCount;
+ register const char *cref = count->argByReferenceUser ? "*" : "";
+
+ if (in || overwrite) {
+ fprintf(file, "\t if (%s%s > %d)\n", cref, count->argVarName,
+ it->itKPD_Number);
+ WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE");
+ fprintf(file, "\t for (i = 0; i < %s%s; ptr++, i++) %s\n",
+ cref, count->argVarName, (bracket) ? "{" : "");
+ } else {
+ fprintf(file, "\t j = min(Out%dP->%s, %s%s);\n", count->argReplyPos,
+ count->argVarName, cref, count->argVarName);
+ fprintf(file, "\t for (i = 0; i < j; ptr++, i++) %s\n",
+ (bracket) ? "{" : "");
+ }
+ } else
+ fprintf(file, "\t for (i = 0; i < %d; ptr++, i++) %s\n", it->itKPD_Number,
+ (bracket) ? "{" : "");
+}
+
+/*************************************************************
+ * Writes the standard includes. The subsystem specific
+ * includes are in <SubsystemName>.h and writen by
+ * header:WriteHeader. Called by WriteProlog.
+ *************************************************************/
+static void
+WriteMyIncludes(FILE *file, statement_t *stats)
+{
+#ifdef MIG_KERNEL_PORT_CONVERSION
+ if (IsKernelServer)
+ {
+ /*
+ * We want to get the user-side definitions of types
+ * like task_t, ipc_space_t, etc. in mach/mach_types.h.
+ */
+
+ fprintf(file, "#undef\tMACH_KERNEL\n");
+
+ if (InternalHeaderFileName != strNULL)
+ {
+ register const char *cp;
+
+ /* Strip any leading path from InternalHeaderFileName. */
+ cp = strrchr(InternalHeaderFileName, '/');
+ if (cp == 0)
+ cp = InternalHeaderFileName;
+ else
+ cp++; /* skip '/' */
+ fprintf(file, "#include \"%s\"\n", cp);
+ }
+ }
+#endif
+
+ if (UserHeaderFileName == strNULL || UseSplitHeaders)
+ WriteIncludes(file, TRUE, FALSE);
+ if (UserHeaderFileName != strNULL)
+ {
+ register const char *cp;
+
+ /* Strip any leading path from UserHeaderFileName. */
+ cp = strrchr(UserHeaderFileName, '/');
+ if (cp == 0)
+ cp = UserHeaderFileName;
+ else
+ cp++; /* skip '/' */
+ fprintf(file, "#include \"%s\"\n", cp);
+ }
+ if (UseSplitHeaders)
+ WriteImplImports(file, stats, TRUE);
+
+ if (UseEventLogger) {
+ if (IsKernelUser) {
+ fprintf(file, "#if\t__MigKernelSpecificCode\n");
+ fprintf(file, "#include <mig_debug.h>\n");
+ fprintf(file, "#endif\t/* __MigKernelSpecificCode */\n");
+ }
+ fprintf(file, "#if MIG_DEBUG\n");
+ fprintf(file, "#include <mach/mig_log.h>\n");
+ fprintf(file, "#endif /* MIG_DEBUG */\n");
+ }
+ fprintf(file, "/* LINTLIBRARY */\n");
+ fprintf(file, "\n");
+ if (!BeAnsiC) {
+ fprintf(file, "#if\t%s\n", NewCDecl);
+ fprintf(file, "#else\t/* %s */\n", NewCDecl);
+ fprintf(file, "extern mach_port_t mig_get_reply_port();\n");
+ fprintf(file, "extern void mig_dealloc_reply_port();\n");
+ fprintf(file, "extern char *%s();\n", MessAllocRoutine);
+ fprintf(file, "extern void %s();\n", MessFreeRoutine);
+ fprintf(file, "#endif\t/* %s */\n", NewCDecl);
+ }
+ fprintf(file, "\n");
+}
+
+static void
+WriteGlobalDecls(FILE *file)
+{
+ if (RCSId != strNULL)
+ WriteRCSDecl(file, strconcat(SubsystemName, "_user"), RCSId);
+
+ fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n");
+ fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n");
+ fprintf(file, "\n");
+ if (UseEventLogger)
+ WriteLogDefines(file, "MACH_MSG_LOG_USER");
+ fprintf(file, "\n");
+}
+
+static void
+WriteOneMachErrorDefine(FILE *file, const char *name, boolean_t timeout)
+{
+ fprintf(file, "#ifndef\t%s\n", name);
+ fprintf(file, "#define\t%s(_R_) { \\\n", name);
+ fprintf(file, "\tswitch (_R_) { \\\n");
+ fprintf(file, "\tcase MACH_SEND_INVALID_REPLY: \\\n");
+ fprintf(file, "\tcase MACH_RCV_INVALID_NAME: \\\n");
+ fprintf(file, "\tcase MACH_RCV_IN_SET: \\\n");
+ fprintf(file, "\tcase MACH_RCV_PORT_DIED: \\\n");
+ fprintf(file, "\tcase MACH_RCV_PORT_CHANGED: \\\n");
+ fprintf(file, "\tcase MACH_SEND_INVALID_MEMORY: \\\n");
+ fprintf(file, "\tcase MACH_SEND_INVALID_RIGHT: \\\n");
+ fprintf(file, "\tcase MACH_SEND_INVALID_TYPE: \\\n");
+ fprintf(file, "\tcase MACH_SEND_MSG_TOO_SMALL: \\\n");
+ fprintf(file, "\tcase MACH_SEND_INVALID_RT_OOL_SIZE: \\\n");
+ if (timeout)
+ fprintf(file, "\tcase MACH_RCV_TIMED_OUT: \\\n");
+ fprintf(file, "\t\tmig_dealloc_reply_port(InP->Head.msgh_reply_port); \\\n");
+ fprintf(file, "\t} \\\n}\n");
+ fprintf(file, "#endif\t/* %s */\n", name);
+ fprintf(file, "\n");
+}
+
+static void
+WriteMachErrorDefines(FILE *file)
+{
+ WriteOneMachErrorDefine(file, "__MachMsgErrorWithTimeout", TRUE);
+ WriteOneMachErrorDefine(file, "__MachMsgErrorWithoutTimeout", FALSE);
+}
+
+static void
+WriteMIGCheckDefines(FILE *file)
+{
+ fprintf(file, "#define\t__MIG_check__Reply__%s_subsystem__ 1\n", SubsystemName);
+ fprintf(file, "\n");
+}
+
+static void
+WriteNDRDefines(FILE *file)
+{
+ fprintf(file, "#define\t__NDR_convert__Reply__%s_subsystem__ 1\n", SubsystemName);
+ fprintf(file, "#define\t__NDR_convert__mig_reply_error_subsystem__ 1\n");
+ fprintf(file, "\n");
+}
+
+/*************************************************************
+ * Writes the standard #includes, #defines, and
+ * RCS declaration. Called by WriteUser.
+ *************************************************************/
+static void
+WriteProlog(FILE *file, statement_t *stats)
+{
+ WriteIdentificationString(file);
+ WriteMIGCheckDefines(file);
+ if (CheckNDR)
+ WriteNDRDefines(file);
+ WriteMyIncludes(file, stats);
+ WriteBogusDefines(file);
+ WriteMachErrorDefines(file);
+ WriteApplDefaults(file, "Send");
+ WriteGlobalDecls(file);
+}
+
+/*ARGSUSED*/
+static void
+WriteEpilog(FILE *file __unused)
+{
+}
+
+static string_t
+WriteHeaderPortType(argument_t *arg)
+{
+ if (arg->argType->itInName == MACH_MSG_TYPE_POLYMORPHIC)
+ return arg->argPoly->argVarName;
+ else
+ return arg->argType->itInNameStr;
+}
+
+static void
+WriteRequestHead(FILE *file, routine_t *rt)
+{
+ if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest)
+ fprintf(file, "ready_to_send:\n");
+
+ if (rt->rtMaxRequestPos > 0) {
+ if (rt->rtOverwrite)
+ fprintf(file, "\tInP = &MessRequest;\n");
+ else
+ fprintf(file, "\tInP = &Mess%sIn;\n",
+ (rtMessOnStack(rt) ? "." : "->"));
+ }
+ fprintf(file, "\tInP->Head.msgh_bits =");
+ if (rt->rtRetCArg == argNULL && !rt->rtSimpleRequest)
+ fprintf(file, " MACH_MSGH_BITS_COMPLEX|");
+ fprintf(file, "\n");
+ fprintf(file, "\t\tMACH_MSGH_BITS(%s, %s);\n",
+ WriteHeaderPortType(rt->rtRequestPort),
+ WriteHeaderPortType(rt->rtReplyPort));
+ if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
+ fprintf(file, "\tif (!%s)\n", rt->rtRetCArg->argVarName);
+ fprintf(file, "\t\tInP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n");
+ }
+
+
+ fprintf(file, "\t/* msgh_size passed as argument */\n");
+
+ /*
+ * KernelUser stubs need to cast the request and reply ports
+ * from ipc_port_t to mach_port_t.
+ */
+
+#ifdef MIG_KERNEL_PORT_CONVERSION
+ if (IsKernelUser)
+ fprintf(file, "\tInP->%s = (mach_port_t) %s;\n",
+ rt->rtRequestPort->argMsgField,
+ rt->rtRequestPort->argVarName);
+ else
+#endif
+ fprintf(file, "\tInP->%s = %s;\n",
+ rt->rtRequestPort->argMsgField,
+ rt->rtRequestPort->argVarName);
+
+ if (akCheck(rt->rtReplyPort->argKind, akbUserArg)) {
+#ifdef MIG_KERNEL_PORT_CONVERSION
+ if (IsKernelUser)
+ fprintf(file, "\tInP->%s = (mach_port_t) %s;\n", rt->rtReplyPort->argMsgField, rt->rtReplyPort->argVarName);
+ else
+#endif
+ fprintf(file, "\tInP->%s = %s;\n", rt->rtReplyPort->argMsgField, rt->rtReplyPort->argVarName);
+ }
+ else if (rt->rtOneWay)
+ fprintf(file, "\tInP->%s = MACH_PORT_NULL;\n", rt->rtReplyPort->argMsgField);
+ else
+ fprintf(file, "\tInP->%s = mig_get_reply_port();\n", rt->rtReplyPort->argMsgField);
+
+ fprintf(file, "\tInP->Head.msgh_id = %d;\n", rt->rtNumber + SubsystemBase);
+
+
+ if (IsVoucherCodeAllowed && !IsKernelUser && !IsKernelServer) {
+ fprintf(file, "\t\n/* BEGIN VOUCHER CODE */\n\n");
+ fprintf(file, "#ifdef USING_VOUCHERS\n");
+ fprintf(file, "\tif (voucher_mach_msg_set != NULL) {\n");
+ fprintf(file, "\t\tvoucher_mach_msg_set(&InP->Head);\n");
+ fprintf(file, "\t}\n");
+ fprintf(file, "#endif // USING_VOUCHERS\n");
+ fprintf(file, "\t\n/* END VOUCHER CODE */\n");
+ }
+}
+
+/*************************************************************
+ * Writes declarations for the message types, variables
+ * and return variable if needed. Called by WriteRoutine.
+ *************************************************************/
+static void
+WriteVarDecls(FILE *file, routine_t *rt)
+{
+ register u_int i;
+
+ if (rt->rtOverwrite) {
+ fprintf(file, "\tRequest MessRequest;\n");
+ fprintf(file, "\tRequest *InP = &MessRequest;\n\n");
+
+ fprintf(file, "\tunion {\n");
+ fprintf(file, "\t\tOverwriteTemplate In;\n");
+ fprintf(file, "\t\tReply Out;\n");
+ fprintf(file, "\t} MessReply;\n");
+
+ fprintf(file, "\tOverwriteTemplate *InOvTemplate = &MessReply.In;\n");
+ fprintf(file, "\tReply *Out0P = &MessReply.Out;\n");
+ for (i = 1; i <= rt->rtMaxReplyPos; i++)
+ fprintf(file, "\t" "Reply *Out%dP = NULL;\n", i);
+ }
+ else {
+ if (rtMessOnStack(rt))
+ fprintf(file, "\tunion {\n");
+ else
+ fprintf(file, "\tunion %sMessU {\n", rt->rtName);
+ fprintf(file, "\t\tRequest In;\n");
+ if (!rt->rtOneWay)
+ fprintf(file, "\t\tReply Out;\n");
+ if (rtMessOnStack(rt))
+ fprintf(file, "\t} Mess;\n");
+ else
+ fprintf(file, "\t} *Mess = (union %sMessU *) %s(sizeof(*Mess));\n",
+ rt->rtName, MessAllocRoutine);
+ fprintf(file, "\n");
+
+ fprintf(file, "\tRequest *InP = &Mess%sIn;\n", (rtMessOnStack(rt) ? "." : "->"));
+ if (!rt->rtOneWay) {
+ fprintf(file, "\tReply *Out0P = &Mess%sOut;\n", (rtMessOnStack(rt) ? "." : "->"));
+ for (i = 1; i <= rt->rtMaxReplyPos; i++)
+ fprintf(file, "\t" "Reply *Out%dP = NULL;\n", i);
+ }
+ }
+
+ fprintf(file, "\n");
+
+ fprintf(file, "\tmach_msg_return_t msg_result;\n");
+
+ /* if request is variable, we need msgh_size_delta and msgh_size */
+ if (rt->rtNumRequestVar > 0)
+ fprintf(file, "\tunsigned int msgh_size;\n");
+ if (rt->rtMaxRequestPos > 0)
+ fprintf(file, "\tunsigned int msgh_size_delta;\n");
+ if (rt->rtNumRequestVar > 1 || rt->rtMaxRequestPos > 0)
+ fprintf(file, "\n");
+
+ if (rt->rtUserImpl) {
+ fprintf(file, "\tmach_msg_max_trailer_t *TrailerP;\n");
+ fprintf(file, "#if\t__MigTypeCheck\n");
+ fprintf(file, "\tunsigned int trailer_size;\n");
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+ }
+ fprintf(file, "\n");
+ fprintf(file, "#ifdef\t__MIG_check__Reply__%s_t__defined\n", rt->rtName);
+ fprintf(file, "\tkern_return_t check_result;\n");
+ fprintf(file, "#endif\t/* __MIG_check__Reply__%s_t__defined */\n", rt->rtName);
+ fprintf(file, "\n");
+ WriteApplMacro(file, "Send", "Declare", rt);
+ fprintf(file, "\n");
+}
+
+static void
+WriteReturn(FILE *file, routine_t *rt, const char *before, const char *value, const char *after)
+{
+ if (rtMessOnStack(rt) && value != stRetCode)
+ {
+ /* get the easy case (no braces needed) out of the way */
+ fprintf(file, "%sreturn%s%s;%s",
+ before, (*value ? " " : ""), value, after);
+ return;
+ }
+
+ /* get the easy case (no braces needed) out of the way */
+ if (rtMessOnStack(rt))
+ {
+ if (value == stRetNone)
+ fprintf(file, "%sreturn;%s",
+ before, after);
+ else if (value == stRetCode)
+ fprintf(file, "%sreturn Out0P->RetCode;%s",
+ before, after);
+ else
+ fprintf(file, "%sreturn %s;%s",
+ before, value, after);
+ return;
+ }
+
+ if (value == stRetCode) {
+ fprintf(file, "%s{\n%s\t%s ReturnValue;\n", before, before, ReturnTypeStr(rt));
+ fprintf(file, "%s\tReturnValue = Out0P->RetCode;\n%s\t", before, before);
+ }
+ else {
+ fprintf(file, "%s{ ", before);
+ }
+
+ fprintf(file, "%s((char *) Mess, sizeof(*Mess)); ", MessFreeRoutine);
+
+ if (value == stRetCode)
+ fprintf(file, "return ReturnValue;\n%s}%s", before, after);
+ else if (value == stRetNone)
+ fprintf(file, "return; }%s", after);
+ else
+ fprintf(file, "return %s; }%s", value, after);
+}
+
+static void
+WriteRetCodeArg(FILE *file, register routine_t *rt)
+{
+ if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
+ register argument_t *arg = rt->rtRetCArg;
+
+ fprintf(file, "\tif (%s) {\n", arg->argVarName);
+ fprintf(file, "\t\t((mig_reply_error_t *)InP)->RetCode = %s;\n", arg->argVarName);
+ fprintf(file, "\t\t((mig_reply_error_t *)InP)->NDR = NDR_record;\n");
+ fprintf(file, "\t\tgoto ready_to_send;\n");
+ fprintf(file, "\t}\n\n");
+ }
+}
+
+/*************************************************************
+ * Writes the logic to check for a message send timeout, and
+ * deallocate any relocated ool data so as not to leak.
+ *************************************************************/
+static void
+WriteMsgCheckForTimeout(FILE *file, routine_t *rt)
+{
+ if (rt->rtWaitTime != argNULL) { /* no reason to test for timeout if no timeout was specified... */
+ argument_t *arg_ptr;
+ fputs("\n\t" "if (msg_result == MACH_SEND_TIMED_OUT) {" "\n", file);
+
+ // iterate over arg list
+ for (arg_ptr = rt->rtArgs; arg_ptr != NULL; arg_ptr = arg_ptr->argNext) {
+
+ // if argument contains ool data
+ if (akCheck(arg_ptr->argKind, akbSendKPD) && arg_ptr->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {
+ // generate code to test current arg address vs. address before the msg_send call
+ // if not at the same address, mig_deallocate the argument
+ fprintf(file, "\t\tif((vm_offset_t) InP->%s.address != (vm_offset_t) %s)\n",
+ arg_ptr->argVarName, arg_ptr->argVarName);
+ fprintf(file, "\t\t\t" "mig_deallocate((vm_offset_t) InP->%s.address, "
+ "(vm_size_t) InP->%s.size);\n", arg_ptr->argVarName, arg_ptr->argVarName);
+ }
+ }
+
+ fputs("\t" "}" "\n\n", file);
+ }
+ return;
+}
+
+/*************************************************************
+ * Writes the send call when there is to be no subsequent
+ * receive. Called by WriteRoutine SimpleRoutines
+ *************************************************************/
+static void
+WriteMsgSend(FILE *file, routine_t *rt)
+{
+ const char *SendSize = "";
+ char string[MAX_STR_LEN];
+
+ if (rt->rtNumRequestVar == 0)
+ SendSize = "sizeof(Request)";
+ else
+ SendSize = "msgh_size";
+
+ if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
+ sprintf(string, "(%s) ? sizeof(mig_reply_error_t) : ",
+ rt->rtRetCArg->argVarName);
+ SendSize = strconcat(string, SendSize);
+ }
+
+ if (IsKernelUser) {
+ fprintf(file, "#if\t__MigKernelSpecificCode\n");
+ fprintf(file, "\tmsg_result = mach_msg_send_from_kernel(");
+ fprintf(file, "&InP->Head, %s);\n", SendSize);
+ fprintf(file, "#else\n");
+ }
+ fprintf(file, "\tmsg_result = mach_msg("
+ "&InP->Head, MACH_SEND_MSG|%s%s, %s, 0, MACH_PORT_NULL, %s, MACH_PORT_NULL);\n",
+ rt->rtWaitTime !=argNULL ? "MACH_SEND_TIMEOUT|" : "",
+ rt->rtMsgOption->argVarName,
+ SendSize,
+ rt->rtWaitTime != argNULL ? rt->rtWaitTime->argVarName:"MACH_MSG_TIMEOUT_NONE");
+
+ if (IsKernelUser) {
+ fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
+ }
+ WriteApplMacro(file, "Send", "After", rt);
+
+ WriteMsgCheckForTimeout(file, rt);
+
+ WriteReturn(file, rt, "\t", "msg_result", "\n");
+}
+
+/*************************************************************
+ * Writes to code to check for error returns from receive.
+ * Called by WriteMsgSendReceive and WriteMsgRPC
+ *************************************************************/
+static void
+WriteMsgCheckReceive(FILE *file, routine_t *rt, const char *success)
+{
+ fprintf(file, "\tif (msg_result != %s) {\n", success);
+ if (!akCheck(rt->rtReplyPort->argKind, akbUserArg) && !IsKernelUser)
+ {
+ /* If we aren't using a user-supplied reply port, then
+ deallocate the reply port when it is invalid or
+ for TIMED_OUT errors. */
+#ifdef DeallocOnAnyError
+ fprintf(file,
+ "\t\tmig_dealloc_reply_port(InP->Head.msgh_reply_port);\n");
+#else
+ if (rt->rtWaitTime != argNULL)
+ fprintf(file, "\t\t__MachMsgErrorWithTimeout(msg_result);\n");
+ else
+ fprintf(file, "\t\t__MachMsgErrorWithoutTimeout(msg_result);\n");
+#endif
+ }
+ WriteReturnMsgError(file, rt, TRUE, argNULL, "msg_result");
+ fprintf(file, "\t}\n");
+}
+
+/*************************************************************
+ * Writes the send and receive calls and code to check
+ * for errors. Normally the rpc code is generated instead
+ * although, the subsytem can be compiled with the -R option
+ * which will cause this code to be generated. Called by
+ * WriteRoutine if UseMsgRPC option is false.
+ *************************************************************/
+static void
+WriteMsgSendReceive(FILE *file, routine_t *rt)
+{
+ const char *SendSize = "";
+ char string[MAX_STR_LEN];
+
+ if (rt->rtNumRequestVar == 0)
+ SendSize = "sizeof(Request)";
+ else
+ SendSize = "msgh_size";
+
+ if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
+ sprintf(string, "(%s) ? sizeof(mig_reply_error_t) : ",
+ rt->rtRetCArg->argVarName);
+ SendSize = strconcat(string, SendSize);
+ }
+
+ /* IsKernelUser to be done! */
+ fprintf(file, "\tmsg_result = mach_msg(&InP->Head, MACH_SEND_MSG|%s%s, %s, 0, ", rt->rtWaitTime != argNULL ? "MACH_SEND_TIMEOUT|" : "", rt->rtMsgOption->argVarName, SendSize);
+ fprintf(file, " MACH_PORT_NULL, %s, MACH_PORT_NULL);\n",
+#if !USE_IMMEDIATE_SEND_TIMEOUT
+ (rt->rtWaitTime != argNULL) ? rt->rtWaitTime->argVarName :
+#endif
+ "MACH_MSG_TIMEOUT_NONE");
+ fprintf(file, "\tif (msg_result != MACH_MSG_SUCCESS)\n");
+ WriteReturnMsgError(file, rt, TRUE, argNULL, "msg_result");
+ fprintf(file, "\n");
+
+ fprintf(file, "\tmsg_result = mach_msg(&Out0P->Head, MACH_RCV_MSG|%s%s%s, 0, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_local_port, %s, MACH_PORT_NULL);\n",
+ rt->rtUserImpl != 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "",
+ (rt->rtWaitTime != argNULL && akIdent(rt->rtWaitTime->argKind) == akeWaitTime) ? "MACH_RCV_TIMEOUT|" : "",
+ rt->rtMsgOption->argVarName,
+ (rt->rtWaitTime != argNULL && akIdent(rt->rtWaitTime->argKind) == akeWaitTime) ? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE");
+ WriteApplMacro(file, "Send", "After", rt);
+ WriteMsgCheckReceive(file, rt, "MACH_MSG_SUCCESS");
+ fprintf(file, "\n");
+}
+
+/*************************************************************
+ * Writes the rpc call and the code to check for errors.
+ * This is the default code to be generated. Called by WriteRoutine
+ * for all routine types except SimpleRoutine.
+ *************************************************************/
+static void
+WriteMsgRPC(FILE *file, routine_t *rt)
+{
+ const char *SendSize = "";
+ char string[MAX_STR_LEN];
+
+ if (rt->rtNumRequestVar == 0)
+ SendSize = "sizeof(Request)";
+ else
+ SendSize = "msgh_size";
+
+ if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
+ sprintf(string, "(%s) ? (mach_msg_size_t)sizeof(mig_reply_error_t) : ", rt->rtRetCArg->argVarName);
+ SendSize = strconcat(string, SendSize);
+ }
+
+ if (IsKernelUser) {
+ fprintf(file, "#if\t(__MigKernelSpecificCode) || (_MIG_KERNELSPECIFIC_CODE_)\n");
+ fprintf(file, "\tmsg_result = mach_msg_rpc_from_kernel(&InP->Head, %s, (mach_msg_size_t)sizeof(Reply));\n", SendSize);
+ fprintf(file, "#else\n");
+ }
+ if (rt->rtOverwrite) {
+ fprintf(file, "\tmsg_result = mach_msg_overwrite(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_RCV_OVERWRITE|%s%s%s, %s, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, %s, MACH_PORT_NULL, ",
+ rt->rtUserImpl != 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "",
+ rt->rtWaitTime != argNULL ?
+ (akIdent(rt->rtWaitTime->argKind) == akeWaitTime ? "MACH_SEND_TIMEOUT|MACH_RCV_TIMEOUT|" : "MACH_SEND_TIMEOUT|") : "",
+ rt->rtMsgOption->argVarName,
+ SendSize,
+ rt->rtWaitTime != argNULL? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE");
+ fprintf(file, " &InOvTemplate->Head, (mach_msg_size_t)sizeof(OverwriteTemplate));\n");
+ }
+ else {
+ fprintf(file, "\tmsg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|%s%s%s, %s, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, %s, MACH_PORT_NULL);\n",
+ rt->rtUserImpl != 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "",
+ rt->rtWaitTime != argNULL ?
+ (akIdent(rt->rtWaitTime->argKind) == akeWaitTime ? "MACH_SEND_TIMEOUT|MACH_RCV_TIMEOUT|" : "MACH_SEND_TIMEOUT|") : "",
+ rt->rtMsgOption->argVarName,
+ SendSize,
+ rt->rtWaitTime != argNULL? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE");
+ }
+ if (IsKernelUser)
+ fprintf(file,"#endif /* __MigKernelSpecificCode */\n");
+ WriteApplMacro(file, "Send", "After", rt);
+
+ WriteMsgCheckForTimeout(file, rt);
+
+ WriteMsgCheckReceive(file, rt, "MACH_MSG_SUCCESS");
+ fprintf(file, "\n");
+}
+
+/*
+ * argKPD_Pack discipline for Port types.
+ */
+static void
+WriteKPD_port(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *subindex = "";
+ const char *recast = "";
+ char firststring[MAX_STR_LEN];
+ char string[MAX_STR_LEN];
+ const char *ref = arg->argByReferenceUser ? "*" : "";
+ ipc_type_t *real_it;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, TRUE, FALSE, it->itVarArray, arg, TRUE);
+ (void)sprintf(firststring, "\t*ptr");
+ (void)sprintf(string, "\tptr->");
+ subindex = "[i]";
+ real_it = it->itElement;
+ } else {
+ (void)sprintf(firststring, "InP->%s", arg->argMsgField);
+ (void)sprintf(string, "InP->%s.", arg->argMsgField);
+ real_it = it;
+ }
+
+#ifdef MIG_KERNEL_PORT_CONVERSION
+ if (IsKernelUser && streql(real_it->itUserType, "ipc_port_t"))
+ recast = "(mach_port_t)";
+#endif
+ fprintf(file, "#if\tUseStaticTemplates\n");
+ fprintf(file, "\t%s = %s;\n", firststring,
+ arg->argTTName);
+ /* ref is required also in the Request part, because of inout parameters */
+ fprintf(file, "\t%sname = %s%s%s%s;\n", string,
+ recast, ref, arg->argVarName, subindex);
+ if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendSnd)) {
+ register argument_t *poly = arg->argPoly;
+
+ fprintf(file, "\t%sdisposition = %s%s;\n", string,
+ poly->argByReferenceUser ? "*" : "", poly->argVarName);
+ }
+ fprintf(file, "#else\t/* UseStaticTemplates */\n");
+ fprintf(file, "\t%sname = %s%s%s%s;\n", string,
+ recast, ref, arg->argVarName, subindex);
+ if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendSnd)) {
+ register argument_t *poly = arg->argPoly;
+
+ fprintf(file, "\t%sdisposition = %s%s;\n", string,
+ poly->argByReferenceUser ? "*" : "", poly->argVarName);
+ } else
+ fprintf(file, "\t%sdisposition = %s;\n", string,
+ it->itInNameStr);
+ fprintf(file, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string);
+ fprintf(file, "#endif\t/* UseStaticTemplates */\n");
+ if (IS_MULTIPLE_KPD(it)) {
+ fprintf(file, "\t }\n");
+ if (it->itVarArray) {
+ fprintf(file, "\t for (i = %s; i < %d; ptr++, i++) {\n",
+ arg->argCount->argVarName, it->itKPD_Number);
+ /* fill the rest of the statically allocated KPD entries with MACH_PORT_NULL */
+ fprintf(file, "#if\tUseStaticTemplates\n");
+ fprintf(file, "\t%s = %s;\n", firststring,
+ arg->argTTName);
+ fprintf(file, "#else\t/* UseStaticTemplates */\n");
+ fprintf(file, "\t%sname = MACH_PORT_NULL;\n", string);
+ fprintf(file, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string);
+ fprintf(file, "#endif\t/* UseStaticTemplates */\n");
+ fprintf(file, "\t }\n");
+ }
+ fprintf(file, "\t}\n");
+ }
+ fprintf(file, "\n");
+}
+
+static void
+WriteKPD_ool_varsize(FILE *file, argument_t *arg, const char *who, const char *where, boolean_t iscomplex)
+{
+ register ipc_type_t *it = arg->argType;
+ register argument_t *count;
+ const char *cref;
+
+ if (iscomplex) {
+ it = it->itElement;
+ count = arg->argSubCount;
+ } else
+ count = arg->argCount;
+ cref = count->argByReferenceUser ? "*" : "";
+
+ /* size has to be expressed in bytes! */
+ if (count->argMultiplier > 1 || it->itSize > 8)
+ fprintf(file, "\t%s->%s = %s%s%s * %d;\n", who, where,
+ cref, count->argVarName,
+ (iscomplex)? "[i]" : "",
+ count->argMultiplier * it->itSize / 8);
+ else
+ fprintf(file, "\t%s->%s = %s%s%s;\n", who, where,
+ cref, count->argVarName,
+ (iscomplex)? "[i]" : "");
+}
+
+/*
+ * argKPD_Pack discipline for out-of-line types.
+ */
+static void
+WriteKPD_ool(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *ref = arg->argByReferenceUser ? "*" : "";
+ char firststring[MAX_STR_LEN];
+ char string[MAX_STR_LEN];
+ boolean_t VarArray;
+ u_int howmany, howbig;
+ const char *subindex;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, TRUE, FALSE, it->itVarArray, arg, TRUE);
+ (void)sprintf(firststring, "\t*ptr");
+ (void)sprintf(string, "\tptr->");
+ VarArray = it->itElement->itVarArray;
+ howmany = it->itElement->itNumber;
+ howbig = it->itElement->itSize;
+ subindex = "[i]";
+ } else {
+ (void)sprintf(firststring, "InP->%s", arg->argMsgField);
+ (void)sprintf(string, "InP->%s.", arg->argMsgField);
+ VarArray = it->itVarArray;
+ howmany = it->itNumber;
+ howbig = it->itSize;
+ subindex = "";
+ }
+
+ fprintf(file, "#if\tUseStaticTemplates\n");
+
+ fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
+ fprintf(file, "\t%saddress = (void *)(%s%s%s);\n",
+ string, ref, arg->argVarName, subindex);
+ if (VarArray) {
+ if (IS_MULTIPLE_KPD(it))
+ WriteKPD_ool_varsize(file, arg, "\tptr", "size", TRUE);
+ else
+ WriteKPD_ool_varsize(file, arg, "InP",
+ strconcat(arg->argMsgField, ".size"), FALSE);
+ }
+ if (arg->argDeallocate == d_MAYBE)
+ fprintf(file, "\t%sdeallocate = %s;\n",
+ string, arg->argDealloc->argVarName);
+
+ fprintf(file, "#else\t/* UseStaticTemplates */\n");
+
+ fprintf(file, "\t%saddress = (void *)(%s%s%s);\n",
+ string, ref, arg->argVarName, subindex);
+ if (VarArray)
+ if (IS_MULTIPLE_KPD(it))
+ WriteKPD_ool_varsize(file, arg, "\tptr", "size", TRUE);
+ else
+ WriteKPD_ool_varsize(file, arg, "InP",
+ strconcat(arg->argMsgField, ".size"), FALSE);
+ else
+ fprintf(file, "\t%ssize = %d;\n", string,
+ (howmany * howbig + 7)/8);
+ if (arg->argDeallocate == d_MAYBE)
+ fprintf(file, "\t%sdeallocate = %s;\n", string,
+ arg->argDealloc->argVarName);
+ else
+ fprintf(file, "\t%sdeallocate = %s;\n", string,
+ (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE");
+ fprintf(file, "\t%scopy = %s;\n", string,
+ (arg->argFlags & flPhysicalCopy) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY");
+#ifdef ALIGNMENT
+ fprintf(file, "\t%salignment = MACH_MSG_ALIGN_%d;\n", string,
+ (it->itElement->itSize < 8) ? 1 : it->itElement->itSize / 8);
+#endif
+ fprintf(file, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string);
+
+ fprintf(file, "#endif\t/* UseStaticTemplates */\n");
+ if (IS_MULTIPLE_KPD(it)) {
+ fprintf(file, "\t }\n");
+ if (it->itVarArray) {
+ fprintf(file, "\t for (i = %s; i < %d; ptr++, i++) {\n",
+ arg->argCount->argVarName, it->itKPD_Number);
+ /* fill the rest of the statically allocated KPD entries with size NULL */
+ fprintf(file, "#if\tUseStaticTemplates\n");
+ fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
+ if (!VarArray)
+ fprintf(file, "\t%ssize = 0;\n", string);
+ /* otherwise the size in the template would be != 0! */
+ fprintf(file, "#else\t/* UseStaticTemplates */\n");
+ fprintf(file, "\t%ssize = 0;\n", string);
+ fprintf(file, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string);
+ fprintf(file, "#endif\t/* UseStaticTemplates */\n");
+ fprintf(file, "\t }\n");
+ }
+ fprintf(file, "\t}\n");
+ }
+ fprintf(file, "\n");
+}
+
+/*
+ * argKPD_Pack discipline for out-of-line Port types.
+ */
+static void
+WriteKPD_oolport(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *ref = arg->argByReferenceUser ? "*" : "";
+ register argument_t *count;
+ boolean_t VarArray;
+ string_t howstr;
+ u_int howmany;
+ const char *subindex;
+ char firststring[MAX_STR_LEN];
+ char string[MAX_STR_LEN];
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, TRUE, FALSE, it->itVarArray, arg, TRUE);
+ (void)sprintf(firststring, "\t*ptr");
+ (void)sprintf(string, "\tptr->");
+ VarArray = it->itElement->itVarArray;
+ howmany = it->itElement->itNumber;
+ howstr = it->itElement->itInNameStr;
+ count = arg->argSubCount;
+ subindex = "[i]";
+ } else {
+ (void)sprintf(firststring, "InP->%s", arg->argMsgField);
+ (void)sprintf(string, "InP->%s.", arg->argMsgField);
+ VarArray = it->itVarArray;
+ howmany = it->itNumber;
+ howstr = it->itInNameStr;
+ count = arg->argCount;
+ subindex = "";
+ }
+
+ fprintf(file, "#if\tUseStaticTemplates\n");
+
+ fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
+ fprintf(file, "\t%saddress = (void *)(%s%s%s);\n", string,
+ ref, arg->argVarName, subindex);
+ if (VarArray)
+ fprintf(file, "\t%scount = %s%s%s;\n", string,
+ count->argByReferenceUser ? "*" : "",
+ count->argVarName, subindex);
+ if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendSnd)) {
+ register argument_t *poly = arg->argPoly;
+ const char *pref = poly->argByReferenceUser ? "*" : "";
+
+ fprintf(file, "\t%sdisposition = %s%s;\n", string,
+ pref, poly->argVarName);
+ }
+ if (arg->argDeallocate == d_MAYBE)
+ fprintf(file, "\t%sdeallocate = %s;\n", string,
+ arg->argDealloc->argVarName);
+
+ fprintf(file, "#else\t/* UseStaticTemplates */\n");
+
+ fprintf(file, "\t%saddress = (void *)(%s%s%s);\n",
+ string, ref, arg->argVarName, subindex);
+ if (VarArray)
+ fprintf(file, "\t%scount = %s%s%s;\n", string,
+ count->argByReferenceUser ? "*" : "",
+ count->argVarName, subindex);
+ else
+ fprintf(file, "\t%scount = %d;\n", string,
+ howmany);
+ if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendSnd)) {
+ register argument_t *poly = arg->argPoly;
+ const char *pref = poly->argByReferenceUser ? "*" : "";
+
+ fprintf(file, "\t%sdisposition = %s%s;\n",
+ string, pref, poly->argVarName);
+ } else
+ fprintf(file, "\t%sdisposition = %s;\n",
+ string, howstr);
+ if (arg->argDeallocate == d_MAYBE)
+ fprintf(file, "\t%sdeallocate = %s;\n", string,
+ arg->argDealloc->argVarName);
+ else
+ fprintf(file, "\t%sdeallocate = %s;\n", string,
+ (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE");
+ fprintf(file, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string);
+
+ fprintf(file, "#endif\t/* UseStaticTemplates */\n");
+ fprintf(file, "\n");
+
+ if (IS_MULTIPLE_KPD(it)) {
+ fprintf(file, "\t }\n");
+ if (it->itVarArray) {
+ fprintf(file, "\t for (i = %s; i < %d; ptr++, i++) {\n",
+ arg->argCount->argVarName, it->itKPD_Number);
+ /* fill the rest of the statically allocated KPD entries with size NULL */
+ fprintf(file, "#if\tUseStaticTemplates\n");
+ fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
+ if (!VarArray)
+ fprintf(file, "\t%scount = 0;\n", string);
+ /* otherwise the size in the template would be != 0! */
+ fprintf(file, "#else\t/* UseStaticTemplates */\n");
+ fprintf(file, "\t%scount = 0;\n", string);
+ fprintf(file, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string);
+ fprintf(file, "#endif\t/* UseStaticTemplates */\n");
+ fprintf(file, "\t }\n");
+ }
+ fprintf(file, "\t}\n");
+ }
+ fprintf(file, "\n");
+}
+
+static void
+WriteOverwriteTemplate(FILE *file, routine_t *rt)
+{
+ register argument_t *arg;
+ char string[MAX_STR_LEN];
+ const char *subindex = "";
+ boolean_t finish = FALSE;
+
+ fprintf(file, "\t/* Initialize the template for overwrite */\n");
+ fprintf(file, "\tInOvTemplate->msgh_body.msgh_descriptor_count = %d;\n",
+ rt->rtOverwriteKPDs);
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ register ipc_type_t *it = arg->argType;
+ const char *ref = arg->argByReferenceUser ? "*" : "";
+ argument_t *count;
+ const char *cref;
+ boolean_t VarIndex;
+ u_int howmany, howbig;
+
+ if (akCheck(arg->argKind, akbOverwrite)) {
+ if (arg->argFlags & flOverwrite) {
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, TRUE, it->itVarArray, arg, TRUE);
+ if (it->itVarArray)
+ finish = TRUE;
+ sprintf(string, "\tptr->");
+ subindex = "[i]";
+ count = arg->argSubCount;
+ VarIndex = it->itElement->itVarArray;
+ howmany = it->itElement->itNumber;
+ howbig = it->itElement->itSize;
+ } else {
+ sprintf(string, "InOvTemplate->%s.", arg->argMsgField);
+ subindex = "";
+ count = arg->argCount;
+ VarIndex = it->itVarArray;
+ howmany = it->itNumber;
+ howbig = it->itSize;
+ }
+
+ fprintf(file, "\t%saddress = (void *) %s%s%s;\n", string,
+ ref, arg->argVarName, subindex);
+
+ if (it->itPortType) {
+ fprintf(file, "\t%scount = ", string);
+ if (VarIndex) {
+ cref = count->argByReferenceUser ? "*" : "";
+ fprintf(file, "%s%s%s;\n", cref, count->argVarName, subindex);
+ } else
+ fprintf(file, "%d;\n", howmany);
+ } else {
+ fprintf(file, "\t%ssize = ", string);
+ if (VarIndex) {
+ cref = count->argByReferenceUser ? "*" : "";
+ if (count->argMultiplier > 1 || howbig > 8)
+ fprintf(file, "%s%s%s * %d;\n", cref, count->argVarName, subindex,
+ count->argMultiplier * howbig / 8);
+ else
+ fprintf(file, "%s%s%s;\n", cref, count->argVarName, subindex);
+ }
+ else
+ fprintf(file, "\t%ssize = %d;\n", string, (howmany * howbig + 7)/8);
+ }
+ fprintf(file, "\t%scopy = MACH_MSG_OVERWRITE;\n", string);
+ fprintf(file, "\t%stype = MACH_MSG_OOL_%sDESCRIPTOR;\n", string,
+ (it->itPortType) ? "PORTS_" : "");
+ if (IS_MULTIPLE_KPD(it))
+ fprintf(file, "\t }\n");
+ if (finish) {
+ fprintf(file, "\t for (i = %s%s; i < %d; ptr++, i++) {\n",
+ (arg->argCount->argByReferenceUser) ? "*" : "",
+ arg->argCount->argVarName, it->itKPD_Number);
+ fprintf(file, "\t\tptr->copy = MACH_MSG_ALLOCATE;\n");
+ fprintf(file, "\t\tptr->type = MACH_MSG_OOL_%sDESCRIPTOR;\n",
+ (it->itPortType) ? "PORTS_" : "");
+ fprintf(file, "\t }\n");
+ }
+ if (IS_MULTIPLE_KPD(it))
+ fprintf(file, "\t}\n");
+ } else {
+ /* just a placeholder */
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, TRUE, FALSE, arg, TRUE);
+ fprintf(file, "\t\tptr->copy = MACH_MSG_ALLOCATE;\n");
+ fprintf(file, "\t\tptr->type = MACH_MSG_OOL_%sDESCRIPTOR;\n",
+ (it->itPortType) ? "PORTS_" : "");
+ fprintf(file, "\t }\n\t}\n");
+ }
+ else {
+ fprintf(file, "\tInOvTemplate->%s.copy = MACH_MSG_ALLOCATE;\n", arg->argMsgField);
+ /* not sure whether this is needed */
+ fprintf(file, "\tInOvTemplate->%s.type = MACH_MSG_OOL_%sDESCRIPTOR;\n",
+ arg->argMsgField, (it->itPortType) ? "PORTS_" : "");
+ }
+ }
+ }
+ }
+ fprintf(file, "\n");
+}
+
+/*************************************************************
+ * Writes code to copy an argument into the request message.
+ * Called by WriteRoutine for each argument that is to placed
+ * in the request message.
+ *************************************************************/
+
+static void
+WritePackArgValueNormal(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *ref = (arg->argByReferenceUser ||
+ it->itNativePointer) ? "*" : "";
+
+ if (IS_VARIABLE_SIZED_UNTYPED(it) || it->itNoOptArray) {
+ if (it->itString) {
+ /*
+ * Copy variable-size C string with mig_strncpy.
+ * Save the string length (+ 1 for trailing 0)
+ * in the argument`s count field.
+ */
+ fprintf(file,
+ "\tInP->%s = mig_strncpy(InP->%s, %s, %d);\n",
+ arg->argCount->argMsgField,
+ arg->argMsgField,
+ arg->argVarName,
+ it->itNumber);
+ } else if (it->itNoOptArray)
+ fprintf(file, "\t(void)memcpy((char *) InP->%s, (const char *) %s%s, %d);\n",
+ arg->argMsgField, ref, arg->argVarName, it->itTypeSize);
+ else {
+
+ /*
+ * Copy in variable-size inline array with (void)memcpy,
+ * after checking that number of elements doesn`t
+ * exceed declared maximum.
+ */
+ register argument_t *count = arg->argCount;
+ const char *countRef = count->argByReferenceUser ? "*" : "";
+ register ipc_type_t *btype = it->itElement;
+
+ /* Note btype->itNumber == count->argMultiplier */
+
+ if (akIdent(arg->argKind) != akeSubCount) {
+ /* we skip the SubCount case, as we have already taken care of */
+ fprintf(file, "\tif (%s%s > %d) {\n",
+ countRef, count->argVarName,
+ it->itNumber/btype->itNumber);
+ WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE");
+ fprintf(file, "\t}\n");
+ }
+
+ fprintf(file, "\t(void)memcpy((char *) InP->%s, (const char *) %s%s, ",
+ arg->argMsgField, ref, arg->argVarName);
+ if (btype->itTypeSize > 1)
+ fprintf(file, "%d * ", btype->itTypeSize);
+ fprintf(file, "%s%s);\n", countRef, count->argVarName);
+ }
+ }
+ else if (IS_OPTIONAL_NATIVE(it)) {
+ fprintf(file, "\tif ((InP->__Present__%s = (%s != %s))) {\n",
+ arg->argMsgField, arg->argVarName, it->itBadValue);
+ WriteCopyType(file, it, "\tInP->%s.__Real__%s", "/* %s%s */ %s%s",
+ arg->argMsgField, arg->argMsgField,
+ ref, arg->argVarName);
+ fprintf(file, "\t}\n");
+ }
+ else
+ WriteCopyType(file, it, "InP->%s", "/* %s */ %s%s",
+ arg->argMsgField, ref, arg->argVarName);
+ fprintf(file, "\n");
+}
+
+/*
+ * Calculate the size of a variable-length message field.
+ */
+static void
+WriteArgSizeVariable(FILE *file, register argument_t *arg, ipc_type_t *ptype)
+{
+ register int bsize = ptype->itElement->itTypeSize;
+ register argument_t *count = arg->argCount;
+
+ if (PackMsg == FALSE) {
+ fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize);
+ return;
+ }
+
+ /* If the base type size of the data field isn`t a multiple of 4,
+ we have to round up. */
+ if (bsize % itWordAlign != 0)
+ fprintf(file, "_WALIGN_");
+ fprintf(file, "(");
+ if (bsize > 1)
+ fprintf(file, "%d * ", bsize);
+ if (ptype->itString)
+ /* get count from descriptor in message */
+ fprintf(file, "InP->%s", count->argMsgField);
+ else
+ /* get count from argument */
+ fprintf(file, "%s%s",
+ count->argByReferenceUser ? "*" : "",
+ count->argVarName);
+ fprintf(file, ")");
+}
+
+static void
+WriteArgSizeOptional(FILE *file, argument_t *arg, ipc_type_t *ptype)
+{
+
+ fprintf(file, "(InP->__Present__%s ? _WALIGNSZ_(%s) : 0)",
+ arg->argVarName, ptype->itUserType);
+}
+
+static void
+WriteArgSize(FILE *file, argument_t *arg)
+
+{
+ ipc_type_t *ptype = arg->argType;
+
+ if (IS_OPTIONAL_NATIVE(ptype))
+ WriteArgSizeOptional(file, arg, ptype);
+ else
+ WriteArgSizeVariable(file, arg, ptype);
+}
+
+/*
+ * Adjust message size and advance request pointer.
+ * Called after packing a variable-length argument that
+ * has more arguments following.
+ */
+static void
+WriteAdjustMsgSize(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *ptype = arg->argType;
+
+ /* There are more In arguments. We need to adjust msgh_size
+ and advance InP, so we save the size of the current field
+ in msgh_size_delta. */
+
+ fprintf(file, "\tmsgh_size_delta = ");
+ WriteArgSize(file, arg);
+ fprintf(file, ";\n");
+
+ if (arg->argRequestPos == 0) {
+ /* First variable-length argument. The previous msgh_size value
+ is the minimum request size. */
+
+ fprintf(file, "\tmsgh_size = ");
+ rtMinRequestSize(file, arg->argRoutine, "Request");
+ fprintf(file, " + msgh_size_delta;\n");
+ } else
+ fprintf(file, "\tmsgh_size += msgh_size_delta;\n");
+
+ if (PackMsg == TRUE) {
+ fprintf(file,
+ "\tInP = (Request *) ((pointer_t) InP + msgh_size_delta - ");
+ if (IS_OPTIONAL_NATIVE(ptype))
+ fprintf(file,
+ "_WALIGNSZ_(%s)",
+ ptype->itUserType);
+ else
+ fprintf(file,
+ "%d",
+ ptype->itTypeSize + ptype->itPadSize);
+ fprintf(file,
+ ");\n\n");
+ }
+}
+
+/*
+ * Calculate the size of the message. Called after the
+ * last argument has been packed.
+ */
+static void
+WriteFinishMsgSize(FILE *file, register argument_t *arg)
+{
+ /* No more In arguments. If this is the only variable In
+ argument, the previous msgh_size value is the minimum
+ request size. */
+
+ if (arg->argRequestPos == 0) {
+ fprintf(file, "\tmsgh_size = ");
+ rtMinRequestSize(file, arg->argRoutine, "Request");
+ fprintf(file, " + (");
+ WriteArgSize(file, arg);
+ fprintf(file, ");\n");
+ }
+ else {
+ fprintf(file, "\tmsgh_size += ");
+ WriteArgSize(file, arg);
+ fprintf(file, ";\n");
+ }
+}
+
+static void
+WriteInitializeCount(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *ptype = arg->argCInOut->argParent->argType;
+ register ipc_type_t *btype = ptype->itElement;
+
+ fprintf(file, "\tif (%s%s < %d)\n",
+ arg->argByReferenceUser ? "*" : "",
+ arg->argVarName,
+ ptype->itNumber/btype->itNumber);
+ fprintf(file, "\t\tInP->%s = %s%s;\n",
+ arg->argMsgField,
+ arg->argByReferenceUser ? "*" : "",
+ arg->argVarName);
+ fprintf(file, "\telse\n");
+ fprintf(file, "\t\tInP->%s = %d;\n",
+ arg->argMsgField, ptype->itNumber/btype->itNumber);
+ fprintf(file, "\n");
+}
+
+/*
+ * Generate code to fill in all of the request arguments and their
+ * message types.
+ */
+static void
+WriteRequestArgs(FILE *file, register routine_t *rt)
+{
+ register argument_t *arg;
+ register argument_t *lastVarArg;
+
+ /*
+ * 1. The Kernel Processed Data
+ */
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
+ if (akCheckAll(arg->argKind, akbSendSnd|akbSendKPD))
+ (*arg->argKPD_Pack)(file, arg);
+
+ /*
+ * 2. The Data Stream
+ */
+ lastVarArg = argNULL;
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ /*
+ * Adjust message size and advance message pointer if
+ * the last request argument was variable-length and the
+ * request position will change.
+ */
+ if (lastVarArg != argNULL &&
+ lastVarArg->argRequestPos < arg->argRequestPos)
+ {
+ WriteAdjustMsgSize(file, lastVarArg);
+ lastVarArg = argNULL;
+ }
+
+ if ((akIdent(arg->argKind) == akeCountInOut) &&
+ akCheck(arg->argKind, akbSendSnd))
+ WriteInitializeCount(file, arg);
+ else if (akCheckAll(arg->argKind, akbSendSnd|akbSendBody))
+ WritePackArgValueNormal(file, arg);
+ /*
+ * Remember whether this was variable-length.
+ */
+ if (akCheckAll(arg->argKind, akbSendSnd|akbSendBody|akbVariable))
+ lastVarArg = arg;
+ }
+ /*
+ * Finish the message size.
+ */
+ if (lastVarArg != argNULL)
+ WriteFinishMsgSize(file, lastVarArg);
+}
+
+/*************************************************************
+ * Writes code to check that the return msgh_id is correct and that
+ * the size of the return message is correct. Called by
+ * WriteRoutine.
+ *************************************************************/
+static void
+WriteCheckIdentity(FILE *file, routine_t *rt)
+{
+ fprintf(file, "\tif (Out0P->Head.msgh_id != %d) {\n",
+ rt->rtNumber + SubsystemBase + 100);
+ fprintf(file, "\t if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)\n");
+ fprintf(file, "\t\t{ return MIG_SERVER_DIED; }\n");
+ fprintf(file, "\t else\n");
+ fprintf(file, "\t\t{ return MIG_REPLY_MISMATCH; }\n");
+ fprintf(file, "\t}\n");
+ fprintf(file, "\n");
+ if (!rt->rtSimpleReply)
+ fprintf(file, "\tmsgh_simple = !(Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);\n");
+ fprintf(file, "#if\t__MigTypeCheck\n");
+
+ if (!rt->rtNoReplyArgs)
+ fprintf(file, "\tmsgh_size = Out0P->Head.msgh_size;\n\n");
+
+ if (rt->rtSimpleReply)
+ {
+ /* Expecting a simple message. We can factor out the check for
+ a simple message, since the error reply message is also simple.
+ */
+ fprintf(file,
+ "\tif ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
+ if (rt->rtNoReplyArgs)
+ fprintf(file, "\t (Out0P->Head.msgh_size != sizeof(__Reply)))\n");
+ else {
+ /*
+ * We have an error iff:
+ * 1) the message size is not the one expected AND
+ * 2) the message size is also different from sizeof(mig_reply_error_t)
+ * or the RetCode == KERN_SUCCESS
+ */
+ if (rt->rtNumReplyVar > 0) {
+ fprintf(file, "\t ((msgh_size > sizeof(__Reply) || msgh_size < ");
+ rtMinReplySize(file, rt, "__Reply");
+ fprintf(file, ") &&\n");
+ } else
+ fprintf(file, "\t ((msgh_size != sizeof(__Reply)) &&\n");
+ fprintf(file, "\t (msgh_size != sizeof(mig_reply_error_t) ||\n");
+ fprintf(file, "\t Out0P->RetCode == KERN_SUCCESS)))\n");
+ }
+ }
+ else {
+ /* Expecting a complex message. */
+
+ fprintf(file, "\tif ((msgh_simple || Out0P->msgh_body.msgh_descriptor_count != %d ||\n",
+ rt->rtReplyKPDs);
+ if (rt->rtNumReplyVar > 0) {
+ fprintf(file, "\t msgh_size < ");
+ rtMinReplySize(file, rt, "__Reply");
+ fprintf(file, " || msgh_size > sizeof(__Reply)) &&\n");
+ } else
+ fprintf(file, "\t msgh_size != sizeof(__Reply)) &&\n");
+ fprintf(file, "\t (!msgh_simple || msgh_size != sizeof(mig_reply_error_t) ||\n");
+ fprintf(file, "\t ((mig_reply_error_t *)Out0P)->RetCode == KERN_SUCCESS))\n");
+ }
+ fprintf(file, "\t\t{ return MIG_TYPE_ERROR ; }\n");
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+ fprintf(file, "\n");
+}
+
+/*************************************************************
+ * Write code to generate error handling code if the RetCode
+ * argument of a Routine is not KERN_SUCCESS.
+ *************************************************************/
+static void
+WriteRetCodeCheck(FILE *file, routine_t *rt)
+{
+ if (rt->rtSimpleReply)
+ fprintf(file, "\tif (Out0P->RetCode != KERN_SUCCESS) {\n");
+ else
+ fprintf(file, "\tif (msgh_simple) {\n");
+ if (CheckNDR) {
+ fprintf(file, "#ifdef\t__NDR_convert__mig_reply_error_t__defined\n");
+ fprintf(file, "\t\t__NDR_convert__mig_reply_error_t((mig_reply_error_t *)Out0P);\n");
+ fprintf(file, "#endif\t/* __NDR_convert__mig_reply_error_t__defined */\n");
+ }
+ fprintf(file, "\t\treturn ((mig_reply_error_t *)Out0P)->RetCode;\n");
+ fprintf(file, "\t}\n");
+ fprintf(file, "\n");
+}
+
+/*
+ * argKPD_TypeCheck discipline for Port types.
+ */
+static void
+WriteTCheckKPD_port(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *tab = "";
+ char string[MAX_STR_LEN];
+ boolean_t close = FALSE;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, FALSE, FALSE, arg, TRUE);
+ (void)sprintf(string, "ptr->");
+ tab = "\t";
+ close = TRUE;
+ } else
+ (void)sprintf(string, "Out%dP->%s.", arg->argReplyPos, arg->argMsgField);
+ fprintf(file, "\t%sif (%stype != MACH_MSG_PORT_DESCRIPTOR",
+ tab, string);
+ if (arg->argPoly == argNULL && !it->itVarArray)
+ /* we can't check disposition when poly or VarArray,
+ (because some of the entries could be empty) */
+ fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, it->itOutNameStr);
+ fprintf(file,
+ ") {\n"
+ "\t\t%s" "return MIG_TYPE_ERROR;\n"
+ "\t%s" "}\n"
+ , tab, tab);
+ if (close)
+ fprintf(file, "\t }\n\t}\n");
+}
+
+/*
+ * argKPD_TypeCheck discipline for out-of-line types.
+ */
+static void
+WriteTCheckKPD_ool(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *tab;
+ char string[MAX_STR_LEN];
+ boolean_t test;
+ u_int howmany, howbig;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, FALSE, FALSE, arg, TRUE);
+ tab = "\t";
+ sprintf(string, "ptr->");
+ howmany = it->itElement->itNumber;
+ howbig = it->itElement->itSize;
+ test = !it->itVarArray && !it->itElement->itVarArray;
+ } else {
+ tab = "";
+ sprintf(string, "Out%dP->%s.", arg->argReplyPos, arg->argMsgField);
+ howmany = it->itNumber;
+ howbig = it->itSize;
+ test = !it->itVarArray;
+ }
+
+ fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_DESCRIPTOR", tab, string);
+ if (test)
+ /* if VarArray we may use no-op; if itElement->itVarArray size might change */
+ fprintf(file, " ||\n\t%s %ssize != %d", tab, string, (howmany * howbig + 7)/8);
+ fprintf(file,
+ ") {\n"
+ "\t\t%s" "return MIG_TYPE_ERROR;\n"
+ "\t%s" "}\n"
+ , tab, tab);
+ if (IS_MULTIPLE_KPD(it))
+ fprintf(file, "\t }\n\t}\n");
+}
+
+/*
+ * argKPD_TypeCheck discipline for out-of-line Port types.
+ */
+static void
+WriteTCheckKPD_oolport(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *tab;
+ char string[MAX_STR_LEN];
+ boolean_t test;
+ u_int howmany;
+ const char *howstr;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, FALSE, FALSE, arg, TRUE);
+ tab = "\t";
+ sprintf(string, "ptr->");
+ howmany = it->itElement->itNumber;
+ test = !it->itVarArray && !it->itElement->itVarArray;
+ howstr = it->itElement->itOutNameStr;
+ } else {
+ tab = "";
+ sprintf(string, "Out%dP->%s.", arg->argReplyPos, arg->argMsgField);
+ howmany = it->itNumber;
+ test = !it->itVarArray;
+ howstr = it->itOutNameStr;
+ }
+
+ fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_PORTS_DESCRIPTOR", tab, string);
+ if (test)
+ /* if VarArray we may use no-op; if itElement->itVarArray size might change */
+ fprintf(file, " ||\n\t%s %scount != %d", tab, string, howmany);
+ if (arg->argPoly == argNULL)
+ fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, howstr);
+ fprintf(file, ") {\n"
+ "\t\t%s" "return MIG_TYPE_ERROR;\n"
+ "\t%s" "}\n"
+ ,tab, tab);
+ if (IS_MULTIPLE_KPD(it))
+ fprintf(file, "\t }\n\t}\n");
+}
+
+/*************************************************************
+ * Writes code to check that the type of each of the arguments
+ * in the reply message is what is expected. Called by
+ * WriteRoutine for each out && typed argument in the reply message.
+ *************************************************************/
+static void
+WriteTypeCheck(FILE *file, register argument_t *arg)
+{
+ fprintf(file, "#if\t__MigTypeCheck\n");
+ (*arg->argKPD_TypeCheck)(file, arg);
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+}
+
+
+/*
+ * argKPD_Extract discipline for Port types.
+ */
+static void
+WriteExtractKPD_port(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ const char *ref = arg->argByReferenceUser ? "*" : "";
+ const char *subindex;
+ const char *recast = "";
+ ipc_type_t *real_it;
+
+ real_it = (IS_MULTIPLE_KPD(it)) ? it->itElement : it;
+#ifdef MIG_KERNEL_PORT_CONVERSION
+ if (IsKernelUser && streql(real_it->itUserType, "ipc_port_t"))
+ recast = "(mach_port_t)";
+#endif
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, FALSE, it->itVarArray, arg, FALSE);
+
+ fprintf(file, "\t\t%s[i] = %sptr->name;\n",
+ arg->argVarName, recast);
+ if (it->itVarArray) {
+ register argument_t *count = arg->argCount;
+ const char *cref = count->argByReferenceUser ? "*" : "";
+
+ fprintf(file, "\t if (Out%dP->%s > %s%s)\n", count->argReplyPos,
+ count->argVarName, cref, count->argVarName);
+ WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE");
+ }
+ fprintf(file, "\t}\n");
+ subindex = "[0]";
+ }
+ else {
+ fprintf(file, "\t%s%s = %sOut%dP->%s.name;\n", ref, arg->argVarName, recast, arg->argReplyPos, arg->argMsgField);
+ subindex = "";
+ }
+
+ if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnRcv)) {
+ register argument_t *poly = arg->argPoly;
+ const char *pref = poly->argByReferenceUser ? "*" : "";
+
+ fprintf(file, "\t%s%s = Out%dP->%s%s.disposition;\n",
+ pref, poly->argVarName, arg->argReplyPos, arg->argMsgField, subindex);
+ }
+}
+
+/*
+ * argKPD_Extract discipline for out-of-line types.
+ */
+static void
+WriteExtractKPD_ool(FILE *file, register argument_t *arg)
+{
+ const char *ref = arg->argByReferenceUser ? "*" : "";
+ register ipc_type_t *it = arg->argType;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, FALSE, it->itVarArray, arg, FALSE);
+ fprintf(file, "\t\t%s[i] = ptr->address;\n",
+ arg->argVarName);
+ fprintf(file, "\t}\n");
+ } else
+ fprintf(file, "\t%s%s = (%s)(Out%dP->%s.address);\n",
+ ref, arg->argVarName, arg->argType->itUserType,
+ arg->argReplyPos, arg->argMsgField);
+ /*
+ * In case of variable sized arrays,
+ * the count field will be retrieved from the untyped
+ * section of the message
+ */
+}
+
+/*
+ * argKPD_Extract discipline for out-of-line Port types.
+ */
+static void
+WriteExtractKPD_oolport(FILE *file, register argument_t *arg)
+{
+ const char *ref = arg->argByReferenceUser ? "*" : "";
+ register ipc_type_t *it = arg->argType;
+ const char *subindex;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ WriteKPD_Iterator(file, FALSE, FALSE, it->itVarArray, arg, FALSE);
+ fprintf(file, "\t\t%s[i] = ptr->address;\n",
+ arg->argVarName);
+ fprintf(file, "\t}\n");
+ subindex = "[0]";
+ }
+ else {
+ fprintf(file, "\t%s%s = (%s)(Out%dP->%s.address);\n", ref, arg->argVarName, arg->argType->itUserType, arg->argReplyPos, arg->argMsgField);
+ subindex = "";
+ }
+ /*
+ * In case of variable sized arrays,
+ * the count field will be retrieved from the untyped
+ * section of the message
+ */
+ if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnRcv)) {
+ register argument_t *poly = arg->argPoly;
+ const char *pref = poly->argByReferenceUser ? "*" : "";
+
+ fprintf(file, "\t%s%s = Out%dP->%s%s.disposition;\n",
+ pref, poly->argVarName, arg->argReplyPos, arg->argMsgField, subindex);
+ }
+}
+
+/*************************************************************
+ * Write code to copy an argument from the reply message
+ * to the parameter. Called by WriteRoutine for each argument
+ * in the reply message.
+ *************************************************************/
+
+static void
+WriteExtractArgValueNormal(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *argType = arg->argType;
+ const char *ref = arg->argByReferenceUser ? "*" : "";
+ char who[20];
+
+ if (akCheck(arg->argKind, akbUserImplicit))
+ sprintf(who, "TrailerP");
+ else
+ sprintf(who, "Out%dP", arg->argReplyPos);
+
+ if (IS_VARIABLE_SIZED_UNTYPED(argType) || argType->itNoOptArray) {
+ if (argType->itString) {
+ /*
+ * Copy out variable-size C string with mig_strncpy.
+ */
+ fprintf(file, "\t(void) mig_strncpy(%s%s, %s->%s, %d);\n",
+ ref,
+ arg->argVarName,
+ who,
+ arg->argMsgField,
+ argType->itNumber);
+ }
+ else if (argType->itNoOptArray)
+ fprintf(file, "\t(void)memcpy((char *) %s%s, (const char *) %s->%s, %d);\n",
+ ref, arg->argVarName, who, arg->argMsgField, argType->itTypeSize);
+ else {
+
+ /*
+ * Copy out variable-size inline array with (void)memcpy,
+ * after checking that number of elements doesn`t
+ * exceed user`s maximum.
+ */
+ register argument_t *count = arg->argCount;
+ const char *countRef = count->argByReferenceUser ? "*" : "";
+ register ipc_type_t *btype = argType->itElement;
+
+ /* Note count->argMultiplier == btype->itNumber */
+ /* Note II: trailer logic isn't supported in this case */
+ fprintf(file, "\tif (Out%dP->%s", count->argReplyPos, count->argMsgField);
+ if (arg->argCountInOut) {
+ fprintf(file, " > %s%s) {\n", countRef, count->argVarName);
+ }
+ else {
+ fprintf(file, " > %d) {\n", argType->itNumber/btype->itNumber);
+ }
+
+ /*
+ * If number of elements is too many for user receiving area,
+ * fill user`s area as much as possible. Return the correct
+ * number of elements.
+ */
+ fprintf(file, "\t\t(void)memcpy((char *) %s%s, (const char *) Out%dP->%s, ",
+ ref, arg->argVarName, arg->argReplyPos, arg->argMsgField);
+ if (btype->itTypeSize > 1)
+ fprintf(file, "%d * ", btype->itTypeSize);
+ if (arg->argCountInOut) {
+ fprintf(file, " %s%s);\n", countRef, count->argVarName);
+ }
+ else {
+ fprintf(file, " %d);\n", argType->itNumber/btype->itNumber);
+ }
+ fprintf(file, "\t\t%s%s = Out%dP->%s", countRef, count->argVarName, count->argReplyPos, count->argMsgField);
+ fprintf(file, ";\n");
+ WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE");
+
+ fprintf(file, "\t}\n");
+
+ fprintf(file, "\t(void)memcpy((char *) %s%s, (const char *) Out%dP->%s, ",
+ ref, arg->argVarName, arg->argReplyPos, arg->argMsgField);
+ if (btype->itTypeSize > 1)
+ fprintf(file, "%d * ",
+ btype->itTypeSize);
+ fprintf(file, "Out%dP->%s);\n",
+ count->argReplyPos, count->argMsgField);
+ }
+ }
+ else
+ WriteCopyType(file, argType,
+ "%s%s", "/* %s%s */ %s->%s",
+ ref, arg->argVarName, who, arg->argMsgField);
+ fprintf(file, "\n");
+}
+
+static void
+WriteCalcArgSize(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *ptype = arg->argType;
+ register ipc_type_t *btype = ptype->itElement;
+ argument_t *count = arg->argCount;
+ int multiplier = btype->itTypeSize;
+
+ /* If the base type size of the data field isn`t a multiple of 4,
+ we have to round up. */
+ if (btype->itTypeSize % itWordAlign != 0)
+ fprintf(file, "_WALIGN_(");
+
+ fprintf(file, "Out%dP->%s", count->argReplyPos, count->argMsgField);
+ if (multiplier > 1)
+ fprintf(file, " * %d", multiplier);
+
+ if (btype->itTypeSize % itWordAlign != 0)
+ fprintf(file, ")");
+}
+
+static void
+WriteCheckArgSize(FILE *file, routine_t *rt, argument_t *arg, const char *comparator)
+{
+ register ipc_type_t *ptype = arg->argType;
+ register ipc_type_t *btype = ptype->itElement;
+ argument_t *count = arg->argCount;
+ int multiplier = btype->itTypeSize;
+
+ fprintf(file, "\tif (((msgh_size - ");
+ rtMinReplySize(file, rt, "__Reply");
+ fprintf(file, ")");
+ if (multiplier > 1)
+ fprintf(file, " / %d", multiplier);
+ fprintf(file, "< Out%dP->%s) ||\n", count->argReplyPos, count->argMsgField);
+ fprintf(file, "\t (msgh_size %s ", comparator);
+ rtMinReplySize(file, rt, "__Reply");
+ fprintf(file, " + ");
+ WriteCalcArgSize(file, arg);
+ fprintf(file, ")");
+ fprintf(file, ")\n\t\t{ return MIG_TYPE_ERROR ; }\n");
+}
+
+
+/* NDR Conversion routines */
+
+
+static void
+WriteReplyNDRConvertIntRepArgCond(FILE *file, argument_t *arg)
+{
+ routine_t *rt = arg->argRoutine;
+
+ fprintf(file, "defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
+}
+
+static void
+WriteReplyNDRConvertCharRepArgCond(FILE *file, argument_t *arg)
+{
+ routine_t *rt = arg->argRoutine;
+
+ if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
+ fprintf(file, "defined(__NDR_convert__char_rep__Reply__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
+ else
+ fprintf(file, "0");
+}
+
+static void
+WriteReplyNDRConvertFloatRepArgCond(FILE *file, argument_t *arg)
+{
+ routine_t *rt = arg->argRoutine;
+
+ if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
+ fprintf(file, "defined(__NDR_convert__float_rep__Reply__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
+ else
+ fprintf(file, "0");
+}
+
+static void
+WriteReplyNDRConvertIntRepArgDecl(FILE *file, argument_t *arg)
+{
+ WriteNDRConvertArgDecl(file, arg, "int_rep", "Reply");
+}
+
+static void
+WriteReplyNDRConvertCharRepArgDecl(FILE *file, argument_t *arg)
+{
+ if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
+ WriteNDRConvertArgDecl(file, arg, "char_rep", "Reply");
+}
+
+static void
+WriteReplyNDRConvertFloatRepArgDecl(FILE *file, argument_t *arg)
+{
+ if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
+ WriteNDRConvertArgDecl(file, arg, "float_rep", "Reply");
+}
+
+
+
+static void
+WriteReplyNDRConvertArgUse(FILE *file, argument_t *arg, const char *convert)
+{
+ routine_t *rt = arg->argRoutine;
+ argument_t *count = arg->argCount;
+ char argname[MAX_STR_LEN];
+
+ if ((akIdent(arg->argKind) == akeCount || akIdent(arg->argKind) == akeCountInOut) &&
+ (arg->argParent && akCheck(arg->argParent->argKind, akbReturnNdr)))
+ return;
+
+ if (arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {
+ if (count && !arg->argSameCount && !strcmp(convert, "int_rep")) {
+ fprintf(file, "#if defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)\n", rt->rtName, count->argMsgField);
+ fprintf(file, "\t\t__NDR_convert__int_rep__Reply__%s_t__%s(&Out%dP->%s, Out%dP->NDR.int_rep);\n", rt->rtName, count->argMsgField, count->argReplyPos, count->argMsgField, count->argReplyPos);
+ fprintf(file, "#endif\t/* __NDR_convert__int_rep__Reply__%s_t__%s__defined */\n", rt->rtName, count->argMsgField);
+ }
+
+ sprintf(argname, "(%s)(Out%dP->%s.address)", FetchServerType(arg->argType), arg->argReplyPos, arg->argMsgField);
+ }
+ else {
+ sprintf(argname, "&Out%dP->%s", arg->argReplyPos, arg->argMsgField);
+ }
+
+ fprintf(file, "#if defined(__NDR_convert__%s__Reply__%s_t__%s__defined)\n", convert, rt->rtName, arg->argMsgField);
+ fprintf(file, "\t\t__NDR_convert__%s__Reply__%s_t__%s(%s, Out0P->NDR.%s", convert, rt->rtName, arg->argMsgField, argname, convert);
+ if (count)
+ fprintf(file, ", Out%dP->%s", count->argReplyPos, count->argMsgField);
+ fprintf(file, ");\n");
+ fprintf(file, "#endif /* __NDR_convert__%s__Reply__%s_t__%s__defined */\n", convert, rt->rtName, arg->argMsgField);
+}
+
+static void
+WriteReplyNDRConvertIntRepOneArgUse(FILE *file, argument_t *arg)
+{
+ routine_t *rt = arg->argRoutine;
+
+ fprintf(file, "#if defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)\n", rt->rtName, arg->argMsgField);
+ fprintf(file, "\tif (Out0P->NDR.int_rep != NDR_record.int_rep)\n");
+ fprintf(file, "\t\t__NDR_convert__int_rep__Reply__%s_t__%s(&Out%dP->%s, Out%dP->NDR.int_rep);\n", rt->rtName, arg->argMsgField, arg->argReplyPos, arg->argMsgField, arg->argReplyPos);
+ fprintf(file, "#endif\t/* __NDR_convert__int_rep__Reply__%s_t__%s__defined */\n", rt->rtName, arg->argMsgField);
+}
+
+static void
+WriteReplyNDRConvertIntRepArgUse(FILE *file, argument_t *arg)
+{
+ WriteReplyNDRConvertArgUse(file, arg, "int_rep");
+}
+
+static void
+WriteReplyNDRConvertCharRepArgUse(FILE *file, argument_t *arg)
+{
+ if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
+ WriteReplyNDRConvertArgUse(file, arg, "char_rep");
+}
+
+static void
+WriteReplyNDRConvertFloatRepArgUse(FILE *file, argument_t *arg)
+{
+ if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
+ WriteReplyNDRConvertArgUse(file, arg, "float_rep");
+}
+
+static void
+WriteCheckMsgSize(FILE *file, register argument_t *arg)
+{
+ register routine_t *rt = arg->argRoutine;
+
+ /* If there aren't any more Out args after this, then
+ we can use the msgh_size_delta value directly in
+ the TypeCheck conditional. */
+
+ if (CheckNDR && arg->argCount && !arg->argSameCount)
+ WriteReplyNDRConvertIntRepOneArgUse(file, arg->argCount);
+
+ if (arg->argReplyPos == rt->rtMaxReplyPos) {
+ fprintf(file, "#if\t__MigTypeCheck\n");
+
+ /*
+ * emit code to verify that the server-code-provided count does not exceed the maximum count allowed by the type.
+ */
+ fprintf(file, "\t" "if ( Out%dP->%s > %d )\n", arg->argCount->argReplyPos, arg->argCount->argMsgField, arg->argType->itNumber);
+ fputs("\t\t" "return MIG_TYPE_ERROR;\n", file);
+ /* ...end... */
+
+ WriteCheckArgSize(file, rt, arg, "!=");
+
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+ }
+ else {
+ /* If there aren't any more variable-sized arguments after this,
+ then we must check for exact msg-size and we don't need
+ to update msgh_size. */
+
+ boolean_t LastVarArg = arg->argReplyPos+1 == rt->rtNumReplyVar;
+
+ /* calculate the actual size in bytes of the data field. note
+ that this quantity must be a multiple of four. hence, if
+ the base type size isn't a multiple of four, we have to
+ round up. note also that btype->itNumber must
+ divide btype->itTypeSize (see itCalculateSizeInfo). */
+
+ fprintf(file, "\tmsgh_size_delta = ");
+ WriteCalcArgSize(file, arg);
+ fprintf(file, ";\n");
+ fprintf(file, "#if\t__MigTypeCheck\n");
+
+ /*
+ * Advance message pointer if the last reply argument was
+ * variable-length and the reply position will change.
+ */
+ fprintf(file, "\t" "if ( Out%dP->%s > %d )\n", arg->argCount->argReplyPos, arg->argCount->argMsgField, arg->argType->itNumber);
+ fputs("\t\t" "return MIG_TYPE_ERROR;\n", file);
+ /* ...end... */
+
+ WriteCheckArgSize(file, rt, arg, LastVarArg ? "!=" : "<");
+
+ if (!LastVarArg)
+ fprintf(file, "\tmsgh_size -= msgh_size_delta;\n");
+
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+ }
+ fprintf(file, "\n");
+}
+
+static void
+WriteAdjustReplyMsgPtr(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *ptype = arg->argType;
+
+ fprintf(file, "\t*Out%dPP = Out%dP = (__Reply *) ((pointer_t) Out%dP + msgh_size_delta - %d);\n\n",
+ arg->argReplyPos+1, arg->argReplyPos +1, arg->argReplyPos, ptype->itTypeSize + ptype->itPadSize);
+}
+
+static void
+WriteReplyArgs(FILE *file, register routine_t *rt)
+{
+ register argument_t *arg;
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ if (akCheckAll(arg->argKind, akbReturnRcv|akbReturnBody)) {
+ WriteExtractArgValueNormal(file, arg);
+ }
+ else if (akCheckAll(arg->argKind, akbReturnRcv|akbReturnKPD)) {
+ /*
+ * KPDs have argReplyPos 0, therefore they escape the above logic
+ */
+ (*arg->argKPD_Extract)(file, arg);
+ }
+ else if (akCheck(arg->argKind, akbUserImplicit)) {
+ WriteExtractArgValueNormal(file, arg);
+ }
+ }
+}
+
+/*************************************************************
+ * Writes code to return the return value. Called by WriteRoutine
+ * for routines and functions.
+ *************************************************************/
+static void
+WriteReturnValue(FILE *file, routine_t *rt)
+{
+ /* If returning RetCode, we have already checked that it is KERN_SUCCESS */
+ WriteReturn(file, rt, "\t", "KERN_SUCCESS", "\n");
+}
+
+/*************************************************************
+ * Writes the elements of the message type declaration: the
+ * msg_type structure, the argument itself and any padding
+ * that is required to make the argument a multiple of 4 bytes.
+ * Called by WriteRoutine for all the arguments in the request
+ * message first and then the reply message.
+ *************************************************************/
+static void
+WriteFieldDecl(FILE *file, argument_t *arg)
+{
+ if (akCheck(arg->argKind, akbSendKPD) ||
+ akCheck(arg->argKind, akbReturnKPD))
+ WriteFieldDeclPrim(file, arg, FetchKPDType);
+ else
+ WriteFieldDeclPrim(file, arg, FetchUserType);
+}
+
+/* Fill in the string with an expression that refers to the size
+ * of the specified array:
+ */
+static void
+GetArraySize(register argument_t *arg, char *size)
+{
+ register ipc_type_t *it = arg->argType;
+
+ if (it->itVarArray) {
+ if (arg->argCount->argByReferenceUser) {
+ sprintf(size, "*%s", arg->argCount->argVarName);
+ } else
+ sprintf(size, "%s", arg->argCount->argVarName);
+ } else {
+ sprintf(size, "%d", (it->itNumber * it->itSize + 7) / 8);
+ }
+}
+
+
+static void
+WriteRPCPortDisposition(FILE *file, register argument_t *arg)
+{
+ /*
+ * According to the MIG specification, the port disposition could be different
+ * on input and output. If we stay with this then a new bitfield will have
+ * to be added. Right now the port disposition is the same for in and out cases.
+ */
+ switch(arg->argType->itInName)
+ {
+
+ case MACH_MSG_TYPE_MOVE_RECEIVE:
+ fprintf(file, " | MACH_RPC_MOVE_RECEIVE");
+ break;
+
+ case MACH_MSG_TYPE_MOVE_SEND:
+ fprintf(file, " | MACH_RPC_MOVE_SEND");
+ break;
+
+ case MACH_MSG_TYPE_MOVE_SEND_ONCE:
+ fprintf(file, " | MACH_RPC_MOVE_SEND_ONCE");
+ break;
+
+ case MACH_MSG_TYPE_COPY_SEND:
+ fprintf(file, " | MACH_RPC_COPY_SEND");
+ break;
+
+ case MACH_MSG_TYPE_MAKE_SEND:
+ fprintf(file, " | MACH_RPC_MAKE_SEND");
+ break;
+
+ case MACH_MSG_TYPE_MAKE_SEND_ONCE:
+ fprintf(file, " | MACH_RPC_MAKE_SEND_ONCE");
+ break;
+ }
+}
+
+static void
+WriteRPCArgDescriptor(FILE *file, register argument_t *arg, int offset)
+{
+ fprintf(file, " {\n 0 ");
+ if (RPCPort(arg))
+ {
+ fprintf(file, "| MACH_RPC_PORT ");
+ if (arg->argType->itNumber > 1)
+ fprintf(file, "| MACH_RPC_ARRAY ");
+ if (arg->argType->itVarArray)
+ fprintf(file, "| MACH_RPC_VARIABLE ");
+ WriteRPCPortDisposition(file, arg);
+ }
+ else if (RPCPortArray(arg))
+ {
+ fprintf(file, "| MACH_RPC_PORT_ARRAY ");
+ if (arg->argType->itVarArray)
+ fprintf(file, "| MACH_RPC_VARIABLE ");
+ WriteRPCPortDisposition(file, arg);
+ }
+ else if (RPCFixedArray(arg))
+ fprintf(file, "| MACH_RPC_ARRAY_FIXED ");
+ else if (RPCVariableArray(arg))
+ fprintf(file, "| MACH_RPC_ARRAY_VARIABLE ");
+ if (argIsIn(arg))
+ fprintf(file, " | MACH_RPC_IN ");
+ if (argIsOut(arg))
+ fprintf(file, " | MACH_RPC_OUT ");
+ if ((! arg->argType->itInLine) && (! arg->argType->itMigInLine))
+ fprintf(file, " | MACH_RPC_POINTER ");
+ if (arg->argFlags & flDealloc)
+ fprintf(file, " | MACH_RPC_DEALLOCATE ");
+ if (arg->argFlags & flPhysicalCopy)
+ fprintf(file, " | MACH_RPC_PHYSICAL_COPY ");
+ fprintf(file, ",\n");
+ fprintf(file, " %d,\n", (arg->argType->itSize / 8));
+ fprintf(file, " %d,\n", arg->argType->itNumber);
+ fprintf(file, " %d,\n },\n", offset);
+}
+
+void
+WriteRPCRoutineDescriptor(FILE *file, routine_t *rt __unused, int arg_count,
+ int descr_count,
+ string_t stub_routine, string_t sig_array)
+{
+
+ fprintf(file, " { (mig_impl_routine_t) 0,\n\
+ (mig_stub_routine_t) %s, ",
+ stub_routine);
+ fprintf(file, "%d, %d, %s }", arg_count, descr_count, sig_array);
+}
+
+void
+WriteRPCRoutineArgDescriptor(FILE *file, register routine_t *rt)
+{
+ register argument_t *arg;
+ int offset = 0;
+ int size = 0;
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
+ {
+ boolean_t compound = arg->argType->itStruct && arg->argType->itInLine;
+
+ if (RPCPort(arg) || RPCPortArray(arg) ||
+ RPCFixedArray(arg) || RPCVariableArray(arg))
+ {
+ WriteRPCArgDescriptor(file, arg, offset);
+ size = 4;
+ }
+ if (! size)
+ {
+ if (compound)
+ size = arg->argType->itNumber * (arg->argType->itSize / 8);
+ else
+ size = (arg->argType->itSize / 8);
+ }
+ if (akCheck(arg->argKind, akbServerArg))
+ offset += size;
+ size = 0;
+ }
+}
+
+
+static void
+WriteRPCSignature(FILE *file, register routine_t *rt)
+{
+ int arg_count = 0;
+ int descr_count = 0;
+
+ fprintf(file, " kern_return_t rtn;\n");
+ descr_count = rtCountArgDescriptors(rt->rtArgs, &arg_count);
+ fprintf(file, " const static struct\n {\n");
+ fprintf(file, " struct rpc_routine_descriptor rd;\n");
+ fprintf(file, " struct rpc_routine_arg_descriptor rad[%d];\n", descr_count);
+ fprintf(file, " } sig =\n {\n");
+ WriteRPCRoutineDescriptor(file, rt, arg_count, descr_count, "0", "sig.rad, 0");
+ fprintf(file, ",\n");
+ fprintf(file, " {\n");
+ WriteRPCRoutineArgDescriptor(file, rt);
+ fprintf(file, "\n }\n");
+ fprintf(file, "\n };\n\n");
+}
+
+static void
+WriteRPCCall(FILE *file, register routine_t *rt)
+{
+ register argument_t *arg;
+ register int i;
+
+ i = 0;
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ if (akIdent(arg->argKind) == akeRequestPort) {
+ fprintf(file, " rtn = (MACH_RPC(&sig, (mach_msg_size_t)sizeof(sig), %d, %s,\n", rt->rtNumber + SubsystemBase, arg->argVarName);
+ fprintf(file, " (%s", arg->argVarName);
+ }
+ else if (akCheck(arg->argKind, akbServerArg))
+ {
+ if (i && (i++ % 6 == 0))
+ fprintf(file, ",\n ");
+ else
+ fprintf(file, ", ");
+ fprintf(file, "%s", arg->argVarName);
+ }
+ }
+ fprintf(file, ")));\n");
+ fprintf(file, "\n");
+ fprintf(file, " if (rtn != KERN_NO_ACCESS) return rtn;\n\n");
+ fprintf(file, "/* The following message rpc code is generated for the network case */\n\n");
+}
+
+static int
+CheckRPCCall(register routine_t *rt)
+{
+ register argument_t *arg;
+ register int i;
+
+ i = 0;
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
+ {
+ if (akCheck(arg->argKind, akbUserArg) &&
+ ((arg->argType->itOutName == (u_int)-1) || (arg->argType->itInName == (u_int)-1)))
+ {
+ return FALSE;
+ }
+ if (arg->argFlags & flMaybeDealloc)
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static void
+WriteRPCRoutine(FILE *file, register routine_t *rt)
+{
+ if (CheckRPCCall(rt))
+ {
+ WriteRPCSignature(file, rt);
+ WriteRPCCall(file, rt);
+ }
+}
+
+/********************** End UserRPCTrap Routines*************************/
+
+/* Process an IN/INOUT arg before the short-circuited RPC */
+static void
+WriteShortCircInArgBefore(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ char size[128];
+
+ fprintf(file, "\n\t/* IN %s: */\n", arg->argVarName);
+
+ if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) {
+ switch (arg->argKPD_Type) {
+
+ case MACH_MSG_PORT_DESCRIPTOR:
+ break;
+
+ case MACH_MSG_OOL_DESCRIPTOR:
+ /* Arg is an out-of-line array: */
+ if (!(arg->argFlags & flDealloc) &&
+ (!(arg->argFlags & flAuto) || !(arg->argFlags & flConst))) {
+ /* Need to map a copy of the array: */
+ GetArraySize(arg, size);
+ fprintf(file, "\t(void)vm_read(mach_task_self(),\n");
+ fprintf(file, "\t\t (vm_address_t) %s%s, %s, (vm_address_t *) &_%sTemp_, &_MIG_Ignore_Count_);\n",
+ (arg->argByReferenceUser ? "*" : ""),
+ arg->argVarName, size, arg->argVarName);
+ /* Point argument at the copy: */
+ fprintf(file, "\t*(char **)&%s%s = _%sTemp_;\n",
+ (arg->argByReferenceUser ? "*" : ""),
+ arg->argVarName,
+ arg->argVarName);
+ } else if ((arg->argFlags & flDealloc) &&
+ ((arg->argFlags & flAuto) || it->itMigInLine)) {
+ /* Point the temp var at the original argument: */
+ fprintf(file, "\t_%sTemp_ = (char *) %s%s;\n",
+ arg->argVarName,
+ (arg->argByReferenceUser ? "*" : ""),
+ arg->argVarName);
+ }
+ break;
+ case MACH_MSG_OOL_PORTS_DESCRIPTOR:
+ break;
+ default:
+ printf("MiG internal error: type of kernel processed data unknown\n");
+ exit(1);
+ } /* end of switch */
+ } else if (it->itNumber > 1) {
+ if (it->itStruct) {
+ /* Arg is a struct -- nothing to do. */
+ } else {
+ /* Arg is a C string or an in-line array: */
+ if (!argIsOut(arg) && !(arg->argFlags & flConst)) {
+ /* Have to copy it into a temp. Use a stack var, if this would
+ * not overflow the -maxonstack specification:
+ */
+ if (it->itTypeSize <= sizeof(char *) ||
+ rtMessOnStack(arg->argRoutine) ||
+ arg->argRoutine->rtTempBytesOnStack +
+ it->itTypeSize <= (u_int)MaxMessSizeOnStack) {
+ fprintf(file, "\t{ char _%sTemp_[%d];\n",
+ arg->argVarName, it->itTypeSize);
+ arg->argRoutine->rtTempBytesOnStack += it->itTypeSize;
+ arg->argTempOnStack = TRUE;
+ }
+ else {
+ fprintf(file, "\t{ _%sTemp_ = (char *) %s(%d);\n", arg->argVarName, MessAllocRoutine, it->itTypeSize);
+ arg->argTempOnStack = FALSE;
+ }
+ WriteCopyArg(file, arg, "_%sTemp_", "/* %s */ (char *) %s",
+ arg->argVarName, arg->argVarName);
+ /* Point argument at temp: */
+ fprintf(file, "\t *(char **)&%s%s = _%sTemp_;\n",
+ (arg->argByReferenceUser ? "*" : ""),
+ arg->argVarName,
+ arg->argVarName);
+ fprintf(file, "\t}\n");
+ }
+ }
+ }
+}
+
+
+/* Process an INOUT/OUT arg before the short-circuited RPC */
+static void
+WriteShortCircOutArgBefore(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+
+ fprintf(file, "\n\t/* OUT %s: */\n", arg->argVarName);
+
+
+ fprintf(file, "\n\t/* OUT %s: */\n", arg->argVarName);
+
+ if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) {
+ switch (arg->argKPD_Type) {
+ case MACH_MSG_PORT_DESCRIPTOR:
+ break;
+ case MACH_MSG_OOL_DESCRIPTOR:
+ /* Arg is an out-of-line array: */
+ if (!argIsIn(arg) && (arg->argFlags & flOverwrite)) {
+ /* Point the temp var at the original argument: */
+ fprintf(file, "\t _%sTemp_ = (char *) %s%s;\n",
+ arg->argVarName,
+ (arg->argByReferenceUser ? "*" : ""),
+ arg->argVarName);
+ }
+ break;
+ case MACH_MSG_OOL_PORTS_DESCRIPTOR:
+ break;
+ default:
+ printf("MiG internal error: type of kernel processed data unknown\n");
+ exit(1);
+ } /* end of switch */
+ } else if (it->itNumber > 1) {
+ /* Arg is an in-line array: */
+ }
+}
+
+
+
+/* Process an IN arg after the short-circuited RPC */
+static void
+WriteShortCircInArgAfter(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ char size[128];
+
+ fprintf(file, "\n\t/* IN %s: */\n", arg->argVarName);
+
+ if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) {
+ switch (arg->argKPD_Type) {
+
+ case MACH_MSG_PORT_DESCRIPTOR:
+ break;
+
+ case MACH_MSG_OOL_DESCRIPTOR:
+ /* Arg is an out-of-line array: */
+ GetArraySize(arg, size);
+ if ((!(arg->argFlags & flAuto) && it->itMigInLine) ||
+ ((arg->argFlags & flAuto) &&
+ ((arg->argFlags & flDealloc) ||
+ !(arg->argFlags & flConst))
+ )) {
+ /* Need to dealloc the temporary: */
+ fprintf(file, "\t(void)vm_deallocate(mach_task_self(),");
+ fprintf(file, " (vm_address_t *) _%sTemp_, %s);\n",
+ arg->argVarName, size);
+ }
+ break;
+ case MACH_MSG_OOL_PORTS_DESCRIPTOR:
+ break;
+ default:
+ printf("MiG internal error: type of kernel processed data unknown\n");
+ exit(1);
+ } /* end of switch */
+ } else if (it->itNumber > 1) {
+ if (it->itStruct) {
+ /* Arg is a struct -- nothing to do. */
+ } else {
+ /* Arg is a C string or an in-line array: */
+ if (!argIsOut(arg) && !(arg->argFlags & flConst)) {
+ /* A temp needs to be deallocated, if not on stack: */
+ if (!arg->argTempOnStack) {
+ fprintf(file, "\t%s(_%sTemp_, %d);\n",
+ MessFreeRoutine, arg->argVarName, it->itTypeSize);
+ }
+ }
+ }
+ }
+}
+
+static void
+WriteShortCircOutArgAfter(FILE *file, register argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+ char size[128];
+
+ fprintf(file, "\n\t/* OUT %s: */\n", arg->argVarName);
+
+ if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) {
+ switch (arg->argKPD_Type) {
+
+ case MACH_MSG_PORT_DESCRIPTOR:
+ break;
+
+ case MACH_MSG_OOL_DESCRIPTOR:
+ /* Arg is an out-of-line array: */
+
+ /* Calculate size of array: */
+ GetArraySize(arg, size);
+ if (!(arg->argFlags & flDealloc) || (arg->argFlags & flOverwrite)) {
+ /* Copy argument to vm_allocated Temp: */
+ fprintf(file, "\t(void)vm_read(mach_task_self(),\n");
+ fprintf(file, "\t\t (vm_address_t) %s%s, %s, (vm_address_t *) &_%sTemp_, &_MIG_Ignore_Count_);\n",
+ (arg->argByReferenceUser ? "*" : ""),
+ arg->argVarName, size, arg->argVarName);
+ if (!argIsIn(arg) && (arg->argFlags & flDealloc) &&
+ (arg->argFlags & flOverwrite)) {
+ /* Deallocate argument returned by server */
+ fprintf(file, "\t(void)vm_deallocate(mach_task_self(),");
+ fprintf(file, " (vm_address_t *) %s%s, %s);\n",
+ (arg->argByReferenceUser ? "*" : ""),
+ arg->argVarName, size);
+ }
+ /* Point argument at new temporary: */
+ fprintf(file, "\t*(char **)&%s%s = _%sTemp_;\n",
+ (arg->argByReferenceUser ? "*" : ""),
+ arg->argVarName,
+ arg->argVarName);
+ }
+ break;
+ case MACH_MSG_OOL_PORTS_DESCRIPTOR:
+ break;
+ default:
+ printf("MiG internal error: type of kernel processed data unknown\n");
+ exit(1);
+ } /* end of switch */
+ } else if (it->itNumber != 1) {
+ /* Arg is an in-line array: */
+ }
+}
+
+
+static void
+WriteShortCircRPC(FILE *file, register routine_t *rt)
+{
+ register argument_t *arg;
+ register int server_argc, i;
+ boolean_t ShortCircOkay = TRUE;
+ boolean_t first_OOL_arg = TRUE;
+
+ fprintf(file, " if (0 /* Should be: !(%s & 0x3) XXX */) {\n",
+ rt->rtRequestPort->argVarName);
+
+ if (rt->rtOneWay) {
+ /* Do not short-circuit simple routines: */
+ ShortCircOkay = FALSE;
+ } else {
+ /* Scan for any types we can't yet handle. If found, give up on short-
+ * circuiting and fall back to mach_msg:
+ */
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ if (arg->argFlags & flMaybeDealloc) {
+ ShortCircOkay = FALSE;
+ break;
+ }
+ /* Can't yet handle ports: */
+ if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD) &&
+ (arg->argKPD_Type == MACH_MSG_PORT_DESCRIPTOR ||
+ arg->argKPD_Type == MACH_MSG_OOL_PORTS_DESCRIPTOR)) {
+ ShortCircOkay = FALSE;
+ break;
+ }
+ }
+ }
+
+ if (ShortCircOkay) {
+
+ fprintf(file,
+ " rpc_subsystem_t subsystem = ((rpc_port_t)%s)->rp_subsystem;\n",
+ rt->rtRequestPort->argVarName);
+ fprintf(file, "\n");
+ fprintf(file, " if (subsystem && subsystem->start == %d) {\n",
+ SubsystemBase);
+ fprintf(file, "\tkern_return_t rtn;\n");
+ fprintf(file, "\n");
+
+ /* Declare temp vars for out-of-line array args, and for all array
+ * args, if -maxonstack has forced us to allocate in-line arrays
+ * off the stack:
+ */
+ rt->rtTempBytesOnStack = 0;
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ arg->argTempOnStack = FALSE;
+ if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD) &&
+ arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {
+ if (first_OOL_arg) {
+ /* Need a garbage temporary to hold the datacount
+ * returned by vm_read, which we always ignore:
+ */
+ fprintf(file,
+ "\tmach_msg_type_number_t _MIG_Ignore_Count_;\n");
+ first_OOL_arg = FALSE;
+ }
+ } else if (!rtMessOnStack(rt) &&
+ arg->argType->itNumber > 1 && !arg->argType->itStruct) {
+ } else
+ continue;
+ fprintf(file, "\tchar *_%sTemp_;\n", arg->argVarName);
+ rt->rtTempBytesOnStack += sizeof(char *);
+ }
+
+ /* Process the IN arguments, in order: */
+
+ fprintf(file, "\t/* Pre-Process the IN arguments: */\n");
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ if (argIsIn(arg))
+ WriteShortCircInArgBefore(file, arg);
+ if (argIsOut(arg))
+ WriteShortCircOutArgBefore(file, arg);
+ }
+ fprintf(file, "\n");
+
+ /* Count the number of server args: */
+ server_argc = 0;
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
+ if (akCheck(arg->argKind, akbServerArg))
+ server_argc++;
+
+ /* Call RPC_SIMPLE to switch to server stack and function: */
+ i = 0;
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ if (akIdent(arg->argKind) == akeRequestPort) {
+ fprintf(file, "\trtn = RPC_SIMPLE(%s, %d, %d, (",
+ arg->argVarName, rt->rtNumber + SubsystemBase,
+ server_argc);
+ fprintf(file, "%s", arg->argVarName);
+ } else if (akCheck(arg->argKind, akbServerArg)) {
+ if (i++ % 6 == 0)
+ fprintf(file, ",\n\t\t");
+ else
+ fprintf(file, ", ");
+ fprintf(file, "%s", arg->argVarName);
+ }
+ }
+ fprintf(file, "));\n");
+ fprintf(file, "\n");
+
+ /* Process the IN and OUT arguments, in order: */
+ fprintf(file, "\t/* Post-Process the IN and OUT arguments: */\n");
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ if (argIsIn(arg))
+ WriteShortCircInArgAfter(file, arg);
+ if (argIsOut(arg))
+ WriteShortCircOutArgAfter(file, arg);
+ }
+ fprintf(file, "\n");
+
+ fprintf(file, "\treturn rtn;\n");
+ fprintf(file, " }\n");
+ }
+
+ /* In latest design, the following is not necessary, because in
+ * kernel-loaded tasks, the Mach port name is the same as the handle
+ * used by the RPC mechanism, namely a pointer to the ipc_port, and
+ * in user-mode tasks, the Mach port name gets renamed to be a pointer
+ * to the user-mode rpc_port_t struct.
+ */
+#if 0
+ if (IsKernelUser)
+ fprintf(file, " %s = (ipc_port_t)%s->rp_receiver_name;\n",
+ rt->rtRequestPort->argVarName,
+ rt->rtRequestPort->argVarName);
+ else
+ fprintf(file, " %s = ((rpc_port_t)%s)->rp_receiver_name;\n",
+ rt->rtRequestPort->argVarName,
+ rt->rtRequestPort->argVarName);
+#endif
+
+ fprintf(file, " }\n");
+}
+
+static void
+WriteStubDecl(FILE *file, register routine_t *rt)
+{
+ fprintf(file, "\n");
+ fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
+ fprintf(file, "mig_external %s %s\n", ReturnTypeStr(rt), rt->rtUserName);
+ 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, "\t(");
+ WriteList(file, rt->rtArgs, WriteNameDecl, akbUserArg, ", ", "");
+ fprintf(file, ")\n");
+ WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ";\n", ";\n");
+ fprintf(file, "#endif\t/* %s */\n", NewCDecl);
+ }
+ fprintf(file, "{\n");
+}
+
+static void
+InitKPD_Disciplines(argument_t *args)
+{
+ argument_t *arg;
+ extern void KPD_noop();
+ extern void KPD_error();
+ extern void WriteTemplateKPD_port();
+ extern void WriteTemplateKPD_ool();
+ extern void WriteTemplateKPD_oolport();
+
+ /*
+ * WriteKPD_port, WriteExtractKPD_port,
+ * WriteKPD_ool, WriteExtractKPD_ool,
+ * WriteKPD_oolport, WriteExtractKPD_oolport
+ * are local to this module (which is the reason why this initialization
+ * takes place here rather than in utils.c).
+ * Common routines for user and server will be established SOON, and
+ * all of them (including the initialization) will be transfert to
+ * utils.c
+ * All the KPD disciplines are defaulted to be KPD_error().
+ * Note that akbSendKPD and akbReturnKPd are not exclusive,
+ * because of inout type of parameters.
+ */
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD))
+ switch (arg->argKPD_Type) {
+
+ case MACH_MSG_PORT_DESCRIPTOR:
+ arg->argKPD_Init = KPD_noop;
+ if akCheck(arg->argKind, akbSendKPD) {
+ arg->argKPD_Template = WriteTemplateKPD_port;
+ arg->argKPD_Pack = WriteKPD_port;
+ }
+ if akCheck(arg->argKind, akbReturnKPD) {
+ arg->argKPD_Extract = WriteExtractKPD_port;
+ arg->argKPD_TypeCheck = WriteTCheckKPD_port;
+ }
+ break;
+
+ case MACH_MSG_OOL_DESCRIPTOR:
+ arg->argKPD_Init = KPD_noop;
+ if akCheck(arg->argKind, akbSendKPD) {
+ arg->argKPD_Template = WriteTemplateKPD_ool;
+ arg->argKPD_Pack = WriteKPD_ool;
+ }
+ if akCheck(arg->argKind, akbReturnKPD) {
+ arg->argKPD_TypeCheck = WriteTCheckKPD_ool;
+ arg->argKPD_Extract = WriteExtractKPD_ool;
+ }
+ break;
+
+ case MACH_MSG_OOL_PORTS_DESCRIPTOR:
+ arg->argKPD_Init = KPD_noop;
+ if akCheck(arg->argKind, akbSendKPD) {
+ arg->argKPD_Template = WriteTemplateKPD_oolport;
+ arg->argKPD_Pack = WriteKPD_oolport;
+ }
+ if akCheck(arg->argKind, akbReturnKPD) {
+ arg->argKPD_TypeCheck = WriteTCheckKPD_oolport;
+ arg->argKPD_Extract = WriteExtractKPD_oolport;
+ }
+ break;
+
+ default:
+ printf("MiG internal error: type of kernel processed data unknown\n");
+ exit(1);
+ } /* end of switch */
+}
+
+static void
+WriteLimitCheck(FILE *file, routine_t *rt)
+{
+ if (MaxMessSizeOnStack == -1 || UserTypeLimit == -1)
+ return;
+ if (!rt->rtRequestUsedLimit && !rt->rtReplyUsedLimit)
+ return;
+ fprintf(file, "#if LimitCheck\n");
+ if (rt->rtRequestUsedLimit) {
+ if (rt->rtRequestFits) {
+ fprintf(file, "\tif ((sizeof(Request) - %d) > %d)\n",
+ rt->rtRequestSizeKnown, UserTypeLimit);
+ fprintf(file, "\t __RequestOnStackAbort(%d, \"%s\");\n",
+ SubsystemBase + rt->rtNumber, rt->rtName);
+ } else if (rt->rtReplyFits) {
+ fprintf(file, "\tif (sizeof(Request) < %d)\n",
+ MaxMessSizeOnStack);
+ fprintf(file, "\t __MessageOffStackNote(%d, \"%s\");\n",
+ SubsystemBase + rt->rtNumber, rt->rtName);
+ }
+ }
+ if (rt->rtReplyUsedLimit) {
+ if (rt->rtReplyFits) {
+ fprintf(file, "\tif ((sizeof(Reply) - %d) > %d)\n",
+ rt->rtReplySizeKnown, UserTypeLimit);
+ fprintf(file, "\t __ReplyOnStackAbort(%d, \"%s\");\n",
+ SubsystemBase + rt->rtNumber, rt->rtName);
+ } else if (rt->rtRequestFits) {
+ fprintf(file, "\tif (sizeof(Reply) < %d)\n",
+ MaxMessSizeOnStack);
+ fprintf(file, "\t __MessageOffStackNote(%d, \"%s\");\n",
+ SubsystemBase + rt->rtNumber, rt->rtName);
+ }
+ }
+ if (rt->rtRequestUsedLimit && rt->rtReplyUsedLimit &&
+ ! (rt->rtRequestFits || rt->rtReplyFits)) {
+ fprintf(file, "\tif (sizeof(Request) < %d \n",
+ MaxMessSizeOnStack);
+ fprintf(file, "&& sizeof(Reply) < %d)\n",
+ MaxMessSizeOnStack);
+ fprintf(file, "\t __MessageOffStackNote(%d, \"%s\");\n",
+ SubsystemBase + rt->rtNumber, rt->rtName);
+ }
+ fprintf(file, "#endif /* LimitCheck */\n");
+}
+
+static void
+WriteCheckReply(FILE *file, routine_t *rt)
+{
+ u_int i;
+
+ /* initialize the disciplines for the handling of KPDs */
+ InitKPD_Disciplines(rt->rtArgs);
+
+ if (rt->rtOneWay)
+ return;
+
+ fprintf(file, "\n");
+ fprintf(file, "#if ( __MigTypeCheck ");
+ if (CheckNDR)
+ fprintf(file, "|| __NDR_convert__ ");
+ fprintf(file, ")\n");
+ fprintf(file, "#if __MIG_check__Reply__%s_subsystem__\n", SubsystemName);
+ fprintf(file, "#if !defined(__MIG_check__Reply__%s_t__defined)\n", rt->rtName);
+ fprintf(file, "#define __MIG_check__Reply__%s_t__defined\n", rt->rtName);
+ if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbReply)) {
+ WriteList(file, rt->rtArgs, WriteReplyNDRConvertIntRepArgDecl, akbReturnNdr, "\n", "\n");
+ WriteList(file, rt->rtArgs, WriteReplyNDRConvertCharRepArgDecl, akbReturnNdr, "\n", "\n");
+ WriteList(file, rt->rtArgs, WriteReplyNDRConvertFloatRepArgDecl, akbReturnNdr, "\n", "\n");
+ }
+ fprintf(file, "\n");
+ fprintf(file, "mig_internal kern_return_t __MIG_check__Reply__%s_t(__Reply__%s_t *Out0P", rt->rtName, rt->rtName);
+ for (i = 1; i <= rt->rtMaxReplyPos; i++)
+ fprintf(file, ", __Reply__%s_t **Out%dPP", rt->rtName, i);
+ fprintf(file, ")\n{\n");
+
+
+ fprintf(file, "\n\ttypedef __Reply__%s_t __Reply;\n", rt->rtName);
+ for (i = 1; i <= rt->rtMaxReplyPos; i++)
+ fprintf(file, "\t__Reply *Out%dP;\n", i);
+ if (!rt->rtSimpleReply)
+ fprintf(file, "\tboolean_t msgh_simple;\n");
+ if (!rt->rtNoReplyArgs) {
+ fprintf(file, "#if\t__MigTypeCheck\n");
+ fprintf(file, "\tunsigned int msgh_size;\n");
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+ }
+ if (rt->rtMaxReplyPos > 0)
+ fprintf(file, "\tunsigned int msgh_size_delta;\n");
+ if (rt->rtNumReplyVar > 0 || rt->rtMaxReplyPos > 0)
+ fprintf(file, "\n");
+
+ /* Check the values that are returned in the reply message */
+
+ WriteCheckIdentity(file, rt);
+
+ /* If the reply message has no Out parameters or return values
+ other than the return code, we can type-check it and
+ return it directly. */
+
+ if (rt->rtNoReplyArgs && !rt->rtUserImpl) {
+ if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbReply) && rt->rtRetCode)
+ WriteReplyNDRConvertIntRepOneArgUse(file, rt->rtRetCode);
+ WriteReturn(file, rt, "\t", stRetCode, "\n");
+ }
+ else {
+ if (UseEventLogger)
+ WriteLogMsg(file, rt, LOG_USER, LOG_REPLY);
+
+ WriteRetCodeCheck(file, rt);
+
+ /* Type Checking for the Out parameters which are typed */
+ WriteList(file, rt->rtArgs, WriteTypeCheck, akbReturnKPD, "\n", "\n");
+
+ {
+ register argument_t *arg, *lastVarArg;
+
+ lastVarArg = argNULL;
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ /*
+ * Advance message pointer if the last reply argument was
+ * variable-length and the reply position will change.
+ */
+ if (lastVarArg != argNULL &&
+ lastVarArg->argReplyPos < arg->argReplyPos) {
+ WriteAdjustReplyMsgPtr(file, lastVarArg);
+ lastVarArg = argNULL;
+ }
+
+ if (akCheckAll(arg->argKind, akbReturnRcv|akbReturnBody)) {
+ if (akCheck(arg->argKind, akbVariable)) {
+ WriteCheckMsgSize(file, arg);
+ lastVarArg = arg;
+ }
+ }
+ }
+ }
+
+ if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbReply)) {
+ fprintf(file, "#if\t");
+ WriteList(file, rt->rtArgs, WriteReplyNDRConvertIntRepArgCond, akbReturnNdr, " || \\\n\t", "\n");
+ fprintf(file, "\tif (Out0P->NDR.int_rep != NDR_record.int_rep) {\n");
+ WriteList(file, rt->rtArgs, WriteReplyNDRConvertIntRepArgUse, akbReturnNdr, "", "");
+ fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__int_rep...) */\n\n");
+
+ fprintf(file, "#if\t");
+ WriteList(file, rt->rtArgs, WriteReplyNDRConvertCharRepArgCond, akbReturnNdr, " || \\\n\t", "\n");
+ fprintf(file, "\tif (Out0P->NDR.char_rep != NDR_record.char_rep) {\n");
+ WriteList(file, rt->rtArgs, WriteReplyNDRConvertCharRepArgUse, akbReturnNdr, "", "");
+ fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__char_rep...) */\n\n");
+
+ fprintf(file, "#if\t");
+ WriteList(file, rt->rtArgs, WriteReplyNDRConvertFloatRepArgCond, akbReturnNdr, " || \\\n\t", "\n");
+ fprintf(file, "\tif (Out0P->NDR.float_rep != NDR_record.float_rep) {\n");
+ WriteList(file, rt->rtArgs, WriteReplyNDRConvertFloatRepArgUse, akbReturnNdr, "", "");
+ fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__float_rep...) */\n\n");
+ }
+ fprintf(file, "\treturn MACH_MSG_SUCCESS;\n");
+ }
+ fprintf(file, "}\n");
+ fprintf(file, "#endif /* !defined(__MIG_check__Reply__%s_t__defined) */\n", rt->rtName);
+ fprintf(file, "#endif /* __MIG_check__Reply__%s_subsystem__ */\n", SubsystemName);
+ fprintf(file, "#endif /* ( __MigTypeCheck ");
+ if (CheckNDR)
+ fprintf(file, "|| __NDR_convert__ ");
+ fprintf(file, ") */\n\n");
+}
+
+static void
+WriteCheckReplyCall(FILE *file, routine_t *rt)
+{
+ u_int i;
+
+ fprintf(file, "\n");
+ fprintf(file, "#if\tdefined(__MIG_check__Reply__%s_t__defined)\n", rt->rtName);
+ fprintf(file, "\tcheck_result = __MIG_check__Reply__%s_t((__Reply__%s_t *)Out0P", rt->rtName, rt->rtName);
+ for (i = 1; i <= rt->rtMaxReplyPos; i++)
+ fprintf(file, ", (__Reply__%s_t **)&Out%dP", rt->rtName, i);
+ fprintf(file, ");\n");
+ fprintf(file, "\tif (check_result != MACH_MSG_SUCCESS)\n");
+ WriteReturnMsgError(file, rt, TRUE, argNULL, "check_result");
+ fprintf(file, "#endif\t/* defined(__MIG_check__Reply__%s_t__defined) */\n", rt->rtName);
+ fprintf(file, "\n");
+}
+
+void
+WriteCheckReplies(FILE *file, statement_t *stats)
+{
+ statement_t *stat;
+
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ if (stat->stKind == skRoutine)
+ WriteCheckReply(file, stat->stRoutine);
+}
+
+static void
+WriteCheckReplyTrailerArgs(FILE *file, routine_t *rt)
+{
+ register argument_t *arg;
+
+ if (rt->rtUserImpl)
+ WriteCheckTrailerHead(file, rt, TRUE);
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+ if (akCheck(arg->argKind, akbUserImplicit))
+ WriteCheckTrailerSize(file, TRUE, arg);
+ }
+ if (rt->rtUserImpl)
+ fprintf(file, "\n");
+}
+
+
+/*************************************************************
+ * Writes all the code comprising a routine body. Called by
+ * WriteUser for each routine.
+ *************************************************************/
+static void
+WriteRoutine(FILE *file, register routine_t *rt)
+{
+ /* write the stub's declaration */
+ WriteStubDecl(file, rt);
+
+ /* Use the RPC trap for user-user and user-kernel RPC */
+ if (UseRPCTrap)
+ WriteRPCRoutine(file, rt);
+
+ /* write the code for doing a short-circuited RPC: */
+ if (ShortCircuit)
+ WriteShortCircRPC(file, rt);
+
+ /* typedef of structure for Request and Reply messages */
+ WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest,
+ "Request", rt->rtSimpleRequest, FALSE, FALSE, FALSE);
+ if (!rt->rtOneWay) {
+ WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply,
+ "Reply", rt->rtSimpleReply, TRUE, rt->rtUserImpl, FALSE);
+ WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply,
+ "__Reply", rt->rtSimpleReply, FALSE, FALSE, FALSE);
+ }
+ if (rt->rtOverwrite)
+ WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply|akbOverwrite,
+ "OverwriteTemplate", FALSE, TRUE, FALSE, TRUE);
+ /*
+ * Define a Minimal Reply structure to be used in case of errors
+ */
+ fprintf(file, "\t/*\n");
+ fprintf(file, "\t * typedef struct {\n");
+ fprintf(file, "\t * \tmach_msg_header_t Head;\n");
+ fprintf(file, "\t * \tNDR_record_t NDR;\n");
+ fprintf(file, "\t * \tkern_return_t RetCode;\n");
+ fprintf(file, "\t * } mig_reply_error_t;\n");
+ fprintf(file, "\t */\n");
+ fprintf(file, "\n");
+
+
+ /* declarations for local vars: Union of Request and Reply messages,
+ InP, OutP and return value */
+
+ WriteVarDecls(file, rt);
+
+ /* declarations and initializations of the mach_msg_type_descriptor_t variables
+ for each argument that is a Kernel Processed Data */
+
+ WriteList(file, rt->rtArgs, WriteTemplateDeclIn, akbRequest | akbSendKPD, "\n", "\n");
+
+ WriteLimitCheck(file, rt);
+ WriteRetCodeArg(file, rt);
+
+ /* fill in the fields that are non related to parameters */
+
+ if (!rt->rtSimpleRequest)
+ fprintf(file, "\tInP->msgh_body.msgh_descriptor_count = %d;\n",
+ rt->rtRequestKPDs);
+
+ /* fill in all the request message types and then arguments */
+
+ WriteRequestArgs(file, rt);
+
+ /* fill in request message head */
+
+ WriteRequestHead(file, rt);
+ fprintf(file, "\n");
+
+ /* give the application a chance to do some stuff. */
+ WriteApplMacro(file, "Send", "Before", rt);
+
+ /* Write the send/receive or rpc call */
+
+ if (UseEventLogger)
+ WriteLogMsg(file, rt, LOG_USER, LOG_REQUEST);
+
+ if (rt->rtOneWay) {
+ WriteMsgSend(file, rt);
+ }
+ else {
+ if (UseMsgRPC
+#if USE_IMMEDIATE_SEND_TIMEOUT
+ && (rt->rtWaitTime == argNULL)
+#endif
+ ) {
+ /* overwrite mode meaningful only when UseMsgRPC is enabled */
+ if (rt->rtOverwrite)
+ WriteOverwriteTemplate(file, rt);
+ WriteMsgRPC(file, rt);
+ } else
+ WriteMsgSendReceive(file, rt);
+
+ WriteCheckReplyCall(file, rt);
+ WriteCheckReplyTrailerArgs(file, rt);
+
+ if (UseEventLogger)
+ WriteLogMsg(file, rt, LOG_USER, LOG_REPLY);
+
+ WriteReplyArgs(file, rt);
+ }
+ /* return the return value, if any */
+ if (!rt->rtOneWay) // WriteMsgSend() already wrote the 'return'
+ WriteReturnValue(file, rt);
+ fprintf(file, "}\n");
+}
+
+static void
+WriteRPCClientFunctions(FILE *file, statement_t *stats)
+{
+ register statement_t *stat;
+ const char *fname;
+ const char *argfmt = "(mach_port_t, char *, mach_msg_type_number_t)";
+
+ fprintf(file, "#ifdef AUTOTEST\n");
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ if (stat->stKind == skRoutine) {
+ fname = stat->stRoutine->rtName;
+ fprintf(file, "extern void client_%s%s;\n", fname, argfmt);
+ }
+ fprintf(file, "function_table_entry %s_client_functions[] =\n", SubsystemName);
+ fprintf(file, "{\n");
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ if (stat->stKind == skRoutine)
+ {
+ fname = stat->stRoutine->rtName;
+ fprintf(file, " { \"%s\", client_%s },\n", fname, fname);
+ }
+ fprintf(file, " { (char *) 0, (function_ptr_t) 0 }\n");
+ fprintf(file, "};\n");
+ fprintf(file, "#endif /* AUTOTEST */\n");
+}
+
+/*************************************************************
+ * Writes out the xxxUser.c file. Called by mig.c
+ *************************************************************/
+void
+WriteUser(FILE *file, statement_t *stats)
+{
+ register statement_t *stat;
+
+ WriteProlog(file, stats);
+ if (TestRPCTrap)
+ WriteRPCClientFunctions(file, stats);
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ switch (stat->stKind)
+ {
+ case skRoutine:
+ WriteCheckReply(file, stat->stRoutine);
+ WriteRoutine(file, stat->stRoutine);
+ break;
+ case skImport:
+ case skUImport:
+ case skSImport:
+ case skDImport:
+ case skIImport:
+ break;
+ default:
+ fatal("WriteUser(): bad statement_kind_t (%d)",
+ (int) stat->stKind);
+ }
+ WriteEpilog(file);
+}
+
+/*************************************************************
+ * Writes out individual .c user files for each routine. Called by mig.c
+ *************************************************************/
+void
+WriteUserIndividual(statement_t *stats)
+{
+ register statement_t *stat;
+
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ switch (stat->stKind)
+ {
+ case skRoutine:
+ {
+ FILE *file;
+ char *filename;
+
+ filename = (char *)(uintptr_t)strconcat(UserFilePrefix,
+ strconcat(stat->stRoutine->rtName, ".c"));
+ file = fopen(filename, "w");
+ if (file == NULL)
+ fatal("fopen(%s): %s", filename,
+ strerror(errno));
+ WriteProlog(file, stats);
+ WriteRoutine(file, stat->stRoutine);
+ WriteEpilog(file);
+ fclose(file);
+ strfree(filename);
+ }
+ case skUImport:
+ case skSImport:
+ case skDImport:
+ case skIImport:
+ break;
+ default:
+ fatal("WriteUserIndividual(): bad statement_kind_t (%d)",
+ (int) stat->stKind);
+ }
+}
Property changes on: trunk/usr.bin/migcom/user.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/utils.c
===================================================================
--- trunk/usr.bin/migcom/utils.c (rev 0)
+++ trunk/usr.bin/migcom/utils.c 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,1103 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014, Matthew Macy <kmacy at FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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.
+ */
+/*
+ * 92/03/03 16:25:39 jeffreyh
+ * Changes from TRUNK
+ * [92/02/26 12:33:02 jeffreyh]
+ *
+ * 92/01/14 16:47:08 rpd
+ * Modified WriteTypeDeclIn and WriteTypeDeclOut to disable
+ * the deallocate flag on Indefinite arguments.
+ * [92/01/09 rpd]
+ *
+ * 92/01/03 20:30:51 dbg
+ * Change argByReferenceUser and argByReferenceServer to fields in
+ * argument_t.
+ * [91/08/29 dbg]
+ *
+ * 91/07/31 18:11:45 dbg
+ * Accept new dealloc_t argument type in WriteStaticDecl,
+ * WritePackMsgType.
+ *
+ * Don't need to zero last character of C string. Mig_strncpy does
+ * the proper work.
+ *
+ * Add SkipVFPrintf, so that WriteCopyType doesn't print fields in
+ * comments.
+ * [91/07/17 dbg]
+ *
+ * 91/06/25 10:32:36 rpd
+ * Changed WriteVarDecl to WriteUserVarDecl.
+ * Added WriteServerVarDecl.
+ * [91/05/23 rpd]
+ *
+ * 91/02/05 17:56:28 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:56:39 mrt]
+ *
+ * 90/06/02 15:06:11 rpd
+ * Created for new IPC.
+ * [90/03/26 21:14:54 rpd]
+ *
+ * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
+ * Extensive revamping. Added polymorphic arguments.
+ * Allow multiple variable-sized inline arguments in messages.
+ *
+ * 21-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Added deallocflag to the WritePackMsg routines.
+ *
+ * 29-Jul-87 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Changed WriteVarDecl to not automatically write
+ * semi-colons between items, so that it can be
+ * used to write C++ argument lists.
+ *
+ * 27-May-87 Richard Draves (rpd) at Carnegie-Mellon University
+ * Created.
+ */
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "type.h"
+
+#include <mach/message.h>
+#include "routine.h"
+#include "write.h"
+#include "global.h"
+#include "routine.h"
+#include "utils.h"
+#include "alloc.h"
+
+
+void
+WriteIdentificationString(FILE *file)
+{
+
+ fprintf(file, "/*\n");
+ fprintf(file, " * IDENTIFICATION:\n");
+ fprintf(file, " * stub generated %s", GenerationDate);
+ fprintf(file, " * with a MiG generated %s by %s\n", MigGenerationDate, MigMoreData);
+ fprintf(file, " * OPTIONS: \n");
+ if (IsKernelUser)
+ fprintf(file, " *\tKernelUser\n");
+ if (IsKernelServer)
+ fprintf(file, " *\tKernelServer\n");
+ if (!UseMsgRPC)
+ fprintf(file, " *\t-R (no RPC calls)\n");
+ fprintf(file, " */\n");
+}
+
+void
+WriteMigExternal(FILE *file)
+{
+ fprintf(file, "#ifdef\tmig_external\n");
+ fprintf(file, "mig_external\n");
+ fprintf(file, "#else\n");
+ fprintf(file, "extern\n");
+ fprintf(file, "#endif\t/* mig_external */\n");
+}
+
+void
+WriteMigInternal(FILE *file)
+{
+ fprintf(file, "#ifdef\tmig_internal\n");
+ fprintf(file, "mig_internal\n");
+ fprintf(file, "#else\n");
+ fprintf(file, "static\n");
+ fprintf(file, "#endif\t/* mig_internal */\n");
+}
+
+void
+WriteImport(FILE *file, string_t filename)
+{
+ fprintf(file, "#include %s\n", filename);
+}
+
+void
+WriteImplImports(FILE *file, statement_t *stats, boolean_t isuser)
+{
+ register statement_t *stat;
+
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ switch (stat->stKind)
+ {
+ case skImport:
+ case skIImport:
+ WriteImport(file, stat->stFileName);
+ break;
+ case skSImport:
+ if (!isuser)
+ WriteImport(file, stat->stFileName);
+ break;
+ case skUImport:
+ if (isuser)
+ WriteImport(file, stat->stFileName);
+ break;
+ case skRoutine:
+ case skDImport:
+ break;
+ default:
+ printf("WriteImplImport(): bad statement_kind_t (%d)",
+ (int) stat->stKind);
+ abort();
+ }
+}
+
+void
+WriteRCSDecl(FILE *file, identifier_t name, string_t rcs)
+{
+ fprintf(file, "#ifndef\tlint\n");
+ fprintf(file, "#if\tUseExternRCSId\n");
+ fprintf(file, "%s char %s_rcsid[] = %s;\n", (BeAnsiC) ? "const" : "", name, rcs);
+ fprintf(file, "#else\t/* UseExternRCSId */\n");
+ fprintf(file, "static %s char rcsid[] = %s;\n", (BeAnsiC) ? "const" : "", rcs);
+ fprintf(file, "#endif\t/* UseExternRCSId */\n");
+ fprintf(file, "#endif\t/* lint */\n");
+ fprintf(file, "\n");
+}
+
+static void
+WriteOneApplDefault(FILE *file, const char *word1, const char *word2, const char *word3)
+{
+ char buf[50];
+
+ sprintf(buf, "__%s%s%s", word1, word2, word3);
+ fprintf(file, "#ifndef\t%s\n", buf);
+ fprintf(file, "#define\t%s(_NUM_, _NAME_)\n", buf);
+ fprintf(file, "#endif\t/* %s */\n", buf);
+ fprintf(file, "\n");
+}
+
+void
+WriteApplDefaults(FILE *file, const char *dir)
+{
+ WriteOneApplDefault(file, "Declare", dir, "Rpc");
+ WriteOneApplDefault(file, "Before", dir, "Rpc");
+ WriteOneApplDefault(file, "After", dir, "Rpc");
+ WriteOneApplDefault(file, "Declare", dir, "Simple");
+ WriteOneApplDefault(file, "Before", dir, "Simple");
+ WriteOneApplDefault(file, "After", dir, "Simple");
+}
+
+void
+WriteApplMacro(FILE *file, const char *dir, const char *when, routine_t *rt)
+{
+ const char *what = (rt->rtOneWay) ? "Simple" : "Rpc";
+
+ fprintf(file, "\t__%s%s%s(%d, \"%s\")\n",
+ when, dir, what, SubsystemBase + rt->rtNumber, rt->rtName);
+}
+
+void
+WriteBogusDefines(FILE *file)
+{
+ fprintf(file, "#ifndef\tmig_internal\n");
+ fprintf(file, "#define\tmig_internal\tstatic __inline__\n");
+ fprintf(file, "#endif\t/* mig_internal */\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "#ifndef\tmig_external\n");
+ fprintf(file, "#define mig_external\n");
+ fprintf(file, "#endif\t/* mig_external */\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "#if\t!defined(__MigTypeCheck) && defined(TypeCheck)\n");
+ fprintf(file, "#define\t__MigTypeCheck\t\tTypeCheck\t/* Legacy setting */\n");
+ fprintf(file, "#endif\t/* !defined(__MigTypeCheck) */\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "#if\t!defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)\n");
+ fprintf(file, "#define\t__MigKernelSpecificCode\t_MIG_KERNEL_SPECIFIC_CODE_\t/* Legacy setting */\n");
+ fprintf(file, "#endif\t/* !defined(__MigKernelSpecificCode) */\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "#ifndef\tLimitCheck\n");
+ fprintf(file, "#define\tLimitCheck 0\n");
+ fprintf(file, "#endif\t/* LimitCheck */\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "#ifndef\tmin\n");
+ fprintf(file, "#define\tmin(a,b) ( ((a) < (b))? (a): (b) )\n");
+ fprintf(file, "#endif\t/* min */\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "#if !defined(_WALIGN_)\n");
+ fprintf(file, "#define _WALIGN_(x) (((x) + %d) & ~%d)\n", (int)(itWordAlign - 1), (int)(itWordAlign - 1));
+ fprintf(file, "#endif /* !defined(_WALIGN_) */\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "#if !defined(_WALIGNSZ_)\n");
+ fprintf(file, "#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))\n");
+ fprintf(file, "#endif /* !defined(_WALIGNSZ_) */\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "#ifndef\tUseStaticTemplates\n");
+ if (BeAnsiC) {
+ fprintf(file, "#define\tUseStaticTemplates\t1\n");
+ } else {
+ fprintf(file, "#if\t%s\n", NewCDecl);
+ fprintf(file, "#define\tUseStaticTemplates\t1\n");
+ fprintf(file, "#endif\t/* %s */\n", NewCDecl);
+ }
+ fprintf(file, "#endif\t/* UseStaticTemplates */\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "#define _WALIGN_(x) (((x) + %ld) & ~%ld)\n",
+ itWordAlign - 1, itWordAlign - 1);
+ fprintf(file, "#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))\n");
+}
+
+void
+WriteList(FILE *file, argument_t *args, void (*func)(), u_int mask, const char *between, const char *after)
+{
+ argument_t *arg;
+ boolean_t sawone = FALSE;
+
+ for (arg = args; arg != argNULL; arg = arg->argNext) {
+ if (akCheckAll(arg->argKind, mask)) {
+ if (sawone)
+ fprintf(file, "%s", between);
+ sawone = TRUE;
+
+ (*func)(file, arg);
+ }
+ }
+ if (sawone)
+ fprintf(file, "%s", after);
+}
+
+static boolean_t
+WriteReverseListPrim(FILE *file, argument_t *arg, void (*func)(), u_int mask, const char *between)
+{
+ boolean_t sawone = FALSE;
+
+ if (arg != argNULL)
+ {
+ sawone = WriteReverseListPrim(file, arg->argNext, func, mask, between);
+
+ if (akCheckAll(arg->argKind, mask))
+ {
+ if (sawone)
+ fprintf(file, "%s", between);
+ sawone = TRUE;
+
+ (*func)(file, arg);
+ }
+ }
+
+ return sawone;
+}
+
+void
+WriteReverseList(FILE *file, argument_t *args, void (*func)(), u_int mask, const char *between, const char *after)
+{
+ boolean_t sawone;
+
+ sawone = WriteReverseListPrim(file, args, func, mask, between);
+
+ if (sawone)
+ fprintf(file, "%s", after);
+}
+
+void
+WriteNameDecl(FILE *file, argument_t *arg)
+{
+ fprintf(file, "%s", arg->argVarName);
+}
+
+void
+WriteUserVarDecl(FILE *file, argument_t *arg)
+{
+ boolean_t pointer = (arg->argByReferenceUser ||arg->argType->itNativePointer);
+ const char *ref = (pointer) ? "*" : "";
+ const char *cnst = ((arg->argFlags & flConst) &&
+ (IS_VARIABLE_SIZED_UNTYPED(arg->argType) ||
+ arg->argType->itNoOptArray || arg->argType->itString)) ? "const " : "";
+
+ fprintf(file, "\t%s%s %s%s", cnst, arg->argType->itUserType, ref, arg->argVarName);
+}
+
+void
+WriteServerVarDecl(FILE *file, argument_t *arg)
+{
+ const char *ref = (arg->argByReferenceServer ||
+ arg->argType->itNativePointer) ? "*" : "";
+ const char *cnst = ((arg->argFlags & flConst) &&
+ (IS_VARIABLE_SIZED_UNTYPED(arg->argType) ||
+ arg->argType->itNoOptArray || arg->argType->itString)) ? "const " : "";
+
+ fprintf(file, "\t%s%s %s%s", cnst, arg->argType->itTransType, ref, arg->argVarName);
+}
+
+const char *
+ReturnTypeStr(routine_t *rt)
+{
+ return rt->rtRetCode->argType->itUserType;
+}
+
+const char *
+FetchUserType(ipc_type_t *it)
+{
+ return it->itUserType;
+}
+
+const char *
+FetchServerType(ipc_type_t *it)
+{
+ return it->itServerType;
+}
+
+const char *
+FetchKPDType(ipc_type_t *it)
+{
+ return it->itKPDType;
+}
+
+static void
+WriteTrailerDecl(FILE *file, boolean_t trailer)
+{
+ if (trailer)
+ fprintf(file, "\t\tmach_msg_max_trailer_t trailer;\n");
+ else
+ fprintf(file, "\t\tmach_msg_trailer_t trailer;\n");
+}
+
+void
+WriteFieldDeclPrim(FILE *file, argument_t *arg, const char *(*tfunc)(ipc_type_t *))
+{
+ register ipc_type_t *it = arg->argType;
+
+ if (IS_VARIABLE_SIZED_UNTYPED(it) || it->itNoOptArray) {
+ register argument_t *count = arg->argCount;
+ register ipc_type_t *btype = it->itElement;
+
+ /*
+ * Build our own declaration for a varying array:
+ * use the element type and maximum size specified.
+ * Note arg->argCount->argMultiplier == btype->itNumber.
+ */
+ /*
+ * NDR encoded VarStrings requires the offset field.
+ * Since it is not used, it wasn't worthwhile to create an extra
+ * parameter
+ */
+ if (it->itString)
+ fprintf(file, "\t\t%s %sOffset; /* MiG doesn't use it */\n",
+ (*tfunc)(count->argType), arg->argName);
+
+ if (!(arg->argFlags & flSameCount) && !it->itNoOptArray)
+ /* in these cases we would have a count, which we don't want */
+ fprintf(file, "\t\t%s %s;\n", (*tfunc)(count->argType),
+ count->argMsgField);
+ fprintf(file, "\t\t%s %s[%d];",
+ (*tfunc)(btype),
+ arg->argMsgField,
+ it->itNumber/btype->itNumber);
+ }
+ else if (IS_MULTIPLE_KPD(it))
+ fprintf(file, "\t\t%s %s[%d];", (*tfunc)(it), arg->argMsgField,
+ it->itKPD_Number);
+ else if (IS_OPTIONAL_NATIVE(it)) {
+ fprintf(file, "\t\tboolean_t __Present__%s;\n", arg->argMsgField);
+ fprintf(file, "\t\tunion {\n");
+ fprintf(file, "\t\t %s __Real__%s;\n",
+ (*tfunc)(it), arg->argMsgField);
+ fprintf(file, "\t\t char __Phony__%s[_WALIGNSZ_(%s)];\n",
+ arg->argMsgField, (*tfunc)(it));
+ fprintf(file, "\t\t} %s;", arg->argMsgField);
+ }
+ else {
+ /* either simple KPD or simple in-line */
+ fprintf(file, "\t\t%s %s;", (*tfunc)(it), arg->argMsgField);
+ }
+
+ /* Kernel Processed Data has always PadSize = 0 */
+ if (it->itPadSize != 0)
+ fprintf(file, "\n\t\tchar %s[%d];", arg->argPadName, it->itPadSize);
+}
+
+void
+WriteKPDFieldDecl(FILE *file, argument_t *arg)
+{
+ if (akCheck(arg->argKind, akbSendKPD) ||
+ akCheck(arg->argKind, akbReturnKPD))
+ WriteFieldDeclPrim(file, arg, FetchKPDType);
+ else
+ WriteFieldDeclPrim(file, arg, FetchServerType);
+}
+
+void
+WriteStructDecl(FILE *file, argument_t *args, void (*func)(), u_int mask,
+ const char *name, boolean_t simple, boolean_t trailer,
+ boolean_t trailer_t, boolean_t template_only)
+{
+ fprintf(file, "\n#ifdef __MigPackStructs\n#pragma pack(%lu)\n#endif\n",sizeof(natural_t));
+ fprintf(file, "\ttypedef struct {\n");
+ fprintf(file, "\t\tmach_msg_header_t Head;\n");
+ if (simple == FALSE) {
+ fprintf(file, "\t\t/* start of the kernel processed data */\n");
+ fprintf(file, "\t\tmach_msg_body_t msgh_body;\n");
+ if (mask == akbRequest)
+ WriteList(file, args, func, mask | akbSendKPD, "\n", "\n");
+ else
+ WriteList(file, args, func, mask | akbReturnKPD, "\n", "\n");
+ fprintf(file, "\t\t/* end of the kernel processed data */\n");
+ }
+ if (!template_only) {
+ if (mask == akbRequest)
+ WriteList(file, args, func, mask | akbSendBody, "\n", "\n");
+
+ else
+ WriteList(file, args, func, mask | akbReturnBody, "\n", "\n");
+ if (trailer)
+ WriteTrailerDecl(file, trailer_t);
+ }
+ fprintf(file, "\t} %s;\n", name);
+ fprintf(file, "#ifdef __MigPackStructs\n#pragma pack()\n#endif\n");
+}
+
+void
+WriteTemplateDeclIn(FILE *file, register argument_t *arg)
+{
+ (*arg->argKPD_Template)(file, arg, TRUE);
+}
+
+void
+WriteTemplateDeclOut(FILE *file, register argument_t *arg)
+{
+ (*arg->argKPD_Template)(file, arg, FALSE);
+}
+
+void
+WriteTemplateKPD_port(FILE *file, argument_t *arg, boolean_t in)
+{
+ register ipc_type_t *it = arg->argType;
+
+ fprintf(file, "#if\tUseStaticTemplates\n");
+ fprintf(file, "\tconst static %s %s = {\n", it->itKPDType, arg->argTTName);
+
+ fprintf(file, "\t\t.name = MACH_PORT_NULL,\n");
+ fprintf(file, "\t\t.disposition = %s,\n", in ? it->itInNameStr: it->itOutNameStr);
+ fprintf(file, "\t\t.type = MACH_MSG_PORT_DESCRIPTOR,\n");
+
+ fprintf(file, "\t};\n");
+ fprintf(file, "#endif\t/* UseStaticTemplates */\n");
+}
+
+void
+WriteTemplateKPD_ool(FILE *file, argument_t *arg, boolean_t in __unused)
+{
+ register ipc_type_t *it = arg->argType;
+
+ fprintf(file, "#if\tUseStaticTemplates\n");
+ fprintf(file, "\tconst static %s %s = {\n", it->itKPDType, arg->argTTName);
+
+ if (IS_MULTIPLE_KPD(it))
+ it = it->itElement;
+
+ fprintf(file, "\t\t.address = (void *)0,\n");
+ if (it->itVarArray)
+ fprintf(file, "\t\t.size = 0,\n");
+ else
+ fprintf(file, "\t\t.size = %d,\n",
+ (it->itNumber * it->itSize + 7)/8);
+ fprintf(file, "\t\t.deallocate = %s,\n",
+ (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE");
+ /* the d_MAYBE case will be fixed runtime */
+ fprintf(file, "\t\t.copy = %s,\n",
+ (arg->argFlags & flPhysicalCopy) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY");
+ /* the PHYSICAL COPY flag has not been established yet */
+ fprintf(file, "\t\t.type = MACH_MSG_OOL_DESCRIPTOR,\n");
+
+ fprintf(file, "\t};\n");
+ fprintf(file, "#endif\t/* UseStaticTemplates */\n");
+}
+
+void
+WriteTemplateKPD_oolport(FILE *file, argument_t *arg, boolean_t in)
+{
+ register ipc_type_t *it = arg->argType;
+
+ fprintf(file, "#if\tUseStaticTemplates\n");
+ fprintf(file, "\tconst static %s %s = {\n", it->itKPDType, arg->argTTName);
+
+ if (IS_MULTIPLE_KPD(it))
+ it = it->itElement;
+
+ fprintf(file, "\t\t.address = (void *)0,\n");
+ if (!it->itVarArray)
+ fprintf(file, "\t\t.count = %d,\n",
+ it->itNumber);
+ else
+ fprintf(file, "\t\t.count = 0,\n");
+ fprintf(file, "\t\t.deallocate = %s,\n",
+ (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE");
+ fprintf(file, "\t\t/* copy is meaningful only in overwrite mode */\n");
+ fprintf(file, "\t\t.copy = MACH_MSG_PHYSICAL_COPY,\n");
+ fprintf(file, "\t\t.disposition = %s,\n",
+ in ? it->itInNameStr: it->itOutNameStr);
+ fprintf(file, "\t\t.type = MACH_MSG_OOL_PORTS_DESCRIPTOR,\n");
+
+ fprintf(file, "\t};\n");
+ fprintf(file, "#endif\t/* UseStaticTemplates */\n");
+}
+
+void
+WriteReplyTypes(FILE *file, statement_t *stats)
+{
+ register statement_t *stat;
+
+ fprintf(file, "/* typedefs for all replies */\n\n");
+ fprintf(file, "#ifndef __Reply__%s_subsystem__defined\n", SubsystemName);
+ fprintf(file, "#define __Reply__%s_subsystem__defined\n", SubsystemName);
+ for (stat = stats; stat != stNULL; stat = stat->stNext) {
+ if (stat->stKind == skRoutine) {
+ register routine_t *rt;
+ char str[MAX_STR_LEN];
+
+ rt = stat->stRoutine;
+ sprintf(str, "__Reply__%s_t", rt->rtName);
+ WriteStructDecl(file, rt->rtArgs, WriteKPDFieldDecl, akbReply, str, rt->rtSimpleReply, FALSE, FALSE, FALSE);
+ }
+ }
+ fprintf(file, "#endif /* !__Reply__%s_subsystem__defined */\n", SubsystemName);
+ fprintf(file, "\n");
+}
+
+void
+WriteRequestTypes(FILE *file, statement_t *stats)
+{
+ register statement_t *stat;
+
+ fprintf(file, "/* typedefs for all requests */\n\n");
+ fprintf(file, "#ifndef __Request__%s_subsystem__defined\n", SubsystemName);
+ fprintf(file, "#define __Request__%s_subsystem__defined\n", SubsystemName);
+ for (stat = stats; stat != stNULL; stat = stat->stNext) {
+ if (stat->stKind == skRoutine) {
+ register routine_t *rt;
+ char str[MAX_STR_LEN];
+
+ rt = stat->stRoutine;
+ sprintf(str, "__Request__%s_t", rt->rtName);
+ WriteStructDecl(file, rt->rtArgs, WriteKPDFieldDecl, akbRequest, str, rt->rtSimpleRequest, FALSE, FALSE, FALSE);
+ }
+ }
+ fprintf(file, "#endif /* !__Request__%s_subsystem__defined */\n", SubsystemName);
+ fprintf(file, "\n");
+}
+
+void
+WriteNDRConvertArgDecl(FILE *file, argument_t *arg, const char *convert, const char *dir)
+{
+ argument_t *count = arg->argCount;
+ argument_t *parent = arg->argParent;
+ const char *carg = (count) ? ", c" : "";
+ routine_t *rt = arg->argRoutine;
+ ipc_type_t *ptype = arg->argType;
+ ipc_type_t *btype;
+ int multi, array;
+ char domain[MAX_STR_LEN];
+
+ fprintf(file, "#ifndef __NDR_convert__%s__%s__%s_t__%s__defined\n#", convert, dir, rt->rtName, arg->argMsgField);
+
+ for (btype = ptype, multi = (!parent) ? arg->argMultiplier : 1, array = 0;
+ btype;
+ ptype = btype, array += ptype->itVarArray, btype = btype->itElement) {
+ const char *bttype;
+
+ if (btype->itNumber < ptype->itNumber && !ptype->itVarArray && !parent) {
+ multi *= ptype->itNumber / btype->itNumber;
+ if (!btype->itString)
+ continue;
+ }
+ else if (array && ptype->itVarArray)
+ continue;
+ if (btype != ptype)
+ fprintf(file, "#el");
+
+ bttype = (multi > 1 && btype->itString) ? "string" : FetchServerType(btype);
+ sprintf(domain, "__%s", SubsystemName);
+ do {
+ fprintf(file, "if\tdefined(__NDR_convert__%s%s__%s__defined)\n", convert, domain, bttype);
+ fprintf(file, "#define\t__NDR_convert__%s__%s__%s_t__%s__defined\n", convert, dir, rt->rtName, arg->argMsgField);
+ fprintf(file, "#define\t__NDR_convert__%s__%s__%s_t__%s(a, f%s) \\\n\t", convert, dir, rt->rtName, arg->argMsgField, carg);
+ if (multi > 1) {
+ if (array) {
+ if (btype->itString)
+ fprintf(file, "__NDR_convert__2DARRAY((%s *)(a), f, %d, c, ", bttype, multi);
+ else
+ fprintf(file, "__NDR_convert__ARRAY((%s *)(a), f, %d * (c), ", bttype, multi);
+ }
+ else if (!btype->itString)
+ fprintf(file, "__NDR_convert__ARRAY((%s *)(a), f, %d, ", bttype, multi);
+ }
+ else if (array)
+ fprintf(file, "__NDR_convert__ARRAY((%s *)(a), f, c, ", bttype);
+ fprintf(file, "__NDR_convert__%s%s__%s", convert, domain, bttype);
+ if (multi > 1) {
+ if (!array && btype->itString)
+ fprintf(file, "(a, f, %d", multi);
+ }
+ else if (!array)
+ fprintf(file, "((%s *)(a), f%s", bttype, carg);
+ fprintf(file, ")\n");
+ } while (strcmp(domain, "") && (domain[0] = '\0', fprintf(file, "#el")));
+ }
+ fprintf(file, "#endif /* defined(__NDR_convert__*__defined) */\n");
+ fprintf(file, "#endif /* __NDR_convert__%s__%s__%s_t__%s__defined */\n\n", convert, dir, rt->rtName, arg->argMsgField);
+}
+
+/*
+ * Like vfprintf, but omits a leading comment in the format string
+ * and skips the items that would be printed by it. Only %s, %d,
+ * and %f are recognized.
+ */
+static void
+SkipVFPrintf(FILE *file, const char *fmt, va_list pvar)
+{
+ if (*fmt == 0)
+ return; /* degenerate case */
+
+ if (fmt[0] == '/' && fmt[1] == '*') {
+ /* Format string begins with C comment. Scan format
+ string until end-comment delimiter, skipping the
+ items in pvar that the enclosed format items would
+ print. */
+
+ register int c;
+
+ fmt += 2;
+ for (;;) {
+ c = *fmt++;
+ if (c == 0)
+ return; /* nothing to format */
+ if (c == '*') {
+ if (*fmt == '/') {
+ break;
+ }
+ }
+ else if (c == '%') {
+ /* Field to skip */
+ c = *fmt++;
+ switch (c) {
+
+ case 's':
+ (void) va_arg(pvar, char *);
+ break;
+
+ case 'd':
+ (void) va_arg(pvar, int);
+ break;
+
+ case 'f':
+ (void) va_arg(pvar, double);
+ break;
+
+ case '\0':
+ return; /* error - fmt ends with '%' */
+
+ default:
+ break;
+ }
+ }
+ }
+ /* End of comment. To be pretty, skip
+ the space that follows. */
+ fmt++;
+ if (*fmt == ' ')
+ fmt++;
+ }
+
+ /* Now format the string. */
+ (void) vfprintf(file, fmt, pvar);
+}
+
+static void
+vWriteCopyType(FILE *file, ipc_type_t *it, const char *left, const char *right, va_list pvar)
+{
+ va_list pv2;
+ __va_copy(pv2,pvar);
+ if (it->itStruct)
+ {
+ fprintf(file, "\t");
+ (void) SkipVFPrintf(file, left, pvar);
+ fprintf(file, " = ");
+ (void) SkipVFPrintf(file, right, pv2);
+ fprintf(file, ";\n");
+ }
+ else if (it->itString)
+ {
+ fprintf(file, "\t(void) mig_strncpy(");
+ (void) SkipVFPrintf(file, left, pvar);
+ fprintf(file, ", ");
+ (void) SkipVFPrintf(file, right, pv2);
+ fprintf(file, ", %d);\n", it->itTypeSize);
+ }
+ else
+ {
+ fprintf(file, "\t{ typedef struct { char data[%d]; } *sp;\n",
+ it->itTypeSize);
+ fprintf(file, "\t * (sp) ");
+ (void) SkipVFPrintf(file, left, pvar);
+ fprintf(file, " = * (sp) ");
+ (void) SkipVFPrintf(file, right, pv2);
+ fprintf(file, ";\n\t}\n");
+ }
+
+ va_end(pv2);
+}
+
+
+/*ARGSUSED*/
+/*VARARGS4*/
+void
+WriteCopyType(FILE *file, ipc_type_t *it, const char *left, const char *right, ...)
+{
+ va_list pvar;
+ va_start(pvar, right);
+
+ vWriteCopyType(file, it, left, right, pvar);
+
+ va_end(pvar);
+}
+
+
+/*ARGSUSED*/
+/*VARARGS4*/
+void
+WriteCopyArg(FILE *file, argument_t *arg, const char *left, const char *right, ...)
+{
+ va_list pvar;
+ va_start(pvar, right);
+
+ {
+ ipc_type_t *it = arg->argType;
+ if (it->itVarArray && !it->itString) {
+ fprintf(file, "\t (void)memcpy(");
+ (void) SkipVFPrintf(file, left, pvar);
+ va_end(pvar);
+ fprintf(file, ", ");
+ va_start(pvar, right);
+ (void) SkipVFPrintf(file, right, pvar);
+ fprintf(file, ", %s);\n", arg->argCount->argVarName);
+ } else
+ vWriteCopyType(file, it, left, right, pvar);
+ }
+
+ va_end(pvar);
+}
+
+
+/*
+ * Global KPD disciplines
+ */
+void
+KPD_error(FILE *file __unused, argument_t *arg)
+{
+ printf("MiG internal error: argument is %s\n", arg->argVarName);
+ exit(1);
+}
+
+void
+KPD_noop(FILE *file __unused, argument_t *arg __unused)
+{
+}
+
+static void
+WriteStringDynArgs(args, mask, InPOutP, str_oolports, str_ool)
+ argument_t *args;
+ u_int mask;
+ string_t InPOutP;
+ string_t *str_oolports, *str_ool;
+{
+ argument_t *arg;
+ char loc[100], sub[20];
+ string_t tmp_str1 = "";
+ string_t tmp_str2 = "";
+ int cnt, multiplier = 1;
+ boolean_t test, complex = FALSE;
+
+ for (arg = args; arg != argNULL; arg = arg->argNext) {
+ ipc_type_t *it = arg->argType;
+
+ if (IS_MULTIPLE_KPD(it)) {
+ test = it->itVarArray || it->itElement->itVarArray;
+ if (test) {
+ multiplier = it->itKPD_Number;
+ it = it->itElement;
+ complex = TRUE;
+ }
+ } else
+ test = it->itVarArray;
+
+ cnt = multiplier;
+ while (cnt) {
+ if (complex)
+ sprintf(sub, "[%d]", multiplier - cnt);
+ if (akCheck(arg->argKind, mask) &&
+ it->itPortType && !it->itInLine && test) {
+ sprintf(loc, " + %s->%s%s.count", InPOutP, arg->argMsgField,
+ complex ? sub : "");
+ tmp_str1 = strconcat(tmp_str1, loc);
+ }
+ if (akCheck(arg->argKind, mask) &&
+ !it->itInLine && !it->itPortType && test) {
+ sprintf(loc, " + %s->%s%s.size", InPOutP, arg->argMsgField,
+ complex ? sub : "");
+ tmp_str2 = strconcat(tmp_str2, loc);
+ }
+ cnt--;
+ }
+ }
+ *str_oolports = tmp_str1;
+ *str_ool = tmp_str2;
+}
+
+/*
+ * Utilities for Logging Events that happen at the stub level
+ */
+void
+WriteLogMsg(FILE *file, routine_t *rt, boolean_t where, boolean_t what)
+{
+ string_t ptr_str;
+ string_t StringOolPorts = strNULL;
+ string_t StringOOL = strNULL;
+ u_int ports, oolports, ool;
+ string_t event;
+
+ fprintf(file, "\n#if MIG_DEBUG\n");
+ if (where == LOG_USER)
+ fprintf(file, "\tLOG_TRACE(MACH_MSG_LOG_USER,\n");
+ else
+ fprintf(file, "\tLOG_TRACE(MACH_MSG_LOG_SERVER,\n");
+ if (where == LOG_USER && what == LOG_REQUEST) {
+ ptr_str = "InP";
+ event = "MACH_MSG_REQUEST_BEING_SENT";
+ } else if (where == LOG_USER && what == LOG_REPLY) {
+ ptr_str = "Out0P";
+ event = "MACH_MSG_REPLY_BEING_RCVD";
+ } else if (where == LOG_SERVER && what == LOG_REQUEST) {
+ ptr_str = "In0P";
+ event = "MACH_MSG_REQUEST_BEING_RCVD";
+ } else {
+ ptr_str = "OutP";
+ event = "MACH_MSG_REPLY_BEING_SENT";
+ }
+ WriteStringDynArgs(rt->rtArgs,
+ (what == LOG_REQUEST) ? akbSendKPD : akbReturnKPD,
+ ptr_str, &StringOolPorts, &StringOOL);
+ fprintf(file, "\t\t%s,\n", event);
+ fprintf(file, "\t\t%s->Head.msgh_id,\n", ptr_str);
+ if (where == LOG_USER && what == LOG_REQUEST) {
+ if (rt->rtNumRequestVar)
+ fprintf(file, "\t\tmsgh_size,\n");
+ else
+ fprintf(file, "\t\tsizeof(Request),\n");
+ } else
+ fprintf(file, "\t\t%s->Head.msgh_size,\n", ptr_str);
+ if ((what == LOG_REQUEST && rt->rtSimpleRequest == FALSE) ||
+ (what == LOG_REPLY && rt->rtSimpleReply == FALSE))
+ fprintf(file, "\t\t%s->msgh_body.msgh_descriptor_count,\n", ptr_str);
+ else
+ fprintf(file, "\t\t0, /* Kernel Proc. Data entries */\n");
+ if (what == LOG_REQUEST) {
+ fprintf(file, "\t\t0, /* RetCode */\n");
+ ports = rt->rtCountPortsIn;
+ oolports = rt->rtCountOolPortsIn;
+ ool = rt->rtCountOolIn;
+ } else {
+ if (akCheck(rt->rtRetCode->argKind, akbReply))
+ fprintf(file, "\t\t%s->RetCode,\n", ptr_str);
+ else
+ fprintf(file, "\t\t0, /* RetCode */\n");
+ ports = rt->rtCountPortsOut;
+ oolports = rt->rtCountOolPortsOut;
+ ool = rt->rtCountOolOut;
+ }
+ fprintf(file, "\t\t/* Ports */\n");
+ fprintf(file, "\t\t%d,\n", ports);
+ fprintf(file, "\t\t/* Out-of-Line Ports */\n");
+ fprintf(file, "\t\t%d", oolports);
+ if (StringOolPorts != strNULL)
+ fprintf(file, "%s,\n", StringOolPorts);
+ else
+ fprintf(file, ",\n");
+ fprintf(file, "\t\t/* Out-of-Line Bytes */\n");
+ fprintf(file, "\t\t%d", ool);
+ if (StringOOL != strNULL)
+ fprintf(file, "%s,\n", StringOOL);
+ else
+ fprintf(file, ",\n");
+ fprintf(file, "\t\t__FILE__, __LINE__);\n");
+ fprintf(file, "#endif /* MIG_DEBUG */\n\n");
+}
+
+void
+WriteLogDefines(FILE *file, string_t who)
+{
+ fprintf(file, "#if MIG_DEBUG\n");
+ fprintf(file, "#define LOG_W_E(X)\tLOG_ERRORS(%s, \\\n", who);
+ fprintf(file, "\t\t\tMACH_MSG_ERROR_WHILE_PARSING, (void *)(X), __FILE__, __LINE__)\n");
+ fprintf(file, "#else /* MIG_DEBUG */\n");
+ fprintf(file, "#define LOG_W_E(X)\n");
+ fprintf(file, "#endif /* MIG_DEBUG */\n");
+ fprintf(file, "\n");
+}
+
+/* common utility to report errors */
+void
+WriteReturnMsgError(FILE *file, routine_t *rt, boolean_t isuser, argument_t *arg, string_t error)
+{
+ char space[MAX_STR_LEN];
+ char * string = &space[0];
+
+ if (UseEventLogger && arg != argNULL)
+ sprintf(string, "LOG_W_E(\"%s\"); ", arg->argVarName);
+ else
+ string = __DECONST(char *, "");
+
+ fprintf(file, "\t\t{ ");
+
+ if (isuser) {
+ if (! rtMessOnStack(rt))
+ fprintf(file, "%s((char *) Mess, sizeof(*Mess)); ", MessFreeRoutine);
+
+ fprintf(file, "%sreturn %s; }\n", string, error);
+ }
+ else
+ fprintf(file, "%sMIG_RETURN_ERROR(OutP, %s); }\n", string, error);
+}
+
+/* executed iff elements are defined */
+void
+WriteCheckTrailerHead(FILE *file, routine_t *rt __unused, boolean_t isuser)
+{
+ string_t who = (isuser) ? "Out0P" : "In0P";
+
+ fprintf(file, "\tTrailerP = (mach_msg_max_trailer_t *)((vm_offset_t)%s +\n", who);
+ fprintf(file, "\t\tround_msg(%s->Head.msgh_size));\n", who);
+ fprintf(file, "\tif (TrailerP->msgh_trailer_type != MACH_MSG_TRAILER_FORMAT_0)\n");
+ if (isuser)
+ fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n");
+ else
+ fprintf(file, "\t\t{ MIG_RETURN_ERROR(%s, MIG_TRAILER_ERROR); }\n", who);
+
+ fprintf(file, "#if\t__MigTypeCheck\n");
+ fprintf(file, "\ttrailer_size = TrailerP->msgh_trailer_size -\n");
+ fprintf(file, "\t\t(mach_msg_size_t)(sizeof(mach_msg_trailer_type_t) - sizeof(mach_msg_trailer_size_t));\n");
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+}
+
+/* executed iff elements are defined */
+void
+WriteCheckTrailerSize(FILE *file, boolean_t isuser, register argument_t *arg)
+{
+ fprintf(file, "#if\t__MigTypeCheck\n");
+ if (akIdent(arg->argKind) == akeMsgSeqno) {
+ fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(mach_port_seqno_t))\n");
+ if (isuser)
+ fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n");
+ else
+ fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n");
+ fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(mach_port_seqno_t);\n");
+ }
+ else if (akIdent(arg->argKind) == akeSecToken) {
+ fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(security_token_t))\n");
+ if (isuser)
+ fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n");
+ else
+ fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n");
+ fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(security_token_t);\n");
+ }
+ else if (akIdent(arg->argKind) == akeAuditToken) {
+ fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(audit_token_t))\n");
+ if (isuser)
+ fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n");
+ else
+ fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n");
+ fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(audit_token_t);\n");
+ }
+ else if (akIdent(arg->argKind) == akeContextToken) {
+ fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(mach_vm_address_t))\n");
+ if (isuser)
+ fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n");
+ else
+ fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n");
+ fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(mach_vm_address_t);\n");
+ }
+ fprintf(file, "#endif\t/* __MigTypeCheck */\n");
+}
+
Property changes on: trunk/usr.bin/migcom/utils.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/utils.h
===================================================================
--- trunk/usr.bin/migcom/utils.h (rev 0)
+++ trunk/usr.bin/migcom/utils.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,165 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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/06/25 10:32:47 rpd
+ * Changed WriteVarDecl to WriteUserVarDecl.
+ * Added WriteServerVarDecl.
+ * [91/05/23 rpd]
+ *
+ * 91/02/05 17:56:33 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:56:48 mrt]
+ *
+ * 90/06/02 15:06:16 rpd
+ * Created for new IPC.
+ * [90/03/26 21:15:06 rpd]
+ *
+ * 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
+
+#include "type.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, const char *between, const char *after);
+
+extern void WriteReverseList(FILE *file, argument_t *args,
+ void (*func)(FILE *file, argument_t *arg),
+ u_int mask, const char *between, const 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 WriteTemplateKPD_port(FILE *file, argument_t *arg, boolean_t in);
+extern void WriteTemplateKPD_ool(FILE *file, argument_t *arg, boolean_t in __unused);
+extern void WriteTemplateKPD_oolport(FILE *file, argument_t *arg, boolean_t in __unused);
+extern void WriteLogDefines(FILE *file, string_t who);
+extern void WriteCheckDecl(FILE *file, argument_t *arg);
+
+extern const char *ReturnTypeStr( routine_t *rt );
+
+extern const char *FetchUserType( ipc_type_t *it );
+extern const char *FetchServerType( ipc_type_t *it );
+extern const char *FetchKPDType( ipc_type_t *it );
+extern void WriteKPDFieldDecl(FILE *file, argument_t *arg);
+
+extern void WriteFieldDeclPrim( FILE *file, argument_t *arg, const char *(*tfunc)(ipc_type_t *it) );
+
+extern void WriteStructDecl(FILE *file, argument_t *args,
+ void (*func)(FILE *file, argument_t *arg),
+ u_int mask, const 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, const char *left, const char *right, ...);
+
+extern void WriteCopyArg(FILE *file, argument_t *arg, const char *left, const 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, const char *convert, const char *dir);
+extern void WriteIdentificationString(FILE *file);
+
+extern void KPD_error(FILE *file,argument_t *arg);
+extern void KPD_noop(FILE *file,argument_t *arg);
+
+
+#endif /* _UTILS_H */
Property changes on: trunk/usr.bin/migcom/utils.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/migcom/write.h
===================================================================
--- trunk/usr.bin/migcom/write.h (rev 0)
+++ trunk/usr.bin/migcom/write.h 2016-01-03 17:31:36 UTC (rev 7395)
@@ -0,0 +1,98 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * cmk1.1
+ */
+/*
+ * 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 at 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/08/28 11:17:39 jsb
+ * Removed TrapRoutine support.
+ * [91/08/12 rpd]
+ *
+ * 91/06/25 10:32:55 rpd
+ * Changed WriteHeader to WriteUserHeader.
+ * Added WriteServerHeader.
+ * [91/05/23 rpd]
+ *
+ * 91/02/05 17:56:38 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:56:55 mrt]
+ *
+ * 90/06/02 15:06:20 rpd
+ * Created for new IPC.
+ * [90/03/26 21:15:16 rpd]
+ *
+ * 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, const char *dir);
+extern void WriteApplMacro(FILE *file, const char *dir, const char *when,
+ routine_t *rt);
+
+#endif /* _WRITE_H */
Property changes on: trunk/usr.bin/migcom/write.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
More information about the Midnightbsd-cvs
mailing list