summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--=announce-1.02
-rw-r--r--ChangeLog35
-rw-r--r--Drivers.macros11
-rw-r--r--Makefile.in52
-rw-r--r--README2
-rw-r--r--configure.in13
-rw-r--r--i386/Drivers.in14
-rw-r--r--i386/Files1
-rw-r--r--i386/Makefrag30
-rw-r--r--include/alloca.h25
-rw-r--r--include/sys/ioctl.h52
-rw-r--r--include/sys/reboot.h123
-rw-r--r--include/sys/time.h53
-rw-r--r--include/sys/types.h91
-rw-r--r--kern/exception.c4
-rw-r--r--mig/ChangeLog163
-rw-r--r--mig/alloc.h34
-rw-r--r--mig/boolean.h38
-rw-r--r--mig/cpu.sym58
-rw-r--r--mig/error.c91
-rw-r--r--mig/error.h61
-rw-r--r--mig/global.c94
-rw-r--r--mig/global.h77
-rw-r--r--mig/header.c210
-rw-r--r--mig/lexxer.c2518
-rw-r--r--mig/lexxer.h33
-rw-r--r--mig/lexxer.l269
-rw-r--r--mig/message.h37
-rw-r--r--mig/mig.sh95
-rw-r--r--mig/mig_string.h49
-rw-r--r--mig/migcom.c298
-rw-r--r--mig/parser.c1700
-rw-r--r--mig/parser.h87
-rw-r--r--mig/parser.y671
-rw-r--r--mig/routine.c1334
-rw-r--r--mig/routine.h401
-rw-r--r--mig/server.c1322
-rw-r--r--mig/statement.c48
-rw-r--r--mig/statement.h65
-rw-r--r--mig/string.c79
-rw-r--r--mig/type.c918
-rw-r--r--mig/type.h218
-rw-r--r--mig/user.c1332
-rw-r--r--mig/utils.c417
-rw-r--r--mig/utils.h76
-rw-r--r--mig/vprint.c433
-rw-r--r--mig/write.h41
47 files changed, 13753 insertions, 22 deletions
diff --git a/=announce-1.0 b/=announce-1.0
index a8eb895..3ee9cd7 100644
--- a/=announce-1.0
+++ b/=announce-1.0
@@ -1,5 +1,5 @@
I am pleased to announce version 1.0 of the GNU distribution of the
-Mach kernel. It may be found in the file (about XXX MB compressed)
+Mach kernel. It may be found in the file (about 2.54 MB compressed)
ftp://prep.ai.mit.edu/pub/gnu/gnumach-1.0.tar.gz.
This distribution was prepared in order to install some bug fixes and
diff --git a/ChangeLog b/ChangeLog
index f843879..edf5524 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+Mon Apr 14 11:50:45 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * i386/Makefrag: Add rebuilding rules for configure subscript.
+
+ * i386/Makefrag: Fix up copyright notice.
+ * i386/Drivers.in: Likewise.
+ * Makefile.in: Likewise.
+ * Drivers.macros: Likewise.
+ * configure.in: Likewise.
+
+ * include/sys/time.h: New file, from include/mach/sa/sys/time.h.
+ * include/sys/reboot.h: New file, from include/mach/sa/sys/reboot.h.
+ * include/sys/ioctl.h: New file, from include/mach/sa/sys/ioctl.h.
+ * include/alloca.h: New file, from include/mach/sa/alloca.h.
+ * Makefile.in (other-sys-headers): Add time.h, ioctl.h, and reboot.h.
+ (other-mach-headers): New variable.
+ (mach-exec-headers): New variable.
+ (other-headers): New variable.
+ (installed-headers): Add mach-exec-headers.
+ (dist): Distribute other-mach-headers, other-sys-headers,
+ mach-exec-headers, and other-headers.
+ (device-files): Add device.srv.
+
+ * Makefile.in (check-clib-routines): Use more efficient rule.
+
+Fri Apr 11 15:18:09 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * Makefile.in (dist): Repair rule.
+ (other-sys-headers): New variable.
+ (dist): Install $(other-sys-headers).
+ (INCLUDES): Remove -I$(srcdir)/include/mach/sa.
+ (rules for mig-related .d files): Include MiG-specific -I flags.
+ (mach-headers): Add inline.h.
+ * include/sys/types.h: New file, from include/mach/sa/sys/types.h.
+
Mon Mar 24 16:23:21 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
* version.c (version): Make that 1.0. Whee.
diff --git a/Drivers.macros b/Drivers.macros
index 95bab83..054e521 100644
--- a/Drivers.macros
+++ b/Drivers.macros
@@ -1,6 +1,17 @@
dnl
dnl Some autoconf macros useful for device driver configuration
dnl
+dnl Copyright 1997 Free Software Foundation, Inc.
+dnl Permission to use, copy, modify and distribute this software and its
+dnl documentation is hereby granted, provided that both the copyright
+dnl notice and this permission notice appear in all copies of the
+dnl software, derivative works or modified versions, and any portions
+dnl thereof, and that both notices appear in supporting documentation.
+dnl
+dnl THE FREE SOFTWARE FOUNDATION ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+dnl "AS IS" CONDITION. THE FREE SOFTWARE FOUNDATION DISCLAIMS ANY
+dnl LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE
+dnl USE OF THIS SOFTWARE.
AC_SUBST(device_drivers)
diff --git a/Makefile.in b/Makefile.in
index 8ecc22c..8326d2d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,6 +1,17 @@
# Makefile for Mach 4 kernel directory
-# Copyright 1996 Free Software Foundation, Inc.
-# This file is part of GNU Mach. Redistribution terms are not yet decided.
+# Copyright 1997 Free Software Foundation, Inc.
+#
+# 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.
+#
+# THE FREE SOFTWARE FOUNDATION ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+# "AS IS" CONDITION. THE FREE SOFTWARE FOUNDATION DISCLAIMS ANY
+# LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE
+# USE OF THIS SOFTWARE.
+
@@ -102,7 +113,7 @@ device-files = blkio.c chario.c cirbuf.c cons.c dev_lookup.c dev_name.c \
buf.h cirbuf.h conf.h cons.h dev_hdr.h dev_master.h device_port.h \
device_types_kernel.h ds_routines.h errno.h if_ether.h if_hdr.h \
io_req.h net_io.h param.h tty.h memory_object_reply.cli \
- dev_forward.defs device_pager.srv device_reply.cli
+ dev_forward.defs device_pager.srv device_reply.cli device.srv
# IPC implementation
ipc-cfiles = $(addprefix ipc_,$(ipc-names)) \
@@ -192,14 +203,19 @@ mach-headers= $(addprefix mach/, bootstrap.defs default_pager.defs \
task_info.h task_special_ports.h thread_info.h \
thread_special_ports.h thread_status.h thread_switch.h \
time_value.h version.h vm_attributes.h vm_inherit.h \
- vm_param.h vm_prot.h vm_statistics.h)
-
+ vm_param.h vm_prot.h vm_statistics.h inline.h)
+mach-exec-headers= $(addprefix mach/exec/, a.out.h elf.h exec.h)
mach-debug-headers:= $(addprefix mach_debug/, hash_info.h ipc_info.h \
mach_debug.defs mach_debug_types.defs mach_debug_types.h \
pc_info.h vm_info.h zone_info.h)
-installed-headers:= $(device-headers) $(mach-headers)
+installed-headers:= $(device-headers) $(mach-headers) $(mach-exec-headers)
+# Other headers for the distribution. We don't install these, because the
+# GNU C library has correct versions for users to use.
+other-sys-headers := types.h time.h reboot.h ioctl.h
+other-mach-headers := mig_support.h mach_traps.h error.h
+other-headers := alloca.h
# We steal routines from the C library and put them here.
@@ -218,8 +234,7 @@ clib-routines.o: $(installed-clib)
# extra symbols.
kernel: check-clib-routines
check-clib-routines: clib-routines.o
- (set -e; test `echo $(clib-routines) | wc -w` -eq `nm $< | wc -l`; \
- touch check-clib-routines)
+ test `echo $(clib-routines) | wc -w` -eq `nm $< | wc -l` && touch check-clib-routines
# Empty dependency file
@@ -249,7 +264,7 @@ vpath %.srv $(srcdir)/device $(srcdir)/ipc $(srcdir)/kern
#
DEFINES += -DMACH -DCMU -DMACH_KERNEL -DKERNEL
-INCLUDES += -I. -I$(srcdir) -I$(srcdir)/include -I$(srcdir)/include/mach/sa \
+INCLUDES += -I. -I$(srcdir) -I$(srcdir)/include \
-I$(srcdir)/bogus -I$(srcdir)/util -I$(srcdir)/kern -I$(srcdir)/device
@@ -304,7 +319,8 @@ dist:
mkdir gnumach-$(version)
# Directories
mkdir gnumach-$(version)/{bogus,chips,ddb,device,ipc,kern,mig,scsi,util,vm,include}
- mkdir gnumach-$(version)/include/{mach,device,mach_debug}
+ mkdir gnumach-$(version)/include/{mach,device,mach_debug,sys}
+ mkdir gnumach-$(version)/include/mach/exec
for dir in `cat $(all-archs-subdirs)`; do \
mkdir -p gnumach-$(version)/$$dir; \
done
@@ -323,13 +339,19 @@ dist:
ln $(addprefix $(srcdir)/include/,$(mach-headers)) gnumach-$(version)/include/mach
ln $(addprefix $(srcdir)/include/,$(device-headers)) gnumach-$(version)/include/device
ln $(addprefix $(srcdir)/include/,$(mach-debug-headers)) gnumach-$(version)/include/mach_debug
+ ln $(addprefix $(srcdir)/include/,$(mach-exec-headers)) gnumach-$(version)/include/mach/exec
+ ln $(addprefix $(srcdir)/include/,$(other-headers)) gnumach-$(version)/include
+ ln $(addprefix $(srcdir)/include/sys/,$(other-sys-headers)) gnumach-$(version)/include/sys
+ ln $(addprefix $(srcdir)/include/mach/,$(other-mach-headers)) gnumach-$(version)/include/mach
# Files in arch dirs
for file in `cat $(all-archs-files)`; do \
ln $(srcdir)/$$file gnumach-$(version)/`dirname $$file`; \
done
for arch in $(all-archs); do \
- ln -s $$arch gnumach-$(version)/arch/include/mach/machine; \
+ ln -s $$arch gnumach-$(version)/$$arch/include/mach/machine; \
done
+ tar cfz gnumach-$(version).tar.gz gnumach-$(version)
+ rm -rf gnumach-$(version)
@@ -458,8 +480,8 @@ include $(subst .o,.d,$(cross-mig-objfiles)) /dev/null
endif
$(subst .o,.d,$(cross-mig-objfiles)): cross-%.d: $(srcdir)/mig/%.c
- set -e; $(CC) $(CFLAGS) -M -MG $< | \
- sed > $@.new -e 's/$*\.o:/$*.o $@:/'
+ set -e; $(CC) $(CFLAGS) -M -MG -I. -I$(srcdir)/mig $< | \
+ sed > $@.new -e 's/$*\.o:/cross-$*.o $@:/'
mv -f $@.new $@
@@ -478,14 +500,14 @@ include $(subst .o,.d,$(mig-objfiles))
endif
$(subst .o,.d,$(mig-objfiles)): %.d: $(srcdir)/mig/%.c
- set -e; $(BUILD_CC) $(BUILD_CFLAGS) -M -MG $< | \
+ set -e; $(BUILD_CC) $(BUILD_CFLAGS) -M -MG -I. -I$(srcdir)/mig $< | \
sed > $@.new -e 's/$*\.o:/$*.o $@:/'
mv -f $@.new $@
else
./migcom: ./cross-migcom
rm -f $@
- $(LN) $< $@
+ ln $< $@
endif
$(srcdir)/mig/lexxer.c: $(srcdir)/mig/lexxer.l
diff --git a/README b/README
index f3a04a4..4fa606f 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
-*- Text -*-
-This is the GNU mach 0.1 distribution.
+This is the GNU mach 1.0 distribution.
This kernel is derived from the Utah kernel source. We use it to run
the Hurd on. It is being distributed by us so that we can more easily
diff --git a/configure.in b/configure.in
index aef8c73..6885f6b 100644
--- a/configure.in
+++ b/configure.in
@@ -1,6 +1,17 @@
dnl Configure script for GNU Mach.
dnl Copyright 1997 Free Software Foundation, Inc.
-dnl This file is part of GNU Mach. Redistribution terms are not yet decided.
+
+dnl Permission to use, copy, modify and distribute this software and its
+dnl documentation is hereby granted, provided that both the copyright
+dnl notice and this permission notice appear in all copies of the
+dnl software, derivative works or modified versions, and any portions
+dnl thereof, and that both notices appear in supporting documentation.
+dnl
+dnl THE FREE SOFTWARE FOUNDATION ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+dnl "AS IS" CONDITION. THE FREE SOFTWARE FOUNDATION DISCLAIMS ANY
+dnl LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE
+dnl USE OF THIS SOFTWARE.
+
AC_INIT(kern/ipc_kobject.c)
diff --git a/i386/Drivers.in b/i386/Drivers.in
index e4d2260..b58eb1a 100644
--- a/i386/Drivers.in
+++ b/i386/Drivers.in
@@ -1,3 +1,17 @@
+dnl Device driver options for i386
+dnl Copyright 1997, Free Software Foundation, Inc.
+
+dnl Permission to use, copy, modify and distribute this software and its
+dnl documentation is hereby granted, provided that both the copyright
+dnl notice and this permission notice appear in all copies of the
+dnl software, derivative works or modified versions, and any portions
+dnl thereof, and that both notices appear in supporting documentation.
+dnl
+dnl THE FREE SOFTWARE FOUNDATION ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+dnl "AS IS" CONDITION. THE FREE SOFTWARE FOUNDATION DISCLAIMS ANY
+dnl LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE
+dnl USE OF THIS SOFTWARE.
+
AC_INIT(i386/i386asm.sym)
sinclude([../Drivers.macros])
diff --git a/i386/Files b/i386/Files
index 9521be3..a55e410 100644
--- a/i386/Files
+++ b/i386/Files
@@ -500,7 +500,6 @@ i386/include/Makefile.in
i386/include/Makerules
i386/include/mach/proc_ops.h
i386/include/mach/setjmp.h
-i386/include/mach/machine
i386/include/mach/sa/stdarg.h
i386/include/mach/sa/sys/varargs.h
i386/include/mach/i386/asm.h
diff --git a/i386/Makefrag b/i386/Makefrag
index fcab470..d08bc3f 100644
--- a/i386/Makefrag
+++ b/i386/Makefrag
@@ -1,6 +1,16 @@
# i386 Mach makefile fragment
-# Copyright 1996 Free Software Foundation, Inc.
-# This file is part of GNU Mach. Redistribution terms are not yet decided.
+# Copyright 1997 Free Software Foundation, Inc.
+#
+# 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.
+#
+# THE FREE SOFTWARE FOUNDATION ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+# "AS IS" CONDITION. THE FREE SOFTWARE FOUNDATION DISCLAIMS ANY
+# LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE
+# USE OF THIS SOFTWARE.
# Some of the i386-specific code checks for these.
@@ -150,9 +160,23 @@ i386-installed-headers= mach/proc_ops.h \
vm_types.h)
+# Autoconf support
+
+$(sysdep)/configure: $(sysdep)/Drivers.in $(srcdir)/Drivers.macros
+ cd $(sysdep) && rm -f configure && autoconf Drivers.in > configure
+
+$(systype)/device-drivers.h $(systype)/driverlist: $(sysdep)/driverlist.in $(systype)/config.status
+ cd $(systype) && ./config.status
+
+$(systype)/config.status: $(sysdep)/configure
+ cd $(systype) && ./config.status --recheck
+
+
+
+
# Cheat, cheat, cheat.
fpe.o: fpe.b_elf
uudecode $<
vpath fpe.b_elf $(sysdep)/i386
-fpe.d:; touch $@ \ No newline at end of file
+fpe.d:; touch $@
diff --git a/include/alloca.h b/include/alloca.h
new file mode 100644
index 0000000..0a476b4
--- /dev/null
+++ b/include/alloca.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL). 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.
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ * Author: Bryan Ford, University of Utah CSL
+ */
+#ifndef _MACH_ALLOCA_H_
+#define _MACH_ALLOCA_H_
+
+#define alloca(size) __builtin_alloca(size)
+
+#endif _MACH_ALLOCA_H_
diff --git a/include/sys/ioctl.h b/include/sys/ioctl.h
new file mode 100644
index 0000000..732494d
--- /dev/null
+++ b/include/sys/ioctl.h
@@ -0,0 +1,52 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon rights
+ * to redistribute these changes.
+ */
+/*
+ * Format definitions for 'ioctl' commands in device definitions.
+ *
+ * From BSD4.4.
+ */
+
+#ifndef _MACH_SYS_IOCTL_H_
+#define _MACH_SYS_IOCTL_H_
+/*
+ * Ioctl's have the command encoded in the lower word, and the size of
+ * any in or out parameters in the upper word. The high 3 bits of the
+ * upper word are used to encode the in/out status of the parameter.
+ */
+#define IOCPARM_MASK 0x1fff /* parameter length, at most 13 bits */
+#define IOC_VOID 0x20000000 /* no parameters */
+#define IOC_OUT 0x40000000 /* copy out parameters */
+#define IOC_IN 0x80000000U /* copy in parameters */
+#define IOC_INOUT (IOC_IN|IOC_OUT)
+
+#define _IOC(inout,group,num,len) \
+ (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num))
+#define _IO(g,n) _IOC(IOC_VOID, (g), (n), 0)
+#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t))
+#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t))
+#define _IOWR(g,n,t) _IOC(IOC_INOUT, (g), (n), sizeof(t))
+
+#endif _MACH_SYS_IOCTL_H_
diff --git a/include/sys/reboot.h b/include/sys/reboot.h
new file mode 100644
index 0000000..d74ed98
--- /dev/null
+++ b/include/sys/reboot.h
@@ -0,0 +1,123 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993,1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)reboot.h 7.5 (Berkeley) 6/27/88
+ */
+/*
+ * Warning: The contents of this file are deprecated;
+ * it should only ever be used for BSD and Mach 3 compatibility.
+ * As the above copyright notice suggests, this file originated in BSD;
+ * it is mostly the same, except the flags after RB_DFLTROOT
+ * have diverged from BSD.
+ */
+#ifndef _MACH_SYS_REBOOT_H_
+#define _MACH_SYS_REBOOT_H_
+
+/*
+ * Arguments to reboot system call.
+ * These are converted to switches, and passed to startup program,
+ * and on to init.
+ */
+#define RB_AUTOBOOT 0 /* flags for system auto-booting itself */
+
+#define RB_ASKNAME 0x01 /* -a: ask for file name to reboot from */
+#define RB_SINGLE 0x02 /* -s: reboot to single user only */
+#define RB_KDB 0x04 /* -d: kernel debugger symbols loaded */
+#define RB_HALT 0x08 /* -h: enter KDB at bootup */
+ /* for host_reboot(): don't reboot,
+ just halt */
+#define RB_INITNAME 0x10 /* -i: name given for /etc/init (unused) */
+#define RB_DFLTROOT 0x20 /* use compiled-in rootdev */
+#define RB_NOBOOTRC 0x20 /* -b: don't run /etc/rc.boot */
+#define RB_ALTBOOT 0x40 /* use /boot.old vs /boot */
+#define RB_UNIPROC 0x80 /* -u: start only one processor */
+
+#define RB_SHIFT 8 /* second byte is for ux */
+
+#define RB_DEBUGGER 0x1000 /* for host_reboot(): enter kernel
+ debugger from user level */
+
+/* Corresponding BSD definitions, where they disagree with the Mach flags. */
+#define BSD_RB_NOSYNC 0x04 /* dont sync before reboot */
+#define BSD_RB_KDB 0x40 /* give control to kernel debugger */
+#define BSD_RB_RDONLY 0x80 /* mount root fs read-only */
+#define BSD_RB_DUMP 0x100 /* dump kernel memory before reboot */
+#define BSD_RB_MINIROOT 0x200 /* mini-root present in memory at boot time */
+#define BSD_RB_CONFIG 0x400 /* invoke user configuration routing */
+
+
+/*
+ * Constants for converting boot-style device number to type,
+ * adaptor (uba, mba, etc), unit number and partition number.
+ * Type (== major device number) is in the low byte
+ * for backward compatibility. Except for that of the "magic
+ * number", each mask applies to the shifted value.
+ * Format:
+ * (4) (4) (4) (4) (8) (8)
+ * --------------------------------
+ * |MA | AD| CT| UN| PART | TYPE |
+ * --------------------------------
+ */
+#define B_ADAPTORSHIFT 24
+#define B_ADAPTORMASK 0x0f
+#define B_ADAPTOR(val) (((val) >> B_ADAPTORSHIFT) & B_ADAPTORMASK)
+#define B_CONTROLLERSHIFT 20
+#define B_CONTROLLERMASK 0xf
+#define B_CONTROLLER(val) (((val)>>B_CONTROLLERSHIFT) & B_CONTROLLERMASK)
+#define B_UNITSHIFT 16
+#define B_UNITMASK 0xf
+#define B_UNIT(val) (((val) >> B_UNITSHIFT) & B_UNITMASK)
+#define B_PARTITIONSHIFT 8
+#define B_PARTITIONMASK 0xff
+#define B_PARTITION(val) (((val) >> B_PARTITIONSHIFT) & B_PARTITIONMASK)
+#define B_TYPESHIFT 0
+#define B_TYPEMASK 0xff
+#define B_TYPE(val) (((val) >> B_TYPESHIFT) & B_TYPEMASK)
+
+#define B_MAGICMASK ((u_int)0xf0000000U)
+#define B_DEVMAGIC ((u_int)0xa0000000U)
+
+#define MAKEBOOTDEV(type, adaptor, controller, unit, partition) \
+ (((type) << B_TYPESHIFT) | ((adaptor) << B_ADAPTORSHIFT) | \
+ ((controller) << B_CONTROLLERSHIFT) | ((unit) << B_UNITSHIFT) | \
+ ((partition) << B_PARTITIONSHIFT) | B_DEVMAGIC)
+
+#endif /* _MACH_SYS_REBOOT_H_ */
diff --git a/include/sys/time.h b/include/sys/time.h
new file mode 100644
index 0000000..ab96678
--- /dev/null
+++ b/include/sys/time.h
@@ -0,0 +1,53 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon rights
+ * to redistribute these changes.
+ */
+/*
+ * Time-keeper for kernel IO devices.
+ *
+ * May or may not have any relation to wall-clock time.
+ */
+
+#ifndef _MACH_SA_SYS_TIME_H_
+#define _MACH_SA_SYS_TIME_H_
+
+#include <mach/time_value.h>
+
+extern time_value_t time;
+
+/*
+ * Definitions to keep old code happy.
+ */
+#define timeval_t time_value_t
+#define timeval time_value
+#define tv_sec seconds
+#define tv_usec microseconds
+
+#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
+#define timercmp(tvp, uvp, cmp) \
+ ((tvp)->tv_sec cmp (uvp)->tv_sec || \
+ (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)
+#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
+
+#endif _MACH_SA_SYS_TIME_H_
diff --git a/include/sys/types.h b/include/sys/types.h
new file mode 100644
index 0000000..6973f89
--- /dev/null
+++ b/include/sys/types.h
@@ -0,0 +1,91 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+#ifndef _MACH_SA_SYS_TYPES_H_
+#define _MACH_SA_SYS_TYPES_H_
+
+#include <mach/machine/vm_types.h>
+
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef natural_t size_t;
+#endif
+
+#ifndef _SSIZE_T
+#define _SSIZE_T
+typedef integer_t ssize_t;
+#endif
+
+typedef unsigned short dev_t; /* device id */
+typedef unsigned long gid_t; /* group id */
+typedef unsigned long ino_t; /* inode number */
+typedef unsigned short mode_t; /* permissions */
+typedef unsigned short nlink_t; /* link count */
+typedef natural_t off_t; /* file offset */
+typedef unsigned long uid_t; /* user id */
+
+
+/* Symbols allowed but not required by POSIX */
+
+typedef char * caddr_t; /* address of a (signed) char */
+
+#ifndef _TIME_T
+#define _TIME_T
+typedef unsigned int time_t;
+#endif
+
+#define RAND_MAX 0x7fffffff
+
+/* Symbols not allowed by POSIX */
+#ifndef _POSIX_SOURCE
+
+/*
+ * Common type definitions that lots of old files seem to want.
+ */
+
+typedef unsigned char u_char; /* unsigned char */
+typedef unsigned short u_short; /* unsigned short */
+typedef unsigned int u_int; /* unsigned int */
+typedef unsigned long u_long; /* unsigned long */
+
+typedef struct _quad_ {
+ unsigned int val[2]; /* 2 32-bit values make... */
+} quad; /* an 8-byte item */
+
+typedef unsigned int daddr_t; /* disk address */
+
+#define major(i) (((i) >> 8) & 0xFF)
+#define minor(i) ((i) & 0xFF)
+#define makedev(i,j) ((((i) & 0xFF) << 8) | ((j) & 0xFF))
+
+#define NBBY 8
+
+#ifndef NULL
+#define NULL ((void *) 0) /* the null pointer */
+#endif
+
+#endif /* _POSIX_SOURCE */
+
+#endif /* _MACH_SA_SYS_TYPES_H_ */
diff --git a/kern/exception.c b/kern/exception.c
index ebd9e5b..e50541b 100644
--- a/kern/exception.c
+++ b/kern/exception.c
@@ -243,6 +243,10 @@ exception_no_server()
while (thread_should_halt(self))
thread_halt_self();
+
+ if (thread_suspend (self) == KERN_SUCCESS)
+ thread_exception_return ();
+
#if MACH_KDB
if (debug_user_with_kdb) {
/*
diff --git a/mig/ChangeLog b/mig/ChangeLog
new file mode 100644
index 0000000..00182f4
--- /dev/null
+++ b/mig/ChangeLog
@@ -0,0 +1,163 @@
+Thu Mar 20 14:56:34 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * error.c (unix_error_string): Assume HAVE_STRERROR.
+
+Wed May 15 13:55:01 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * user.c (WriteRequestArgs): Don't check args against akbUserArg.
+ (WritePackArg): Do check poly args also against akbUserArg.
+
+Thu May 2 19:13:32 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * routine.h (struct routine): Split rtReplyPort field into
+ rtUReplyPort and rtSReplyPort fields.
+ * routine.c (rtAddDummyReplyPort): Add USER arg, and use it.
+ (rtCheckRoutineArg): Set user or server or both reply ports.
+ (rtSetArgDefaults, rtCheckArgTypes, rtCheckRoutine): Deal with
+ split reply ports.
+ * user.c (WriteRequestHead, WriteMsgCheckReceive): Use
+ rtUReplyPort field instead of rtReplyPort.
+ (WriteRequestArgs): Only deal with user-side args.
+
+Wed May 15 13:55:01 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * user.c (WriteRequestArgs): Don't check args against akbUserArg.
+ (WritePackArg): Do check poly args also against akbUserArg.
+
+Thu May 2 19:13:32 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * routine.h (struct routine): Split rtReplyPort field into
+ rtUReplyPort and rtSReplyPort fields.
+ * routine.c (rtAddDummyReplyPort): Add USER arg, and use it.
+ (rtCheckRoutineArg): Set user or server or both reply ports.
+ (rtSetArgDefaults, rtCheckArgTypes, rtCheckRoutine): Deal with
+ split reply ports.
+ * user.c (WriteRequestHead, WriteMsgCheckReceive): Use
+ rtUReplyPort field instead of rtReplyPort.
+ (WriteRequestArgs): Only deal with user-side args.
+
+Thu Feb 29 12:46:40 1996 steve clawson <sclawson@marker.cs.utah.edu>
+
+ * user.c (WriteMsgCheckReceive): If the reply-port isn't
+ user-supplied and there was a message transmission error, then
+ deallocate it. From Michael I Bushnell (mib@gnu.ai.mit.edu).
+
+ * user.c (WriteMsgCheckIdentity): Dealloc reply port if a
+ mismatched reply comes in to avoid cascaded errors. From
+ Michael I Bushnell (mib@gnu.ai.mit.edu).
+
+Wed May 3 13:59:54 MDT 1995 Bryan Ford <baford@cs.utah.edu>
+
+ Merged in diffs from UK02p12 to UK02p15:
+
+ Wed May 3 10:47:41 MDT 1995 Bryan Ford <baford@cs.utah.edu>
+
+ * Released UK02p15.
+
+ * mig_string.h: include string.h instead of strings.h
+
+ * user.c, lexxer.l: changed index/rindex to strchr/strrchr.
+
+Fri Feb 10 13:25:54 MST 1995 Bryan Ford <baford@cs.utah.edu>
+
+ Merged in diffs from UK02p7 to UK02p9:
+
+ Sun, 29 Jan 1995 Remy.Card@masi.ibp.fr (Remy CARD)
+
+ Fixed a bug that causes mig to generate bad file names
+ in #include directives when generating the user source file.
+
+Fri Nov 25 13:56:32 MST 1994 Bryan Ford (baford@cs.utah.edu)
+
+ Merged in diffs from UK02p6 to UK02p7:
+
+ * MIG now compiles under BSD without 'vm_???_t' types
+ conflicting between host (BSD) and target (Mach)
+ header files. Basically, the MIG source files compiled
+ to run on the host machine no longer include mach/message.h;
+ instead they get the needed defines through cpu.h
+ which is built by compiling cpu.sym for the target machine.
+
+Mon Aug 29 18:31:21 1994 Bryan Ford (baford@cs.utah.edu)
+
+ * got rid of /usr/bin pathname in call to basename:
+ basename isn't always in /usr/bin.
+
+Fri Aug 26 11:36:10 1994 Louis-D. Dubeau (hallu@info.polymtl.ca)
+
+ * Fixed mig.sh to pass -imacros flags to CPP correctly.
+
+Tue Sep 6 10:00:29 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * Released UK02p6.
+
+ * use strerror instead of sys_errlist if it's available.
+
+ * Other minor portability fixes.
+
+Mon Aug 15 18:37:47 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * global.c (more_global): Prepend RoutinePrefix to ServerDemux
+ even for non-default value of ServerDemux.
+
+Fri Jul 8 14:36:53 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * routine.h (rtSkip): Take int arg.
+ * routine.c (rtSkip): Take int arg and increment by that many.
+ * parser.y (Statement): Grok `skip N;'; pass int arg to rtSkip.
+
+Fri May 13 15:08:56 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
+
+ * user.c (WriteMsgCheckReceive): Deallocate the reply port also if
+ we get one of the send errors that can cause the message to be
+ partially sent and then destroyed; otherwise we might later get a
+ spurious send-once notification.
+
+Wed Aug 4 10:34:42 1993 Michael I. Bushnell (mib at ernst.gnu.ai.mit.edu)
+
+ * Makefile: Don't use flex or bison; use lex and yacc instead.
+
+ * migcom.c (myfopen): Added extern declaration of errno.
+
+Wed Jun 30 19:46:51 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * user.c (WriteUser): Call WriteImport for skImport and skUImport
+ statements.
+ (WriteUserIndividual): Write all the import and uimport statements
+ to each file.
+
+Mon Jun 28 22:07:14 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * utils.c (WriteStaticShortDecl, WriteCheckDecl,
+ WriteStaticLongDecl): Generate a `const' definition.
+
+Fri Jun 25 17:53:26 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * utils.c (WriteCopyType): Write SubrPrefix before `mig_strncpy'.
+
+ * user.c (WriteRequestHead): Write SubrPrefix before
+ `mig_get_reply_port'.
+ (WriteMsgCheckReceive): Write SubrPrefix before
+ `mig_dealloc_reply_port'.
+ (WritePackArgValue): Write SubrPrefix before `mig_strncpy'.
+ (WriteExtractArgValue): Likewise.
+ (WriteExtractArgValue): Write SubrPrefix before `mig_allocate'.
+ (WriteMsgSend): Write SubrPrefix before `mach_msg_send_from_kernel'
+ and `mach_msg'.
+ (WriteMsgSendReceive): Write SubrPrefix before `mach_msg'.
+ (WriteMsgRPC): Write SubrPrefix before `mach_msg_rpc_from_kernel'
+ and `mach_msg'.
+
+ * server.c (WriteDestroyArg): Write SubrPrefix before `mig_deallocate'.
+ (WritePackArgValue): Write SubrPrefix before `mig_strncpy'.
+ (WriteDestroyPortArg): Write SubrPrefix before `ipc_port_release_send'.
+ (WriteAdjustMsgCircular): Write SubrPrefix before
+ `ipc_port_check_circularity'.
+
+ * routine.c (rtCheckRoutine): Prepend RoutinePrefix to
+ RT->rtServerName and RT->rtUserName.
+
+ * migcom.c (parseArgs): Recognize -subrprefix and -prefix.
+
+ * global.c (SubrPrefix, RoutinePrefix): Define new variables.
+ * global.h: Declare them.
diff --git a/mig/alloc.h b/mig/alloc.h
new file mode 100644
index 0000000..1d0b88f
--- /dev/null
+++ b/mig/alloc.h
@@ -0,0 +1,34 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#ifndef _ALLOC_H
+#define _ALLOC_H
+
+extern char *malloc();
+extern char *calloc();
+extern void free();
+
+#endif _ALLOC_H
diff --git a/mig/boolean.h b/mig/boolean.h
new file mode 100644
index 0000000..5773e5e
--- /dev/null
+++ b/mig/boolean.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ * Author: Bryan Ford, University of Utah CSL
+ */
+#ifndef _MIG_BOOLEAN_H_
+#define _MIG_BOOLEAN_H_
+
+#ifndef boolean_t
+#define boolean_t int
+#endif
+
+#ifndef TRUE
+#define TRUE ((boolean_t) 1)
+#endif
+
+#ifndef FALSE
+#define FALSE ((boolean_t) 0)
+#endif
+
+#endif /* _MIG_BOOLEAN_H_ */
diff --git a/mig/cpu.sym b/mig/cpu.sym
new file mode 100644
index 0000000..eca50f3
--- /dev/null
+++ b/mig/cpu.sym
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ * Author: Bryan Ford, University of Utah CSL
+ */
+
+#include <mach/message.h>
+
+expr sizeof(integer_t) word_size
+expr sizeof(integer_t)*8 word_size_in_bits
+expr sizeof(void*) sizeof_pointer
+expr sizeof(mach_msg_header_t) sizeof_mach_msg_header_t
+expr sizeof(mach_msg_type_t) sizeof_mach_msg_type_t
+expr sizeof(mach_msg_type_long_t) sizeof_mach_msg_type_long_t
+
+expr MACH_MSG_TYPE_UNSTRUCTURED
+expr MACH_MSG_TYPE_POLYMORPHIC
+expr MACH_MSG_TYPE_BIT
+expr MACH_MSG_TYPE_BOOLEAN
+expr MACH_MSG_TYPE_INTEGER_16
+expr MACH_MSG_TYPE_INTEGER_32
+expr MACH_MSG_TYPE_CHAR
+expr MACH_MSG_TYPE_BYTE
+expr MACH_MSG_TYPE_INTEGER_8
+expr MACH_MSG_TYPE_REAL
+expr MACH_MSG_TYPE_INTEGER_64
+expr MACH_MSG_TYPE_STRING
+expr MACH_MSG_TYPE_STRING_C
+
+expr MACH_MSG_TYPE_MOVE_RECEIVE
+expr MACH_MSG_TYPE_MOVE_SEND
+expr MACH_MSG_TYPE_MOVE_SEND_ONCE
+expr MACH_MSG_TYPE_COPY_SEND
+expr MACH_MSG_TYPE_MAKE_SEND
+expr MACH_MSG_TYPE_MAKE_SEND_ONCE
+
+expr MACH_MSG_TYPE_PORT_NAME
+expr MACH_MSG_TYPE_PORT_RECEIVE
+expr MACH_MSG_TYPE_PORT_SEND
+expr MACH_MSG_TYPE_PORT_SEND_ONCE
+
diff --git a/mig/error.c b/mig/error.c
new file mode 100644
index 0000000..ae97143
--- /dev/null
+++ b/mig/error.c
@@ -0,0 +1,91 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "global.h"
+#include "error.h"
+#include "lexxer.h"
+
+static const char *program;
+int errors = 0;
+
+void
+fatal(const char *format, ...)
+{
+ va_list pvar;
+ va_start(pvar, format);
+ fprintf(stderr, "%s: fatal: ", program);
+ (void) vfprintf(stderr, format, pvar);
+ fprintf(stderr, "\n");
+ va_end(pvar);
+ exit(1);
+}
+
+void
+warn(const char *format, ...)
+{
+ va_list pvar;
+ va_start(pvar, format);
+ if (!BeQuiet && (errors == 0))
+ {
+ fprintf(stderr, "\"%s\", line %d: warning: ", inname, lineno-1);
+ (void) vfprintf(stderr, format, pvar);
+ fprintf(stderr, "\n");
+ }
+ va_end(pvar);
+}
+
+void
+error(const char *format, ...)
+{
+ va_list pvar;
+ va_start(pvar, format);
+ fprintf(stderr, "\"%s\", line %d: ", inname, lineno-1);
+ (void) vfprintf(stderr, format, pvar);
+ fprintf(stderr, "\n");
+ va_end(pvar);
+ errors++;
+}
+
+const char *
+unix_error_string(int error_num)
+{
+ static char buffer[256];
+ const char *error_mess;
+
+ error_mess = strerror (error_num);
+
+ sprintf(buffer, "%s (%d)", error_mess, error_num);
+ return buffer;
+}
+
+void
+set_program_name(const char *name)
+{
+ program = name;
+}
diff --git a/mig/error.h b/mig/error.h
new file mode 100644
index 0000000..a5962fe
--- /dev/null
+++ b/mig/error.h
@@ -0,0 +1,61 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#ifndef _ERROR_H
+#define _ERROR_H
+
+#include <sys/errno.h>
+extern int errno;
+
+#if defined(__GNUC__)
+extern void fatal(const char *format, ...)
+#if __GNUC__ > 1
+ __attribute__ ((format (printf, 1, 2),
+ noreturn))
+#endif
+ ;
+extern void warn(const char *format, ...)
+#if __GNUC__ > 1
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ ;
+extern void error(const char *format, ...)
+#if __GNUC__ > 1
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ ;
+#else /* not defined(__GNUC__) */
+extern void fatal(const char *format, ...);
+extern void warn(const char *format, ...);
+extern void error(const char *format, ...);
+#endif /* defined(__GNUC__) */
+
+extern const char *unix_error_string(int error_num);
+
+extern int errors;
+extern void set_program_name(const char *name);
+
+#endif /* _ERROR_H */
diff --git a/mig/global.c b/mig/global.c
new file mode 100644
index 0000000..f1b25ac
--- /dev/null
+++ b/mig/global.c
@@ -0,0 +1,94 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include "error.h"
+#include "global.h"
+
+boolean_t BeQuiet = FALSE;
+boolean_t BeVerbose = FALSE;
+boolean_t UseMsgRPC = TRUE;
+boolean_t GenSymTab = FALSE;
+
+boolean_t IsKernelUser = FALSE;
+boolean_t IsKernelServer = FALSE;
+
+const_string_t RCSId = strNULL;
+
+const_string_t SubsystemName = strNULL;
+u_int SubsystemBase = 0;
+
+const_string_t MsgOption = strNULL;
+const_string_t WaitTime = strNULL;
+const_string_t ErrorProc = "MsgError";
+const_string_t ServerPrefix = "";
+const_string_t UserPrefix = "";
+const_string_t ServerDemux = strNULL;
+const_string_t SubrPrefix = "";
+const_string_t RoutinePrefix = "";
+
+string_t yyinname;
+
+const 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 UserFileName = strNULL;
+string_t ServerFileName = 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 (RoutinePrefix != NULL)
+ ServerDemux = strconcat (RoutinePrefix, ServerDemux);
+}
diff --git a/mig/global.h b/mig/global.h
new file mode 100644
index 0000000..b841cd5
--- /dev/null
+++ b/mig/global.h
@@ -0,0 +1,77 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#ifndef _GLOBAL_H
+#define _GLOBAL_H
+
+#include <sys/types.h>
+
+#include "boolean.h"
+#include "mig_string.h"
+
+extern boolean_t BeQuiet; /* no warning messages */
+extern boolean_t BeVerbose; /* summarize types, routines */
+extern boolean_t UseMsgRPC;
+extern boolean_t GenSymTab;
+
+extern boolean_t IsKernelUser;
+extern boolean_t IsKernelServer;
+
+extern const_string_t RCSId;
+
+extern const_string_t SubsystemName;
+extern u_int SubsystemBase;
+
+extern const_string_t MsgOption;
+extern const_string_t WaitTime;
+extern const_string_t ErrorProc;
+extern const_string_t ServerPrefix;
+extern const_string_t UserPrefix;
+extern const_string_t ServerDemux;
+extern const_string_t SubrPrefix;
+extern const_string_t RoutinePrefix;
+
+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 UserFileName;
+extern string_t ServerFileName;
+
+extern void more_global(void);
+
+extern const char LintLib[];
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#endif /* _GLOBAL_H */
diff --git a/mig/header.c b/mig/header.c
new file mode 100644
index 0000000..2635bc0
--- /dev/null
+++ b/mig/header.c
@@ -0,0 +1,210 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include "write.h"
+#include "utils.h"
+#include "global.h"
+#include "error.h"
+
+static void
+WriteIncludes(FILE *file)
+{
+ fprintf(file, "#include <mach/kern_return.h>\n");
+ fprintf(file, "#include <mach/port.h>\n");
+ fprintf(file, "#include <mach/message.h>\n");
+ fprintf(file, "\n");
+}
+
+static void
+WriteDefines(FILE *file)
+{
+}
+
+static 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\n");
+}
+
+static void
+WriteProlog(FILE *file, const char *protect)
+{
+ 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");
+
+ WriteIncludes(file);
+ WriteDefines(file);
+}
+
+static void
+WriteEpilog(FILE *file, const char *protect)
+{
+ if (protect != strNULL) {
+ fprintf(file, "\n");
+ fprintf(file, "#endif\t/* not defined(_%s) */\n", protect);
+ }
+}
+
+static void
+WriteUserRoutine(FILE *file, const 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, "{ ");
+ if (!rt->rtProcedure)
+ fprintf(file, "return ");
+ fprintf(file, "%s(", rt->rtUserName);
+ WriteList(file, rt->rtArgs, WriteNameDecl, akbUserArg, ", ", "");
+ fprintf(file, "); }\n");
+ fprintf(file, "#else\n");
+ fprintf(file, "(\n");
+ WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n");
+ fprintf(file, ");\n");
+ fprintf(file, "#endif\n");
+}
+
+void
+WriteUserHeader(FILE *file, const statement_t *stats)
+{
+ register const statement_t *stat;
+ const char *protect = strconcat(SubsystemName, "_user_");
+
+ WriteProlog(file, protect);
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ switch (stat->stKind)
+ {
+ case skRoutine:
+ WriteUserRoutine(file, stat->stRoutine);
+ break;
+ case skImport:
+ case skUImport:
+ WriteImport(file, stat->stFileName);
+ break;
+ case skSImport:
+ break;
+ default:
+ fatal("WriteHeader(): bad statement_kind_t (%d)",
+ (int) stat->stKind);
+ }
+ WriteEpilog(file, protect);
+}
+
+static void
+WriteServerRoutine(FILE *file, const 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, "{ ");
+ if (!rt->rtProcedure)
+ fprintf(file, "return ");
+ fprintf(file, "%s(", rt->rtServerName);
+ WriteList(file, rt->rtArgs, WriteNameDecl, akbServerArg, ", ", "");
+ fprintf(file, "); }\n");
+ fprintf(file, "#else\n");
+ fprintf(file, "(\n");
+ WriteList(file, rt->rtArgs, WriteServerVarDecl,
+ akbServerArg, ",\n", "\n");
+ fprintf(file, ");\n");
+ fprintf(file, "#endif\n");
+}
+
+void
+WriteServerHeader(FILE *file, const statement_t *stats)
+{
+ register const statement_t *stat;
+ const char *protect = strconcat(SubsystemName, "_server_");
+
+ WriteProlog(file, protect);
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ switch (stat->stKind)
+ {
+ case skRoutine:
+ WriteServerRoutine(file, stat->stRoutine);
+ break;
+ case skImport:
+ case skSImport:
+ WriteImport(file, stat->stFileName);
+ break;
+ case skUImport:
+ break;
+ default:
+ fatal("WriteServerHeader(): bad statement_kind_t (%d)",
+ (int) stat->stKind);
+ }
+ WriteEpilog(file, protect);
+}
+
+static void
+WriteInternalRedefine(FILE *file, register const routine_t *rt)
+{
+ fprintf(file, "#define %s %s_external\n", rt->rtUserName, rt->rtUserName);
+}
+
+void
+WriteInternalHeader(FILE *file, const statement_t *stats)
+{
+ register const 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:
+ break;
+ default:
+ fatal("WriteInternalHeader(): bad statement_kind_t (%d)",
+ (int) stat->stKind);
+ }
+}
diff --git a/mig/lexxer.c b/mig/lexxer.c
new file mode 100644
index 0000000..4119cdf
--- /dev/null
+++ b/mig/lexxer.c
@@ -0,0 +1,2518 @@
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: cvs/gnumach/mig/Attic/lexxer.c,v 1.1 1997/04/14 20:28:00 thomas Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator). This
+ * avoids problems with code like:
+ *
+ * if ( condition_holds )
+ * yyless( 5 );
+ * else
+ * do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ *yy_cp = yy_hold_char; \
+ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+ };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext_ptr = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 100
+#define YY_END_OF_BUFFER 101
+static yyconst short int yy_accept[515] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 101, 99, 97, 98, 94, 77, 78, 75,
+ 73, 72, 74, 76, 88, 70, 71, 82, 79, 83,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 84, 85, 80,
+ 87, 86, 81, 89, 99, 99, 99, 96, 96, 95,
+ 94, 0, 0, 93, 88, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 11, 87, 87, 87,
+ 87, 87, 19, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+
+ 89, 0, 90, 0, 0, 91, 0, 0, 0, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 12,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 0, 92, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 31,
+ 87, 87, 87, 28, 87, 87, 87, 87, 18, 87,
+ 87, 36, 87, 87, 87, 87, 20, 87, 87, 13,
+
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 24, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 25, 33, 40, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 32, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 42, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 34, 87, 87, 87, 87, 1,
+ 87, 87, 87, 87, 87, 27, 87, 87, 26, 87,
+ 87, 87, 87, 87, 87, 39, 87, 2, 87, 87,
+
+ 87, 87, 87, 8, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 9,
+ 87, 87, 37, 87, 41, 87, 87, 87, 7, 87,
+ 87, 87, 3, 15, 87, 87, 87, 87, 87, 87,
+ 87, 6, 87, 87, 45, 87, 35, 87, 30, 87,
+ 43, 10, 87, 87, 44, 87, 87, 87, 87, 17,
+ 16, 22, 38, 87, 87, 46, 14, 23, 87, 87,
+ 87, 29, 87, 21, 87, 87, 87, 87, 5, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 4,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+
+ 87, 87, 48, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 54, 53, 87, 87,
+ 87, 87, 87, 87, 56, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 57, 87, 49, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 58,
+ 87, 60, 87, 87, 87, 55, 61, 87, 62, 87,
+ 65, 87, 67, 87, 50, 51, 52, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 69, 87, 87,
+
+ 87, 87, 59, 87, 66, 87, 47, 87, 87, 87,
+ 63, 64, 68, 0
+ } ;
+
+static yyconst int yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 4, 1, 5, 6, 7, 1, 1, 1, 8,
+ 9, 10, 11, 12, 13, 7, 14, 15, 16, 17,
+ 18, 19, 15, 20, 15, 21, 15, 22, 23, 24,
+ 25, 26, 1, 1, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 36,
+ 52, 1, 53, 54, 55, 1, 56, 57, 58, 59,
+
+ 60, 32, 61, 62, 63, 36, 64, 65, 66, 67,
+ 68, 69, 43, 70, 71, 72, 73, 74, 49, 50,
+ 75, 36, 1, 76, 1, 77, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst int yy_meta[78] =
+ { 0,
+ 1, 1, 2, 1, 1, 1, 3, 1, 1, 1,
+ 1, 1, 3, 3, 4, 4, 4, 4, 4, 4,
+ 4, 1, 1, 1, 1, 1, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 1, 1, 1, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 1, 1
+ } ;
+
+static yyconst short int yy_base[524] =
+ { 0,
+ 0, 3, 9, 979, 86, 163, 97, 101, 111, 124,
+ 115, 129, 984, 986, 986, 986, 132, 986, 986, 986,
+ 986, 986, 986, 986, 139, 986, 986, 986, 986, 986,
+ 76, 0, 135, 62, 100, 131, 152, 152, 134, 143,
+ 162, 152, 169, 210, 126, 189, 172, 986, 986, 986,
+ 150, 986, 986, 0, 978, 956, 976, 986, 986, 986,
+ 246, 273, 282, 302, 293, 0, 181, 185, 171, 163,
+ 197, 198, 260, 202, 186, 202, 283, 287, 211, 951,
+ 282, 284, 0, 286, 211, 285, 289, 293, 290, 294,
+ 300, 305, 297, 297, 314, 303, 307, 316, 317, 315,
+
+ 0, 974, 986, 952, 972, 986, 377, 381, 971, 332,
+ 334, 300, 333, 330, 319, 342, 338, 346, 360, 358,
+ 356, 360, 359, 364, 366, 941, 367, 381, 386, 369,
+ 368, 387, 374, 379, 373, 375, 374, 381, 382, 383,
+ 381, 386, 403, 397, 407, 392, 407, 969, 986, 405,
+ 409, 410, 428, 416, 417, 426, 423, 424, 423, 426,
+ 425, 445, 425, 427, 443, 918, 433, 446, 447, 447,
+ 439, 446, 458, 460, 447, 469, 469, 474, 470, 0,
+ 475, 485, 464, 0, 476, 482, 479, 470, 0, 488,
+ 493, 0, 480, 492, 489, 481, 0, 496, 490, 0,
+
+ 493, 504, 503, 507, 933, 503, 928, 523, 510, 531,
+ 505, 531, 0, 522, 518, 526, 525, 536, 527, 519,
+ 528, 531, 533, 529, 537, 543, 543, 541, 533, 546,
+ 559, 563, 557, 0, 0, 0, 558, 567, 925, 566,
+ 565, 571, 569, 576, 574, 572, 579, 576, 592, 604,
+ 586, 578, 585, 0, 585, 589, 595, 608, 603, 608,
+ 605, 611, 625, 0, 613, 620, 625, 635, 622, 936,
+ 629, 630, 634, 639, 0, 636, 631, 637, 637, 0,
+ 641, 652, 640, 644, 648, 0, 649, 660, 0, 653,
+ 936, 665, 653, 652, 673, 0, 667, 0, 678, 671,
+
+ 682, 912, 678, 0, 678, 683, 689, 693, 682, 688,
+ 688, 692, 701, 695, 687, 694, 701, 699, 702, 0,
+ 698, 705, 0, 706, 0, 704, 711, 920, 0, 719,
+ 728, 727, 0, 0, 722, 720, 721, 933, 743, 727,
+ 733, 0, 734, 914, 0, 744, 0, 751, 0, 912,
+ 0, 0, 754, 738, 0, 912, 750, 755, 754, 0,
+ 0, 0, 0, 749, 919, 0, 0, 0, 910, 757,
+ 751, 0, 928, 0, 749, 766, 903, 754, 0, 792,
+ 769, 244, 768, 917, 96, 915, 924, 908, 913, 0,
+ 906, 910, 904, 922, 906, 901, 909, 897, 192, 917,
+
+ 899, 897, 0, 903, 909, 895, 887, 906, 905, 904,
+ 883, 887, 894, 896, 884, 898, 0, 0, 873, 894,
+ 871, 870, 885, 868, 0, 882, 877, 893, 874, 887,
+ 872, 97, 875, 763, 882, 867, 873, 881, 867, 879,
+ 878, 877, 863, 879, 874, 873, 848, 873, 0, 861,
+ 845, 859, 869, 857, 854, 856, 865, 853, 863, 845,
+ 860, 812, 859, 857, 857, 852, 854, 853, 853, 0,
+ 835, 0, 861, 863, 860, 0, 823, 842, 821, 840,
+ 0, 839, 818, 828, 0, 0, 0, 830, 822, 822,
+ 830, 807, 797, 804, 785, 792, 774, 0, 494, 329,
+
+ 319, 267, 0, 249, 0, 184, 0, 114, 112, 93,
+ 0, 0, 0, 986, 839, 843, 847, 4, 849, 853,
+ 857, 861, 865
+ } ;
+
+static yyconst short int yy_def[524] =
+ { 0,
+ 515, 515, 514, 3, 516, 516, 515, 515, 515, 515,
+ 517, 517, 514, 514, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 514, 514, 514,
+ 518, 514, 514, 519, 520, 521, 522, 514, 514, 514,
+ 514, 514, 514, 514, 514, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+
+ 519, 520, 514, 521, 522, 514, 514, 514, 523, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 523, 514, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+
+ 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
+ 518, 518, 518, 0, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514
+ } ;
+
+static yyconst short int yy_nxt[1064] =
+ { 0,
+ 514, 15, 16, 15, 15, 16, 15, 66, 17, 14,
+ 15, 16, 15, 14, 14, 14, 18, 19, 20, 21,
+ 22, 23, 24, 25, 25, 25, 25, 25, 25, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 32, 32, 37, 32, 38, 32, 39, 40, 41,
+ 42, 32, 43, 44, 45, 46, 32, 47, 32, 32,
+ 48, 49, 50, 32, 31, 32, 33, 34, 35, 32,
+ 32, 37, 38, 32, 51, 40, 41, 42, 43, 44,
+ 45, 46, 32, 32, 52, 53, 14, 15, 16, 15,
+ 14, 14, 73, 14, 14, 14, 14, 14, 15, 16,
+
+ 15, 55, 15, 16, 15, 55, 17, 14, 14, 14,
+ 14, 14, 15, 16, 15, 57, 59, 60, 59, 67,
+ 56, 73, 397, 513, 56, 15, 16, 15, 57, 17,
+ 59, 60, 59, 62, 61, 63, 398, 14, 14, 14,
+ 441, 442, 512, 74, 511, 67, 64, 64, 64, 64,
+ 64, 64, 64, 65, 65, 65, 65, 65, 65, 65,
+ 80, 14, 14, 14, 15, 16, 15, 14, 17, 74,
+ 14, 14, 14, 14, 14, 68, 96, 75, 81, 69,
+ 70, 71, 79, 82, 14, 14, 14, 14, 14, 72,
+ 76, 77, 85, 83, 81, 86, 78, 87, 100, 88,
+
+ 96, 112, 68, 75, 81, 69, 70, 71, 84, 89,
+ 82, 79, 510, 113, 14, 14, 14, 76, 77, 85,
+ 81, 86, 78, 97, 110, 119, 87, 100, 88, 411,
+ 112, 111, 98, 99, 84, 412, 89, 113, 14, 14,
+ 90, 114, 115, 120, 91, 118, 92, 62, 131, 63,
+ 110, 97, 119, 93, 125, 94, 95, 111, 98, 99,
+ 64, 64, 64, 64, 64, 64, 64, 114, 115, 90,
+ 120, 118, 91, 92, 62, 131, 62, 509, 391, 93,
+ 125, 94, 95, 62, 392, 63, 116, 107, 107, 107,
+ 107, 107, 107, 107, 393, 508, 64, 64, 64, 64,
+
+ 64, 64, 64, 108, 117, 108, 109, 65, 65, 65,
+ 65, 65, 65, 65, 127, 116, 64, 64, 64, 64,
+ 64, 64, 64, 121, 123, 132, 124, 140, 122, 128,
+ 117, 130, 129, 133, 134, 135, 136, 137, 138, 139,
+ 141, 142, 127, 152, 143, 144, 145, 146, 507, 147,
+ 121, 123, 132, 124, 122, 128, 140, 130, 150, 133,
+ 154, 134, 136, 137, 155, 138, 141, 139, 506, 152,
+ 142, 143, 144, 151, 153, 145, 146, 147, 108, 156,
+ 108, 109, 108, 157, 108, 109, 158, 150, 159, 154,
+ 155, 107, 107, 107, 107, 107, 107, 107, 160, 163,
+
+ 151, 153, 161, 162, 164, 165, 156, 167, 174, 157,
+ 169, 168, 170, 158, 171, 173, 175, 159, 172, 176,
+ 177, 178, 179, 180, 181, 160, 163, 182, 161, 162,
+ 183, 164, 165, 184, 167, 187, 174, 168, 185, 169,
+ 171, 170, 172, 175, 173, 176, 177, 178, 186, 179,
+ 180, 181, 188, 182, 190, 189, 183, 191, 192, 193,
+ 194, 187, 184, 195, 202, 185, 196, 197, 198, 199,
+ 200, 201, 203, 204, 206, 186, 207, 208, 188, 189,
+ 190, 209, 210, 191, 211, 193, 194, 192, 212, 213,
+ 195, 202, 196, 197, 198, 199, 200, 214, 203, 215,
+
+ 201, 206, 204, 216, 217, 207, 208, 218, 210, 209,
+ 219, 211, 220, 221, 222, 226, 223, 212, 213, 224,
+ 225, 214, 227, 228, 505, 229, 230, 232, 215, 231,
+ 233, 216, 235, 217, 218, 234, 236, 219, 222, 220,
+ 237, 226, 221, 223, 238, 245, 224, 225, 240, 242,
+ 227, 229, 228, 232, 230, 243, 231, 244, 233, 235,
+ 246, 234, 248, 247, 236, 249, 251, 237, 250, 253,
+ 252, 238, 245, 254, 240, 255, 256, 259, 242, 257,
+ 258, 243, 260, 262, 261, 263, 244, 264, 248, 246,
+ 247, 265, 249, 253, 250, 251, 252, 266, 267, 254,
+
+ 271, 255, 256, 257, 272, 259, 258, 262, 273, 260,
+ 261, 268, 263, 269, 274, 275, 264, 276, 277, 278,
+ 265, 279, 280, 286, 266, 267, 287, 284, 271, 285,
+ 288, 272, 281, 282, 289, 273, 290, 268, 291, 269,
+ 274, 292, 275, 276, 277, 283, 278, 279, 293, 286,
+ 294, 280, 295, 287, 284, 285, 288, 296, 297, 298,
+ 289, 281, 282, 290, 299, 300, 301, 291, 292, 303,
+ 304, 305, 283, 306, 308, 293, 294, 307, 310, 295,
+ 309, 311, 312, 313, 297, 296, 298, 314, 315, 316,
+ 317, 299, 301, 318, 300, 320, 303, 304, 305, 321,
+
+ 308, 306, 322, 323, 307, 310, 309, 324, 311, 313,
+ 325, 312, 327, 314, 326, 315, 316, 329, 330, 317,
+ 318, 331, 332, 333, 320, 321, 322, 334, 335, 336,
+ 337, 338, 323, 340, 324, 339, 344, 341, 325, 342,
+ 326, 327, 343, 345, 329, 330, 346, 351, 331, 347,
+ 332, 348, 333, 334, 349, 335, 336, 337, 352, 340,
+ 338, 353, 339, 341, 344, 354, 342, 356, 343, 345,
+ 355, 358, 359, 346, 363, 347, 351, 348, 360, 361,
+ 349, 364, 366, 367, 369, 370, 375, 352, 371, 353,
+ 376, 354, 372, 356, 355, 378, 379, 381, 359, 390,
+
+ 358, 394, 444, 363, 360, 361, 445, 446, 395, 367,
+ 364, 366, 369, 504, 370, 375, 371, 376, 372, 382,
+ 383, 378, 503, 381, 502, 379, 384, 473, 390, 474,
+ 385, 475, 476, 386, 501, 387, 388, 500, 389, 14,
+ 14, 14, 14, 54, 54, 54, 54, 58, 58, 58,
+ 58, 101, 101, 102, 499, 102, 102, 104, 498, 104,
+ 104, 105, 497, 105, 105, 148, 148, 148, 148, 496,
+ 495, 494, 493, 492, 491, 490, 489, 488, 487, 486,
+ 485, 484, 483, 482, 481, 480, 479, 478, 477, 472,
+ 471, 470, 469, 468, 467, 466, 465, 464, 463, 462,
+
+ 461, 460, 459, 458, 457, 456, 455, 454, 453, 452,
+ 451, 450, 449, 448, 447, 443, 440, 439, 438, 437,
+ 436, 435, 434, 433, 432, 431, 430, 429, 428, 427,
+ 426, 425, 424, 423, 422, 421, 420, 419, 418, 417,
+ 416, 415, 414, 413, 410, 409, 408, 407, 406, 405,
+ 404, 403, 402, 401, 400, 399, 396, 380, 377, 374,
+ 373, 368, 365, 362, 357, 350, 328, 319, 302, 270,
+ 241, 239, 205, 149, 166, 149, 106, 103, 103, 126,
+ 106, 103, 103, 514, 17, 13, 514, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514
+ } ;
+
+static yyconst short int yy_chk[1064] =
+ { 0,
+ 0, 1, 1, 1, 2, 2, 2, 518, 2, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 5, 5, 5, 5,
+ 5, 5, 34, 5, 5, 5, 5, 5, 7, 7,
+
+ 7, 7, 8, 8, 8, 8, 8, 5, 5, 5,
+ 5, 5, 9, 9, 9, 9, 11, 11, 11, 31,
+ 7, 34, 385, 510, 8, 10, 10, 10, 10, 10,
+ 12, 12, 12, 17, 12, 17, 385, 5, 5, 5,
+ 432, 432, 509, 35, 508, 31, 17, 17, 17, 17,
+ 17, 17, 17, 25, 25, 25, 25, 25, 25, 25,
+ 39, 5, 5, 6, 6, 6, 6, 6, 6, 35,
+ 6, 6, 6, 6, 6, 33, 45, 36, 39, 33,
+ 33, 33, 38, 40, 6, 6, 6, 6, 6, 33,
+ 37, 37, 42, 41, 51, 42, 37, 43, 47, 43,
+
+ 45, 69, 33, 36, 39, 33, 33, 33, 41, 43,
+ 40, 38, 506, 70, 6, 6, 6, 37, 37, 42,
+ 51, 42, 37, 46, 67, 75, 43, 47, 43, 399,
+ 69, 68, 46, 46, 41, 399, 43, 70, 6, 6,
+ 44, 71, 72, 76, 44, 74, 44, 61, 85, 61,
+ 67, 46, 75, 44, 79, 44, 44, 68, 46, 46,
+ 61, 61, 61, 61, 61, 61, 61, 71, 72, 44,
+ 76, 74, 44, 44, 62, 85, 62, 504, 382, 44,
+ 79, 44, 44, 63, 382, 63, 73, 62, 62, 62,
+ 62, 62, 62, 62, 382, 502, 63, 63, 63, 63,
+
+ 63, 63, 63, 64, 73, 64, 64, 65, 65, 65,
+ 65, 65, 65, 65, 81, 73, 64, 64, 64, 64,
+ 64, 64, 64, 77, 78, 86, 78, 93, 77, 82,
+ 73, 84, 82, 87, 88, 88, 89, 90, 91, 92,
+ 94, 95, 81, 112, 96, 97, 98, 99, 501, 100,
+ 77, 78, 86, 78, 77, 82, 93, 84, 110, 87,
+ 114, 88, 89, 90, 115, 91, 94, 92, 500, 112,
+ 95, 96, 97, 111, 113, 98, 99, 100, 107, 116,
+ 107, 107, 108, 117, 108, 108, 118, 110, 119, 114,
+ 115, 107, 107, 107, 107, 107, 107, 107, 120, 123,
+
+ 111, 113, 121, 122, 124, 125, 116, 127, 133, 117,
+ 128, 127, 129, 118, 130, 132, 134, 119, 131, 135,
+ 136, 137, 138, 139, 140, 120, 123, 141, 121, 122,
+ 142, 124, 125, 143, 127, 146, 133, 127, 144, 128,
+ 130, 129, 131, 134, 132, 135, 136, 137, 145, 138,
+ 139, 140, 147, 141, 151, 150, 142, 152, 153, 154,
+ 155, 146, 143, 156, 163, 144, 157, 158, 159, 160,
+ 161, 162, 164, 165, 167, 145, 168, 169, 147, 150,
+ 151, 170, 171, 152, 172, 154, 155, 153, 173, 174,
+ 156, 163, 157, 158, 159, 160, 161, 175, 164, 176,
+
+ 162, 167, 165, 177, 178, 168, 169, 179, 171, 170,
+ 179, 172, 181, 182, 183, 188, 185, 173, 174, 186,
+ 187, 175, 190, 191, 499, 193, 194, 196, 176, 195,
+ 198, 177, 201, 178, 179, 199, 202, 179, 183, 181,
+ 203, 188, 182, 185, 204, 211, 186, 187, 206, 208,
+ 190, 193, 191, 196, 194, 209, 195, 210, 198, 201,
+ 212, 199, 215, 214, 202, 216, 218, 203, 217, 220,
+ 219, 204, 211, 221, 206, 222, 223, 226, 208, 224,
+ 225, 209, 227, 229, 228, 230, 210, 231, 215, 212,
+ 214, 232, 216, 220, 217, 218, 219, 233, 237, 221,
+
+ 240, 222, 223, 224, 241, 226, 225, 229, 242, 227,
+ 228, 238, 230, 238, 243, 244, 231, 245, 246, 247,
+ 232, 248, 249, 252, 233, 237, 253, 251, 240, 251,
+ 255, 241, 250, 250, 256, 242, 257, 238, 258, 238,
+ 243, 259, 244, 245, 246, 250, 247, 248, 260, 252,
+ 261, 249, 262, 253, 251, 251, 255, 263, 265, 266,
+ 256, 250, 250, 257, 267, 268, 269, 258, 259, 271,
+ 272, 273, 250, 274, 277, 260, 261, 276, 279, 262,
+ 278, 281, 282, 283, 265, 263, 266, 284, 285, 287,
+ 288, 267, 269, 290, 268, 292, 271, 272, 273, 293,
+
+ 277, 274, 294, 295, 276, 279, 278, 297, 281, 283,
+ 299, 282, 301, 284, 300, 285, 287, 303, 305, 288,
+ 290, 306, 307, 308, 292, 293, 294, 309, 310, 311,
+ 312, 313, 295, 315, 297, 314, 319, 316, 299, 317,
+ 300, 301, 318, 321, 303, 305, 322, 330, 306, 324,
+ 307, 326, 308, 309, 327, 310, 311, 312, 331, 315,
+ 313, 332, 314, 316, 319, 335, 317, 337, 318, 321,
+ 336, 339, 340, 322, 346, 324, 330, 326, 341, 343,
+ 327, 348, 353, 354, 357, 358, 370, 331, 359, 332,
+ 371, 335, 364, 337, 336, 375, 376, 378, 340, 381,
+
+ 339, 383, 434, 346, 341, 343, 434, 434, 383, 354,
+ 348, 353, 357, 497, 358, 370, 359, 371, 364, 380,
+ 380, 375, 496, 378, 495, 376, 380, 462, 381, 462,
+ 380, 462, 462, 380, 494, 380, 380, 493, 380, 515,
+ 515, 515, 515, 516, 516, 516, 516, 517, 517, 517,
+ 517, 519, 519, 520, 492, 520, 520, 521, 491, 521,
+ 521, 522, 490, 522, 522, 523, 523, 523, 523, 489,
+ 488, 484, 483, 482, 480, 479, 478, 477, 475, 474,
+ 473, 471, 469, 468, 467, 466, 465, 464, 463, 461,
+ 460, 459, 458, 457, 456, 455, 454, 453, 452, 451,
+
+ 450, 448, 447, 446, 445, 444, 443, 442, 441, 440,
+ 439, 438, 437, 436, 435, 433, 431, 430, 429, 428,
+ 427, 426, 424, 423, 422, 421, 420, 419, 416, 415,
+ 414, 413, 412, 411, 410, 409, 408, 407, 406, 405,
+ 404, 402, 401, 400, 398, 397, 396, 395, 394, 393,
+ 392, 391, 389, 388, 387, 386, 384, 377, 373, 369,
+ 365, 356, 350, 344, 338, 328, 302, 291, 270, 239,
+ 207, 205, 166, 148, 126, 109, 105, 104, 102, 80,
+ 57, 56, 55, 13, 4, 514, 514, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
+ 514, 514, 514
+ } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+char *yytext;
+#line 1 "../gnumach/mig/lexxer.l"
+#define INITIAL 0
+#line 15 "../gnumach/mig/lexxer.l"
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <string.h>
+
+#include "mig_string.h"
+#include "type.h"
+#include "statement.h"
+#include "global.h"
+#include "parser.h"
+#include "lexxer.h"
+#include "cpu.h"
+
+#define stringize(x) #x
+
+#ifdef LDEBUG
+#define RETURN(sym) \
+{ \
+ printf("yylex: returning '%s' (%d)\n", #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 FRETURN(val) \
+{ \
+ yylval.flag = (val); \
+ RETURN(syIPCFlag); \
+}
+
+extern YYSTYPE yylval; /* added by rm */
+
+int lineno;
+char *inname;
+
+#ifdef YY_START
+static int oldYYBegin;
+#define SAVE_BEGIN oldYYBegin = YY_START
+#define RSTR_BEGIN BEGIN oldYYBegin
+#else
+static struct yysvf *oldYYBegin;
+#define SAVE_BEGIN oldYYBegin = yybgin
+#define RSTR_BEGIN yybgin = oldYYBegin;
+#endif
+
+static void doSharp(const char *body); /* process body of # directives */
+#define Normal 1
+#define String 2
+#define FileName 3
+#define QString 4
+#define SkipToEOL 5
+
+#line 859 "lex.yy.c"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines. This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( yy_current_buffer->yy_is_interactive ) \
+ { \
+ int c = '*', n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+ && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ if ( yyleng > 0 ) \
+ yy_current_buffer->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
+ YY_USER_ACTION
+
+YY_DECL
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 101 "../gnumach/mig/lexxer.l"
+
+
+#line 1012 "lex.yy.c"
+
+ if ( yy_init )
+ {
+ yy_init = 0;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yy_start )
+ yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! yy_current_buffer )
+ yy_current_buffer =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_load_buffer_state();
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+ yy_current_state += YY_AT_BOL();
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 515 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 986 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+
+do_action: /* This label is used only to access EOF actions. */
+
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yy_hold_char;
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 103 "../gnumach/mig/lexxer.l"
+RETURN(syRoutine);
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 104 "../gnumach/mig/lexxer.l"
+RETURN(syFunction);
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 105 "../gnumach/mig/lexxer.l"
+RETURN(syProcedure);
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 106 "../gnumach/mig/lexxer.l"
+RETURN(sySimpleProcedure);
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 107 "../gnumach/mig/lexxer.l"
+RETURN(sySimpleRoutine);
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 108 "../gnumach/mig/lexxer.l"
+RETURN(sySubsystem);
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 109 "../gnumach/mig/lexxer.l"
+RETURN(syMsgOption);
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 110 "../gnumach/mig/lexxer.l"
+RETURN(syMsgSeqno);
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 111 "../gnumach/mig/lexxer.l"
+RETURN(syWaitTime);
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 112 "../gnumach/mig/lexxer.l"
+RETURN(syNoWaitTime);
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 113 "../gnumach/mig/lexxer.l"
+RETURN(syIn);
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 114 "../gnumach/mig/lexxer.l"
+RETURN(syOut);
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 115 "../gnumach/mig/lexxer.l"
+RETURN(syInOut);
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 116 "../gnumach/mig/lexxer.l"
+RETURN(syRequestPort);
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 117 "../gnumach/mig/lexxer.l"
+RETURN(syReplyPort);
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 118 "../gnumach/mig/lexxer.l"
+RETURN(syUReplyPort);
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 119 "../gnumach/mig/lexxer.l"
+RETURN(sySReplyPort);
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 120 "../gnumach/mig/lexxer.l"
+RETURN(syArray);
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 121 "../gnumach/mig/lexxer.l"
+RETURN(syOf);
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 122 "../gnumach/mig/lexxer.l"
+RETURN(syErrorProc);
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 123 "../gnumach/mig/lexxer.l"
+RETURN(syServerPrefix);
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 124 "../gnumach/mig/lexxer.l"
+RETURN(syUserPrefix);
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 125 "../gnumach/mig/lexxer.l"
+RETURN(syServerDemux);
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 126 "../gnumach/mig/lexxer.l"
+RETURN(syRCSId);
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 127 "../gnumach/mig/lexxer.l"
+RETURN(syImport);
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 128 "../gnumach/mig/lexxer.l"
+RETURN(syUImport);
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 129 "../gnumach/mig/lexxer.l"
+RETURN(sySImport);
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 130 "../gnumach/mig/lexxer.l"
+RETURN(syType);
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 131 "../gnumach/mig/lexxer.l"
+RETURN(syKernelServer);
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 132 "../gnumach/mig/lexxer.l"
+RETURN(syKernelUser);
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 133 "../gnumach/mig/lexxer.l"
+RETURN(sySkip);
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 134 "../gnumach/mig/lexxer.l"
+RETURN(syStruct);
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 135 "../gnumach/mig/lexxer.l"
+RETURN(syInTran);
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 136 "../gnumach/mig/lexxer.l"
+RETURN(syOutTran);
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 137 "../gnumach/mig/lexxer.l"
+RETURN(syDestructor);
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 138 "../gnumach/mig/lexxer.l"
+RETURN(syCType);
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 139 "../gnumach/mig/lexxer.l"
+RETURN(syCUserType);
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 140 "../gnumach/mig/lexxer.l"
+RETURN(syCServerType);
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 141 "../gnumach/mig/lexxer.l"
+RETURN(syCString);
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 143 "../gnumach/mig/lexxer.l"
+FRETURN(flLong);
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 144 "../gnumach/mig/lexxer.l"
+FRETURN(flNotLong);
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 145 "../gnumach/mig/lexxer.l"
+FRETURN(flDealloc);
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 146 "../gnumach/mig/lexxer.l"
+FRETURN(flNotDealloc);
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 147 "../gnumach/mig/lexxer.l"
+FRETURN(flServerCopy);
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 148 "../gnumach/mig/lexxer.l"
+FRETURN(flCountInOut);
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 150 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_POLYMORPHIC,word_size_in_bits);
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 152 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_UNSTRUCTURED,0);
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 153 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_BIT,1);
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 154 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_BOOLEAN,32);
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 155 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_INTEGER_16,16);
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 156 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_INTEGER_32,32);
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 157 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_INTEGER_64,64);
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 158 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_CHAR,8);
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 159 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_BYTE,8);
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 160 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_INTEGER_8,8);
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 161 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_REAL,0);
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 162 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_STRING,0);
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 163 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_STRING_C,0);
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 165 "../gnumach/mig/lexxer.l"
+TPRETURN(MACH_MSG_TYPE_MOVE_RECEIVE,MACH_MSG_TYPE_PORT_RECEIVE,word_size_in_bits);
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 166 "../gnumach/mig/lexxer.l"
+TPRETURN(MACH_MSG_TYPE_COPY_SEND,MACH_MSG_TYPE_PORT_SEND,word_size_in_bits);
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 167 "../gnumach/mig/lexxer.l"
+TPRETURN(MACH_MSG_TYPE_MAKE_SEND,MACH_MSG_TYPE_PORT_SEND,word_size_in_bits);
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 168 "../gnumach/mig/lexxer.l"
+TPRETURN(MACH_MSG_TYPE_MOVE_SEND,MACH_MSG_TYPE_PORT_SEND,word_size_in_bits);
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 169 "../gnumach/mig/lexxer.l"
+TPRETURN(MACH_MSG_TYPE_MAKE_SEND_ONCE,MACH_MSG_TYPE_PORT_SEND_ONCE,word_size_in_bits);
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 170 "../gnumach/mig/lexxer.l"
+TPRETURN(MACH_MSG_TYPE_MOVE_SEND_ONCE,MACH_MSG_TYPE_PORT_SEND_ONCE,word_size_in_bits);
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 172 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_PORT_NAME,word_size_in_bits);
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 173 "../gnumach/mig/lexxer.l"
+TPRETURN(MACH_MSG_TYPE_POLYMORPHIC,MACH_MSG_TYPE_PORT_RECEIVE,word_size_in_bits);
+ YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 174 "../gnumach/mig/lexxer.l"
+TPRETURN(MACH_MSG_TYPE_POLYMORPHIC,MACH_MSG_TYPE_PORT_SEND,word_size_in_bits);
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 175 "../gnumach/mig/lexxer.l"
+TPRETURN(MACH_MSG_TYPE_POLYMORPHIC,MACH_MSG_TYPE_PORT_SEND_ONCE,word_size_in_bits);
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 176 "../gnumach/mig/lexxer.l"
+TRETURN(MACH_MSG_TYPE_POLYMORPHIC,0);
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 178 "../gnumach/mig/lexxer.l"
+RETURN(syColon);
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 179 "../gnumach/mig/lexxer.l"
+RETURN(sySemi);
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 180 "../gnumach/mig/lexxer.l"
+RETURN(syComma);
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 181 "../gnumach/mig/lexxer.l"
+RETURN(syPlus);
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 182 "../gnumach/mig/lexxer.l"
+RETURN(syMinus);
+ YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 183 "../gnumach/mig/lexxer.l"
+RETURN(syStar);
+ YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 184 "../gnumach/mig/lexxer.l"
+RETURN(syDiv);
+ YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 185 "../gnumach/mig/lexxer.l"
+RETURN(syLParen);
+ YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 186 "../gnumach/mig/lexxer.l"
+RETURN(syRParen);
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 187 "../gnumach/mig/lexxer.l"
+RETURN(syEqual);
+ YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 188 "../gnumach/mig/lexxer.l"
+RETURN(syCaret);
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 189 "../gnumach/mig/lexxer.l"
+RETURN(syTilde);
+ YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 190 "../gnumach/mig/lexxer.l"
+RETURN(syLAngle);
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 191 "../gnumach/mig/lexxer.l"
+RETURN(syRAngle);
+ YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 192 "../gnumach/mig/lexxer.l"
+RETURN(syLBrack);
+ YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 193 "../gnumach/mig/lexxer.l"
+RETURN(syRBrack);
+ YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 194 "../gnumach/mig/lexxer.l"
+RETURN(syBar);
+ YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 196 "../gnumach/mig/lexxer.l"
+{ yylval.identifier = strmake(yytext);
+ RETURN(syIdentifier); }
+ YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 198 "../gnumach/mig/lexxer.l"
+{ yylval.number = atoi(yytext); RETURN(syNumber); }
+ YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 200 "../gnumach/mig/lexxer.l"
+{ yylval.string = strmake(yytext);
+ BEGIN Normal; RETURN(syString); }
+ YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 202 "../gnumach/mig/lexxer.l"
+{ yylval.string = strmake(yytext);
+ BEGIN Normal; RETURN(syFileName); }
+ YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 204 "../gnumach/mig/lexxer.l"
+{ yylval.string = strmake(yytext);
+ BEGIN Normal; RETURN(syQString); }
+ YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 207 "../gnumach/mig/lexxer.l"
+{ doSharp(yytext+1);
+ SAVE_BEGIN;
+ BEGIN SkipToEOL; }
+ YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 210 "../gnumach/mig/lexxer.l"
+{ doSharp(yytext+1);
+ SAVE_BEGIN;
+ BEGIN SkipToEOL; }
+ YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 213 "../gnumach/mig/lexxer.l"
+{ yyerror("illegal # directive");
+ SAVE_BEGIN;
+ BEGIN SkipToEOL; }
+ YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 217 "../gnumach/mig/lexxer.l"
+RSTR_BEGIN;
+ YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 218 "../gnumach/mig/lexxer.l"
+;
+ YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 220 "../gnumach/mig/lexxer.l"
+;
+ YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 221 "../gnumach/mig/lexxer.l"
+{ lineno++; }
+ YY_BREAK
+case 99:
+YY_RULE_SETUP
+#line 222 "../gnumach/mig/lexxer.l"
+{ BEGIN Normal; RETURN(syError); }
+ YY_BREAK
+case 100:
+YY_RULE_SETUP
+#line 224 "../gnumach/mig/lexxer.l"
+ECHO;
+ YY_BREAK
+#line 1606 "lex.yy.c"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(Normal):
+case YY_STATE_EOF(String):
+case YY_STATE_EOF(FileName):
+case YY_STATE_EOF(QString):
+case YY_STATE_EOF(SkipToEOL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yy_hold_char;
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between yy_current_buffer and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yy_current_buffer->yy_input_file = yyin;
+ yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap() )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p =
+ yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+ {
+ register char *dest = yy_current_buffer->yy_ch_buf;
+ register char *source = yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( yy_current_buffer->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a singled characater, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+ YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = yy_current_buffer;
+
+ int yy_c_buf_p_offset =
+ (int) (yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yy_flex_realloc( (void *) b->yy_ch_buf,
+ b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = yy_current_buffer->yy_buf_size -
+ number_to_move - 1;
+#endif
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read );
+ }
+
+ if ( yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+ return ret_val;
+ }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = yy_start;
+ yy_current_state += YY_AT_BOL();
+
+ for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 515 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+ }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+ {
+ register int yy_is_jam;
+ register char *yy_cp = yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 515 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 514);
+
+ return yy_is_jam ? 0 : yy_current_state;
+ }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+ {
+ register char *yy_cp = yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yy_hold_char;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yy_n_chars + 2;
+ register char *dest = &yy_current_buffer->yy_ch_buf[
+ yy_current_buffer->yy_buf_size + 2];
+ register char *source =
+ &yy_current_buffer->yy_ch_buf[number_to_move];
+
+ while ( source > yy_current_buffer->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+
+ yytext_ptr = yy_bp;
+ yy_hold_char = *yy_cp;
+ yy_c_buf_p = yy_cp;
+ }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+ {
+ int c;
+
+ *yy_c_buf_p = yy_hold_char;
+
+ if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* This was really a NUL. */
+ *yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ yytext_ptr = yy_c_buf_p;
+ ++yy_c_buf_p;
+
+ switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap() )
+ {
+ yy_c_buf_p =
+ yytext_ptr + YY_MORE_ADJ;
+ return EOF;
+ }
+
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+ break;
+
+ case EOB_ACT_LAST_MATCH:
+#ifdef __cplusplus
+ YY_FATAL_ERROR(
+ "unexpected last match in yyinput()" );
+#else
+ YY_FATAL_ERROR(
+ "unexpected last match in input()" );
+#endif
+ }
+ }
+ }
+
+ c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
+ *yy_c_buf_p = '\0'; /* preserve yytext */
+ yy_hold_char = *++yy_c_buf_p;
+
+ yy_current_buffer->yy_at_bol = (c == '\n');
+
+ return c;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+ {
+ if ( ! yy_current_buffer )
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_init_buffer( yy_current_buffer, input_file );
+ yy_load_buffer_state();
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+ {
+ if ( yy_current_buffer == new_buffer )
+ return;
+
+ if ( yy_current_buffer )
+ {
+ /* Flush out information for old buffer. */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+ {
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+ }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file );
+
+ return b;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+ {
+ if ( ! b )
+ return;
+
+ if ( b == yy_current_buffer )
+ yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yy_flex_free( (void *) b->yy_ch_buf );
+
+ yy_flex_free( (void *) b );
+ }
+
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+ {
+ yy_flush_buffer( b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+ b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+ b->yy_is_interactive = 0;
+#else
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+ {
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == yy_current_buffer )
+ yy_load_buffer_state();
+ }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer( b );
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *str )
+#else
+YY_BUFFER_STATE yy_scan_string( str )
+yyconst char *str;
+#endif
+ {
+ int len;
+ for ( len = 0; str[len]; ++len )
+ ;
+
+ return yy_scan_bytes( str, len );
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+ {
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+ buf = (char *) yy_flex_alloc( n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < len; ++i )
+ buf[i] = bytes[i];
+
+ buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer( buf, n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+ {
+ if ( yy_start_stack_ptr >= yy_start_stack_depth )
+ {
+ yy_size_t new_size;
+
+ yy_start_stack_depth += YY_START_STACK_INCR;
+ new_size = yy_start_stack_depth * sizeof( int );
+
+ if ( ! yy_start_stack )
+ yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+ else
+ yy_start_stack = (int *) yy_flex_realloc(
+ (void *) yy_start_stack, new_size );
+
+ if ( ! yy_start_stack )
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack" );
+ }
+
+ yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+ BEGIN(new_state);
+ }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+ {
+ if ( --yy_start_stack_ptr < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN(yy_start_stack[yy_start_stack_ptr]);
+ }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+ {
+ return yy_start_stack[yy_start_stack_ptr - 1];
+ }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+ {
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+ }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ yytext[yyleng] = yy_hold_char; \
+ yy_c_buf_p = yytext + n - YY_MORE_ADJ; \
+ yy_hold_char = *yy_c_buf_p; \
+ *yy_c_buf_p = '\0'; \
+ yyleng = n; \
+ } \
+ while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+ {
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+ }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+ {
+ return (void *) malloc( size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+ {
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+ {
+ free( ptr );
+ }
+
+#if YY_MAIN
+int main()
+ {
+ yylex();
+ return 0;
+ }
+#endif
+#line 224 "../gnumach/mig/lexxer.l"
+
+
+extern void
+LookNormal(void)
+{
+ if (inname == 0)
+ {
+ inname = strmake("(unknown)");
+ lineno = 0;
+ }
+
+ BEGIN Normal;
+}
+
+extern void
+LookString(void)
+{
+ BEGIN String;
+}
+
+extern void
+LookQString(void)
+{
+ BEGIN QString;
+}
+
+extern void
+LookFileName(void)
+{
+ BEGIN FileName;
+}
+
+static void
+doSharp(const char *body)
+{
+ register const char *startName;
+
+ lineno = atoi(body);
+ startName = strchr(body, '"');
+ if (startName != NULL)
+ {
+ *strrchr(body, '"') = '\0';
+ strfree(inname);
+ inname = strmake(startName+1);
+ }
+}
diff --git a/mig/lexxer.h b/mig/lexxer.h
new file mode 100644
index 0000000..822df89
--- /dev/null
+++ b/mig/lexxer.h
@@ -0,0 +1,33 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+extern int lineno;
+extern char *inname;
+
+extern void LookFileName(void);
+extern void LookString(void);
+extern void LookQString(void);
+extern void LookNormal(void);
diff --git a/mig/lexxer.l b/mig/lexxer.l
new file mode 100644
index 0000000..179e770
--- /dev/null
+++ b/mig/lexxer.l
@@ -0,0 +1,269 @@
+%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})
+
+%{
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <string.h>
+
+#include "mig_string.h"
+#include "type.h"
+#include "statement.h"
+#include "global.h"
+#include "parser.h"
+#include "lexxer.h"
+#include "cpu.h"
+
+#define stringize(x) #x
+
+#ifdef LDEBUG
+#define RETURN(sym) \
+{ \
+ printf("yylex: returning '%s' (%d)\n", #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 FRETURN(val) \
+{ \
+ yylval.flag = (val); \
+ RETURN(syIPCFlag); \
+}
+
+extern YYSTYPE yylval; /* added by rm */
+
+int lineno;
+char *inname;
+
+#ifdef YY_START
+static int oldYYBegin;
+#define SAVE_BEGIN oldYYBegin = YY_START
+#define RSTR_BEGIN BEGIN oldYYBegin
+#else
+static struct yysvf *oldYYBegin;
+#define SAVE_BEGIN oldYYBegin = yybgin
+#define RSTR_BEGIN yybgin = oldYYBegin;
+#endif
+
+static void doSharp(const char *body); /* process body of # directives */
+%}
+
+%Start Normal String FileName QString SkipToEOL
+
+%%
+
+<Normal>[Rr][Oo][Uu][Tt][Ii][Nn][Ee] RETURN(syRoutine);
+<Normal>[Ff][Uu][Nn][Cc][Tt][Ii][Oo][Nn] RETURN(syFunction);
+<Normal>[Pp][Rr][Oo][Cc][Ee][Dd][Uu][Rr][Ee] RETURN(syProcedure);
+<Normal>[Ss][Ii][Mm][Pp][Ll][Ee][Pp][Rr][Oo][Cc][Ee][Dd][Uu][Rr][Ee] RETURN(sySimpleProcedure);
+<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>[Ii][Nn] RETURN(syIn);
+<Normal>[Oo][Uu][Tt] RETURN(syOut);
+<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>[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>[Ii][Ss][Ll][Oo][Nn][Gg] FRETURN(flLong);
+<Normal>[Ii][Ss][Nn][Oo][Tt][Ll][Oo][Nn][Gg] FRETURN(flNotLong);
+<Normal>[Dd][Ee][Aa][Ll][Ll][Oo][Cc] FRETURN(flDealloc);
+<Normal>[Nn][Oo][Tt][Dd][Ee][Aa][Ll][Ll][Oo][Cc] FRETURN(flNotDealloc);
+<Normal>[Ss][Ee][Rr][Vv][Ee][Rr][Cc][Oo][Pp][Yy] FRETURN(flServerCopy);
+<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] TRETURN(MACH_MSG_TYPE_POLYMORPHIC,word_size_in_bits);
+
+<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_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_CHAR" TRETURN(MACH_MSG_TYPE_CHAR,8);
+<Normal>"MACH_MSG_TYPE_BYTE" TRETURN(MACH_MSG_TYPE_BYTE,8);
+<Normal>"MACH_MSG_TYPE_INTEGER_8" TRETURN(MACH_MSG_TYPE_INTEGER_8,8);
+<Normal>"MACH_MSG_TYPE_REAL" TRETURN(MACH_MSG_TYPE_REAL,0);
+<Normal>"MACH_MSG_TYPE_STRING" TRETURN(MACH_MSG_TYPE_STRING,0);
+<Normal>"MACH_MSG_TYPE_STRING_C" TRETURN(MACH_MSG_TYPE_STRING_C,0);
+
+<Normal>"MACH_MSG_TYPE_MOVE_RECEIVE" TPRETURN(MACH_MSG_TYPE_MOVE_RECEIVE,MACH_MSG_TYPE_PORT_RECEIVE,word_size_in_bits);
+<Normal>"MACH_MSG_TYPE_COPY_SEND" TPRETURN(MACH_MSG_TYPE_COPY_SEND,MACH_MSG_TYPE_PORT_SEND,word_size_in_bits);
+<Normal>"MACH_MSG_TYPE_MAKE_SEND" TPRETURN(MACH_MSG_TYPE_MAKE_SEND,MACH_MSG_TYPE_PORT_SEND,word_size_in_bits);
+<Normal>"MACH_MSG_TYPE_MOVE_SEND" TPRETURN(MACH_MSG_TYPE_MOVE_SEND,MACH_MSG_TYPE_PORT_SEND,word_size_in_bits);
+<Normal>"MACH_MSG_TYPE_MAKE_SEND_ONCE" TPRETURN(MACH_MSG_TYPE_MAKE_SEND_ONCE,MACH_MSG_TYPE_PORT_SEND_ONCE,word_size_in_bits);
+<Normal>"MACH_MSG_TYPE_MOVE_SEND_ONCE" TPRETURN(MACH_MSG_TYPE_MOVE_SEND_ONCE,MACH_MSG_TYPE_PORT_SEND_ONCE,word_size_in_bits);
+
+<Normal>"MACH_MSG_TYPE_PORT_NAME" TRETURN(MACH_MSG_TYPE_PORT_NAME,word_size_in_bits);
+<Normal>"MACH_MSG_TYPE_PORT_RECEIVE" TPRETURN(MACH_MSG_TYPE_POLYMORPHIC,MACH_MSG_TYPE_PORT_RECEIVE,word_size_in_bits);
+<Normal>"MACH_MSG_TYPE_PORT_SEND" TPRETURN(MACH_MSG_TYPE_POLYMORPHIC,MACH_MSG_TYPE_PORT_SEND,word_size_in_bits);
+<Normal>"MACH_MSG_TYPE_PORT_SEND_ONCE" TPRETURN(MACH_MSG_TYPE_POLYMORPHIC,MACH_MSG_TYPE_PORT_SEND_ONCE,word_size_in_bits);
+<Normal>"MACH_MSG_TYPE_POLYMORPHIC" TRETURN(MACH_MSG_TYPE_POLYMORPHIC,0);
+
+<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);
+ BEGIN Normal; RETURN(syString); }
+<FileName>{FileName} { yylval.string = strmake(yytext);
+ BEGIN Normal; RETURN(syFileName); }
+<QString>{QString} { yylval.string = strmake(yytext);
+ BEGIN Normal; RETURN(syQString); }
+
+^\#[ \t]*{Number}[ \t]*\"[^"]*\" { doSharp(yytext+1);
+ SAVE_BEGIN;
+ BEGIN SkipToEOL; }
+^\#\ *{Number} { doSharp(yytext+1);
+ SAVE_BEGIN;
+ BEGIN SkipToEOL; }
+^\# { yyerror("illegal # directive");
+ SAVE_BEGIN;
+ BEGIN SkipToEOL; }
+
+<SkipToEOL>\n RSTR_BEGIN;
+<SkipToEOL>. ;
+
+[ \t] ;
+\n { lineno++; }
+. { BEGIN Normal; RETURN(syError); }
+
+%%
+
+extern void
+LookNormal(void)
+{
+ if (inname == 0)
+ {
+ inname = strmake("(unknown)");
+ lineno = 0;
+ }
+
+ BEGIN Normal;
+}
+
+extern void
+LookString(void)
+{
+ BEGIN String;
+}
+
+extern void
+LookQString(void)
+{
+ BEGIN QString;
+}
+
+extern void
+LookFileName(void)
+{
+ BEGIN FileName;
+}
+
+static void
+doSharp(const char *body)
+{
+ register const char *startName;
+
+ lineno = atoi(body);
+ startName = strchr(body, '"');
+ if (startName != NULL)
+ {
+ *strrchr(body, '"') = '\0';
+ strfree(inname);
+ inname = strmake(startName+1);
+ }
+}
diff --git a/mig/message.h b/mig/message.h
new file mode 100644
index 0000000..bd98086
--- /dev/null
+++ b/mig/message.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ * Author: Bryan Ford, University of Utah CSL
+ */
+#ifndef _MIG_MESSAGE_H
+#define _MIG_MESSAGE_H
+
+/* This file is a substitute for mach/message.h,
+ to be used within MIG sources compiled for the build machine.
+ This way we avoid pulling in all the bogus typedefs and stuff
+ that would normally come with mach/message.h. */
+
+#include "cpu.h"
+
+#define MACH_MSG_TYPE_PORT_ANY(x) \
+ (((x) >= MACH_MSG_TYPE_MOVE_RECEIVE) && \
+ ((x) <= MACH_MSG_TYPE_MAKE_SEND_ONCE))
+
+#endif /* _MIG_MESSAGE_H */
diff --git a/mig/mig.sh b/mig/mig.sh
new file mode 100644
index 0000000..31afb7e
--- /dev/null
+++ b/mig/mig.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+#
+# Mach Operating System
+# Copyright (c) 1991,1990 Carnegie Mellon University
+# All Rights Reserved.
+#
+# Permission to use, copy, modify and distribute this software and its
+# documentation is hereby granted, provided that both the copyright
+# notice and this permission notice appear in all copies of the
+# software, derivative works or modified versions, and any portions
+# thereof, and that both notices appear in supporting documentation.
+#
+# CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+# CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+# ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+#
+# Carnegie Mellon requests users of this software to return to
+#
+# Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+# School of Computer Science
+# Carnegie Mellon University
+# Pittsburgh PA 15213-3890
+#
+# any improvements or extensions that they make and grant Carnegie Mellon
+# the rights to redistribute these changes.
+#
+
+migcom=${MIGDIR-@MIGDIR@}/migcom
+cpp="${CPP-@CPP@}"
+
+cppflags=
+migflags=
+files=
+
+# If an argument to this shell script contains whitespace,
+# then we will screw up. migcom will see it as multiple arguments.
+#
+# As a special hack, if -i is specified first we don't pass -user to migcom.
+# We do use the -user argument for the dependencies.
+# In this case, the -user argument can have whitespace.
+
+until [ $# -eq 0 ]
+do
+ case "$1" in
+ -[qQvVtTrRsS] ) migflags="$migflags $1"; shift;;
+ -i ) sawI=1; migflags="$migflags $1 $2"; shift; shift;;
+ -user ) user="$2"; if [ ! "${sawI-}" ]; then migflags="$migflags $1 $2"; fi; shift; shift;;
+ -server ) server="$2"; migflags="$migflags $1 $2"; shift; shift;;
+ -header ) header="$2"; migflags="$migflags $1 $2"; shift; shift;;
+ -sheader ) sheader="$2"; migflags="$migflags $1 $2"; shift; shift;;
+ -iheader ) iheader="$2"; migflags="$migflags $1 $2"; shift; shift;;
+ -prefix | -subrprefix ) migflags="$migflags $1 $2"; shift; shift;;
+
+ -MD ) sawMD=1; cppflags="$cppflags $1"; shift;;
+ -imacros ) cppflags="$cppflags $1 $2"; shift; shift;;
+ -cc) cpp="$2"; shift; shift;;
+ -migcom) migcom="$2"; shift; shift;;
+ -* ) cppflags="$cppflags $1"; shift;;
+ * ) files="$files $1"; shift;;
+ esac
+done
+
+for file in $files
+do
+ $cpp $cppflags "$file" | $migcom $migflags || exit
+
+ if [ $sawMD ]
+ then
+ base="`basename "$file"|sed 's%[.][^.]*$%%'`"
+ deps=
+ rheader="${header-${base}.h}"
+ if [ "$rheader" != /dev/null ]; then deps="$deps $rheader"; fi
+ ruser="${user-${base}User.c}"
+ if [ "$ruser" != /dev/null ]; then
+ if [ $sawI ]; then
+ for un in $ruser
+ do
+ deps="$deps $un"
+ done
+ else
+ deps="$deps $ruser"
+ fi
+ fi
+ rserver="${server-${base}Server.c}"
+ if [ "$rserver" != /dev/null ]; then deps="$deps $rserver"; fi
+ rsheader="${sheader-/dev/null}"
+ if [ "$rsheader" != /dev/null ]; then deps="$deps $rsheader"; fi
+ riheader="${iheader-/dev/null}"
+ if [ "$riheader" != /dev/null ]; then deps="$deps $riheader"; fi
+ sed 's%^[^:]*:%'"${deps}"':%' <"${base}.d" >"${base}-mig.d"
+ rm -f ${base}.d
+ fi
+done
+
+exit 0
diff --git a/mig/mig_string.h b/mig/mig_string.h
new file mode 100644
index 0000000..d6cef95
--- /dev/null
+++ b/mig/mig_string.h
@@ -0,0 +1,49 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#ifndef _MIG_STRING_H
+#define _MIG_STRING_H
+
+#include <string.h>
+
+#include "boolean.h"
+
+typedef char *string_t;
+typedef const char *const_string_t;
+typedef const_string_t identifier_t;
+
+#define strNULL ((string_t) 0)
+
+extern string_t strmake(const char *string);
+extern string_t strconcat(const_string_t left, const_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(const_string_t string);
+
+#endif /* _MIG_STRING_H */
diff --git a/mig/migcom.c b/mig/migcom.c
new file mode 100644
index 0000000..bfd6724
--- /dev/null
+++ b/mig/migcom.c
@@ -0,0 +1,298 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993,1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * Switches are;
+ * -[v,Q] verbose or not quiet: prints out type
+ * and routine information as mig runs.
+ * -[V,q] not verbose or quiet : don't print
+ * information during compilation
+ * (this is the default)
+ * -[r,R] do or don't use rpc calls instead of
+ * send/receive pairs. Default is -r.
+ * -[s,S] generate symbol table or not: generate a
+ * table of rpc-name, number, routine triplets
+ * as an external data structure -- main use is
+ * for protection system's specification of rights
+ * and for protection dispatch code. Default is -s.
+ * -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>
+ *
+ * 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 "error.h"
+#include "lexxer.h"
+#include "global.h"
+#include "write.h"
+
+extern int yyparse();
+static FILE *myfopen(const char *name, const char *mode);
+
+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 '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], "-subrprefix"))
+ {
+ --argc; ++argv;
+ if (argc == 0)
+ fatal ("missing string for -subrprefix option");
+ SubrPrefix = strmake(argv[0]);
+ }
+ else
+ GenSymTab = TRUE;
+ break;
+ case 'S':
+ GenSymTab = 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 'p':
+ if (streql(argv[0], "-prefix"))
+ {
+ if (--argc == 0)
+ fatal ("missing string for -prefix option");
+ RoutinePrefix = strmake(*++argv);
+ }
+ break;
+ default:
+ fatal("unknown flag: '%s'", argv[0]);
+ /*NOTREACHED*/
+ }
+ }
+ else
+ fatal("bad argument: '%s'", *argv);
+}
+
+void
+main(int argc, char **argv)
+{
+ FILE *uheader, *server, *user;
+ FILE *iheader, *sheader;
+
+ set_program_name("mig");
+ parseArgs(argc, argv);
+ init_global();
+ init_type();
+
+ LookNormal();
+ (void) yyparse();
+
+ if (errors > 0)
+ exit(1);
+
+ 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 (BeVerbose)
+ {
+ printf("Writing %s ... ", UserHeaderFileName);
+ fflush(stdout);
+ }
+ WriteUserHeader(uheader, StatementList);
+ fclose(uheader);
+ if (ServerHeaderFileName)
+ {
+ if (BeVerbose)
+ {
+ printf ("done.\nWriting %s ...", ServerHeaderFileName);
+ fflush (stdout);
+ }
+ WriteServerHeader(sheader, StatementList);
+ fclose(sheader);
+ }
+ if (IsKernelServer)
+ {
+ if (BeVerbose)
+ {
+ printf("done.\nWriting %s ... ", InternalHeaderFileName);
+ fflush(stdout);
+ }
+ WriteInternalHeader(iheader, StatementList);
+ fclose(iheader);
+ }
+ if (UserFilePrefix)
+ {
+ if (BeVerbose)
+ {
+ printf("done.\nWriting individual user files ... ");
+ fflush(stdout);
+ }
+ WriteUserIndividual(StatementList);
+ }
+ else
+ {
+ if (BeVerbose)
+ {
+ printf("done.\nWriting %s ... ", UserFileName);
+ fflush(stdout);
+ }
+ WriteUser(user, StatementList);
+ fclose(user);
+ }
+ if (BeVerbose)
+ {
+ printf("done.\nWriting %s ... ", ServerFileName);
+ fflush(stdout);
+ }
+ WriteServer(server, StatementList);
+ fclose(server);
+ if (BeVerbose)
+ printf("done.\n");
+
+ exit(0);
+}
+
+static FILE *
+myfopen(const char *name, const char *mode)
+{
+ const char *realname;
+ FILE *file;
+ extern int errno;
+
+ if (name == strNULL)
+ realname = "/dev/null";
+ else
+ realname = name;
+
+ file = fopen(realname, mode);
+ if (file == NULL)
+ fatal("fopen(%s): %s", realname, unix_error_string(errno));
+
+ return file;
+}
diff --git a/mig/parser.c b/mig/parser.c
new file mode 100644
index 0000000..c2ba442
--- /dev/null
+++ b/mig/parser.c
@@ -0,0 +1,1700 @@
+
+/* A Bison parser, made from ../gnumach/mig/parser.y
+ by Bison version A2.5 (Andrew Consortium)
+ */
+
+#define YYBISON 1 /* Identify Bison output. */
+
+#define sySkip 258
+#define syRoutine 259
+#define sySimpleRoutine 260
+#define sySimpleProcedure 261
+#define syProcedure 262
+#define syFunction 263
+#define sySubsystem 264
+#define syKernelUser 265
+#define syKernelServer 266
+#define syMsgOption 267
+#define syMsgSeqno 268
+#define syWaitTime 269
+#define syNoWaitTime 270
+#define syErrorProc 271
+#define syServerPrefix 272
+#define syUserPrefix 273
+#define syServerDemux 274
+#define syRCSId 275
+#define syImport 276
+#define syUImport 277
+#define sySImport 278
+#define syIn 279
+#define syOut 280
+#define syInOut 281
+#define syRequestPort 282
+#define syReplyPort 283
+#define sySReplyPort 284
+#define syUReplyPort 285
+#define syType 286
+#define syArray 287
+#define syStruct 288
+#define syOf 289
+#define syInTran 290
+#define syOutTran 291
+#define syDestructor 292
+#define syCType 293
+#define syCUserType 294
+#define syCServerType 295
+#define syCString 296
+#define syColon 297
+#define sySemi 298
+#define syComma 299
+#define syPlus 300
+#define syMinus 301
+#define syStar 302
+#define syDiv 303
+#define syLParen 304
+#define syRParen 305
+#define syEqual 306
+#define syCaret 307
+#define syTilde 308
+#define syLAngle 309
+#define syRAngle 310
+#define syLBrack 311
+#define syRBrack 312
+#define syBar 313
+#define syError 314
+#define syNumber 315
+#define sySymbolicType 316
+#define syIdentifier 317
+#define syString 318
+#define syQString 319
+#define syFileName 320
+#define syIPCFlag 321
+
+#line 117 "../gnumach/mig/parser.y"
+
+
+#include <stdio.h>
+
+#include "error.h"
+#include "lexxer.h"
+#include "global.h"
+#include "mig_string.h"
+#include "type.h"
+#include "routine.h"
+#include "statement.h"
+
+static const char *import_name(statement_kind_t sk);
+
+void
+yyerror(const char *s)
+{
+ error(s);
+}
+
+#line 138 "../gnumach/mig/parser.y"
+typedef union
+{
+ u_int number;
+ identifier_t identifier;
+ const_string_t string;
+ statement_kind_t statement_kind;
+ ipc_type_t *type;
+ struct
+ {
+ u_int innumber; /* msgt_name value, when sending */
+ const_string_t instr;
+ u_int outnumber; /* msgt_name value, when receiving */
+ const_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;
+} YYSTYPE;
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define YYFINAL 213
+#define YYFLAG -32768
+#define YYNTBASE 67
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 321 ? yytranslate[x] : 112)
+
+static const char yytranslate[] = { 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = { 0,
+ 0, 1, 4, 7, 10, 13, 16, 19, 22, 25,
+ 28, 31, 34, 38, 41, 44, 46, 49, 54, 56,
+ 57, 60, 62, 64, 66, 68, 72, 76, 78, 81,
+ 84, 87, 90, 94, 96, 98, 100, 104, 107, 111,
+ 113, 122, 131, 139, 144, 149, 154, 156, 158, 161,
+ 164, 167, 170, 172, 174, 181, 182, 186, 192, 194,
+ 196, 198, 202, 204, 209, 215, 223, 229, 235, 240,
+ 247, 251, 255, 259, 263, 265, 269, 271, 273, 275,
+ 277, 279, 283, 287, 291, 295, 300, 303, 307, 309,
+ 313, 318, 319, 321, 323, 325, 327, 329, 331, 333,
+ 335, 337, 339, 342, 345, 346, 347
+};
+
+static const short yyrhs[] = { -1,
+ 67, 68, 0, 69, 43, 0, 76, 43, 0, 75,
+ 43, 0, 77, 43, 0, 78, 43, 0, 79, 43,
+ 0, 80, 43, 0, 84, 43, 0, 98, 43, 0,
+ 3, 43, 0, 3, 60, 43, 0, 81, 43, 0,
+ 83, 43, 0, 43, 0, 1, 43, 0, 70, 71,
+ 73, 74, 0, 9, 0, 0, 71, 72, 0, 10,
+ 0, 11, 0, 62, 0, 60, 0, 109, 12, 63,
+ 0, 109, 14, 63, 0, 15, 0, 16, 62, 0,
+ 17, 62, 0, 18, 62, 0, 19, 62, 0, 110,
+ 82, 65, 0, 21, 0, 22, 0, 23, 0, 111,
+ 20, 64, 0, 31, 85, 0, 62, 51, 86, 0,
+ 87, 0, 86, 35, 42, 62, 62, 49, 62, 50,
+ 0, 86, 36, 42, 62, 62, 49, 62, 50, 0,
+ 86, 37, 42, 62, 49, 62, 50, 0, 86, 38,
+ 42, 62, 0, 86, 39, 42, 62, 0, 86, 40,
+ 42, 62, 0, 88, 0, 92, 0, 93, 87, 0,
+ 94, 87, 0, 52, 87, 0, 95, 87, 0, 96,
+ 0, 91, 0, 49, 91, 44, 97, 89, 50, 0,
+ 0, 89, 44, 66, 0, 89, 44, 66, 56, 57,
+ 0, 60, 0, 61, 0, 90, 0, 90, 58, 90,
+ 0, 62, 0, 32, 56, 57, 34, 0, 32, 56,
+ 47, 57, 34, 0, 32, 56, 47, 42, 97, 57,
+ 34, 0, 32, 56, 97, 57, 34, 0, 33, 56,
+ 97, 57, 34, 0, 41, 56, 97, 57, 0, 41,
+ 56, 47, 42, 97, 57, 0, 97, 45, 97, 0,
+ 97, 46, 97, 0, 97, 47, 97, 0, 97, 48,
+ 97, 0, 60, 0, 49, 97, 50, 0, 99, 0,
+ 100, 0, 101, 0, 102, 0, 103, 0, 4, 62,
+ 104, 0, 5, 62, 104, 0, 7, 62, 104, 0,
+ 6, 62, 104, 0, 8, 62, 104, 108, 0, 49,
+ 50, 0, 49, 105, 50, 0, 106, 0, 106, 43,
+ 105, 0, 107, 62, 108, 89, 0, 0, 24, 0,
+ 25, 0, 26, 0, 27, 0, 28, 0, 29, 0,
+ 30, 0, 14, 0, 12, 0, 13, 0, 42, 62,
+ 0, 42, 85, 0, 0, 0, 0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+ 161, 162, 165, 166, 167, 168, 169, 170, 171, 172,
+ 173, 183, 185, 187, 188, 189, 190, 194, 207, 219,
+ 220, 223, 229, 237, 240, 243, 260, 266, 274, 282,
+ 290, 298, 306, 317, 318, 319, 322, 332, 342, 346,
+ 348, 368, 388, 403, 417, 426, 438, 440, 442, 444,
+ 446, 448, 450, 454, 460, 469, 471, 478, 487, 493,
+ 497, 499, 523, 527, 529, 531, 536, 540, 544, 546,
+ 551, 553, 555, 557, 559, 561, 566, 567, 568, 569,
+ 570, 573, 577, 581, 585, 589, 593, 595, 600, 602,
+ 609, 619, 620, 621, 622, 623, 624, 625, 626, 627,
+ 628, 629, 632, 638, 642, 646, 650
+};
+#endif
+
+
+#if YYDEBUG != 0
+
+static const char * const yytname[] = { "$","error","$undefined.","sySkip",
+"syRoutine","sySimpleRoutine","sySimpleProcedure","syProcedure","syFunction",
+"sySubsystem","syKernelUser","syKernelServer","syMsgOption","syMsgSeqno","syWaitTime",
+"syNoWaitTime","syErrorProc","syServerPrefix","syUserPrefix","syServerDemux",
+"syRCSId","syImport","syUImport","sySImport","syIn","syOut","syInOut","syRequestPort",
+"syReplyPort","sySReplyPort","syUReplyPort","syType","syArray","syStruct","syOf",
+"syInTran","syOutTran","syDestructor","syCType","syCUserType","syCServerType",
+"syCString","syColon","sySemi","syComma","syPlus","syMinus","syStar","syDiv",
+"syLParen","syRParen","syEqual","syCaret","syTilde","syLAngle","syRAngle","syLBrack",
+"syRBrack","syBar","syError","syNumber","sySymbolicType","syIdentifier","syString",
+"syQString","syFileName","syIPCFlag","Statements","Statement","Subsystem","SubsystemStart",
+"SubsystemMods","SubsystemMod","SubsystemName","SubsystemBase","MsgOption","WaitTime",
+"Error","ServerPrefix","UserPrefix","ServerDemux","Import","ImportIndicant",
+"RCSDecl","TypeDecl","NamedTypeSpec","TransTypeSpec","TypeSpec","BasicTypeSpec",
+"IPCFlags","PrimIPCType","IPCType","PrevTypeSpec","VarArrayHead","ArrayHead",
+"StructHead","CStringSpec","IntExp","RoutineDecl","Routine","SimpleRoutine",
+"Procedure","SimpleProcedure","Function","Arguments","ArgumentList","Argument",
+"Direction","ArgumentType","LookString","LookFileName","LookQString", NULL
+};
+#endif
+
+static const short yyr1[] = { 0,
+ 67, 67, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 69, 70, 71,
+ 71, 72, 72, 73, 74, 75, 76, 76, 77, 78,
+ 79, 80, 81, 82, 82, 82, 83, 84, 85, 86,
+ 86, 86, 86, 86, 86, 86, 87, 87, 87, 87,
+ 87, 87, 87, 88, 88, 89, 89, 89, 90, 90,
+ 91, 91, 92, 93, 93, 93, 94, 95, 96, 96,
+ 97, 97, 97, 97, 97, 97, 98, 98, 98, 98,
+ 98, 99, 100, 101, 102, 103, 104, 104, 105, 105,
+ 106, 107, 107, 107, 107, 107, 107, 107, 107, 107,
+ 107, 107, 108, 108, 109, 110, 111
+};
+
+static const short yyr2[] = { 0,
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 3, 2, 2, 1, 2, 4, 1, 0,
+ 2, 1, 1, 1, 1, 3, 3, 1, 2, 2,
+ 2, 2, 3, 1, 1, 1, 3, 2, 3, 1,
+ 8, 8, 7, 4, 4, 4, 1, 1, 2, 2,
+ 2, 2, 1, 1, 6, 0, 3, 5, 1, 1,
+ 1, 3, 1, 4, 5, 7, 5, 5, 4, 6,
+ 3, 3, 3, 3, 1, 3, 1, 1, 1, 1,
+ 1, 3, 3, 3, 3, 4, 2, 3, 1, 3,
+ 4, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 2, 0, 0, 0
+};
+
+static const short yydefact[] = { 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 19, 28,
+ 0, 0, 0, 0, 0, 16, 2, 0, 20, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 77,
+ 78, 79, 80, 81, 0, 0, 0, 17, 12, 0,
+ 0, 0, 0, 0, 0, 29, 30, 31, 32, 0,
+ 38, 3, 0, 5, 4, 6, 7, 8, 9, 14,
+ 15, 10, 11, 0, 0, 34, 35, 36, 0, 0,
+ 13, 92, 82, 83, 85, 84, 0, 0, 22, 23,
+ 24, 21, 0, 26, 27, 33, 37, 101, 102, 100,
+ 93, 94, 95, 96, 97, 98, 99, 87, 0, 89,
+ 0, 0, 86, 0, 0, 0, 0, 0, 59, 60,
+ 63, 39, 40, 47, 61, 54, 48, 0, 0, 0,
+ 53, 25, 18, 88, 92, 0, 103, 104, 0, 0,
+ 0, 0, 51, 0, 0, 0, 0, 0, 0, 0,
+ 49, 50, 52, 90, 56, 0, 0, 0, 75, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 62, 91, 0, 0, 0, 64, 0, 0, 0, 0,
+ 0, 0, 0, 69, 56, 0, 0, 0, 44, 45,
+ 46, 0, 0, 65, 76, 71, 72, 73, 74, 67,
+ 68, 0, 0, 0, 0, 0, 57, 0, 70, 55,
+ 0, 0, 0, 0, 66, 0, 0, 43, 58, 41,
+ 42, 0, 0
+};
+
+static const short yydefgoto[] = { 1,
+ 17, 18, 19, 53, 82, 83, 123, 20, 21, 22,
+ 23, 24, 25, 26, 69, 27, 28, 51, 112, 113,
+ 114, 162, 115, 116, 117, 118, 119, 120, 121, 150,
+ 29, 30, 31, 32, 33, 34, 73, 99, 100, 101,
+ 103, 35, 36, 37
+};
+
+static const short yypact[] = {-32768,
+ 2, -5, -31, -16, 27, 28, 30, 33,-32768,-32768,
+ 35, 49, 71, 72, 89,-32768,-32768, 6,-32768, 60,
+ 67, 107, 109, 110, 111, 112, 113, 114, 115,-32768,
+-32768,-32768,-32768,-32768, 56, 9, 51,-32768,-32768, 116,
+ 117, 117, 117, 117, 117,-32768,-32768,-32768,-32768, 118,
+-32768,-32768, -10,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+-32768,-32768,-32768, 98, 99,-32768,-32768,-32768, 95, 100,
+-32768, 48,-32768,-32768,-32768,-32768, 121, 47,-32768,-32768,
+-32768,-32768, 105,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 120, 124,
+ 106, 119,-32768, 122, 123, 126, -7, 47,-32768,-32768,
+-32768, 101,-32768,-32768, 125,-32768,-32768, 47, 47, 47,
+-32768,-32768,-32768,-32768, 88, 121, 118,-32768, -13, -45,
+ -12, 127,-32768, 130, 131, 132, 133, 134, 135, -7,
+-32768,-32768,-32768,-32768,-32768, -29, -45, 146,-32768, -6,
+ 10, 142, 36, -45, 128, 129, 136, 137, 138, 139,
+-32768, 141, -45, 152, 82,-32768, -45, -45, -45, -45,
+ 153, 154, -45,-32768, 97, 140, 143, 144,-32768,-32768,
+-32768, 145, 74,-32768,-32768, 39, 39,-32768,-32768,-32768,
+-32768, 78, 41, 147, 148, 150, 151, 155,-32768,-32768,
+ 156, 157, 158, 149,-32768, 159, 160,-32768,-32768,-32768,
+-32768, 192,-32768
+};
+
+static const short yypgoto[] = {-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768, 92,-32768, -14,
+-32768, 20, 63, 108,-32768,-32768,-32768,-32768,-32768, -104,
+-32768,-32768,-32768,-32768,-32768,-32768, 104, 79,-32768,-32768,
+ 87,-32768,-32768,-32768
+};
+
+
+#define YYLAST 219
+
+
+static const short yytable[] = { 79,
+ 80, 212, 2, 147, 3, 4, 5, 6, 7, 8,
+ 9, 39, 163, -105, 149, -105, 10, 11, 12, 13,
+ 14, -107, -106, -106, -106, 151, 153, 164, 40, 66,
+ 67, 68, 15, 146, 152, 147, 147, 38, 167, 168,
+ 169, 170, 165, 148, 16, 41, 149, 149, 52, 175,
+ 171, 81, 109, 110, 167, 168, 169, 170, 183, 88,
+ 89, 90, 186, 187, 188, 189, 172, 64, 192, 65,
+ 70, 91, 92, 93, 94, 95, 96, 97, 104, 105,
+ 167, 168, 169, 170, 182, 169, 170, 106, 42, 43,
+ 200, 44, 174, 133, 45, 107, 46, 98, 108, 88,
+ 89, 90, 54, 141, 142, 143, 109, 110, 111, 55,
+ 47, 91, 92, 93, 94, 95, 96, 97, 167, 168,
+ 169, 170, 167, 168, 169, 170, 167, 168, 169, 170,
+ 198, 185, 48, 49, 199, 134, 135, 136, 137, 138,
+ 139, 167, 168, 169, 170, 74, 75, 76, 77, 56,
+ 50, 57, 58, 59, 60, 61, 62, 63, 71, 86,
+ 84, 85, 102, 87, 122, 72, 125, 126, 78, 124,
+ 154, 155, 156, 157, 158, 159, 160, 129, 130, 166,
+ 127, 131, 140, 173, 182, 184, 190, 191, 205, 176,
+ 177, 213, 196, 128, 193, 201, 202, 178, 179, 180,
+ 181, 194, 161, 144, 195, 209, 204, 208, 210, 211,
+ 197, 203, 145, 0, 132, 0, 0, 206, 207
+};
+
+static const short yycheck[] = { 10,
+ 11, 0, 1, 49, 3, 4, 5, 6, 7, 8,
+ 9, 43, 42, 12, 60, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 130, 131, 57, 60, 21,
+ 22, 23, 31, 47, 47, 49, 49, 43, 45, 46,
+ 47, 48, 147, 57, 43, 62, 60, 60, 43, 154,
+ 57, 62, 60, 61, 45, 46, 47, 48, 163, 12,
+ 13, 14, 167, 168, 169, 170, 57, 12, 173, 14,
+ 20, 24, 25, 26, 27, 28, 29, 30, 32, 33,
+ 45, 46, 47, 48, 44, 47, 48, 41, 62, 62,
+ 50, 62, 57, 108, 62, 49, 62, 50, 52, 12,
+ 13, 14, 43, 118, 119, 120, 60, 61, 62, 43,
+ 62, 24, 25, 26, 27, 28, 29, 30, 45, 46,
+ 47, 48, 45, 46, 47, 48, 45, 46, 47, 48,
+ 57, 50, 62, 62, 57, 35, 36, 37, 38, 39,
+ 40, 45, 46, 47, 48, 42, 43, 44, 45, 43,
+ 62, 43, 43, 43, 43, 43, 43, 43, 43, 65,
+ 63, 63, 42, 64, 60, 49, 43, 62, 51, 50,
+ 44, 42, 42, 42, 42, 42, 42, 56, 56, 34,
+ 62, 56, 58, 42, 44, 34, 34, 34, 34, 62,
+ 62, 0, 49, 102, 175, 49, 49, 62, 62, 62,
+ 62, 62, 140, 125, 62, 57, 56, 50, 50, 50,
+ 66, 62, 126, -1, 107, -1, -1, 62, 62
+};
+/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+#line 3 "/usr/share/bison.simple"
+
+/* Skeleton output parser for bison,
+ Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C. */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#include <alloca.h>
+#else /* not sparc */
+#if defined (MSDOS) && !defined (__TURBOC__)
+#include <malloc.h>
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+#include <malloc.h>
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#ifdef __cplusplus
+extern "C" {
+void *alloca (unsigned int);
+};
+#else /* not __cplusplus */
+void *alloca ();
+#endif /* not __cplusplus */
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc. */
+#endif /* not GNU C. */
+#endif /* alloca not defined. */
+
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+/* Note: there must be only one dollar sign in this file.
+ It is replaced by the list of actions, each action
+ as one case of the switch. */
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYACCEPT return(0)
+#define YYABORT return(1)
+#define YYERROR goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+ This remains here temporarily to ease the
+ transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+#define YYFAIL goto yyerrlab
+#define YYRECOVERING() (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { yychar = (token), yylval = (value); \
+ yychar1 = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { yyerror ("syntax error: cannot back up"); YYERROR; } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+#ifndef YYPURE
+#define YYLEX yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int yychar; /* the lookahead symbol */
+YYSTYPE yylval; /* the semantic value of the */
+ /* lookahead symbol */
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc; /* location data for the lookahead */
+ /* symbol */
+#endif
+
+int yynerrs; /* number of parse errors so far */
+#endif /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug; /* nonzero means print parse trace */
+/* Since this is uninitialized, it does not stop multiple parsers
+ from coexisting. */
+#endif
+
+/* YYINITDEPTH indicates the initial size of the parser's stacks */
+
+#ifndef YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH is the maximum size the stacks can grow to
+ (effective only if the built-in stack extension method is used). */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+/* Prevent warning if -Wstrict-prototypes. */
+#ifdef __GNUC__
+int yyparse (void);
+#endif
+
+#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+#else /* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (from, to, count)
+ char *from;
+ char *to;
+ int count;
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (char *from, char *to, int count)
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#endif
+#endif
+
+#line 192 "/usr/share/bison.simple"
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+ into yyparse. The argument should have type void *.
+ It should actually point to an object.
+ Grammar actions can access the variable by casting it
+ to the proper pointer type. */
+
+#ifdef YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#else
+#define YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#endif
+
+int
+yyparse(YYPARSE_PARAM)
+ YYPARSE_PARAM_DECL
+{
+ register int yystate;
+ register int yyn;
+ register short *yyssp;
+ register YYSTYPE *yyvsp;
+ int yyerrstatus; /* number of tokens to shift before error messages enabled */
+ int yychar1 = 0; /* lookahead token as an internal (translated) token number */
+
+ short yyssa[YYINITDEPTH]; /* the state stack */
+ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
+
+ short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
+ YYLTYPE *yyls = yylsa;
+ YYLTYPE *yylsp;
+
+#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK (yyvsp--, yyssp--)
+#endif
+
+ int yystacksize = YYINITDEPTH;
+
+#ifdef YYPURE
+ int yychar;
+ YYSTYPE yylval;
+ int yynerrs;
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylloc;
+#endif
+#endif
+
+ YYSTYPE yyval; /* the variable used to return */
+ /* semantic values from the action */
+ /* routines */
+
+ int yylen;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Starting parse\n");
+#endif
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss - 1;
+ yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in yystate . */
+/* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks. */
+yynewstate:
+
+ *++yyssp = yystate;
+
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ /* Give user a chance to reallocate the stack */
+ /* Use copies of these so that the &'s don't force the real ones into memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+ YYLTYPE *yyls1 = yyls;
+#endif
+
+ /* Get the current used size of the three stacks, in elements. */
+ int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ /* Each stack pointer address is followed by the size of
+ the data in use in that stack, in bytes. */
+#ifdef YYLSP_NEEDED
+ /* This used to be a conditional around just the two extra args,
+ but that might be undefined if yyoverflow is a macro. */
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yyls1, size * sizeof (*yylsp),
+ &yystacksize);
+#else
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yystacksize);
+#endif
+
+ yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+ yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+ /* Extend the stack our own way. */
+ if (yystacksize >= YYMAXDEPTH)
+ {
+ yyerror("parser stack overflow");
+ return 2;
+ }
+ yystacksize *= 2;
+ if (yystacksize > YYMAXDEPTH)
+ yystacksize = YYMAXDEPTH;
+ yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
+ __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
+ yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
+ __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+ yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
+ __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + size - 1;
+ yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+ if (yyssp >= yyss + yystacksize - 1)
+ YYABORT;
+ }
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+ goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* yychar is either YYEMPTY or YYEOF
+ or a valid token in external form. */
+
+ if (yychar == YYEMPTY)
+ {
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Reading a token: ");
+#endif
+ yychar = YYLEX;
+ }
+
+ /* Convert token to internal form (in yychar1) for indexing tables with */
+
+ if (yychar <= 0) /* This means end of input. */
+ {
+ yychar1 = 0;
+ yychar = YYEOF; /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Now at end of input.\n");
+#endif
+ }
+ else
+ {
+ yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+ /* Give the individual parser a way to print the precise meaning
+ of a token, for further debugging info. */
+#ifdef YYPRINT
+ YYPRINT (stderr, yychar, yylval);
+#endif
+ fprintf (stderr, ")\n");
+ }
+#endif
+ }
+
+ yyn += yychar1;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+ goto yydefault;
+
+ yyn = yytable[yyn];
+
+ /* yyn is what to do for this token type in this state.
+ Negative => reduce, -yyn is rule number.
+ Positive => shift, yyn is new state.
+ New state is final state => don't bother to shift,
+ just return success.
+ 0, or most negative number => error. */
+
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ /* count tokens shifted since error; after three, turn off error status. */
+ if (yyerrstatus) yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+/* Do the default action for the current state. */
+yydefault:
+
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+
+/* Do a reduction. yyn is the number of a rule to reduce with. */
+yyreduce:
+ yylen = yyr2[yyn];
+ if (yylen > 0)
+ yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ int i;
+
+ fprintf (stderr, "Reducing via rule %d (line %d), ",
+ yyn, yyrline[yyn]);
+
+ /* Print the symbols being reduced, and their result. */
+ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+ fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+ fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+ }
+#endif
+
+
+ switch (yyn) {
+
+case 11:
+#line 174 "../gnumach/mig/parser.y"
+{
+ register statement_t *st = stAlloc();
+
+ st->stKind = skRoutine;
+ st->stRoutine = yyvsp[-1].routine;
+ rtCheckRoutine(yyvsp[-1].routine);
+ if (BeVerbose)
+ rtPrintRoutine(yyvsp[-1].routine);
+;
+ break;}
+case 12:
+#line 184 "../gnumach/mig/parser.y"
+{ rtSkip(1); ;
+ break;}
+case 13:
+#line 186 "../gnumach/mig/parser.y"
+{ rtSkip(yyvsp[-1].number); ;
+ break;}
+case 17:
+#line 191 "../gnumach/mig/parser.y"
+{ yyerrok; ;
+ break;}
+case 18:
+#line 196 "../gnumach/mig/parser.y"
+{
+ if (BeVerbose)
+ {
+ printf("Subsystem %s: base = %u%s%s\n\n",
+ SubsystemName, SubsystemBase,
+ IsKernelUser ? ", KernelUser" : "",
+ IsKernelServer ? ", KernelServer" : "");
+ }
+;
+ break;}
+case 19:
+#line 208 "../gnumach/mig/parser.y"
+{
+ if (SubsystemName != strNULL)
+ {
+ warn("previous Subsystem decl (of %s) will be ignored", SubsystemName);
+ IsKernelUser = FALSE;
+ IsKernelServer = FALSE;
+ strfree((string_t) SubsystemName);
+ }
+;
+ break;}
+case 22:
+#line 224 "../gnumach/mig/parser.y"
+{
+ if (IsKernelUser)
+ warn("duplicate KernelUser keyword");
+ IsKernelUser = TRUE;
+;
+ break;}
+case 23:
+#line 230 "../gnumach/mig/parser.y"
+{
+ if (IsKernelServer)
+ warn("duplicate KernelServer keyword");
+ IsKernelServer = TRUE;
+;
+ break;}
+case 24:
+#line 237 "../gnumach/mig/parser.y"
+{ SubsystemName = yyvsp[0].identifier; ;
+ break;}
+case 25:
+#line 240 "../gnumach/mig/parser.y"
+{ SubsystemBase = yyvsp[0].number; ;
+ break;}
+case 26:
+#line 244 "../gnumach/mig/parser.y"
+{
+ if (streql(yyvsp[0].string, "MACH_MSG_OPTION_NONE"))
+ {
+ MsgOption = strNULL;
+ if (BeVerbose)
+ printf("MsgOption: canceled\n\n");
+ }
+ else
+ {
+ MsgOption = yyvsp[0].string;
+ if (BeVerbose)
+ printf("MsgOption %s\n\n",yyvsp[0].string);
+ }
+;
+ break;}
+case 27:
+#line 261 "../gnumach/mig/parser.y"
+{
+ WaitTime = yyvsp[0].string;
+ if (BeVerbose)
+ printf("WaitTime %s\n\n", WaitTime);
+;
+ break;}
+case 28:
+#line 267 "../gnumach/mig/parser.y"
+{
+ WaitTime = strNULL;
+ if (BeVerbose)
+ printf("NoWaitTime\n\n");
+;
+ break;}
+case 29:
+#line 275 "../gnumach/mig/parser.y"
+{
+ ErrorProc = yyvsp[0].identifier;
+ if (BeVerbose)
+ printf("ErrorProc %s\n\n", ErrorProc);
+;
+ break;}
+case 30:
+#line 283 "../gnumach/mig/parser.y"
+{
+ ServerPrefix = yyvsp[0].identifier;
+ if (BeVerbose)
+ printf("ServerPrefix %s\n\n", ServerPrefix);
+;
+ break;}
+case 31:
+#line 291 "../gnumach/mig/parser.y"
+{
+ UserPrefix = yyvsp[0].identifier;
+ if (BeVerbose)
+ printf("UserPrefix %s\n\n", UserPrefix);
+;
+ break;}
+case 32:
+#line 299 "../gnumach/mig/parser.y"
+{
+ ServerDemux = yyvsp[0].identifier;
+ if (BeVerbose)
+ printf("ServerDemux %s\n\n", ServerDemux);
+;
+ break;}
+case 33:
+#line 307 "../gnumach/mig/parser.y"
+{
+ register statement_t *st = stAlloc();
+ st->stKind = yyvsp[-1].statement_kind;
+ st->stFileName = yyvsp[0].string;
+
+ if (BeVerbose)
+ printf("%s %s\n\n", import_name(yyvsp[-1].statement_kind), yyvsp[0].string);
+;
+ break;}
+case 34:
+#line 317 "../gnumach/mig/parser.y"
+{ yyval.statement_kind = skImport; ;
+ break;}
+case 35:
+#line 318 "../gnumach/mig/parser.y"
+{ yyval.statement_kind = skUImport; ;
+ break;}
+case 36:
+#line 319 "../gnumach/mig/parser.y"
+{ yyval.statement_kind = skSImport; ;
+ break;}
+case 37:
+#line 323 "../gnumach/mig/parser.y"
+{
+ if (RCSId != strNULL)
+ warn("previous RCS decl will be ignored");
+ if (BeVerbose)
+ printf("RCSId %s\n\n", yyvsp[0].string);
+ RCSId = yyvsp[0].string;
+;
+ break;}
+case 38:
+#line 333 "../gnumach/mig/parser.y"
+{
+ register identifier_t name = yyvsp[0].type->itName;
+
+ if (itLookUp(name) != itNULL)
+ warn("overriding previous definition of %s", name);
+ itInsert(name, yyvsp[0].type);
+;
+ break;}
+case 39:
+#line 343 "../gnumach/mig/parser.y"
+{ itTypeDecl(yyvsp[-2].identifier, yyval.type = yyvsp[0].type); ;
+ break;}
+case 40:
+#line 347 "../gnumach/mig/parser.y"
+{ yyval.type = itResetType(yyvsp[0].type); ;
+ break;}
+case 41:
+#line 350 "../gnumach/mig/parser.y"
+{
+ yyval.type = yyvsp[-7].type;
+
+ if ((yyval.type->itTransType != strNULL) && !streql(yyval.type->itTransType, yyvsp[-4].identifier))
+ warn("conflicting translation types (%s, %s)",
+ yyval.type->itTransType, yyvsp[-4].identifier);
+ yyval.type->itTransType = yyvsp[-4].identifier;
+
+ if ((yyval.type->itInTrans != strNULL) && !streql(yyval.type->itInTrans, yyvsp[-3].identifier))
+ warn("conflicting in-translation functions (%s, %s)",
+ yyval.type->itInTrans, yyvsp[-3].identifier);
+ yyval.type->itInTrans = yyvsp[-3].identifier;
+
+ if ((yyval.type->itServerType != strNULL) && !streql(yyval.type->itServerType, yyvsp[-1].identifier))
+ warn("conflicting server types (%s, %s)",
+ yyval.type->itServerType, yyvsp[-1].identifier);
+ yyval.type->itServerType = yyvsp[-1].identifier;
+;
+ break;}
+case 42:
+#line 370 "../gnumach/mig/parser.y"
+{
+ yyval.type = yyvsp[-7].type;
+
+ if ((yyval.type->itServerType != strNULL) && !streql(yyval.type->itServerType, yyvsp[-4].identifier))
+ warn("conflicting server types (%s, %s)",
+ yyval.type->itServerType, yyvsp[-4].identifier);
+ yyval.type->itServerType = yyvsp[-4].identifier;
+
+ if ((yyval.type->itOutTrans != strNULL) && !streql(yyval.type->itOutTrans, yyvsp[-3].identifier))
+ warn("conflicting out-translation functions (%s, %s)",
+ yyval.type->itOutTrans, yyvsp[-3].identifier);
+ yyval.type->itOutTrans = yyvsp[-3].identifier;
+
+ if ((yyval.type->itTransType != strNULL) && !streql(yyval.type->itTransType, yyvsp[-1].identifier))
+ warn("conflicting translation types (%s, %s)",
+ yyval.type->itTransType, yyvsp[-1].identifier);
+ yyval.type->itTransType = yyvsp[-1].identifier;
+;
+ break;}
+case 43:
+#line 390 "../gnumach/mig/parser.y"
+{
+ yyval.type = yyvsp[-6].type;
+
+ if ((yyval.type->itDestructor != strNULL) && !streql(yyval.type->itDestructor, yyvsp[-3].identifier))
+ warn("conflicting destructor functions (%s, %s)",
+ yyval.type->itDestructor, yyvsp[-3].identifier);
+ yyval.type->itDestructor = yyvsp[-3].identifier;
+
+ if ((yyval.type->itTransType != strNULL) && !streql(yyval.type->itTransType, yyvsp[-1].identifier))
+ warn("conflicting translation types (%s, %s)",
+ yyval.type->itTransType, yyvsp[-1].identifier);
+ yyval.type->itTransType = yyvsp[-1].identifier;
+;
+ break;}
+case 44:
+#line 404 "../gnumach/mig/parser.y"
+{
+ yyval.type = yyvsp[-3].type;
+
+ if ((yyval.type->itUserType != strNULL) && !streql(yyval.type->itUserType, yyvsp[0].identifier))
+ warn("conflicting user types (%s, %s)",
+ yyval.type->itUserType, yyvsp[0].identifier);
+ yyval.type->itUserType = yyvsp[0].identifier;
+
+ if ((yyval.type->itServerType != strNULL) && !streql(yyval.type->itServerType, yyvsp[0].identifier))
+ warn("conflicting server types (%s, %s)",
+ yyval.type->itServerType, yyvsp[0].identifier);
+ yyval.type->itServerType = yyvsp[0].identifier;
+;
+ break;}
+case 45:
+#line 418 "../gnumach/mig/parser.y"
+{
+ yyval.type = yyvsp[-3].type;
+
+ if ((yyval.type->itUserType != strNULL) && !streql(yyval.type->itUserType, yyvsp[0].identifier))
+ warn("conflicting user types (%s, %s)",
+ yyval.type->itUserType, yyvsp[0].identifier);
+ yyval.type->itUserType = yyvsp[0].identifier;
+;
+ break;}
+case 46:
+#line 428 "../gnumach/mig/parser.y"
+{
+ yyval.type = yyvsp[-3].type;
+
+ if ((yyval.type->itServerType != strNULL) && !streql(yyval.type->itServerType, yyvsp[0].identifier))
+ warn("conflicting server types (%s, %s)",
+ yyval.type->itServerType, yyvsp[0].identifier);
+ yyval.type->itServerType = yyvsp[0].identifier;
+;
+ break;}
+case 47:
+#line 439 "../gnumach/mig/parser.y"
+{ yyval.type = yyvsp[0].type; ;
+ break;}
+case 48:
+#line 441 "../gnumach/mig/parser.y"
+{ yyval.type = yyvsp[0].type; ;
+ break;}
+case 49:
+#line 443 "../gnumach/mig/parser.y"
+{ yyval.type = itVarArrayDecl(yyvsp[-1].number, yyvsp[0].type); ;
+ break;}
+case 50:
+#line 445 "../gnumach/mig/parser.y"
+{ yyval.type = itArrayDecl(yyvsp[-1].number, yyvsp[0].type); ;
+ break;}
+case 51:
+#line 447 "../gnumach/mig/parser.y"
+{ yyval.type = itPtrDecl(yyvsp[0].type); ;
+ break;}
+case 52:
+#line 449 "../gnumach/mig/parser.y"
+{ yyval.type = itStructDecl(yyvsp[-1].number, yyvsp[0].type); ;
+ break;}
+case 53:
+#line 451 "../gnumach/mig/parser.y"
+{ yyval.type = yyvsp[0].type; ;
+ break;}
+case 54:
+#line 455 "../gnumach/mig/parser.y"
+{
+ yyval.type = itShortDecl(yyvsp[0].symtype.innumber, yyvsp[0].symtype.instr,
+ yyvsp[0].symtype.outnumber, yyvsp[0].symtype.outstr,
+ yyvsp[0].symtype.size);
+;
+ break;}
+case 55:
+#line 462 "../gnumach/mig/parser.y"
+{
+ yyval.type = itLongDecl(yyvsp[-4].symtype.innumber, yyvsp[-4].symtype.instr,
+ yyvsp[-4].symtype.outnumber, yyvsp[-4].symtype.outstr,
+ yyvsp[-4].symtype.size, yyvsp[-2].number, yyvsp[-1].flag);
+;
+ break;}
+case 56:
+#line 470 "../gnumach/mig/parser.y"
+{ yyval.flag = flNone; ;
+ break;}
+case 57:
+#line 472 "../gnumach/mig/parser.y"
+{
+ if (yyvsp[-2].flag & yyvsp[0].flag)
+ warn("redundant IPC flag ignored");
+ else
+ yyval.flag = yyvsp[-2].flag | yyvsp[0].flag;
+;
+ break;}
+case 58:
+#line 479 "../gnumach/mig/parser.y"
+{
+ if (yyvsp[-2].flag != flDealloc)
+ warn("only Dealloc is variable");
+ else
+ yyval.flag = yyvsp[-4].flag | flMaybeDealloc;
+;
+ break;}
+case 59:
+#line 488 "../gnumach/mig/parser.y"
+{
+ yyval.symtype.innumber = yyval.symtype.outnumber = yyvsp[0].number;
+ yyval.symtype.instr = yyval.symtype.outstr = strNULL;
+ yyval.symtype.size = 0;
+;
+ break;}
+case 60:
+#line 494 "../gnumach/mig/parser.y"
+{ yyval.symtype = yyvsp[0].symtype; ;
+ break;}
+case 61:
+#line 498 "../gnumach/mig/parser.y"
+{ yyval.symtype = yyvsp[0].symtype; ;
+ break;}
+case 62:
+#line 500 "../gnumach/mig/parser.y"
+{
+ if (yyvsp[-2].symtype.size != yyvsp[0].symtype.size)
+ {
+ if (yyvsp[-2].symtype.size == 0)
+ yyval.symtype.size = yyvsp[0].symtype.size;
+ else if (yyvsp[0].symtype.size == 0)
+ yyval.symtype.size = yyvsp[-2].symtype.size;
+ else
+ {
+ error("sizes in IPCTypes (%d, %d) aren't equal",
+ yyvsp[-2].symtype.size, yyvsp[0].symtype.size);
+ yyval.symtype.size = 0;
+ }
+ }
+ else
+ yyval.symtype.size = yyvsp[-2].symtype.size;
+ yyval.symtype.innumber = yyvsp[-2].symtype.innumber;
+ yyval.symtype.instr = yyvsp[-2].symtype.instr;
+ yyval.symtype.outnumber = yyvsp[0].symtype.outnumber;
+ yyval.symtype.outstr = yyvsp[0].symtype.outstr;
+;
+ break;}
+case 63:
+#line 524 "../gnumach/mig/parser.y"
+{ yyval.type = itPrevDecl(yyvsp[0].identifier); ;
+ break;}
+case 64:
+#line 528 "../gnumach/mig/parser.y"
+{ yyval.number = 0; ;
+ break;}
+case 65:
+#line 530 "../gnumach/mig/parser.y"
+{ yyval.number = 0; ;
+ break;}
+case 66:
+#line 533 "../gnumach/mig/parser.y"
+{ yyval.number = yyvsp[-2].number; ;
+ break;}
+case 67:
+#line 537 "../gnumach/mig/parser.y"
+{ yyval.number = yyvsp[-2].number; ;
+ break;}
+case 68:
+#line 541 "../gnumach/mig/parser.y"
+{ yyval.number = yyvsp[-2].number; ;
+ break;}
+case 69:
+#line 545 "../gnumach/mig/parser.y"
+{ yyval.type = itCStringDecl(yyvsp[-1].number, FALSE); ;
+ break;}
+case 70:
+#line 548 "../gnumach/mig/parser.y"
+{ yyval.type = itCStringDecl(yyvsp[-1].number, TRUE); ;
+ break;}
+case 71:
+#line 552 "../gnumach/mig/parser.y"
+{ yyval.number = yyvsp[-2].number + yyvsp[0].number; ;
+ break;}
+case 72:
+#line 554 "../gnumach/mig/parser.y"
+{ yyval.number = yyvsp[-2].number - yyvsp[0].number; ;
+ break;}
+case 73:
+#line 556 "../gnumach/mig/parser.y"
+{ yyval.number = yyvsp[-2].number * yyvsp[0].number; ;
+ break;}
+case 74:
+#line 558 "../gnumach/mig/parser.y"
+{ yyval.number = yyvsp[-2].number / yyvsp[0].number; ;
+ break;}
+case 75:
+#line 560 "../gnumach/mig/parser.y"
+{ yyval.number = yyvsp[0].number; ;
+ break;}
+case 76:
+#line 562 "../gnumach/mig/parser.y"
+{ yyval.number = yyvsp[-1].number; ;
+ break;}
+case 77:
+#line 566 "../gnumach/mig/parser.y"
+{ yyval.routine = yyvsp[0].routine; ;
+ break;}
+case 78:
+#line 567 "../gnumach/mig/parser.y"
+{ yyval.routine = yyvsp[0].routine; ;
+ break;}
+case 79:
+#line 568 "../gnumach/mig/parser.y"
+{ yyval.routine = yyvsp[0].routine; ;
+ break;}
+case 80:
+#line 569 "../gnumach/mig/parser.y"
+{ yyval.routine = yyvsp[0].routine; ;
+ break;}
+case 81:
+#line 570 "../gnumach/mig/parser.y"
+{ yyval.routine = yyvsp[0].routine; ;
+ break;}
+case 82:
+#line 574 "../gnumach/mig/parser.y"
+{ yyval.routine = rtMakeRoutine(yyvsp[-1].identifier, yyvsp[0].argument); ;
+ break;}
+case 83:
+#line 578 "../gnumach/mig/parser.y"
+{ yyval.routine = rtMakeSimpleRoutine(yyvsp[-1].identifier, yyvsp[0].argument); ;
+ break;}
+case 84:
+#line 582 "../gnumach/mig/parser.y"
+{ yyval.routine = rtMakeProcedure(yyvsp[-1].identifier, yyvsp[0].argument); ;
+ break;}
+case 85:
+#line 586 "../gnumach/mig/parser.y"
+{ yyval.routine = rtMakeSimpleProcedure(yyvsp[-1].identifier, yyvsp[0].argument); ;
+ break;}
+case 86:
+#line 590 "../gnumach/mig/parser.y"
+{ yyval.routine = rtMakeFunction(yyvsp[-2].identifier, yyvsp[-1].argument, yyvsp[0].type); ;
+ break;}
+case 87:
+#line 594 "../gnumach/mig/parser.y"
+{ yyval.argument = argNULL; ;
+ break;}
+case 88:
+#line 596 "../gnumach/mig/parser.y"
+{ yyval.argument = yyvsp[-1].argument; ;
+ break;}
+case 89:
+#line 601 "../gnumach/mig/parser.y"
+{ yyval.argument = yyvsp[0].argument; ;
+ break;}
+case 90:
+#line 603 "../gnumach/mig/parser.y"
+{
+ yyval.argument = yyvsp[-2].argument;
+ yyval.argument->argNext = yyvsp[0].argument;
+;
+ break;}
+case 91:
+#line 610 "../gnumach/mig/parser.y"
+{
+ yyval.argument = argAlloc();
+ yyval.argument->argKind = yyvsp[-3].direction;
+ yyval.argument->argName = yyvsp[-2].identifier;
+ yyval.argument->argType = yyvsp[-1].type;
+ yyval.argument->argFlags = yyvsp[0].flag;
+;
+ break;}
+case 92:
+#line 619 "../gnumach/mig/parser.y"
+{ yyval.direction = akNone; ;
+ break;}
+case 93:
+#line 620 "../gnumach/mig/parser.y"
+{ yyval.direction = akIn; ;
+ break;}
+case 94:
+#line 621 "../gnumach/mig/parser.y"
+{ yyval.direction = akOut; ;
+ break;}
+case 95:
+#line 622 "../gnumach/mig/parser.y"
+{ yyval.direction = akInOut; ;
+ break;}
+case 96:
+#line 623 "../gnumach/mig/parser.y"
+{ yyval.direction = akRequestPort; ;
+ break;}
+case 97:
+#line 624 "../gnumach/mig/parser.y"
+{ yyval.direction = akReplyPort; ;
+ break;}
+case 98:
+#line 625 "../gnumach/mig/parser.y"
+{ yyval.direction = akSReplyPort; ;
+ break;}
+case 99:
+#line 626 "../gnumach/mig/parser.y"
+{ yyval.direction = akUReplyPort; ;
+ break;}
+case 100:
+#line 627 "../gnumach/mig/parser.y"
+{ yyval.direction = akWaitTime; ;
+ break;}
+case 101:
+#line 628 "../gnumach/mig/parser.y"
+{ yyval.direction = akMsgOption; ;
+ break;}
+case 102:
+#line 629 "../gnumach/mig/parser.y"
+{ yyval.direction = akMsgSeqno; ;
+ break;}
+case 103:
+#line 633 "../gnumach/mig/parser.y"
+{
+ yyval.type = itLookUp(yyvsp[0].identifier);
+ if (yyval.type == itNULL)
+ error("type '%s' not defined", yyvsp[0].identifier);
+;
+ break;}
+case 104:
+#line 639 "../gnumach/mig/parser.y"
+{ yyval.type = yyvsp[0].type; ;
+ break;}
+case 105:
+#line 643 "../gnumach/mig/parser.y"
+{ LookString(); ;
+ break;}
+case 106:
+#line 647 "../gnumach/mig/parser.y"
+{ LookFileName(); ;
+ break;}
+case 107:
+#line 651 "../gnumach/mig/parser.y"
+{ LookQString(); ;
+ break;}
+}
+ /* the action file gets copied in in place of this dollarsign */
+#line 487 "/usr/share/bison.simple"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+ yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+ *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+ yylsp++;
+ if (yylen == 0)
+ {
+ yylsp->first_line = yylloc.first_line;
+ yylsp->first_column = yylloc.first_column;
+ yylsp->last_line = (yylsp-1)->last_line;
+ yylsp->last_column = (yylsp-1)->last_column;
+ yylsp->text = 0;
+ }
+ else
+ {
+ yylsp->last_line = (yylsp+yylen-1)->last_line;
+ yylsp->last_column = (yylsp+yylen-1)->last_column;
+ }
+#endif
+
+ /* Now "shift" the result of the reduction.
+ Determine what state that goes to,
+ based on the state we popped back to
+ and the rule number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+ if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTBASE];
+
+ goto yynewstate;
+
+yyerrlab: /* here on detecting error */
+
+ if (! yyerrstatus)
+ /* If not already recovering from an error, report this error. */
+ {
+ ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (yyn > YYFLAG && yyn < YYLAST)
+ {
+ int size = 0;
+ char *msg;
+ int x, count;
+
+ count = 0;
+ /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ size += strlen(yytname[x]) + 15, count++;
+ msg = (char *) malloc(size + 15);
+ if (msg != 0)
+ {
+ strcpy(msg, "parse error");
+
+ if (count < 5)
+ {
+ count = 0;
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ {
+ strcat(msg, count == 0 ? ", expecting `" : " or `");
+ strcat(msg, yytname[x]);
+ strcat(msg, "'");
+ count++;
+ }
+ }
+ yyerror(msg);
+ free(msg);
+ }
+ else
+ yyerror ("parse error; also virtual memory exceeded");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror("parse error");
+ }
+
+ goto yyerrlab1;
+yyerrlab1: /* here on error raised explicitly by an action */
+
+ if (yyerrstatus == 3)
+ {
+ /* if just tried and failed to reuse lookahead token after an error, discard it. */
+
+ /* return failure if at end of input */
+ if (yychar == YYEOF)
+ YYABORT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+ yychar = YYEMPTY;
+ }
+
+ /* Else will try to reuse lookahead token
+ after shifting the error token. */
+
+ yyerrstatus = 3; /* Each real token shifted decrements this */
+
+ goto yyerrhandle;
+
+yyerrdefault: /* current state does not do anything special for the error token. */
+
+#if 0
+ /* This is wrong; only states that explicitly want error tokens
+ should shift them. */
+ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+ if (yyn) goto yydefault;
+#endif
+
+yyerrpop: /* pop the current state because it cannot handle the error token */
+
+ if (yyssp == yyss) YYABORT;
+ yyvsp--;
+ yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+ yylsp--;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "Error: state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+yyerrhandle:
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yyerrdefault;
+
+ yyn += YYTERROR;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+ goto yyerrdefault;
+
+ yyn = yytable[yyn];
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrpop;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting error token, ");
+#endif
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ yystate = yyn;
+ goto yynewstate;
+}
+#line 654 "../gnumach/mig/parser.y"
+
+
+static const char *
+import_name(statement_kind_t sk)
+{
+ switch (sk)
+ {
+ case skImport:
+ return "Import";
+ case skSImport:
+ return "SImport";
+ case skUImport:
+ return "UImport";
+ default:
+ fatal("import_name(%d): not import statement", (int) sk);
+ /*NOTREACHED*/
+ }
+}
diff --git a/mig/parser.h b/mig/parser.h
new file mode 100644
index 0000000..5dd38ac
--- /dev/null
+++ b/mig/parser.h
@@ -0,0 +1,87 @@
+typedef union
+{
+ u_int number;
+ identifier_t identifier;
+ const_string_t string;
+ statement_kind_t statement_kind;
+ ipc_type_t *type;
+ struct
+ {
+ u_int innumber; /* msgt_name value, when sending */
+ const_string_t instr;
+ u_int outnumber; /* msgt_name value, when receiving */
+ const_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;
+} YYSTYPE;
+#define sySkip 258
+#define syRoutine 259
+#define sySimpleRoutine 260
+#define sySimpleProcedure 261
+#define syProcedure 262
+#define syFunction 263
+#define sySubsystem 264
+#define syKernelUser 265
+#define syKernelServer 266
+#define syMsgOption 267
+#define syMsgSeqno 268
+#define syWaitTime 269
+#define syNoWaitTime 270
+#define syErrorProc 271
+#define syServerPrefix 272
+#define syUserPrefix 273
+#define syServerDemux 274
+#define syRCSId 275
+#define syImport 276
+#define syUImport 277
+#define sySImport 278
+#define syIn 279
+#define syOut 280
+#define syInOut 281
+#define syRequestPort 282
+#define syReplyPort 283
+#define sySReplyPort 284
+#define syUReplyPort 285
+#define syType 286
+#define syArray 287
+#define syStruct 288
+#define syOf 289
+#define syInTran 290
+#define syOutTran 291
+#define syDestructor 292
+#define syCType 293
+#define syCUserType 294
+#define syCServerType 295
+#define syCString 296
+#define syColon 297
+#define sySemi 298
+#define syComma 299
+#define syPlus 300
+#define syMinus 301
+#define syStar 302
+#define syDiv 303
+#define syLParen 304
+#define syRParen 305
+#define syEqual 306
+#define syCaret 307
+#define syTilde 308
+#define syLAngle 309
+#define syRAngle 310
+#define syLBrack 311
+#define syRBrack 312
+#define syBar 313
+#define syError 314
+#define syNumber 315
+#define sySymbolicType 316
+#define syIdentifier 317
+#define syString 318
+#define syQString 319
+#define syFileName 320
+#define syIPCFlag 321
+
+
+extern YYSTYPE yylval;
diff --git a/mig/parser.y b/mig/parser.y
new file mode 100644
index 0000000..5ff1aae
--- /dev/null
+++ b/mig/parser.y
@@ -0,0 +1,671 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+%token sySkip
+%token syRoutine
+%token sySimpleRoutine
+%token sySimpleProcedure
+%token syProcedure
+%token syFunction
+
+%token sySubsystem
+%token syKernelUser
+%token syKernelServer
+
+%token syMsgOption
+%token syMsgSeqno
+%token syWaitTime
+%token syNoWaitTime
+%token syErrorProc
+%token syServerPrefix
+%token syUserPrefix
+%token syServerDemux
+%token syRCSId
+
+%token syImport
+%token syUImport
+%token sySImport
+
+%token syIn
+%token syOut
+%token syInOut
+%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 syCServerType
+
+%token syCString
+
+%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 TypeSpec
+%type <type> CStringSpec
+%type <type> BasicTypeSpec PrevTypeSpec ArgumentType
+%type <symtype> PrimIPCType IPCType
+%type <routine> RoutineDecl Routine SimpleRoutine
+%type <routine> Procedure SimpleProcedure Function
+%type <direction> Direction
+%type <argument> Argument Arguments ArgumentList
+%type <flag> IPCFlags
+
+%{
+
+#include <stdio.h>
+
+#include "error.h"
+#include "lexxer.h"
+#include "global.h"
+#include "mig_string.h"
+#include "type.h"
+#include "routine.h"
+#include "statement.h"
+
+static const char *import_name(statement_kind_t sk);
+
+void
+yyerror(const char *s)
+{
+ error(s);
+}
+%}
+
+%union
+{
+ u_int number;
+ identifier_t identifier;
+ const_string_t string;
+ statement_kind_t statement_kind;
+ ipc_type_t *type;
+ struct
+ {
+ u_int innumber; /* msgt_name value, when sending */
+ const_string_t instr;
+ u_int outnumber; /* msgt_name value, when receiving */
+ const_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
+ | MsgOption 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(1); }
+ | sySkip syNumber sySemi
+ { rtSkip($2); }
+ | 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((string_t) SubsystemName);
+ }
+}
+ ;
+
+SubsystemMods : /* empty */
+ | SubsystemMods SubsystemMod
+ ;
+
+SubsystemMod : syKernelUser
+{
+ if (IsKernelUser)
+ warn("duplicate KernelUser keyword");
+ 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);
+ }
+}
+ ;
+
+WaitTime : LookString syWaitTime syString
+{
+ WaitTime = $3;
+ if (BeVerbose)
+ printf("WaitTime %s\n\n", WaitTime);
+}
+ | syNoWaitTime
+{
+ WaitTime = strNULL;
+ if (BeVerbose)
+ printf("NoWaitTime\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; }
+ ;
+
+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; }
+ ;
+
+BasicTypeSpec : IPCType
+{
+ $$ = itShortDecl($1.innumber, $1.instr,
+ $1.outnumber, $1.outstr,
+ $1.size);
+}
+ | syLParen IPCType syComma IntExp
+ IPCFlags syRParen
+{
+ $$ = itLongDecl($2.innumber, $2.instr,
+ $2.outnumber, $2.outstr,
+ $2.size, $4, $5);
+}
+ ;
+
+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;
+}
+ ;
+
+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); }
+ ;
+
+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; }
+ | Procedure { $$ = $1; }
+ | SimpleProcedure { $$ = $1; }
+ | Function { $$ = $1; }
+ ;
+
+Routine : syRoutine syIdentifier Arguments
+ { $$ = rtMakeRoutine($2, $3); }
+ ;
+
+SimpleRoutine : sySimpleRoutine syIdentifier Arguments
+ { $$ = rtMakeSimpleRoutine($2, $3); }
+ ;
+
+Procedure : syProcedure syIdentifier Arguments
+ { $$ = rtMakeProcedure($2, $3); }
+ ;
+
+SimpleProcedure : sySimpleProcedure syIdentifier Arguments
+ { $$ = rtMakeSimpleProcedure($2, $3); }
+ ;
+
+Function : syFunction syIdentifier Arguments ArgumentType
+ { $$ = rtMakeFunction($2, $3, $4); }
+ ;
+
+Arguments : syLParen syRParen
+ { $$ = argNULL; }
+ | syLParen ArgumentList syRParen
+ { $$ = $2; }
+
+ ;
+
+ArgumentList : Argument
+ { $$ = $1; }
+ | Argument sySemi ArgumentList
+{
+ $$ = $1;
+ $$->argNext = $3;
+}
+ ;
+
+Argument : Direction syIdentifier ArgumentType IPCFlags
+{
+ $$ = argAlloc();
+ $$->argKind = $1;
+ $$->argName = $2;
+ $$->argType = $3;
+ $$->argFlags = $4;
+}
+ ;
+
+Direction : /* empty */ { $$ = akNone; }
+ | syIn { $$ = akIn; }
+ | syOut { $$ = akOut; }
+ | syInOut { $$ = akInOut; }
+ | syRequestPort { $$ = akRequestPort; }
+ | syReplyPort { $$ = akReplyPort; }
+ | sySReplyPort { $$ = akSReplyPort; }
+ | syUReplyPort { $$ = akUReplyPort; }
+ | syWaitTime { $$ = akWaitTime; }
+ | syMsgOption { $$ = akMsgOption; }
+ | syMsgSeqno { $$ = akMsgSeqno; }
+ ;
+
+ArgumentType : syColon syIdentifier
+{
+ $$ = itLookUp($2);
+ if ($$ == itNULL)
+ error("type '%s' not defined", $2);
+}
+ | syColon NamedTypeSpec
+ { $$ = $2; }
+ ;
+
+LookString : /* empty */
+ { LookString(); }
+ ;
+
+LookFileName : /* empty */
+ { LookFileName(); }
+ ;
+
+LookQString : /* empty */
+ { LookQString(); }
+ ;
+
+%%
+
+static const char *
+import_name(statement_kind_t sk)
+{
+ switch (sk)
+ {
+ case skImport:
+ return "Import";
+ case skSImport:
+ return "SImport";
+ case skUImport:
+ return "UImport";
+ default:
+ fatal("import_name(%d): not import statement", (int) sk);
+ /*NOTREACHED*/
+ }
+}
diff --git a/mig/routine.c b/mig/routine.c
new file mode 100644
index 0000000..70707bd
--- /dev/null
+++ b/mig/routine.c
@@ -0,0 +1,1334 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992,1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+ * 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 <stdlib.h>
+
+#include "error.h"
+#include "global.h"
+#include "routine.h"
+#include "message.h"
+
+u_int rtNumber = 0;
+
+routine_t *
+rtAlloc(void)
+{
+ register routine_t *new;
+
+ new = (routine_t *) calloc(1, sizeof *new);
+ if (new == rtNULL)
+ fatal("rtAlloc(): %s", unix_error_string(errno));
+ new->rtNumber = rtNumber++;
+ new->rtName = strNULL;
+ new->rtErrorName = strNULL;
+ new->rtUserName = strNULL;
+ new->rtServerName = strNULL;
+
+ return new;
+}
+
+void
+rtSkip(int n)
+{
+ rtNumber += n;
+}
+
+argument_t *
+argAlloc(void)
+{
+ static const argument_t prototype =
+ {
+ strNULL, /* identifier_t argName */
+ argNULL, /* argument_t *argNext */
+ akNone, /* arg_kind_t argKind */
+ itNULL, /* ipc_type_t *argType */
+ strNULL, /* string_t argVarName */
+ strNULL, /* string_t argMsgField */
+ strNULL, /* string_t argTTName */
+ strNULL, /* string_t argPadName */
+ flNone, /* ipc_flags_t argFlags */
+ d_NO, /* dealloc_t argDeallocate */
+ FALSE, /* boolean_t argLongForm */
+ FALSE, /* boolean_t argServerCopy */
+ FALSE, /* boolean_t argCountInOut */
+ rtNULL, /* routine_t *argRoutine */
+ argNULL, /* argument_t *argCount */
+ argNULL, /* argument_t *argCInOut */
+ argNULL, /* argument_t *argPoly */
+ argNULL, /* argument_t *argDealloc */
+ argNULL, /* argument_t *argSCopy */
+ argNULL, /* argument_t *argParent */
+ 1, /* int argMultiplier */
+ 0, /* int argRequestPos */
+ 0, /* int argReplyPos */
+ FALSE, /* boolean_t argByReferenceUser */
+ FALSE /* boolean_t argByReferenceServer */
+ };
+ register argument_t *new;
+
+ new = malloc(sizeof *new);
+ if (new == argNULL)
+ fatal("argAlloc(): %s", unix_error_string(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;
+}
+
+routine_t *
+rtMakeProcedure(identifier_t name, argument_t *args)
+{
+ register routine_t *rt = rtAlloc();
+
+ rt->rtName = name;
+ rt->rtKind = rkProcedure;
+ rt->rtArgs = args;
+
+ warn("Procedure %s: obsolete routine kind", name);
+
+ return rt;
+}
+
+routine_t *
+rtMakeSimpleProcedure(identifier_t name, argument_t *args)
+{
+ register routine_t *rt = rtAlloc();
+
+ rt->rtName = name;
+ rt->rtKind = rkSimpleProcedure;
+ rt->rtArgs = args;
+
+ warn("SimpleProcedure %s: obsolete routine kind", name);
+
+ return rt;
+}
+
+routine_t *
+rtMakeFunction(identifier_t name, argument_t *args, ipc_type_t *type)
+{
+ register routine_t *rt = rtAlloc();
+ register argument_t *ret = argAlloc();
+
+ ret->argName = name;
+ ret->argKind = akReturn;
+ ret->argType = type;
+ ret->argNext = args;
+
+ rt->rtName = name;
+ rt->rtKind = rkFunction;
+ rt->rtArgs = ret;
+
+ warn("Function %s: obsolete routine kind", name);
+
+ return rt;
+}
+
+const char *
+rtRoutineKindToStr(routine_kind_t rk)
+{
+ switch (rk)
+ {
+ case rkRoutine:
+ return "Routine";
+ case rkSimpleRoutine:
+ return "SimpleRoutine";
+ case rkProcedure:
+ return "Procedure";
+ case rkSimpleProcedure:
+ return "SimpleProcedure";
+ case rkFunction:
+ return "Function";
+ default:
+ fatal("rtRoutineKindToStr(%d): not a routine_kind_t", rk);
+ /*NOTREACHED*/
+ }
+}
+
+static void
+rtPrintArg(register const argument_t *arg)
+{
+ register const ipc_type_t *it = arg->argType;
+
+ if (!akCheck(arg->argKind, akbUserArg|akbServerArg) ||
+ (akIdent(arg->argKind) == akeCount) ||
+ (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 akeMsgOption:
+ printf("MsgOption");
+ break;
+ case akeMsgSeqno:
+ printf("MsgSeqno\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 != it->itDeallocate)
+ if (arg->argDeallocate == d_YES)
+ printf(", Dealloc");
+ else if (arg->argDeallocate == d_MAYBE)
+ printf(", Dealloc[]");
+ else
+ printf(", NotDealloc");
+
+ if (arg->argLongForm != it->itLongForm)
+ if (arg->argLongForm)
+ printf(", IsLong");
+ else
+ printf(", IsNotLong");
+
+ if (arg->argServerCopy)
+ printf(", ServerCopy");
+
+ if (arg->argCountInOut)
+ printf(", CountInOut");
+}
+
+void
+rtPrintRoutine(register const routine_t *rt)
+{
+ register const 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);
+
+ if (rt->rtKind == rkFunction)
+ printf("): %s\n", rt->rtReturn->argType->itName);
+ else
+ printf(")\n");
+
+ printf("\n");
+}
+
+/*
+ * Determines appropriate value of msg-simple for the message,
+ * and whether this value can vary at runtime. (If it can vary,
+ * then the simple value is optimistically returned as TRUE.)
+ * Uses itInName values, so useful when sending messages.
+ */
+
+static void
+rtCheckSimpleIn(const argument_t *args, u_int mask, boolean_t *fixed,
+ boolean_t *simple)
+{
+ register const argument_t *arg;
+ boolean_t MayBeComplex = FALSE;
+ boolean_t MustBeComplex = FALSE;
+
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (akCheck(arg->argKind, mask))
+ {
+ register const ipc_type_t *it = arg->argType;
+
+ if (it->itInName == MACH_MSG_TYPE_POLYMORPHIC)
+ MayBeComplex = TRUE;
+
+ if (it->itIndefinite)
+ MayBeComplex = TRUE;
+
+ if (MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
+ !it->itInLine)
+ MustBeComplex = TRUE;
+ }
+
+ *fixed = MustBeComplex || !MayBeComplex;
+ *simple = !MustBeComplex;
+}
+
+/*
+ * Determines appropriate value of msg-simple for the message,
+ * and whether this value can vary at runtime. (If it can vary,
+ * then the simple value is optimistically returned as TRUE.)
+ * Uses itOutName values, so useful when receiving messages
+ * (and sending reply messages in KernelServer interfaces).
+ */
+
+static void
+rtCheckSimpleOut(const argument_t *args, u_int mask, boolean_t *fixed,
+ boolean_t *simple)
+{
+ register const argument_t *arg;
+ boolean_t MayBeComplex = FALSE;
+ boolean_t MustBeComplex = FALSE;
+
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (akCheck(arg->argKind, mask))
+ {
+ register const ipc_type_t *it = arg->argType;
+
+ if (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
+ MayBeComplex = TRUE;
+
+ if (it->itIndefinite)
+ MayBeComplex = TRUE;
+
+ if (MACH_MSG_TYPE_PORT_ANY(it->itOutName) ||
+ !it->itInLine)
+ MustBeComplex = TRUE;
+ }
+
+ *fixed = MustBeComplex || !MayBeComplex;
+ *simple = !MustBeComplex;
+}
+
+static u_int
+rtFindSize(const argument_t *args, u_int mask)
+{
+ register const argument_t *arg;
+ u_int size = sizeof_mach_msg_header_t;
+
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (akCheck(arg->argKind, mask))
+ {
+ register ipc_type_t *it = arg->argType;
+
+ if (arg->argLongForm) {
+ /* might need proper alignment on 64bit archies */
+ size = (size + word_size-1) & ~(word_size-1);
+ size += sizeof_mach_msg_type_long_t;
+ } else {
+ register bs = (it->itSize / 8); /* in bytes */
+ size += (bs > sizeof_mach_msg_type_t) ? bs : sizeof_mach_msg_type_t;
+ }
+
+ size += it->itMinTypeSize;
+ }
+
+ return size;
+}
+
+boolean_t
+rtCheckMask(const argument_t *args, u_int mask)
+{
+ register const argument_t *arg;
+
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (akCheckAll(arg->argKind, mask))
+ return TRUE;
+ return FALSE;
+}
+
+boolean_t
+rtCheckMaskFunction(const argument_t *args, u_int mask,
+ boolean_t (*func)(const argument_t *))
+{
+ register const argument_t *arg;
+
+ for (arg = args; arg != argNULL; arg = arg->argNext)
+ if (akCheckAll(arg->argKind, mask))
+ if ((*func)(arg))
+ return TRUE;
+ return FALSE;
+}
+
+/* arg->argType may be NULL in this function */
+
+static void
+rtDefaultArgKind(const 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->argLongForm,
+ * arg->argServerCopy, arg->argCountInOut from arg->argFlags.
+ */
+
+static void
+rtProcessArgFlags(register argument_t *arg)
+{
+ register const ipc_type_t *it = arg->argType;
+
+ arg->argFlags = itCheckFlags(arg->argFlags, arg->argName);
+
+ if (((IsKernelServer && akCheck(arg->argKind, akbReturn)) ||
+ (IsKernelUser && akCheck(arg->argKind, akbSend))) &&
+ (arg->argFlags & flDealloc) &&
+ (it->itDeallocate == d_NO)) {
+ /*
+ * 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.
+ */
+
+ arg->argDeallocate = d_YES;
+ } else
+ arg->argDeallocate = itCheckDeallocate(it, arg->argFlags,
+ it->itDeallocate, arg->argName);
+
+ arg->argLongForm = itCheckIsLong(it, arg->argFlags,
+ it->itLongForm, arg->argName);
+
+ if (arg->argFlags & flServerCopy) {
+ if (it->itIndefinite && akCheck(arg->argKind, akbSend))
+ arg->argServerCopy = TRUE;
+ else
+ warn("%s: ServerCopy on argument is meaningless", arg->argName);
+ }
+
+ if (arg->argFlags & flCountInOut) {
+ if (it->itVarArray && it->itInLine &&
+ akCheck(arg->argKind, akbReply))
+ arg->argCountInOut = TRUE;
+ else
+ warn("%s: CountInOut on argument is meaningless", arg->argName);
+ }
+}
+
+static void
+rtAugmentArgKind(argument_t *arg)
+{
+ register ipc_type_t *it = arg->argType;
+
+ /* akbVariable means variable-sized inline. */
+
+ if (it->itVarArray && it->itInLine)
+ {
+ if (akCheckAll(arg->argKind, akbRequest|akbReply))
+ error("%s: Inline variable-sized arguments can't be InOut",
+ arg->argName);
+ arg->argKind = akAddFeature(arg->argKind, akbVariable);
+
+ /* akbIndefinite means inline or out-of-line */
+
+ if (it->itIndefinite)
+ arg->argKind = akAddFeature(arg->argKind, akbIndefinite);
+ }
+
+ /*
+ * Kernel servers can't do quick-checking of request arguments
+ * which are out-of-line or ports, because the deallocate bit isn't
+ * predictable. This is because the deallocate bit is preserved
+ * at message copyin time and normalized during message copyout.
+ * This accomodates old IPC programs which expect the deallocate
+ * bit to be preserved.
+ */
+
+ if (akCheck(arg->argKind, akbRequest) &&
+ !arg->argLongForm &&
+ (it->itOutName != MACH_MSG_TYPE_POLYMORPHIC) &&
+ !it->itVarArray &&
+ !(IsKernelServer && (!it->itInLine ||
+ MACH_MSG_TYPE_PORT_ANY(it->itOutName))))
+ arg->argKind = akAddFeature(arg->argKind, akbRequestQC);
+
+ if (akCheck(arg->argKind, akbReply) &&
+ !arg->argLongForm &&
+ (it->itOutName != MACH_MSG_TYPE_POLYMORPHIC) &&
+ !it->itVarArray)
+ arg->argKind = akAddFeature(arg->argKind, akbReplyQC);
+
+ /*
+ * 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 a count arg, getting returned. The count can't get
+ * stored directly into the msg-type, because the msg-type won't
+ * get initialized until later, and that would trash the count.
+ * 5) This is a poly arg, getting returned. The name can't get
+ * stored directly into the msg-type, because the msg-type won't
+ * get initialized until later, and that would trash the name.
+ * 6) This is a dealloc arg, being returned. The name can't be
+ * stored directly into the msg_type, because the msg-type
+ * field is a bit-field.
+ */
+
+ 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)) ||
+ ((akIdent(arg->argKind) == akeCount) &&
+ akCheck(arg->argKind, akbReturnSnd)) ||
+ ((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);
+ }
+
+ /*
+ * If the argument is a variable-length array that can be passed in-line
+ * or out-of-line, and is being returned, the server procedure
+ * is passed a pointer to the buffer, which it can change.
+ */
+ if (it->itIndefinite &&
+ akCheck(arg->argKind, akbReturnSnd))
+ {
+ arg->argKind = akAddFeature(arg->argKind, akbPointer);
+ }
+}
+
+/* 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 (akCheck (arg->argKind, akbUserArg))
+ {
+ if (rt->rtUReplyPort != argNULL)
+ warn("multiple UserReplyPort args in %s; %s won't be used",
+ rt->rtName, rt->rtUReplyPort->argName);
+ rt->rtUReplyPort = arg;
+ }
+ if (akCheck (arg->argKind, akbServerArg))
+ {
+ if (rt->rtSReplyPort != argNULL)
+ warn("multiple ServerReplyPort args in %s; %s won't be used",
+ rt->rtName, rt->rtSReplyPort->argName);
+ rt->rtSReplyPort = arg;
+ }
+ break;
+
+ case akeWaitTime:
+ if (rt->rtWaitTime != argNULL)
+ warn("multiple WaitTime 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;
+
+ case akeMsgSeqno:
+ if (rt->rtMsgSeqno != argNULL)
+ warn("multiple MsgSeqno args in %s; %s won't be used",
+ rt->rtName, rt->rtMsgSeqno->argName);
+ rt->rtMsgSeqno = arg;
+ break;
+
+ case akeReturn:
+ if (rt->rtReturn != argNULL)
+ warn("multiple Return args in %s; %s won't be used",
+ rt->rtName, rt->rtReturn->argName);
+ rt->rtReturn = 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 akeMsgSeqno:
+ arg->argMsgField = "Head.msgh_seqno";
+ break;
+ default:
+ arg->argMsgField = arg->argName;
+ break;
+ }
+ if (arg->argTTName == strNULL)
+ arg->argTTName = strconcat(arg->argName, "Type");
+ 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->rtUReplyPort != argNULL) &&
+ (rt->rtUReplyPort->argPoly == arg) &&
+ (arg->argType != itNULL)) {
+ arg->argMsgField = "Head.msgh_bits";
+ arg->argType->itInTrans = "MACH_MSGH_BITS_REPLY";
+ }
+ if ((rt->rtSReplyPort != argNULL) &&
+ (rt->rtSReplyPort->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;
+
+ count = argAlloc();
+ count->argName = strconcat(arg->argName, "Cnt");
+ count->argType = itMakeCountType();
+ count->argParent = arg;
+ count->argMultiplier = arg->argType->itElement->itNumber;
+ count->argNext = arg->argNext;
+ arg->argNext = count;
+ arg->argCount = count;
+
+ if (arg->argType->itString) {
+ /* C String gets no Count argument on either side.
+ There is no explicit field in the message -
+ the count is passed as part of the descriptor. */
+ count->argKind = akeCount;
+ count->argVarName = (char *)0;
+ } else
+ count->argKind = akAddFeature(akCount,
+ akCheck(arg->argKind, akbSendReturnBits));
+
+ if (arg->argLongForm)
+ count->argMsgField = strconcat(arg->argTTName,
+ ".msgtl_number");
+ else
+ count->argMsgField = strconcat(arg->argTTName, ".msgt_number");
+}
+
+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 const 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|akbSendBody;
+ akbreturn = akbReturn|akbReturnBody;
+
+ 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));
+
+ if (arg->argLongForm)
+ poly->argMsgField = strconcat(arg->argTTName,
+ ".msgtl_name");
+ else
+ poly->argMsgField = strconcat(arg->argTTName, ".msgt_name");
+}
+
+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;
+
+ /*
+ * For Indefinite types, we leave out akbSendSnd and akbReturnSnd
+ * so that the normal argument-packing is bypassed. The special code
+ * generated for the Indefinite argument handles the deallocate bit.
+ * (It can only be enabled if the data is actually out-of-line.)
+ */
+
+ dealloc->argKind = akeDealloc;
+ if (akCheck(arg->argKind, akbSend))
+ dealloc->argKind = akAddFeature(dealloc->argKind,
+ akCheck(arg->argKind,
+ akbUserArg|akbSend|akbSendBody|
+ (arg->argType->itIndefinite ? 0 : akbSendSnd)));
+ if (akCheck(arg->argKind, akbReturn)) {
+ dealloc->argKind = akAddFeature(dealloc->argKind,
+ akCheck(arg->argKind,
+ akbServerArg|akbReturn|akbReturnBody|
+ (arg->argType->itIndefinite ? 0 : akbReturnSnd)));
+
+ /*
+ * Without akbReturnSnd, rtAugmentArgKind will not add
+ * akbVarNeeded and rtAddByReference will not set
+ * argByReferenceServer. So we do it here.
+ */
+
+ if (arg->argType->itIndefinite) {
+ dealloc->argKind = akAddFeature(dealloc->argKind, akbVarNeeded);
+ dealloc->argByReferenceServer = TRUE;
+ }
+ }
+
+ if (arg->argLongForm)
+ dealloc->argMsgField = strconcat(arg->argTTName,
+ ".msgtl_header.msgt_deallocate");
+ else
+ dealloc->argMsgField = strconcat(arg->argTTName, ".msgt_deallocate");
+
+}
+
+static void
+rtAddSCopyArg(register argument_t *arg)
+{
+ register argument_t *scopy;
+
+ scopy = argAlloc();
+ scopy->argName = strconcat(arg->argName, "SCopy");
+ scopy->argType = itMakeDeallocType();
+ scopy->argParent = arg;
+ scopy->argNext = arg->argNext;
+ arg->argNext = scopy;
+ arg->argSCopy = scopy;
+
+ scopy->argKind = akServerCopy;
+
+ if (arg->argLongForm)
+ scopy->argMsgField = strconcat(arg->argTTName,
+ ".msgtl_header.msgt_inline");
+ else
+ scopy->argMsgField = strconcat(arg->argTTName, ".msgt_inline");
+}
+
+static void
+rtCheckRoutineArgs(routine_t *rt)
+{
+ register argument_t *arg;
+
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
+ {
+ register const 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)
+ {
+ /* need to set argLongForm before adding implicit args */
+ rtProcessArgFlags(arg);
+ rtAugmentArgKind(arg);
+
+ /* args added here will get processed in later iterations */
+ /* order of args is 'arg poly countinout count dealloc scopy' */
+
+ if (arg->argServerCopy)
+ rtAddSCopyArg(arg);
+ if (arg->argDeallocate == d_MAYBE)
+ rtAddDeallocArg(arg);
+ if (it->itVarArray)
+ rtAddCountArg(arg);
+ if (arg->argCountInOut)
+ rtAddCountInOutArg(arg);
+ if ((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) ||
+ (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC))
+ rtAddPolyArg(arg);
+ }
+ }
+}
+
+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->rtKind == rkFunction) &&
+ (rt->rtReturn == argNULL))
+ error("Function %s doesn't have a return arg", rt->rtName);
+
+ if ((rt->rtKind != rkFunction) &&
+ (rt->rtReturn != argNULL))
+ error("non-function %s has a return arg", rt->rtName);
+
+ if ((rt->rtReturn == argNULL) && !rt->rtProcedure)
+ rt->rtReturn = rt->rtRetCode;
+
+ rt->rtServerReturn = rt->rtReturn;
+
+ if ((rt->rtReturn != argNULL) &&
+ (rt->rtReturn->argType != itNULL))
+ itCheckReturnType(rt->rtReturn->argName,
+ rt->rtReturn->argType);
+
+ if ((rt->rtRequestPort != argNULL) &&
+ (rt->rtRequestPort->argType != itNULL))
+ itCheckRequestPortType(rt->rtRequestPort->argName,
+ rt->rtRequestPort->argType);
+
+ if ((rt->rtUReplyPort != argNULL) &&
+ (rt->rtUReplyPort->argType != itNULL))
+ itCheckReplyPortType(rt->rtUReplyPort->argName,
+ rt->rtUReplyPort->argType);
+ if ((rt->rtSReplyPort != argNULL) &&
+ (rt->rtSReplyPort->argType != itNULL))
+ itCheckReplyPortType(rt->rtSReplyPort->argName,
+ rt->rtSReplyPort->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 ((rt->rtMsgSeqno != argNULL) &&
+ (rt->rtMsgSeqno->argType != itNULL))
+ itCheckNaturalType(rt->rtMsgSeqno->argName,
+ rt->rtMsgSeqno->argType);
+}
+
+/*
+ * 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(const routine_t *rt)
+{
+ register const 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)
+ {
+ register const 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. Even if there is no reply
+ * message (rtOneWay is true), we generate the argument because
+ * the server-side stub needs a dummy reply msg to return error codes
+ * back to the server loop.
+ */
+
+static void
+rtAddRetCode(routine_t *rt)
+{
+ register argument_t *arg = argAlloc();
+
+ arg->argName = "RetCode";
+ arg->argType = itRetCodeType;
+ arg->argKind = akRetCode;
+ rt->rtRetCode = arg;
+
+ /* add at beginning, so return-code is first in the reply message */
+ arg->argNext = rt->rtArgs;
+ rt->rtArgs = arg;
+}
+
+/*
+ * 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)
+{
+ register argument_t *arg = argAlloc();
+ argument_t **loc;
+
+ arg->argName = "dummy WaitTime arg";
+ arg->argVarName = name;
+ arg->argType = itWaitTimeType;
+ arg->argKind = akeWaitTime;
+ 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 */
+
+ if (rt->rtMsgSeqno != argNULL)
+ loc = &rt->rtMsgSeqno->argNext;
+ else
+ loc = &rt->rtArgs;
+
+ arg->argNext = *loc;
+ *loc = arg;
+
+ rtSetArgDefaults(rt, arg);
+}
+
+/*
+ * Adds a dummy reply port argument to the function. If USER is true, the
+ * user reply port is set, otherwise the server.
+ */
+
+static void
+rtAddDummyReplyPort(routine_t *rt, ipc_type_t *type, int user)
+{
+ register argument_t *arg = argAlloc();
+ argument_t **loc;
+
+ arg->argName = "dummy ReplyPort arg";
+ arg->argVarName = "dummy ReplyPort arg";
+ arg->argType = type;
+ arg->argKind = akeReplyPort;
+ if (user)
+ rt->rtUReplyPort = arg;
+ else
+ rt->rtSReplyPort = 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);
+}
+
+/*
+ * 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;
+
+ if (parent == argNULL) {
+ if (akCheck(arg->argKind, akbRequest|akbSend)) {
+ arg->argRequestPos = NumRequestVar;
+ MaxRequestPos = NumRequestVar;
+ if (akCheck(arg->argKind, akbVariable))
+ NumRequestVar++;
+ } else
+ arg->argRequestPos = -1;
+
+ if (akCheck(arg->argKind, akbReply|akbReturn)) {
+ arg->argReplyPos = NumReplyVar;
+ MaxReplyPos = NumReplyVar;
+ if (akCheck(arg->argKind, akbVariable))
+ NumReplyVar++;
+ } else
+ arg->argReplyPos = -1;
+ } else {
+ arg->argRequestPos = parent->argRequestPos;
+ arg->argReplyPos = parent->argReplyPos;
+ }
+
+ /* Out variables that follow a variable-sized field
+ need VarNeeded or ReplyCopy; they can't be stored
+ directly into the reply message. */
+
+ if (akCheck(arg->argKind, akbReturnSnd) &&
+ !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 const ipc_type_t *it = arg->argType;
+
+ if(akCheck(arg->argKind, akbSendRcv) &&
+ !akCheck(arg->argKind, akbReturnSnd)) {
+ if ((it->itDestructor != strNULL) ||
+ (akCheck(arg->argKind, akbIndefinite) && !arg->argServerCopy))
+ 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 const ipc_type_t *it = arg->argType;
+
+ if (akCheck(arg->argKind, akbReturnRcv) &&
+ (it->itStruct || it->itIndefinite)) {
+ 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) &&
+ (it->itStruct || it->itIndefinite))
+ arg->argByReferenceServer = TRUE;
+ }
+}
+
+void
+rtCheckRoutine(register routine_t *rt)
+{
+ /* Initialize random fields. */
+
+ rt->rtErrorName = ErrorProc;
+ rt->rtOneWay = ((rt->rtKind == rkSimpleProcedure) ||
+ (rt->rtKind == rkSimpleRoutine));
+ rt->rtProcedure = ((rt->rtKind == rkProcedure) ||
+ (rt->rtKind == rkSimpleProcedure));
+ rt->rtUseError = rt->rtProcedure || (rt->rtKind == rkFunction);
+ rt->rtServerName = strconcat(ServerPrefix, rt->rtName);
+ rt->rtServerName = strconcat(RoutinePrefix, rt->rtServerName);
+ rt->rtUserName = strconcat(UserPrefix, rt->rtName);
+ rt->rtUserName = strconcat(RoutinePrefix, rt->rtUserName);
+
+ /* Add implicit arguments. */
+
+ rtAddRetCode(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->rtUReplyPort == argNULL)
+ if (rt->rtOneWay)
+ rtAddDummyReplyPort(rt, itZeroReplyPortType, 1);
+ else
+ rtAddDummyReplyPort(rt, itRealReplyPortType, 1);
+ if (rt->rtSReplyPort == argNULL)
+ if (rt->rtOneWay)
+ rtAddDummyReplyPort(rt, itZeroReplyPortType, 0);
+ else
+ rtAddDummyReplyPort(rt, itRealReplyPortType, 0);
+
+ if (rt->rtMsgOption == argNULL)
+ if (MsgOption == strNULL)
+ rtAddMsgOption(rt, "MACH_MSG_OPTION_NONE");
+ else
+ rtAddMsgOption(rt, MsgOption);
+
+ if ((rt->rtWaitTime == argNULL) &&
+ (WaitTime != strNULL))
+ rtAddWaitTime(rt, WaitTime);
+
+ /* Now that all the arguments are in place, do more checking. */
+
+ rtCheckArgTypes(rt);
+ rtCheckArgTrans(rt);
+
+ if (rt->rtOneWay && rtCheckMask(rt->rtArgs, akbReturn))
+ 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)
+ return;
+
+ rtCheckSimpleIn(rt->rtArgs, akbRequest,
+ &rt->rtSimpleFixedRequest,
+ &rt->rtSimpleSendRequest);
+ rtCheckSimpleOut(rt->rtArgs, akbRequest,
+ &rt->rtSimpleCheckRequest,
+ &rt->rtSimpleReceiveRequest);
+ rt->rtRequestSize = rtFindSize(rt->rtArgs, akbRequest);
+
+ if (IsKernelServer)
+ rtCheckSimpleOut(rt->rtArgs, akbReply,
+ &rt->rtSimpleFixedReply,
+ &rt->rtSimpleSendReply);
+ else
+ rtCheckSimpleIn(rt->rtArgs, akbReply,
+ &rt->rtSimpleFixedReply,
+ &rt->rtSimpleSendReply);
+ rtCheckSimpleOut(rt->rtArgs, akbReply,
+ &rt->rtSimpleCheckReply,
+ &rt->rtSimpleReceiveReply);
+ rt->rtReplySize = rtFindSize(rt->rtArgs, akbReply);
+
+ rtCheckVariable(rt);
+ rtCheckDestroy(rt);
+ rtAddByReference(rt);
+
+ if (rt->rtKind == rkFunction)
+ rt->rtNoReplyArgs = FALSE;
+ else
+ rt->rtNoReplyArgs = !rtCheckMask(rt->rtArgs, akbReturnSnd);
+}
diff --git a/mig/routine.h b/mig/routine.h
new file mode 100644
index 0000000..f80a174
--- /dev/null
+++ b/mig/routine.h
@@ -0,0 +1,401 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#ifndef _ROUTINE_H
+#define _ROUTINE_H
+
+#include <sys/types.h>
+
+#include "boolean.h"
+#include "type.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/rtReturn */
+#define akeReturn (8) /* pointed at by rtReturn */
+#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 akeServerCopy (12) /* a server-copy arg for argParent */
+#define akeCountInOut (13) /* a count-in-out arg */
+
+#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 akbReplyInit (0x00040000) /* reply msg-type must be init'ed */
+#define akbRequestQC (0x00080000) /* msg_type can be checked quickly */
+#define akbReplyQC (0x00100000) /* msg_type can be checked quickly */
+#define akbReplyCopy (0x00200000) /* copy reply value from request */
+#define akbVarNeeded (0x00400000) /* may need local var in server */
+#define akbDestroy (0x00800000) /* call destructor function */
+#define akbVariable (0x01000000) /* variable size inline data */
+#define akbIndefinite (0x02000000) /* variable size, inline or out */
+#define akbPointer (0x04000000) /* server gets a pointer to the
+ real buffer */
+/* 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 (with akbReplyInit, akbRequestQC, akbReplyQC)
+ * 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.
+ * 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 argument's msg_type field in the reply msg.
+ * Some special arguments (RetCode, Dummy, Tid) have their msg_type
+ * fields in the reply message initialized by the server demux
+ * function; these arguments have akbReply but not akbReplyInit.
+ *
+ * akbRequestQC implies akbRequest. If it's on, then the
+ * mach_msg_type_t value in the request message can be checked quickly
+ * (by casting to an int and checking with a single comparison).
+ * akbReplyQC has the analogous meaning with respect to akbReply.
+ *
+ * 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.
+ *
+ * Header file generation (header.c) uses:
+ * akbUserArg
+ *
+ * User stub generation (user.c) uses:
+ * akbUserArg, akbRequest, akbReply, akbSendSnd,
+ * akbSendBody, akbReturnRcv, akbReplyQC
+ *
+ * Server stub generation (server.c) uses:
+ * akbServerArg, akbRequest, akbReply, akbSendRcv, akbReturnSnd,
+ * akbReplyInit, akbReplyCopy, akbVarNeeded, akbSendBody, akbRequestQC
+ *
+ *
+ * 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|akbReplyInit)
+
+#define akInOut akAddFeature(akeNormal, \
+ akbUserArg|akbServerArg|akbRequest|akbReply| \
+ akbSendBits|akbReturnBits|akbReplyInit|akbReplyCopy)
+
+#define akRequestPort akAddFeature(akeRequestPort, \
+ akbUserArg|akbServerArg|akbSend|akbSendSnd|akbSendRcv)
+
+#define akWaitTime akAddFeature(akeWaitTime, akbUserArg)
+
+#define akMsgOption akAddFeature(akeMsgOption, akbUserArg)
+
+#define akMsgSeqno akAddFeature(akeMsgSeqno, \
+ akbServerArg|akbSend|akbSendRcv)
+
+#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)
+
+#define akReturn akAddFeature(akeReturn, \
+ akbReply|akbReplyInit)
+
+#define akCount akAddFeature(akeCount, \
+ akbUserArg|akbServerArg)
+
+#define akPoly akePoly
+
+#define akDealloc akAddFeature(akeDealloc, akbUserArg)
+
+#define akServerCopy akAddFeature(akeServerCopy, akbServerArg|akbSendRcv)
+
+#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)
+
+/*
+ * 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 and longform bits
+ * in the argument's type. rtProcessArgFlags sets argDeallocate and
+ * argLongForm 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;
+
+ const_string_t argVarName; /* local variable and argument names */
+ const_string_t argMsgField; /* message field's name */
+ const_string_t argTTName; /* name for msg_type fields, static vars */
+ const_string_t argPadName; /* name for pad field in msg */
+
+ ipc_flags_t argFlags;
+ dealloc_t argDeallocate; /* overrides argType->itDeallocate */
+ boolean_t argLongForm; /* overrides argType->itLongForm */
+ boolean_t argServerCopy;
+ boolean_t argCountInOut;
+
+ struct routine *argRoutine; /* routine we are part of */
+
+ struct argument *argCount; /* our count arg, if present */
+ 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 *argSCopy; /* our serverCopy arg, if present */
+ struct argument *argParent; /* in a count or poly arg, the base arg */
+ 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 */
+ int argRequestPos;
+ int argReplyPos;
+ /* whether argument is by reference, on user and server side */
+ boolean_t argByReferenceUser;
+ boolean_t argByReferenceServer;
+} argument_t;
+
+/*
+ * The various routine kinds' peculiarities are abstracted by rtCheckRoutine
+ * into attributes like rtOneWay, rtProcedure, etc. These are what
+ * code generation should use. It is Bad Form for code generation to
+ * test rtKind.
+ */
+
+typedef enum
+{
+ rkRoutine,
+ rkSimpleRoutine,
+ rkSimpleProcedure,
+ rkProcedure,
+ rkFunction,
+} 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) */
+
+ /* rtErrorName is only used for Procs, SimpleProcs, & Functions */
+ identifier_t rtErrorName; /* error-handler name */
+
+ boolean_t rtOneWay; /* SimpleProcedure or SimpleRoutine */
+ boolean_t rtProcedure; /* Procedure or SimpleProcedure */
+ boolean_t rtUseError; /* Procedure or Function */
+
+ boolean_t rtSimpleFixedRequest; /* fixed msg-simple value in request */
+ boolean_t rtSimpleSendRequest; /* in any case, initial value */
+ boolean_t rtSimpleCheckRequest; /* check msg-simple in request */
+ boolean_t rtSimpleReceiveRequest; /* if so, the expected value */
+
+ boolean_t rtSimpleFixedReply; /* fixed msg-simple value in reply */
+ boolean_t rtSimpleSendReply; /* in any case, initial value */
+ boolean_t rtSimpleCheckReply; /* check msg-simple in reply */
+ boolean_t rtSimpleReceiveReply; /* if so, the expected value */
+
+ u_int rtRequestSize; /* minimal size of a legal request msg */
+ u_int rtReplySize; /* minimal size of a legal reply msg */
+
+ int rtNumRequestVar; /* number of variable/inline args in request */
+ int rtNumReplyVar; /* number of variable/inline args in reply */
+
+ int rtMaxRequestPos; /* maximum of argRequestPos */
+ int rtMaxReplyPos; /* maximum of argReplyPos */
+
+ boolean_t rtNoReplyArgs; /* if so, no reply message arguments beyond
+ what the server dispatch routine inserts */
+
+ /* distinguished arguments */
+ argument_t *rtRequestPort; /* always non-NULL, defaults to first arg */
+ argument_t *rtUReplyPort; /* always non-NULL, defaults to Mig-supplied */
+ argument_t *rtSReplyPort; /* always non-NULL, defaults to Mig-supplied */
+ argument_t *rtReturn; /* non-NULL unless rtProcedure */
+ argument_t *rtServerReturn; /* NULL or rtReturn */
+ argument_t *rtRetCode; /* always non-NULL */
+ argument_t *rtWaitTime; /* if non-NULL, will use MACH_RCV_TIMEOUT */
+ argument_t *rtMsgOption; /* always non-NULL, defaults to NONE */
+ argument_t *rtMsgSeqno; /* if non-NULL, server gets passed seqno */
+} routine_t;
+
+#define rtNULL ((routine_t *) 0)
+#define argNULL ((argument_t *) 0)
+
+extern u_int rtNumber;
+/* rt->rtNumber will be initialized */
+extern routine_t *rtAlloc(void);
+/* skip a number */
+extern void rtSkip(int);
+
+extern argument_t *argAlloc(void);
+
+extern boolean_t rtCheckMask(const argument_t *args, u_int mask);
+
+extern boolean_t rtCheckMaskFunction(const argument_t *args, u_int mask,
+ boolean_t (*func)(const argument_t *arg));
+
+extern routine_t *rtMakeRoutine(identifier_t name, argument_t *args);
+extern routine_t *rtMakeSimpleRoutine(identifier_t name, argument_t *args);
+extern routine_t *rtMakeProcedure(identifier_t name, argument_t *args);
+extern routine_t *rtMakeSimpleProcedure(identifier_t name, argument_t *args);
+extern routine_t *rtMakeFunction(identifier_t name, argument_t *args,
+ ipc_type_t *type);
+
+extern void rtPrintRoutine(const routine_t *rt);
+extern void rtCheckRoutine(routine_t *rt);
+
+extern const char *rtRoutineKindToStr(routine_kind_t rk);
+
+#endif /* _ROUTINE_H */
diff --git a/mig/server.c b/mig/server.c
new file mode 100644
index 0000000..07e4964
--- /dev/null
+++ b/mig/server.c
@@ -0,0 +1,1322 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <assert.h>
+
+#include "write.h"
+#include "utils.h"
+#include "global.h"
+#include "error.h"
+#include "cpu.h"
+
+static void
+WriteIncludes(FILE *file)
+{
+ fprintf(file, "#define EXPORT_BOOLEAN\n");
+ fprintf(file, "#include <mach/boolean.h>\n");
+ fprintf(file, "#include <mach/kern_return.h>\n");
+ fprintf(file, "#include <mach/message.h>\n");
+ fprintf(file, "#include <mach/mig_errors.h>\n");
+ fprintf(file, "#include <mach/mig_support.h>\n");
+ if (IsKernelServer)
+ fprintf(file, "#include <ipc/ipc_port.h>\n");
+ fprintf(file, "\n");
+}
+
+static void
+WriteGlobalDecls(FILE *file)
+{
+ if (RCSId != strNULL)
+ 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, "#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");
+ }
+ else
+ {
+ 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");
+ }
+ fprintf(file, "\n");
+}
+
+static void
+WriteProlog(FILE *file)
+{
+ fprintf(file, "/* Module %s */\n", SubsystemName);
+ fprintf(file, "\n");
+
+ WriteIncludes(file);
+ WriteBogusDefines(file);
+ WriteGlobalDecls(file);
+}
+
+
+static void
+WriteSymTabEntries(FILE *file, const statement_t *stats)
+{
+ register const statement_t *stat;
+ register u_int current = 0;
+
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ if (stat->stKind == skRoutine) {
+ register 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
+WriteArrayEntries(FILE *file, const statement_t *stats)
+{
+ register u_int current = 0;
+ register const statement_t *stat;
+
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ if (stat->stKind == skRoutine)
+ {
+ register const routine_t *rt = stat->stRoutine;
+
+ while (current++ < rt->rtNumber)
+ fprintf(file, "\t\t0,\n");
+ fprintf(file, "\t\t_X%s,\n", rt->rtName);
+ }
+ while (current++ < rtNumber)
+ fprintf(file, "\t\t\t0,\n");
+}
+
+static void
+WriteEpilog(FILE *file, const statement_t *stats)
+{
+ fprintf(file, "\n");
+
+ /*
+ * First, the symbol table
+ */
+ fprintf(file, "static mig_routine_t %s_routines[] = {\n", ServerDemux);
+
+ WriteArrayEntries(file, stats);
+
+ fprintf(file, "};\n");
+ fprintf(file, "\n");
+
+ /*
+ * Then, the server routine
+ */
+ fprintf(file, "mig_external boolean_t %s\n", ServerDemux);
+ fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
+
+ fprintf(file, "{\n");
+ fprintf(file, "\tregister mach_msg_header_t *InP = InHeadP;\n");
+
+ fprintf(file, "\tregister mig_reply_header_t *OutP = (mig_reply_header_t *) OutHeadP;\n");
+
+ fprintf(file, "\n");
+
+ WriteStaticDecl(file, itRetCodeType,
+ itRetCodeType->itDeallocate, itRetCodeType->itLongForm,
+ !IsKernelServer, "RetCodeType");
+ fprintf(file, "\n");
+
+ fprintf(file, "\tregister mig_routine_t routine;\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "\tOutP->Head.msgh_bits = ");
+ fprintf(file, "MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InP->msgh_bits), 0);\n");
+ fprintf(file, "\tOutP->Head.msgh_size = sizeof *OutP;\n");
+ fprintf(file, "\tOutP->Head.msgh_remote_port = InP->msgh_reply_port;\n");
+ fprintf(file, "\tOutP->Head.msgh_local_port = MACH_PORT_NULL;\n");
+ fprintf(file, "\tOutP->Head.msgh_seqno = 0;\n");
+ fprintf(file, "\tOutP->Head.msgh_id = InP->msgh_id + 100;\n");
+ fprintf(file, "\n");
+ WritePackMsgType(file, itRetCodeType,
+ itRetCodeType->itDeallocate, itRetCodeType->itLongForm,
+ !IsKernelServer, "OutP->RetCodeType", "RetCodeType");
+ fprintf(file, "\n");
+
+ fprintf(file, "\tif ((InP->msgh_id > %d) || (InP->msgh_id < %d) ||\n",
+ SubsystemBase + rtNumber - 1, SubsystemBase);
+ fprintf(file, "\t ((routine = %s_routines[InP->msgh_id - %d]) == 0)) {\n",
+ ServerDemux, SubsystemBase);
+ fprintf(file, "\t\tOutP->RetCode = MIG_BAD_ID;\n");
+ fprintf(file, "\t\treturn FALSE;\n");
+ fprintf(file, "\t}\n");
+
+ /* Call appropriate routine */
+ fprintf(file, "\t(*routine) (InP, &OutP->Head);\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);
+ fprintf(file, "\t(const mach_msg_header_t *InHeadP)\n");
+
+ 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_routines[msgh_id];\n", ServerDemux);
+ fprintf(file, "}\n");
+ 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()".
+ */
+static const char *
+ServerSideType(const routine_t *rt)
+{
+ if (rt->rtServerReturn == argNULL)
+ return "void";
+ else
+ return rt->rtServerReturn->argType->itTransType;
+}
+
+static void
+WriteLocalVarDecl(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *it = arg->argType;
+
+ if (it->itInLine && it->itVarArray)
+ {
+ register const ipc_type_t *btype = it->itElement;
+
+ fprintf(file, "\t%s %s[%d]", btype->itTransType,
+ arg->argVarName, it->itNumber/btype->itNumber);
+ }
+ else
+ fprintf(file, "\t%s %s", it->itTransType, arg->argVarName);
+}
+
+static void
+WriteLocalPtrDecl(FILE *file, register const argument_t *arg)
+{
+ fprintf(file, "\t%s *%sP",
+ FetchServerType(arg->argType->itElement),
+ arg->argVarName);
+}
+
+static void
+WriteServerArgDecl(FILE *file, const argument_t *arg)
+{
+ fprintf(file, "%s %s%s",
+ arg->argType->itTransType,
+ arg->argByReferenceServer ? "*" : "",
+ arg->argVarName);
+}
+
+/*
+ * Writes the local variable declarations which are always
+ * present: InP, OutP, the server-side work function.
+ */
+static void
+WriteVarDecls(FILE *file, const routine_t *rt)
+{
+ int i;
+ boolean_t NeedMsghSize = FALSE;
+ boolean_t NeedMsghSizeDelta = FALSE;
+
+ fprintf(file, "\tregister Request *In0P = (Request *) InHeadP;\n");
+ for (i = 1; i <= rt->rtMaxRequestPos; i++)
+ fprintf(file, "\tregister Request *In%dP;\n", i);
+ fprintf(file, "\tregister Reply *OutP = (Reply *) OutHeadP;\n");
+
+ fprintf(file, "\tmig_external %s %s\n",
+ ServerSideType(rt), rt->rtServerName);
+ fprintf(file, "\t\t(");
+ WriteList(file, rt->rtArgs, WriteServerArgDecl, akbServerArg, ", ", "");
+ fprintf(file, ");\n");
+ fprintf(file, "\n");
+
+ if (!rt->rtSimpleFixedReply)
+ fprintf(file, "\tboolean_t msgh_simple;\n");
+ else if (!rt->rtSimpleCheckRequest)
+ {
+ fprintf(file, "#if\tTypeCheck\n");
+ fprintf(file, "\tboolean_t msgh_simple;\n");
+ fprintf(file, "#endif\t/* TypeCheck */\n");
+ fprintf(file, "\n");
+ }
+
+ /* if either request or reply is variable, we may need
+ msgh_size_delta and msgh_size */
+
+ if (rt->rtNumRequestVar > 0)
+ NeedMsghSize = TRUE;
+ if (rt->rtMaxRequestPos > 0)
+ NeedMsghSizeDelta = TRUE;
+
+ if (rt->rtNumReplyVar > 1)
+ NeedMsghSize = TRUE;
+ if (rt->rtMaxReplyPos > 0)
+ NeedMsghSizeDelta = TRUE;
+
+ if (NeedMsghSize)
+ fprintf(file, "\tunsigned int msgh_size;\n");
+ if (NeedMsghSizeDelta)
+ fprintf(file, "\tunsigned int msgh_size_delta;\n");
+
+ if (NeedMsghSize || NeedMsghSizeDelta)
+ fprintf(file, "\n");
+}
+
+static void
+WriteMsgError(FILE *file, const char *error_msg)
+{
+ fprintf(file, "\t\t{ OutP->RetCode = %s; return; }\n", error_msg);
+}
+
+static void
+WriteReplyInit(FILE *file, const routine_t *rt)
+{
+ boolean_t printed_nl = FALSE;
+
+ if (rt->rtSimpleFixedReply)
+ {
+ if (!rt->rtSimpleSendReply) /* complex reply message */
+ {
+ printed_nl = TRUE;
+ fprintf(file, "\n");
+ fprintf(file,
+ "\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n");
+ }
+ }
+ else
+ {
+ printed_nl = TRUE;
+ fprintf(file, "\n");
+ fprintf(file, "\tmsgh_simple = %s;\n",
+ strbool(rt->rtSimpleSendReply));
+ }
+
+ if (rt->rtNumReplyVar == 0)
+ {
+ if (!printed_nl)
+ fprintf(file, "\n");
+ fprintf(file, "\tOutP->Head.msgh_size = %d;\n", rt->rtReplySize);
+ }
+}
+
+static void
+WriteReplyHead(FILE *file, const routine_t *rt)
+{
+ if ((!rt->rtSimpleFixedReply) ||
+ (rt->rtNumReplyVar > 1))
+ {
+ fprintf(file, "\n");
+ if (rt->rtMaxReplyPos > 0)
+ fprintf(file, "\tOutP = (Reply *) OutHeadP;\n");
+ }
+
+ if (!rt->rtSimpleFixedReply)
+ {
+ fprintf(file, "\tif (!msgh_simple)\n");
+ fprintf(file,
+ "\t\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n");
+ }
+ if (rt->rtNumReplyVar > 1)
+ fprintf(file, "\tOutP->Head.msgh_size = msgh_size;\n");
+}
+
+static void
+WriteCheckHead(FILE *file, const routine_t *rt)
+{
+ fprintf(file, "#if\tTypeCheck\n");
+ if (rt->rtNumRequestVar > 0)
+ fprintf(file, "\tmsgh_size = In0P->Head.msgh_size;\n");
+ if (!rt->rtSimpleCheckRequest)
+ fprintf(file, "\tmsgh_simple = !(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);\n");
+
+ if (rt->rtNumRequestVar > 0)
+ fprintf(file, "\tif ((msgh_size < %d)",
+ rt->rtRequestSize);
+ else
+ fprintf(file, "\tif ((In0P->Head.msgh_size != %d)",
+ rt->rtRequestSize);
+
+ if (rt->rtSimpleCheckRequest)
+ fprintf(file, " ||\n\t %s(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)",
+ rt->rtSimpleReceiveRequest ? "" : "!");
+ fprintf(file, ")\n");
+ WriteMsgError(file, "MIG_BAD_ARGUMENTS");
+ fprintf(file, "#endif\t/* TypeCheck */\n");
+ fprintf(file, "\n");
+}
+
+static void
+WriteTypeCheck(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *it = arg->argType;
+ register const routine_t *rt = arg->argRoutine;
+
+ fprintf(file, "#if\tTypeCheck\n");
+ if (akCheck(arg->argKind, akbRequestQC))
+ fprintf(file, "\tif (* (int *) &In%dP->%s != * (int *) &%sCheck)\n",
+ arg->argRequestPos, arg->argTTName, arg->argVarName);
+ else
+ {
+ fprintf(file, "\tif (");
+ if (!it->itIndefinite) {
+ fprintf(file, "(In%dP->%s%s.msgt_inline != %s) ||\n\t ",
+ arg->argRequestPos, arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "",
+ strbool(it->itInLine));
+ }
+ fprintf(file, "(In%dP->%s%s.msgt_longform != %s) ||\n",
+ arg->argRequestPos, arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "",
+ strbool(arg->argLongForm));
+ if (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
+ {
+ if (!rt->rtSimpleCheckRequest)
+ fprintf(file, "\t (MACH_MSG_TYPE_PORT_ANY(In%dP->%s.msgt%s_name) && msgh_simple) ||\n",
+ arg->argRequestPos, arg->argTTName,
+ arg->argLongForm ? "l" : "");
+ }
+ else
+ fprintf(file, "\t (In%dP->%s.msgt%s_name != %s) ||\n",
+ arg->argRequestPos, arg->argTTName,
+ arg->argLongForm ? "l" : "",
+ it->itOutNameStr);
+ if (!it->itVarArray)
+ fprintf(file, "\t (In%dP->%s.msgt%s_number != %d) ||\n",
+ arg->argRequestPos, arg->argTTName,
+ arg->argLongForm ? "l" : "",
+ it->itNumber);
+ fprintf(file, "\t (In%dP->%s.msgt%s_size != %d))\n",
+ arg->argRequestPos, arg->argTTName,
+ arg->argLongForm ? "l" : "",
+ it->itSize);
+ }
+ WriteMsgError(file, "MIG_BAD_ARGUMENTS");
+ fprintf(file, "#endif\t/* TypeCheck */\n");
+ fprintf(file, "\n");
+}
+
+static void
+WriteCheckArgSize(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *ptype = arg->argType;
+ register const ipc_type_t *btype = ptype->itElement;
+ const argument_t *count = arg->argCount;
+ int multiplier = btype->itTypeSize / btype->itNumber;
+
+ if (ptype->itIndefinite) {
+ /*
+ * Check descriptor. If out-of-line, use standard size.
+ */
+ fprintf(file, "(In%dP->%s%s.msgt_inline) ? ",
+ arg->argRequestPos,
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "");
+ }
+
+ if (btype->itTypeSize % 4 != 0)
+ fprintf(file, "(");
+
+ if (multiplier > 1)
+ fprintf(file, "%d * ", multiplier);
+
+ fprintf(file, "In%dP->%s", arg->argRequestPos, count->argMsgField);
+
+ /* If the base type size of the data field isn`t a multiple of 4,
+ we have to round up. */
+ if (btype->itTypeSize % 4 != 0)
+ fprintf(file, " + 3) & ~3");
+
+ if (ptype->itIndefinite) {
+ fprintf(file, " : sizeof(%s *)", FetchServerType(btype));
+ }
+}
+
+static void
+WriteCheckMsgSize(FILE *file, register const argument_t *arg)
+{
+ register const routine_t *rt = arg->argRoutine;
+
+ /* If there aren't any more In args after this, then
+ we can use the msgh_size_delta value directly in
+ the TypeCheck conditional. */
+
+ if (arg->argRequestPos == rt->rtMaxRequestPos)
+ {
+ fprintf(file, "#if\tTypeCheck\n");
+ fprintf(file, "\tif (msgh_size != %d + (", rt->rtRequestSize);
+ WriteCheckArgSize(file, arg);
+ fprintf(file, "))\n");
+
+ WriteMsgError(file, "MIG_BAD_ARGUMENTS");
+ fprintf(file, "#endif\t/* TypeCheck */\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 = ");
+ WriteCheckArgSize(file, arg);
+ fprintf(file, ";\n");
+ fprintf(file, "#if\tTypeCheck\n");
+
+ /* Don't decrement msgh_size until we've checked that
+ it won't underflow. */
+
+ if (LastVarArg)
+ fprintf(file, "\tif (msgh_size != %d + msgh_size_delta)\n",
+ rt->rtRequestSize);
+ else
+ fprintf(file, "\tif (msgh_size < %d + msgh_size_delta)\n",
+ rt->rtRequestSize);
+ WriteMsgError(file, "MIG_BAD_ARGUMENTS");
+
+ if (!LastVarArg)
+ fprintf(file, "\tmsgh_size -= msgh_size_delta;\n");
+
+ fprintf(file, "#endif\t/* TypeCheck */\n");
+ }
+ fprintf(file, "\n");
+}
+
+static const char *
+InArgMsgField(register const argument_t *arg)
+{
+ static char buffer[100];
+
+ /*
+ * 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 (IsKernelServer &&
+ ((akIdent(arg->argKind) == akeRequestPort) ||
+ (akIdent(arg->argKind) == akeReplyPort)))
+ sprintf(buffer, "(ipc_port_t) In%dP->%s",
+ arg->argRequestPos, arg->argMsgField);
+ else
+ sprintf(buffer, "In%dP->%s",
+ arg->argRequestPos, arg->argMsgField);
+
+ return buffer;
+}
+
+static void
+WriteExtractArgValue(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *it = arg->argType;
+
+ if (arg->argMultiplier > 1)
+ WriteCopyType(file, it, "%s", "/* %s */ %s / %d",
+ arg->argVarName, InArgMsgField(arg), arg->argMultiplier);
+ else if (it->itInTrans != strNULL)
+ WriteCopyType(file, it, "%s", "/* %s */ %s(%s)",
+ arg->argVarName, it->itInTrans, InArgMsgField(arg));
+ else
+ WriteCopyType(file, it, "%s", "/* %s */ %s",
+ arg->argVarName, InArgMsgField(arg));
+ fprintf(file, "\n");
+}
+
+static void
+WriteInitializeCount(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *ptype = arg->argParent->argType;
+ register const ipc_type_t *btype = ptype->itElement;
+
+ /*
+ * Initialize 'count' argument for variable-length inline OUT parameter
+ * with maximum allowed number of elements.
+ */
+
+ fprintf(file, "\t%s = %d;\n", arg->argVarName,
+ ptype->itNumber/btype->itNumber);
+
+ /*
+ * 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, arg->argVarName);
+ fprintf(file, "\t\t%s = %s;\n", arg->argVarName, msgfield);
+ }
+
+ fprintf(file, "\n");
+}
+
+static void
+WriteInitializePtr(FILE *file, register const argument_t *arg)
+{
+ if (akCheck(arg->argKind, akbVarNeeded))
+ fprintf(file, "\t%sP = %s;\n",
+ arg->argVarName, arg->argVarName);
+ else
+ fprintf(file, "\t%sP = OutP->%s;\n",
+ arg->argVarName, arg->argMsgField);
+}
+
+static void
+WriteTypeCheckArg(FILE *file, register const argument_t *arg)
+{
+ if (akCheck(arg->argKind, akbRequest)) {
+ WriteTypeCheck(file, arg);
+
+ if (akCheck(arg->argKind, akbVariable))
+ WriteCheckMsgSize(file, arg);
+ }
+}
+
+static void
+WriteAdjustRequestMsgPtr(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *ptype = arg->argType;
+
+ fprintf(file,
+ "\tIn%dP = (Request *) ((char *) In%dP + msgh_size_delta - %d);\n\n",
+ arg->argRequestPos+1, arg->argRequestPos,
+ ptype->itTypeSize + ptype->itPadSize);
+}
+
+static void
+WriteTypeCheckRequestArgs(FILE *file, register const routine_t *rt)
+{
+ register const argument_t *arg;
+ register const argument_t *lastVarArg;
+
+ lastVarArg = argNULL;
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+
+ /*
+ * Advance message pointer if the last request argument was
+ * variable-length and the request position will change.
+ */
+ if (lastVarArg != argNULL &&
+ lastVarArg->argRequestPos < arg->argRequestPos)
+ {
+ WriteAdjustRequestMsgPtr(file, lastVarArg);
+ lastVarArg = argNULL;
+ }
+
+ /*
+ * Type-check the argument.
+ */
+ WriteTypeCheckArg(file, arg);
+
+ /*
+ * Remember whether this was variable-length.
+ */
+ if (akCheckAll(arg->argKind, akbVariable|akbRequest))
+ lastVarArg = arg;
+ }
+}
+
+static void
+WriteExtractArg(FILE *file, register const argument_t *arg)
+{
+ if (akCheckAll(arg->argKind, akbSendRcv|akbVarNeeded))
+ WriteExtractArgValue(file, arg);
+
+ if ((akIdent(arg->argKind) == akeCount) &&
+ akCheck(arg->argKind, akbReturnSnd))
+ {
+ register ipc_type_t *ptype = arg->argParent->argType;
+
+ if (ptype->itInLine && ptype->itVarArray)
+ WriteInitializeCount(file, arg);
+ }
+
+ if (akCheckAll(arg->argKind, akbReturnSnd|akbPointer))
+ WriteInitializePtr(file, arg);
+}
+
+static void
+WriteServerCallArg(FILE *file, register const argument_t *arg)
+{
+ const ipc_type_t *it = arg->argType;
+ boolean_t NeedClose = FALSE;
+
+ if (arg->argByReferenceServer)
+ fprintf(file, "&");
+
+ if ((it->itInTrans != strNULL) &&
+ akCheck(arg->argKind, akbSendRcv) &&
+ !akCheck(arg->argKind, akbVarNeeded))
+ {
+ fprintf(file, "%s(", it->itInTrans);
+ NeedClose = TRUE;
+ }
+
+ if (akCheck(arg->argKind, akbPointer))
+ fprintf(file, "%sP", arg->argVarName);
+ else if (akCheck(arg->argKind, akbVarNeeded))
+ fprintf(file, "%s", arg->argVarName);
+ else if (akCheck(arg->argKind, akbSendRcv)) {
+ if (akCheck(arg->argKind, akbIndefinite)) {
+ fprintf(file, "(In%dP->%s%s.msgt_inline) ",
+ arg->argRequestPos,
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "");
+ fprintf(file, "? %s ", InArgMsgField(arg));
+ fprintf(file, ": *((%s **)%s)",
+ FetchServerType(arg->argType->itElement),
+ InArgMsgField(arg));
+ }
+ else
+ fprintf(file, "%s", InArgMsgField(arg));
+ }
+ else
+ fprintf(file, "OutP->%s", arg->argMsgField);
+
+ if (NeedClose)
+ fprintf(file, ")");
+
+ if (!arg->argByReferenceServer && (arg->argMultiplier > 1))
+ fprintf(file, " / %d", arg->argMultiplier);
+}
+
+static void
+WriteDestroyArg(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *it = arg->argType;
+
+ if (akCheck(arg->argKind, akbIndefinite)) {
+ /*
+ * Deallocate only if out-of-line.
+ */
+ argument_t *count = arg->argCount;
+ ipc_type_t *btype = it->itElement;
+ int multiplier = btype->itTypeSize / btype->itNumber;
+
+ fprintf(file, "\tif (!In%dP->%s%s.msgt_inline)\n",
+ arg->argRequestPos,
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "");
+ fprintf(file, "\t\t%smig_deallocate(* (vm_offset_t *) %s, ",
+ SubrPrefix, InArgMsgField(arg));
+ if (multiplier > 1)
+ fprintf(file, "%d * ", multiplier);
+ fprintf(file, " %s);\n", InArgMsgField(count));
+ } 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 const argument_t *arg)
+{
+ register const 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.
+ */
+
+ if ((it->itInTrans != strNULL) &&
+ (it->itOutName == MACH_MSG_TYPE_PORT_SEND))
+ {
+ fprintf(file, "\n");
+ fprintf(file, "\tif (IP_VALID(%s))\n", InArgMsgField(arg));
+ fprintf(file, "\t\t%sipc_port_release_send(%s);\n",
+ SubrPrefix, InArgMsgField(arg));
+ }
+}
+
+/*
+ * Check whether WriteDestroyPortArg would generate any code for arg.
+ */
+static boolean_t
+CheckDestroyPortArg(register const argument_t *arg)
+{
+ register const 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, const routine_t *rt)
+{
+ boolean_t NeedClose = FALSE;
+
+ fprintf(file, "\t");
+ if (rt->rtServerReturn != argNULL)
+ {
+ const argument_t *arg = rt->rtServerReturn;
+ const ipc_type_t *it = arg->argType;
+
+ fprintf(file, "OutP->%s = ", arg->argMsgField);
+ if (it->itOutTrans != strNULL)
+ {
+ fprintf(file, "%s(", it->itOutTrans);
+ NeedClose = TRUE;
+ }
+ }
+ fprintf(file, "%s(", rt->rtServerName);
+ WriteList(file, rt->rtArgs, WriteServerCallArg, akbServerArg, ", ", "");
+ if (NeedClose)
+ fprintf(file, ")");
+ fprintf(file, ");\n");
+}
+
+static void
+WriteGetReturnValue(FILE *file, register const routine_t *rt)
+{
+ if (rt->rtServerReturn != rt->rtRetCode)
+ fprintf(file, "\tOutP->%s = KERN_SUCCESS;\n",
+ rt->rtRetCode->argMsgField);
+}
+
+static void
+WriteCheckReturnValue(FILE *file, register const routine_t *rt)
+{
+ if (rt->rtServerReturn == rt->rtRetCode)
+ {
+ fprintf(file, "\tif (OutP->%s != KERN_SUCCESS)\n",
+ rt->rtRetCode->argMsgField);
+ fprintf(file, "\t\treturn;\n");
+ }
+}
+
+static void
+WritePackArgType(FILE *file, register const argument_t *arg)
+{
+ fprintf(file, "\n");
+
+ WritePackMsgType(file, arg->argType,
+ arg->argType->itIndefinite ? d_NO : arg->argDeallocate,
+ arg->argLongForm, !IsKernelServer,
+ "OutP->%s", "%s", arg->argTTName);
+}
+
+static void
+WritePackArgValue(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *it = arg->argType;
+
+ fprintf(file, "\n");
+
+ if (it->itInLine && it->itVarArray) {
+
+ 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 = %smig_strncpy(OutP->%s, %s, %d);\n",
+ arg->argCount->argMsgField,
+ SubrPrefix,
+ arg->argMsgField,
+ arg->argVarName,
+ it->itNumber);
+ }
+ else {
+ register argument_t *count = arg->argCount;
+ register ipc_type_t *btype = it->itElement;
+
+ /* Note btype->itNumber == count->argMultiplier */
+
+ if (it->itIndefinite) {
+ /*
+ * If we are packing argument, it must be from
+ * a local variable.
+ */
+ fprintf(file, "\tif (%sP != %s) {\n",
+ arg->argVarName,
+ arg->argVarName);
+ fprintf(file, "\t\tOutP->%s%s.msgt_inline = FALSE;\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "");
+ if (arg->argDeallocate == d_YES)
+ fprintf(file, "\t\tOutP->%s%s.msgt_deallocate = TRUE;\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "");
+ else if (arg->argDeallocate == d_MAYBE)
+ fprintf(file, "\t\tOutP->%s%s.msgt_deallocate = %s;\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "",
+ arg->argDealloc->argVarName);
+ fprintf(file, "\t\t*((%s **)OutP->%s) = %sP;\n",
+ FetchServerType(btype),
+ arg->argMsgField,
+ arg->argVarName);
+ if (!arg->argRoutine->rtSimpleFixedReply)
+ fprintf(file, "\t\tmsgh_simple = FALSE;\n");
+ fprintf(file, "\t}\n\telse {\n\t");
+ }
+ fprintf(file, "\tmemcpy(OutP->%s, %s, ",
+ arg->argMsgField, arg->argVarName);
+ if (btype->itTypeSize > 1)
+ fprintf(file, "%d * ",
+ btype->itTypeSize);
+ fprintf(file, "%s);\n",
+ count->argVarName);
+ if (it->itIndefinite)
+ fprintf(file, "\t}\n");
+ }
+ }
+ else if (arg->argMultiplier > 1)
+ WriteCopyType(file, it, "OutP->%s", "/* %s */ %d * %s",
+ arg->argMsgField,
+ arg->argMultiplier,
+ arg->argVarName);
+ 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
+WriteCopyArgValue(FILE *file, register const argument_t *arg)
+{
+ fprintf(file, "\n");
+ WriteCopyType(file, arg->argType, "/* %d */ OutP->%s", "In%dP->%s",
+ arg->argRequestPos, arg->argMsgField);
+}
+
+static void
+WriteAdjustMsgSimple(FILE *file, register const argument_t *arg)
+{
+ /* akbVarNeeded must be on */
+
+ if (!arg->argRoutine->rtSimpleFixedReply)
+ {
+ fprintf(file, "\n");
+ fprintf(file, "\tif (MACH_MSG_TYPE_PORT_ANY(%s))\n", arg->argVarName);
+ fprintf(file, "\t\tmsgh_simple = FALSE;\n");
+ }
+}
+
+static void
+WriteAdjustMsgCircular(FILE *file, register const argument_t *arg)
+{
+ fprintf(file, "\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. Note we must use InHeadP
+ * (or In0P->Head) and OutHeadP to access the message headers,
+ * because of the variable-sized messages.
+ */
+
+ fprintf(file, "\tif (IP_VALID((ipc_port_t) InHeadP->msgh_reply_port) &&\n");
+ fprintf(file, "\t IP_VALID((ipc_port_t) OutP->%s) &&\n", arg->argMsgField);
+ fprintf(file, "\t %sipc_port_check_circularity((ipc_port_t) OutP->%s, (ipc_port_t) InHeadP->msgh_reply_port))\n",
+ SubrPrefix, arg->argMsgField);
+ fprintf(file, "\t\tOutHeadP->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;\n");
+}
+
+/*
+ * Calculate the size of a variable-length message field.
+ */
+static void
+WriteArgSize(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *ptype = arg->argType;
+ register int bsize = ptype->itElement->itTypeSize;
+ register const argument_t *count = arg->argCount;
+
+ if (ptype->itIndefinite) {
+ /*
+ * Check descriptor. If out-of-line, use standard size.
+ */
+ fprintf(file, "(OutP->%s%s.msgt_inline) ? ",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "");
+ }
+
+ if (bsize % 4 != 0)
+ fprintf(file, "(");
+
+ if (bsize > 1)
+ fprintf(file, "%d * ", bsize);
+ if (ptype->itString)
+ /* 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(int) [4],
+ * we have to round up.
+ */
+ if (bsize % 4 != 0)
+ fprintf(file, " + 3) & ~3");
+
+ if (ptype->itIndefinite) {
+ fprintf(file, " : sizeof(%s *)",
+ FetchServerType(ptype->itElement));
+ }
+}
+
+/*
+ * 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 const 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 = %d + msgh_size_delta;\n",
+ rt->rtReplySize);
+ else
+ if (arg->argReplyPos == 0)
+ /* First variable-length argument. The previous msgh_size value
+ is the minimum reply size. */
+
+ fprintf(file, "\tmsgh_size = %d + msgh_size_delta;\n",
+ rt->rtReplySize);
+ else
+ fprintf(file, "\tmsgh_size += msgh_size_delta;\n");
+
+ fprintf(file,
+ "\tOutP = (Reply *) ((char *) 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 const 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 = %d + (",
+ arg->argRoutine->rtReplySize);
+ WriteArgSize(file, arg);
+ fprintf(file, ");\n");
+ }
+ else {
+ fprintf(file, "\tmsgh_size += ");
+ WriteArgSize(file, arg);
+ fprintf(file, ";\n");
+ }
+}
+
+static void
+WritePackArg(FILE *file, register const argument_t *arg)
+{
+ if (akCheck(arg->argKind, akbReplyInit))
+ WritePackArgType(file, arg);
+
+ if ((akIdent(arg->argKind) == akePoly) &&
+ akCheck(arg->argKind, akbReturnSnd))
+ WriteAdjustMsgSimple(file, arg);
+
+ if (akCheckAll(arg->argKind, akbReturnSnd|akbVarNeeded))
+ WritePackArgValue(file, arg);
+ else if (akCheckAll(arg->argKind, akbReturnSnd|akbVariable)) {
+ register const ipc_type_t *it = arg->argType;
+
+ if (it->itString) {
+ /* Need to call strlen to calculate the size of the argument. */
+ fprintf(file, "\tOutP->%s = strlen(OutP->%s) + 1;\n",
+ arg->argCount->argMsgField, arg->argMsgField);
+ } else if (it->itIndefinite) {
+ /*
+ * We know that array is in reply message.
+ */
+ fprintf(file, "\tif (%sP != OutP->%s) {\n",
+ arg->argVarName,
+ arg->argMsgField);
+ fprintf(file, "\t\tOutP->%s%s.msgt_inline = FALSE;\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "");
+ if (arg->argDeallocate == d_YES)
+ fprintf(file, "\t\tOutP->%s%s.msgt_deallocate = TRUE;\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "");
+ else if (arg->argDeallocate == d_MAYBE)
+ fprintf(file, "\t\tOutP->%s%s.msgt_deallocate = %s;\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "",
+ arg->argDealloc->argVarName);
+ fprintf(file, "\t\t*((%s **)OutP->%s) = %sP;\n",
+ FetchServerType(it->itElement),
+ arg->argMsgField,
+ arg->argVarName);
+ if (!arg->argRoutine->rtSimpleFixedReply)
+ fprintf(file, "\t\tmsgh_simple = FALSE;\n");
+ fprintf(file, "\t}\n");
+ }
+ }
+
+ if (akCheck(arg->argKind, akbReplyCopy))
+ WriteCopyArgValue(file, arg);
+
+ /*
+ * 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 &&
+ akCheck(arg->argKind, akbReturnSnd) &&
+ ((arg->argType->itOutName == MACH_MSG_TYPE_PORT_RECEIVE) ||
+ (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC)))
+ WriteAdjustMsgCircular(file, arg);
+}
+
+/*
+ * Handle reply arguments - fill in message types and copy arguments
+ * that need to be copied.
+ */
+static void
+WritePackReplyArgs(FILE *file, register const routine_t *rt)
+{
+ register const argument_t *arg;
+ register const argument_t *lastVarArg;
+
+ lastVarArg = argNULL;
+ for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
+
+ /*
+ * Adjust message size and advance message pointer if
+ * the last reply argument was variable-length and the
+ * request position will change.
+ */
+ if (lastVarArg != argNULL &&
+ lastVarArg->argReplyPos < arg->argReplyPos)
+ {
+ WriteAdjustMsgSize(file, lastVarArg);
+ lastVarArg = argNULL;
+ }
+
+ /*
+ * Copy the argument
+ */
+ WritePackArg(file, arg);
+
+ /*
+ * Remember whether this was variable-length.
+ */
+ if (akCheckAll(arg->argKind, akbReturnSnd|akbVariable))
+ lastVarArg = arg;
+ }
+
+ /*
+ * Finish the message size.
+ */
+ if (lastVarArg != argNULL)
+ WriteFinishMsgSize(file, lastVarArg);
+}
+
+static void
+WriteFieldDecl(FILE *file, const argument_t *arg)
+{
+ WriteFieldDeclPrim(file, arg, FetchServerType);
+}
+
+static void
+WriteRoutine(FILE *file, register const routine_t *rt)
+{
+ fprintf(file, "\n");
+
+ fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
+ fprintf(file, "mig_internal void _X%s\n", rt->rtName);
+ fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
+
+ fprintf(file, "{\n");
+ WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request");
+ WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply, "Reply");
+
+ WriteVarDecls(file, rt);
+
+ WriteList(file, rt->rtArgs, WriteCheckDecl, akbRequestQC, "\n", "\n");
+ WriteList(file, rt->rtArgs,
+ IsKernelServer ? WriteTypeDeclOut : WriteTypeDeclIn,
+ akbReplyInit, "\n", "\n");
+
+ WriteList(file, rt->rtArgs, WriteLocalVarDecl,
+ akbVarNeeded, ";\n", ";\n\n");
+ WriteList(file, rt->rtArgs, WriteLocalPtrDecl,
+ akbPointer, ";\n", ";\n\n");
+
+ WriteCheckHead(file, rt);
+
+ WriteTypeCheckRequestArgs(file, rt);
+ WriteList(file, rt->rtArgs, WriteExtractArg, akbNone, "", "");
+
+ WriteServerCall(file, rt);
+ WriteGetReturnValue(file, rt);
+
+ 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)
+ {
+ if (rtCheckMaskFunction(rt->rtArgs, akbSendBody|akbSendRcv,
+ CheckDestroyPortArg))
+ {
+ WriteCheckReturnValue(file, rt);
+ }
+ WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg,
+ akbSendBody|akbSendRcv, "", "");
+ }
+ }
+ else
+ {
+ WriteCheckReturnValue(file, rt);
+
+ if (IsKernelServer)
+ WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg,
+ akbSendBody|akbSendRcv, "", "");
+
+ WriteReplyInit(file, rt);
+ WritePackReplyArgs(file, rt);
+ WriteReplyHead(file, rt);
+ }
+
+ fprintf(file, "}\n");
+}
+
+void
+WriteServer(FILE *file, const statement_t *stats)
+{
+ register const statement_t *stat;
+
+ WriteProlog(file);
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ switch (stat->stKind)
+ {
+ case skRoutine:
+ WriteRoutine(file, stat->stRoutine);
+ break;
+ case skImport:
+ case skSImport:
+ WriteImport(file, stat->stFileName);
+ break;
+ case skUImport:
+ break;
+ default:
+ fatal("WriteServer(): bad statement_kind_t (%d)",
+ (int) stat->stKind);
+ }
+ WriteEpilog(file, stats);
+}
diff --git a/mig/statement.c b/mig/statement.c
new file mode 100644
index 0000000..d26e17c
--- /dev/null
+++ b/mig/statement.c
@@ -0,0 +1,48 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <stdlib.h>
+
+#include "global.h"
+#include "error.h"
+#include "statement.h"
+
+statement_t *StatementList = stNULL;
+static statement_t **last = &StatementList;
+
+statement_t *
+stAlloc(void)
+{
+ register statement_t *new;
+
+ new = malloc(sizeof *new);
+ if (new == stNULL)
+ fatal("stAlloc(): %s", unix_error_string(errno));
+ *last = new;
+ last = &new->stNext;
+ new->stNext = stNULL;
+ return new;
+}
diff --git a/mig/statement.h b/mig/statement.h
new file mode 100644
index 0000000..914c6d8
--- /dev/null
+++ b/mig/statement.h
@@ -0,0 +1,65 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#ifndef _STATEMENT_H
+#define _STATEMENT_H
+
+#include "routine.h"
+
+typedef enum statement_kind
+{
+ skRoutine,
+ skImport,
+ skUImport,
+ skSImport,
+ 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 */
+ const_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 *StatementList;
+
+#endif _STATEMENT_H
diff --git a/mig/string.c b/mig/string.c
new file mode 100644
index 0000000..6fe29c2
--- /dev/null
+++ b/mig/string.c
@@ -0,0 +1,79 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+
+#include "boolean.h"
+#include "error.h"
+#include "mig_string.h"
+
+string_t
+strmake(const char *string)
+{
+ register string_t saved;
+
+ saved = malloc(strlen(string) + 1);
+ if (saved == strNULL)
+ fatal("strmake('%s'): %s", string, unix_error_string(errno));
+ return strcpy(saved, string);
+}
+
+string_t
+strconcat(const_string_t left, const_string_t right)
+{
+ register string_t saved;
+
+ saved = malloc(strlen(left) + strlen(right) + 1);
+ if (saved == strNULL)
+ fatal("strconcat('%s', '%s'): %s",
+ left, right, unix_error_string(errno));
+ return strcat(strcpy(saved, left), right);
+}
+
+void
+strfree(string_t string)
+{
+ free(string);
+}
+
+const char *
+strbool(boolean_t bool)
+{
+ if (bool)
+ return "TRUE";
+ else
+ return "FALSE";
+}
+
+const char *
+strstring(const_string_t string)
+{
+ if (string == strNULL)
+ return "NULL";
+ else
+ return string;
+}
diff --git a/mig/type.c b/mig/type.c
new file mode 100644
index 0000000..9c786e2
--- /dev/null
+++ b/mig/type.c
@@ -0,0 +1,918 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "error.h"
+#include "global.h"
+#include "type.h"
+#include "message.h"
+
+#if word_size_in_bits == 32
+#define word_size_name MACH_MSG_TYPE_INTEGER_32
+#define word_size_name_string "MACH_MSG_TYPE_INTEGER_32"
+#else
+#if word_size_in_bits == 64
+#define word_size_name MACH_MSG_TYPE_INTEGER_64
+#define word_size_name_string "MACH_MSG_TYPE_INTEGER_64"
+#else
+#error Unsupported word size!
+#endif
+#endif
+
+ipc_type_t *itRetCodeType; /* used for return codes */
+ipc_type_t *itDummyType; /* used for camelot dummy args */
+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;
+
+/*
+ * 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 const 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 */
+ TRUE, /* boolean_t itInLine */
+ FALSE, /* boolean_t itLongForm */
+ d_NO, /* dealloc_t itDeallocate */
+ strNULL, /* string_t itInNameStr */
+ strNULL, /* string_t itOutNameStr */
+ flNone, /* ipc_flags_t itFlags */
+ TRUE, /* boolean_t itStruct */
+ FALSE, /* boolean_t itString */
+ FALSE, /* boolean_t itVarArray */
+ FALSE, /* boolean_t itIndefinite */
+ itNULL, /* ipc_type_t *itElement */
+ strNULL, /* identifier_t itUserType */
+ strNULL, /* identifier_t itServerType */
+ strNULL, /* identifier_t itTransType */
+ strNULL, /* identifier_t itInTrans */
+ strNULL, /* identifier_t itOutTrans */
+ strNULL, /* identifier_t itDestructor */
+ };
+ register ipc_type_t *new;
+
+ new = malloc(sizeof *new);
+ if (new == itNULL)
+ fatal("itAlloc(): %s", unix_error_string(errno));
+ *new = prototype;
+ return new;
+}
+
+/*
+ * Convert an IPC type-name into a string.
+ */
+static string_t
+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 (it->itInLine)
+ {
+ u_int bytes = (it->itNumber * it->itSize + 7) / 8;
+ u_int padding = (4 - bytes%4)%4;
+
+ it->itTypeSize = bytes;
+ it->itPadSize = padding;
+ if (it->itVarArray)
+ it->itMinTypeSize = 0;
+ else
+ it->itMinTypeSize = bytes + padding;
+ }
+ else
+ {
+ /* out-of-line, so use size of pointers */
+ u_int bytes = sizeof_pointer;
+
+ 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->itNumber * it->itSize) % 8 != 0)
+ warn("size of C types must be multiples of 8 bits");
+
+ if ((it->itTypeSize == 0) && !it->itVarArray)
+ warn("sizeof(%s) == 0", it->itName);
+}
+
+/*
+ * 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;
+
+ /*
+ * 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";
+
+ if (it->itTransType == strNULL)
+ it->itTransType = it->itServerType;
+}
+
+ipc_flags_t
+itCheckFlags(ipc_flags_t flags, identifier_t name)
+{
+ /* only one of flLong and flNotLong */
+
+ if ((flags&(flLong|flNotLong)) == (flLong|flNotLong)) {
+ warn("%s: IsLong and IsNotLong cancel out", name);
+ flags &= ~(flLong|flNotLong);
+ }
+
+ /* 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);
+ }
+
+ return flags;
+}
+
+dealloc_t
+itCheckDeallocate(const ipc_type_t *it, ipc_flags_t flags, dealloc_t dfault,
+ identifier_t name)
+{
+ dealloc_t dealloc = dfault;
+
+ if (flags & flMaybeDealloc)
+ dealloc = d_MAYBE;
+ if (flags & flDealloc)
+ dealloc = d_YES;
+ if (flags & flNotDealloc)
+ dealloc = d_NO;
+
+ if (dealloc == dfault) {
+ if (flags & flMaybeDealloc)
+ warn("%s: Dealloc[] is redundant", name);
+ if (flags & flDealloc)
+ warn("%s: Dealloc is redundant", name);
+ if (flags & flNotDealloc)
+ warn("%s: NotDealloc is redundant", name);
+ }
+
+ if (flags & (flMaybeDealloc|flDealloc|flNotDealloc)) {
+ /* only give semantic warnings if the user specified something */
+
+ if (dealloc != d_NO) {
+ if (it->itInLine && !it->itIndefinite)
+ warn("%s: Dealloc will cause an IPC error", name);
+ }
+ }
+
+ return dealloc;
+}
+
+static enum uselong { NotLong, CanBeLong, ShouldBeLong, MustBeLong, TooLong }
+itUseLong(register const ipc_type_t *it)
+{
+ enum uselong uselong = NotLong;
+
+ if ((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) ||
+ (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC) ||
+ it->itVarArray)
+ uselong = CanBeLong;
+
+ if ((it->itVarArray && !it->itInLine) || it->itIndefinite)
+ uselong = ShouldBeLong;
+
+ if (((it->itInName != MACH_MSG_TYPE_POLYMORPHIC) &&
+ (it->itInName >= (1<<8))) ||
+ ((it->itOutName != MACH_MSG_TYPE_POLYMORPHIC) &&
+ (it->itOutName >= (1<<8))) ||
+ (it->itSize >= (1<<8)) ||
+ (it->itNumber >= (1<<12)))
+ uselong = MustBeLong;
+
+ if (((it->itInName != MACH_MSG_TYPE_POLYMORPHIC) &&
+ (it->itInName >= (1<<16))) ||
+ ((it->itOutName != MACH_MSG_TYPE_POLYMORPHIC) &&
+ (it->itOutName >= (1<<16))) ||
+ (it->itSize >= (1<<16)))
+ uselong = TooLong;
+
+ return uselong;
+}
+
+boolean_t
+itCheckIsLong(const ipc_type_t *it, ipc_flags_t flags, boolean_t dfault,
+ identifier_t name)
+{
+ boolean_t islong = dfault;
+
+ if (flags & flLong)
+ islong = TRUE;
+ if (flags & flNotLong)
+ islong = FALSE;
+
+ if (islong == dfault) {
+ if (flags & flLong)
+ warn("%s: IsLong is redundant", name);
+ if (flags & flNotLong)
+ warn("%s: IsNotLong is redundant", name);
+ }
+
+ if (flags & (flLong|flNotLong)) {
+ enum uselong uselong = itUseLong(it);
+
+ /* only give semantic warnings if the user specified something */
+
+ if (islong && ((int)uselong <= (int)NotLong))
+ warn("%s: doesn't need IsLong", name);
+ if (!islong && ((int)uselong >= (int)MustBeLong))
+ warn("%s: too big for IsNotLong", name);
+ }
+
+ return islong;
+}
+
+/******************************************************
+ * 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)
+{
+ enum uselong uselong;
+
+ 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);
+ }
+
+ if (it->itVarArray && it->itInLine) {
+ if ((it->itElement->itUserType == strNULL) ||
+ (it->itElement->itServerType == strNULL))
+ error("%s: variable-sized in-line arrays need a named base type",
+ name);
+ }
+
+ /* process the IPC flag specification */
+
+ it->itFlags = itCheckFlags(it->itFlags, name);
+
+ it->itDeallocate = itCheckDeallocate(it, it->itFlags, d_NO, name);
+
+ uselong = itUseLong(it);
+ if (uselong == TooLong)
+ warn("%s: too big for mach_msg_type_long_t", name);
+ it->itLongForm = itCheckIsLong(it, it->itFlags,
+ (int)uselong >= (int)ShouldBeLong, name);
+}
+
+/*
+ * Pretty-prints translation/destruction/type information.
+ */
+static void
+itPrintTrans(const 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, const ipc_type_t *it)
+{
+ printf("Type %s = ", name);
+ if (!it->itInLine)
+ printf("^ ");
+ if (it->itVarArray)
+ if (it->itNumber == 0 || it->itIndefinite)
+ 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%s%s)\n", it->itSize, it->itLongForm ? ", IsLong" : "",
+ it->itDeallocate == d_YES ? ", Dealloc"
+ :it->itDeallocate == d_MAYBE ?", Dealloc[]"
+ : "");
+
+ 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, const_string_t instr, u_int outname,
+ const_string_t outstr, u_int defsize)
+{
+ if (defsize == 0)
+ error("must use full IPC type decl");
+
+ return itLongDecl(inname, instr, outname, outstr, defsize, defsize, flNone);
+}
+
+/*
+ * Handles declarations like
+ * type new = (name, size, flags...)
+ * type new = (inname|outname, size, flags...)
+ */
+ipc_type_t *
+itLongDecl(u_int inname, const_string_t instr, u_int outname,
+ const_string_t outstr, u_int defsize, u_int size, ipc_flags_t flags)
+{
+ register ipc_type_t *it;
+
+ if ((defsize != 0) && (defsize != size))
+ warn("IPC type decl has strange size (%u instead of %u)",
+ size, defsize);
+
+ it = itAlloc();
+ it->itInName = inname;
+ it->itInNameStr = instr;
+ it->itOutName = outname;
+ it->itOutNameStr = outstr;
+ it->itSize = size;
+ if (inname == MACH_MSG_TYPE_STRING_C)
+ {
+ it->itStruct = FALSE;
+ it->itString = TRUE;
+ }
+ it->itFlags = flags;
+
+ itCalculateSizeInfo(it);
+ return it;
+}
+
+static ipc_type_t *
+itCopyType(const ipc_type_t *old)
+{
+ register ipc_type_t *new = itAlloc();
+
+ *new = *old;
+ new->itName = strNULL;
+ new->itNext = itNULL;
+ new->itElement = (ipc_type_t *) 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 0
+ * type new = array[*] of old; // number is 0
+ * type new = array[*:number] of old;
+ */
+ipc_type_t *
+itVarArrayDecl(u_int number, register const ipc_type_t *old)
+{
+ register ipc_type_t *it = itResetType(itCopyType(old));
+
+ if (!it->itInLine || it->itVarArray)
+ error("IPC type decl is too complicated");
+ if (number != 0)
+ it->itNumber *= number;
+ else {
+ /*
+ * Send at most 2048 bytes inline.
+ */
+ u_int bytes;
+
+ bytes = (it->itNumber * it->itSize + 7) / 8;
+ it->itNumber = (2048 / bytes) * it->itNumber;
+ it->itIndefinite = TRUE;
+ }
+ it->itVarArray = TRUE;
+ it->itStruct = FALSE;
+ it->itString = FALSE;
+
+ itCalculateSizeInfo(it);
+ return it;
+}
+
+/*
+ * Handles the declaration
+ * type new = array[number] of old;
+ */
+ipc_type_t *
+itArrayDecl(u_int number, const 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 = FALSE;
+ it->itString = FALSE;
+
+ itCalculateSizeInfo(it);
+ return it;
+}
+
+/*
+ * Handles the declaration
+ * type new = ^ old;
+ */
+ipc_type_t *
+itPtrDecl(ipc_type_t *it)
+{
+ if (!it->itInLine ||
+ (it->itVarArray && !it->itIndefinite && (it->itNumber > 0)))
+ error("IPC type decl is too complicated");
+ it->itNumber = 0;
+ it->itIndefinite = FALSE;
+ it->itInLine = FALSE;
+ it->itStruct = TRUE;
+ it->itString = FALSE;
+
+ itCalculateSizeInfo(it);
+ return it;
+}
+
+/*
+ * Handles the declaration
+ * type new = struct[number] of old;
+ */
+ipc_type_t *
+itStructDecl(u_int number, const 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;
+}
+
+ipc_type_t *
+itMakeCountType(void)
+{
+ ipc_type_t *it = itAlloc();
+
+ it->itName = "mach_msg_type_number_t";
+ it->itInName = word_size_name;
+ it->itInNameStr = word_size_name_string;
+ it->itOutName = word_size_name;
+ it->itOutNameStr = word_size_name_string;
+ it->itSize = word_size_in_bits;
+
+ itCalculateSizeInfo(it);
+ itCalculateNameInfo(it);
+ return it;
+}
+
+extern ipc_type_t *
+itMakeIntType()
+{
+ ipc_type_t *it = itAlloc();
+
+ it->itName = "int";
+ it->itInName = MACH_MSG_TYPE_INTEGER_32;
+ it->itInNameStr = "MACH_MSG_TYPE_INTEGER_32";
+ it->itOutName = MACH_MSG_TYPE_INTEGER_32;
+ it->itOutNameStr = "MACH_MSG_TYPE_INTEGER_32";
+ it->itSize = 32;
+
+ itCalculateSizeInfo(it);
+ itCalculateNameInfo(it);
+ return it;
+}
+
+ipc_type_t *
+itMakePolyType(void)
+{
+ ipc_type_t *it = itAlloc();
+
+ it->itName = "mach_msg_type_name_t";
+ it->itInName = word_size_name;
+ it->itInNameStr = word_size_name_string;
+ it->itOutName = word_size_name;
+ it->itOutNameStr = word_size_name_string;
+ it->itSize = word_size_in_bits;
+
+ itCalculateSizeInfo(it);
+ itCalculateNameInfo(it);
+ return it;
+}
+
+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 = 32;
+
+ itCalculateSizeInfo(it);
+ itCalculateNameInfo(it);
+ return it;
+}
+
+/*
+ * Initializes the pre-defined types.
+ */
+void
+init_type(void)
+{
+ itRetCodeType = itAlloc();
+ itRetCodeType->itName = "kern_return_t";
+ itRetCodeType->itInName = MACH_MSG_TYPE_INTEGER_32;
+ itRetCodeType->itInNameStr = "MACH_MSG_TYPE_INTEGER_32";
+ itRetCodeType->itOutName = MACH_MSG_TYPE_INTEGER_32;
+ itRetCodeType->itOutNameStr = "MACH_MSG_TYPE_INTEGER_32";
+ itRetCodeType->itSize = 32;
+ itCalculateSizeInfo(itRetCodeType);
+ itCalculateNameInfo(itRetCodeType);
+
+ 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 = word_size_in_bits;
+ itCalculateSizeInfo(itDummyType);
+ itCalculateNameInfo(itDummyType);
+
+ 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 = word_size_in_bits;
+ 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 = word_size_in_bits;
+ 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 = word_size_in_bits;
+ itCalculateSizeInfo(itRealReplyPortType);
+ itCalculateNameInfo(itRealReplyPortType);
+
+ itWaitTimeType = itMakeIntType();
+ itMsgOptionType = itMakeIntType();
+}
+
+/******************************************************
+ * Make sure return values of functions are assignable.
+ ******************************************************/
+void
+itCheckReturnType(identifier_t name, const 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, const 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->itNumber != 1) ||
+ (it->itSize != word_size_in_bits) ||
+ !it->itInLine ||
+ it->itDeallocate != d_NO ||
+ !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, const 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 != word_size_in_bits) ||
+ !it->itInLine ||
+ it->itDeallocate != d_NO ||
+ !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 32 integer.
+ ******************************************************/
+void
+itCheckIntType(identifier_t name, const ipc_type_t *it)
+{
+ if ((it->itInName != MACH_MSG_TYPE_INTEGER_32) ||
+ (it->itOutName != MACH_MSG_TYPE_INTEGER_32) ||
+ (it->itNumber != 1) ||
+ (it->itSize != 32) ||
+ !it->itInLine ||
+ it->itDeallocate != d_NO ||
+ !it->itStruct ||
+ it->itVarArray)
+ error("argument %s isn't a proper integer", name);
+}
+void
+itCheckNaturalType(name, it)
+ identifier_t name;
+ ipc_type_t *it;
+{
+ if ((it->itInName != word_size_name) ||
+ (it->itOutName != word_size_name) ||
+ (it->itNumber != 1) ||
+ (it->itSize != word_size_in_bits) ||
+ !it->itInLine ||
+ it->itDeallocate != d_NO ||
+ !it->itStruct ||
+ it->itVarArray)
+ error("argument %s should have been a %s", name, word_size_name_string);
+}
diff --git a/mig/type.h b/mig/type.h
new file mode 100644
index 0000000..f199059
--- /dev/null
+++ b/mig/type.h
@@ -0,0 +1,218 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992,1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#ifndef _TYPE_H
+#define _TYPE_H
+
+#include <sys/types.h>
+
+#include "boolean.h"
+#include "mig_string.h"
+
+typedef u_int ipc_flags_t;
+
+#define flNone (0x00)
+#define flLong (0x01) /* IsLong specified */
+#define flNotLong (0x02) /* NotIsLong specified */
+#define flDealloc (0x04) /* Dealloc specified */
+#define flNotDealloc (0x08) /* NotDealloc specified */
+#define flMaybeDealloc (0x10) /* Dealloc[] specified */
+#define flServerCopy (0x20) /* ServerCopy specified */
+#define flCountInOut (0x40) /* CountInOut specified */
+
+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, itInLine, itLongForm,
+ * and itDeallocate 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 msgt_name value supplied to the kernel,
+ * and itOutName is the msgt_name value received from the kernel.
+ * Either or both may be MACH_MSG_TYPE_POLYMORPHIC, indicating a
+ * "polymorphic" msgt_name. For itInName, this means the user
+ * supplies the value with an argument. For itOutName, this means the
+ * 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.
+ *
+ * itFlags contains the user's requests for itLongForm and itDeallocate
+ * values. itCheckDecl takes it into account when setting itLongForm
+ * and itDeallocate, but they can be overridden (with a warning message).
+ *
+ * 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.
+ *
+ * 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).
+ *
+ * itIndefinite means this is an indefinite-length array - it may be sent
+ * either inline or out-of-line. itNumber is assigned so that at most
+ * 2048 bytes are sent inline.
+ *
+ * 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;
+ boolean_t itInLine;
+ boolean_t itLongForm;
+ dealloc_t itDeallocate;
+
+ const_string_t itInNameStr; /* string form of itInName */
+ const_string_t itOutNameStr;/* string form of itOutName */
+
+ /* what the user wants, not necessarily what he gets */
+ ipc_flags_t itFlags;
+
+ boolean_t itStruct;
+ boolean_t itString;
+ boolean_t itVarArray;
+ boolean_t itIndefinite;
+
+ struct ipc_type *itElement; /* may be NULL */
+
+ identifier_t itUserType;
+ identifier_t itServerType;
+ identifier_t itTransType;
+
+ identifier_t itInTrans; /* may be NULL */
+ identifier_t itOutTrans; /* may be NULL */
+ identifier_t itDestructor; /* may be NULL */
+} ipc_type_t;
+
+#define itNULL ((ipc_type_t *) 0)
+
+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, const_string_t instr,
+ u_int outname, const_string_t outstr,
+ u_int defsize);
+extern ipc_type_t *itLongDecl(u_int inname, const_string_t instr,
+ u_int outname, const_string_t outstr,
+ u_int defsize, u_int size, ipc_flags_t flags);
+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, const ipc_type_t *it);
+extern ipc_type_t *itArrayDecl(u_int number, const ipc_type_t *it);
+extern ipc_type_t *itPtrDecl(ipc_type_t *it);
+extern ipc_type_t *itStructDecl(u_int number, const ipc_type_t *it);
+extern ipc_type_t *itCStringDecl(u_int number, boolean_t varying);
+
+extern ipc_type_t *itRetCodeType;
+extern ipc_type_t *itDummyType;
+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 *itMakePolyType(void);
+extern ipc_type_t *itMakeDeallocType(void);
+
+extern void init_type(void);
+
+extern void itCheckReturnType(identifier_t name, const ipc_type_t *it);
+extern void itCheckRequestPortType(identifier_t name, const ipc_type_t *it);
+extern void itCheckReplyPortType(identifier_t name, const ipc_type_t *it);
+extern void itCheckIntType(identifier_t name, const ipc_type_t *it);
+extern void itCheckNaturalType(identifier_t name, ipc_type_t *it);
+
+
+extern ipc_flags_t itCheckFlags(ipc_flags_t flags, identifier_t name);
+extern dealloc_t itCheckDeallocate(const ipc_type_t *it, ipc_flags_t flags,
+ dealloc_t dfault, identifier_t name);
+extern boolean_t itCheckIsLong(const ipc_type_t *it, ipc_flags_t flags,
+ boolean_t dfault, identifier_t name);
+
+#endif /* _TYPE_H */
diff --git a/mig/user.c b/mig/user.c
new file mode 100644
index 0000000..a5ca5fb
--- /dev/null
+++ b/mig/user.c
@@ -0,0 +1,1332 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992,1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <assert.h>
+
+#include "write.h"
+#include "error.h"
+#include "utils.h"
+#include "global.h"
+#include "mig_string.h"
+#include "cpu.h"
+
+/*************************************************************
+ * Writes the standard includes. The subsystem specific
+ * includes are in <SubsystemName>.h and writen by
+ * header:WriteHeader. Called by WriteProlog.
+ *************************************************************/
+static void
+WriteIncludes(FILE *file)
+{
+ 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\tKERNEL\n");
+
+ if (InternalHeaderFileName != strNULL)
+ {
+ register 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);
+ }
+ }
+
+ if (UserHeaderFileName != strNULL)
+ {
+ register 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);
+ }
+
+ fprintf(file, "#define EXPORT_BOOLEAN\n");
+ fprintf(file, "#include <mach/boolean.h>\n");
+ fprintf(file, "#include <mach/kern_return.h>\n");
+ fprintf(file, "#include <mach/message.h>\n");
+ fprintf(file, "#include <mach/notify.h>\n");
+ fprintf(file, "#include <mach/mach_types.h>\n");
+ fprintf(file, "#include <mach/mig_errors.h>\n");
+ fprintf(file, "#include <mach/mig_support.h>\n");
+ fprintf(file, "#include <mach/msg_type.h>\n");
+ fprintf(file, "/* LINTLIBRARY */\n");
+ 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");
+}
+
+/*************************************************************
+ * Writes the standard #includes, #defines, and
+ * RCS declaration. Called by WriteUser.
+ *************************************************************/
+static void
+WriteProlog(FILE *file)
+{
+ WriteIncludes(file);
+ WriteBogusDefines(file);
+ WriteGlobalDecls(file);
+}
+
+/*ARGSUSED*/
+static void
+WriteEpilog(FILE *file)
+{
+}
+
+static const_string_t
+WriteHeaderPortType(const 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, const routine_t *rt)
+{
+ if (rt->rtMaxRequestPos > 0)
+ fprintf(file, "\tInP = &Mess.In;\n");
+
+ if (rt->rtSimpleFixedRequest) {
+ fprintf(file, "\tInP->Head.msgh_bits =");
+ if (!rt->rtSimpleSendRequest)
+ fprintf(file, " MACH_MSGH_BITS_COMPLEX|");
+ fprintf(file, "\n");
+ fprintf(file, "\t\tMACH_MSGH_BITS(%s, %s);\n",
+ WriteHeaderPortType(rt->rtRequestPort),
+ WriteHeaderPortType(rt->rtUReplyPort));
+ } else {
+ fprintf(file, "\tInP->Head.msgh_bits = msgh_simple ?\n");
+ fprintf(file, "\t\tMACH_MSGH_BITS(%s, %s) :\n",
+ WriteHeaderPortType(rt->rtRequestPort),
+ WriteHeaderPortType(rt->rtUReplyPort));
+ fprintf(file, "\t\t(MACH_MSGH_BITS_COMPLEX|\n");
+ fprintf(file, "\t\t MACH_MSGH_BITS(%s, %s));\n",
+ WriteHeaderPortType(rt->rtRequestPort),
+ WriteHeaderPortType(rt->rtUReplyPort));
+ }
+
+ 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.
+ */
+
+ if (IsKernelUser)
+ fprintf(file, "\tInP->%s = (mach_port_t) %s;\n",
+ rt->rtRequestPort->argMsgField,
+ rt->rtRequestPort->argVarName);
+ else
+ fprintf(file, "\tInP->%s = %s;\n",
+ rt->rtRequestPort->argMsgField,
+ rt->rtRequestPort->argVarName);
+
+ if (akCheck(rt->rtUReplyPort->argKind, akbUserArg)) {
+ if (IsKernelUser)
+ fprintf(file, "\tInP->%s = (mach_port_t) %s;\n",
+ rt->rtUReplyPort->argMsgField,
+ rt->rtUReplyPort->argVarName);
+ else
+ fprintf(file, "\tInP->%s = %s;\n",
+ rt->rtUReplyPort->argMsgField,
+ rt->rtUReplyPort->argVarName);
+ } else if (rt->rtOneWay || IsKernelUser)
+ fprintf(file, "\tInP->%s = MACH_PORT_NULL;\n",
+ rt->rtUReplyPort->argMsgField);
+ else
+ fprintf(file, "\tInP->%s = %smig_get_reply_port();\n",
+ rt->rtUReplyPort->argMsgField, SubrPrefix);
+
+ fprintf(file, "\tInP->Head.msgh_seqno = 0;\n");
+ fprintf(file, "\tInP->Head.msgh_id = %d;\n", rt->rtNumber + SubsystemBase);
+}
+
+/*************************************************************
+ * Writes declarations for the message types, variables
+ * and return variable if needed. Called by WriteRoutine.
+ *************************************************************/
+static void
+WriteVarDecls(FILE *file, const routine_t *rt)
+{
+ fprintf(file, "\tunion {\n");
+ fprintf(file, "\t\tRequest In;\n");
+ if (!rt->rtOneWay)
+ fprintf(file, "\t\tReply Out;\n");
+ fprintf(file, "\t} Mess;\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "\tregister Request *InP = &Mess.In;\n");
+ if (!rt->rtOneWay)
+ fprintf(file, "\tregister Reply *OutP = &Mess.Out;\n");
+ fprintf(file, "\n");
+
+ if (!rt->rtOneWay || rt->rtProcedure)
+ fprintf(file, "\tmach_msg_return_t msg_result;\n");
+
+ if (!rt->rtSimpleFixedRequest)
+ fprintf(file, "\tboolean_t msgh_simple = %s;\n",
+ strbool(rt->rtSimpleSendRequest));
+ else if (!rt->rtOneWay &&
+ !(rt->rtSimpleCheckReply && rt->rtSimpleReceiveReply)) {
+ fprintf(file, "#if\tTypeCheck\n");
+ fprintf(file, "\tboolean_t msgh_simple;\n");
+ fprintf(file, "#endif\t/* TypeCheck */\n");
+ }
+
+ if (rt->rtNumRequestVar > 0)
+ fprintf(file, "\tunsigned int msgh_size;\n");
+ else if (!rt->rtOneWay && !rt->rtNoReplyArgs)
+ {
+ fprintf(file, "#if\tTypeCheck\n");
+ fprintf(file, "\tunsigned int msgh_size;\n");
+ fprintf(file, "#endif\t/* TypeCheck */\n");
+ }
+
+ /* if either request or reply is variable, we need msgh_size_delta */
+ if ((rt->rtMaxRequestPos > 0) ||
+ (rt->rtMaxReplyPos > 0))
+ fprintf(file, "\tunsigned int msgh_size_delta;\n");
+
+ fprintf(file, "\n");
+}
+
+/*************************************************************
+ * Writes code to call the user provided error procedure
+ * when a MIG error occurs. Called by WriteMsgSend,
+ * WriteMsgCheckReceive, WriteMsgSendReceive, WriteCheckIdentity,
+ * WriteRetCodeCheck, WriteTypeCheck, WritePackArgValue.
+ *************************************************************/
+static void
+WriteMsgError(FILE *file, const routine_t *rt, const char *error_msg)
+{
+ if (rt->rtProcedure)
+ fprintf(file, "\t\t{ %s(%s); return; }\n", rt->rtErrorName, error_msg);
+ else if (rt->rtReturn != rt->rtRetCode)
+ {
+ fprintf(file, "\t\t{ %s(%s); ", rt->rtErrorName, error_msg);
+ if (rt->rtNumReplyVar > 0)
+ fprintf(file, "OutP = &Mess.Out; ");
+ fprintf(file, "return OutP->%s; }\n", rt->rtReturn->argMsgField);
+ }
+ else
+ fprintf(file, "\t\treturn %s;\n", error_msg);
+}
+
+/*************************************************************
+ * Writes the send call when there is to be no subsequent
+ * receive. Called by WriteRoutine for SimpleProcedures
+ * or SimpleRoutines
+ *************************************************************/
+static void
+WriteMsgSend(FILE *file, const routine_t *rt)
+{
+ const char *MsgResult = (rt->rtProcedure)
+ ? "msg_result ="
+ : "return";
+
+ char SendSize[24];
+
+ if (rt->rtNumRequestVar == 0)
+ sprintf(SendSize, "%d", rt->rtRequestSize);
+ else
+ strcpy(SendSize, "msgh_size");
+
+ if (IsKernelUser)
+ {
+ fprintf(file, "\t%s %smach_msg_send_from_kernel(",
+ MsgResult, SubrPrefix);
+ fprintf(file, "&InP->Head, %s);\n", SendSize);
+ }
+ else
+ {
+ fprintf(file, "\t%s %smach_msg(&InP->Head, MACH_SEND_MSG|%s, %s, 0,",
+ MsgResult,
+ SubrPrefix,
+ rt->rtMsgOption->argVarName,
+ SendSize);
+ fprintf(file,
+ " MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);\n"
+ );
+ }
+
+ if (rt->rtProcedure)
+ {
+ fprintf(file, "\tif (msg_result != MACH_MSG_SUCCESS)\n");
+ WriteMsgError(file, rt, "msg_result");
+ }
+}
+
+/*************************************************************
+ * Writes to code to check for error returns from receive.
+ * Called by WriteMsgSendReceive and WriteMsgRPC
+ *************************************************************/
+static void
+WriteMsgCheckReceive(FILE *file, const routine_t *rt, const char *success)
+{
+ fprintf(file, "\tif (msg_result != %s) {\n", success);
+ if (!akCheck(rt->rtUReplyPort->argKind, akbUserArg) && !IsKernelUser)
+ {
+ /* If we aren't using a user-supplied reply port,
+ then deallocate the reply port on any message transmission
+ errors. */
+ fprintf(file, "\t\t%smig_dealloc_reply_port(%s);\n",
+ SubrPrefix, "InP->Head.msgh_reply_port");
+ }
+ WriteMsgError(file, rt, "msg_result");
+ fprintf(file, "\t}\n");
+
+ /*
+ * If not using a user supplied reply port, tell the port
+ * allocator we're done with the port.
+ */
+ if (!akCheck(rt->rtUReplyPort->argKind, akbUserArg) && !IsKernelUser)
+ {
+ fprintf(file, "\t%smig_put_reply_port(InP->Head.msgh_reply_port);\n",
+ SubrPrefix);
+ }
+}
+
+/*************************************************************
+ * 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, const routine_t *rt)
+{
+ char SendSize[24];
+
+ if (rt->rtNumRequestVar == 0)
+ sprintf(SendSize, "%d", rt->rtRequestSize);
+ else
+ strcpy(SendSize, "msgh_size");
+
+ fprintf(file, "\tmsg_result = %smach_msg(&InP->Head, MACH_SEND_MSG|%s, %s, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);\n",
+ SubrPrefix,
+ rt->rtMsgOption->argVarName,
+ SendSize);
+
+ fprintf(file, "\tif (msg_result != MACH_MSG_SUCCESS)\n");
+ WriteMsgError(file, rt, "msg_result");
+ fprintf(file, "\n");
+
+ fprintf(file, "\tmsg_result = %smach_msg(&OutP->Head, MACH_RCV_MSG|%s%s, 0, sizeof(Reply), InP->Head.msgh_local_port, %s, MACH_PORT_NULL);\n",
+ SubrPrefix,
+ rt->rtMsgOption->argVarName,
+ rt->rtWaitTime != argNULL ? "|MACH_RCV_TIMEOUT" : "",
+ rt->rtWaitTime != argNULL ? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE");
+ 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 SimpleProcedure and SimpleRoutine.
+ *************************************************************/
+static void
+WriteMsgRPC(FILE *file, const routine_t *rt)
+{
+ char SendSize[24];
+
+ if (rt->rtNumRequestVar == 0)
+ sprintf(SendSize, "%d", rt->rtRequestSize);
+ else
+ strcpy(SendSize, "msgh_size");
+
+ if (IsKernelUser)
+ fprintf(file, "\tmsg_result = %smach_msg_rpc_from_kernel(&InP->Head, %s, sizeof(Reply));\n",
+ SubrPrefix,
+ SendSize);
+ else
+ fprintf(file, "\tmsg_result = %smach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|%s%s, %s, sizeof(Reply), InP->Head.msgh_reply_port, %s, MACH_PORT_NULL);\n",
+ SubrPrefix,
+ rt->rtMsgOption->argVarName,
+ rt->rtWaitTime != argNULL ? "|MACH_RCV_TIMEOUT" : "",
+ SendSize,
+ rt->rtWaitTime != argNULL? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE");
+ WriteMsgCheckReceive(file, rt, "MACH_MSG_SUCCESS");
+ fprintf(file, "\n");
+}
+
+/*************************************************************
+ * Sets the correct value of the dealloc flag and calls
+ * Utils:WritePackMsgType to fill in the ipc msg type word(s)
+ * in the request message. Called by WriteRoutine for each
+ * argument that is to be sent in the request message.
+ *************************************************************/
+static void
+WritePackArgType(FILE *file, const argument_t *arg)
+{
+ WritePackMsgType(file, arg->argType,
+ arg->argType->itIndefinite ? d_NO : arg->argDeallocate,
+ arg->argLongForm, TRUE,
+ "InP->%s", "%s", arg->argTTName);
+ 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
+WritePackArgValue(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *it = arg->argType;
+ register const char *ref = arg->argByReferenceUser ? "*" : "";
+
+ if (it->itInLine && it->itVarArray) {
+
+ 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 = %smig_strncpy(InP->%s, %s, %d);\n",
+ arg->argCount->argMsgField,
+ SubrPrefix,
+ arg->argMsgField,
+ arg->argVarName,
+ it->itNumber);
+ }
+ else {
+
+ /*
+ * Copy in variable-size inline array with memcpy,
+ * after checking that number of elements doesn`t
+ * exceed declared maximum.
+ */
+ register const argument_t *count = arg->argCount;
+ register const char *countRef = count->argByReferenceUser ? "*" :"";
+ register const ipc_type_t *btype = it->itElement;
+
+ /* Note btype->itNumber == count->argMultiplier */
+
+ fprintf(file, "\tif (%s%s > %d) {\n",
+ countRef, count->argVarName,
+ it->itNumber/btype->itNumber);
+ if (it->itIndefinite) {
+ fprintf(file, "\t\tInP->%s%s.msgt_inline = FALSE;\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "");
+ if (arg->argDeallocate == d_YES)
+ fprintf(file, "\t\tInP->%s%s.msgt_deallocate = TRUE;\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "");
+ else if (arg->argDeallocate == d_MAYBE)
+ fprintf(file, "\t\tInP->%s%s.msgt_deallocate = %s%s;\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "",
+ arg->argDealloc->argByReferenceUser ? "*" : "",
+ arg->argDealloc->argVarName);
+ fprintf(file, "\t\t*((%s **)InP->%s) = %s%s;\n",
+ FetchUserType(btype),
+ arg->argMsgField,
+ ref, arg->argVarName);
+ if (!arg->argRoutine->rtSimpleFixedRequest)
+ fprintf(file, "\t\tmsgh_simple = FALSE;\n");
+ }
+ else
+ WriteMsgError(file, arg->argRoutine, "MIG_ARRAY_TOO_LARGE");
+
+ fprintf(file, "\t}\n\telse {\n");
+
+ fprintf(file, "\t\tmemcpy(InP->%s, %s%s, ", arg->argMsgField,
+ ref, arg->argVarName);
+ if (btype->itTypeSize > 1)
+ fprintf(file, "%d * ", btype->itTypeSize);
+ fprintf(file, "%s%s);\n",
+ countRef, count->argVarName);
+ fprintf(file, "\t}\n");
+ }
+ }
+ else if (arg->argMultiplier > 1)
+ WriteCopyType(file, it, "InP->%s", "/* %s */ %d * %s%s",
+ arg->argMsgField, arg->argMultiplier,
+ ref, arg->argVarName);
+ else
+ WriteCopyType(file, it, "InP->%s", "/* %s */ %s%s",
+ arg->argMsgField, ref, arg->argVarName);
+ fprintf(file, "\n");
+}
+
+static void
+WriteAdjustMsgSimple(FILE *file, register const argument_t *arg)
+{
+ if (!arg->argRoutine->rtSimpleFixedRequest)
+ {
+ register const char *ref = arg->argByReferenceUser ? "*" : "";
+
+ fprintf(file, "\tif (MACH_MSG_TYPE_PORT_ANY(%s%s))\n",
+ ref, arg->argVarName);
+ fprintf(file, "\t\tmsgh_simple = FALSE;\n");
+ fprintf(file, "\n");
+ }
+}
+
+/*
+ * Calculate the size of a variable-length message field.
+ */
+static void
+WriteArgSize(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *ptype = arg->argType;
+ register int bsize = ptype->itElement->itTypeSize;
+ register const argument_t *count = arg->argCount;
+
+ if (ptype->itIndefinite) {
+ /*
+ * Check descriptor. If out-of-line, use standard size.
+ */
+ fprintf(file, "(InP->%s%s.msgt_inline) ? ",
+ arg->argTTName, arg->argLongForm ? ".msgtl_header" : "");
+ }
+ if (bsize % 4 != 0)
+ 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);
+
+ /*
+ * If the base type size is not a multiple of sizeof(int) [4],
+ * we have to round up.
+ */
+ if (bsize % 4 != 0)
+ fprintf(file, " + 3) & ~3");
+
+ if (ptype->itIndefinite) {
+ fprintf(file, " : sizeof(%s *)",
+ FetchUserType(ptype->itElement));
+ }
+}
+
+/*
+ * 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 const argument_t *arg)
+{
+ register const 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 = %d + msgh_size_delta;\n",
+ arg->argRoutine->rtRequestSize);
+ else
+ fprintf(file, "\tmsgh_size += msgh_size_delta;\n");
+
+ fprintf(file,
+ "\tInP = (Request *) ((char *) InP + 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 const 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 = %d + (",
+ arg->argRoutine->rtRequestSize);
+ WriteArgSize(file, arg);
+ fprintf(file, ");\n");
+ }
+ else {
+ fprintf(file, "\tmsgh_size += ");
+ WriteArgSize(file, arg);
+ fprintf(file, ";\n");
+ }
+}
+
+static void
+WriteInitializeCount(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *ptype = arg->argCInOut->argParent->argType;
+ register const 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");
+}
+
+/*
+ * Called for every argument. Responsible for packing that
+ * argument into the request message.
+ */
+static void
+WritePackArg(FILE *file, register const argument_t *arg)
+{
+ if (akCheck(arg->argKind, akbRequest))
+ WritePackArgType(file, arg);
+
+ if ((akIdent(arg->argKind) == akePoly) &&
+ akCheckAll(arg->argKind, akbSendSnd|akbUserArg))
+ WriteAdjustMsgSimple(file, arg);
+
+ if ((akIdent(arg->argKind) == akeCountInOut) &&
+ akCheck(arg->argKind, akbSendSnd))
+ WriteInitializeCount(file, arg);
+ else if (akCheckAll(arg->argKind, akbSendSnd|akbSendBody))
+ WritePackArgValue(file, arg);
+}
+
+/*
+ * Generate code to fill in all of the request arguments and their
+ * message types.
+ */
+static void
+WriteRequestArgs(FILE *file, register const routine_t *rt)
+{
+ register const argument_t *arg;
+ register const argument_t *lastVarArg;
+
+ 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;
+ }
+
+ /*
+ * Copy the argument
+ */
+ WritePackArg(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, const routine_t *rt)
+{
+ fprintf(file, "\tif (OutP->Head.msgh_id != %d) {\n",
+ rt->rtNumber + SubsystemBase + 100);
+ fprintf(file, "\t\tif (OutP->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)\n");
+ WriteMsgError(file, rt, "MIG_SERVER_DIED");
+ fprintf(file, "\t\telse {\n");
+ fprintf(file, "\t\t\t%smig_dealloc_reply_port(%s);\n\t",
+ SubrPrefix,"InP->Head.msgh_reply_port");
+ WriteMsgError(file, rt, "MIG_REPLY_MISMATCH");
+ fprintf(file, "\t\t}\n\t}\n");
+ fprintf(file, "\n");
+ fprintf(file, "#if\tTypeCheck\n");
+
+ if (rt->rtSimpleCheckReply && rt->rtSimpleReceiveReply)
+ {
+ /* Expecting a simple message. We can factor out the check for
+ a simple message, since the error reply message is also simple.
+ */
+
+ if (!rt->rtNoReplyArgs)
+ fprintf(file, "\tmsgh_size = OutP->Head.msgh_size;\n\n");
+
+ fprintf(file,
+ "\tif ((OutP->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
+ if (rt->rtNoReplyArgs)
+ fprintf(file, "\t (OutP->Head.msgh_size != %d))\n",
+ rt->rtReplySize);
+ else {
+ fprintf(file, "\t ((msgh_size %s %d) &&\n",
+ (rt->rtNumReplyVar > 0) ? "<" : "!=",
+ rt->rtReplySize);
+ fprintf(file, "\t ((msgh_size != sizeof(mig_reply_header_t)) ||\n");
+ fprintf(file, "\t (OutP->RetCode == KERN_SUCCESS))))\n");
+ }
+ }
+ else {
+ /* Expecting a complex message, or may vary at run time. */
+
+ fprintf(file, "\tmsgh_size = OutP->Head.msgh_size;\n");
+ fprintf(file, "\tmsgh_simple = !(OutP->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "\tif (((msgh_size %s %d)",
+ (rt->rtNumReplyVar > 0) ? "<" : "!=",
+ rt->rtReplySize);
+
+ if (rt->rtSimpleCheckReply)
+ /* if rtSimpleReceiveReply was true, then we would have
+ executed the code above. So we know that the message
+ is complex. */
+ fprintf(file, " || msgh_simple");
+ fprintf(file, ") &&\n");
+
+ fprintf(file, "\t ((msgh_size != sizeof(mig_reply_header_t)) ||\n");
+ fprintf(file, "\t !msgh_simple ||\n");
+ fprintf(file, "\t (OutP->RetCode == KERN_SUCCESS)))\n");
+ }
+ WriteMsgError(file, rt, "MIG_TYPE_ERROR");
+ fprintf(file, "#endif\t/* TypeCheck */\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, const routine_t *rt)
+{
+ fprintf(file, "\tif (OutP->RetCode != KERN_SUCCESS)\n");
+ WriteMsgError(file, rt, "OutP->RetCode");
+ fprintf(file, "\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 argument in the reply message.
+ *************************************************************/
+static void
+WriteTypeCheck(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *it = arg->argType;
+ register const routine_t *rt = arg->argRoutine;
+
+ fprintf(file, "#if\tTypeCheck\n");
+ if (akCheck(arg->argKind, akbReplyQC))
+ {
+ fprintf(file, "\tif (* (int *) &OutP->%s != * (int *) &%sCheck)\n",
+ arg->argTTName, arg->argVarName);
+ }
+ else
+ {
+ fprintf(file, "\tif (");
+ if (!it->itIndefinite) {
+ fprintf(file, "(OutP->%s%s.msgt_inline != %s) ||\n\t ",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "",
+ strbool(it->itInLine));
+ }
+ fprintf(file, "(OutP->%s%s.msgt_longform != %s) ||\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "",
+ strbool(arg->argLongForm));
+ if (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
+ {
+ if (!rt->rtSimpleCheckReply)
+ fprintf(file, "\t (MACH_MSG_TYPE_PORT_ANY(OutP->%s.msgt%s_name) && msgh_simple) ||\n",
+ arg->argTTName,
+ arg->argLongForm ? "l" : "");
+ }
+ else
+ fprintf(file, "\t (OutP->%s.msgt%s_name != %s) ||\n",
+ arg->argTTName,
+ arg->argLongForm ? "l" : "",
+ it->itOutNameStr);
+ if (!it->itVarArray)
+ fprintf(file, "\t (OutP->%s.msgt%s_number != %d) ||\n",
+ arg->argTTName,
+ arg->argLongForm ? "l" : "",
+ it->itNumber);
+ fprintf(file, "\t (OutP->%s.msgt%s_size != %d))\n",
+ arg->argTTName,
+ arg->argLongForm ? "l" : "",
+ it->itSize);
+ }
+ WriteMsgError(file, rt, "MIG_TYPE_ERROR");
+ fprintf(file, "#endif\t/* TypeCheck */\n");
+ fprintf(file, "\n");
+}
+
+static void
+WriteCheckArgSize(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *ptype = arg->argType;
+ register const ipc_type_t *btype = ptype->itElement;
+ const argument_t *count = arg->argCount;
+ int multiplier = btype->itTypeSize / btype->itNumber;
+
+ if (ptype->itIndefinite) {
+ /*
+ * Check descriptor. If out-of-line, use standard size.
+ */
+ fprintf(file, "(OutP->%s%s.msgt_inline) ? ",
+ arg->argTTName, arg->argLongForm ? ".msgtl_header" : "");
+ }
+
+ if (btype->itTypeSize % 4 != 0)
+ fprintf(file, "(");
+
+ if (multiplier > 1)
+ fprintf(file, "%d * ", multiplier);
+
+ fprintf(file, "OutP->%s", count->argMsgField);
+
+ /* If the base type size of the data field isn`t a multiple of 4,
+ we have to round up. */
+ if (btype->itTypeSize % 4 != 0)
+ fprintf(file, " + 3) & ~3");
+
+ if (ptype->itIndefinite)
+ fprintf(file, " : sizeof(%s *)", FetchUserType(btype));
+}
+
+static void
+WriteCheckMsgSize(FILE *file, register const argument_t *arg)
+{
+ register const 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 (arg->argReplyPos == rt->rtMaxReplyPos)
+ {
+ fprintf(file, "#if\tTypeCheck\n");
+ fprintf(file, "\tif (msgh_size != %d + (",
+ rt->rtReplySize);
+ WriteCheckArgSize(file, arg);
+ fprintf(file, "))\n");
+
+ WriteMsgError(file, rt, "MIG_TYPE_ERROR");
+ fprintf(file, "#endif\t/* TypeCheck */\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 = ");
+ WriteCheckArgSize(file, arg);
+ fprintf(file, ";\n");
+ fprintf(file, "#if\tTypeCheck\n");
+
+ /* Don't decrement msgh_size until we've checked that
+ it won't underflow. */
+
+ if (LastVarArg)
+ fprintf(file, "\tif (msgh_size != %d + msgh_size_delta)\n",
+ rt->rtReplySize);
+ else
+ fprintf(file, "\tif (msgh_size < %d + msgh_size_delta)\n",
+ rt->rtReplySize);
+ WriteMsgError(file, rt, "MIG_TYPE_ERROR");
+
+ if (!LastVarArg)
+ fprintf(file, "\tmsgh_size -= msgh_size_delta;\n");
+
+ fprintf(file, "#endif\t/* TypeCheck */\n");
+ }
+ fprintf(file, "\n");
+}
+
+/*************************************************************
+ * 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
+WriteExtractArgValue(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *argType = arg->argType;
+ register const char *ref = arg->argByReferenceUser ? "*" : "";
+
+ if (argType->itInLine && argType->itVarArray) {
+
+ if (argType->itString) {
+ /*
+ * Copy out variable-size C string with mig_strncpy.
+ */
+ fprintf(file, "\t(void) %smig_strncpy(%s%s, OutP->%s, %d);\n",
+ SubrPrefix,
+ ref,
+ arg->argVarName,
+ arg->argMsgField,
+ argType->itNumber);
+ }
+ else if (argType->itIndefinite) {
+ /*
+ * If data was returned out-of-line,
+ * change user`s pointer to point to it.
+ * If data was returned in-line but doesn`t fit,
+ * allocate a new buffer, copy the data to it,
+ * and change user`s pointer to point to it.
+ * If data was returned in-line and fits,
+ * copy to buffer.
+ */
+ const argument_t *count = arg->argCount;
+ const char *countRef = count->argByReferenceUser ? "*" : "";
+ const ipc_type_t *btype = argType->itElement;
+
+ fprintf(file, "\tif (!OutP->%s%s.msgt_inline)\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "");
+ fprintf(file, "\t %s%s = *((%s **)OutP->%s);\n",
+ ref, arg->argVarName,
+ FetchUserType(btype), arg->argMsgField);
+ fprintf(file, "\telse if (OutP->%s", count->argMsgField);
+ if (btype->itNumber > 1)
+ fprintf(file, " / %d", btype->itNumber);
+ fprintf(file, " > %s%s) {\n", countRef, count->argVarName);
+ fprintf(file, "\t %smig_allocate((vm_offset_t *)%s,\n\t\t",
+ SubrPrefix, arg->argVarName); /* no ref! */
+ if (btype->itTypeSize != btype->itNumber)
+ fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
+ fprintf(file, "OutP->%s);\n", count->argMsgField);
+ fprintf(file, "\t memcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
+ arg->argMsgField);
+ if (btype->itTypeSize != btype->itNumber)
+ fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
+ fprintf(file, "OutP->%s);\n", count->argMsgField);
+ fprintf(file, "\t}\n");
+ fprintf(file, "\telse {\n");
+
+ fprintf(file, "\t memcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
+ arg->argMsgField);
+ if (btype->itTypeSize != btype->itNumber)
+ fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
+ fprintf(file, "OutP->%s);\n", count->argMsgField);
+ fprintf(file, "\t}\n");
+ }
+ else {
+
+ /*
+ * Copy out variable-size inline array with memcpy,
+ * after checking that number of elements doesn`t
+ * exceed user`s maximum.
+ */
+ register const argument_t *count = arg->argCount;
+ register const char *countRef = count->argByReferenceUser ? "*" :"";
+ register const ipc_type_t *btype = argType->itElement;
+
+ /* Note count->argMultiplier == btype->itNumber */
+
+ fprintf(file, "\tif (OutP->%s", count->argMsgField);
+ if (btype->itNumber > 1)
+ fprintf(file, " / %d", btype->itNumber);
+ fprintf(file, " > %s%s) {\n",
+ countRef, count->argVarName);
+
+ /*
+ * 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\tmemcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
+ arg->argMsgField);
+ if (btype->itTypeSize > 1)
+ fprintf(file, "%d * ", btype->itTypeSize);
+ fprintf(file, "%s%s);\n",
+ countRef, count->argVarName);
+
+ fprintf(file, "\t\t%s%s = OutP->%s",
+ countRef, count->argVarName, count->argMsgField);
+ if (btype->itNumber > 1)
+ fprintf(file, " / %d", btype->itNumber);
+ fprintf(file, ";\n");
+ WriteMsgError(file,arg->argRoutine, "MIG_ARRAY_TOO_LARGE");
+
+ fprintf(file, "\t}\n\telse {\n");
+
+ fprintf(file, "\t\tmemcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
+ arg->argMsgField);
+ if (btype->itTypeSize != btype->itNumber)
+ fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
+ fprintf(file, "OutP->%s);\n", count->argMsgField);
+ fprintf(file, "\t}\n");
+ }
+ }
+ else if (arg->argMultiplier > 1)
+ WriteCopyType(file, argType,
+ "%s%s", "/* %s%s */ OutP->%s / %d",
+ ref, arg->argVarName, arg->argMsgField,
+ arg->argMultiplier);
+ else
+ WriteCopyType(file, argType,
+ "%s%s", "/* %s%s */ OutP->%s",
+ ref, arg->argVarName, arg->argMsgField);
+ fprintf(file, "\n");
+}
+
+static void
+WriteExtractArg(FILE *file, register const argument_t *arg)
+{
+ register const routine_t *rt = arg->argRoutine;
+
+ if (akCheck(arg->argKind, akbReply))
+ WriteTypeCheck(file, arg);
+
+ if (akCheckAll(arg->argKind, akbVariable|akbReply))
+ WriteCheckMsgSize(file, arg);
+
+ /* Now that the RetCode is type-checked, check its value.
+ Must abort immediately if it isn't KERN_SUCCESS, because
+ in that case the reply message is truncated. */
+
+ if (arg == rt->rtRetCode)
+ WriteRetCodeCheck(file, rt);
+
+ if (akCheckAll(arg->argKind, akbReturnRcv))
+ WriteExtractArgValue(file, arg);
+}
+
+static void
+WriteAdjustReplyMsgPtr(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *ptype = arg->argType;
+
+ fprintf(file,
+ "\tOutP = (Reply *) ((char *) OutP + msgh_size_delta - %d);\n\n",
+ ptype->itTypeSize + ptype->itPadSize);
+}
+
+static void
+WriteReplyArgs(FILE *file, register const routine_t *rt)
+{
+ register const argument_t *arg;
+ register const argument_t *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;
+ }
+
+ /*
+ * Copy the argument
+ */
+ WriteExtractArg(file, arg);
+
+ /*
+ * Remember whether this was variable-length.
+ */
+ if (akCheckAll(arg->argKind, akbReturnRcv|akbVariable))
+ lastVarArg = arg;
+ }
+}
+
+/*************************************************************
+ * Writes code to return the return value. Called by WriteRoutine
+ * for routines and functions.
+ *************************************************************/
+static void
+WriteReturnValue(FILE *file, const routine_t *rt)
+{
+ if (rt->rtReturn == rt->rtRetCode)
+ /* If returning RetCode, we have already checked that it is
+ KERN_SUCCESS */
+ fprintf(file, "\treturn KERN_SUCCESS;\n");
+
+ else
+ {
+ if (rt->rtNumReplyVar > 0)
+ fprintf(file, "\tOutP = &Mess.Out;\n");
+
+ fprintf(file, "\treturn OutP->%s;\n", rt->rtReturn->argMsgField);
+ }
+}
+
+/*************************************************************
+ * 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, const argument_t *arg)
+{
+ WriteFieldDeclPrim(file, arg, FetchUserType);
+}
+
+static void
+WriteStubDecl(FILE *file, register const 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);
+ fprintf(file, "(\n");
+ WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n");
+ fprintf(file, ")\n");
+ fprintf(file, "{\n");
+}
+
+/*************************************************************
+ * Writes all the code comprising a routine body. Called by
+ * WriteUser for each routine.
+ *************************************************************/
+static void
+WriteRoutine(FILE *file, register const routine_t *rt)
+{
+ /* write the stub's declaration */
+
+ WriteStubDecl(file, rt);
+
+ /* typedef of structure for Request and Reply messages */
+
+ WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request");
+ if (!rt->rtOneWay)
+ WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply, "Reply");
+
+ /* 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_t variables
+ for each argument */
+
+ WriteList(file, rt->rtArgs, WriteTypeDeclIn, akbRequest, "\n", "\n");
+ if (!rt->rtOneWay)
+ WriteList(file, rt->rtArgs, WriteCheckDecl, akbReplyQC, "\n", "\n");
+
+ /* fill in all the request message types and then arguments */
+
+ WriteRequestArgs(file, rt);
+
+ /* fill in request message head */
+
+ WriteRequestHead(file, rt);
+ fprintf(file, "\n");
+
+ /* Write the send/receive or rpc call */
+
+ if (rt->rtOneWay)
+ WriteMsgSend(file, rt);
+ else
+ {
+ if (UseMsgRPC)
+ WriteMsgRPC(file, rt);
+ else
+ WriteMsgSendReceive(file, rt);
+
+ /* 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)
+ {
+ WriteTypeCheck(file, rt->rtRetCode);
+
+ fprintf(file, "\treturn OutP->RetCode;\n");
+ }
+ else {
+ WriteReplyArgs(file, rt);
+
+ /* return the return value, if any */
+
+ if (rt->rtProcedure)
+ fprintf(file, "\t/* Procedure - no return needed */\n");
+ else
+ WriteReturnValue(file, rt);
+ }
+ }
+
+ fprintf(file, "}\n");
+}
+
+/*************************************************************
+ * Writes out the xxxUser.c file. Called by mig.c
+ *************************************************************/
+void
+WriteUser(FILE *file, const statement_t *stats)
+{
+ register const statement_t *stat;
+
+ WriteProlog(file);
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ switch (stat->stKind)
+ {
+ case skRoutine:
+ WriteRoutine(file, stat->stRoutine);
+ break;
+ case skImport:
+ case skUImport:
+ WriteImport(file, stat->stFileName);
+ break;
+ case skSImport:
+ 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(const statement_t *stats)
+{
+ register const statement_t *stat;
+
+ for (stat = stats; stat != stNULL; stat = stat->stNext)
+ switch (stat->stKind)
+ {
+ case skRoutine:
+ {
+ FILE *file;
+ register char *filename;
+
+ filename = strconcat(UserFilePrefix,
+ strconcat(stat->stRoutine->rtName, ".c"));
+ file = fopen(filename, "w");
+ if (file == NULL)
+ fatal("fopen(%s): %s", filename,
+ unix_error_string(errno));
+ WriteProlog(file);
+
+ {
+ /* Write all the imports. */
+ const statement_t *s;
+ for (s = stats; s != stNULL; s = s->stNext)
+ switch (s->stKind)
+ {
+ case skImport:
+ case skUImport:
+ WriteImport(file, s->stFileName);
+ break;
+ }
+ }
+
+ WriteRoutine(file, stat->stRoutine);
+ WriteEpilog(file);
+ fclose(file);
+ strfree(filename);
+ }
+ break;
+ case skImport:
+ case skUImport:
+ break;
+ case skSImport:
+ break;
+ default:
+ fatal("WriteUserIndividual(): bad statement_kind_t (%d)",
+ (int) stat->stKind);
+ }
+}
diff --git a/mig/utils.c b/mig/utils.c
new file mode 100644
index 0000000..f716e01
--- /dev/null
+++ b/mig/utils.c
@@ -0,0 +1,417 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <stdarg.h>
+
+#include "write.h"
+#include "utils.h"
+#include "global.h"
+
+void
+WriteImport(FILE *file, const_string_t filename)
+{
+ fprintf(file, "#include %s\n", filename);
+}
+
+void
+WriteRCSDecl(FILE *file, identifier_t name, const_string_t rcs)
+{
+ fprintf(file, "#ifndef\tlint\n");
+ fprintf(file, "#if\tUseExternRCSId\n");
+ fprintf(file, "char %s_rcsid[] = %s;\n", name, rcs);
+ fprintf(file, "#else\t/* UseExternRCSId */\n");
+ fprintf(file, "static char rcsid[] = %s;\n", rcs);
+ fprintf(file, "#endif\t/* UseExternRCSId */\n");
+ fprintf(file, "#endif\t/* lint */\n");
+ fprintf(file, "\n");
+}
+
+void
+WriteBogusDefines(FILE *file)
+{
+ fprintf(file, "#ifndef\tmig_internal\n");
+ fprintf(file, "#define\tmig_internal\tstatic\n");
+ fprintf(file, "#endif\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "#ifndef\tmig_external\n");
+ fprintf(file, "#define mig_external\n");
+ fprintf(file, "#endif\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "#ifndef\tTypeCheck\n");
+ fprintf(file, "#define\tTypeCheck 1\n");
+ fprintf(file, "#endif\n");
+ fprintf(file, "\n");
+
+ fprintf(file, "#ifndef\tUseExternRCSId\n");
+ fprintf(file, "#define\tUseExternRCSId\t\t1\n");
+ fprintf(file, "#endif\n");
+ fprintf(file, "\n");
+}
+
+void
+WriteList(FILE *file, const argument_t *args, write_list_fn_t *func, u_int mask,
+ const char *between, const char *after)
+{
+ register const argument_t *arg;
+ register 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, register const argument_t *arg,
+ write_list_fn_t *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, const argument_t *args, write_list_fn_t *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, const argument_t *arg)
+{
+ fprintf(file, "%s", arg->argVarName);
+}
+
+void
+WriteUserVarDecl(FILE *file, const argument_t *arg)
+{
+ const char *ref = arg->argByReferenceUser ? "*" : "";
+
+ fprintf(file, "\t%s %s%s", arg->argType->itUserType, ref, arg->argVarName);
+}
+
+void
+WriteServerVarDecl(FILE *file, const argument_t *arg)
+{
+ const char *ref = arg->argByReferenceServer ? "*" : "";
+
+ fprintf(file, "\t%s %s%s",
+ arg->argType->itTransType, ref, arg->argVarName);
+}
+
+void
+WriteTypeDeclIn(FILE *file, register const argument_t *arg)
+{
+ WriteStaticDecl(file, arg->argType,
+ arg->argType->itIndefinite ? d_NO : arg->argDeallocate,
+ arg->argLongForm, TRUE, arg->argTTName);
+}
+
+void
+WriteTypeDeclOut(FILE *file, register const argument_t *arg)
+{
+ WriteStaticDecl(file, arg->argType,
+ arg->argType->itIndefinite ? d_NO : arg->argDeallocate,
+ arg->argLongForm, FALSE, arg->argTTName);
+}
+
+void
+WriteCheckDecl(FILE *file, register const argument_t *arg)
+{
+ register const ipc_type_t *it = arg->argType;
+
+ /* We'll only be called for short-form types.
+ Note we use itOutNameStr instead of itInNameStr, because
+ this declaration will be used to check received types. */
+
+ fprintf(file, "\tstatic const mach_msg_type_t %sCheck = {\n",
+ arg->argVarName);
+ fprintf(file, "\t\t/* msgt_name = */\t\t%s,\n", it->itOutNameStr);
+ fprintf(file, "\t\t/* msgt_size = */\t\t%d,\n", it->itSize);
+ fprintf(file, "\t\t/* msgt_number = */\t\t%d,\n", it->itNumber);
+ fprintf(file, "\t\t/* msgt_inline = */\t\t%s,\n",
+ strbool(it->itInLine));
+ fprintf(file, "\t\t/* msgt_longform = */\t\tFALSE,\n");
+ fprintf(file, "\t\t/* msgt_deallocate = */\t\t%s,\n",
+ strbool(!it->itInLine));
+ fprintf(file, "\t\t/* msgt_unused = */\t\t0\n");
+ fprintf(file, "\t};\n");
+}
+
+const char *
+ReturnTypeStr(const routine_t *rt)
+{
+ if (rt->rtReturn == argNULL)
+ return "void";
+ else
+ return rt->rtReturn->argType->itUserType;
+}
+
+const char *
+FetchUserType(const ipc_type_t *it)
+{
+ return it->itUserType;
+}
+
+const char *
+FetchServerType(const ipc_type_t *it)
+{
+ return it->itServerType;
+}
+
+void
+WriteFieldDeclPrim(FILE *file, const argument_t *arg,
+ const char *(*tfunc)(const ipc_type_t *))
+{
+ register const ipc_type_t *it = arg->argType;
+
+ fprintf(file, "\t\tmach_msg_type_%st %s;\n",
+ arg->argLongForm ? "long_" : "", arg->argTTName);
+
+ if (it->itInLine && it->itVarArray)
+ {
+ 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.
+ */
+ fprintf(file, "\t\t%s %s[%d];",
+ (*tfunc)(btype),
+ arg->argMsgField,
+ it->itNumber/btype->itNumber);
+ }
+ else
+ fprintf(file, "\t\t%s %s;", (*tfunc)(it), arg->argMsgField);
+
+ if (it->itPadSize != 0)
+ fprintf(file, "\n\t\tchar %s[%d];", arg->argPadName, it->itPadSize);
+}
+
+void
+WriteStructDecl(FILE *file, const argument_t *args, write_list_fn_t *func,
+ u_int mask, const char *name)
+{
+ fprintf(file, "\ttypedef struct {\n");
+ fprintf(file, "\t\tmach_msg_header_t Head;\n");
+ WriteList(file, args, func, mask, "\n", "\n");
+ fprintf(file, "\t} %s;\n", name);
+ fprintf(file, "\n");
+}
+
+static void
+WriteStaticLongDecl(FILE *file, register const ipc_type_t *it,
+ dealloc_t dealloc, boolean_t inname, identifier_t name)
+{
+ fprintf(file, "\tstatic const mach_msg_type_long_t %s = {\n", name);
+ fprintf(file, "\t{\n");
+ fprintf(file, "\t\t/* msgt_name = */\t\t0,\n");
+ fprintf(file, "\t\t/* msgt_size = */\t\t0,\n");
+ fprintf(file, "\t\t/* msgt_number = */\t\t0,\n");
+ fprintf(file, "\t\t/* msgt_inline = */\t\t%s,\n",
+ strbool(it->itInLine));
+ fprintf(file, "\t\t/* msgt_longform = */\t\tTRUE,\n");
+ fprintf(file, "\t\t/* msgt_deallocate = */\t\t%s,\n",
+ strdealloc(dealloc));
+ fprintf(file, "\t\t/* msgt_unused = */\t\t0\n");
+ fprintf(file, "\t},\n");
+ fprintf(file, "\t\t/* msgtl_name = */\t%s,\n",
+ inname ? it->itInNameStr : it->itOutNameStr);
+ fprintf(file, "\t\t/* msgtl_size = */\t%d,\n", it->itSize);
+ fprintf(file, "\t\t/* msgtl_number = */\t%d,\n", it->itNumber);
+ fprintf(file, "\t};\n");
+}
+
+static void
+WriteStaticShortDecl(FILE *file, register const ipc_type_t *it,
+ dealloc_t dealloc, boolean_t inname, identifier_t name)
+{
+ fprintf(file, "\tstatic const mach_msg_type_t %s = {\n", name);
+ fprintf(file, "\t\t/* msgt_name = */\t\t%s,\n",
+ inname ? it->itInNameStr : it->itOutNameStr);
+ fprintf(file, "\t\t/* msgt_size = */\t\t%d,\n", it->itSize);
+ fprintf(file, "\t\t/* msgt_number = */\t\t%d,\n", it->itNumber);
+ fprintf(file, "\t\t/* msgt_inline = */\t\t%s,\n",
+ strbool(it->itInLine));
+ fprintf(file, "\t\t/* msgt_longform = */\t\tFALSE,\n");
+ fprintf(file, "\t\t/* msgt_deallocate = */\t\t%s,\n",
+ strdealloc(dealloc));
+ fprintf(file, "\t\t/* msgt_unused = */\t\t0\n");
+ fprintf(file, "\t};\n");
+}
+
+void
+WriteStaticDecl(FILE *file, const ipc_type_t *it, dealloc_t dealloc,
+ boolean_t longform, boolean_t inname, identifier_t name)
+{
+ if (longform)
+ WriteStaticLongDecl(file, it, dealloc, inname, name);
+ else
+ WriteStaticShortDecl(file, it, dealloc, inname, name);
+}
+
+/*
+ * 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, register 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);
+}
+
+void
+WriteCopyType(FILE *file, const ipc_type_t *it, const char *left,
+ const char *right, ...)
+{
+ va_list pvar;
+ va_start(pvar, right);
+
+ if (it->itStruct)
+ {
+ fprintf(file, "\t");
+ SkipVFPrintf(file, left, pvar);
+ fprintf(file, " = ");
+ SkipVFPrintf(file, right, pvar);
+ fprintf(file, ";\n");
+ }
+ else if (it->itString)
+ {
+ fprintf(file, "\t(void) %smig_strncpy(", SubrPrefix);
+ SkipVFPrintf(file, left, pvar);
+ fprintf(file, ", ");
+ SkipVFPrintf(file, right, pvar);
+ fprintf(file, ", %d);\n", it->itTypeSize);
+ }
+ else
+ {
+ fprintf(file, "\t{ typedef struct { char data[%d]; } *sp; * (sp) ",
+ it->itTypeSize);
+ SkipVFPrintf(file, left, pvar);
+ fprintf(file, " = * (sp) ");
+ SkipVFPrintf(file, right, pvar);
+ fprintf(file, "; }\n");
+ }
+ va_end(pvar);
+}
+
+void
+WritePackMsgType(FILE *file, const ipc_type_t *it, dealloc_t dealloc,
+ boolean_t longform, boolean_t inname, const char *left,
+ const char *right, ...)
+{
+ va_list pvar;
+ va_start(pvar, right);
+
+ fprintf(file, "\t");
+ SkipVFPrintf(file, left, pvar);
+ fprintf(file, " = ");
+ SkipVFPrintf(file, right, pvar);
+ fprintf(file, ";\n");
+
+ va_end(pvar);
+}
diff --git a/mig/utils.h b/mig/utils.h
new file mode 100644
index 0000000..3a4c832
--- /dev/null
+++ b/mig/utils.h
@@ -0,0 +1,76 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#ifndef _UTILS_H
+#define _UTILS_H
+
+/* stuff used by more than one of header.c, user.c, server.c */
+
+typedef void write_list_fn_t(FILE *file, const argument_t *arg);
+
+extern void WriteImport(FILE *file, const_string_t filename);
+extern void WriteRCSDecl(FILE *file, identifier_t name, const_string_t rcs);
+extern void WriteBogusDefines(FILE *file);
+
+extern void WriteList(FILE *file, const argument_t *args, write_list_fn_t *func,
+ u_int mask, const char *between, const char *after);
+
+extern void WriteReverseList(FILE *file, const argument_t *args,
+ write_list_fn_t *func, u_int mask,
+ const char *between, const char *after);
+
+/* good as arguments to WriteList */
+extern write_list_fn_t WriteNameDecl;
+extern write_list_fn_t WriteUserVarDecl;
+extern write_list_fn_t WriteServerVarDecl;
+extern write_list_fn_t WriteTypeDeclIn;
+extern write_list_fn_t WriteTypeDeclOut;
+extern write_list_fn_t WriteCheckDecl;
+
+extern const char *ReturnTypeStr(const routine_t *rt);
+
+extern const char *FetchUserType(const ipc_type_t *it);
+extern const char *FetchServerType(const ipc_type_t *it);
+extern void WriteFieldDeclPrim(FILE *file, const argument_t *arg,
+ const char *(*tfunc)(const ipc_type_t *it));
+
+extern void WriteStructDecl(FILE *file, const argument_t *args,
+ write_list_fn_t *func, u_int mask,
+ const char *name);
+
+extern void WriteStaticDecl(FILE *file, const ipc_type_t *it,
+ dealloc_t dealloc, boolean_t longform,
+ boolean_t inname, identifier_t name);
+
+extern void WriteCopyType(FILE *file, const ipc_type_t *it,
+ const char *left, const char *right, ...);
+
+extern void WritePackMsgType(FILE *file, const ipc_type_t *it,
+ dealloc_t dealloc, boolean_t longform,
+ boolean_t inname, const char *left,
+ const char *right, ...);
+
+#endif /* _UTILS_H */
diff --git a/mig/vprint.c b/mig/vprint.c
new file mode 100644
index 0000000..ea66c59
--- /dev/null
+++ b/mig/vprint.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 1990,1992,1993 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#ifndef HAVE_VPRINTF
+
+/*
+ * ansi varargs versions of printf routines
+ * This are directly included to deal with nonansi libc's.
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <limits.h>
+
+/*
+ * Forward declaration.
+ */
+static void _doprnt_ansi(const char *_fmt, va_list _args, FILE *_stream);
+
+int
+vprintf(const char *fmt, va_list args)
+{
+ _doprnt_ansi(fmt, args, stdout);
+ return (ferror(stdout) ? EOF : 0);
+}
+
+int
+vfprintf(FILE *f, const char *fmt, va_list args)
+{
+ _doprnt_ansi(fmt, args, f);
+ return (ferror(f) ? EOF : 0);
+}
+
+int
+vsprintf(char *s, const char *fmt, va_list args)
+{
+ FILE fakebuf;
+
+ fakebuf._flag = _IOSTRG; /* no _IOWRT: avoid stdio bug */
+ fakebuf._ptr = s;
+ fakebuf._cnt = 32767;
+ _doprnt_ansi(fmt, args, &fakebuf);
+ putc('\0', &fakebuf);
+ return (strlen(s));
+}
+
+int
+vsnprintf(char *s, int n, const char *fmt, va_list args)
+{
+ FILE fakebuf;
+
+ fakebuf._flag = _IOSTRG; /* no _IOWRT: avoid stdio bug */
+ fakebuf._ptr = s;
+ fakebuf._cnt = n-1;
+ _doprnt_ansi(fmt, args, &fakebuf);
+ fakebuf._cnt++;
+ putc('\0', &fakebuf);
+ if (fakebuf._cnt<0)
+ fakebuf._cnt = 0;
+ return (n-fakebuf._cnt-1);
+}
+
+/*
+ * Common code for printf et al.
+ *
+ * The calling routine typically takes a variable number of arguments,
+ * and passes the address of the first one. This implementation
+ * assumes a straightforward, stack implementation, aligned to the
+ * machine's wordsize. Increasing addresses are assumed to point to
+ * successive arguments (left-to-right), as is the case for a machine
+ * with a downward-growing stack with arguments pushed right-to-left.
+ *
+ * To write, for example, fprintf() using this routine, the code
+ *
+ * fprintf(fd, format, args)
+ * FILE *fd;
+ * char *format;
+ * {
+ * _doprnt_ansi(format, &args, fd);
+ * }
+ *
+ * would suffice. (This example does not handle the fprintf's "return
+ * value" correctly, but who looks at the return value of fprintf
+ * anyway?)
+ *
+ * This version implements the following printf features:
+ *
+ * %d decimal conversion
+ * %u unsigned conversion
+ * %x hexadecimal conversion
+ * %X hexadecimal conversion with capital letters
+ * %o octal conversion
+ * %c character
+ * %s string
+ * %m.n field width, precision
+ * %-m.n left adjustment
+ * %0m.n zero-padding
+ * %*.* width and precision taken from arguments
+ *
+ * This version does not implement %f, %e, or %g. It accepts, but
+ * ignores, an `l' as in %ld, %lo, %lx, and %lu, and therefore will not
+ * work correctly on machines for which sizeof(long) != sizeof(int).
+ * It does not even parse %D, %O, or %U; you should be using %ld, %o and
+ * %lu if you mean long conversion.
+ *
+ * As mentioned, this version does not return any reasonable value.
+ *
+ * Permission is granted to use, modify, or propagate this code as
+ * long as this notice is incorporated.
+ *
+ * Steve Summit 3/25/87
+ */
+
+/*
+ * Added for general use:
+ * # prefix for alternate format:
+ * 0x (0X) for hex
+ * leading 0 for octal
+ * + print '+' if positive
+ * blank print ' ' if positive
+ *
+ */
+
+/*
+ * Fixed to handle `l' and `h' prefixes, %% format, and ANSI %p format.
+ * It does not handle the ANSI %n format.
+ *
+ * ANSI NOTE: The formating of %d, %o, %u, %x, and %X are not compliant.
+ *
+ * NOTE: Given that this routine uses stdarg.h, I'm not sure that the
+ * comment above about stack layout is valid.
+ *
+ * Peter Stout, 1/11/93
+ */
+
+#define Ctod(c) ((c) - '0')
+
+#define MAXBUF (sizeof(long int) * 8) /* enough for binary */
+
+typedef int boolean_t;
+#define FALSE ((boolean_t) 0)
+#define TRUE ((boolean_t) 1)
+
+#define SHORT sizeof(short)
+#define INT sizeof(int)
+#define LONG sizeof(long)
+
+static void
+_doprnt_ansi(register const char *fmt, va_list args, FILE *stream)
+{
+ int length;
+ int prec;
+ boolean_t ladjust;
+ char padc;
+ long n;
+ unsigned long u;
+ int plus_sign;
+ int sign_char;
+ boolean_t altfmt;
+ int base;
+ int size;
+ unsigned char char_buf[2];
+
+ char_buf[1] = '\0';
+
+ while (*fmt != '\0') {
+ if (*fmt != '%') {
+ putc(*fmt++, stream);
+ continue;
+ }
+
+ fmt++;
+
+ length = 0;
+ prec = -1;
+ ladjust = FALSE;
+ padc = ' ';
+ plus_sign = 0;
+ sign_char = 0;
+ altfmt = FALSE;
+
+ while (TRUE) {
+ if (*fmt == '#') {
+ altfmt = TRUE;
+ fmt++;
+ }
+ else if (*fmt == '-') {
+ ladjust = TRUE;
+ fmt++;
+ }
+ else if (*fmt == '+') {
+ plus_sign = '+';
+ fmt++;
+ }
+ else if (*fmt == ' ') {
+ if (plus_sign == 0)
+ plus_sign = ' ';
+ fmt++;
+ }
+ else
+ break;
+ }
+
+ if (*fmt == '0') {
+ padc = '0';
+ fmt++;
+ }
+
+ if (isdigit(*fmt)) {
+ while(isdigit(*fmt))
+ length = 10 * length + Ctod(*fmt++);
+ }
+ else if (*fmt == '*') {
+ length = va_arg(args, int);
+ fmt++;
+ if (length < 0) {
+ ladjust = !ladjust;
+ length = -length;
+ }
+ }
+
+ if (*fmt == '.') {
+ prec = 0;
+ fmt++;
+ if (isdigit(*fmt)) {
+ prec = 0;
+ while(isdigit(*fmt))
+ prec = 10 * prec + Ctod(*fmt++);
+ }
+ else if (*fmt == '*') {
+ prec = va_arg(args, int);
+ fmt++;
+ }
+ }
+
+ if (*fmt == 'l' || *fmt == 'h')
+ size = *(fmt++) == 'l' ? LONG : SHORT;
+ else
+ size = INT;
+
+ switch(*fmt) {
+ case 'c':
+ {
+ register const char *p;
+ register const char *p2;
+
+ char_buf[0] = va_arg(args, int);
+ p = char_buf;
+ prec = 1;
+ goto put_string;
+
+ case 's':
+ if (prec == -1)
+ prec = INT_MAX;
+
+ p = va_arg(args, char *);
+
+ if (p == (const char *)0)
+ p = "";
+
+ put_string:
+ if (length > 0 && !ladjust) {
+ n = 0;
+ p2 = p;
+
+ for (; *p != '\0' && n < prec; p++)
+ n++;
+
+ p = p2;
+
+ while (n < length) {
+ putc(padc, stream);
+ n++;
+ }
+ }
+
+ n = 0;
+
+ while (*p != '\0') {
+ if (++n > prec)
+ break;
+
+ putc(*p++, stream);
+ }
+
+ if (n < length && ladjust) {
+ while (n < length) {
+ putc(' ', stream);
+ n++;
+ }
+ }
+
+ break;
+ }
+
+ case 'o':
+ base = 8;
+ goto print_unsigned;
+
+ case 'i':
+ case 'd':
+ base = 10;
+ goto print_signed;
+
+ case 'u':
+ base = 10;
+ goto print_unsigned;
+
+ case 'x':
+ case 'X':
+ base = 16;
+ goto print_unsigned;
+
+ case 'p':
+ base = 16;
+ altfmt = TRUE;
+ u = (unsigned long) va_arg(args, void *);
+ goto print_num;
+
+ print_signed:
+ if (size == INT)
+ n = va_arg(args, int);
+ else if (size == LONG)
+ n = va_arg(args, long);
+ else
+ n = (short) va_arg(args, int);
+ if (n >= 0) {
+ u = n;
+ sign_char = plus_sign;
+ }
+ else {
+ u = -n;
+ sign_char = '-';
+ }
+ goto print_num;
+
+ print_unsigned:
+ if (size == INT)
+ u = va_arg(args, unsigned int);
+ else if (size == LONG)
+ u = va_arg(args, unsigned long);
+ else
+ u = (unsigned short) va_arg(args, unsigned int);
+ goto print_num;
+
+ print_num:
+ {
+ char buf[MAXBUF]; /* build number here */
+ register char * p = &buf[MAXBUF-1];
+ static const char digits[] = "0123456789abcdef";
+ const char *prefix = 0;
+
+ if (u != 0 && altfmt) {
+ if (base == 8)
+ prefix = "0";
+ else if (base == 16)
+ prefix = "0x";
+ }
+
+ do {
+ *p-- = digits[u % base];
+ u /= base;
+ } while (u != 0);
+
+ length -= (&buf[MAXBUF-1] - p);
+ if (sign_char)
+ length--;
+ if (prefix)
+ length -= strlen(prefix);
+
+ if (padc == ' ' && !ladjust) {
+ /* blank padding goes before prefix */
+ while (--length >= 0)
+ putc(' ', stream);
+ }
+ if (sign_char)
+ putc(sign_char, stream);
+ if (prefix)
+ while (*prefix)
+ putc(*prefix++, stream);
+ if (padc == '0') {
+ /* zero padding goes after sign and prefix */
+ while (--length >= 0)
+ putc('0', stream);
+ }
+ while (++p != &buf[MAXBUF])
+ putc(*p, stream);
+
+ if (ladjust) {
+ while (--length >= 0)
+ putc(' ', stream);
+ }
+ break;
+ }
+
+ case '%':
+ putc('%', stream);
+ break;
+
+ case '\0':
+ fmt--;
+ break;
+
+ default:
+ putc(*fmt, stream);
+ }
+ fmt++;
+ }
+}
+
+#endif !HAVE_VPRINTF
diff --git a/mig/write.h b/mig/write.h
new file mode 100644
index 0000000..8b481a3
--- /dev/null
+++ b/mig/write.h
@@ -0,0 +1,41 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#ifndef _WRITE_H
+#define _WRITE_H
+
+#include <stdio.h>
+
+#include "statement.h"
+
+extern void WriteUserHeader(FILE *file, const statement_t *stats);
+extern void WriteServerHeader(FILE *file, const statement_t *stats);
+extern void WriteInternalHeader(FILE *file, const statement_t *stats);
+extern void WriteUser(FILE *file, const statement_t *stats);
+extern void WriteUserIndividual(const statement_t *stats);
+extern void WriteServer(FILE *file, const statement_t *stats);
+
+#endif /* _WRITE_H */