MIG codegen: user stubs

bootstrap_cmds/migcom.tproj/user.c · 3256 lines · browse source

Emits the user-side RPC stub for each routine: pack arguments into a request message, call mach_msg, then unpack the reply. This is the body behind each MIG routine's C prototype.

WriteKPD_Iterator source
static void
WriteKPD_Iterator(FILE *file, boolean_t in, boolean_t overwrite, boolean_t varying, argument_t *arg, boolean_t bracket)
{
  ipc_type_t *it = arg->argType;
  char string[MAX_STR_LEN];

  fprintf(file, "\t{\n");
  fprintf(file, "\t    %s\t*ptr;\n", it->itKPDType);
  fprintf(file, "\t    int\ti");
  if (varying && !in)
    fprintf(file, ", j");
  fprintf(file, ";\n\n");

  if (in)
    sprintf(string, "InP");
  else if (overwrite)
    sprintf(string, "InOvTemplate");
  else
    sprintf(string, "Out%dP", arg->argRequestPos);

  fprintf(file, "\t    ptr = &%s->%s[0];\n", string, arg->argMsgField);

  if (varying) {
    argument_t *count = arg->argCount;
    char *cref = count->argByReferenceUser ? "*" : "";

    if (in || overwrite) {
      fprintf(file, "\t    if (%s%s > %d)\n", cref, count->argVarName, it->itKPD_Number);
      WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE");
      fprintf(file, "\t    for (i = 0; i < %s%s; ptr++, i++) %s\n", cref, count->argVarName, (bracket) ? "{" : "");
… more in source
WriteMyIncludes source
*********************************************************** Writes the standard includes. The subsystem specific includes are in <SubsystemName>.h and writen by header:WriteHeader. Called by WriteProlog. ***********************************************************
static void
WriteMyIncludes(FILE *file, statement_t *stats)
{
#ifdef MIG_KERNEL_PORT_CONVERSION
  if (IsKernelServer)
  {
    /*
     * We want to get the user-side definitions of types
     * like task_t, ipc_space_t, etc. in mach/mach_types.h.
     */

    fprintf(file, "#undef\tMACH_KERNEL\n");

    if (InternalHeaderFileName != strNULL)
    {
      char *cp;

      /* Strip any leading path from InternalHeaderFileName. */
      cp = strrchr(InternalHeaderFileName, '/');
      if (cp == 0)
        cp = InternalHeaderFileName;
      else
        cp++; /* skip '/' */
      fprintf(file, "#include \"%s\"\n", cp);
    }
  }
#endif

  if (UserHeaderFileName == strNULL || UseSplitHeaders)
    WriteIncludes(file, TRUE, FALSE);
… more in source
WriteGlobalDecls source
static void
WriteGlobalDecls(FILE *file)
{
  if (RCSId != strNULL)
    WriteRCSDecl(file, strconcat(SubsystemName, "_user"), RCSId);

  fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n");
  fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n");
  fprintf(file, "\n");
  if (UseEventLogger)
    WriteLogDefines(file, "MACH_MSG_LOG_USER");
  fprintf(file, "\n");
}
WriteOneMachErrorDefine source
static void
WriteOneMachErrorDefine(FILE *file, char *name, boolean_t timeout, boolean_t SpecialReplyPort)
{
  fprintf(file, "#ifndef\t%s\n", name);
  fprintf(file, "#define\t%s(_R_) { \\\n", name);
  fprintf(file, "\tswitch (_R_) { \\\n");
  fprintf(file, "\tcase MACH_SEND_INVALID_DATA: \\\n");
  fprintf(file, "\tcase MACH_SEND_INVALID_DEST: \\\n");
  fprintf(file, "\tcase MACH_SEND_INVALID_HEADER: \\\n");
  if (!SpecialReplyPort) {
    fprintf(file, "\t\tmig_put_reply_port(InP->Head.msgh_reply_port); \\\n");
  }
  fprintf(file, "\t\tbreak; \\\n");
  if (timeout) {
	  fprintf(file, "\tcase MACH_SEND_TIMED_OUT: \\\n");
	  fprintf(file, "\tcase MACH_RCV_TIMED_OUT: \\\n");
  }
  fprintf(file, "\tdefault: \\\n");
  if (SpecialReplyPort) {
    fprintf(file, "\t\tmig_dealloc_special_reply_port(InP->Head.msgh_reply_port); \\\n");
  } else {
    fprintf(file, "\t\tmig_dealloc_reply_port(InP->Head.msgh_reply_port); \\\n");
  }
  fprintf(file, "\t} \\\n}\n");
  fprintf(file, "#endif\t/* %s */\n", name);
  fprintf(file, "\n");
}
WriteMachErrorDefines source
static void
WriteMachErrorDefines(FILE *file)
{
  WriteOneMachErrorDefine(file, "__MachMsgErrorWithTimeout", TRUE, FALSE);
  WriteOneMachErrorDefine(file, "__MachMsgErrorWithoutTimeout", FALSE, FALSE);
  if (HasUseSpecialReplyPort) {
    WriteOneMachErrorDefine(file, "__MachMsgErrorWithTimeoutSRP", TRUE, TRUE);
    WriteOneMachErrorDefine(file, "__MachMsgErrorWithoutTimeoutSRP", FALSE, TRUE);
  }
}
WriteMIGCheckDefines source
static void
WriteMIGCheckDefines(FILE *file)
{
  fprintf(file, "#define\t__MIG_check__Reply__%s_subsystem__ 1\n", SubsystemName);
  fprintf(file, "\n");
}
WriteNDRDefines source
static void
WriteNDRDefines(FILE *file)
{
  fprintf(file, "#define\t__NDR_convert__Reply__%s_subsystem__ 1\n", SubsystemName);
  fprintf(file, "#define\t__NDR_convert__mig_reply_error_subsystem__ 1\n");
  fprintf(file, "\n");
}
WriteProlog source
*********************************************************** Writes the standard #includes, #defines, and RCS declaration. Called by WriteUser. ***********************************************************
static void
WriteProlog(FILE *file, statement_t *stats)
{
  WriteIdentificationString(file);
  WriteMIGCheckDefines(file);
  if (CheckNDR)
	  WriteNDRDefines(file);
  WriteMyIncludes(file, stats);
  WriteBogusDefines(file);
  WriteMachErrorDefines(file);
  WriteApplDefaults(file, "Send");
  WriteGlobalDecls(file);
}
WriteEpilog source
ARGSUSED
static void
WriteEpilog(FILE *file)
{
  /* nothing to see here, move along... */
}
WriteHeaderPortType source
static string_t
WriteHeaderPortType(argument_t *arg)
{
  if (arg->argType->itInName == MACH_MSG_TYPE_POLYMORPHIC)
    return arg->argPoly->argVarName;
  else
    return arg->argType->itInNameStr;
}
WriteRequestHead source
static void
WriteRequestHead(FILE *file, routine_t *rt)
{
  if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest)
    fprintf(file, "ready_to_send:\n");

  if (rt->rtMaxRequestPos > 0) {
    if (rt->rtOverwrite)
      fprintf(file, "\tInP = &MessRequest;\n");
    else
      fprintf(file, "\tInP = &Mess%sIn;\n", (rtMessOnStack(rt) ? "." : "->"));
  }

  if (akCheck(rt->rtReplyPort->argKind, akbUserArg)) {
#ifdef MIG_KERNEL_PORT_CONVERSION
    if (IsKernelUser)
      fprintf(file, "\tInP->%s = (mach_port_t) %s;\n", rt->rtReplyPort->argMsgField, rt->rtReplyPort->argVarName);
    else
#endif
      fprintf(file, "\tInP->%s = %s;\n", rt->rtReplyPort->argMsgField, rt->rtReplyPort->argVarName);
  }
  else if (rt->rtOneWay)
    fprintf(file, "\tInP->%s = MACH_PORT_NULL;\n", rt->rtReplyPort->argMsgField);
  else if (rt->rtUseSpecialReplyPort)
    fprintf(file, "\tInP->%s = mig_get_special_reply_port();\n", rt->rtReplyPort->argMsgField);
  else
    fprintf(file, "\tInP->%s = mig_get_reply_port();\n", rt->rtReplyPort->argMsgField);

  fprintf(file, "\tInP->Head.msgh_bits =");
  if (rt->rtRetCArg == argNULL && !rt->rtSimpleRequest)
… more in source
WriteVarDecls source
*********************************************************** Writes declarations for the message types, variables and return variable if needed. Called by WriteRoutine. ***********************************************************
static void
WriteVarDecls(FILE *file, routine_t *rt)
{
  int i;

  if (rt->rtOverwrite) {
    fprintf(file, "\tRequest MessRequest;\n");
    fprintf(file, "\tRequest *InP = &MessRequest;\n\n");

    fprintf(file, "\tunion {\n");
    fprintf(file, "\t\tOverwriteTemplate In;\n");
    fprintf(file, "\t\tReply Out;\n");
    fprintf(file, "\t} MessReply;\n");

    fprintf(file, "\tOverwriteTemplate *InOvTemplate = &MessReply.In;\n");
    fprintf(file, "\tReply *Out0P = &MessReply.Out;\n");
    for (i = 1; i <= rt->rtMaxReplyPos; i++)
      fprintf(file, "\t" "Reply *Out%dP = NULL;\n", i);
  }
  else {
    if (rtMessOnStack(rt))
      fprintf(file, "\tunion {\n");
    else
      fprintf(file, "\tunion %sMessU {\n", rt->rtName);
    fprintf(file, "\t\tRequest In;\n");
    if (!rt->rtOneWay)
      fprintf(file, "\t\tReply Out;\n");
    if (rtMessOnStack(rt))
      fprintf(file, "\t} Mess;\n");
    else
… more in source
WriteReturn source
static void
WriteReturn(FILE *file, routine_t *rt, char *before, char *value, char *after, boolean_t deallocate_mess)
{
  if (rtMessOnStack(rt)) {
    if (value != stRetCode) {
      /* get the easy case (no braces needed) out of the way */
      fprintf(file, "%sreturn%s%s;%s", before, (*value ? " " : ""), value, after);
      return;
    }
    else {
      fprintf(file, "%s{\n", before);
      fprintf(file, "%s\treturn Out0P->RetCode;\n%s}%s", before, before, after);
      return;
    }
  }

  if (value == stRetCode) {
    fprintf(file, "%s{\n%s\t%s ReturnValue;\n", before, before, ReturnTypeStr(rt));
    fprintf(file, "%s\tReturnValue = Out0P->RetCode;\n%s\t", before, before);
  }
  else {
    fprintf(file, "%s{ ", before);
  }

  if (deallocate_mess) {
    fprintf(file, "%s((char *) Mess, sizeof(*Mess)); ", MessFreeRoutine);
  }

  if (value == stRetCode)
    fprintf(file, "return ReturnValue;\n%s}%s", before, after);
… more in source
WriteRetCodeArg source
static void
WriteRetCodeArg(FILE *file, routine_t *rt)
{
  if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
    argument_t *arg = rt->rtRetCArg;

    fprintf(file, "\tif (%s) {\n", arg->argVarName);
    fprintf(file, "\t\t((mig_reply_error_t *)InP)->RetCode = %s;\n", arg->argVarName);
    fprintf(file, "\t\t((mig_reply_error_t *)InP)->NDR = NDR_record;\n");
    fprintf(file, "\t\tgoto ready_to_send;\n");
    fprintf(file, "\t}\n\n");
  }
}
WriteMsgCheckForSendErrors source
*********************************************************** Writes the logic to check for a message send timeout, and deallocate any relocated ool data so as not to leak. ***********************************************************
static void
WriteMsgCheckForSendErrors(FILE *file, routine_t *rt)
{
  if (rt->rtConsumeOnSendError != ConsumeOnSendErrorAny && rt->rtWaitTime == argNULL) {
    return;
  }

  if (rt->rtConsumeOnSendError == ConsumeOnSendErrorAny) {
    // other errors mean the kernel consumed some of the rights
    // and we can't possibly know if there's something left to destroy
    fputs("\n"
          "\t"    "if (msg_result == MACH_SEND_INVALID_DEST ||" "\n"
          "\t\t"    "msg_result == MACH_SEND_TIMED_OUT) {" "\n", file);
  } else {
    fputs("\n"
          "\t"    "if (msg_result == MACH_SEND_TIMED_OUT) {" "\n", file);
  }

  if (rt->rtConsumeOnSendError == ConsumeOnSendErrorNone) {
      argument_t  *arg_ptr;

    // iterate over arg list
    for (arg_ptr = rt->rtArgs; arg_ptr != NULL; arg_ptr = arg_ptr->argNext) {

      //  if argument contains ool data
      if (akCheck(arg_ptr->argKind, akbSendKPD) && arg_ptr->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {
        //    generate code to test current arg address vs. address before the msg_send call
        //    if not at the same address, mig_deallocate the argument
        fprintf(file, "\t\t"    "if((vm_offset_t) InP->%s.address != (vm_offset_t) %s)\n",
                arg_ptr->argVarName, arg_ptr->argVarName);
… more in source
WriteMsgSend source
*********************************************************** Writes the send call when there is to be no subsequent receive. Called by WriteRoutine SimpleRoutines ***********************************************************
static void
WriteMsgSend(FILE *file, routine_t *rt)
{
  char *SendSize = "";
  char string[MAX_STR_LEN];

  if (rt->rtNumRequestVar == 0)
    SendSize = "(mach_msg_size_t)sizeof(Request)";
  else
    SendSize = "msgh_size";

  if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
    sprintf(string, "(%s) ? (mach_msg_size_t)sizeof(mig_reply_error_t) : ", rt->rtRetCArg->argVarName);
    SendSize = strconcat(string, SendSize);
  }

  if (IsKernelUser) {
    fprintf(file, "#if\t__MigKernelSpecificCode\n");
    fprintf(file, "\tmsg_result = mach_msg_send_from_kernel(");
    fprintf(file, "&InP->Head, %s);\n", SendSize);
    fprintf(file, "#else\n");
  }
  fprintf(file, "\tmsg_result = mach_msg("
          "&InP->Head, MACH_SEND_MSG|%s%s, %s, 0, MACH_PORT_NULL, %s, MACH_PORT_NULL);\n",
          rt->rtWaitTime !=argNULL ? "MACH_SEND_TIMEOUT|" : "",
          rt->rtMsgOption->argVarName,
          SendSize,
          rt->rtWaitTime != argNULL ? rt->rtWaitTime->argVarName:"MACH_MSG_TIMEOUT_NONE");

  if (IsKernelUser) {
… more in source
WriteMsgCheckReceiveCleanupMigReplyPort source
*********************************************************** Writes to code to check for error returns from receive. Called by WriteMsgSendReceive and WriteMsgRPC ***********************************************************
static void
WriteMsgCheckReceiveCleanupMigReplyPort(FILE *file, routine_t *rt, char *success)
{
  if (!akCheck(rt->rtReplyPort->argKind, akbUserArg))
  {
    /* If we aren't using a user-supplied reply port, then
       deallocate the reply port when it is invalid or
       for TIMED_OUT errors. */
    fprintf(file, "\tif (msg_result != %s) {\n", success);
    if (rt->rtWaitTime != argNULL) {
      fprintf(file, "\t\t__MachMsgErrorWithTimeout%s(msg_result);\n",
        rt->rtUseSpecialReplyPort ? "SRP" : "");
    } else {
      fprintf(file, "\t\t__MachMsgErrorWithoutTimeout%s(msg_result);\n",
        rt->rtUseSpecialReplyPort ? "SRP" : "");
    }
    fprintf(file, "\t}\n");
  }
}
WriteMsgCheckReceive source
static void
WriteMsgCheckReceive(FILE *file, routine_t *rt, char *success)
{
  fprintf(file, "\tif (msg_result != %s) {\n", success);
  WriteReturnMsgError(file, rt, TRUE, argNULL, "msg_result");
  fprintf(file, "\t}\n");
}
WriteMsgSendReceive source
*********************************************************** Writes the send and receive calls and code to check for errors. Normally the rpc code is generated instead although, the subsytem can be compiled with the -R option which will cause this code to be generated. Called by WriteRoutine if UseMsgRPC option is false. ***********************************************************
static void
WriteMsgSendReceive(FILE *file, routine_t *rt)
{
  char *SendSize = "";
  char string[MAX_STR_LEN];

  if (rt->rtNumRequestVar == 0)
    SendSize = "(mach_msg_size_t)sizeof(Request)";
  else
    SendSize = "msgh_size";

  if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
    sprintf(string, "(%s) ? (mach_msg_size_t)sizeof(mig_reply_error_t) : ", rt->rtRetCArg->argVarName);
    SendSize = strconcat(string, SendSize);
  }

  /* IsKernelUser to be done! */
  fprintf(file, "\tmsg_result = mach_msg(&InP->Head, MACH_SEND_MSG|%s%s, %s, 0, ", rt->rtWaitTime != argNULL ? "MACH_SEND_TIMEOUT|" : "", rt->rtMsgOption->argVarName, SendSize);
  fprintf(file, " MACH_PORT_NULL, %s, MACH_PORT_NULL);\n",
#if !USE_IMMEDIATE_SEND_TIMEOUT
          (rt->rtWaitTime != argNULL) ? rt->rtWaitTime->argVarName :
#endif
          "MACH_MSG_TIMEOUT_NONE");
  fprintf(file, "\tif (msg_result != MACH_MSG_SUCCESS)\n");
  WriteReturnMsgError(file, rt, TRUE, argNULL, "msg_result");
  fprintf(file, "\n");

  fprintf(file, "\tmsg_result = mach_msg(&Out0P->Head, MACH_RCV_MSG|%s%s%s, 0, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_local_port, %s, MACH_PORT_NULL);\n",
          rt->rtUserImpl != 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "",
          (rt->rtWaitTime != argNULL && akIdent(rt->rtWaitTime->argKind) == akeWaitTime) ? "MACH_RCV_TIMEOUT|" : "",
… more in source
WriteMsgRPC source
*********************************************************** Writes the rpc call and the code to check for errors. This is the default code to be generated. Called by WriteRoutine for all routine types except SimpleRoutine. ***********************************************************
static void
WriteMsgRPC(FILE *file, routine_t *rt)
{
  char *SendSize = "";
  char string[MAX_STR_LEN];

  if (rt->rtNumRequestVar == 0)
    SendSize = "(mach_msg_size_t)sizeof(Request)";
  else
    SendSize = "msgh_size";

  if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
    sprintf(string, "(%s) ? (mach_msg_size_t)sizeof(mig_reply_error_t) : ", rt->rtRetCArg->argVarName);
    SendSize = strconcat(string, SendSize);
  }

  if (IsKernelUser) {
    fprintf(file, "#if\t(__MigKernelSpecificCode) || (_MIG_KERNELSPECIFIC_CODE_)\n");
    fprintf(file, "\tmsg_result = mach_msg_rpc_from_kernel(&InP->Head, %s, (mach_msg_size_t)sizeof(Reply));\n", SendSize);
    fprintf(file, "#else\n");
  }
  if (rt->rtOverwrite) {
    fprintf(file, "\tmsg_result = mach_msg_overwrite(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_RCV_OVERWRITE|%s%s%s, %s, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, %s, MACH_PORT_NULL, ",
            rt->rtUserImpl != 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "",
            rt->rtWaitTime != argNULL ?
	        (akIdent(rt->rtWaitTime->argKind) == akeWaitTime ? "MACH_SEND_TIMEOUT|MACH_RCV_TIMEOUT|" : "MACH_SEND_TIMEOUT|") : "",
            rt->rtMsgOption->argVarName,
            SendSize,
            rt->rtWaitTime != argNULL? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE");
    fprintf(file, " &InOvTemplate->Head, (mach_msg_size_t)sizeof(OverwriteTemplate));\n");
… more in source
WriteKPD_port source
argKPD_Pack discipline for Port types.
static void
WriteKPD_port(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char *subindex = "";
  char *recast = "";
  char firststring[MAX_STR_LEN];
  char string[MAX_STR_LEN];
  char *ref = arg->argByReferenceUser ? "*" : "";
  ipc_type_t *real_it;

  if (IS_MULTIPLE_KPD(it)) {
    WriteKPD_Iterator(file, TRUE, FALSE, it->itVarArray, arg, TRUE);
    (void)sprintf(firststring, "\t*ptr");
    (void)sprintf(string, "\tptr->");
    subindex = "[i]";
    real_it = it->itElement;
  }
  else {
    (void)sprintf(firststring, "InP->%s", arg->argMsgField);
    (void)sprintf(string, "InP->%s.", arg->argMsgField);
    real_it = it;
  }

#ifdef MIG_KERNEL_PORT_CONVERSION
  if (IsKernelUser && streql(real_it->itUserType, "ipc_port_t"))
    recast = "(mach_port_t)";
#endif
  fprintf(file, "#if\tUseStaticTemplates\n");
  fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
… more in source
WriteKPD_ool_varsize source
static void
WriteKPD_ool_varsize(FILE *file, argument_t *arg, char *who, char *where, boolean_t iscomplex)
{
  ipc_type_t *it = arg->argType;
  argument_t *count;
  char *cref;

  if (iscomplex) {
    it = it->itElement;
    count = arg->argSubCount;
  }
  else
    count = arg->argCount;
  cref = count->argByReferenceUser ? "*" : "";

  /* size has to be expressed in bytes! */
  if (count->argMultiplier > 1 || it->itSize > 8)
    fprintf(file, "\t%s->%s = %s%s%s * %d;\n", who, where, cref, count->argVarName, (iscomplex)? "[i]" : "", count->argMultiplier * it->itSize / 8);
  else
    fprintf(file, "\t%s->%s = %s%s%s;\n", who, where, cref, count->argVarName, (iscomplex)? "[i]" : "");
}
WriteKPD_ool source
argKPD_Pack discipline for out-of-line types.
static void
WriteKPD_ool(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char *ref = arg->argByReferenceUser ? "*" : "";
  char firststring[MAX_STR_LEN];
  char string[MAX_STR_LEN];
  boolean_t VarArray;
  u_int howmany, howbig;
  char *subindex;

  if (IS_MULTIPLE_KPD(it)) {
    WriteKPD_Iterator(file, TRUE, FALSE, it->itVarArray, arg, TRUE);
    (void)sprintf(firststring, "\t*ptr");
    (void)sprintf(string, "\tptr->");
    VarArray = it->itElement->itVarArray;
    howmany = it->itElement->itNumber;
    howbig = it->itElement->itSize;
    subindex = "[i]";
  }
  else {
    (void)sprintf(firststring, "InP->%s", arg->argMsgField);
    (void)sprintf(string, "InP->%s.", arg->argMsgField);
    VarArray = it->itVarArray;
    howmany = it->itNumber;
    howbig = it->itSize;
    subindex = "";
  }

  fprintf(file, "#if\tUseStaticTemplates\n");
… more in source
WriteKPD_oolport source
argKPD_Pack discipline for out-of-line Port types.
static void
WriteKPD_oolport(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char *ref = arg->argByReferenceUser ? "*" : "";
  argument_t *count;
  boolean_t VarArray;
  string_t howstr;
  u_int howmany;
  char *subindex;
  char firststring[MAX_STR_LEN];
  char string[MAX_STR_LEN];

  if (IS_MULTIPLE_KPD(it)) {
    WriteKPD_Iterator(file, TRUE, FALSE, it->itVarArray, arg, TRUE);
    (void)sprintf(firststring, "\t*ptr");
    (void)sprintf(string, "\tptr->");
    VarArray = it->itElement->itVarArray;
    howmany = it->itElement->itNumber;
    howstr = it->itElement->itInNameStr;
    count = arg->argSubCount;
    subindex = "[i]";
  }
  else {
    (void)sprintf(firststring, "InP->%s", arg->argMsgField);
    (void)sprintf(string, "InP->%s.", arg->argMsgField);
    VarArray = it->itVarArray;
    howmany = it->itNumber;
    howstr = it->itInNameStr;
    count = arg->argCount;
… more in source
WriteOverwriteTemplate source
static void
WriteOverwriteTemplate(FILE *file, routine_t *rt)
{
  argument_t *arg;
  char string[MAX_STR_LEN];
  char *subindex = "";
  boolean_t finish = FALSE;

  fprintf(file, "\t/* Initialize the template for overwrite */\n");
  fprintf(file, "\tInOvTemplate->msgh_body.msgh_descriptor_count = %d;\n", rt->rtOverwriteKPDs);
  for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)  {
    ipc_type_t *it = arg->argType;
    char *ref = arg->argByReferenceUser ? "*" : "";
    argument_t *count;
    char *cref;
    boolean_t VarIndex;
    u_int howmany, howbig;

    if (akCheck(arg->argKind, akbOverwrite)) {
      if (arg->argFlags & flOverwrite) {
        if (IS_MULTIPLE_KPD(it)) {
          WriteKPD_Iterator(file, FALSE, TRUE, it->itVarArray, arg, TRUE);
          if (it->itVarArray)
            finish = TRUE;
          sprintf(string, "\tptr->");
          subindex = "[i]";
          count = arg->argSubCount;
          VarIndex = it->itElement->itVarArray;
          howmany = it->itElement->itNumber;
          howbig = it->itElement->itSize;
… more in source
WritePackArgValueNormal source
*********************************************************** Writes code to copy an argument into the request message. Called by WriteRoutine for each argument that is to placed in the request message. ***********************************************************
static void
WritePackArgValueNormal(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char *ref = (arg->argByReferenceUser ||
                        it->itNativePointer) ? "*" : "";

  if (IS_VARIABLE_SIZED_UNTYPED(it) || it->itNoOptArray) {
    if (it->itString) {
      /*
       * Copy variable-size C string with mig_strncpy.
       * Save the string length (+ 1 for trailing 0)
       * in the argument`s count field.
       */
      fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
      fprintf(file, "\tif (mig_strncpy_zerofill != NULL) {\n");
      fprintf(file, "\t\tInP->%s = (%s) mig_strncpy_zerofill(InP->%s, %s, %d);\n", arg->argCount->argMsgField, arg->argCount->argType->itTransType, arg->argMsgField, arg->argVarName, it->itNumber);
      fprintf(file, "\t} else {\n");
      fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");

      fprintf(file, "\t\tInP->%s = (%s) mig_strncpy(InP->%s, %s, %d);\n", arg->argCount->argMsgField, arg->argCount->argType->itTransType, arg->argMsgField, arg->argVarName, it->itNumber);

      fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
      fprintf(file, "\t}\n");
      fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");

      fprintf(file, "\tInP->%sOffset = 0;\n", arg->argMsgField);
    }
    else if (it->itNoOptArray)
      fprintf(file, "\t(void)memcpy((char *) InP->%s, (const char *) %s%s, %d);\n", arg->argMsgField, ref, arg->argVarName, it->itTypeSize);
… more in source
WriteArgSizeVariable source
Calculate the size of a variable-length message field.
static void
WriteArgSizeVariable(FILE *file,  argument_t *arg, ipc_type_t *ptype)
{
  int bsize = ptype->itElement->itTypeSize;
  argument_t *count = arg->argCount;

  if (PackMsg == FALSE) {
    fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize);
    return;
  }

  /* If the base type size of the data field isn`t a multiple of 4,
   we have to round up. */
  if (bsize % itWordAlign != 0)
    fprintf(file, "_WALIGN_");
  fprintf(file, "(");
  if (bsize > 1)
    fprintf(file, "%d * ", bsize);
  if (ptype->itString)
  /* get count from descriptor in message */
    fprintf(file, "InP->%s", count->argMsgField);
  else
  /* get count from argument */
    fprintf(file, "%s%s", count->argByReferenceUser ? "*" : "", count->argVarName);
  fprintf(file, ")");
}
WriteArgSizeOptional source
static void
WriteArgSizeOptional(FILE *file, argument_t *arg, ipc_type_t *ptype)
{
  fprintf(file, "(InP->__Present__%s ? _WALIGNSZ_(%s) : 0)", arg->argVarName, ptype->itUserType);
}
WriteArgSize source
static void
WriteArgSize(FILE *file, argument_t *arg)

{
  ipc_type_t *ptype = arg->argType;

  if (IS_OPTIONAL_NATIVE(ptype))
    WriteArgSizeOptional(file, arg, ptype);
  else
    WriteArgSizeVariable(file, arg, ptype);
}
WriteAdjustMsgSize source
Adjust message size and advance request pointer. Called after packing a variable-length argument that has more arguments following.
static void
WriteAdjustMsgSize(FILE *file, argument_t *arg)
{
  ipc_type_t *ptype = arg->argType;

  /* There are more In arguments.  We need to adjust msgh_size
     and advance InP, so we save the size of the current field
     in msgh_size_delta. */

  fprintf(file, "\tmsgh_size_delta = ");
  WriteArgSize(file, arg);
  fprintf(file, ";\n");

  if (arg->argRequestPos == 0) {
    /* First variable-length argument.  The previous msgh_size value
       is the minimum request size. */

    fprintf(file, "\tmsgh_size = ");
    rtMinRequestSize(file, arg->argRoutine, "Request");
    fprintf(file, " + msgh_size_delta;\n");
  }
  else
    fprintf(file, "\tmsgh_size += msgh_size_delta;\n");

  if (PackMsg == TRUE) {
    fprintf(file, "\tInP = (Request *) ((pointer_t) InP + msgh_size_delta - ");
    if (IS_OPTIONAL_NATIVE(ptype))
      fprintf(file, "_WALIGNSZ_(%s)", ptype->itUserType);
    else
      fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize);
… more in source
WriteFinishMsgSize source
Calculate the size of the message. Called after the last argument has been packed.
static void
WriteFinishMsgSize(FILE *file, argument_t *arg)
{
  /* No more In arguments.  If this is the only variable In
     argument, the previous msgh_size value is the minimum
     request size. */

  if (arg->argRequestPos == 0) {
    fprintf(file, "\tmsgh_size = ");
    rtMinRequestSize(file, arg->argRoutine, "Request");
    fprintf(file, " + (");
    WriteArgSize(file, arg);
    fprintf(file, ");\n");
  }
  else {
    fprintf(file, "\tmsgh_size += ");
    WriteArgSize(file, arg);
    fprintf(file, ";\n");
  }
}
WriteInitializeCount source
static void
WriteInitializeCount(FILE *file, argument_t *arg)
{
  ipc_type_t *ptype = arg->argCInOut->argParent->argType;
  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");
}
WriteRequestArgs source
Generate code to fill in all of the request arguments and their message types.
static void
WriteRequestArgs(FILE *file, routine_t *rt)
{
  argument_t *arg;
  argument_t *lastVarArg;

  /*
   * 1. The Kernel Processed Data
   */
  for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
    if (akCheckAll(arg->argKind, akbSendSnd|akbSendKPD))
      (*arg->argKPD_Pack)(file, arg);

  /*
   * 2. The Data Stream
   */
  lastVarArg = argNULL;
  for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)  {
    /*
     * Adjust message size and advance message pointer if
     * the last request argument was variable-length and the
     * request position will change.
     */
    if (lastVarArg != argNULL &&
        lastVarArg->argRequestPos < arg->argRequestPos) {
      WriteAdjustMsgSize(file, lastVarArg);
      lastVarArg = argNULL;
    }

    if ((akIdent(arg->argKind) == akeCountInOut) &&
… more in source
WriteCheckIdentity source
*********************************************************** Writes code to check that the return msgh_id is correct and that the size of the return message is correct. Called by WriteRoutine. ***********************************************************
static void
WriteCheckIdentity(FILE *file, routine_t *rt)
{
  fprintf(file, "\tif (Out0P->Head.msgh_id != %d) {\n", rt->rtNumber + SubsystemBase + 100);
  fprintf(file, "\t    if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)\n");
  fprintf(file, "\t\t{ return MIG_SERVER_DIED; }\n");
  fprintf(file, "\t    else\n");
  fprintf(file, "\t\t{ return MIG_REPLY_MISMATCH; }\n");
  fprintf(file, "\t}\n");
  fprintf(file, "\n");
  if (!rt->rtSimpleReply)
    fprintf(file, "\tmsgh_simple = !(Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);\n");
  fprintf(file, "#if\t__MigTypeCheck\n");

  if (!rt->rtNoReplyArgs)
    fprintf(file, "\tmsgh_size = Out0P->Head.msgh_size;\n\n");

  if (rt->rtSimpleReply) {
    /* Expecting a simple message.  We can factor out the check for
     * a simple message, since the error reply message is also simple.
     */
    fprintf(file, "\tif ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
    if (rt->rtNoReplyArgs)
      fprintf(file, "\t    (Out0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Reply)))\n");
    else {
      /*
       * We have an error iff:
       * 1) the message size is not the one expected AND
       * 2) the message size is also different from sizeof(mig_reply_error_t)
       *    or the RetCode == KERN_SUCCESSmore in source
WriteRetCodeCheck source
*********************************************************** Write code to generate error handling code if the RetCode argument of a Routine is not KERN_SUCCESS. ***********************************************************
static void
WriteRetCodeCheck(FILE *file, routine_t *rt)
{
  if (rt->rtSimpleReply)
    fprintf(file, "\tif (Out0P->RetCode != KERN_SUCCESS) {\n");
  else
    fprintf(file, "\tif (msgh_simple) {\n");
  if (CheckNDR) {
    fprintf(file, "#ifdef\t__NDR_convert__mig_reply_error_t__defined\n");
    fprintf(file, "\t\t__NDR_convert__mig_reply_error_t((mig_reply_error_t *)Out0P);\n");
    fprintf(file, "#endif\t/* __NDR_convert__mig_reply_error_t__defined */\n");
  }
  fprintf(file, "\t\treturn ((mig_reply_error_t *)Out0P)->RetCode;\n");
  fprintf(file, "\t}\n");
  fprintf(file, "\n");
}

/*
 * argKPD_TypeCheck discipline for Port types.
 */
static void
WriteTCheckKPD_port(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char *tab = "";
  char string[MAX_STR_LEN];
  boolean_t close = FALSE;

  if (IS_MULTIPLE_KPD(it)) {
    WriteKPD_Iterator(file, FALSE, FALSE, FALSE, arg, TRUE);
… more in source
WriteTCheckKPD_port source
argKPD_TypeCheck discipline for Port types.
static void
WriteTCheckKPD_port(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char *tab = "";
  char string[MAX_STR_LEN];
  boolean_t close = FALSE;

  if (IS_MULTIPLE_KPD(it)) {
    WriteKPD_Iterator(file, FALSE, FALSE, FALSE, arg, TRUE);
    (void)sprintf(string, "ptr->");
    tab = "\t";
    close = TRUE;
  }
  else
    (void)sprintf(string, "Out%dP->%s.", arg->argReplyPos, arg->argMsgField);
  fprintf(file, "\t%sif (%stype != MACH_MSG_PORT_DESCRIPTOR", tab, string);
  if (arg->argPoly == argNULL && !it->itVarArray)
  /* we can't check disposition when poly or VarArray,
     (because some of the entries could be empty) */
    fprintf(file, " ||\n\t%s    %sdisposition != %s", tab, string, it->itOutNameStr);
  fprintf(file,
          ") {\n"
          "\t\t%s" "return MIG_TYPE_ERROR;\n"
          "\t%s" "}\n"
        , tab, tab);
  if (close)
    fprintf(file, "\t    }
WriteTCheckKPD_ool source
argKPD_TypeCheck discipline for out-of-line types.
static void
WriteTCheckKPD_ool(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char *tab, string[MAX_STR_LEN];
  boolean_t test;
  u_int howmany, howbig;

  if (IS_MULTIPLE_KPD(it)) {
    WriteKPD_Iterator(file, FALSE, FALSE, FALSE, arg, TRUE);
    tab = "\t";
    sprintf(string, "ptr->");
    howmany = it->itElement->itNumber;
    howbig = it->itElement->itSize;
    test = !it->itVarArray && !it->itElement->itVarArray;
  }
  else {
    tab = "";
    sprintf(string, "Out%dP->%s.", arg->argReplyPos, arg->argMsgField);
    howmany = it->itNumber;
    howbig = it->itSize;
    test = !it->itVarArray;
  }

  fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_DESCRIPTOR", tab, string);
  if (test)
  /* if VarArray we may use no-op; if itElement->itVarArray size might change */
    fprintf(file, " ||\n\t%s    %ssize != %d", tab, string, (howmany * howbig + 7)/8);
  fprintf(file,
          ") {\n"
… more in source
WriteTCheckKPD_oolport source
argKPD_TypeCheck discipline for out-of-line Port types.
static void
WriteTCheckKPD_oolport(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char *tab, string[MAX_STR_LEN];
  boolean_t test;
  u_int howmany;
  char *howstr;

  if (IS_MULTIPLE_KPD(it)) {
    WriteKPD_Iterator(file, FALSE, FALSE, FALSE, arg, TRUE);
    tab = "\t";
    sprintf(string, "ptr->");
    howmany = it->itElement->itNumber;
    test = !it->itVarArray && !it->itElement->itVarArray;
    howstr = it->itElement->itOutNameStr;
  }
  else {
    tab = "";
    sprintf(string, "Out%dP->%s.", arg->argReplyPos, arg->argMsgField);
    howmany = it->itNumber;
    test = !it->itVarArray;
    howstr = it->itOutNameStr;
  }

  fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_PORTS_DESCRIPTOR", tab, string);
  if (test)
    /* if VarArray we may use no-op; if itElement->itVarArray size might change */
    fprintf(file, " ||\n\t%s    %scount != %d", tab, string, howmany);
  if (arg->argPoly == argNULL)
… more in source
WriteTypeCheck source
*********************************************************** Writes code to check that the type of each of the arguments in the reply message is what is expected. Called by WriteRoutine for each out && typed argument in the reply message. ***********************************************************
static void
WriteTypeCheck(FILE *file, argument_t *arg)
{
  fprintf(file, "#if\t__MigTypeCheck\n");
  (*arg->argKPD_TypeCheck)(file, arg);
  fprintf(file, "#endif\t/* __MigTypeCheck */\n");
}
WriteExtractKPD_port source
argKPD_Extract discipline for Port types.
static void
WriteExtractKPD_port(FILE *file,  argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char *ref = arg->argByReferenceUser ? "*" : "";
  char *subindex;
  char *recast = "";
  ipc_type_t *real_it;

  real_it = (IS_MULTIPLE_KPD(it)) ? it->itElement : it;
#ifdef MIG_KERNEL_PORT_CONVERSION
  if (IsKernelUser && streql(real_it->itUserType, "ipc_port_t"))
    recast = "(mach_port_t)";
#endif
  if (IS_MULTIPLE_KPD(it)) {
    WriteKPD_Iterator(file, FALSE, FALSE, it->itVarArray, arg, FALSE);

    fprintf(file, "\t\t%s[i] = %sptr->name;\n", arg->argVarName, recast);
    if (it->itVarArray) {
      argument_t *count = arg->argCount;
      char *cref = count->argByReferenceUser ? "*" : "";

      fprintf(file, "\t    if (Out%dP->%s >",count->argReplyPos, count->argVarName);
      if (arg->argCountInOut) {
        fprintf(file, " %s%s)\n", cref, count->argVarName);
      }
      else {
        fprintf(file, " %d)\n", it->itNumber/it->itElement->itNumber);
      }
      WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE");
… more in source
WriteExtractKPD_ool source
argKPD_Extract discipline for out-of-line types.
static void
WriteExtractKPD_ool(FILE *file, argument_t *arg)
{
  char *ref = arg->argByReferenceUser ? "*" : "";
  ipc_type_t *it = arg->argType;

  if (IS_MULTIPLE_KPD(it)) {
    WriteKPD_Iterator(file, FALSE, FALSE, it->itVarArray, arg, FALSE);
    fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName);
    fprintf(file, "\t}\n");
  }
WriteExtractKPD_oolport source
argKPD_Extract discipline for out-of-line Port types.
static void
WriteExtractKPD_oolport(FILE *file, argument_t *arg)
{
  char *ref = arg->argByReferenceUser ? "*" : "";
  ipc_type_t *it = arg->argType;
  char *subindex;

  if (IS_MULTIPLE_KPD(it)) {
    WriteKPD_Iterator(file, FALSE, FALSE, it->itVarArray, arg, FALSE);
    fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName);
    fprintf(file, "\t}\n");
    subindex = "[0]";
  }
WriteExtractArgValueNormal source
*********************************************************** Write code to copy an argument from the reply message to the parameter. Called by WriteRoutine for each argument in the reply message. ***********************************************************
static void
WriteExtractArgValueNormal(FILE *file, argument_t *arg)
{
  ipc_type_t *argType = arg->argType;
  char *ref = arg->argByReferenceUser ? "*" : "";
  char who[20];

  if (akCheck(arg->argKind, akbUserImplicit))
    sprintf(who, "TrailerP");
  else
    sprintf(who, "Out%dP", arg->argReplyPos);

  if (IS_VARIABLE_SIZED_UNTYPED(argType) || argType->itNoOptArray) {
    if (argType->itString) {
      /*
       * Copy out variable-size C string with mig_strncpy, not the zerofill variant.
       * We don't risk leaking process / kernel memory on this copy-out because
       * we've already zero-filled the buffer on copy-in.
       */
      fprintf(file, "\t(void) mig_strncpy(%s%s, %s->%s, %d);\n", ref, arg->argVarName, who, arg->argMsgField, argType->itNumber);
    }
    else if (argType->itNoOptArray)
      fprintf(file, "\t(void)memcpy((char *) %s%s, (const char *) %s->%s, %d);\n", ref, arg->argVarName, who, arg->argMsgField, argType->itTypeSize);
    else {

      /*
       * Copy out variable-size inline array with (void)memcpy,
       * after checking that number of elements doesn`t
       * exceed user`s maximum.
       */
… more in source
WriteCalcArgSize source
static void
WriteCalcArgSize(FILE *file, argument_t *arg)
{
  ipc_type_t *ptype = arg->argType;
  ipc_type_t *btype = ptype->itElement;
  argument_t *count = arg->argCount;
  int multiplier = btype->itTypeSize;

  /* If the base type size of the data field isn`t a multiple of 4,
     we have to round up. */
  if (btype->itTypeSize % itWordAlign != 0)
    fprintf(file, "_WALIGN_(");

  fprintf(file, "Out%dP->%s", count->argReplyPos, count->argMsgField);
  if (multiplier > 1)
    fprintf(file, " * %d", multiplier);

  if (btype->itTypeSize % itWordAlign != 0)
    fprintf(file, ")");
}
WriteCheckArgSize source
static void
WriteCheckArgSize(FILE *file, routine_t *rt, argument_t *arg, const char *comparator)
{
  ipc_type_t *ptype = arg->argType;
  ipc_type_t *btype = ptype->itElement;
  argument_t *count = arg->argCount;
  int multiplier = btype->itTypeSize;

  fprintf(file, "\tif (((msgh_size - ");
  rtMinReplySize(file, rt, "__Reply");
  fprintf(file, ")");
  if (multiplier > 1)
	  fprintf(file, " / %d", multiplier);
  fprintf(file, "< Out%dP->%s) ||\n", count->argReplyPos, count->argMsgField);
  fprintf(file, "\t    (msgh_size %s ", comparator);
  rtMinReplySize(file, rt, "__Reply");
  fprintf(file, " + ");
  WriteCalcArgSize(file, arg);
  fprintf(file, ")");
  fprintf(file, ")\n\t\t{ return MIG_TYPE_ERROR ; }\n");
}
WriteReplyNDRConvertIntRepArgCond source
NDR Conversion routines
void
WriteReplyNDRConvertIntRepArgCond(FILE *file, argument_t *arg)
{
  routine_t *rt = arg->argRoutine;

  fprintf(file, "defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
}
WriteReplyNDRConvertCharRepArgCond source
void
WriteReplyNDRConvertCharRepArgCond(FILE *file, argument_t *arg)
{
  routine_t *rt = arg->argRoutine;

  if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
    fprintf(file, "defined(__NDR_convert__char_rep__Reply__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
  else
    fprintf(file, "0");
}
WriteReplyNDRConvertFloatRepArgCond source
void
WriteReplyNDRConvertFloatRepArgCond(FILE *file, argument_t *arg)
{
  routine_t *rt = arg->argRoutine;

  if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
    fprintf(file, "defined(__NDR_convert__float_rep__Reply__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
  else
    fprintf(file, "0");
}
WriteReplyNDRConvertIntRepArgDecl source
void
WriteReplyNDRConvertIntRepArgDecl(FILE *file, argument_t *arg)
{
  WriteNDRConvertArgDecl(file, arg, "int_rep", "Reply");
}
WriteReplyNDRConvertCharRepArgDecl source
void
WriteReplyNDRConvertCharRepArgDecl(FILE *file, argument_t *arg)
{
  if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
    WriteNDRConvertArgDecl(file, arg, "char_rep", "Reply");
}
WriteReplyNDRConvertFloatRepArgDecl source
void
WriteReplyNDRConvertFloatRepArgDecl(FILE *file, argument_t *arg)
{
  if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
    WriteNDRConvertArgDecl(file, arg, "float_rep", "Reply");
}
WriteReplyNDRConvertArgUse source
void
WriteReplyNDRConvertArgUse(FILE *file, argument_t *arg, char *convert)
{
  routine_t *rt = arg->argRoutine;
  argument_t *count = arg->argCount;
  char argname[MAX_STR_LEN];

  if ((akIdent(arg->argKind) == akeCount || akIdent(arg->argKind) == akeCountInOut) &&
      (arg->argParent && akCheck(arg->argParent->argKind, akbReturnNdr)))
    return;

  if (arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {
    if (count && !arg->argSameCount && !strcmp(convert, "int_rep")) {
      fprintf(file, "#if defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)\n", rt->rtName, count->argMsgField);
      fprintf(file, "\t\t__NDR_convert__int_rep__Reply__%s_t__%s(&Out%dP->%s, Out%dP->NDR.int_rep);\n", rt->rtName, count->argMsgField, count->argReplyPos, count->argMsgField, count->argReplyPos);
      fprintf(file, "#endif\t/* __NDR_convert__int_rep__Reply__%s_t__%s__defined */\n", rt->rtName, count->argMsgField);
    }

    sprintf(argname, "(%s)(Out%dP->%s.address)", FetchServerType(arg->argType), arg->argReplyPos, arg->argMsgField);
  }
  else {
    sprintf(argname, "&Out%dP->%s", arg->argReplyPos, arg->argMsgField);
  }

  fprintf(file, "#if defined(__NDR_convert__%s__Reply__%s_t__%s__defined)\n", convert, rt->rtName, arg->argMsgField);
  fprintf(file, "\t\t__NDR_convert__%s__Reply__%s_t__%s(%s, Out0P->NDR.%s", convert, rt->rtName, arg->argMsgField, argname, convert);
  if (count)
    fprintf(file, ", Out%dP->%s", count->argReplyPos, count->argMsgField);
  fprintf(file, ");\n");
  fprintf(file, "#endif /* __NDR_convert__%s__Reply__%s_t__%s__defined */\n", convert, rt->rtName, arg->argMsgField);
… more in source
WriteReplyNDRConvertIntRepOneArgUse source
void
WriteReplyNDRConvertIntRepOneArgUse(FILE *file, argument_t *arg)
{
  routine_t *rt = arg->argRoutine;

  fprintf(file, "#if defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)\n", rt->rtName, arg->argMsgField);
  fprintf(file, "\tif (Out0P->NDR.int_rep != NDR_record.int_rep)\n");
  fprintf(file, "\t\t__NDR_convert__int_rep__Reply__%s_t__%s(&Out%dP->%s, Out%dP->NDR.int_rep);\n", rt->rtName, arg->argMsgField, arg->argReplyPos, arg->argMsgField, arg->argReplyPos);
  fprintf(file, "#endif\t/* __NDR_convert__int_rep__Reply__%s_t__%s__defined */\n", rt->rtName, arg->argMsgField);
}
WriteReplyNDRConvertCharRepArgUse source
void
WriteReplyNDRConvertCharRepArgUse(FILE *file, argument_t *arg)
{
  if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
    WriteReplyNDRConvertArgUse(file, arg, "char_rep");
}
WriteReplyNDRConvertFloatRepArgUse source
void
WriteReplyNDRConvertFloatRepArgUse(FILE *file, argument_t *arg)
{
  if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
    WriteReplyNDRConvertArgUse(file, arg, "float_rep");
}
WriteCheckMsgSize source
static void
WriteCheckMsgSize(FILE *file, argument_t *arg)
{
  routine_t *rt = arg->argRoutine;
  ipc_type_t *it = arg->argType;
  ipc_type_t *btype = it->itElement;

  /* If there aren't any more Out args after this, then
     we can use the msgh_size_delta value directly in
     the TypeCheck conditional. */

  if (CheckNDR && arg->argCount && !arg->argSameCount)
    WriteReplyNDRConvertIntRepOneArgUse(file, arg->argCount);

  if (arg->argReplyPos == rt->rtMaxReplyPos) {
    fprintf(file, "#if\t__MigTypeCheck\n");

    /*
     * emit code to verify that the server-code-provided count does not exceed the maximum count allowed by the type.
     */
    fprintf(file, "\t" "if ( Out%dP->%s > %d )\n", arg->argCount->argReplyPos,
	    arg->argCount->argMsgField, it->itNumber/btype->itNumber);
    fputs("\t\t" "return MIG_TYPE_ERROR;\n", file);
    /* ...end... */

    WriteCheckArgSize(file, rt, arg, "!=");

    fprintf(file, "#endif\t/* __MigTypeCheck */\n");
  }
  else {
… more in source
WriteAdjustReplyMsgPtr source
void
WriteAdjustReplyMsgPtr(FILE *file, argument_t *arg)
{
  ipc_type_t *ptype = arg->argType;

  fprintf(file, "\t*Out%dPP = Out%dP = (__Reply *) ((pointer_t) Out%dP + msgh_size_delta - %d);\n\n",
          arg->argReplyPos+1, arg->argReplyPos +1, arg->argReplyPos, ptype->itTypeSize + ptype->itPadSize);
}
WriteReplyArgs source
static void
WriteReplyArgs(FILE *file, routine_t *rt)
{
  argument_t *arg;

  for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
    if (akCheckAll(arg->argKind, akbReturnRcv|akbReturnBody)) {
      WriteExtractArgValueNormal(file, arg);
    }
    else if (akCheckAll(arg->argKind, akbReturnRcv|akbReturnKPD)) {
      /*
       * KPDs have argReplyPos 0, therefore they escape the above logic
       */
      (*arg->argKPD_Extract)(file, arg);
    }
    else if (akCheck(arg->argKind, akbUserImplicit)) {
      WriteExtractArgValueNormal(file, arg);
    }
  }
}
WriteReturnValue source
*********************************************************** Writes code to return the return value. Called by WriteRoutine for routines and functions. ***********************************************************
static void
WriteReturnValue(FILE *file, routine_t *rt)
{
  /* If returning RetCode, we have already checked that it is KERN_SUCCESS */
  WriteReturn(file, rt, "\t", "KERN_SUCCESS", "\n", TRUE);
}
WriteFieldDecl source
*********************************************************** Writes the elements of the message type declaration: the msg_type structure, the argument itself and any padding that is required to make the argument a multiple of 4 bytes. Called by WriteRoutine for all the arguments in the request message first and then the reply message. ***********************************************************
static void
WriteFieldDecl(FILE *file, argument_t *arg)
{
  if (akCheck(arg->argKind, akbSendKPD) ||
      akCheck(arg->argKind, akbReturnKPD))
    WriteFieldDeclPrim(file, arg, FetchKPDType);
  else
    WriteFieldDeclPrim(file, arg, FetchUserType);
}
GetArraySize source
Fill in the string with an expression that refers to the size of the specified array:
static void
GetArraySize(argument_t *arg, char *size)
{
  ipc_type_t *it = arg->argType;

  if (it->itVarArray) {
    if (arg->argCount->argByReferenceUser) {
      sprintf(size, "*%s", arg->argCount->argVarName);
    }
    else
      sprintf(size, "%s", arg->argCount->argVarName);
  }
  else {
    sprintf(size, "%d", (it->itNumber * it->itSize + 7) / 8);
  }
}
WriteRPCPortDisposition source
static void
WriteRPCPortDisposition(FILE *file, argument_t *arg)
{
  /*
   * According to the MIG specification, the port disposition could be different
   * on input and output. If we stay with this then a new bitfield will have
   * to be added. Right now the port disposition is the same for in and out cases.
   */
  switch(arg->argType->itInName) {

    case  MACH_MSG_TYPE_MOVE_RECEIVE:
      fprintf(file, " | MACH_RPC_MOVE_RECEIVE");
      break;

    case  MACH_MSG_TYPE_MOVE_SEND:
      fprintf(file, " | MACH_RPC_MOVE_SEND");
      break;

    case  MACH_MSG_TYPE_MOVE_SEND_ONCE:
      fprintf(file, " | MACH_RPC_MOVE_SEND_ONCE");
      break;

    case  MACH_MSG_TYPE_COPY_SEND:
      fprintf(file, " | MACH_RPC_COPY_SEND");
      break;

    case  MACH_MSG_TYPE_MAKE_SEND:
      fprintf(file, " | MACH_RPC_MAKE_SEND");
      break;
… more in source
WriteRPCArgDescriptor source
static void
WriteRPCArgDescriptor(FILE *file, argument_t *arg, int offset)
{
  fprintf(file, "            {\n                0 ");
  if (RPCPort(arg)) {
    fprintf(file, "| MACH_RPC_PORT ");
    if (arg->argType->itNumber > 1)
      fprintf(file, "| MACH_RPC_ARRAY ");
    if (arg->argType->itVarArray)
      fprintf(file, "| MACH_RPC_VARIABLE ");
    WriteRPCPortDisposition(file, arg);
  }
  else if (RPCPortArray(arg)) {
    fprintf(file, "| MACH_RPC_PORT_ARRAY ");
    if (arg->argType->itVarArray)
      fprintf(file, "| MACH_RPC_VARIABLE ");
    WriteRPCPortDisposition(file, arg);
  }
  else if (RPCFixedArray(arg))
    fprintf(file, "| MACH_RPC_ARRAY_FIXED ");
  else if (RPCVariableArray(arg))
    fprintf(file, "| MACH_RPC_ARRAY_VARIABLE ");
  if (argIsIn(arg))
    fprintf(file, " | MACH_RPC_IN ");
  if (argIsOut(arg))
    fprintf(file, " | MACH_RPC_OUT ");
  if ((! arg->argType->itInLine) && (! arg->argType->itMigInLine))
    fprintf(file, " | MACH_RPC_POINTER ");
  if (arg->argFlags & flDealloc)
    fprintf(file, " | MACH_RPC_DEALLOCATE ");
… more in source
WriteRPCRoutineDescriptor source
void
WriteRPCRoutineDescriptor(FILE *file, routine_t *rt, int arg_count, int descr_count, string_t stub_routine, string_t sig_array)
{
  fprintf(file, "          { (mig_impl_routine_t) 0,\n\
          (mig_stub_routine_t) %s, ", stub_routine);
  fprintf(file, "%d, %d, %s}", arg_count, descr_count, sig_array);
}
WriteRPCRoutineArgDescriptor source
void
WriteRPCRoutineArgDescriptor(FILE *file, routine_t *rt)
{
  argument_t *arg;
  int offset = 0;
  int size = 0;

  for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
    boolean_t compound = arg->argType->itStruct && arg->argType->itInLine;

    if (RPCPort(arg) || RPCPortArray(arg) ||
        RPCFixedArray(arg) || RPCVariableArray(arg)) {
      WriteRPCArgDescriptor(file, arg, offset);
      size = 4;
    }
    if (! size) {
      if (compound)
        size = arg->argType->itNumber * (arg->argType->itSize / 8);
      else
        size = (arg->argType->itSize / 8);
    }
    if (akCheck(arg->argKind, akbServerArg))
      offset += size;
    size = 0;
  }
}
WriteRPCSignature source
static void
WriteRPCSignature(FILE *file, routine_t *rt)
{
  int arg_count = 0;
  int descr_count = 0;

  fprintf(file, "    kern_return_t rtn;\n");
  descr_count = rtCountArgDescriptors(rt->rtArgs, &arg_count);
  fprintf(file, "    const static struct\n    {\n");
  fprintf(file, "        struct rpc_routine_descriptor rd;\n");
  fprintf(file, "        struct rpc_routine_arg_descriptor rad[%d];\n", descr_count);
  fprintf(file, "    } sig =\n    {\n");
  WriteRPCRoutineDescriptor(file, rt, arg_count, descr_count, "0", "sig.rad, 0");
  fprintf(file, ",\n");
  fprintf(file, "        {\n");
  WriteRPCRoutineArgDescriptor(file, rt);
  fprintf(file, "\n        }\n");
  fprintf(file, "\n    };\n\n");
}
WriteRPCCall source
static void
WriteRPCCall(FILE *file, routine_t *rt)
{
  argument_t *arg;
  int i;

  i = 0;
  for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
    if (akIdent(arg->argKind) == akeRequestPort) {
      fprintf(file, "    rtn = (MACH_RPC(&sig, (mach_msg_size_t)sizeof(sig), %d, %s,\n", rt->rtNumber + SubsystemBase, arg->argVarName);
      fprintf(file, "                   (%s", arg->argVarName);
    }
    else if (akCheck(arg->argKind, akbServerArg)) {
      if (i && (i++ % 6 == 0))
        fprintf(file, ",\n                    ");
      else
        fprintf(file, ", ");
      fprintf(file, "%s", arg->argVarName);
    }
  }
  fprintf(file, ")));\n");
  fprintf(file, "\n");
  fprintf(file, "    if (rtn != KERN_NO_ACCESS) return rtn;\n\n");
  fprintf(file, "/* The following message rpc code is generated for the network case */\n\n");
}
CheckRPCCall source
static int
CheckRPCCall(routine_t *rt)
{
  argument_t *arg;
  int i;

  i = 0;
  for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
    if (akCheck(arg->argKind, akbUserArg) &&
        ((arg->argType->itOutName == -1) || (arg->argType->itInName == -1))) {
      return FALSE;
    }
    if (arg->argFlags & flMaybeDealloc) {
      return FALSE;
    }
  }
  return TRUE;
}
WriteRPCRoutine source
static void
WriteRPCRoutine(FILE *file, routine_t *rt)
{
  if (CheckRPCCall(rt)) {
    WriteRPCSignature(file, rt);
    WriteRPCCall(file, rt);
  }
}
WriteShortCircInArgBefore source
Process an IN/INOUT arg before the short-circuited RPC
static void
WriteShortCircInArgBefore(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char size[128];

  fprintf(file, "\n\t/* IN %s: */\n", arg->argVarName);

  if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) {
    switch (arg->argKPD_Type) {

      case MACH_MSG_PORT_DESCRIPTOR:
        break;

      case MACH_MSG_OOL_DESCRIPTOR:
        /* Arg is an out-of-line array: */
        if (!(arg->argFlags & flDealloc) &&
            (!(arg->argFlags & flAuto) || !(arg->argFlags & flConst))) {
          /* Need to map a copy of the array: */
          GetArraySize(arg, size);
          fprintf(file, "\t(void)vm_read(mach_task_self(),\n");
          fprintf(file, "\t\t      (vm_address_t) %s%s, %s, (vm_address_t *) &_%sTemp_, &_MIG_Ignore_Count_);\n", (arg->argByReferenceUser ? "*" : ""), arg->argVarName, size, arg->argVarName);
          /* Point argument at the copy: */
          fprintf(file, "\t*(char **)&%s%s = _%sTemp_;\n", (arg->argByReferenceUser ? "*" : ""), arg->argVarName, arg->argVarName);
        }
        else if ((arg->argFlags & flDealloc) &&
                   ((arg->argFlags & flAuto) || it->itMigInLine)) {
          /* Point the temp var at the original argument: */
          fprintf(file, "\t_%sTemp_ = (char *) %s%s;\n", arg->argVarName, (arg->argByReferenceUser ? "*" : ""), arg->argVarName);
        }
… more in source
WriteShortCircOutArgBefore source
Process an INOUT/OUT arg before the short-circuited RPC
static void
WriteShortCircOutArgBefore(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;

  fprintf(file, "\n\t/* OUT %s: */\n", arg->argVarName);

  if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) {
    switch (arg->argKPD_Type) {

      case MACH_MSG_PORT_DESCRIPTOR:
        break;

      case MACH_MSG_OOL_DESCRIPTOR:
        /* Arg is an out-of-line array: */
        if (!argIsIn(arg) && (arg->argFlags & flOverwrite)) {
          /* Point the temp var at the original argument: */
          fprintf(file, "\t    _%sTemp_ = (char *) %s%s;\n", arg->argVarName, (arg->argByReferenceUser ? "*" : ""), arg->argVarName);
        }
        break;

      case MACH_MSG_OOL_PORTS_DESCRIPTOR:
        break;

      default:
        printf("MiG internal error: type of kernel processed data unknown\n");
        exit(1);
    }   /* end of switch */
  }
  else if (it->itNumber > 1) {
… more in source
WriteShortCircInArgAfter source
Process an IN arg after the short-circuited RPC
static void
WriteShortCircInArgAfter(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char size[128];

  fprintf(file, "\n\t/* IN %s: */\n", arg->argVarName);

  if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) {
    switch (arg->argKPD_Type) {

      case MACH_MSG_PORT_DESCRIPTOR:
        break;

      case MACH_MSG_OOL_DESCRIPTOR:
        /* Arg is an out-of-line array: */
        GetArraySize(arg, size);
        if ((!(arg->argFlags & flAuto) && it->itMigInLine) ||
            ((arg->argFlags & flAuto) &&
             ((arg->argFlags & flDealloc) ||
              !(arg->argFlags & flConst))
             )) {
              /* Need to dealloc the temporary: */
              fprintf(file, "\t(void)vm_deallocate(mach_task_self(),");
          fprintf(file, " (vm_address_t *) _%sTemp_, %s);\n", arg->argVarName, size);
            }
        break;

      case MACH_MSG_OOL_PORTS_DESCRIPTOR:
        break;
… more in source
WriteShortCircOutArgAfter source
static void
WriteShortCircOutArgAfter(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char size[128];

  fprintf(file, "\n\t/* OUT %s: */\n", arg->argVarName);

  if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) {
    switch (arg->argKPD_Type) {

      case MACH_MSG_PORT_DESCRIPTOR:
        break;

      case MACH_MSG_OOL_DESCRIPTOR:
        /* Arg is an out-of-line array: */

        /* Calculate size of array: */
        GetArraySize(arg, size);
        if (!(arg->argFlags & flDealloc) || (arg->argFlags & flOverwrite)) {
          /* Copy argument to vm_allocated Temp: */
          fprintf(file, "\t(void)vm_read(mach_task_self(),\n");
          fprintf(file, "\t\t      (vm_address_t) %s%s, %s, (vm_address_t *) &_%sTemp_, &_MIG_Ignore_Count_);\n", (arg->argByReferenceUser ? "*" : ""), arg->argVarName, size, arg->argVarName);
          if (!argIsIn(arg) && (arg->argFlags & flDealloc) &&
              (arg->argFlags & flOverwrite)) {
            /* Deallocate argument returned by server */
            fprintf(file, "\t(void)vm_deallocate(mach_task_self(),");
            fprintf(file, " (vm_address_t *) %s%s, %s);\n", (arg->argByReferenceUser ? "*" : ""), arg->argVarName, size);
          }
          /* Point argument at new temporary: */
… more in source
WriteShortCircRPC source
static void
WriteShortCircRPC(FILE *file, routine_t *rt)
{
  argument_t *arg;
  int server_argc, i;
  boolean_t ShortCircOkay = TRUE;
  boolean_t first_OOL_arg = TRUE;

  fprintf(file, "    if (0 /* Should be: !(%s & 0x3) XXX */) {\n", rt->rtRequestPort->argVarName);

  if (rt->rtOneWay) {
    /* Do not short-circuit simple routines: */
    ShortCircOkay = FALSE;
  }
  else {
    /* Scan for any types we can't yet handle.  If found, give up on short-
     * circuiting and fall back to mach_msg:
     */
    for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)  {
      if (arg->argFlags & flMaybeDealloc) {
        ShortCircOkay = FALSE;
        break;
      }
      /* Can't yet handle ports: */
      if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD) &&
          (arg->argKPD_Type == MACH_MSG_PORT_DESCRIPTOR ||
           arg->argKPD_Type == MACH_MSG_OOL_PORTS_DESCRIPTOR)) {
            ShortCircOkay = FALSE;
            break;
          }
… more in source
WriteStubDecl source
static void
WriteStubDecl(FILE *file, routine_t *rt)
{
  fprintf(file, "\n");
  fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
  fprintf(file, "mig_external %s %s\n", ReturnTypeStr(rt), rt->rtUserName);
  if (BeAnsiC) {
    fprintf(file, "(\n");
    WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n");
    fprintf(file, ")\n");
  }
  else {
    fprintf(file, "#if\t%s\n", NewCDecl);
    fprintf(file, "(\n");
    WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n");
    fprintf(file, ")\n");
    fprintf(file, "#else\n");
    fprintf(file, "\t(");
    WriteList(file, rt->rtArgs, WriteNameDecl, akbUserArg, ", ", "");
    fprintf(file, ")\n");
    WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ";\n", ";\n");
    fprintf(file, "#endif\t/* %s */\n", NewCDecl);
  }
  fprintf(file, "{\n");
}

static void
InitKPD_Disciplines(argument_t *args)
{
  argument_t *arg;
… more in source
InitKPD_Disciplines source
static void
InitKPD_Disciplines(argument_t *args)
{
  argument_t *arg;
  extern void KPD_noop(FILE *file, argument_t *arg);
  extern void KPD_error(FILE *file, argument_t *arg);
  extern void WriteTemplateKPD_port(FILE *file, argument_t *arg, boolean_t in);
  extern void WriteTemplateKPD_ool(FILE *file, argument_t *arg, boolean_t in);
  extern void WriteTemplateKPD_oolport(FILE *file, argument_t *arg, boolean_t in);

  /*
   * WriteKPD_port,  WriteExtractKPD_port,
   * WriteKPD_ool,  WriteExtractKPD_ool,
   * WriteKPD_oolport,  WriteExtractKPD_oolport
   * are local to this module (which is the reason why this initialization
   * takes place here rather than in utils.c).
   * Common routines for user and server will be established SOON, and
   * all of them (including the initialization) will be transfert to
   * utils.c
   * All the KPD disciplines are defaulted to be KPD_error().
   * Note that akbSendKPD and akbReturnKPd are not exclusive,
   * because of inout type of parameters.
   */
  for (arg = args; arg != argNULL; arg = arg->argNext)
    if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD))
      switch (arg->argKPD_Type) {

        case MACH_MSG_PORT_DESCRIPTOR:
          arg->argKPD_Init = KPD_noop;
          if akCheck(arg->argKind, akbSendKPD) {
… more in source
WriteLimitCheck source
static void
WriteLimitCheck(FILE *file, routine_t *rt)
{
  if (MaxMessSizeOnStack == -1 || UserTypeLimit == -1)
    return;
  if (!rt->rtRequestUsedLimit && !rt->rtReplyUsedLimit)
    return;
  fprintf(file, "#if LimitCheck\n");
  if (rt->rtRequestUsedLimit) {
    if (rt->rtRequestFits) {
      fprintf(file, "\tif ((sizeof(Request) - %d) > %d)\n", rt->rtRequestSizeKnown, UserTypeLimit);
      fprintf(file, "\t    __RequestOnStackAbort(%d, \"%s\");\n", SubsystemBase + rt->rtNumber, rt->rtName);
    }
    else if (rt->rtReplyFits) {
      fprintf(file, "\tif (sizeof(Request) < %d)\n", MaxMessSizeOnStack);
      fprintf(file, "\t    __MessageOffStackNote(%d, \"%s\");\n", SubsystemBase + rt->rtNumber, rt->rtName);
    }
  }
  if (rt->rtReplyUsedLimit) {
    if (rt->rtReplyFits) {
      fprintf(file, "\tif ((sizeof(Reply) - %d) > %d)\n", rt->rtReplySizeKnown, UserTypeLimit);
      fprintf(file, "\t    __ReplyOnStackAbort(%d, \"%s\");\n", SubsystemBase + rt->rtNumber, rt->rtName);
    }
    else if (rt->rtRequestFits) {
      fprintf(file, "\tif (sizeof(Reply) < %d)\n", MaxMessSizeOnStack);
      fprintf(file, "\t    __MessageOffStackNote(%d, \"%s\");\n", SubsystemBase + rt->rtNumber, rt->rtName);
    }
  }
  if (rt->rtRequestUsedLimit && rt->rtReplyUsedLimit &&
      ! (rt->rtRequestFits || rt->rtReplyFits)) {
… more in source
WriteOOLSizeCheck source
static void
WriteOOLSizeCheck(FILE *file, routine_t *rt)
{
  /* Emit code to validate the actual size of ool data vs. the reported size */
  argument_t  *argPtr;
  boolean_t   openedTypeCheckConditional = FALSE;

  // scan through arguments to see if there are any ool data blocks
  for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) {
    if (akCheck(argPtr->argKind, akbReturnKPD)) {
      ipc_type_t *it = argPtr->argType;
      boolean_t multiple_kpd = IS_MULTIPLE_KPD(it);
      char string[MAX_STR_LEN];
      boolean_t test;
      argument_t  *argCountPtr;
      char *tab;

      if (argPtr->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {

        if (multiple_kpd) {
          if ( !openedTypeCheckConditional ) {
            openedTypeCheckConditional = TRUE;
            fputs("#if __MigTypeCheck\n", file);
          }

          WriteKPD_Iterator(file, FALSE, FALSE, FALSE, argPtr, TRUE);
          tab = "\t";
          sprintf(string, "ptr->");
          test = !it->itVarArray && !it->itElement->itVarArray;
          it = it->itElement; // point to element descriptor, so size calculation is correct
… more in source
WriteCheckReply source
static void
WriteCheckReply(FILE *file, routine_t *rt)
{
  int i;

  /* initialize the disciplines for the handling of KPDs */
  InitKPD_Disciplines(rt->rtArgs);

  if (rt->rtOneWay)
    return;

  fprintf(file, "\n");
  fprintf(file, "#if ( __MigTypeCheck ");
  if (CheckNDR)
	  fprintf(file, "|| __NDR_convert__ ");
  fprintf(file, ")\n");
  fprintf(file, "#if __MIG_check__Reply__%s_subsystem__\n", SubsystemName);
  fprintf(file, "#if !defined(__MIG_check__Reply__%s_t__defined)\n", rt->rtName);
  fprintf(file, "#define __MIG_check__Reply__%s_t__defined\n", rt->rtName);
  if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbReply)) {
    WriteList(file, rt->rtArgs, WriteReplyNDRConvertIntRepArgDecl, akbReturnNdr, "\n", "\n");
    WriteList(file, rt->rtArgs, WriteReplyNDRConvertCharRepArgDecl, akbReturnNdr, "\n", "\n");
    WriteList(file, rt->rtArgs, WriteReplyNDRConvertFloatRepArgDecl, akbReturnNdr, "\n", "\n");
  }
  fprintf(file, "\n");
  fprintf(file, "mig_internal kern_return_t __MIG_check__Reply__%s_t(__Reply__%s_t *Out0P", rt->rtName, rt->rtName);
  for (i = 1; i <= rt->rtMaxReplyPos; i++)
    fprintf(file, ", __Reply__%s_t **Out%dPP", rt->rtName, i);
  fprintf(file, ")\n{\n");
… more in source
WriteCheckReplyCall source
static void
WriteCheckReplyCall(FILE *file, routine_t *rt)
{
  int i;

  fprintf(file, "\n");
  fprintf(file, "#if\tdefined(__MIG_check__Reply__%s_t__defined)\n", rt->rtName);
  fprintf(file, "\tcheck_result = __MIG_check__Reply__%s_t((__Reply__%s_t *)Out0P", rt->rtName, rt->rtName);
  for (i = 1; i <= rt->rtMaxReplyPos; i++)
    fprintf(file, ", (__Reply__%s_t **)&Out%dP", rt->rtName, i);
  fprintf(file, ");\n");
  fprintf(file, "\tif (check_result != MACH_MSG_SUCCESS) {\n");
  if (IsKernelUser) {
      fprintf(file, "#if\t__MigKernelSpecificCode\n");
      fprintf(file, "\t\tmach_msg_destroy_from_kernel(&Out0P->Head);\n");
      fprintf(file, "#endif\t/* __MigKernelSpecificCode */\n");
  } else {
      fprintf(file, "\t\tmach_msg_destroy(&Out0P->Head);\n");
  }
  WriteReturnMsgError(file, rt, TRUE, argNULL, "check_result");
  fprintf(file, "\t}\n");
  fprintf(file, "#endif\t/* defined(__MIG_check__Reply__%s_t__defined) */\n", rt->rtName);
  fprintf(file, "\n");
}
WriteCheckReplies source
void
WriteCheckReplies(FILE *file, statement_t *stats)
{
  statement_t *stat;

  for (stat = stats; stat != stNULL; stat = stat->stNext)
    if (stat->stKind == skRoutine)
      WriteCheckReply(file, stat->stRoutine);
}
WriteCheckReplyTrailerArgs source
static void
WriteCheckReplyTrailerArgs(FILE *file, routine_t *rt)
{
  argument_t *arg;

  if (rt->rtUserImpl)
    WriteCheckTrailerHead(file, rt, TRUE);

  for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
    if (akCheck(arg->argKind, akbUserImplicit))
      WriteCheckTrailerSize(file, TRUE, arg);
  }
  if (rt->rtUserImpl)
    fprintf(file, "\n");
}
WriteRoutine source
*********************************************************** Writes all the code comprising a routine body. Called by WriteUser for each routine. ***********************************************************
static void
WriteRoutine(FILE *file, routine_t *rt)
{
  /* write the stub's declaration */
  WriteStubDecl(file, rt);

  /* Use the RPC trap for user-user and user-kernel RPC */
  if (UseRPCTrap)
    WriteRPCRoutine(file, rt);

  /* write the code for doing a short-circuited RPC: */
  if (ShortCircuit)
    WriteShortCircRPC(file, rt);

  /* typedef of structure for Request and Reply messages */
  WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request", rt->rtSimpleRequest, FALSE, FALSE, FALSE);
  if (!rt->rtOneWay) {
    WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply, "Reply", rt->rtSimpleReply, TRUE, rt->rtUserImpl, FALSE);
    WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply, "__Reply", rt->rtSimpleReply, FALSE, FALSE, FALSE);
  }
  if (rt->rtOverwrite)
    WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply|akbOverwrite, "OverwriteTemplate", FALSE, TRUE, FALSE, TRUE);
  /*
   * Define a Minimal Reply structure to be used in case of errors
   */
  fprintf(file, "\t/*\n");
  fprintf(file, "\t * typedef struct {\n");
  fprintf(file, "\t * \tmach_msg_header_t Head;\n");
  fprintf(file, "\t * \tNDR_record_t NDR;\n");
  fprintf(file, "\t * \tkern_return_t RetCode;\n");
… more in source
WriteRPCClientFunctions source
static void
WriteRPCClientFunctions(FILE *file, statement_t *stats)
{
  statement_t *stat;
  char *fname;
  char *argfmt = "(mach_port_t, char *, mach_msg_type_number_t)";

  fprintf(file, "#ifdef AUTOTEST\n");
  for (stat = stats; stat != stNULL; stat = stat->stNext)
    if (stat->stKind == skRoutine) {
      fname = stat->stRoutine->rtName;
      fprintf(file, "extern void client_%s%s;\n", fname, argfmt);
    }
  fprintf(file, "function_table_entry %s_client_functions[] =\n", SubsystemName);
  fprintf(file, "{\n");
  for (stat = stats; stat != stNULL; stat = stat->stNext)
    if (stat->stKind == skRoutine) {
      fname = stat->stRoutine->rtName;
      fprintf(file, "    { \"%s\", client_%s },\n", fname, fname);
    }
  fprintf(file, "    { (char *) 0, (function_ptr_t) 0 }\n");
  fprintf(file, "};\n");
  fprintf(file, "#endif /* AUTOTEST */\n");
}
WriteUser source
*********************************************************** Writes out the xxxUser.c file. Called by mig.c ***********************************************************
void
WriteUser(FILE *file, statement_t *stats)
{
  statement_t *stat;

  WriteProlog(file, stats);
  if (TestRPCTrap)
    WriteRPCClientFunctions(file, stats);
  for (stat = stats; stat != stNULL; stat = stat->stNext)
    switch (stat->stKind) {

      case skRoutine:
        WriteCheckReply(file, stat->stRoutine);
        WriteRoutine(file, stat->stRoutine);
        break;

      case skImport:
      case skUImport:
      case skSImport:
      case skDImport:
      case skIImport:
        break;

      default:
      fatal("WriteUser(): bad statement_kind_t (%d)", (int) stat->stKind);
    }
  WriteEpilog(file);
}
WriteUserIndividual source
*********************************************************** Writes out individual .c user files for each routine. Called by mig.c ***********************************************************
void
WriteUserIndividual(statement_t *stats)
{
  statement_t *stat;

  for (stat = stats; stat != stNULL; stat = stat->stNext)
    switch (stat->stKind) {

      case skRoutine: {
        FILE *file;
        char *filename;

        filename = strconcat(UserFilePrefix, strconcat(stat->stRoutine->rtName, ".c"));
        file = fopen(filename, "w");
        if (file == NULL)
          fatal("fopen(%s): %s", filename, strerror(errno));
        WriteProlog(file, stats);
        WriteRoutine(file, stat->stRoutine);
        WriteEpilog(file);
        fclose(file);
        strfree(filename);
      }
        break;

      case skImport:
      case skUImport:
      case skSImport:
      case skDImport:
      case skIImport:
        break;
… more in source