Annotation of Gnu-Mach/mig/user.c, revision 1.1

1.1     ! root        1: /* 
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1992,1991,1990 Carnegie Mellon University
        !             4:  * All Rights Reserved.
        !             5:  * 
        !             6:  * Permission to use, copy, modify and distribute this software and its
        !             7:  * documentation is hereby granted, provided that both the copyright
        !             8:  * notice and this permission notice appear in all copies of the
        !             9:  * software, derivative works or modified versions, and any portions
        !            10:  * thereof, and that both notices appear in supporting documentation.
        !            11:  * 
        !            12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
        !            13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            15:  * 
        !            16:  * Carnegie Mellon requests users of this software to return to
        !            17:  * 
        !            18:  *  Software Distribution Coordinator  or  [email protected]
        !            19:  *  School of Computer Science
        !            20:  *  Carnegie Mellon University
        !            21:  *  Pittsburgh PA 15213-3890
        !            22:  * 
        !            23:  * any improvements or extensions that they make and grant Carnegie the
        !            24:  * rights to redistribute these changes.
        !            25:  */
        !            26: 
        !            27: #include <assert.h>
        !            28: 
        !            29: #include "write.h"
        !            30: #include "error.h"
        !            31: #include "utils.h"
        !            32: #include "global.h"
        !            33: #include "mig_string.h"
        !            34: #include "cpu.h"
        !            35: 
        !            36: /*************************************************************
        !            37:  *     Writes the standard includes. The subsystem specific
        !            38:  *     includes  are in <SubsystemName>.h and writen by
        !            39:  *     header:WriteHeader. Called by WriteProlog.
        !            40:  *************************************************************/
        !            41: static void
        !            42: WriteIncludes(FILE *file)
        !            43: {
        !            44:     if (IsKernelServer)
        !            45:     {
        !            46:        /*
        !            47:         *      We want to get the user-side definitions of types
        !            48:         *      like task_t, ipc_space_t, etc. in mach/mach_types.h.
        !            49:         */
        !            50: 
        !            51:        fprintf(file, "#undef\tKERNEL\n");
        !            52: 
        !            53:        if (InternalHeaderFileName != strNULL)
        !            54:        {
        !            55:            register char *cp;
        !            56: 
        !            57:            /* Strip any leading path from InternalHeaderFileName. */
        !            58:            cp = strrchr(InternalHeaderFileName, '/');
        !            59:            if (cp == 0)
        !            60:                cp = InternalHeaderFileName;
        !            61:            else
        !            62:                cp++;   /* skip '/' */
        !            63:            fprintf(file, "#include \"%s\"\n", cp);
        !            64:        }
        !            65:     }
        !            66: 
        !            67:     if (UserHeaderFileName != strNULL)
        !            68:     {
        !            69:        register char *cp;
        !            70: 
        !            71:        /* Strip any leading path from UserHeaderFileName. */
        !            72:        cp = strrchr(UserHeaderFileName, '/');
        !            73:        if (cp == 0)
        !            74:            cp = UserHeaderFileName;
        !            75:        else
        !            76:            cp++;       /* skip '/' */
        !            77:        fprintf(file, "#include \"%s\"\n", cp);
        !            78:     }
        !            79: 
        !            80:     fprintf(file, "#define EXPORT_BOOLEAN\n");
        !            81:     fprintf(file, "#include <mach/boolean.h>\n");
        !            82:     fprintf(file, "#include <mach/kern_return.h>\n");
        !            83:     fprintf(file, "#include <mach/message.h>\n");
        !            84:     fprintf(file, "#include <mach/notify.h>\n");
        !            85:     fprintf(file, "#include <mach/mach_types.h>\n");
        !            86:     fprintf(file, "#include <mach/mig_errors.h>\n");
        !            87:     fprintf(file, "#include <mach/mig_support.h>\n");
        !            88:     fprintf(file, "#include <mach/msg_type.h>\n");
        !            89:     fprintf(file, "/* LINTLIBRARY */\n");
        !            90:     fprintf(file, "\n");
        !            91: }
        !            92: 
        !            93: static void
        !            94: WriteGlobalDecls(FILE *file)
        !            95: {
        !            96:     if (RCSId != strNULL)
        !            97:        WriteRCSDecl(file, strconcat(SubsystemName, "_user"), RCSId);
        !            98: 
        !            99:     fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n");
        !           100:     fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n");
        !           101:     fprintf(file, "\n");
        !           102: }
        !           103: 
        !           104: /*************************************************************
        !           105:  *     Writes the standard #includes, #defines, and
        !           106:  *     RCS declaration. Called by WriteUser.
        !           107:  *************************************************************/
        !           108: static void
        !           109: WriteProlog(FILE *file)
        !           110: {
        !           111:     WriteIncludes(file);
        !           112:     WriteBogusDefines(file);
        !           113:     WriteGlobalDecls(file);
        !           114: }
        !           115: 
        !           116: /*ARGSUSED*/
        !           117: static void
        !           118: WriteEpilog(FILE *file)
        !           119: {
        !           120: }
        !           121: 
        !           122: static const_string_t
        !           123: WriteHeaderPortType(const argument_t *arg)
        !           124: {
        !           125:     if (arg->argType->itInName == MACH_MSG_TYPE_POLYMORPHIC)
        !           126:        return arg->argPoly->argVarName;
        !           127:     else
        !           128:        return arg->argType->itInNameStr;
        !           129: }
        !           130: 
        !           131: static void
        !           132: WriteRequestHead(FILE *file, const routine_t *rt)
        !           133: {
        !           134:     if (rt->rtMaxRequestPos > 0)
        !           135:        fprintf(file, "\tInP = &Mess.In;\n");
        !           136: 
        !           137:     if (rt->rtSimpleFixedRequest) {
        !           138:        fprintf(file, "\tInP->Head.msgh_bits =");
        !           139:        if (!rt->rtSimpleSendRequest)
        !           140:            fprintf(file, " MACH_MSGH_BITS_COMPLEX|");
        !           141:        fprintf(file, "\n");
        !           142:        fprintf(file, "\t\tMACH_MSGH_BITS(%s, %s);\n",
        !           143:                WriteHeaderPortType(rt->rtRequestPort),
        !           144:                WriteHeaderPortType(rt->rtUReplyPort));
        !           145:     } else {
        !           146:        fprintf(file, "\tInP->Head.msgh_bits = msgh_simple ?\n");
        !           147:        fprintf(file, "\t\tMACH_MSGH_BITS(%s, %s) :\n",
        !           148:                WriteHeaderPortType(rt->rtRequestPort),
        !           149:                WriteHeaderPortType(rt->rtUReplyPort));
        !           150:        fprintf(file, "\t\t(MACH_MSGH_BITS_COMPLEX|\n");
        !           151:        fprintf(file, "\t\t MACH_MSGH_BITS(%s, %s));\n",
        !           152:                WriteHeaderPortType(rt->rtRequestPort),
        !           153:                WriteHeaderPortType(rt->rtUReplyPort));
        !           154:     }
        !           155: 
        !           156:     fprintf(file, "\t/* msgh_size passed as argument */\n");
        !           157: 
        !           158:     /*
        !           159:      * KernelUser stubs need to cast the request and reply ports
        !           160:      * from ipc_port_t to mach_port_t.
        !           161:      */
        !           162: 
        !           163:     if (IsKernelUser)
        !           164:        fprintf(file, "\tInP->%s = (mach_port_t) %s;\n",
        !           165:                rt->rtRequestPort->argMsgField,
        !           166:                rt->rtRequestPort->argVarName);
        !           167:     else
        !           168:        fprintf(file, "\tInP->%s = %s;\n",
        !           169:                rt->rtRequestPort->argMsgField,
        !           170:                rt->rtRequestPort->argVarName);
        !           171: 
        !           172:     if (akCheck(rt->rtUReplyPort->argKind, akbUserArg)) {
        !           173:        if (IsKernelUser)
        !           174:            fprintf(file, "\tInP->%s = (mach_port_t) %s;\n",
        !           175:                    rt->rtUReplyPort->argMsgField,
        !           176:                    rt->rtUReplyPort->argVarName);
        !           177:        else
        !           178:            fprintf(file, "\tInP->%s = %s;\n",
        !           179:                    rt->rtUReplyPort->argMsgField,
        !           180:                    rt->rtUReplyPort->argVarName);
        !           181:     } else if (rt->rtOneWay || IsKernelUser)
        !           182:        fprintf(file, "\tInP->%s = MACH_PORT_NULL;\n",
        !           183:                rt->rtUReplyPort->argMsgField);
        !           184:     else
        !           185:        fprintf(file, "\tInP->%s = %smig_get_reply_port();\n",
        !           186:                rt->rtUReplyPort->argMsgField, SubrPrefix);
        !           187: 
        !           188:     fprintf(file, "\tInP->Head.msgh_seqno = 0;\n");
        !           189:     fprintf(file, "\tInP->Head.msgh_id = %d;\n", rt->rtNumber + SubsystemBase);
        !           190: }
        !           191: 
        !           192: /*************************************************************
        !           193:  *  Writes declarations for the message types, variables
        !           194:  *  and return  variable if needed. Called by WriteRoutine.
        !           195:  *************************************************************/
        !           196: static void
        !           197: WriteVarDecls(FILE *file, const routine_t *rt)
        !           198: {
        !           199:     fprintf(file, "\tunion {\n");
        !           200:     fprintf(file, "\t\tRequest In;\n");
        !           201:     if (!rt->rtOneWay)
        !           202:        fprintf(file, "\t\tReply Out;\n");
        !           203:     fprintf(file, "\t} Mess;\n");
        !           204:     fprintf(file, "\n");
        !           205: 
        !           206:     fprintf(file, "\tregister Request *InP = &Mess.In;\n");
        !           207:     if (!rt->rtOneWay)
        !           208:        fprintf(file, "\tregister Reply *OutP = &Mess.Out;\n");
        !           209:     fprintf(file, "\n");
        !           210: 
        !           211:     if (!rt->rtOneWay || rt->rtProcedure)
        !           212:        fprintf(file, "\tmach_msg_return_t msg_result;\n");
        !           213: 
        !           214:     if (!rt->rtSimpleFixedRequest)
        !           215:        fprintf(file, "\tboolean_t msgh_simple = %s;\n",
        !           216:                strbool(rt->rtSimpleSendRequest));
        !           217:     else if (!rt->rtOneWay &&
        !           218:             !(rt->rtSimpleCheckReply && rt->rtSimpleReceiveReply)) {
        !           219:        fprintf(file, "#if\tTypeCheck\n");
        !           220:        fprintf(file, "\tboolean_t msgh_simple;\n");
        !           221:        fprintf(file, "#endif\t/* TypeCheck */\n");
        !           222:     }
        !           223: 
        !           224:     if (rt->rtNumRequestVar > 0)
        !           225:        fprintf(file, "\tunsigned int msgh_size;\n");
        !           226:     else if (!rt->rtOneWay && !rt->rtNoReplyArgs)
        !           227:     {
        !           228:        fprintf(file, "#if\tTypeCheck\n");
        !           229:        fprintf(file, "\tunsigned int msgh_size;\n");
        !           230:        fprintf(file, "#endif\t/* TypeCheck */\n");
        !           231:     }
        !           232: 
        !           233:     /* if either request or reply is variable, we need msgh_size_delta */
        !           234:     if ((rt->rtMaxRequestPos > 0) ||
        !           235:        (rt->rtMaxReplyPos > 0))
        !           236:        fprintf(file, "\tunsigned int msgh_size_delta;\n");
        !           237: 
        !           238:     fprintf(file, "\n");
        !           239: }
        !           240: 
        !           241: /*************************************************************
        !           242:  *  Writes code to call the user provided error procedure
        !           243:  *  when a MIG error occurs. Called by WriteMsgSend, 
        !           244:  *  WriteMsgCheckReceive, WriteMsgSendReceive, WriteCheckIdentity,
        !           245:  *  WriteRetCodeCheck, WriteTypeCheck, WritePackArgValue.
        !           246:  *************************************************************/
        !           247: static void
        !           248: WriteMsgError(FILE *file, const routine_t *rt, const char *error_msg)
        !           249: {
        !           250:     if (rt->rtProcedure)
        !           251:        fprintf(file, "\t\t{ %s(%s); return; }\n", rt->rtErrorName, error_msg);
        !           252:     else if (rt->rtReturn != rt->rtRetCode)
        !           253:     {
        !           254:        fprintf(file, "\t\t{ %s(%s); ", rt->rtErrorName, error_msg);
        !           255:        if (rt->rtNumReplyVar > 0)
        !           256:            fprintf(file, "OutP = &Mess.Out; ");
        !           257:        fprintf(file, "return OutP->%s; }\n", rt->rtReturn->argMsgField);
        !           258:     }
        !           259:     else
        !           260:        fprintf(file, "\t\treturn %s;\n", error_msg);
        !           261: }
        !           262: 
        !           263: /*************************************************************
        !           264:  *   Writes the send call when there is to be no subsequent
        !           265:  *   receive. Called by WriteRoutine for SimpleProcedures
        !           266:  *   or SimpleRoutines
        !           267:  *************************************************************/
        !           268: static void
        !           269: WriteMsgSend(FILE *file, const routine_t *rt)
        !           270: {
        !           271:     const char *MsgResult = (rt->rtProcedure)
        !           272:                        ? "msg_result ="
        !           273:                        : "return";
        !           274: 
        !           275:     char SendSize[24];
        !           276: 
        !           277:     if (rt->rtNumRequestVar == 0)
        !           278:         sprintf(SendSize, "%d", rt->rtRequestSize);
        !           279:     else
        !           280:        strcpy(SendSize, "msgh_size");
        !           281: 
        !           282:     if (IsKernelUser)
        !           283:     {
        !           284:        fprintf(file, "\t%s %smach_msg_send_from_kernel(",
        !           285:                MsgResult, SubrPrefix);
        !           286:        fprintf(file, "&InP->Head, %s);\n", SendSize);
        !           287:     }
        !           288:     else
        !           289:     {
        !           290:        fprintf(file, "\t%s %smach_msg(&InP->Head, MACH_SEND_MSG|%s, %s, 0,",
        !           291:                MsgResult,
        !           292:                SubrPrefix,
        !           293:                rt->rtMsgOption->argVarName,
        !           294:                SendSize);
        !           295:        fprintf(file,
        !           296:                " MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);\n"
        !           297:                );
        !           298:     }
        !           299: 
        !           300:     if (rt->rtProcedure)
        !           301:     {
        !           302:        fprintf(file, "\tif (msg_result != MACH_MSG_SUCCESS)\n");
        !           303:        WriteMsgError(file, rt, "msg_result");
        !           304:     }
        !           305: }
        !           306: 
        !           307: /*************************************************************
        !           308:  *  Writes to code to check for error returns from receive.
        !           309:  *  Called by WriteMsgSendReceive and WriteMsgRPC
        !           310:  *************************************************************/
        !           311: static void
        !           312: WriteMsgCheckReceive(FILE *file, const routine_t *rt, const char *success)
        !           313: {
        !           314:     fprintf(file, "\tif (msg_result != %s) {\n", success);
        !           315:     if (!akCheck(rt->rtUReplyPort->argKind, akbUserArg) && !IsKernelUser)
        !           316:     {
        !           317:         /* If we aren't using a user-supplied reply port,
        !           318:           then deallocate the reply port on any message transmission
        !           319:           errors. */
        !           320:        fprintf(file, "\t\t%smig_dealloc_reply_port(%s);\n",
        !           321:                SubrPrefix, "InP->Head.msgh_reply_port");
        !           322:     }
        !           323:     WriteMsgError(file, rt, "msg_result");
        !           324:     fprintf(file, "\t}\n");
        !           325: 
        !           326:     /* 
        !           327:      * If not using a user supplied reply port, tell the port
        !           328:      * allocator we're done with the port.
        !           329:      */
        !           330:     if (!akCheck(rt->rtUReplyPort->argKind, akbUserArg) && !IsKernelUser)
        !           331:     {
        !           332:        fprintf(file, "\t%smig_put_reply_port(InP->Head.msgh_reply_port);\n",
        !           333:                SubrPrefix);
        !           334:     }
        !           335: }
        !           336: 
        !           337: /*************************************************************
        !           338:  *  Writes the send and receive calls and code to check
        !           339:  *  for errors. Normally the rpc code is generated instead
        !           340:  *  although, the subsytem can be compiled with the -R option
        !           341:  *  which will cause this code to be generated. Called by
        !           342:  *  WriteRoutine if UseMsgRPC option is false.
        !           343:  *************************************************************/
        !           344: static void
        !           345: WriteMsgSendReceive(FILE *file, const routine_t *rt)
        !           346: {
        !           347:     char SendSize[24];
        !           348: 
        !           349:     if (rt->rtNumRequestVar == 0)
        !           350:         sprintf(SendSize, "%d", rt->rtRequestSize);
        !           351:     else
        !           352:        strcpy(SendSize, "msgh_size");
        !           353: 
        !           354:     fprintf(file, "\tmsg_result = %smach_msg(&InP->Head, MACH_SEND_MSG|%s, %s, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);\n",
        !           355:            SubrPrefix,
        !           356:            rt->rtMsgOption->argVarName,
        !           357:            SendSize);
        !           358: 
        !           359:     fprintf(file, "\tif (msg_result != MACH_MSG_SUCCESS)\n");
        !           360:     WriteMsgError(file, rt, "msg_result");
        !           361:     fprintf(file, "\n");
        !           362: 
        !           363:     fprintf(file, "\tmsg_result = %smach_msg(&OutP->Head, MACH_RCV_MSG|%s%s, 0, sizeof(Reply), InP->Head.msgh_local_port, %s, MACH_PORT_NULL);\n",
        !           364:            SubrPrefix,
        !           365:            rt->rtMsgOption->argVarName,
        !           366:            rt->rtWaitTime != argNULL ? "|MACH_RCV_TIMEOUT" : "",
        !           367:            rt->rtWaitTime != argNULL ? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE");
        !           368:     WriteMsgCheckReceive(file, rt, "MACH_MSG_SUCCESS");
        !           369:     fprintf(file, "\n");
        !           370: }
        !           371: 
        !           372: /*************************************************************
        !           373:  *  Writes the rpc call and the code to check for errors.
        !           374:  *  This is the default code to be generated. Called by WriteRoutine
        !           375:  *  for all routine types except SimpleProcedure and SimpleRoutine.
        !           376:  *************************************************************/
        !           377: static void
        !           378: WriteMsgRPC(FILE *file, const routine_t *rt)
        !           379: {
        !           380:     char SendSize[24];
        !           381: 
        !           382:     if (rt->rtNumRequestVar == 0)
        !           383:         sprintf(SendSize, "%d", rt->rtRequestSize);
        !           384:     else
        !           385:        strcpy(SendSize, "msgh_size");
        !           386: 
        !           387:     if (IsKernelUser)
        !           388:        fprintf(file, "\tmsg_result = %smach_msg_rpc_from_kernel(&InP->Head, %s, sizeof(Reply));\n",
        !           389:                SubrPrefix,
        !           390:                SendSize);
        !           391:     else
        !           392:        fprintf(file, "\tmsg_result = %smach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|%s%s, %s, sizeof(Reply), InP->Head.msgh_reply_port, %s, MACH_PORT_NULL);\n",
        !           393:            SubrPrefix,
        !           394:            rt->rtMsgOption->argVarName,
        !           395:            rt->rtWaitTime != argNULL ? "|MACH_RCV_TIMEOUT" : "",
        !           396:            SendSize,
        !           397:            rt->rtWaitTime != argNULL? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE");
        !           398:     WriteMsgCheckReceive(file, rt, "MACH_MSG_SUCCESS");
        !           399:     fprintf(file, "\n");
        !           400: }
        !           401: 
        !           402: /*************************************************************
        !           403:  *   Sets the correct value of the dealloc flag and calls
        !           404:  *   Utils:WritePackMsgType to fill in the ipc msg type word(s)
        !           405:  *   in the request message. Called by WriteRoutine for each
        !           406:  *   argument that is to be sent in the request message.
        !           407:  *************************************************************/
        !           408: static void
        !           409: WritePackArgType(FILE *file, const argument_t *arg)
        !           410: {
        !           411:     WritePackMsgType(file, arg->argType,
        !           412:                     arg->argType->itIndefinite ? d_NO : arg->argDeallocate,
        !           413:                     arg->argLongForm, TRUE,
        !           414:                     "InP->%s", "%s", arg->argTTName);
        !           415:     fprintf(file, "\n");
        !           416: }
        !           417: 
        !           418: /*************************************************************
        !           419:  *  Writes code to copy an argument into the request message.  
        !           420:  *  Called by WriteRoutine for each argument that is to placed
        !           421:  *  in the request message.
        !           422:  *************************************************************/
        !           423: static void
        !           424: WritePackArgValue(FILE *file, register const argument_t *arg)
        !           425: {
        !           426:     register const ipc_type_t *it = arg->argType;
        !           427:     register const char *ref = arg->argByReferenceUser ? "*" : "";
        !           428: 
        !           429:     if (it->itInLine && it->itVarArray) {
        !           430: 
        !           431:        if (it->itString) {
        !           432:            /*
        !           433:             *  Copy variable-size C string with mig_strncpy.
        !           434:             *  Save the string length (+ 1 for trailing 0)
        !           435:             *  in the argument`s count field.
        !           436:             */
        !           437:            fprintf(file,
        !           438:                "\tInP->%s = %smig_strncpy(InP->%s, %s, %d);\n",
        !           439:                arg->argCount->argMsgField,
        !           440:                SubrPrefix,
        !           441:                arg->argMsgField,
        !           442:                arg->argVarName,
        !           443:                it->itNumber);
        !           444:        }
        !           445:        else {
        !           446: 
        !           447:            /*
        !           448:             *  Copy in variable-size inline array with memcpy,
        !           449:             *  after checking that number of elements doesn`t
        !           450:             *  exceed declared maximum.
        !           451:             */
        !           452:            register const argument_t *count = arg->argCount;
        !           453:            register const char *countRef = count->argByReferenceUser ? "*" :"";
        !           454:            register const ipc_type_t *btype = it->itElement;
        !           455: 
        !           456:            /* Note btype->itNumber == count->argMultiplier */
        !           457: 
        !           458:            fprintf(file, "\tif (%s%s > %d) {\n",
        !           459:                countRef, count->argVarName,
        !           460:                it->itNumber/btype->itNumber);
        !           461:            if (it->itIndefinite) {
        !           462:                fprintf(file, "\t\tInP->%s%s.msgt_inline = FALSE;\n",
        !           463:                        arg->argTTName,
        !           464:                        arg->argLongForm ? ".msgtl_header" : "");
        !           465:                if (arg->argDeallocate == d_YES)
        !           466:                    fprintf(file, "\t\tInP->%s%s.msgt_deallocate = TRUE;\n",
        !           467:                            arg->argTTName,
        !           468:                            arg->argLongForm ? ".msgtl_header" : "");
        !           469:                else if (arg->argDeallocate == d_MAYBE)
        !           470:                    fprintf(file, "\t\tInP->%s%s.msgt_deallocate = %s%s;\n",
        !           471:                            arg->argTTName,
        !           472:                            arg->argLongForm ? ".msgtl_header" : "",
        !           473:                            arg->argDealloc->argByReferenceUser ? "*" : "",
        !           474:                            arg->argDealloc->argVarName);
        !           475:                fprintf(file, "\t\t*((%s **)InP->%s) = %s%s;\n",
        !           476:                        FetchUserType(btype),
        !           477:                        arg->argMsgField,
        !           478:                        ref, arg->argVarName);
        !           479:                if (!arg->argRoutine->rtSimpleFixedRequest)
        !           480:                    fprintf(file, "\t\tmsgh_simple = FALSE;\n");
        !           481:            }
        !           482:            else
        !           483:                WriteMsgError(file, arg->argRoutine, "MIG_ARRAY_TOO_LARGE");
        !           484: 
        !           485:            fprintf(file, "\t}\n\telse {\n");
        !           486: 
        !           487:            fprintf(file, "\t\tmemcpy(InP->%s, %s%s, ", arg->argMsgField,
        !           488:                ref, arg->argVarName);
        !           489:            if (btype->itTypeSize > 1)
        !           490:                fprintf(file, "%d * ", btype->itTypeSize);
        !           491:            fprintf(file, "%s%s);\n",
        !           492:                countRef, count->argVarName);
        !           493:            fprintf(file, "\t}\n");
        !           494:        }
        !           495:     }
        !           496:     else if (arg->argMultiplier > 1)
        !           497:        WriteCopyType(file, it, "InP->%s", "/* %s */ %d * %s%s",
        !           498:                      arg->argMsgField, arg->argMultiplier,
        !           499:                      ref, arg->argVarName);
        !           500:     else
        !           501:        WriteCopyType(file, it, "InP->%s", "/* %s */ %s%s",
        !           502:                      arg->argMsgField, ref, arg->argVarName);
        !           503:     fprintf(file, "\n");
        !           504: }
        !           505: 
        !           506: static void
        !           507: WriteAdjustMsgSimple(FILE *file, register const argument_t *arg)
        !           508: {
        !           509:     if (!arg->argRoutine->rtSimpleFixedRequest)
        !           510:     {
        !           511:        register const char *ref = arg->argByReferenceUser ? "*" : "";
        !           512: 
        !           513:        fprintf(file, "\tif (MACH_MSG_TYPE_PORT_ANY(%s%s))\n",
        !           514:                ref, arg->argVarName);
        !           515:        fprintf(file, "\t\tmsgh_simple = FALSE;\n");
        !           516:        fprintf(file, "\n");
        !           517:     }
        !           518: }
        !           519: 
        !           520: /*
        !           521:  * Calculate the size of a variable-length message field.
        !           522:  */
        !           523: static void
        !           524: WriteArgSize(FILE *file, register const argument_t *arg)
        !           525: {
        !           526:     register const ipc_type_t *ptype = arg->argType;
        !           527:     register int bsize = ptype->itElement->itTypeSize;
        !           528:     register const argument_t *count = arg->argCount;
        !           529: 
        !           530:     if (ptype->itIndefinite) {
        !           531:        /*
        !           532:         *      Check descriptor.  If out-of-line, use standard size.
        !           533:         */
        !           534:        fprintf(file, "(InP->%s%s.msgt_inline) ? ",
        !           535:                arg->argTTName, arg->argLongForm ? ".msgtl_header" : "");
        !           536:     }
        !           537:     if (bsize % 4 != 0)
        !           538:        fprintf(file, "(");
        !           539: 
        !           540:     if (bsize > 1)
        !           541:        fprintf(file, "%d * ", bsize);
        !           542: 
        !           543:     if (ptype->itString)
        !           544:        /* get count from descriptor in message */
        !           545:        fprintf(file, "InP->%s", count->argMsgField);
        !           546:     else
        !           547:        /* get count from argument */
        !           548:        fprintf(file, "%s%s",
        !           549:                count->argByReferenceUser ? "*" : "",
        !           550:                count->argVarName);
        !           551: 
        !           552:     /*
        !           553:      * If the base type size is not a multiple of sizeof(int) [4],
        !           554:      * we have to round up.
        !           555:      */
        !           556:     if (bsize % 4 != 0)
        !           557:        fprintf(file, " + 3) & ~3");
        !           558: 
        !           559:     if (ptype->itIndefinite) {
        !           560:        fprintf(file, " : sizeof(%s *)",
        !           561:                FetchUserType(ptype->itElement));
        !           562:     }
        !           563: }
        !           564: 
        !           565: /*
        !           566:  * Adjust message size and advance request pointer.
        !           567:  * Called after packing a variable-length argument that
        !           568:  * has more arguments following.
        !           569:  */
        !           570: static void
        !           571: WriteAdjustMsgSize(FILE *file, register const argument_t *arg)
        !           572: {
        !           573:     register const ipc_type_t *ptype = arg->argType;
        !           574: 
        !           575:     /* There are more In arguments.  We need to adjust msgh_size
        !           576:        and advance InP, so we save the size of the current field
        !           577:        in msgh_size_delta. */
        !           578: 
        !           579:     fprintf(file, "\tmsgh_size_delta = ");
        !           580:     WriteArgSize(file, arg);
        !           581:     fprintf(file, ";\n");
        !           582: 
        !           583:     if (arg->argRequestPos == 0)
        !           584:        /* First variable-length argument.  The previous msgh_size value
        !           585:           is the minimum request size. */
        !           586: 
        !           587:        fprintf(file, "\tmsgh_size = %d + msgh_size_delta;\n",
        !           588:                arg->argRoutine->rtRequestSize);
        !           589:     else
        !           590:        fprintf(file, "\tmsgh_size += msgh_size_delta;\n");
        !           591: 
        !           592:     fprintf(file,
        !           593:        "\tInP = (Request *) ((char *) InP + msgh_size_delta - %d);\n",
        !           594:        ptype->itTypeSize + ptype->itPadSize);
        !           595: }
        !           596: 
        !           597: /*
        !           598:  * Calculate the size of the message.  Called after the
        !           599:  * last argument has been packed.
        !           600:  */
        !           601: static void
        !           602: WriteFinishMsgSize(FILE *file, register const argument_t *arg)
        !           603: {
        !           604:     /* No more In arguments.  If this is the only variable In
        !           605:        argument, the previous msgh_size value is the minimum
        !           606:        request size. */
        !           607: 
        !           608:     if (arg->argRequestPos == 0) {
        !           609:        fprintf(file, "\tmsgh_size = %d + (",
        !           610:                        arg->argRoutine->rtRequestSize);
        !           611:        WriteArgSize(file, arg);
        !           612:        fprintf(file, ");\n");
        !           613:     }
        !           614:     else {
        !           615:         fprintf(file, "\tmsgh_size += ");
        !           616:        WriteArgSize(file, arg);
        !           617:         fprintf(file, ";\n");
        !           618:     }
        !           619: }
        !           620: 
        !           621: static void
        !           622: WriteInitializeCount(FILE *file, register const argument_t *arg)
        !           623: {
        !           624:     register const ipc_type_t *ptype = arg->argCInOut->argParent->argType;
        !           625:     register const ipc_type_t *btype = ptype->itElement;
        !           626: 
        !           627:     fprintf(file, "\tif (%s%s < %d)\n",
        !           628:            arg->argByReferenceUser ? "*" : "",
        !           629:            arg->argVarName,
        !           630:            ptype->itNumber/btype->itNumber);
        !           631:     fprintf(file, "\t\tInP->%s = %s%s;\n",
        !           632:            arg->argMsgField,
        !           633:            arg->argByReferenceUser ? "*" : "",
        !           634:            arg->argVarName);
        !           635:     fprintf(file, "\telse\n");
        !           636:     fprintf(file, "\t\tInP->%s = %d;\n",
        !           637:            arg->argMsgField, ptype->itNumber/btype->itNumber);
        !           638:     fprintf(file, "\n");
        !           639: }
        !           640: 
        !           641: /*
        !           642:  * Called for every argument.  Responsible for packing that
        !           643:  * argument into the request message.
        !           644:  */
        !           645: static void
        !           646: WritePackArg(FILE *file, register const argument_t *arg)
        !           647: {
        !           648:     if (akCheck(arg->argKind, akbRequest))
        !           649:        WritePackArgType(file, arg);
        !           650: 
        !           651:     if ((akIdent(arg->argKind) == akePoly) &&
        !           652:        akCheckAll(arg->argKind, akbSendSnd|akbUserArg))
        !           653:        WriteAdjustMsgSimple(file, arg);
        !           654: 
        !           655:     if ((akIdent(arg->argKind) == akeCountInOut) &&
        !           656:        akCheck(arg->argKind, akbSendSnd))
        !           657:        WriteInitializeCount(file, arg);
        !           658:     else if (akCheckAll(arg->argKind, akbSendSnd|akbSendBody))
        !           659:        WritePackArgValue(file, arg);
        !           660: }
        !           661: 
        !           662: /*
        !           663:  * Generate code to fill in all of the request arguments and their
        !           664:  * message types.
        !           665:  */
        !           666: static void
        !           667: WriteRequestArgs(FILE *file, register const routine_t *rt)
        !           668: {
        !           669:     register const argument_t *arg;
        !           670:     register const argument_t *lastVarArg;
        !           671: 
        !           672:     lastVarArg = argNULL;
        !           673:     for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
        !           674:     {
        !           675:        /*
        !           676:         * Adjust message size and advance message pointer if
        !           677:         * the last request argument was variable-length and the
        !           678:         * request position will change.
        !           679:         */
        !           680:        if (lastVarArg != argNULL &&
        !           681:            lastVarArg->argRequestPos < arg->argRequestPos)
        !           682:        {
        !           683:            WriteAdjustMsgSize(file, lastVarArg);
        !           684:            lastVarArg = argNULL;
        !           685:        }
        !           686: 
        !           687:        /*
        !           688:         * Copy the argument
        !           689:         */
        !           690:        WritePackArg(file, arg);
        !           691: 
        !           692:        /*
        !           693:         * Remember whether this was variable-length.
        !           694:         */
        !           695:        if (akCheckAll(arg->argKind, akbSendSnd|akbSendBody|akbVariable))
        !           696:            lastVarArg = arg;
        !           697:     }
        !           698: 
        !           699:     /*
        !           700:      * Finish the message size.
        !           701:      */
        !           702:     if (lastVarArg != argNULL)
        !           703:        WriteFinishMsgSize(file, lastVarArg);
        !           704: }
        !           705: 
        !           706: /*************************************************************
        !           707:  *  Writes code to check that the return msgh_id is correct and that
        !           708:  *  the size of the return message is correct. Called by
        !           709:  *  WriteRoutine.
        !           710:  *************************************************************/
        !           711: static void
        !           712: WriteCheckIdentity(FILE *file, const routine_t *rt)
        !           713: {
        !           714:     fprintf(file, "\tif (OutP->Head.msgh_id != %d) {\n",
        !           715:            rt->rtNumber + SubsystemBase + 100);
        !           716:     fprintf(file, "\t\tif (OutP->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)\n");
        !           717:     WriteMsgError(file, rt, "MIG_SERVER_DIED");
        !           718:     fprintf(file, "\t\telse {\n");
        !           719:     fprintf(file, "\t\t\t%smig_dealloc_reply_port(%s);\n\t",
        !           720:           SubrPrefix,"InP->Head.msgh_reply_port");
        !           721:     WriteMsgError(file, rt, "MIG_REPLY_MISMATCH");
        !           722:     fprintf(file, "\t\t}\n\t}\n");
        !           723:     fprintf(file, "\n");
        !           724:     fprintf(file, "#if\tTypeCheck\n");
        !           725: 
        !           726:     if (rt->rtSimpleCheckReply && rt->rtSimpleReceiveReply)
        !           727:     {
        !           728:        /* Expecting a simple message.  We can factor out the check for
        !           729:           a simple message, since the error reply message is also simple.
        !           730:           */
        !           731: 
        !           732:        if (!rt->rtNoReplyArgs)
        !           733:            fprintf(file, "\tmsgh_size = OutP->Head.msgh_size;\n\n");
        !           734: 
        !           735:        fprintf(file,
        !           736:            "\tif ((OutP->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
        !           737:        if (rt->rtNoReplyArgs)
        !           738:            fprintf(file, "\t    (OutP->Head.msgh_size != %d))\n",
        !           739:                        rt->rtReplySize);
        !           740:        else {
        !           741:            fprintf(file, "\t    ((msgh_size %s %d) &&\n",
        !           742:                (rt->rtNumReplyVar > 0) ? "<" : "!=",
        !           743:                rt->rtReplySize);
        !           744:            fprintf(file, "\t     ((msgh_size != sizeof(mig_reply_header_t)) ||\n");
        !           745:            fprintf(file, "\t      (OutP->RetCode == KERN_SUCCESS))))\n");
        !           746:        }
        !           747:     }
        !           748:     else {
        !           749:        /* Expecting a complex message, or may vary at run time. */
        !           750: 
        !           751:        fprintf(file, "\tmsgh_size = OutP->Head.msgh_size;\n");
        !           752:        fprintf(file, "\tmsgh_simple = !(OutP->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);\n");
        !           753:        fprintf(file, "\n");
        !           754: 
        !           755:        fprintf(file, "\tif (((msgh_size %s %d)",
        !           756:                (rt->rtNumReplyVar > 0) ? "<" : "!=",
        !           757:                rt->rtReplySize);
        !           758: 
        !           759:        if (rt->rtSimpleCheckReply)
        !           760:            /* if rtSimpleReceiveReply was true, then we would have
        !           761:               executed the code above.  So we know that the message
        !           762:               is complex. */
        !           763:            fprintf(file, " || msgh_simple");
        !           764:        fprintf(file, ") &&\n");
        !           765: 
        !           766:        fprintf(file, "\t    ((msgh_size != sizeof(mig_reply_header_t)) ||\n");
        !           767:        fprintf(file, "\t     !msgh_simple ||\n");
        !           768:        fprintf(file, "\t     (OutP->RetCode == KERN_SUCCESS)))\n");
        !           769:     }
        !           770:     WriteMsgError(file, rt, "MIG_TYPE_ERROR");
        !           771:     fprintf(file, "#endif\t/* TypeCheck */\n");
        !           772:     fprintf(file, "\n");
        !           773: }
        !           774: 
        !           775: /*************************************************************
        !           776:  *  Write code to generate error handling code if the RetCode
        !           777:  *  argument of a Routine is not KERN_SUCCESS.
        !           778:  *************************************************************/
        !           779: static void
        !           780: WriteRetCodeCheck(FILE *file, const routine_t *rt)
        !           781: {
        !           782:     fprintf(file, "\tif (OutP->RetCode != KERN_SUCCESS)\n");
        !           783:     WriteMsgError(file, rt, "OutP->RetCode");
        !           784:     fprintf(file, "\n");
        !           785: }
        !           786: 
        !           787: /*************************************************************
        !           788:  *  Writes code to check that the type of each of the arguments
        !           789:  *  in the reply message is what is expected. Called by 
        !           790:  *  WriteRoutine for each argument in the reply message.
        !           791:  *************************************************************/
        !           792: static void
        !           793: WriteTypeCheck(FILE *file, register const argument_t *arg)
        !           794: {
        !           795:     register const ipc_type_t *it = arg->argType;
        !           796:     register const routine_t *rt = arg->argRoutine;
        !           797: 
        !           798:     fprintf(file, "#if\tTypeCheck\n");
        !           799:     if (akCheck(arg->argKind, akbReplyQC))
        !           800:     {
        !           801:        fprintf(file, "\tif (* (int *) &OutP->%s != * (int *) &%sCheck)\n",
        !           802:                arg->argTTName, arg->argVarName);
        !           803:     }
        !           804:     else
        !           805:     {
        !           806:        fprintf(file, "\tif (");
        !           807:        if (!it->itIndefinite) {
        !           808:            fprintf(file, "(OutP->%s%s.msgt_inline != %s) ||\n\t    ",
        !           809:                arg->argTTName,
        !           810:                arg->argLongForm ? ".msgtl_header" : "",
        !           811:                strbool(it->itInLine));
        !           812:        }
        !           813:        fprintf(file, "(OutP->%s%s.msgt_longform != %s) ||\n",
        !           814:                arg->argTTName,
        !           815:                arg->argLongForm ? ".msgtl_header" : "",
        !           816:                strbool(arg->argLongForm));
        !           817:        if (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
        !           818:        {
        !           819:            if (!rt->rtSimpleCheckReply)
        !           820:                fprintf(file, "\t    (MACH_MSG_TYPE_PORT_ANY(OutP->%s.msgt%s_name) && msgh_simple) ||\n",
        !           821:                        arg->argTTName,
        !           822:                        arg->argLongForm ? "l" : "");
        !           823:        }
        !           824:        else
        !           825:            fprintf(file, "\t    (OutP->%s.msgt%s_name != %s) ||\n",
        !           826:                    arg->argTTName,
        !           827:                    arg->argLongForm ? "l" : "",
        !           828:                    it->itOutNameStr);
        !           829:        if (!it->itVarArray)
        !           830:            fprintf(file, "\t    (OutP->%s.msgt%s_number != %d) ||\n",
        !           831:                    arg->argTTName,
        !           832:                    arg->argLongForm ? "l" : "",
        !           833:                    it->itNumber);
        !           834:        fprintf(file, "\t    (OutP->%s.msgt%s_size != %d))\n",
        !           835:                arg->argTTName,
        !           836:                arg->argLongForm ? "l" : "",
        !           837:                it->itSize);
        !           838:     }
        !           839:     WriteMsgError(file, rt, "MIG_TYPE_ERROR");
        !           840:     fprintf(file, "#endif\t/* TypeCheck */\n");
        !           841:     fprintf(file, "\n");
        !           842: }
        !           843: 
        !           844: static void
        !           845: WriteCheckArgSize(FILE *file, register const argument_t *arg)
        !           846: {
        !           847:     register const ipc_type_t *ptype = arg->argType;
        !           848:     register const ipc_type_t *btype = ptype->itElement;
        !           849:     const argument_t *count = arg->argCount;
        !           850:     int multiplier = btype->itTypeSize / btype->itNumber;
        !           851: 
        !           852:     if (ptype->itIndefinite) {
        !           853:        /*
        !           854:         * Check descriptor.  If out-of-line, use standard size.
        !           855:         */
        !           856:        fprintf(file, "(OutP->%s%s.msgt_inline) ? ",
        !           857:                arg->argTTName, arg->argLongForm ? ".msgtl_header" : "");
        !           858:     }
        !           859: 
        !           860:     if (btype->itTypeSize % 4 != 0)
        !           861:        fprintf(file, "(");
        !           862: 
        !           863:     if (multiplier > 1)
        !           864:        fprintf(file, "%d * ", multiplier);
        !           865: 
        !           866:     fprintf(file, "OutP->%s", count->argMsgField);
        !           867: 
        !           868:     /* If the base type size of the data field isn`t a multiple of 4,
        !           869:        we have to round up. */
        !           870:     if (btype->itTypeSize % 4 != 0)
        !           871:        fprintf(file, " + 3) & ~3");
        !           872: 
        !           873:     if (ptype->itIndefinite)
        !           874:        fprintf(file, " : sizeof(%s *)", FetchUserType(btype));
        !           875: }
        !           876: 
        !           877: static void
        !           878: WriteCheckMsgSize(FILE *file, register const argument_t *arg)
        !           879: {
        !           880:     register const routine_t *rt = arg->argRoutine;
        !           881: 
        !           882:     /* If there aren't any more Out args after this, then
        !           883:        we can use the msgh_size_delta value directly in
        !           884:        the TypeCheck conditional. */
        !           885: 
        !           886:     if (arg->argReplyPos == rt->rtMaxReplyPos)
        !           887:     {
        !           888:        fprintf(file, "#if\tTypeCheck\n");
        !           889:        fprintf(file, "\tif (msgh_size != %d + (",
        !           890:                rt->rtReplySize);
        !           891:        WriteCheckArgSize(file, arg);
        !           892:        fprintf(file, "))\n");
        !           893: 
        !           894:        WriteMsgError(file, rt, "MIG_TYPE_ERROR");
        !           895:        fprintf(file, "#endif\t/* TypeCheck */\n");
        !           896:     }
        !           897:     else
        !           898:     {
        !           899:        /* If there aren't any more variable-sized arguments after this,
        !           900:           then we must check for exact msg-size and we don't need
        !           901:           to update msgh_size. */
        !           902: 
        !           903:        boolean_t LastVarArg = arg->argReplyPos+1 == rt->rtNumReplyVar;
        !           904: 
        !           905:        /* calculate the actual size in bytes of the data field.  note
        !           906:           that this quantity must be a multiple of four.  hence, if
        !           907:           the base type size isn't a multiple of four, we have to
        !           908:           round up.  note also that btype->itNumber must
        !           909:           divide btype->itTypeSize (see itCalculateSizeInfo). */
        !           910: 
        !           911:        fprintf(file, "\tmsgh_size_delta = ");
        !           912:        WriteCheckArgSize(file, arg);
        !           913:        fprintf(file, ";\n");
        !           914:        fprintf(file, "#if\tTypeCheck\n");
        !           915: 
        !           916:        /* Don't decrement msgh_size until we've checked that
        !           917:           it won't underflow. */
        !           918: 
        !           919:        if (LastVarArg)
        !           920:            fprintf(file, "\tif (msgh_size != %d + msgh_size_delta)\n",
        !           921:                rt->rtReplySize);
        !           922:        else
        !           923:            fprintf(file, "\tif (msgh_size < %d + msgh_size_delta)\n",
        !           924:                rt->rtReplySize);
        !           925:        WriteMsgError(file, rt, "MIG_TYPE_ERROR");
        !           926: 
        !           927:        if (!LastVarArg)
        !           928:            fprintf(file, "\tmsgh_size -= msgh_size_delta;\n");
        !           929: 
        !           930:        fprintf(file, "#endif\t/* TypeCheck */\n");
        !           931:     }
        !           932:     fprintf(file, "\n");
        !           933: }
        !           934: 
        !           935: /*************************************************************
        !           936:  *  Write code to copy an argument from the reply message
        !           937:  *  to the parameter. Called by WriteRoutine for each argument
        !           938:  *  in the reply message.
        !           939:  *************************************************************/
        !           940: static void
        !           941: WriteExtractArgValue(FILE *file, register const argument_t *arg)
        !           942: {
        !           943:     register const ipc_type_t  *argType = arg->argType;
        !           944:     register const char *ref = arg->argByReferenceUser ? "*" : "";
        !           945: 
        !           946:     if (argType->itInLine && argType->itVarArray) {
        !           947: 
        !           948:        if (argType->itString) {
        !           949:            /*
        !           950:             *  Copy out variable-size C string with mig_strncpy.
        !           951:             */
        !           952:            fprintf(file, "\t(void) %smig_strncpy(%s%s, OutP->%s, %d);\n",
        !           953:                SubrPrefix,
        !           954:                ref,
        !           955:                arg->argVarName,
        !           956:                arg->argMsgField,
        !           957:                argType->itNumber);
        !           958:        }
        !           959:        else if (argType->itIndefinite) {
        !           960:            /*
        !           961:             * If data was returned out-of-line,
        !           962:             *    change user`s pointer to point to it.
        !           963:             * If data was returned in-line but doesn`t fit,
        !           964:             *    allocate a new buffer, copy the data to it,
        !           965:             *    and change user`s pointer to point to it.
        !           966:             * If data was returned in-line and fits,
        !           967:             *    copy to buffer.
        !           968:             */
        !           969:            const argument_t *count = arg->argCount;
        !           970:            const char *countRef = count->argByReferenceUser ? "*" : "";
        !           971:            const ipc_type_t *btype = argType->itElement;
        !           972: 
        !           973:            fprintf(file, "\tif (!OutP->%s%s.msgt_inline)\n",
        !           974:                    arg->argTTName,
        !           975:                    arg->argLongForm ? ".msgtl_header" : "");
        !           976:            fprintf(file, "\t    %s%s = *((%s **)OutP->%s);\n",
        !           977:                    ref, arg->argVarName,
        !           978:                    FetchUserType(btype), arg->argMsgField);
        !           979:            fprintf(file, "\telse if (OutP->%s", count->argMsgField);
        !           980:            if (btype->itNumber > 1)
        !           981:                fprintf(file, " / %d", btype->itNumber);
        !           982:            fprintf(file, " > %s%s) {\n", countRef, count->argVarName);
        !           983:            fprintf(file, "\t    %smig_allocate((vm_offset_t *)%s,\n\t\t",
        !           984:                    SubrPrefix, arg->argVarName);       /* no ref! */
        !           985:            if (btype->itTypeSize != btype->itNumber)
        !           986:                fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
        !           987:            fprintf(file, "OutP->%s);\n", count->argMsgField);
        !           988:            fprintf(file, "\t    memcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
        !           989:                    arg->argMsgField);
        !           990:            if (btype->itTypeSize != btype->itNumber)
        !           991:                fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
        !           992:            fprintf(file, "OutP->%s);\n", count->argMsgField);
        !           993:            fprintf(file, "\t}\n");
        !           994:            fprintf(file, "\telse {\n");
        !           995: 
        !           996:            fprintf(file, "\t    memcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
        !           997:                    arg->argMsgField);
        !           998:            if (btype->itTypeSize != btype->itNumber)
        !           999:                fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
        !          1000:            fprintf(file, "OutP->%s);\n", count->argMsgField);
        !          1001:            fprintf(file, "\t}\n");
        !          1002:        }
        !          1003:        else {
        !          1004: 
        !          1005:            /*
        !          1006:             *  Copy out variable-size inline array with memcpy,
        !          1007:             *  after checking that number of elements doesn`t
        !          1008:             *  exceed user`s maximum.
        !          1009:             */
        !          1010:            register const argument_t *count = arg->argCount;
        !          1011:            register const char *countRef = count->argByReferenceUser ? "*" :"";
        !          1012:            register const ipc_type_t *btype = argType->itElement;
        !          1013: 
        !          1014:            /* Note count->argMultiplier == btype->itNumber */
        !          1015: 
        !          1016:            fprintf(file, "\tif (OutP->%s", count->argMsgField);
        !          1017:            if (btype->itNumber > 1)
        !          1018:                fprintf(file, " / %d", btype->itNumber);
        !          1019:            fprintf(file, " > %s%s) {\n",
        !          1020:                countRef, count->argVarName);
        !          1021: 
        !          1022:            /*
        !          1023:             * If number of elements is too many for user receiving area,
        !          1024:             * fill user`s area as much as possible.  Return the correct
        !          1025:             * number of elements.
        !          1026:             */
        !          1027:            fprintf(file, "\t\tmemcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
        !          1028:                    arg->argMsgField);
        !          1029:            if (btype->itTypeSize > 1)
        !          1030:                fprintf(file, "%d * ", btype->itTypeSize);
        !          1031:            fprintf(file, "%s%s);\n",
        !          1032:                countRef, count->argVarName);
        !          1033: 
        !          1034:            fprintf(file, "\t\t%s%s = OutP->%s",
        !          1035:                     countRef, count->argVarName, count->argMsgField);
        !          1036:            if (btype->itNumber > 1)
        !          1037:                fprintf(file, " / %d", btype->itNumber);
        !          1038:            fprintf(file, ";\n");
        !          1039:            WriteMsgError(file,arg->argRoutine, "MIG_ARRAY_TOO_LARGE");
        !          1040: 
        !          1041:            fprintf(file, "\t}\n\telse {\n");
        !          1042: 
        !          1043:            fprintf(file, "\t\tmemcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
        !          1044:                    arg->argMsgField);
        !          1045:            if (btype->itTypeSize != btype->itNumber)
        !          1046:                fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
        !          1047:            fprintf(file, "OutP->%s);\n", count->argMsgField);
        !          1048:            fprintf(file, "\t}\n");
        !          1049:        }
        !          1050:     }
        !          1051:     else if (arg->argMultiplier > 1)
        !          1052:        WriteCopyType(file, argType,
        !          1053:                      "%s%s", "/* %s%s */ OutP->%s / %d",
        !          1054:                      ref, arg->argVarName, arg->argMsgField,
        !          1055:                      arg->argMultiplier);
        !          1056:     else
        !          1057:        WriteCopyType(file, argType,
        !          1058:                      "%s%s", "/* %s%s */ OutP->%s",
        !          1059:                      ref, arg->argVarName, arg->argMsgField);
        !          1060:     fprintf(file, "\n");
        !          1061: }
        !          1062: 
        !          1063: static void
        !          1064: WriteExtractArg(FILE *file, register const argument_t *arg)
        !          1065: {
        !          1066:     register const routine_t *rt = arg->argRoutine;
        !          1067: 
        !          1068:     if (akCheck(arg->argKind, akbReply))
        !          1069:        WriteTypeCheck(file, arg);
        !          1070: 
        !          1071:     if (akCheckAll(arg->argKind, akbVariable|akbReply))
        !          1072:        WriteCheckMsgSize(file, arg);
        !          1073: 
        !          1074:     /* Now that the RetCode is type-checked, check its value.
        !          1075:        Must abort immediately if it isn't KERN_SUCCESS, because
        !          1076:        in that case the reply message is truncated. */
        !          1077: 
        !          1078:     if (arg == rt->rtRetCode)
        !          1079:        WriteRetCodeCheck(file, rt);
        !          1080: 
        !          1081:     if (akCheckAll(arg->argKind, akbReturnRcv))
        !          1082:        WriteExtractArgValue(file, arg);
        !          1083: }
        !          1084: 
        !          1085: static void
        !          1086: WriteAdjustReplyMsgPtr(FILE *file, register const argument_t *arg)
        !          1087: {
        !          1088:     register const ipc_type_t *ptype = arg->argType;
        !          1089: 
        !          1090:     fprintf(file,
        !          1091:        "\tOutP = (Reply *) ((char *) OutP + msgh_size_delta - %d);\n\n",
        !          1092:        ptype->itTypeSize + ptype->itPadSize);
        !          1093: }
        !          1094: 
        !          1095: static void
        !          1096: WriteReplyArgs(FILE *file, register const routine_t *rt)
        !          1097: {
        !          1098:     register const argument_t *arg;
        !          1099:     register const argument_t *lastVarArg;
        !          1100: 
        !          1101:     lastVarArg = argNULL;
        !          1102:     for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
        !          1103: 
        !          1104:        /*
        !          1105:         * Advance message pointer if the last reply argument was
        !          1106:         * variable-length and the reply position will change.
        !          1107:         */
        !          1108:        if (lastVarArg != argNULL &&
        !          1109:            lastVarArg->argReplyPos < arg->argReplyPos)
        !          1110:        {
        !          1111:            WriteAdjustReplyMsgPtr(file, lastVarArg);
        !          1112:            lastVarArg = argNULL;
        !          1113:        }
        !          1114: 
        !          1115:        /*
        !          1116:         * Copy the argument
        !          1117:         */
        !          1118:        WriteExtractArg(file, arg);
        !          1119: 
        !          1120:        /*
        !          1121:         * Remember whether this was variable-length.
        !          1122:         */
        !          1123:        if (akCheckAll(arg->argKind, akbReturnRcv|akbVariable))
        !          1124:            lastVarArg = arg;
        !          1125:     }
        !          1126: }
        !          1127: 
        !          1128: /*************************************************************
        !          1129:  *  Writes code to return the return value. Called by WriteRoutine
        !          1130:  *  for routines and functions.
        !          1131:  *************************************************************/
        !          1132: static void
        !          1133: WriteReturnValue(FILE *file, const routine_t *rt)
        !          1134: {
        !          1135:     if (rt->rtReturn == rt->rtRetCode)
        !          1136:        /* If returning RetCode, we have already checked that it is
        !          1137:           KERN_SUCCESS */
        !          1138:        fprintf(file, "\treturn KERN_SUCCESS;\n");
        !          1139: 
        !          1140:     else
        !          1141:     {
        !          1142:        if (rt->rtNumReplyVar > 0)
        !          1143:            fprintf(file, "\tOutP = &Mess.Out;\n");
        !          1144: 
        !          1145:        fprintf(file, "\treturn OutP->%s;\n", rt->rtReturn->argMsgField);
        !          1146:     }
        !          1147: }
        !          1148: 
        !          1149: /*************************************************************
        !          1150:  *  Writes the elements of the message type declaration: the
        !          1151:  *  msg_type structure, the argument itself and any padding 
        !          1152:  *  that is required to make the argument a multiple of 4 bytes.
        !          1153:  *  Called by WriteRoutine for all the arguments in the request
        !          1154:  *  message first and then the reply message.
        !          1155:  *************************************************************/
        !          1156: static void
        !          1157: WriteFieldDecl(FILE *file, const argument_t *arg)
        !          1158: {
        !          1159:     WriteFieldDeclPrim(file, arg, FetchUserType);
        !          1160: }
        !          1161: 
        !          1162: static void
        !          1163: WriteStubDecl(FILE *file, register const routine_t *rt)
        !          1164: {
        !          1165:     fprintf(file, "\n");
        !          1166:     fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
        !          1167:     fprintf(file, "mig_external %s %s\n", ReturnTypeStr(rt), rt->rtUserName);
        !          1168:     fprintf(file, "(\n");
        !          1169:     WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n");
        !          1170:     fprintf(file, ")\n");
        !          1171:     fprintf(file, "{\n");
        !          1172: }
        !          1173: 
        !          1174: /*************************************************************
        !          1175:  *  Writes all the code comprising a routine body. Called by
        !          1176:  *  WriteUser for each routine.
        !          1177:  *************************************************************/
        !          1178: static void
        !          1179: WriteRoutine(FILE *file, register const routine_t *rt)
        !          1180: {
        !          1181:     /* write the stub's declaration */
        !          1182: 
        !          1183:     WriteStubDecl(file, rt);
        !          1184: 
        !          1185:     /* typedef of structure for Request and Reply messages */
        !          1186: 
        !          1187:     WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request");
        !          1188:     if (!rt->rtOneWay)
        !          1189:        WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply, "Reply");
        !          1190: 
        !          1191:     /* declarations for local vars: Union of Request and Reply messages,
        !          1192:        InP, OutP and return value */
        !          1193: 
        !          1194:     WriteVarDecls(file, rt);
        !          1195: 
        !          1196:     /* declarations and initializations of the mach_msg_type_t variables
        !          1197:        for each argument */
        !          1198: 
        !          1199:     WriteList(file, rt->rtArgs, WriteTypeDeclIn, akbRequest, "\n", "\n");
        !          1200:     if (!rt->rtOneWay)
        !          1201:        WriteList(file, rt->rtArgs, WriteCheckDecl, akbReplyQC, "\n", "\n");
        !          1202: 
        !          1203:     /* fill in all the request message types and then arguments */
        !          1204: 
        !          1205:     WriteRequestArgs(file, rt);
        !          1206: 
        !          1207:     /* fill in request message head */
        !          1208: 
        !          1209:     WriteRequestHead(file, rt);
        !          1210:     fprintf(file, "\n");
        !          1211: 
        !          1212:     /* Write the send/receive or rpc call */
        !          1213: 
        !          1214:     if (rt->rtOneWay)
        !          1215:        WriteMsgSend(file, rt);
        !          1216:     else
        !          1217:     {
        !          1218:        if (UseMsgRPC)
        !          1219:            WriteMsgRPC(file, rt);
        !          1220:        else
        !          1221:            WriteMsgSendReceive(file, rt);
        !          1222: 
        !          1223:        /* Check the values that are returned in the reply message */
        !          1224: 
        !          1225:        WriteCheckIdentity(file, rt);
        !          1226: 
        !          1227:        /* If the reply message has no Out parameters or return values
        !          1228:           other than the return code, we can type-check it and
        !          1229:           return it directly. */
        !          1230: 
        !          1231:        if (rt->rtNoReplyArgs)
        !          1232:        {
        !          1233:            WriteTypeCheck(file, rt->rtRetCode);
        !          1234: 
        !          1235:            fprintf(file, "\treturn OutP->RetCode;\n");
        !          1236:        }
        !          1237:        else {
        !          1238:            WriteReplyArgs(file, rt);
        !          1239: 
        !          1240:            /* return the return value, if any */
        !          1241: 
        !          1242:            if (rt->rtProcedure)
        !          1243:                fprintf(file, "\t/* Procedure - no return needed */\n");
        !          1244:            else
        !          1245:                WriteReturnValue(file, rt);
        !          1246:        }
        !          1247:     }
        !          1248: 
        !          1249:     fprintf(file, "}\n");
        !          1250: }
        !          1251: 
        !          1252: /*************************************************************
        !          1253:  *  Writes out the xxxUser.c file. Called by mig.c
        !          1254:  *************************************************************/
        !          1255: void
        !          1256: WriteUser(FILE *file, const statement_t *stats)
        !          1257: {
        !          1258:     register const statement_t *stat;
        !          1259: 
        !          1260:     WriteProlog(file);
        !          1261:     for (stat = stats; stat != stNULL; stat = stat->stNext)
        !          1262:        switch (stat->stKind)
        !          1263:        {
        !          1264:          case skRoutine:
        !          1265:            WriteRoutine(file, stat->stRoutine);
        !          1266:            break;
        !          1267:          case skImport:
        !          1268:          case skUImport:
        !          1269:            WriteImport(file, stat->stFileName);
        !          1270:            break;
        !          1271:          case skSImport:
        !          1272:            break;
        !          1273:          default:
        !          1274:            fatal("WriteUser(): bad statement_kind_t (%d)",
        !          1275:                  (int) stat->stKind);
        !          1276:        }
        !          1277:     WriteEpilog(file);
        !          1278: }
        !          1279: 
        !          1280: /*************************************************************
        !          1281:  *  Writes out individual .c user files for each routine.  Called by mig.c
        !          1282:  *************************************************************/
        !          1283: void
        !          1284: WriteUserIndividual(const statement_t *stats)
        !          1285: {
        !          1286:     register const statement_t *stat;
        !          1287: 
        !          1288:     for (stat = stats; stat != stNULL; stat = stat->stNext)
        !          1289:        switch (stat->stKind)
        !          1290:        {
        !          1291:          case skRoutine:
        !          1292:            {
        !          1293:                FILE *file;
        !          1294:                register char *filename;
        !          1295: 
        !          1296:                filename = strconcat(UserFilePrefix,
        !          1297:                                     strconcat(stat->stRoutine->rtName, ".c"));
        !          1298:                file = fopen(filename, "w");
        !          1299:                if (file == NULL)
        !          1300:                    fatal("fopen(%s): %s", filename,
        !          1301:                          unix_error_string(errno));
        !          1302:                WriteProlog(file);
        !          1303: 
        !          1304:                {
        !          1305:                  /* Write all the imports.  */
        !          1306:                  const statement_t *s;
        !          1307:                  for (s = stats; s != stNULL; s = s->stNext)
        !          1308:                    switch (s->stKind)
        !          1309:                      {
        !          1310:                      case skImport:
        !          1311:                      case skUImport:
        !          1312:                        WriteImport(file, s->stFileName);
        !          1313:                        break;
        !          1314:                      }
        !          1315:                }
        !          1316: 
        !          1317:                WriteRoutine(file, stat->stRoutine);
        !          1318:                WriteEpilog(file);
        !          1319:                fclose(file);
        !          1320:                strfree(filename);
        !          1321:            }
        !          1322:            break;
        !          1323:          case skImport:
        !          1324:          case skUImport:
        !          1325:            break;
        !          1326:          case skSImport:
        !          1327:            break;
        !          1328:          default:
        !          1329:            fatal("WriteUserIndividual(): bad statement_kind_t (%d)",
        !          1330:                  (int) stat->stKind);
        !          1331:        }
        !          1332: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.