MIG codegen: server demux

bootstrap_cmds/migcom.tproj/server.c · 2940 lines · browse source

Emits the server-side demultiplexer: decode an incoming request message, dispatch to the handler you implement, and pack the reply message.

WriteKPD_Iterator source
static void
WriteKPD_Iterator(FILE *file, boolean_t in, 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, "%s", arg->argInSegment);
  else
    sprintf(string, "%s", arg->argOutSegment);

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

  if (varying) {
    argument_t *count = arg->argCount;

    if (in)
      fprintf(file, "\t    for (i = 0; i < %s->%s; ptr++, i++) %s\n", count->argInSegment, count->argMsgField, (bracket) ? "{" : "");
    else {
      fprintf(file, "\t    j = min(%d, ", it->itKPD_Number);
      if (akCheck(count->argKind, akbVarNeeded))
        fprintf(file, "%s);\n", count->argName);
      else
… more in source
WriteMyIncludes source
static void
WriteMyIncludes(FILE *file, statement_t *stats)
{
  if (ServerHeaderFileName == strNULL || UseSplitHeaders)
    WriteIncludes(file, FALSE, FALSE);
  if (ServerHeaderFileName != strNULL)
  {
    char *cp;

    /* Strip any leading path from ServerHeaderFileName. */
    cp = strrchr(ServerHeaderFileName, '/');
    if (cp == 0)
      cp = ServerHeaderFileName;
    else
      cp++;       /* skip '/' */
    fprintf(file, "#include \"%s\"\n", cp);
  }
  if (ServerHeaderFileName == strNULL || UseSplitHeaders)
    WriteImplImports(file, stats, FALSE);
  if (UseEventLogger) {
    if (IsKernelServer) {
      fprintf(file, "#if\t__MigKernelSpecificCode\n");
      fprintf(file, "#include <mig_debug.h>\n");
      fprintf(file, "#endif\t/* __MigKernelSpecificCode */\n");
    }
    fprintf(file, "#if  MIG_DEBUG\n");
    fprintf(file, "#include <mach/mig_log.h>\n");
    fprintf(file, "#endif /* MIG_DEBUG */\n");
  }
… more in source
WriteGlobalDecls source
static void
WriteGlobalDecls(FILE *file)
{
  if (BeAnsiC) {
    fprintf(file, "#define novalue void\n");
  }
  else {
    fprintf(file, "#if\t%s\n", NewCDecl);
    fprintf(file, "#define novalue void\n");
    fprintf(file, "#else\n");
    fprintf(file, "#define novalue int\n");
    fprintf(file, "#endif\t/* %s */\n", NewCDecl);
  }
  fprintf(file, "\n");

  if (RCSId != strNULL)
    WriteRCSDecl(file, strconcat(SubsystemName, "_server"), RCSId);

  /* Used for locations in the request message, *not* reply message.
   Reply message locations aren't dependent on IsKernelServer. */

  if (IsKernelServer) {
    fprintf(file, "#if\t__MigKernelSpecificCode\n");
    fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n");
    fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)");
    fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n");
    fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n");
    fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)");
    fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n");
    fprintf(file, "#else\n");
… more in source
WriteForwardDeclarations source
static void
WriteForwardDeclarations(FILE *file, statement_t *stats)
{
  statement_t *stat;

  fprintf(file, "/* Forward Declarations */\n\n");
  for (stat = stats; stat != stNULL; stat = stat->stNext)
    if (stat->stKind == skRoutine) {
      fprintf(file, "\nmig_internal novalue _X%s\n", stat->stRoutine->rtName);
      if (!UseMachMsg2) {
        fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);\n");
      } else {
        fprintf(file, "\t(mach_msg_header_t *InHeadP, void *InDataP, mach_msg_max_trailer_t *InTrailerP, "
          "mach_msg_header_t *OutHeadP, void *OutDataP);\n");
      }
    }
  fprintf(file, "\n");
}
WriteMIGCheckDefines source
static void
WriteMIGCheckDefines(FILE *file)
{
   fprintf(file, "#define\t__MIG_check__Request__%s_subsystem__ 1\n", SubsystemName);
   fprintf(file, "\n");
}
WriteNDRDefines source
static void
WriteNDRDefines(FILE *file)
{
   fprintf(file, "#define\t__NDR_convert__Request__%s_subsystem__ 1\n", SubsystemName);
   fprintf(file, "\n");
}
WriteProlog source
static void
WriteProlog(FILE *file, statement_t *stats)
{
  WriteIdentificationString(file);
  fprintf(file, "\n");
  fprintf(file, "/* Module %s */\n", SubsystemName);
  fprintf(file, "\n");
  WriteMIGCheckDefines(file);
  if (CheckNDR)
	  WriteNDRDefines(file);
  WriteMyIncludes(file, stats);
  WriteBogusDefines(file);
  WriteApplDefaults(file, "Rcv");
  WriteGlobalDecls(file);
  if (ServerHeaderFileName == strNULL) {
    WriteRequestTypes(file, stats);
    WriteReplyTypes(file, stats);
    WriteServerReplyUnion(file, stats);
  }
}
WriteSymTabEntries source
static void
WriteSymTabEntries(FILE *file, statement_t *stats)
{
  statement_t *stat;
  u_int current = 0;

  for (stat = stats; stat != stNULL; stat = stat->stNext)
    if (stat->stKind == skRoutine) {
      int num = stat->stRoutine->rtNumber;
      char  *name = stat->stRoutine->rtName;
      while (++current <= num)
        fprintf(file,"\t\t\t{ \"\", 0, 0 },\n");
      fprintf(file, "\t{ \"%s\", %d, _X%s },\n", name, SubsystemBase + current - 1, name);
    }
  while (++current <= rtNumber)
    fprintf(file,"\t{ \"\", 0, 0 },\n");
}
WriteRoutineEntries source
static void
WriteRoutineEntries(FILE *file, statement_t *stats)
{
  u_int current = 0;
  statement_t *stat;
  char *sig_array, *rt_name;
  int arg_count, descr_count;
  int offset = 0;
  size_t serverSubsysNameLen = strlen(ServerSubsys);
  char *kern_ = UseMachMsg2 ? "kern_" : "";

  fprintf(file, "\t{\n");
  for (stat = stats; stat != stNULL; stat = stat->stNext)
    if (stat->stKind == skRoutine) {
      routine_t *rt = stat->stRoutine;
      size_t       rtNameLen = strlen(rt->rtName);

      if (MaxServerReplyDescrs >= 0 && rt->rtReplyKPDs > MaxServerReplyDescrs) {
        fatal("WriteRoutine(): method %s uses %d reply descriptors (larger than %d)",
          rt->rtName, rt->rtReplyKPDs, MaxServerReplyDescrs);
      }
      if (MaxServerDescrs >= 0 && rt->rtRequestKPDs > MaxServerDescrs) {
        fatal("WriteRoutine(): method %s uses %d descriptors (larger than %d)",
          rt->rtName, rt->rtRequestKPDs, MaxServerDescrs);
      }

      // Include length of rt->rtName in calculation of necessary buffer size, since that string
      // is actually written into the buffer along with the Server Subsystem name.
      sig_array = (char *) malloc(serverSubsysNameLen + rtNameLen + 80);
      rt_name = (char *) malloc(rtNameLen + 5);
… more in source
WriteArgDescriptorEntries source
static void
WriteArgDescriptorEntries(FILE *file, statement_t *stats)
{
  statement_t *stat;

  fprintf(file, ",\n\n\t{\n");
  for (stat = stats; stat != stNULL; stat = stat->stNext)
    if (stat->stKind == skRoutine) {
      routine_t *rt = stat->stRoutine;

      /* For each arg of the routine, write an arg descriptor:
       */
      WriteRPCRoutineArgDescriptor(file, rt);
    }
  fprintf(file, "\t},\n\n");
}
WriteSubsystem source
Write out the description of this subsystem, for use in direct RPC
static void
WriteSubsystem(FILE *file, statement_t *stats)
{
  statement_t *stat;
  int descr_count = 0;
  char *kern_ = "";
  char *k = "";
  char *kernel = "";

  if (UseMachMsg2) {
    kern_ = "kern_";
    k = "k";
    kernel = "kernel ";
  }

  for (stat = stats; stat != stNULL; stat = stat->stNext)
    if (stat->stKind == skRoutine) {
      routine_t *rt = stat->stRoutine;
      descr_count += rtCountArgDescriptors(rt->rtArgs, (int *) 0);
    }
  fprintf(file, "\n");
  if (ServerHeaderFileName == strNULL) {
    WriteMigExternal(file);
    fprintf(file, "boolean_t %s(", ServerDemux);
    if (BeAnsiC) {
      fprintf(file, "\n\t\tmach_msg_header_t *InHeadP,");
      if (!UseMachMsg2) {
        fprintf(file, "\n\t\tmach_msg_header_t *OutHeadP");
      } else {
        fprintf(file, "\n\t\tvoid *InDataP,");
… more in source
WriteArraySizes source
static void
WriteArraySizes(FILE *file, statement_t *stats)
{
  u_int current = 0;
  statement_t *stat;

  for (stat = stats; stat != stNULL; stat = stat->stNext)
    if (stat->stKind == skRoutine) {
      routine_t *rt = stat->stRoutine;

      while (current++ < rt->rtNumber)
        fprintf(file, "\t\t0,\n");
      fprintf(file, "\t\t(mach_msg_size_t)sizeof(__Reply__%s_t),\n", rt->rtName);
    }
  while (current++ < rtNumber)
    fprintf(file, "\t\t\t0,\n");
}
WriteServerRequestUnion source
NOT_CURRENTLY_USED
void
WriteServerRequestUnion(FILE *file, statement_t *stats)
{
  statement_t *stat;

  fprintf(file, "\n");
  fprintf(file, "/* union of all requests */\n\n");
  fprintf(file, "#ifndef __RequestUnion__%s__defined\n", ServerSubsys);
  fprintf(file, "#define __RequestUnion__%s__defined\n", ServerSubsys);
  fprintf(file, "union __RequestUnion__%s {\n", ServerSubsys);
  for (stat = stats; stat != stNULL; stat = stat->stNext) {
    if (stat->stKind == skRoutine) {
      routine_t *rt;

      rt = stat->stRoutine;
      fprintf(file, "\t__Request__%s_t Request_%s;\n", rt->rtName, rt->rtName);
    }
  }
  fprintf(file, "};\n");
  fprintf(file, "#endif /* __RequestUnion__%s__defined */\n", ServerSubsys);
}
WriteServerReplyUnion source
void
WriteServerReplyUnion(FILE *file, statement_t *stats)
{
  statement_t *stat;

  fprintf(file, "\n");
  fprintf(file, "/* union of all replies */\n\n");
  fprintf(file, "#ifndef __ReplyUnion__%s__defined\n", ServerSubsys);
  fprintf(file, "#define __ReplyUnion__%s__defined\n", ServerSubsys);
  fprintf(file, "union __ReplyUnion__%s {\n", ServerSubsys);
  for (stat = stats; stat != stNULL; stat = stat->stNext) {
    if (stat->stKind == skRoutine) {
      routine_t *rt;

      rt = stat->stRoutine;
      fprintf(file, "\t__Reply__%s_t Reply_%s;\n", rt->rtName, rt->rtName);
    }
  }
  fprintf(file, "};\n");
  fprintf(file, "#endif /* __ReplyUnion__%s__defined */\n", ServerSubsys);
}
WriteDispatcher source
static void
WriteDispatcher(FILE *file, statement_t *stats)
{
  char *k = "";
  char *kern_ = "";

  if (UseMachMsg2) {
    k = "k";
    kern_ = "kern_";
  }

  /*
   * Write the subsystem stuff.
   */
  fprintf(file, "\n");
  WriteSubsystem(file, stats);

  /*
   * Then, the server routine
   */
  fprintf(file, "mig_external boolean_t %s\n", ServerDemux);
  if (BeAnsiC) {
    if (!UseMachMsg2) {
      fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
    } else {
      fprintf(file, "\t(mach_msg_header_t *InHeadP, void *InDataP, mach_msg_max_trailer_t *InTrailerP,"
        " mach_msg_header_t *OutHeadP, void *OutDataP)\n");
    }
  }
  else {
… more in source
ServerSideType source
Returns the return type of the server-side work function. Suitable for "extern %s serverfunc()".
static char *
ServerSideType(routine_t *rt)
{
  return rt->rtRetCode->argType->itTransType;
}
WriteRetCode source
NOT_CURRENTLY_USED
static void
WriteRetCode(FILE *file, argument_t *ret)
{
  ipc_type_t *it = ret->argType;

  if (akCheck(ret->argKind, akbVarNeeded)) {
    fprintf(file, "\t%s %s;\n", it->itTransType, ret->argVarName);
  }
}
WriteLocalVarDecl source
static void
WriteLocalVarDecl(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  ipc_type_t *btype = it->itElement;

  if (IS_VARIABLE_SIZED_UNTYPED(it))
    fprintf(file, "\t%s %s[%d]", btype->itTransType, arg->argVarName, btype->itNumber ? it->itNumber/btype->itNumber : 0);
  else if (IS_MULTIPLE_KPD(it)) {
    if (btype->itTransType != strNULL)
      fprintf(file, "\t%s %s[%d]", btype->itTransType, arg->argVarName, it->itKPD_Number);
    else
    /* arrays of ool or oolport */
      fprintf(file, "\tvoid *%s[%d]", arg->argVarName, it->itKPD_Number);
  }
  else
    fprintf(file, "\t%s %s", it->itTransType, arg->argVarName);
}
WriteServerArgDecl source
static void
WriteServerArgDecl(FILE *file, argument_t *arg)
{
  fprintf(file, "%s %s%s", arg->argType->itTransType, arg->argByReferenceServer ? "*" : "", arg->argVarName);
}
WriteVarDecls source
Writes the local variable declarations which are always present: InP, OutP, the server-side work function.
static void
WriteVarDecls(FILE *file, routine_t *rt)
{
  int i;

  if (!UseMachMsg2) {
    fprintf(file, "\tRequest *In0P = (Request *) InHeadP;\n");
    for (i = 1; i <= rt->rtMaxRequestPos; i++)
      fprintf(file, "\tRequest *In%dP;\n", i);
    fprintf(file, "\tReply *OutP = (Reply *) OutHeadP;\n");
  } else {
    fprintf(file, "\tRequestK *InKP = (RequestK *) InHeadP;\n");
    fprintf(file, "\tRequestU *In0UP = (RequestU *) InDataP;\n");
    for (i = 1; i <= rt->rtMaxRequestPos; i++)
      fprintf(file, "\tRequestU *In%dUP;\n", i);
    fprintf(file, "\tReplyK *OutKP = (ReplyK *) OutHeadP;\n");
    fprintf(file, "\tReplyU *OutUP = (ReplyU *) OutDataP;\n");
    fprintf(file, "\t(void)OutUP;\n");
  }

  /* if reply is variable, we may need msgh_size_delta and msgh_size */
  if (rt->rtNumReplyVar > 1)
    fprintf(file, "\tunsigned int msgh_size;\n");
  if (rt->rtMaxReplyPos > 0)
    fprintf(file, "\tunsigned int msgh_size_delta;\n");
  if (rt->rtNumReplyVar > 1 || rt->rtMaxReplyPos > 0)
    fprintf(file, "\n");

  if (rt->rtServerImpl) {
    fprintf(file, "\tmach_msg_max_trailer_t *TrailerP;\n");
… more in source
WriteReplyInit source
static void
WriteReplyInit(FILE *file, routine_t *rt)
{
  fprintf(file, "\n");
  if (!UseMachMsg2 && (rt->rtNumReplyVar > 1 || rt->rtMaxReplyPos))
    /* WritheAdjustMsgSize() has been executed at least once! */
    fprintf(file, "\tOutP = (Reply *) OutHeadP;\n");

  if (!rt->rtSimpleReply)  /* complex reply message */
    fprintf(file, "\t%s->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n", OutHeadSeg);

  if (rt->rtNumReplyVar == 0) {
    fprintf(file, "\t%s->Head.msgh_size = ", OutHeadSeg);
    rtMinReplySize(file, rt, "Reply");
    fprintf(file, ";\n");
  }
  else if (rt->rtNumReplyVar > 1)
    fprintf(file, "\t%s->Head.msgh_size = msgh_size;\n", OutHeadSeg);
  /* the case rt->rtNumReplyVar = 1 is taken care of in WriteAdjustMsgSize() */
}
WriteRetCArgCheckError source
static void
WriteRetCArgCheckError(FILE *file, routine_t *rt)
{
  fprintf(file, "\tif (!(%s->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&\n", InHeadSeg);
  fprintf(file, "\t    (%s->Head.msgh_size == (mach_msg_size_t)sizeof(mig_reply_error_t)))\n", InHeadSeg);
  fprintf(file, "\t{\n");
}

static void
WriteRetCArgFinishError(FILE *file, routine_t *rt)
{
  argument_t *retcode = rt->rtRetCArg;

  fprintf(file, "\treturn;\n");
  fprintf(file, "\t}\n");
  retcode->argMsgField = "KERN_SUCCESS";
}
WriteRetCArgFinishError source
static void
WriteRetCArgFinishError(FILE *file, routine_t *rt)
{
  argument_t *retcode = rt->rtRetCArg;

  fprintf(file, "\treturn;\n");
  fprintf(file, "\t}
WriteCheckHead source
static void
WriteCheckHead(FILE *file, routine_t *rt)
{
  fprintf(file, "#if\t__MigTypeCheck\n");
  if (rt->rtNumRequestVar > 0)
    fprintf(file, "\tmsgh_size = %s->Head.msgh_size;\n", InHeadSeg);

  if (rt->rtSimpleRequest) {
    /* Expecting a simple message. */
    fprintf(file, "\tif ((%s->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n", InHeadSeg);
    if (rt->rtNumRequestVar > 0) {
      fprintf(file, "\t    (msgh_size < ");
      rtMinRequestSize(file, rt, "__Request");
      fprintf(file, ") ||  (msgh_size > (mach_msg_size_t)sizeof(__Request)))\n");
    }
    else
      fprintf(file, "\t    (%s->Head.msgh_size != (mach_msg_size_t)sizeof(__Request)))\n", InHeadSeg);
  }
  else {
    /* Expecting a complex message. */

    fprintf(file, "\tif (");
    if (rt->rtRetCArg != argNULL)
      fprintf(file, "(");
    fprintf(file, "!(%s->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n", InHeadSeg);
    fprintf(file, "\t    (%s->msgh_body.msgh_descriptor_count != %d) ||\n", InHeadSeg, rt->rtRequestKPDs);
    if (rt->rtNumRequestVar > 0) {
      fprintf(file, "\t    (msgh_size < ");
      rtMinRequestSize(file, rt, "__Request");
      fprintf(file, ") ||  (msgh_size > (mach_msg_size_t)sizeof(__Request))");
… more in source
WriteRequestNDRConvertIntRepArgCond source
void
WriteRequestNDRConvertIntRepArgCond(FILE *file, argument_t *arg)
{
  routine_t *rt = arg->argRoutine;

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

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

  if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
    fprintf(file, "defined(__NDR_convert__float_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
  else
    fprintf(file, "0");
}
WriteRequestNDRConvertIntRepArgDecl source
void
WriteRequestNDRConvertIntRepArgDecl(FILE *file, argument_t *arg)
{
  WriteNDRConvertArgDecl(file, arg, "int_rep", "Request");
}
WriteRequestNDRConvertCharRepArgDecl source
void
WriteRequestNDRConvertCharRepArgDecl(FILE *file, argument_t *arg)
{
  if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
    WriteNDRConvertArgDecl(file, arg, "char_rep", "Request");
}
WriteRequestNDRConvertFloatRepArgDecl source
void
WriteRequestNDRConvertFloatRepArgDecl(FILE *file, argument_t *arg)
{
  if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
    WriteNDRConvertArgDecl(file, arg, "float_rep", "Request");
}
WriteRequestNDRConvertArgUse source
void
WriteRequestNDRConvertArgUse(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, akbSendNdr)))
    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__Request__%s_t__%s__defined)\n", rt->rtName, count->argMsgField);
      fprintf(file, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&In%dP->%s, In%dP->NDR.int_rep);\n", rt->rtName, count->argMsgField, count->argRequestPos, count->argMsgField, count->argRequestPos);
      fprintf(file, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt->rtName, count->argMsgField);
    }

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

  fprintf(file, "#if defined(__NDR_convert__%s__Request__%s_t__%s__defined)\n", convert, rt->rtName, arg->argMsgField);
  fprintf(file, "\t\t__NDR_convert__%s__Request__%s_t__%s(%s, In0P->NDR.%s", convert, rt->rtName, arg->argMsgField, argname, convert);
  if (count)
    fprintf(file, ", In%dP->%s", count->argRequestPos, count->argMsgField);
  fprintf(file, ");\n");
  fprintf(file, "#endif\t/* __NDR_convert__%s__Request__%s_t__%s__defined */\n", convert, rt->rtName, arg->argMsgField);
… more in source
WriteRequestNDRConvertIntRepOneArgUse source
void
WriteRequestNDRConvertIntRepOneArgUse(FILE *file, argument_t *arg)
{
  routine_t *rt = arg->argRoutine;
  char *where = UseMachMsg2 ? "UP" : "P";

  fprintf(file, "#if defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)\n", rt->rtName, arg->argMsgField);
  fprintf(file, "\tif (In0%s->NDR.int_rep != NDR_record.int_rep)\n", where);
  fprintf(file, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&%s->%s, %s->NDR.int_rep);\n", rt->rtName,
    arg->argMsgField, arg->argInSegment, arg->argMsgField, arg->argInSegment);
  fprintf(file, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt->rtName, arg->argMsgField);
}
WriteRequestNDRConvertCharRepArgUse source
void
WriteRequestNDRConvertCharRepArgUse(FILE *file, argument_t *arg)
{
  if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
    WriteRequestNDRConvertArgUse(file, arg, "char_rep");
}
WriteRequestNDRConvertFloatRepArgUse source
void
WriteRequestNDRConvertFloatRepArgUse(FILE *file, argument_t *arg)
{
  if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
    WriteRequestNDRConvertArgUse(file, arg, "float_rep");
}
WriteCalcArgSize source
static void
WriteCalcArgSize(FILE *file, argument_t *arg)
{
  ipc_type_t *ptype = arg->argType;

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

  if (IS_OPTIONAL_NATIVE(ptype))
    fprintf(file, "(%s->__Present__%s ? _WALIGNSZ_(%s) : 0)" , arg->argInSegment, arg->argMsgField, ptype->itServerType);
  else {
    ipc_type_t *btype = ptype->itElement;
    argument_t *count = arg->argCount;
    int multiplier = btype->itTypeSize;

    if (btype->itTypeSize % itWordAlign != 0)
      fprintf(file, "_WALIGN_");
    fprintf(file, "(");

    if (multiplier > 1)
      fprintf(file, "%d * ", multiplier);
    fprintf(file, "%s->%s", count->argInSegment, count->argMsgField);
    fprintf(file, ")");
  }
}
WriteCheckArgSize source
static void
WriteCheckArgSize(FILE *file, routine_t *rt, argument_t *arg, const char *comparator)
{
  ipc_type_t *ptype = arg->argType;


  fprintf(file, "\tif (((msgh_size - ");
  rtMinRequestSize(file, rt, "__Request");
  fprintf(file, ") ");
  if (PackMsg == FALSE) {
	  fprintf(file, "%s %d)", comparator, ptype->itTypeSize + ptype->itPadSize);
  } else if (IS_OPTIONAL_NATIVE(ptype)) {
	  fprintf(file, "%s (%s->__Present__%s ? _WALIGNSZ_(%s) : 0))" , comparator, arg->argInSegment, arg->argMsgField, ptype->itServerType);
  } else {
    ipc_type_t *btype = ptype->itElement;
    argument_t *count = arg->argCount;
    int multiplier = btype->itTypeSize;

    if (multiplier > 1)
      fprintf(file, "/ %d ", multiplier);
    fprintf(file, "< %s->%s) ||\n", count->argInSegment, count->argMsgField);
    fprintf(file, "\t    (msgh_size %s ", comparator);
    rtMinRequestSize(file, rt, "__Request");
    fprintf(file, " + ");
    WriteCalcArgSize(file, arg);
    fprintf(file, ")");
  }
  fprintf(file, ")\n\t\treturn MIG_BAD_ARGUMENTS;\n");
}
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 (arg->argCount && !arg->argSameCount)
    WriteRequestNDRConvertIntRepOneArgUse(file, arg->argCount);
  if (arg->argRequestPos == rt->rtMaxRequestPos)  {
    fprintf(file, "#if\t__MigTypeCheck\n");

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

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

    fprintf(file, "#endif\t/* __MigTypeCheck */\n");
  }
  else {
    /* If there aren't any more variable-sized arguments after this,
       then we must check for exact msg-size and we don't need to
       update msgh_size. */

    boolean_t LastVarArg = arg->argRequestPos+1 == rt->rtNumRequestVar;

    /* calculate the actual size in bytes of the data field.  note
… more in source
InArgMsgField source
static char *
InArgMsgField(argument_t *arg,  char *str)
{
  static char buffer[MAX_STR_LEN];
  char who[20] = {0};

  /*
   * Inside the kernel, the request and reply port fields
   * really hold ipc_port_t values, not mach_port_t values.
   * Hence we must cast the values.
   */

  if (!(arg->argFlags & flRetCode)) {
    if (akCheck(arg->argKind, akbServerImplicit))
      sprintf(who, "TrailerP->");
    else
      sprintf(who, "%s->", arg->argInSegment);
  }

#ifdef MIG_KERNEL_PORT_CONVERSION
  if (IsKernelServer &&
      ((akIdent(arg->argKind) == akeRequestPort) ||
       (akIdent(arg->argKind) == akeReplyPort)))
    sprintf(buffer, "(ipc_port_t) %s%s%s", who, str, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField);
  else
#endif
    sprintf(buffer, "%s%s%s", who, str, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField);

  return buffer;
}
WriteExtractArgValue source
static void
WriteExtractArgValue(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  string_t recast;

#ifdef MIG_KERNEL_PORT_CONVERSION
  if (IsKernelServer && it->itPortType && streql(it->itServerType, "ipc_port_t")
      && akIdent(arg->argKind) != akeRequestPort
      && akIdent(arg->argKind) != akeReplyPort)
    recast = "(mach_port_t)";
  else
#endif
    recast = "";
  if (it->itInTrans != strNULL)
    WriteCopyType(file, it, FALSE, "%s", "/* %s */ %s(%s%s)", arg->argVarName, it->itInTrans, recast, InArgMsgField(arg, ""));
  else
    WriteCopyType(file, it, FALSE, "%s", "/* %s */ %s%s", arg->argVarName, recast, InArgMsgField(arg, ""));

  fprintf(file, "\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 *recast = "";

  WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE);
  /* translation function do not apply to complex types */
#ifdef MIG_KERNEL_PORT_CONVERSION
  if (IsKernelServer)
    recast = "(mach_port_t)";
#endif
  fprintf(file, "\t\t%s[i] = %sptr->name;\n", arg->argVarName, recast);
  fprintf(file, "\t}
WriteExtractKPD_ool source
argKPD_Extract discipline for out-of-line types.
static void
WriteExtractKPD_ool(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;

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

  WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE);
  fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName);
  fprintf(file, "\t}
WriteInitializeCount source
static void
WriteInitializeCount(FILE *file, argument_t *arg)
{
  ipc_type_t *ptype = arg->argParent->argType;
  ipc_type_t *btype = ptype->itElement;
  char newstr[MAX_STR_LEN];

  /*
   * Initialize 'count' argument for variable-length inline OUT parameter
   * with maximum allowed number of elements.
   */

  if (akCheck(arg->argKind, akbVarNeeded))
    sprintf(newstr, "%s", arg->argMsgField);
  else
    sprintf(newstr, "%s->%s", arg->argOutSegment, arg->argMsgField);

  fprintf(file, "\t%s = ", newstr);
  if (IS_MULTIPLE_KPD(ptype))
    fprintf(file, "%d;\n", ptype->itKPD_Number);
  else
    fprintf(file, "%d;\n", btype->itNumber? ptype->itNumber/btype->itNumber : 0);

  /*
   * If the user passed in a count, then we use the minimum.
   * We can't let the user completely override our maximum,
   * or the user might convince the server to overwrite the buffer.
   */

  if (arg->argCInOut != argNULL) {
… more in source
WriteAdjustRequestMsgPtr source
static void
WriteAdjustRequestMsgPtr(FILE *file, argument_t *arg)
{
  ipc_type_t *ptype = arg->argType;
  char *where = UseMachMsg2 ? "UP" : "P";
  char *castType = UseMachMsg2 ? "__RequestU" : "__Request";

  if (PackMsg == FALSE) {
    fprintf(file, "\t*In%d%sP = In%d%s = (%s *) ((pointer_t) %s);\n\n",
      arg->argRequestPos+1, where, arg->argRequestPos+1, where, castType, arg->argInSegment);
    return;
  }

  fprintf(file, "\t*In%d%sP = In%d%s = (%s *) ((pointer_t) %s + msgh_size_delta - ",
    arg->argRequestPos+1, where, arg->argRequestPos+1, where, castType, arg->argInSegment);
  if (IS_OPTIONAL_NATIVE(ptype))
    fprintf(file, "_WALIGNSZ_(%s)", ptype->itUserType);
  else
    fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize);
  fprintf(file, ");\n\n");
}
WriteCheckRequestTrailerArgs source
static void
WriteCheckRequestTrailerArgs(FILE *file, routine_t *rt)
{
  argument_t *arg;

  if (rt->rtServerImpl)
    WriteCheckTrailerHead(file, rt, FALSE);

  for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
    if (akCheck(arg->argKind, akbServerImplicit))
      WriteCheckTrailerSize(file, FALSE, arg);
  }
}
WriteExtractArg source
static void
WriteExtractArg(FILE *file, argument_t *arg)
{
  if (akCheckAll(arg->argKind, akbSendRcv|akbVarNeeded)) {
    if (akCheck(arg->argKind, akbSendKPD))
      (*arg->argKPD_Extract)(file, arg);
    else
      WriteExtractArgValue(file, arg);
  }

  if ((akIdent(arg->argKind) == akeCount) &&
      akCheck(arg->argKind, akbReturnSnd)) {

    ipc_type_t *ptype = arg->argParent->argType;
    /*
     * the count will be initialized to 0 in the case of
     * unbounded arrays (MigInLine = TRUE): this is because
     * the old interface used to pass to the target procedure
     * the maximum in-line size (it was 2048 bytes)
     */
    if (IS_VARIABLE_SIZED_UNTYPED(ptype) ||
        IS_MIG_INLINE_EMUL(ptype) ||
        (IS_MULTIPLE_KPD(ptype) && ptype->itVarArray))
      WriteInitializeCount(file, arg);
  }
}
WriteServerCallArg source
static void
WriteServerCallArg(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  boolean_t NeedClose = FALSE;
  u_int elemsize = 0;
  string_t  at = (arg->argByReferenceServer ||
                  it->itNativePointer) ? "&" : "";
  string_t  star = (arg->argByReferenceServer) ? " *" : "";
  string_t  msgfield =
  (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField;

  if ((it->itInTrans != strNULL) &&
      akCheck(arg->argKind, akbSendRcv) &&
      !akCheck(arg->argKind, akbVarNeeded)) {
    fprintf(file, "%s%s(", at, it->itInTrans);
    NeedClose = TRUE;
  }

  if (akCheckAll(arg->argKind, akbVarNeeded|akbServerArg))
    fprintf(file, "%s%s", at, arg->argVarName);
  else if (akCheckAll(arg->argKind, akbSendRcv|akbSendKPD)) {
    if (!it->itInLine)
      /* recast the void *, although it is not necessary */
      fprintf(file, "(%s%s)%s(%s)", it->itTransType, star, at, InArgMsgField(arg, ""));
    else
#ifdef MIG_KERNEL_PORT_CONVERSION
      if (IsKernelServer && streql(it->itServerType, "ipc_port_t"))
        /* recast the port to the kernel internal form value */
        fprintf(file, "(ipc_port_t%s)%s(%s)", star, at, InArgMsgField(arg, ""));
… more in source
WriteConditionalCallArg source
Shrunk version of WriteServerCallArg, to implement the RetCode functionality: we have received a mig_reply_error_t, therefore we want to call the target routine with all 0s except for the error code (and the implicit data). We know that we are a SimpleRoutine.
static void
WriteConditionalCallArg(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  boolean_t NeedClose = FALSE;

  if ((it->itInTrans != strNULL) &&
      akCheck(arg->argKind, akbSendRcv) &&
      !akCheck(arg->argKind, akbVarNeeded)) {
    fprintf(file, "%s(", it->itInTrans);
    NeedClose = TRUE;
  }

  if (akCheck(arg->argKind, akbSendRcv)) {
    if (akIdent(arg->argKind) == akeRequestPort ||
        akCheck(arg->argKind, akbServerImplicit))
      fprintf(file, "%s", InArgMsgField(arg, ""));
    else if (akIdent(arg->argKind) == akeRetCode) {
      assert(arg->argRequestPos == 0);
      fprintf(file, "((mig_reply_error_t *)%s)->RetCode", arg->argInSegment);
    } else
      fprintf(file, "(%s)(0)", it->itTransType);
  }

  if (NeedClose)
    fprintf(file, ")");
}
WriteDestroyArg source
static void
WriteDestroyArg(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;

  /*
   * Deallocate IN/INOUT out-of-line args if specified by "auto" flag.
   *
   * We also have to deallocate in the cases where the target routine
   * is given a itInLine semantic whereas the underlying transmission
   * was out-of-line
   */
  if ((argIsIn(arg) && akCheck(arg->argKind, akbSendKPD|akbReturnKPD) &&
       arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR &&
       (arg->argFlags & flAuto))
      ||
      IS_MIG_INLINE_EMUL(it)
      ) {
    /*
     * Deallocate only if out-of-line.
     */
    argument_t *count = arg->argCount;
    ipc_type_t *btype = it->itElement;
    int multiplier = btype->itNumber ? btype->itSize / (8 * btype->itNumber) : 0;

    if (IsKernelServer) {
      fprintf(file, "#if __MigKernelSpecificCode\n");
      fprintf(file, "\tvm_map_copy_discard(%s);\n", InArgMsgField(arg, ""));
      fprintf(file, "#else\n");
    }
… more in source
WriteDestroyPortArg source
static void
WriteDestroyPortArg(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;

  /*
   * If a translated port argument occurs in the body of a request
   * message, and the message is successfully processed, then the
   * port right should be deallocated.  However, the called function
   * didn't see the port right; it saw the translation.  So we have
   * to release the port right for it.
   *
   *  The test over it->itInTrans will exclude any complex type
   *  made out of ports
   */
  if ((it->itInTrans != strNULL) &&
      (it->itOutName == MACH_MSG_TYPE_PORT_SEND)) {
    fprintf(file, "\tipc_port_release_send((ipc_port_t)%s);\n", InArgMsgField(arg, ""));
  }
}
CheckDestroyPortArg source
Check whether WriteDestroyPortArg would generate any code for arg.
boolean_t
CheckDestroyPortArg(argument_t *arg)
{
  ipc_type_t *it = arg->argType;

  if ((it->itInTrans != strNULL) &&
      (it->itOutName == MACH_MSG_TYPE_PORT_SEND))  {
    return TRUE;
  }
  return FALSE;
}
WriteServerCall source
static void
WriteServerCall(FILE *file, routine_t *rt,  void (*func)(FILE *, argument_t *))
{
  argument_t *arg = rt->rtRetCode;
  ipc_type_t *it = arg->argType;
  boolean_t NeedClose = FALSE;

  fprintf(file, "\t");
  if (akCheck(arg->argKind, akbVarNeeded))
    fprintf(file, "%s = ", arg->argMsgField);
  else
    fprintf(file, "%s->%s = ", arg->argOutSegment, arg->argMsgField);
  if (it->itOutTrans != strNULL) {
    fprintf(file, "%s(", it->itOutTrans);
    NeedClose = TRUE;
  }
  fprintf(file, "%s(", rt->rtServerName);
  WriteList(file, rt->rtArgs, func, akbServerArg, ", ", "");
  if (NeedClose)
    fprintf(file, ")");
  fprintf(file, ");\n");
}
WriteCheckReturnValue source
static void
WriteCheckReturnValue(FILE *file, routine_t *rt)
{
  argument_t *arg = rt->rtRetCode;
  char string[MAX_STR_LEN];

  if (akCheck(arg->argKind, akbVarNeeded))
    sprintf(string, "%s", arg->argMsgField);
  else
    sprintf(string, "%s->%s", arg->argOutSegment, arg->argMsgField);
  fprintf(file, "\tif (%s != KERN_SUCCESS) {\n", string);
  fprintf(file, "\t\tMIG_RETURN_ERROR(%s, %s);\n", OutHeadSeg, string);
  fprintf(file, "\t}\n");
}
WriteInitKPD_port source
argKPD_Init discipline for Port types.
static void
WriteInitKPD_port(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char *subindex = "";
  boolean_t close = FALSE;
  char firststring[MAX_STR_LEN];
  char string[MAX_STR_LEN];

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

  fprintf(file, "#if\tUseStaticTemplates\n");
  fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
  fprintf(file, "#else\t/* UseStaticTemplates */\n");
  if (IS_MULTIPLE_KPD(it) && it->itVarArray)
    fprintf(file, "\t%sname = MACH_PORT_NULL;\n", string);
  if (arg->argPoly == argNULL) {
    if (IsKernelServer) {
      fprintf(file, "#if __MigKernelSpecificCode\n");
      fprintf(file, "\t%sdisposition = %s;\n", string, it->itOutNameStr);
… more in source
WriteInitKPD_ool source
argKPD_Init discipline for out-of-line types.
static void
WriteInitKPD_ool(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  char firststring[MAX_STR_LEN];
  char string[MAX_STR_LEN];
  boolean_t VarArray;
  u_int howmany, howbig;

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

  fprintf(file, "#if\tUseStaticTemplates\n");
  fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
  fprintf(file, "#else\t/* UseStaticTemplates */\n");
  if (!VarArray)
    fprintf(file, "\t%ssize = %d;\n", string, (howmany * howbig + 7)/8);
… more in source
WriteInitKPD_oolport source
argKPD_Init discipline for out-of-line Port types.
static void
WriteInitKPD_oolport(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;
  boolean_t VarArray;
  ipc_type_t *howit;
  u_int howmany;
  char firststring[MAX_STR_LEN];
  char string[MAX_STR_LEN];

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

  fprintf(file, "#if\tUseStaticTemplates\n");
  fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
  fprintf(file, "#else\t/* UseStaticTemplates */\n");
… more in source
WriteInitKPDValue source
static void
WriteInitKPDValue(FILE *file, argument_t *arg)
{
  (*arg->argKPD_Init)(file, arg);
}
WriteAdjustMsgCircular source
static void
WriteAdjustMsgCircular(FILE *file, argument_t *arg)
{
  fprintf(file, "\n");

  fprintf(file,"#if\t__MigKernelSpecificCode\n");
  if (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
    fprintf(file, "\tif (%s == MACH_MSG_TYPE_PORT_RECEIVE)\n", arg->argPoly->argVarName);

  /*
   * The carried port right can be accessed in OutP->XXXX.  Normally
   * the server function stuffs it directly there.  If it is InOut,
   * then it has already been copied into the reply message.
   * If the server function deposited it into a variable (perhaps
   * because the reply message is variable-sized) then it has already
   * been copied into the reply message.
   *
   *  The old MiG does not check for circularity in the case of
   *  array of ports. So do I ...
   */

  fprintf(file, "\t  if (IP_VALID((ipc_port_t) %s->Head.msgh_reply_port) &&\n", InHeadSeg);
  fprintf(file, "\t    IP_VALID((ipc_port_t) %s->%s.name) &&\n", arg->argOutSegment, arg->argMsgField);
  fprintf(file, "\t    ipc_port_check_circularity((ipc_port_t) %s->%s.name, (ipc_port_t) %s->Head.msgh_reply_port))\n",
    arg->argOutSegment, arg->argMsgField, InHeadSeg);
  fprintf(file, "\t\t%s->Head.msgh_bits |= MACH_MSGH_BITS_CIRCULAR;\n", OutHeadSeg);
  fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
}
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 = "";
  boolean_t close = FALSE;
  char string[MAX_STR_LEN];
  ipc_type_t *real_it;

  if (akCheck(arg->argKind, akbVarNeeded)) {
    if (IS_MULTIPLE_KPD(it)) {
      WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE);
      (void)sprintf(string, "\tptr->");
      subindex = "[i]";
      close = TRUE;
      real_it = it->itElement;
    }
    else {
      (void)sprintf(string, "%s->%s.", arg->argOutSegment, arg->argMsgField);
      real_it = it;
    }
#ifdef MIG_KERNEL_PORT_CONVERSIONS
    if (IsKernelServer && streql(real_it->itTransType, "ipc_port_t"))
      recast = "(mach_port_t)";
#endif

    if (it->itOutTrans != strNULL && !close)
      fprintf(file, "\t%sname = (mach_port_t)%s(%s);\n", string, it->itOutTrans, arg->argVarName);
    else
… more in source
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 string[MAX_STR_LEN];
  boolean_t VarArray;
  argument_t *count;
  u_int howbig;
  char *subindex;

  if (IS_MULTIPLE_KPD(it)) {
    WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE);
    (void)sprintf(string, "\tptr->");
    VarArray = it->itElement->itVarArray;
    count = arg->argSubCount;
    howbig = it->itElement->itSize;
    subindex = "[i]";
  }
  else {
    (void)sprintf(string, "%s->%s.", arg->argOutSegment, arg->argMsgField);
    VarArray = it->itVarArray;
    count = arg->argCount;
    howbig = it->itSize;
    subindex = "";
  }

  if (akCheck(arg->argKind, akbVarNeeded))
    fprintf(file, "\t%saddress = (void *)%s%s;\n", string, arg->argMsgField, subindex);
  if (arg->argDealloc != argNULL)
    if (akCheck(arg->argDealloc->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it))
… 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;
  boolean_t VarArray;
  argument_t *count;
  char *subindex, string[MAX_STR_LEN];

  if (IS_MULTIPLE_KPD(it)) {
    WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE);
    (void)sprintf(string, "\tptr->");
    VarArray = it->itElement->itVarArray;
    count = arg->argSubCount;
    subindex = "[i]";
  }
  else {
    (void)sprintf(string, "%s->%s.", arg->argOutSegment, arg->argMsgField);
    VarArray = it->itVarArray;
    count = arg->argCount;
    subindex = "";
  }

  if (akCheck(arg->argKind, akbVarNeeded))
    fprintf(file, "\t%saddress = (void *)%s%s;\n", string, arg->argMsgField, subindex);
  if (arg->argDealloc != argNULL)
    if (akCheck(arg->argDealloc->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it))
      fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName);
  if (VarArray) {
    fprintf(file, "\t%scount = ", string);
    if (akCheck(count->argKind, akbVarNeeded))
… 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, TRUE, FALSE, arg, TRUE);
    (void)sprintf(string, "ptr->");
    tab = "\t";
    close = TRUE;
  }
  else
    (void)sprintf(string, "%s->%s.", arg->argInSegment, arg->argMsgField);

  fprintf(file, "\t%sif (%stype != MACH_MSG_PORT_DESCRIPTOR", tab, string);
  /*
   * We can't check disposition on varArray
   * (because some of the entries could be empty).
   */
  if (!it->itVarArray) {
    if (arg->argPoly != argNULL) {
      switch (it->itOutName) {

        case MACH_MSG_TYPE_MOVE_RECEIVE:
          fprintf(file, " || \n\t%s    %sdisposition != MACH_MSG_TYPE_MOVE_RECEIVE", tab, string);
          break;
… more in source
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, TRUE, FALSE, arg, TRUE);
    tab = "\t\t\t";
    sprintf(string, "ptr->");
    howmany = it->itElement->itNumber;
    howbig = it->itElement->itSize;
    test = !it->itVarArray && !it->itElement->itVarArray;
  }
  else {
    tab = "";
    sprintf(string, "%s->%s.", arg->argInSegment, 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);
  }
… 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, TRUE, 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, "%s->%s.", arg->argInSegment, 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 in && typed argument in the request 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");
}
WritePackArgValueNormal source
static void
WritePackArgValueNormal(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;

  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\t%s->%s = (%s) mig_strncpy_zerofill(%s->%s, %s, %d);\n",
        arg->argCount->argOutSegment, arg->argCount->argMsgField, arg->argCount->argType->itTransType,
        arg->argOutSegment, arg->argMsgField, arg->argVarName, it->itNumber);
      fprintf(file, "\t} else {\n");
      fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");

      fprintf(file, "\t\t%s->%s = (%s) mig_strncpy(%s->%s, %s, %d);\n",
        arg->argCount->argOutSegment, arg->argCount->argMsgField, arg->argCount->argType->itTransType,
        arg->argOutSegment, 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, "\t%s->%sOffset = 0;\n", arg->argOutSegment, arg->argMsgField);
    }
… more in source
WritePackArgValueVariable source
static void
WritePackArgValueVariable(FILE *file, argument_t *arg)
{
  ipc_type_t *it = arg->argType;

  /*
   * only itString are treated here so far
   */
  if (it->itString) {
    /*
     * Emit logic to call strlen to calculate the size of the argument, and ensure that it fits within the 32-bit result field
     * in the Reply, when targeting a 64-bit architecture. If a 32-bit architecture is the target, we emit code to just call
     * strlen() directly (since it'll return a 32-bit value that is guaranteed to fit).
     */
    fputs("#ifdef __LP64__\n", file);
    fprintf(file, "\t{\n"
                  "\t\t" "size_t strLength = strlen(%s->%s) + 1;\n", arg->argOutSegment, arg->argMsgField);
    fprintf(file,        "\t\t" "if (strLength > 0xffffffff)\n"
                  "\t\t\t"  "MIG_RETURN_ERROR(%s, MIG_BAD_ARGUMENTS);\n", OutHeadSeg);
    fprintf(file, "\t\t" "%s->%s = (mach_msg_type_number_t) strLength;\n"
                  "\t}\n", arg->argCount->argOutSegment, arg->argCount->argMsgField);
    fputs("#else\n", file);
    fprintf(file, "\t%s->%s = (mach_msg_type_number_t) strlen(%s->%s) + 1;\n",
      arg->argCount->argOutSegment, arg->argCount->argMsgField, arg->argOutSegment, arg->argMsgField);
    fputs("#endif /* __LP64__ */\n", file);
    fprintf(file, "\t%s->%sOffset = 0;\n", arg->argCount->argOutSegment, arg->argMsgField);
  }
}
WriteCopyArgValue source
static void
WriteCopyArgValue(FILE *file, argument_t *arg)
{
  fprintf(file, "\n");
  char *field =  (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField;
  WriteCopyType(file, arg->argType, TRUE, "%s->%s",
    "/* %s %s */ %s->%s",arg->argOutSegment, field, arg->argInSegment, field);
}
WriteInitArgValue source
static void
WriteInitArgValue(FILE *file, argument_t *arg)
{
  fprintf(file, "\n");
  fprintf(file, "\t%s->%s = %s;\n\n", arg->argOutSegment, arg->argMsgField, arg->argVarName);
}
WriteArgSize source
Calculate the size of a variable-length message field.
static void
WriteArgSize(FILE *file, argument_t *arg)
{
  ipc_type_t *ptype = arg->argType;
  int bsize = ptype->itElement->itTypeSize;
  argument_t *count = arg->argCount;

  /* 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_");

  /* Here, we generate ((value + %d) & ~%d). We have to put two (( at the
   * the beginning.
   */
  fprintf(file, "((");
  if (bsize > 1)
    fprintf(file, "%d * ", bsize);
  if (ptype->itString || !akCheck(count->argKind, akbVarNeeded))
    /* get count from descriptor in message */
    fprintf(file, "%s->%s", count->argOutSegment, count->argMsgField);
  else
    /* get count from argument */
    fprintf(file, "%s", count->argVarName);

  /*
   * If the base type size is not a multiple of sizeof(natural_t),
   * we have to round up.
   */
  if (bsize % sizeof(natural_t) != 0)
… more in source
WriteAdjustMsgSize source
Adjust message size and advance reply pointer. Called after packing a variable-length argument that has more arguments following.
static void
WriteAdjustMsgSize(FILE *file, argument_t *arg)
{
  routine_t *rt = arg->argRoutine;
  ipc_type_t *ptype = arg->argType;

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

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

  if (rt->rtNumReplyVar == 1) {
    /* We can still address the message header directly.  Fill
       in the size field. */

    fprintf(file, "\t%s->Head.msgh_size = ", OutHeadSeg);
    rtMinReplySize(file, rt, "Reply");
    fprintf(file, " + msgh_size_delta;\n");
  }
  else if (arg->argReplyPos == 0) {
    /* First variable-length argument.  The previous msgh_size value
       is the minimum reply size. */

    fprintf(file, "\tmsgh_size = ");
    rtMinReplySize(file, rt, "Reply");
    fprintf(file, " + msgh_size_delta;\n");
  }
… 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 Out arguments.  If this is the only variable Out
     argument, we can assign to msgh_size directly. */

  if (arg->argReplyPos == 0) {
    fprintf(file, "\t%s->Head.msgh_size = ", OutHeadSeg);
    rtMinReplySize(file, arg->argRoutine, "Reply");
    fprintf(file, " + (");
    WriteArgSize(file, arg);
    fprintf(file, ");\n");
  }
  else {
    fprintf(file, "\tmsgh_size += ");
    WriteArgSize(file, arg);
    fprintf(file, ";\n");
  }
}
WriteReplyArgs source
Handle reply arguments - fill in message types and copy arguments that need to be copied.
static void
WriteReplyArgs(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, akbReturnSnd|akbReturnKPD))
      (*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->argReplyPos < arg->argReplyPos) {
      WriteAdjustMsgSize(file, lastVarArg);
      lastVarArg = argNULL;
    }

    if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVarNeeded))
      WritePackArgValueNormal(file, arg);
… more in source
WriteFieldDecl source
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, FetchServerType);
}
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);

  /*
   * WriteInitKPD_port, WriteKPD_port,  WriteExtractKPD_port,
   * WriteInitKPD_ool, WriteKPD_ool,  WriteExtractKPD_ool,
   * WriteInitKPD_oolport, 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:
          if akCheck(arg->argKind, akbSendKPD) {
            arg->argKPD_Extract =
… 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, akbSendKPD)) {
      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, TRUE, 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
WriteCheckRequest source
void
WriteCheckRequest(FILE *file, routine_t *rt)
{
  int i;

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

  fprintf(file, "\n");
  fprintf(file, "#if ( __MigTypeCheck ");
  if (CheckNDR)
	  fprintf(file, "|| __NDR_convert__ ");
  fprintf(file, ")\n");
  fprintf(file, "#if __MIG_check__Request__%s_subsystem__\n", SubsystemName);
  fprintf(file, "#if !defined(__MIG_check__Request__%s_t__defined)\n", rt->rtName);
  fprintf(file, "#define __MIG_check__Request__%s_t__defined\n", rt->rtName);
  if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbRequest)) {
    __KernelServer_unreachable();
    WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgDecl, akbSendNdr, "", "");
    WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgDecl, akbSendNdr, "", "");
    WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgDecl, akbSendNdr, "", "");
  }
  fprintf(file, "\n");
  if (!UseMachMsg2) {
    fprintf(file, "mig_internal kern_return_t __MIG_check__Request__%s_t(__attribute__((__unused__)) __Request__%s_t *In0P",
      rt->rtName, rt->rtName);
    for (i = 1; i <= rt->rtMaxRequestPos; i++)
      fprintf(file, ", __attribute__((__unused__)) __Request__%s_t **In%dPP", rt->rtName, i);
  } else {
    fprintf(file, "mig_internal kern_return_t __MIG_check__Request__%s_t(\n"
… more in source
WriteCheckRequestCall source
void
WriteCheckRequestCall(FILE *file, routine_t *rt)
{
  int i;

  fprintf(file, "\n");
  fprintf(file, "#if\tdefined(__MIG_check__Request__%s_t__defined)\n", rt->rtName);
  if (!UseMachMsg2) {
    fprintf(file, "\tcheck_result = __MIG_check__Request__%s_t((__Request *)In0P", rt->rtName);
    for (i = 1; i <= rt->rtMaxRequestPos; i++)
      fprintf(file, ", (__Request **)&In%dP", i);
  } else {
    fprintf(file, "\tcheck_result = __MIG_check__Request__%s_t((RequestK *)InKP, (__RequestU *)In0UP, InTrailerP", rt->rtName);
    for (i = 1; i <= rt->rtMaxRequestPos; i++)
      fprintf(file, ", (__RequestU **)&In%dUP", i);
  }
  fprintf(file, ");\n");
  fprintf(file, "\tif (check_result != MACH_MSG_SUCCESS)\n");
  fprintf(file, "\t\t{ MIG_RETURN_ERROR(%s, check_result); }\n", OutHeadSeg);
  fprintf(file, "#endif\t/* defined(__MIG_check__Request__%s_t__defined) */\n", rt->rtName);
  fprintf(file, "\n");
}
WriteCheckRequests source
void
WriteCheckRequests(FILE *file, statement_t *stats)
{
  statement_t *stat;

  for (stat = stats; stat != stNULL; stat = stat->stNext)
    if (stat->stKind == skRoutine)
      WriteCheckRequest(file, stat->stRoutine);
}
WriteRoutine source
static void
WriteRoutine(FILE *file, routine_t *rt)
{
  /*  Declare the server work function: */
  if (ServerHeaderFileName == strNULL)
    WriteServerRoutine(file, rt);

  fprintf(file, "\n");

  fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
  fprintf(file, "mig_internal novalue _X%s\n", rt->rtName);
  if (BeAnsiC) {
    if (!UseMachMsg2) {
      fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
    } else {
      fprintf(file, "\t(mach_msg_header_t *InHeadP, __attribute__((__unused__)) void *InDataP,\n"
        "\t__attribute__((__unused__)) mach_msg_max_trailer_t *InTrailerP,\n"
        "\tmach_msg_header_t *OutHeadP, __attribute__((__unused__)) void *OutDataP)\n");
    }
  }
  else {
    __KernelServer_unreachable();
    fprintf(file, "#if\t%s\n", NewCDecl);
    fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
    fprintf(file, "#else\n");
    fprintf(file, "\t(InHeadP, OutHeadP)\n");
    fprintf(file, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n");
    fprintf(file, "#endif\t/* %s */\n", NewCDecl);
  }
… more in source
WriteServer source
void
WriteServer(FILE *file, statement_t *stats)
{
  statement_t *stat;

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

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

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

      default:
        fatal("WriteServer(): bad statement_kind_t (%d)",
              (int) stat->stKind);
    }
  WriteDispatcher(file, stats);
}