#include "type.h"
#include <mach/message.h>
#include <mach/ndr.h>
#include "routine.h"
#include "error.h"
#include "alloc.h"
#include "global.h"
#include <stdio.h>
ipc_type_t *itRetCodeType;
ipc_type_t *itNdrCodeType;
ipc_type_t *itDummyType;
ipc_type_t *itTidType;
ipc_type_t *itRequestPortType;
ipc_type_t *itZeroReplyPortType;
ipc_type_t *itRealReplyPortType;
ipc_type_t *itWaitTimeType;
ipc_type_t *itMsgOptionType;
static ipc_type_t *list = itNULL;
ipc_type_t *
itLookUp(name)
identifier_t name;
{
register ipc_type_t *it, **last;
for (it = *(last = &list); it != itNULL; it = *(last = &it->itNext))
if (streql(name, it->itName))
{
*last = it->itNext;
it->itNext = list;
list = it;
return it;
}
return itNULL;
}
void
itInsert(name, it)
identifier_t name;
ipc_type_t *it;
{
it->itName = name;
it->itNext = list;
list = it;
}
static ipc_type_t *
itAlloc()
{
static ipc_type_t prototype =
{
strNULL,
0,
0,
0,
0,
0,
0,
0,
1,
0,
TRUE,
FALSE,
FALSE,
strNULL,
strNULL,
TRUE,
FALSE,
FALSE,
FALSE,
itNULL,
strNULL,
strNULL,
strNULL,
strNULL,
strNULL,
strNULL,
strNULL,
strNULL,
};
register ipc_type_t *new;
new = (ipc_type_t *) malloc(sizeof *new);
if (new == itNULL)
fatal("itAlloc(): %s", strerror(errno));
*new = prototype;
return new;
}
static char *
itNameToString(name)
u_int name;
{
char buffer[100];
(void) sprintf(buffer, "%u", name);
return strmake(buffer);
}
static void
itCalculateSizeInfo(it)
register ipc_type_t *it;
{
if (!IS_KERN_PROC_DATA(it))
{
u_int bytes = (it->itNumber * it->itSize + 7) / 8;
u_int padding = (4 - bytes%4)%4;
it->itTypeSize = bytes;
it->itPadSize = padding;
if (IS_VARIABLE_SIZED_UNTYPED(it)) {
it->itMinTypeSize = 4;
if (it->itString)
it->itMinTypeSize += 4;
} else
it->itMinTypeSize = bytes + padding;
} else {
u_int bytes;
if (IS_MULTIPLE_KPD(it))
bytes = it->itKPD_Number * sizeof(mach_msg_descriptor_t);
else
bytes = sizeof(mach_msg_descriptor_t);
it->itTypeSize = bytes;
it->itPadSize = 0;
it->itMinTypeSize = bytes;
}
if ((it->itTypeSize == 0) && !it->itVarArray)
warn("sizeof(%s) == 0");
}
static void
itCalculateNameInfo(it)
register ipc_type_t *it;
{
if (it->itInNameStr == strNULL)
it->itInNameStr = strmake(itNameToString(it->itInName));
if (it->itOutNameStr == strNULL)
it->itOutNameStr = strmake(itNameToString(it->itOutName));
if (it->itUserType == strNULL)
it->itUserType = it->itName;
if (it->itServerType == strNULL)
it->itServerType = it->itName;
if (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;
}
static void
itCheckDecl(name, it)
identifier_t name;
register ipc_type_t *it;
{
it->itName = name;
itCalculateNameInfo(it);
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);
}
}
static void
itPrintTrans(it)
register ipc_type_t *it;
{
if (!streql(it->itName, it->itUserType))
printf("\tCUserType:\t%s\n", it->itUserType);
if (!streql(it->itName, it->itServerType))
printf("\tCServerType:\t%s\n", it->itServerType);
if (it->itInTrans != strNULL)
printf("\tInTran:\t\t%s %s(%s)\n",
it->itTransType, it->itInTrans, it->itServerType);
if (it->itOutTrans != strNULL)
printf("\tOutTran:\t%s %s(%s)\n",
it->itServerType, it->itOutTrans, it->itTransType);
if (it->itDestructor != strNULL)
printf("\tDestructor:\t%s(%s)\n", it->itDestructor, it->itTransType);
}
static void
itPrintDecl(name, it)
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");
}
void
itTypeDecl(name, it)
identifier_t name;
ipc_type_t *it;
{
itCheckDecl(name, it);
if (BeVerbose)
itPrintDecl(name, it);
}
ipc_type_t *
itShortDecl(inname, instr, outname, outstr, defsize)
u_int inname;
string_t instr;
u_int outname;
string_t outstr;
u_int defsize;
{
register ipc_type_t *it;
if (defsize == 0)
error("must use full IPC type decl");
it = itAlloc();
it->itInName = inname;
it->itInNameStr = instr;
it->itOutName = outname;
it->itOutNameStr = outstr;
it->itSize = defsize;
if (inname == MACH_MSG_TYPE_STRING_C)
{
it->itStruct = FALSE;
it->itString = TRUE;
}
if (MACH_MSG_TYPE_PORT_ANY(inname) ||
inname == MACH_MSG_TYPE_POLYMORPHIC) {
it->itPortType = TRUE;
it->itKPD_Number = 1;
}
itCalculateSizeInfo(it);
return it;
}
static ipc_type_t *
itCopyType(old)
ipc_type_t *old;
{
register ipc_type_t *new = itAlloc();
*new = *old;
new->itName = strNULL;
new->itNext = itNULL;
new->itElement = old;
return new;
}
ipc_type_t *
itResetType(old)
ipc_type_t *old;
{
old->itInTrans = strNULL;
old->itOutTrans = strNULL;
old->itDestructor = strNULL;
old->itUserType = strNULL;
old->itServerType = strNULL;
old->itTransType = strNULL;
return old;
}
ipc_type_t *
itPrevDecl(name)
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);
}
ipc_type_t *
itVarArrayDecl(number, old)
u_int number;
register ipc_type_t *old;
{
register ipc_type_t *it = itResetType(itCopyType(old));
if (!it->itInLine) {
if (it->itKPD_Number != 1 || !number)
error("IPC type decl is too complicated for Kernel Processed Data");
it->itKPD_Number *= number;
it->itNumber = 1;
it->itInLine = FALSE;
it->itStruct = FALSE;
} else if (it->itVarArray)
error("IPC type decl is too complicated");
else if (number) {
it->itNumber *= number;
it->itInLine = TRUE;
it->itStruct = FALSE;
if (it->itPortType)
it->itKPD_Number *= number;
} else {
it->itNumber = 0;
it->itMigInLine = TRUE;
it->itInLine = FALSE;
it->itStruct = TRUE;
it->itKPD_Number = 1;
}
it->itVarArray = TRUE;
it->itString = FALSE;
itCalculateSizeInfo(it);
return it;
}
ipc_type_t *
itArrayDecl(number, old)
u_int number;
ipc_type_t *old;
{
register ipc_type_t *it = itResetType(itCopyType(old));
if (!it->itInLine) {
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;
}
ipc_type_t *
itPtrDecl(it)
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;
}
ipc_type_t *
itStructDecl(number, old)
u_int number;
ipc_type_t *old;
{
register ipc_type_t *it = itResetType(itCopyType(old));
if (!it->itInLine || it->itVarArray)
error("IPC type decl is too complicated");
it->itNumber *= number;
it->itStruct = TRUE;
it->itString = FALSE;
itCalculateSizeInfo(it);
return it;
}
ipc_type_t *
itCStringDecl(count, varying)
int count;
boolean_t varying;
{
register ipc_type_t *it;
register ipc_type_t *itElement;
itElement = itShortDecl(MACH_MSG_TYPE_STRING_C,
"MACH_MSG_TYPE_STRING_C",
MACH_MSG_TYPE_STRING_C,
"MACH_MSG_TYPE_STRING_C",
8);
itCheckDecl("char", itElement);
it = itResetType(itCopyType(itElement));
it->itNumber = count;
it->itVarArray = varying;
it->itStruct = FALSE;
it->itString = TRUE;
itCalculateSizeInfo(it);
return it;
}
extern ipc_type_t *
itMakeSubCountType(count, varying, name)
int count;
boolean_t varying;
string_t name;
{
register ipc_type_t *it;
register ipc_type_t *itElement;
itElement = itShortDecl(MACH_MSG_TYPE_INTEGER_32,
"MACH_MSG_TYPE_INTEGER_32",
MACH_MSG_TYPE_INTEGER_32,
"MACH_MSG_TYPE_INTEGER_32",
32);
itCheckDecl("mach_msg_type_number_t", itElement);
it = itResetType(itCopyType(itElement));
it->itNumber = count;
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
it->itNoOptArray = TRUE;
itCalculateSizeInfo(it);
itCalculateNameInfo(it);
return it;
}
extern ipc_type_t *
itMakeCountType()
{
ipc_type_t *it = itAlloc();
it->itName = "mach_msg_type_number_t";
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;
}
extern ipc_type_t *
itMakePolyType()
{
ipc_type_t *it = itAlloc();
it->itName = "mach_msg_type_name_t";
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;
}
extern ipc_type_t *
itMakeDeallocType()
{
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;
}
void
init_type()
{
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);
itNdrCodeType = itAlloc();
itNdrCodeType->itName = "NDR_record_t";
itNdrCodeType->itInName = 0;
itNdrCodeType->itInNameStr = "NDR_record_t";
itNdrCodeType->itOutName = 0;
itNdrCodeType->itOutNameStr = "NDR_record_t";
itNdrCodeType->itSize = sizeof(NDR_record_t) * 8;
itCalculateSizeInfo(itNdrCodeType);
itCalculateNameInfo(itNdrCodeType);
itDummyType = itAlloc();
itDummyType->itName = "char *";
itDummyType->itInName = MACH_MSG_TYPE_UNSTRUCTURED;
itDummyType->itInNameStr = "MACH_MSG_TYPE_UNSTRUCTURED";
itDummyType->itOutName = MACH_MSG_TYPE_UNSTRUCTURED;
itDummyType->itOutNameStr = "MACH_MSG_TYPE_UNSTRUCTURED";
itDummyType->itSize = 32;
itCalculateSizeInfo(itDummyType);
itCalculateNameInfo(itDummyType);
itTidType = itAlloc();
itTidType->itName = "tid_t";
itTidType->itInName = MACH_MSG_TYPE_INTEGER_32;
itTidType->itInNameStr = "MACH_MSG_TYPE_INTEGER_32";
itTidType->itOutName = MACH_MSG_TYPE_INTEGER_32;
itTidType->itOutNameStr = "MACH_MSG_TYPE_INTEGER_32";
itTidType->itSize = 32;
itTidType->itNumber = 6;
itCalculateSizeInfo(itTidType);
itCalculateNameInfo(itTidType);
itRequestPortType = itAlloc();
itRequestPortType->itName = "mach_port_t";
itRequestPortType->itInName = MACH_MSG_TYPE_COPY_SEND;
itRequestPortType->itInNameStr = "MACH_MSG_TYPE_COPY_SEND";
itRequestPortType->itOutName = MACH_MSG_TYPE_PORT_SEND;
itRequestPortType->itOutNameStr = "MACH_MSG_TYPE_PORT_SEND";
itRequestPortType->itSize = 32;
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 = 32;
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 = 32;
itCalculateSizeInfo(itRealReplyPortType);
itCalculateNameInfo(itRealReplyPortType);
itWaitTimeType = itMakeCountType();
itMsgOptionType = itMakeCountType();
}
void
itCheckReturnType(name, it)
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);
}
void
itCheckRequestPortType(name, it)
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->itNumber != 1) ||
(it->itSize != 32) ||
!it->itInLine ||
!it->itStruct ||
it->itVarArray)
error("argument %s isn't a proper request port", name);
}
void
itCheckReplyPortType(name, it)
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 != 32) ||
!it->itInLine ||
!it->itStruct ||
it->itVarArray)
error("argument %s isn't a proper reply port", name);
}
void
itCheckIntType(name, it)
identifier_t name;
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->itStruct ||
it->itVarArray)
error("argument %s isn't a proper integer", name);
}
void
itCheckSecTokenType(name, it)
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 SecToken", name);
}