diff options
author | Thomas Bushnell <thomas@gnu.org> | 1997-04-14 20:29:05 +0000 |
---|---|---|
committer | Thomas Bushnell <thomas@gnu.org> | 1997-04-14 20:29:05 +0000 |
commit | a646a7a564d263b503692fb007bac6a512571793 (patch) | |
tree | bd598587a1f4267e917fa046a5a75f1ff17f2865 /mig/type.c | |
parent | 30b32d2ccbf95436b642e6208d6829dcf68981fa (diff) |
Baseline.
Diffstat (limited to 'mig/type.c')
-rw-r--r-- | mig/type.c | 918 |
1 files changed, 918 insertions, 0 deletions
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); +} |