MIG type marshaling
itLookUp source
Searches for a named type. We use a simple
self-organizing linked list.
ipc_type_t * itLookUp(identifier_t name) { ipc_type_t *it, **last; for (it = *(last = &list); it != itNULL; it = *(last = &it->itNext)) if (streql(name, it->itName)) { /* move this type to the front of the list */ *last = it->itNext; it->itNext = list; list = it; return it; } return itNULL; }
itInsert source
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; }
itAlloc source
static ipc_type_t * itAlloc(void) { static ipc_type_t prototype = { strNULL, /* identifier_t itName */ 0, /* ipc_type_t *itNext */ 0, /* u_int itTypeSize */ 0, /* u_int itPadSize */ 0, /* u_int itMinTypeSize */ 0, /* u_int itInName */ 0, /* u_int itOutName */ 0, /* u_int itSize */ 1, /* u_int itNumber */ 0, /* u_int itKPD_Number */ TRUE, /* boolean_t itInLine */ FALSE, /* boolean_t itMigInLine */ FALSE, /* boolean_t itPortType */ strNULL, /* string_t itInNameStr */ strNULL, /* string_t itOutNameStr */ TRUE, /* boolean_t itStruct */ FALSE, /* boolean_t itString */ FALSE, /* boolean_t itVarArray */ FALSE, /* boolean_t itNoOptArray */ FALSE, /* boolean_t itNative */ FALSE, /* boolean_t itNativePointer */ itNULL, /* ipc_type_t *itElement */ strNULL, /* identifier_t itUserType */ strNULL, /* identifier_t itServerType */ strNULL, /* identifier_t itTransType */ … more in source
itNameToString source
Convert an IPC type-name into a string.
static char * itNameToString(u_int name) { char buffer[100]; (void) sprintf(buffer, "%u", name); return strmake(buffer); }
itCalculateSizeInfo source
Calculate itTypeSize, itPadSize, itMinTypeSize
Every type needs this info; it is recalculated
when itInLine, itNumber, or itSize changes.
static void itCalculateSizeInfo(ipc_type_t *it) { if (!IS_KERN_PROC_DATA(it)) { u_int bytes = (it->itNumber * it->itSize + 7) / 8; u_int padding = machine_padding(bytes); it->itTypeSize = bytes; it->itPadSize = padding; if (IS_VARIABLE_SIZED_UNTYPED(it)) { /* * for these arrays, the argCount is not a akbRequest|akbReply, * therefore we need to account here for the space of the count * (itMinTypeSize is used only in rtFindSize) */ it->itMinTypeSize = sizeof (mach_msg_type_number_t); /* * NDR encoded VarString carry the extra offset 4-bytes fields * for MIG, it should be always 0; */ if (it->itString) it->itMinTypeSize += sizeof (mach_msg_type_number_t); } else it->itMinTypeSize = bytes + padding; } else { /* * 1) ports 2) OOL 3) ports OOL … more in source
itCalculateNameInfo source
Fill in default values for some fields used in code generation:
itInNameStr, itOutNameStr, itUserType, itServerType, itTransType
Every argument's type should have these values filled in.
static void itCalculateNameInfo(ipc_type_t *it) { if (it->itInNameStr == strNULL) it->itInNameStr = strmake(itNameToString(it->itInName)); if (it->itOutNameStr == strNULL) it->itOutNameStr = strmake(itNameToString(it->itOutName)); if (it->itUserType == strNULL) it->itUserType = it->itName; if (it->itServerType == strNULL) it->itServerType = it->itName; #if 0 /* * KernelServer and KernelUser interfaces get special treatment here. * On the kernel side of the interface, ports are really internal * port pointers (ipc_port_t), not port names (mach_port_t). * At this point, we don't know if the argument is in or out, * so we don't know if we should look at itInName or itOutName. * Looking at both should be OK. * * This is definitely a hack, but I think it is cleaner than * mucking with type declarations throughout the kernel .def files, * hand-conditionalizing on KERNEL_SERVER and KERNEL_USER. */ if (IsKernelServer && streql(it->itServerType, "mach_port_t") && (((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) && (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) || … more in source
itCheckDecl source
****************************************************
Checks for non-implemented types, conflicting type
flags and whether the long or short form of msg type
descriptor is appropriate. Called after each type statement
is parsed.
****************************************************
static void itCheckDecl(identifier_t name, ipc_type_t *it) { it->itName = name; itCalculateNameInfo(it); /* do a bit of error checking, mostly necessary because of limitations in Mig */ if (it->itVarArray) { if ((it->itInTrans != strNULL) || (it->itOutTrans != strNULL)) error("%s: can't translate variable-sized arrays", name); if (it->itDestructor != strNULL) error("%s: can't destroy variable-sized array", name); } }
itPrintTrans source
Pretty-prints translation/destruction/type information.
static void itPrintTrans(ipc_type_t *it) { if (!streql(it->itName, it->itUserType)) printf("\tCUserType:\t%s\n", it->itUserType); if (!streql(it->itName, it->itServerType)) printf("\tCServerType:\t%s\n", it->itServerType); if (it->itInTrans != strNULL) printf("\tInTran:\t\t%s %s(%s)\n", it->itTransType, it->itInTrans, it->itServerType); if (it->itOutTrans != strNULL) printf("\tOutTran:\t%s %s(%s)\n", it->itServerType, it->itOutTrans, it->itTransType); if (it->itDestructor != strNULL) printf("\tDestructor:\t%s(%s)\n", it->itDestructor, it->itTransType); }
itPrintDecl source
Pretty-prints type declarations.
static void itPrintDecl(identifier_t name, ipc_type_t *it) { printf("Type %s = ", name); if (!it->itInLine) printf("^ "); if (it->itVarArray) if (it->itNumber == 0 || it->itMigInLine) printf("array [] of "); else printf("array [*:%d] of ", it->itNumber); else if (it->itStruct && ((it->itNumber != 1) || (it->itInName == MACH_MSG_TYPE_STRING_C))) printf("struct [%d] of ", it->itNumber); else if (it->itNumber != 1) printf("array [%d] of ", it->itNumber); if (streql(it->itInNameStr, it->itOutNameStr)) printf("(%s,", it->itInNameStr); else printf("(%s|%s", it->itInNameStr, it->itOutNameStr); printf(" %d)\n", it->itSize); itPrintTrans(it); printf("\n"); }
itTypeDecl source
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); }
itShortDecl source
Handles declarations like
type new = name;
type new = inname|outname;
ipc_type_t * itShortDecl(u_int inname, string_t instr, u_int outname, string_t outstr, u_int defsize) { ipc_type_t *it; if (defsize == 0) error("must use full IPC type decl"); it = itAlloc(); it->itInName = inname; it->itInNameStr = instr; it->itOutName = outname; it->itOutNameStr = outstr; it->itSize = defsize; if (inname == MACH_MSG_TYPE_STRING_C) { it->itStruct = FALSE; it->itString = TRUE; } /* * I check only inname, because outname * has to be a port as well (polymorphic types * are now restricted to port rights) */ if (MACH_MSG_TYPE_PORT_ANY(inname) || inname == MACH_MSG_TYPE_POLYMORPHIC) { it->itPortType = TRUE; it->itKPD_Number = 1; } … more in source
itCopyType source
static ipc_type_t * itCopyType(ipc_type_t *old) { ipc_type_t *new = itAlloc(); *new = *old; new->itName = strNULL; new->itNext = itNULL; new->itElement = old; /* size info still valid */ return new; }
itResetType source
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; }
itPrevDecl source
Handles the declaration
type new = old;
ipc_type_t * itPrevDecl(identifier_t name) { ipc_type_t *old; old = itLookUp(name); if (old == itNULL) { error("type '%s' not defined", name); return itAlloc(); } else return itCopyType(old); }
itVarArrayDecl source
Handles the declarations
type new = array[] of old; // number is oo
type new = array[*] of old; // number is oo
type new = array[*:number] of old;
ipc_type_t * itVarArrayDecl(u_int number, ipc_type_t *old) { ipc_type_t *it = itResetType(itCopyType(old)); if (!it->itInLine) { /* already an initialized KPD */ if (it->itKPD_Number != 1 || !number) error("IPC type decl is too complicated for Kernel Processed Data"); it->itKPD_Number *= number; it->itNumber = 1; it->itInLine = FALSE; it->itStruct = FALSE; it->itOOL_Number = number; } else if (it->itVarArray) error("IPC type decl is too complicated"); else if (number) { it->itNumber *= number; /* * Bounded [Scalar, Port] VarArray: in-line! */ it->itInLine = TRUE; it->itStruct = FALSE; if (it->itPortType) it->itKPD_Number *= number; it->itOOL_Number = number; } else { it->itNumber = 0; … more in source
itArrayDecl source
Handles the declaration
type new = array[number] of old;
ipc_type_t * itArrayDecl(u_int number, ipc_type_t *old) { ipc_type_t *it = itResetType(itCopyType(old)); if (!it->itInLine) { /* already an initialized KPD */ if (it->itKPD_Number != 1) error("IPC type decl is too complicated for Kernel Processed Data"); it->itKPD_Number *= number; it->itNumber = 1; it->itStruct = FALSE; it->itString = FALSE; it->itVarArray = FALSE; } else if (it->itVarArray) error("IPC type decl is too complicated"); else { it->itNumber *= number; it->itStruct = FALSE; it->itString = FALSE; if (it->itPortType) it->itKPD_Number *= number; } itCalculateSizeInfo(it); return it; }
itPtrDecl source
Handles the declaration
type new = ^ old;
ipc_type_t * itPtrDecl(ipc_type_t *it) { if (!it->itInLine && !it->itMigInLine) error("IPC type decl is already defined to be Out-Of-Line"); it->itInLine = FALSE; it->itStruct = TRUE; it->itString = FALSE; it->itMigInLine = FALSE; it->itKPD_Number = 1; itCalculateSizeInfo(it); return it; }
itStructDecl source
Handles the declaration
type new = struct[number] of old;
ipc_type_t * itStructDecl(u_int number, ipc_type_t *old) { ipc_type_t *it = itResetType(itCopyType(old)); if (!it->itInLine || it->itVarArray) error("IPC type decl is too complicated"); it->itNumber *= number; it->itStruct = TRUE; it->itString = FALSE; itCalculateSizeInfo(it); return it; }
itCStringDecl source
Treat 'c_string[n]' as
'array[n] of (MSG_TYPE_STRING_C, 8)'
ipc_type_t * itCStringDecl(int count, boolean_t varying) { ipc_type_t *it; ipc_type_t *itElement; itElement = itShortDecl(MACH_MSG_TYPE_STRING_C, "MACH_MSG_TYPE_STRING_C", MACH_MSG_TYPE_STRING_C, "MACH_MSG_TYPE_STRING_C", 8); itCheckDecl("char", itElement); it = itResetType(itCopyType(itElement)); it->itNumber = count; it->itVarArray = varying; it->itStruct = FALSE; it->itString = TRUE; itCalculateSizeInfo(it); return it; }
itMakeSubCountType source
extern ipc_type_t * itMakeSubCountType(int count, boolean_t varying, string_t name) { ipc_type_t *it; ipc_type_t *itElement; itElement = itShortDecl(machine_integer_size, machine_integer_name, machine_integer_size, machine_integer_name, machine_integer_bits); itCheckDecl("mach_msg_type_number_t", itElement); it = itResetType(itCopyType(itElement)); it->itNumber = count; /* * I cannot consider it as a Fixed array, otherwise MiG will try * to follow the path for efficient copy of arrays */ it->itVarArray = FALSE; it->itStruct = FALSE; it->itString = FALSE; it->itInLine = TRUE; it->itName = "mach_msg_type_number_t *"; if (varying) it->itVarArray = TRUE; else /* to skip the optimized copy of fixed array: in fact we need to * reference each element and we also miss a user type for it */ it->itNoOptArray = TRUE; itCalculateSizeInfo(it); itCalculateNameInfo(it); return it; … more in source
itMakeCountType source
extern ipc_type_t * itMakeCountType(void) { ipc_type_t *it = itAlloc(); it->itName = "mach_msg_type_number_t"; it->itInName = machine_integer_size; it->itInNameStr = machine_integer_name; it->itOutName = machine_integer_size; it->itOutNameStr = machine_integer_name; it->itSize = machine_integer_bits; itCalculateSizeInfo(it); itCalculateNameInfo(it); return it; }
itMakePolyType source
extern ipc_type_t * itMakePolyType(void) { ipc_type_t *it = itAlloc(); it->itName = "mach_msg_type_name_t"; it->itInName = machine_integer_size; it->itInNameStr = machine_integer_name; it->itOutName = machine_integer_size; it->itOutNameStr = machine_integer_name; it->itSize = machine_integer_bits; itCalculateSizeInfo(it); itCalculateNameInfo(it); return it; }
itMakeDeallocType source
extern ipc_type_t * itMakeDeallocType(void) { ipc_type_t *it = itAlloc(); it->itName = "boolean_t"; it->itInName = MACH_MSG_TYPE_BOOLEAN; it->itInNameStr = "MACH_MSG_TYPE_BOOLEAN"; it->itOutName = MACH_MSG_TYPE_BOOLEAN; it->itOutNameStr = "MACH_MSG_TYPE_BOOLEAN"; it->itSize = machine_integer_bits; itCalculateSizeInfo(it); itCalculateNameInfo(it); return it; }
itNativeType source
extern ipc_type_t * itNativeType(identifier_t id, boolean_t ptr, identifier_t badval) { ipc_type_t *it = itAlloc(); it->itInName = MACH_MSG_TYPE_BYTE; it->itInNameStr = "MACH_MSG_TYPE_BYTE"; it->itOutName = MACH_MSG_TYPE_BYTE; it->itOutNameStr = "MACH_MSG_TYPE_BYTE"; it->itInLine = TRUE; it->itNative = TRUE; it->itNativePointer = ptr; it->itServerType = id; it->itUserType = id; it->itTransType = id; it->itBadValue = badval; itCalculateSizeInfo(it); itCalculateNameInfo(it); return it; }
init_type source
Initializes the pre-defined types.
void init_type(void) { u_int size; size = NBBY * sizeof (natural_t); if (size == 32) { machine_integer_name = "MACH_MSG_TYPE_INTEGER_32"; machine_integer_size = MACH_MSG_TYPE_INTEGER_32; } else if (size == 64) { machine_integer_name = "MACH_MSG_TYPE_INTEGER_64"; machine_integer_size = MACH_MSG_TYPE_INTEGER_64; } else error("init_type unknown size %d", size); machine_integer_bits = size; itRetCodeType = itAlloc(); itRetCodeType->itName = "kern_return_t"; itRetCodeType->itInName = machine_integer_size; itRetCodeType->itInNameStr = machine_integer_name; itRetCodeType->itOutName = machine_integer_size; itRetCodeType->itOutNameStr = machine_integer_name; itRetCodeType->itSize = machine_integer_bits; itCalculateSizeInfo(itRetCodeType); itCalculateNameInfo(itRetCodeType); itNdrCodeType = itAlloc(); … more in source
itCheckReturnType source
****************************************************
Make sure return values of functions are assignable.
****************************************************
void itCheckReturnType(identifier_t name, ipc_type_t *it) { if (!it->itStruct) error("type of %s is too complicated", name); if ((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) || (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) error("type of %s can't be polymorphic", name); }
itCheckRequestPortType source
****************************************************
Called by routine.c to check that request ports are
simple and correct ports with send rights.
****************************************************
void itCheckRequestPortType(identifier_t name, ipc_type_t *it) { /* error("Port size = %d %d name = %s\n", PortSize, it->itSize, it->itName); error("server = %s user = %x\n",it->itServerType, it->itUserType); */ if (((it->itOutName != MACH_MSG_TYPE_PORT_SEND) && (it->itOutName != MACH_MSG_TYPE_PORT_SEND_ONCE) && (it->itOutName != MACH_MSG_TYPE_POLYMORPHIC)) || (it->itNumber != 1) || (it->itSize != PortSize) || !it->itInLine || !it->itStruct || it->itVarArray) error("argument %s isn't a proper request port", name); }
itCheckReplyPortType source
****************************************************
Called by routine.c to check that reply ports are
simple and correct ports with send rights.
****************************************************
void itCheckReplyPortType(identifier_t name, ipc_type_t *it) { if (((it->itOutName != MACH_MSG_TYPE_PORT_SEND) && (it->itOutName != MACH_MSG_TYPE_PORT_SEND_ONCE) && (it->itOutName != MACH_MSG_TYPE_POLYMORPHIC) && (it->itOutName != 0)) || (it->itNumber != 1) || (it->itSize != PortSize) || !it->itInLine || !it->itStruct || it->itVarArray) error("argument %s isn't a proper reply port", name); }
itCheckIntType source
****************************************************
Used by routine.c to check that WaitTime is a
simple bit machine_integer_bits integer.
****************************************************
void itCheckIntType(identifier_t name, ipc_type_t *it) { if ((it->itInName != machine_integer_size) || (it->itOutName != machine_integer_size) || (it->itNumber != 1) || (it->itSize != machine_integer_bits) || !it->itInLine || !it->itStruct || it->itVarArray) error("argument %s isn't a proper integer", name); }
itCheckTokenType source
void itCheckTokenType(identifier_t name, ipc_type_t *it) { if (it->itMigInLine || it->itNoOptArray || it->itString || it->itTypeSize != 8 || !it->itInLine || !it->itStruct || it->itVarArray || it->itPortType) error("argument %s isn't a proper Token", name); }