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

1.1     ! root        1: /* 
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 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 "AS IS"
        !            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 Mellon
        !            24:  * the rights to redistribute these changes.
        !            25:  */
        !            26: 
        !            27: #include <assert.h>
        !            28: 
        !            29: #include "write.h"
        !            30: #include "utils.h"
        !            31: #include "global.h"
        !            32: #include "error.h"
        !            33: #include "cpu.h"
        !            34: 
        !            35: static void
        !            36: WriteIncludes(FILE *file)
        !            37: {
        !            38:     fprintf(file, "#define EXPORT_BOOLEAN\n");
        !            39:     fprintf(file, "#include <mach/boolean.h>\n");
        !            40:     fprintf(file, "#include <mach/kern_return.h>\n");
        !            41:     fprintf(file, "#include <mach/message.h>\n");
        !            42:     fprintf(file, "#include <mach/mig_errors.h>\n");
        !            43:     fprintf(file, "#include <mach/mig_support.h>\n");
        !            44:     if (IsKernelServer)
        !            45:        fprintf(file, "#include <ipc/ipc_port.h>\n");
        !            46:     fprintf(file, "\n");
        !            47: }
        !            48: 
        !            49: static void
        !            50: WriteGlobalDecls(FILE *file)
        !            51: {
        !            52:     if (RCSId != strNULL)
        !            53:        WriteRCSDecl(file, strconcat(SubsystemName, "_server"), RCSId);
        !            54: 
        !            55:     /* Used for locations in the request message, *not* reply message.
        !            56:        Reply message locations aren't dependent on IsKernelServer. */
        !            57: 
        !            58:     if (IsKernelServer)
        !            59:     {
        !            60:        fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n");
        !            61:        fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)");
        !            62:        fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n");
        !            63:        fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n");
        !            64:        fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)");
        !            65:        fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n");
        !            66:     }
        !            67:     else
        !            68:     {
        !            69:        fprintf(file, "#define msgh_request_port\tmsgh_local_port\n");
        !            70:        fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)");
        !            71:        fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n");
        !            72:        fprintf(file, "#define msgh_reply_port\t\tmsgh_remote_port\n");
        !            73:        fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)");
        !            74:        fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n");
        !            75:     }
        !            76:     fprintf(file, "\n");
        !            77: }
        !            78: 
        !            79: static void
        !            80: WriteProlog(FILE *file)
        !            81: {
        !            82:     fprintf(file, "/* Module %s */\n", SubsystemName);
        !            83:     fprintf(file, "\n");
        !            84:     
        !            85:     WriteIncludes(file);
        !            86:     WriteBogusDefines(file);
        !            87:     WriteGlobalDecls(file);
        !            88: }
        !            89: 
        !            90: 
        !            91: static void
        !            92: WriteSymTabEntries(FILE *file, const statement_t *stats)
        !            93: {
        !            94:     register const statement_t *stat;
        !            95:     register u_int current = 0;
        !            96: 
        !            97:     for (stat = stats; stat != stNULL; stat = stat->stNext)
        !            98:        if (stat->stKind == skRoutine) {
        !            99:            register    num = stat->stRoutine->rtNumber;
        !           100:            const char  *name = stat->stRoutine->rtName;
        !           101: 
        !           102:            while (++current <= num)
        !           103:                fprintf(file,"\t\t\t{ \"\", 0, 0 },\n");
        !           104:            fprintf(file, "\t{ \"%s\", %d, _X%s },\n",
        !           105:                name,
        !           106:                SubsystemBase + current - 1,
        !           107:                name);
        !           108:        }
        !           109:     while (++current <= rtNumber)
        !           110:        fprintf(file,"\t{ \"\", 0, 0 },\n");
        !           111: }
        !           112: 
        !           113: static void
        !           114: WriteArrayEntries(FILE *file, const statement_t *stats)
        !           115: {
        !           116:     register u_int current = 0;
        !           117:     register const statement_t *stat;
        !           118: 
        !           119:     for (stat = stats; stat != stNULL; stat = stat->stNext)
        !           120:        if (stat->stKind == skRoutine)
        !           121:        {
        !           122:            register const routine_t *rt = stat->stRoutine;
        !           123: 
        !           124:            while (current++ < rt->rtNumber)
        !           125:                fprintf(file, "\t\t0,\n");
        !           126:            fprintf(file, "\t\t_X%s,\n", rt->rtName);
        !           127:        }
        !           128:     while (current++ < rtNumber)
        !           129:        fprintf(file, "\t\t\t0,\n");
        !           130: }
        !           131: 
        !           132: static void
        !           133: WriteEpilog(FILE *file, const statement_t *stats)
        !           134: {
        !           135:     fprintf(file, "\n");
        !           136: 
        !           137:     /*
        !           138:      * First, the symbol table
        !           139:      */
        !           140:      fprintf(file, "static mig_routine_t %s_routines[] = {\n", ServerDemux);
        !           141: 
        !           142:      WriteArrayEntries(file, stats);
        !           143: 
        !           144:      fprintf(file, "};\n");
        !           145:      fprintf(file, "\n");
        !           146: 
        !           147:      /*
        !           148:       * Then, the server routine
        !           149:       */
        !           150:     fprintf(file, "mig_external boolean_t %s\n", ServerDemux);
        !           151:     fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
        !           152: 
        !           153:     fprintf(file, "{\n");
        !           154:     fprintf(file, "\tregister mach_msg_header_t *InP =  InHeadP;\n");
        !           155: 
        !           156:     fprintf(file, "\tregister mig_reply_header_t *OutP = (mig_reply_header_t *) OutHeadP;\n");
        !           157: 
        !           158:     fprintf(file, "\n");
        !           159: 
        !           160:     WriteStaticDecl(file, itRetCodeType,
        !           161:                    itRetCodeType->itDeallocate, itRetCodeType->itLongForm,
        !           162:                    !IsKernelServer, "RetCodeType");
        !           163:     fprintf(file, "\n");
        !           164: 
        !           165:     fprintf(file, "\tregister mig_routine_t routine;\n");
        !           166:     fprintf(file, "\n");
        !           167: 
        !           168:     fprintf(file, "\tOutP->Head.msgh_bits = ");
        !           169:     fprintf(file, "MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InP->msgh_bits), 0);\n");
        !           170:     fprintf(file, "\tOutP->Head.msgh_size = sizeof *OutP;\n");
        !           171:     fprintf(file, "\tOutP->Head.msgh_remote_port = InP->msgh_reply_port;\n");
        !           172:     fprintf(file, "\tOutP->Head.msgh_local_port = MACH_PORT_NULL;\n");
        !           173:     fprintf(file, "\tOutP->Head.msgh_seqno = 0;\n");
        !           174:     fprintf(file, "\tOutP->Head.msgh_id = InP->msgh_id + 100;\n");
        !           175:     fprintf(file, "\n");
        !           176:     WritePackMsgType(file, itRetCodeType,
        !           177:                     itRetCodeType->itDeallocate, itRetCodeType->itLongForm,
        !           178:                     !IsKernelServer, "OutP->RetCodeType", "RetCodeType");
        !           179:     fprintf(file, "\n");
        !           180: 
        !           181:     fprintf(file, "\tif ((InP->msgh_id > %d) || (InP->msgh_id < %d) ||\n",
        !           182:            SubsystemBase + rtNumber - 1, SubsystemBase);
        !           183:     fprintf(file, "\t    ((routine = %s_routines[InP->msgh_id - %d]) == 0)) {\n",
        !           184:            ServerDemux, SubsystemBase);
        !           185:     fprintf(file, "\t\tOutP->RetCode = MIG_BAD_ID;\n");
        !           186:     fprintf(file, "\t\treturn FALSE;\n");
        !           187:     fprintf(file, "\t}\n");
        !           188: 
        !           189:     /* Call appropriate routine */
        !           190:     fprintf(file, "\t(*routine) (InP, &OutP->Head);\n");
        !           191:     fprintf(file, "\treturn TRUE;\n");
        !           192:     fprintf(file, "}\n");
        !           193:     fprintf(file, "\n");
        !           194: 
        !           195:     /*
        !           196:      * Then, the <subsystem>_server_routine routine
        !           197:      */
        !           198:     fprintf(file, "mig_external mig_routine_t %s_routine\n", ServerDemux);
        !           199:     fprintf(file, "\t(const mach_msg_header_t *InHeadP)\n");
        !           200: 
        !           201:     fprintf(file, "{\n");
        !           202:     fprintf(file, "\tregister int msgh_id;\n");
        !           203:     fprintf(file, "\n");
        !           204:     fprintf(file, "\tmsgh_id = InHeadP->msgh_id - %d;\n", SubsystemBase);
        !           205:     fprintf(file, "\n");
        !           206:     fprintf(file, "\tif ((msgh_id > %d) || (msgh_id < 0))\n",
        !           207:            rtNumber - 1);
        !           208:     fprintf(file, "\t\treturn 0;\n");
        !           209:     fprintf(file, "\n");
        !           210:     fprintf(file, "\treturn %s_routines[msgh_id];\n", ServerDemux);
        !           211:     fprintf(file, "}\n");
        !           212:     fprintf(file, "\n");
        !           213: 
        !           214:     /* symtab */
        !           215: 
        !           216:     if (GenSymTab) {
        !           217:        fprintf(file,"\nmig_symtab_t _%sSymTab[] = {\n",SubsystemName);
        !           218:        WriteSymTabEntries(file,stats);
        !           219:        fprintf(file,"};\n");
        !           220:        fprintf(file,"int _%sSymTabBase = %d;\n",SubsystemName,SubsystemBase);
        !           221:        fprintf(file,"int _%sSymTabEnd = %d;\n",SubsystemName,SubsystemBase+rtNumber);
        !           222:     }
        !           223: }
        !           224: 
        !           225: /*
        !           226:  *  Returns the return type of the server-side work function.
        !           227:  *  Suitable for "extern %s serverfunc()".
        !           228:  */
        !           229: static const char *
        !           230: ServerSideType(const routine_t *rt)
        !           231: {
        !           232:     if (rt->rtServerReturn == argNULL)
        !           233:        return "void";
        !           234:     else
        !           235:        return rt->rtServerReturn->argType->itTransType;
        !           236: }
        !           237: 
        !           238: static void
        !           239: WriteLocalVarDecl(FILE *file, register const argument_t *arg)
        !           240: {
        !           241:     register const ipc_type_t *it = arg->argType;
        !           242: 
        !           243:     if (it->itInLine && it->itVarArray)
        !           244:     {
        !           245:        register const ipc_type_t *btype = it->itElement;
        !           246: 
        !           247:        fprintf(file, "\t%s %s[%d]", btype->itTransType,
        !           248:                arg->argVarName, it->itNumber/btype->itNumber);
        !           249:     }
        !           250:     else
        !           251:        fprintf(file, "\t%s %s", it->itTransType, arg->argVarName);
        !           252: }
        !           253: 
        !           254: static void
        !           255: WriteLocalPtrDecl(FILE *file, register const argument_t *arg)
        !           256: {
        !           257:     fprintf(file, "\t%s *%sP",
        !           258:                FetchServerType(arg->argType->itElement),
        !           259:                arg->argVarName);
        !           260: }
        !           261: 
        !           262: static void
        !           263: WriteServerArgDecl(FILE *file, const argument_t *arg)
        !           264: {
        !           265:     fprintf(file, "%s %s%s",
        !           266:            arg->argType->itTransType,
        !           267:            arg->argByReferenceServer ? "*" : "",
        !           268:            arg->argVarName);
        !           269: }
        !           270: 
        !           271: /*
        !           272:  *  Writes the local variable declarations which are always
        !           273:  *  present:  InP, OutP, the server-side work function.
        !           274:  */
        !           275: static void
        !           276: WriteVarDecls(FILE *file, const routine_t *rt)
        !           277: {
        !           278:     int i;
        !           279:     boolean_t NeedMsghSize = FALSE;
        !           280:     boolean_t NeedMsghSizeDelta = FALSE;
        !           281: 
        !           282:     fprintf(file, "\tregister Request *In0P = (Request *) InHeadP;\n");
        !           283:     for (i = 1; i <= rt->rtMaxRequestPos; i++)
        !           284:        fprintf(file, "\tregister Request *In%dP;\n", i);
        !           285:     fprintf(file, "\tregister Reply *OutP = (Reply *) OutHeadP;\n");
        !           286: 
        !           287:     fprintf(file, "\tmig_external %s %s\n",
        !           288:            ServerSideType(rt), rt->rtServerName);
        !           289:     fprintf(file, "\t\t(");
        !           290:     WriteList(file, rt->rtArgs, WriteServerArgDecl, akbServerArg, ", ", "");
        !           291:     fprintf(file, ");\n");
        !           292:     fprintf(file, "\n");
        !           293: 
        !           294:     if (!rt->rtSimpleFixedReply)
        !           295:        fprintf(file, "\tboolean_t msgh_simple;\n");
        !           296:     else if (!rt->rtSimpleCheckRequest)
        !           297:     {
        !           298:        fprintf(file, "#if\tTypeCheck\n");
        !           299:        fprintf(file, "\tboolean_t msgh_simple;\n");
        !           300:        fprintf(file, "#endif\t/* TypeCheck */\n");
        !           301:        fprintf(file, "\n");
        !           302:     }
        !           303: 
        !           304:     /* if either request or reply is variable, we may need
        !           305:        msgh_size_delta and msgh_size */
        !           306: 
        !           307:     if (rt->rtNumRequestVar > 0)
        !           308:        NeedMsghSize = TRUE;
        !           309:     if (rt->rtMaxRequestPos > 0)
        !           310:        NeedMsghSizeDelta = TRUE;
        !           311: 
        !           312:     if (rt->rtNumReplyVar > 1)
        !           313:        NeedMsghSize = TRUE;
        !           314:     if (rt->rtMaxReplyPos > 0)
        !           315:        NeedMsghSizeDelta = TRUE;
        !           316: 
        !           317:     if (NeedMsghSize)
        !           318:        fprintf(file, "\tunsigned int msgh_size;\n");
        !           319:     if (NeedMsghSizeDelta)
        !           320:        fprintf(file, "\tunsigned int msgh_size_delta;\n");
        !           321: 
        !           322:     if (NeedMsghSize || NeedMsghSizeDelta)
        !           323:        fprintf(file, "\n");
        !           324: }
        !           325: 
        !           326: static void
        !           327: WriteMsgError(FILE *file, const char *error_msg)
        !           328: {
        !           329:     fprintf(file, "\t\t{ OutP->RetCode = %s; return; }\n", error_msg);
        !           330: }
        !           331: 
        !           332: static void
        !           333: WriteReplyInit(FILE *file, const routine_t *rt)
        !           334: {
        !           335:     boolean_t printed_nl = FALSE;
        !           336: 
        !           337:     if (rt->rtSimpleFixedReply)
        !           338:     {
        !           339:        if (!rt->rtSimpleSendReply) /* complex reply message */
        !           340:        {
        !           341:            printed_nl = TRUE;
        !           342:            fprintf(file, "\n");
        !           343:            fprintf(file,
        !           344:                "\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n");
        !           345:        }
        !           346:     }
        !           347:     else
        !           348:     {
        !           349:        printed_nl = TRUE;
        !           350:        fprintf(file, "\n");
        !           351:        fprintf(file, "\tmsgh_simple = %s;\n", 
        !           352:                          strbool(rt->rtSimpleSendReply));
        !           353:     }
        !           354: 
        !           355:     if (rt->rtNumReplyVar == 0)
        !           356:     {
        !           357:        if (!printed_nl)
        !           358:            fprintf(file, "\n");
        !           359:        fprintf(file, "\tOutP->Head.msgh_size = %d;\n", rt->rtReplySize);
        !           360:     }
        !           361: }
        !           362: 
        !           363: static void
        !           364: WriteReplyHead(FILE *file, const routine_t *rt)
        !           365: {
        !           366:     if ((!rt->rtSimpleFixedReply) ||
        !           367:        (rt->rtNumReplyVar > 1))
        !           368:     {
        !           369:        fprintf(file, "\n");
        !           370:        if (rt->rtMaxReplyPos > 0)
        !           371:            fprintf(file, "\tOutP = (Reply *) OutHeadP;\n");
        !           372:     }
        !           373: 
        !           374:     if (!rt->rtSimpleFixedReply)
        !           375:     {
        !           376:        fprintf(file, "\tif (!msgh_simple)\n");
        !           377:        fprintf(file,
        !           378:                "\t\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n");
        !           379:     }
        !           380:     if (rt->rtNumReplyVar > 1)
        !           381:        fprintf(file, "\tOutP->Head.msgh_size = msgh_size;\n");
        !           382: }
        !           383: 
        !           384: static void
        !           385: WriteCheckHead(FILE *file, const routine_t *rt)
        !           386: {
        !           387:     fprintf(file, "#if\tTypeCheck\n");
        !           388:     if (rt->rtNumRequestVar > 0)
        !           389:        fprintf(file, "\tmsgh_size = In0P->Head.msgh_size;\n");
        !           390:     if (!rt->rtSimpleCheckRequest)
        !           391:        fprintf(file, "\tmsgh_simple = !(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);\n");
        !           392: 
        !           393:     if (rt->rtNumRequestVar > 0)
        !           394:        fprintf(file, "\tif ((msgh_size < %d)",
        !           395:                rt->rtRequestSize);
        !           396:     else
        !           397:        fprintf(file, "\tif ((In0P->Head.msgh_size != %d)",
        !           398:                rt->rtRequestSize);
        !           399: 
        !           400:     if (rt->rtSimpleCheckRequest)
        !           401:        fprintf(file, " ||\n\t    %s(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)",
        !           402:                rt->rtSimpleReceiveRequest ? "" : "!");
        !           403:     fprintf(file, ")\n");
        !           404:     WriteMsgError(file, "MIG_BAD_ARGUMENTS");
        !           405:     fprintf(file, "#endif\t/* TypeCheck */\n");
        !           406:     fprintf(file, "\n");
        !           407: }
        !           408: 
        !           409: static void
        !           410: WriteTypeCheck(FILE *file, register const argument_t *arg)
        !           411: {
        !           412:     register const ipc_type_t *it = arg->argType;
        !           413:     register const routine_t *rt = arg->argRoutine;
        !           414: 
        !           415:     fprintf(file, "#if\tTypeCheck\n");
        !           416:     if (akCheck(arg->argKind, akbRequestQC))
        !           417:        fprintf(file, "\tif (* (int *) &In%dP->%s != * (int *) &%sCheck)\n",
        !           418:                arg->argRequestPos, arg->argTTName, arg->argVarName);
        !           419:     else
        !           420:     {
        !           421:        fprintf(file, "\tif (");
        !           422:        if (!it->itIndefinite) {
        !           423:            fprintf(file, "(In%dP->%s%s.msgt_inline != %s) ||\n\t    ",
        !           424:                arg->argRequestPos, arg->argTTName,
        !           425:                arg->argLongForm ? ".msgtl_header" : "",
        !           426:                strbool(it->itInLine));
        !           427:        }
        !           428:        fprintf(file, "(In%dP->%s%s.msgt_longform != %s) ||\n",
        !           429:                arg->argRequestPos, arg->argTTName,
        !           430:                arg->argLongForm ? ".msgtl_header" : "",
        !           431:                strbool(arg->argLongForm));
        !           432:        if (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
        !           433:        {
        !           434:            if (!rt->rtSimpleCheckRequest)
        !           435:                fprintf(file, "\t    (MACH_MSG_TYPE_PORT_ANY(In%dP->%s.msgt%s_name) && msgh_simple) ||\n",
        !           436:                        arg->argRequestPos, arg->argTTName,
        !           437:                        arg->argLongForm ? "l" : "");
        !           438:        }
        !           439:        else
        !           440:            fprintf(file, "\t    (In%dP->%s.msgt%s_name != %s) ||\n",
        !           441:                    arg->argRequestPos, arg->argTTName,
        !           442:                    arg->argLongForm ? "l" : "",
        !           443:                    it->itOutNameStr);
        !           444:        if (!it->itVarArray)
        !           445:            fprintf(file, "\t    (In%dP->%s.msgt%s_number != %d) ||\n",
        !           446:                    arg->argRequestPos, arg->argTTName,
        !           447:                    arg->argLongForm ? "l" : "",
        !           448:                    it->itNumber);
        !           449:        fprintf(file, "\t    (In%dP->%s.msgt%s_size != %d))\n",
        !           450:                arg->argRequestPos, arg->argTTName,
        !           451:                arg->argLongForm ? "l" : "",
        !           452:                it->itSize);
        !           453:     }
        !           454:     WriteMsgError(file, "MIG_BAD_ARGUMENTS");
        !           455:     fprintf(file, "#endif\t/* TypeCheck */\n");
        !           456:     fprintf(file, "\n");
        !           457: }
        !           458: 
        !           459: static void
        !           460: WriteCheckArgSize(FILE *file, register const argument_t *arg)
        !           461: {
        !           462:     register const ipc_type_t *ptype = arg->argType;
        !           463:     register const ipc_type_t *btype = ptype->itElement;
        !           464:     const argument_t *count = arg->argCount;
        !           465:     int multiplier = btype->itTypeSize / btype->itNumber;
        !           466: 
        !           467:     if (ptype->itIndefinite) {
        !           468:        /*
        !           469:         * Check descriptor.  If out-of-line, use standard size.
        !           470:         */
        !           471:        fprintf(file, "(In%dP->%s%s.msgt_inline) ? ",
        !           472:                arg->argRequestPos,
        !           473:                arg->argTTName,
        !           474:                arg->argLongForm ? ".msgtl_header" : "");
        !           475:     }
        !           476: 
        !           477:     if (btype->itTypeSize % 4 != 0)
        !           478:        fprintf(file, "(");
        !           479: 
        !           480:     if (multiplier > 1)
        !           481:        fprintf(file, "%d * ", multiplier);
        !           482: 
        !           483:     fprintf(file, "In%dP->%s", arg->argRequestPos, count->argMsgField);
        !           484: 
        !           485:     /* If the base type size of the data field isn`t a multiple of 4,
        !           486:        we have to round up. */
        !           487:     if (btype->itTypeSize % 4 != 0)
        !           488:        fprintf(file, " + 3) & ~3");
        !           489: 
        !           490:     if (ptype->itIndefinite) {
        !           491:        fprintf(file, " : sizeof(%s *)", FetchServerType(btype));
        !           492:     }
        !           493: }
        !           494: 
        !           495: static void
        !           496: WriteCheckMsgSize(FILE *file, register const argument_t *arg)
        !           497: {
        !           498:     register const routine_t *rt = arg->argRoutine;
        !           499: 
        !           500:     /* If there aren't any more In args after this, then
        !           501:        we can use the msgh_size_delta value directly in
        !           502:        the TypeCheck conditional. */
        !           503: 
        !           504:     if (arg->argRequestPos == rt->rtMaxRequestPos)
        !           505:     {
        !           506:        fprintf(file, "#if\tTypeCheck\n");
        !           507:        fprintf(file, "\tif (msgh_size != %d + (", rt->rtRequestSize);
        !           508:        WriteCheckArgSize(file, arg);
        !           509:        fprintf(file, "))\n");
        !           510: 
        !           511:        WriteMsgError(file, "MIG_BAD_ARGUMENTS");
        !           512:        fprintf(file, "#endif\t/* TypeCheck */\n");
        !           513:     }
        !           514:     else
        !           515:     {
        !           516:        /* If there aren't any more variable-sized arguments after this,
        !           517:           then we must check for exact msg-size and we don't need to
        !           518:           update msgh_size. */
        !           519: 
        !           520:        boolean_t LastVarArg = arg->argRequestPos+1 == rt->rtNumRequestVar;
        !           521: 
        !           522:        /* calculate the actual size in bytes of the data field.  note
        !           523:           that this quantity must be a multiple of four.  hence, if
        !           524:           the base type size isn't a multiple of four, we have to
        !           525:           round up.  note also that btype->itNumber must
        !           526:           divide btype->itTypeSize (see itCalculateSizeInfo). */
        !           527: 
        !           528:        fprintf(file, "\tmsgh_size_delta = ");
        !           529:        WriteCheckArgSize(file, arg);
        !           530:        fprintf(file, ";\n");
        !           531:        fprintf(file, "#if\tTypeCheck\n");
        !           532: 
        !           533:        /* Don't decrement msgh_size until we've checked that
        !           534:           it won't underflow. */
        !           535: 
        !           536:        if (LastVarArg)
        !           537:            fprintf(file, "\tif (msgh_size != %d + msgh_size_delta)\n",
        !           538:                rt->rtRequestSize);
        !           539:        else
        !           540:            fprintf(file, "\tif (msgh_size < %d + msgh_size_delta)\n",
        !           541:                rt->rtRequestSize);
        !           542:        WriteMsgError(file, "MIG_BAD_ARGUMENTS");
        !           543: 
        !           544:        if (!LastVarArg)
        !           545:            fprintf(file, "\tmsgh_size -= msgh_size_delta;\n");
        !           546: 
        !           547:        fprintf(file, "#endif\t/* TypeCheck */\n");
        !           548:     }
        !           549:     fprintf(file, "\n");
        !           550: }
        !           551: 
        !           552: static const char *
        !           553: InArgMsgField(register const argument_t *arg)
        !           554: {
        !           555:     static char buffer[100];
        !           556: 
        !           557:     /*
        !           558:      * Inside the kernel, the request and reply port fields
        !           559:      * really hold ipc_port_t values, not mach_port_t values.
        !           560:      * Hence we must cast the values.
        !           561:      */
        !           562: 
        !           563:     if (IsKernelServer &&
        !           564:        ((akIdent(arg->argKind) == akeRequestPort) ||
        !           565:         (akIdent(arg->argKind) == akeReplyPort)))
        !           566:        sprintf(buffer, "(ipc_port_t) In%dP->%s",
        !           567:                arg->argRequestPos, arg->argMsgField);
        !           568:     else
        !           569:        sprintf(buffer, "In%dP->%s",
        !           570:                arg->argRequestPos, arg->argMsgField);
        !           571: 
        !           572:     return buffer;
        !           573: }
        !           574: 
        !           575: static void
        !           576: WriteExtractArgValue(FILE *file, register const argument_t *arg)
        !           577: {
        !           578:     register const ipc_type_t *it = arg->argType;
        !           579: 
        !           580:     if (arg->argMultiplier > 1)
        !           581:        WriteCopyType(file, it, "%s", "/* %s */ %s / %d",
        !           582:                      arg->argVarName, InArgMsgField(arg), arg->argMultiplier);
        !           583:     else if (it->itInTrans != strNULL)
        !           584:        WriteCopyType(file, it, "%s", "/* %s */ %s(%s)",
        !           585:                      arg->argVarName, it->itInTrans, InArgMsgField(arg));
        !           586:     else
        !           587:        WriteCopyType(file, it, "%s", "/* %s */ %s",
        !           588:                      arg->argVarName, InArgMsgField(arg));
        !           589:     fprintf(file, "\n");
        !           590: }
        !           591: 
        !           592: static void
        !           593: WriteInitializeCount(FILE *file, register const argument_t *arg)
        !           594: {
        !           595:     register const ipc_type_t *ptype = arg->argParent->argType;
        !           596:     register const ipc_type_t *btype = ptype->itElement;
        !           597: 
        !           598:     /*
        !           599:      * Initialize 'count' argument for variable-length inline OUT parameter
        !           600:      * with maximum allowed number of elements.
        !           601:      */
        !           602: 
        !           603:     fprintf(file, "\t%s = %d;\n", arg->argVarName,
        !           604:            ptype->itNumber/btype->itNumber);
        !           605: 
        !           606:     /*
        !           607:      * If the user passed in a count, then we use the minimum.
        !           608:      * We can't let the user completely override our maximum,
        !           609:      * or the user might convince the server to overwrite the buffer.
        !           610:      */
        !           611: 
        !           612:     if (arg->argCInOut != argNULL) {
        !           613:        const char *msgfield = InArgMsgField(arg->argCInOut);
        !           614: 
        !           615:        fprintf(file, "\tif (%s < %s)\n", msgfield, arg->argVarName);
        !           616:        fprintf(file, "\t\t%s = %s;\n", arg->argVarName, msgfield);
        !           617:     }
        !           618: 
        !           619:     fprintf(file, "\n");
        !           620: }
        !           621: 
        !           622: static void
        !           623: WriteInitializePtr(FILE *file, register const argument_t *arg)
        !           624: {
        !           625:     if (akCheck(arg->argKind, akbVarNeeded))
        !           626:        fprintf(file, "\t%sP = %s;\n",
        !           627:                arg->argVarName, arg->argVarName);
        !           628:     else
        !           629:        fprintf(file, "\t%sP = OutP->%s;\n",
        !           630:                arg->argVarName, arg->argMsgField);
        !           631: }
        !           632: 
        !           633: static void
        !           634: WriteTypeCheckArg(FILE *file, register const argument_t *arg)
        !           635: {
        !           636:     if (akCheck(arg->argKind, akbRequest)) {
        !           637:        WriteTypeCheck(file, arg);
        !           638: 
        !           639:        if (akCheck(arg->argKind, akbVariable))
        !           640:            WriteCheckMsgSize(file, arg);
        !           641:     }
        !           642: }
        !           643: 
        !           644: static void
        !           645: WriteAdjustRequestMsgPtr(FILE *file, register const argument_t *arg)
        !           646: {
        !           647:     register const ipc_type_t *ptype = arg->argType;
        !           648: 
        !           649:     fprintf(file,
        !           650:        "\tIn%dP = (Request *) ((char *) In%dP + msgh_size_delta - %d);\n\n",
        !           651:        arg->argRequestPos+1, arg->argRequestPos,
        !           652:        ptype->itTypeSize + ptype->itPadSize);
        !           653: }
        !           654: 
        !           655: static void
        !           656: WriteTypeCheckRequestArgs(FILE *file, register const routine_t *rt)
        !           657: {
        !           658:     register const argument_t *arg;
        !           659:     register const argument_t *lastVarArg;
        !           660: 
        !           661:     lastVarArg = argNULL;
        !           662:     for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
        !           663: 
        !           664:        /*
        !           665:         * Advance message pointer if the last request argument was
        !           666:         * variable-length and the request position will change.
        !           667:         */
        !           668:        if (lastVarArg != argNULL &&
        !           669:            lastVarArg->argRequestPos < arg->argRequestPos)
        !           670:        {
        !           671:            WriteAdjustRequestMsgPtr(file, lastVarArg);
        !           672:            lastVarArg = argNULL;
        !           673:        }
        !           674: 
        !           675:        /*
        !           676:         * Type-check the argument.
        !           677:         */
        !           678:        WriteTypeCheckArg(file, arg);
        !           679: 
        !           680:        /*
        !           681:         * Remember whether this was variable-length.
        !           682:         */
        !           683:        if (akCheckAll(arg->argKind, akbVariable|akbRequest))
        !           684:            lastVarArg = arg;
        !           685:     }
        !           686: }
        !           687: 
        !           688: static void
        !           689: WriteExtractArg(FILE *file, register const argument_t *arg)
        !           690: {
        !           691:     if (akCheckAll(arg->argKind, akbSendRcv|akbVarNeeded))
        !           692:        WriteExtractArgValue(file, arg);
        !           693: 
        !           694:     if ((akIdent(arg->argKind) == akeCount) &&
        !           695:        akCheck(arg->argKind, akbReturnSnd))
        !           696:     {
        !           697:        register ipc_type_t *ptype = arg->argParent->argType;
        !           698: 
        !           699:        if (ptype->itInLine && ptype->itVarArray)
        !           700:            WriteInitializeCount(file, arg);
        !           701:     }
        !           702: 
        !           703:     if (akCheckAll(arg->argKind, akbReturnSnd|akbPointer))
        !           704:        WriteInitializePtr(file, arg);
        !           705: }
        !           706: 
        !           707: static void
        !           708: WriteServerCallArg(FILE *file, register const argument_t *arg)
        !           709: {
        !           710:     const ipc_type_t *it = arg->argType;
        !           711:     boolean_t NeedClose = FALSE;
        !           712: 
        !           713:     if (arg->argByReferenceServer)
        !           714:        fprintf(file, "&");
        !           715: 
        !           716:     if ((it->itInTrans != strNULL) &&
        !           717:        akCheck(arg->argKind, akbSendRcv) &&
        !           718:        !akCheck(arg->argKind, akbVarNeeded))
        !           719:     {
        !           720:        fprintf(file, "%s(", it->itInTrans);
        !           721:        NeedClose = TRUE;
        !           722:     }
        !           723: 
        !           724:     if (akCheck(arg->argKind, akbPointer))
        !           725:        fprintf(file, "%sP", arg->argVarName);
        !           726:     else if (akCheck(arg->argKind, akbVarNeeded))
        !           727:        fprintf(file, "%s", arg->argVarName);
        !           728:     else if (akCheck(arg->argKind, akbSendRcv)) {
        !           729:        if (akCheck(arg->argKind, akbIndefinite)) {
        !           730:            fprintf(file, "(In%dP->%s%s.msgt_inline) ",
        !           731:                    arg->argRequestPos,
        !           732:                    arg->argTTName,
        !           733:                    arg->argLongForm ? ".msgtl_header" : "");
        !           734:            fprintf(file, "? %s ", InArgMsgField(arg));
        !           735:            fprintf(file, ": *((%s **)%s)",
        !           736:                        FetchServerType(arg->argType->itElement),
        !           737:                        InArgMsgField(arg));
        !           738:        }
        !           739:        else
        !           740:            fprintf(file, "%s", InArgMsgField(arg));
        !           741:     }
        !           742:     else
        !           743:        fprintf(file, "OutP->%s", arg->argMsgField);
        !           744: 
        !           745:     if (NeedClose)
        !           746:        fprintf(file, ")");
        !           747: 
        !           748:     if (!arg->argByReferenceServer && (arg->argMultiplier > 1))
        !           749:        fprintf(file, " / %d", arg->argMultiplier);
        !           750: }
        !           751: 
        !           752: static void
        !           753: WriteDestroyArg(FILE *file, register const argument_t *arg)
        !           754: {
        !           755:     register const ipc_type_t *it = arg->argType;
        !           756: 
        !           757:     if (akCheck(arg->argKind, akbIndefinite)) {
        !           758:        /*
        !           759:         * Deallocate only if out-of-line.
        !           760:         */
        !           761:        argument_t *count = arg->argCount;
        !           762:        ipc_type_t *btype = it->itElement;
        !           763:        int     multiplier = btype->itTypeSize / btype->itNumber;
        !           764: 
        !           765:        fprintf(file, "\tif (!In%dP->%s%s.msgt_inline)\n",
        !           766:                arg->argRequestPos,
        !           767:                arg->argTTName,
        !           768:                arg->argLongForm ? ".msgtl_header" : "");
        !           769:        fprintf(file, "\t\t%smig_deallocate(* (vm_offset_t *) %s, ",
        !           770:                SubrPrefix, InArgMsgField(arg));
        !           771:        if (multiplier > 1)
        !           772:            fprintf(file, "%d * ", multiplier);
        !           773:        fprintf(file, " %s);\n", InArgMsgField(count));
        !           774:     } else {
        !           775:        if (akCheck(arg->argKind, akbVarNeeded))
        !           776:            fprintf(file, "\t%s(%s);\n", it->itDestructor, arg->argVarName);
        !           777:        else
        !           778:            fprintf(file, "\t%s(%s);\n", it->itDestructor,
        !           779:                InArgMsgField(arg));
        !           780:     }
        !           781: }
        !           782: 
        !           783: static void
        !           784: WriteDestroyPortArg(FILE *file, register const argument_t *arg)
        !           785: {
        !           786:     register const ipc_type_t *it = arg->argType;
        !           787: 
        !           788:     /*
        !           789:      * If a translated port argument occurs in the body of a request
        !           790:      * message, and the message is successfully processed, then the
        !           791:      * port right should be deallocated.  However, the called function
        !           792:      * didn't see the port right; it saw the translation.  So we have
        !           793:      * to release the port right for it.
        !           794:      */
        !           795: 
        !           796:     if ((it->itInTrans != strNULL) &&
        !           797:        (it->itOutName == MACH_MSG_TYPE_PORT_SEND))
        !           798:     {
        !           799:        fprintf(file, "\n");
        !           800:        fprintf(file, "\tif (IP_VALID(%s))\n", InArgMsgField(arg));
        !           801:        fprintf(file, "\t\t%sipc_port_release_send(%s);\n",
        !           802:                SubrPrefix, InArgMsgField(arg));
        !           803:     }
        !           804: }
        !           805: 
        !           806: /*
        !           807:  * Check whether WriteDestroyPortArg would generate any code for arg.
        !           808:  */
        !           809: static boolean_t
        !           810: CheckDestroyPortArg(register const argument_t *arg)
        !           811: {
        !           812:     register const ipc_type_t *it = arg->argType;
        !           813: 
        !           814:     if ((it->itInTrans != strNULL) &&
        !           815:        (it->itOutName == MACH_MSG_TYPE_PORT_SEND))
        !           816:     {
        !           817:        return TRUE;
        !           818:     }
        !           819:     return FALSE;
        !           820: }
        !           821: 
        !           822: static void
        !           823: WriteServerCall(FILE *file, const routine_t *rt)
        !           824: {
        !           825:     boolean_t NeedClose = FALSE;
        !           826: 
        !           827:     fprintf(file, "\t");
        !           828:     if (rt->rtServerReturn != argNULL)
        !           829:     {
        !           830:        const argument_t *arg = rt->rtServerReturn;
        !           831:        const ipc_type_t *it = arg->argType;
        !           832: 
        !           833:        fprintf(file, "OutP->%s = ", arg->argMsgField);
        !           834:        if (it->itOutTrans != strNULL)
        !           835:        {
        !           836:            fprintf(file, "%s(", it->itOutTrans);
        !           837:            NeedClose = TRUE;
        !           838:        }
        !           839:     }
        !           840:     fprintf(file, "%s(", rt->rtServerName);
        !           841:     WriteList(file, rt->rtArgs, WriteServerCallArg, akbServerArg, ", ", "");
        !           842:     if (NeedClose)
        !           843:        fprintf(file, ")");
        !           844:     fprintf(file, ");\n");
        !           845: }
        !           846: 
        !           847: static void
        !           848: WriteGetReturnValue(FILE *file, register const routine_t *rt)
        !           849: {
        !           850:     if (rt->rtServerReturn != rt->rtRetCode)
        !           851:        fprintf(file, "\tOutP->%s = KERN_SUCCESS;\n",
        !           852:                rt->rtRetCode->argMsgField);
        !           853: }
        !           854: 
        !           855: static void
        !           856: WriteCheckReturnValue(FILE *file, register const routine_t *rt)
        !           857: {
        !           858:     if (rt->rtServerReturn == rt->rtRetCode)
        !           859:     {
        !           860:        fprintf(file, "\tif (OutP->%s != KERN_SUCCESS)\n",
        !           861:                rt->rtRetCode->argMsgField);
        !           862:        fprintf(file, "\t\treturn;\n");
        !           863:     }
        !           864: }
        !           865: 
        !           866: static void
        !           867: WritePackArgType(FILE *file, register const argument_t *arg)
        !           868: {
        !           869:     fprintf(file, "\n");
        !           870: 
        !           871:     WritePackMsgType(file, arg->argType,
        !           872:                     arg->argType->itIndefinite ? d_NO : arg->argDeallocate,
        !           873:                     arg->argLongForm, !IsKernelServer,
        !           874:                     "OutP->%s", "%s", arg->argTTName);
        !           875: }
        !           876: 
        !           877: static void
        !           878: WritePackArgValue(FILE *file, register const argument_t *arg)
        !           879: {
        !           880:     register const ipc_type_t *it = arg->argType;
        !           881: 
        !           882:     fprintf(file, "\n");
        !           883: 
        !           884:     if (it->itInLine && it->itVarArray) {
        !           885: 
        !           886:        if (it->itString) {
        !           887:            /*
        !           888:             *  Copy variable-size C string with mig_strncpy.
        !           889:             *  Save the string length (+ 1 for trailing 0)
        !           890:             *  in the argument`s count field.
        !           891:             */
        !           892:            fprintf(file,
        !           893:                "\tOutP->%s = %smig_strncpy(OutP->%s, %s, %d);\n",
        !           894:                arg->argCount->argMsgField,
        !           895:                SubrPrefix,
        !           896:                arg->argMsgField,
        !           897:                arg->argVarName,
        !           898:                it->itNumber);
        !           899:        }
        !           900:        else {
        !           901:            register argument_t *count = arg->argCount;
        !           902:            register ipc_type_t *btype = it->itElement;
        !           903: 
        !           904:            /* Note btype->itNumber == count->argMultiplier */
        !           905: 
        !           906:            if (it->itIndefinite) {
        !           907:                /*
        !           908:                 * If we are packing argument, it must be from
        !           909:                 * a local variable.
        !           910:                 */
        !           911:                fprintf(file, "\tif (%sP != %s) {\n",
        !           912:                        arg->argVarName,
        !           913:                        arg->argVarName);
        !           914:                fprintf(file, "\t\tOutP->%s%s.msgt_inline = FALSE;\n",
        !           915:                        arg->argTTName,
        !           916:                        arg->argLongForm ? ".msgtl_header" : "");
        !           917:                if (arg->argDeallocate == d_YES)
        !           918:                    fprintf(file, "\t\tOutP->%s%s.msgt_deallocate = TRUE;\n",
        !           919:                            arg->argTTName,
        !           920:                            arg->argLongForm ? ".msgtl_header" : "");
        !           921:                else if (arg->argDeallocate == d_MAYBE)
        !           922:                    fprintf(file, "\t\tOutP->%s%s.msgt_deallocate = %s;\n",
        !           923:                            arg->argTTName,
        !           924:                            arg->argLongForm ? ".msgtl_header" : "",
        !           925:                            arg->argDealloc->argVarName);
        !           926:                fprintf(file, "\t\t*((%s **)OutP->%s) = %sP;\n",
        !           927:                        FetchServerType(btype),
        !           928:                        arg->argMsgField,
        !           929:                        arg->argVarName);
        !           930:                if (!arg->argRoutine->rtSimpleFixedReply)
        !           931:                    fprintf(file, "\t\tmsgh_simple = FALSE;\n");
        !           932:                fprintf(file, "\t}\n\telse {\n\t");
        !           933:            }
        !           934:            fprintf(file, "\tmemcpy(OutP->%s, %s, ",
        !           935:                    arg->argMsgField, arg->argVarName);
        !           936:            if (btype->itTypeSize > 1)
        !           937:                fprintf(file, "%d * ",
        !           938:                        btype->itTypeSize);
        !           939:            fprintf(file, "%s);\n",
        !           940:                count->argVarName);
        !           941:            if (it->itIndefinite)
        !           942:                fprintf(file, "\t}\n");
        !           943:        }
        !           944:     }
        !           945:     else if (arg->argMultiplier > 1)
        !           946:        WriteCopyType(file, it, "OutP->%s", "/* %s */ %d * %s",
        !           947:                      arg->argMsgField,
        !           948:                      arg->argMultiplier,
        !           949:                      arg->argVarName);
        !           950:     else if (it->itOutTrans != strNULL)
        !           951:        WriteCopyType(file, it, "OutP->%s", "/* %s */ %s(%s)",
        !           952:                      arg->argMsgField, it->itOutTrans, arg->argVarName);
        !           953:     else
        !           954:        WriteCopyType(file, it, "OutP->%s", "/* %s */ %s",
        !           955:                      arg->argMsgField, arg->argVarName);
        !           956: }
        !           957: 
        !           958: static void
        !           959: WriteCopyArgValue(FILE *file, register const argument_t *arg)
        !           960: {
        !           961:     fprintf(file, "\n");
        !           962:     WriteCopyType(file, arg->argType, "/* %d */ OutP->%s", "In%dP->%s",
        !           963:                  arg->argRequestPos, arg->argMsgField);
        !           964: }
        !           965: 
        !           966: static void
        !           967: WriteAdjustMsgSimple(FILE *file, register const argument_t *arg)
        !           968: {
        !           969:     /* akbVarNeeded must be on */
        !           970: 
        !           971:     if (!arg->argRoutine->rtSimpleFixedReply)
        !           972:     {
        !           973:        fprintf(file, "\n");
        !           974:        fprintf(file, "\tif (MACH_MSG_TYPE_PORT_ANY(%s))\n", arg->argVarName);
        !           975:        fprintf(file, "\t\tmsgh_simple = FALSE;\n");
        !           976:     }
        !           977: }
        !           978: 
        !           979: static void
        !           980: WriteAdjustMsgCircular(FILE *file, register const argument_t *arg)
        !           981: {
        !           982:     fprintf(file, "\n");
        !           983: 
        !           984:     if (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
        !           985:        fprintf(file, "\tif (%s == MACH_MSG_TYPE_PORT_RECEIVE)\n",
        !           986:                arg->argPoly->argVarName);
        !           987: 
        !           988:     /*
        !           989:      * The carried port right can be accessed in OutP->XXXX.  Normally
        !           990:      * the server function stuffs it directly there.  If it is InOut,
        !           991:      * then it has already been copied into the reply message.
        !           992:      * If the server function deposited it into a variable (perhaps
        !           993:      * because the reply message is variable-sized) then it has already
        !           994:      * been copied into the reply message.  Note we must use InHeadP
        !           995:      * (or In0P->Head) and OutHeadP to access the message headers,
        !           996:      * because of the variable-sized messages.
        !           997:      */
        !           998: 
        !           999:     fprintf(file, "\tif (IP_VALID((ipc_port_t) InHeadP->msgh_reply_port) &&\n");
        !          1000:     fprintf(file, "\t    IP_VALID((ipc_port_t) OutP->%s) &&\n", arg->argMsgField);
        !          1001:     fprintf(file, "\t    %sipc_port_check_circularity((ipc_port_t) OutP->%s, (ipc_port_t) InHeadP->msgh_reply_port))\n",
        !          1002:            SubrPrefix, arg->argMsgField);
        !          1003:     fprintf(file, "\t\tOutHeadP->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;\n");
        !          1004: }
        !          1005: 
        !          1006: /*
        !          1007:  * Calculate the size of a variable-length message field.
        !          1008:  */
        !          1009: static void
        !          1010: WriteArgSize(FILE *file, register const argument_t *arg)
        !          1011: {
        !          1012:     register const ipc_type_t *ptype = arg->argType;
        !          1013:     register int bsize = ptype->itElement->itTypeSize;
        !          1014:     register const argument_t *count = arg->argCount;
        !          1015: 
        !          1016:     if (ptype->itIndefinite) {
        !          1017:        /*
        !          1018:         * Check descriptor.  If out-of-line, use standard size.
        !          1019:         */
        !          1020:        fprintf(file, "(OutP->%s%s.msgt_inline) ? ",
        !          1021:                arg->argTTName,
        !          1022:                arg->argLongForm ? ".msgtl_header" : "");
        !          1023:     }
        !          1024: 
        !          1025:     if (bsize % 4 != 0)
        !          1026:        fprintf(file, "(");
        !          1027: 
        !          1028:     if (bsize > 1)
        !          1029:        fprintf(file, "%d * ", bsize);
        !          1030:     if (ptype->itString)
        !          1031:        /* get count from descriptor in message */
        !          1032:        fprintf(file, "OutP->%s", count->argMsgField);
        !          1033:     else
        !          1034:        /* get count from argument */
        !          1035:        fprintf(file, "%s", count->argVarName);
        !          1036: 
        !          1037:     /*
        !          1038:      * If the base type size is not a multiple of sizeof(int) [4],
        !          1039:      * we have to round up.
        !          1040:      */
        !          1041:     if (bsize % 4 != 0)
        !          1042:        fprintf(file, " + 3) & ~3");
        !          1043: 
        !          1044:     if (ptype->itIndefinite) {
        !          1045:        fprintf(file, " : sizeof(%s *)",
        !          1046:                FetchServerType(ptype->itElement));
        !          1047:     }
        !          1048: }
        !          1049: 
        !          1050: /*
        !          1051:  * Adjust message size and advance reply pointer.
        !          1052:  * Called after packing a variable-length argument that
        !          1053:  * has more arguments following.
        !          1054:  */
        !          1055: static void
        !          1056: WriteAdjustMsgSize(FILE *file, register const argument_t *arg)
        !          1057: {
        !          1058:     register routine_t *rt = arg->argRoutine;
        !          1059:     register ipc_type_t *ptype = arg->argType;
        !          1060: 
        !          1061:     /* There are more Out arguments.  We need to adjust msgh_size
        !          1062:        and advance OutP, so we save the size of the current field
        !          1063:        in msgh_size_delta. */
        !          1064: 
        !          1065:     fprintf(file, "\tmsgh_size_delta = ");
        !          1066:     WriteArgSize(file, arg);
        !          1067:     fprintf(file, ";\n");
        !          1068: 
        !          1069:     if (rt->rtNumReplyVar == 1)
        !          1070:        /* We can still address the message header directly.  Fill
        !          1071:           in the size field. */
        !          1072: 
        !          1073:        fprintf(file, "\tOutP->Head.msgh_size = %d + msgh_size_delta;\n",
        !          1074:                        rt->rtReplySize);
        !          1075:     else
        !          1076:     if (arg->argReplyPos == 0)
        !          1077:        /* First variable-length argument.  The previous msgh_size value
        !          1078:           is the minimum reply size. */
        !          1079: 
        !          1080:        fprintf(file, "\tmsgh_size = %d + msgh_size_delta;\n",
        !          1081:                rt->rtReplySize);
        !          1082:     else
        !          1083:        fprintf(file, "\tmsgh_size += msgh_size_delta;\n");
        !          1084: 
        !          1085:     fprintf(file,
        !          1086:        "\tOutP = (Reply *) ((char *) OutP + msgh_size_delta - %d);\n",
        !          1087:        ptype->itTypeSize + ptype->itPadSize);
        !          1088: }
        !          1089: 
        !          1090: /*
        !          1091:  * Calculate the size of the message.  Called after the
        !          1092:  * last argument has been packed.
        !          1093:  */
        !          1094: static void
        !          1095: WriteFinishMsgSize(FILE *file, register const argument_t *arg)
        !          1096: {
        !          1097:     /* No more Out arguments.  If this is the only variable Out
        !          1098:        argument, we can assign to msgh_size directly. */
        !          1099: 
        !          1100:     if (arg->argReplyPos == 0) {
        !          1101:        fprintf(file, "\tOutP->Head.msgh_size = %d + (",
        !          1102:                        arg->argRoutine->rtReplySize);
        !          1103:        WriteArgSize(file, arg);
        !          1104:        fprintf(file, ");\n");
        !          1105:     }
        !          1106:     else {
        !          1107:        fprintf(file, "\tmsgh_size += ");
        !          1108:        WriteArgSize(file, arg);
        !          1109:        fprintf(file, ";\n");
        !          1110:     }
        !          1111: }
        !          1112: 
        !          1113: static void
        !          1114: WritePackArg(FILE *file, register const argument_t *arg)
        !          1115: {
        !          1116:     if (akCheck(arg->argKind, akbReplyInit))
        !          1117:        WritePackArgType(file, arg);
        !          1118: 
        !          1119:     if ((akIdent(arg->argKind) == akePoly) &&
        !          1120:        akCheck(arg->argKind, akbReturnSnd))
        !          1121:        WriteAdjustMsgSimple(file, arg);
        !          1122: 
        !          1123:     if (akCheckAll(arg->argKind, akbReturnSnd|akbVarNeeded))
        !          1124:        WritePackArgValue(file, arg);
        !          1125:     else if (akCheckAll(arg->argKind, akbReturnSnd|akbVariable)) {
        !          1126:        register const ipc_type_t *it = arg->argType;
        !          1127: 
        !          1128:        if (it->itString) {
        !          1129:            /* Need to call strlen to calculate the size of the argument. */
        !          1130:            fprintf(file, "\tOutP->%s = strlen(OutP->%s) + 1;\n",
        !          1131:                    arg->argCount->argMsgField, arg->argMsgField);
        !          1132:        } else if (it->itIndefinite) {
        !          1133:            /*
        !          1134:             * We know that array is in reply message.
        !          1135:             */
        !          1136:            fprintf(file, "\tif (%sP != OutP->%s) {\n",
        !          1137:                        arg->argVarName,
        !          1138:                        arg->argMsgField);
        !          1139:            fprintf(file, "\t\tOutP->%s%s.msgt_inline = FALSE;\n",
        !          1140:                    arg->argTTName,
        !          1141:                    arg->argLongForm ? ".msgtl_header" : "");
        !          1142:            if (arg->argDeallocate == d_YES)
        !          1143:                fprintf(file, "\t\tOutP->%s%s.msgt_deallocate = TRUE;\n",
        !          1144:                        arg->argTTName,
        !          1145:                        arg->argLongForm ? ".msgtl_header" : "");
        !          1146:            else if (arg->argDeallocate == d_MAYBE)
        !          1147:                fprintf(file, "\t\tOutP->%s%s.msgt_deallocate = %s;\n",
        !          1148:                        arg->argTTName,
        !          1149:                        arg->argLongForm ? ".msgtl_header" : "",
        !          1150:                        arg->argDealloc->argVarName);
        !          1151:            fprintf(file, "\t\t*((%s **)OutP->%s) = %sP;\n",
        !          1152:                        FetchServerType(it->itElement),
        !          1153:                        arg->argMsgField,
        !          1154:                        arg->argVarName);
        !          1155:            if (!arg->argRoutine->rtSimpleFixedReply)
        !          1156:                fprintf(file, "\t\tmsgh_simple = FALSE;\n");
        !          1157:            fprintf(file, "\t}\n");
        !          1158:        }
        !          1159:     }
        !          1160: 
        !          1161:     if (akCheck(arg->argKind, akbReplyCopy))
        !          1162:        WriteCopyArgValue(file, arg);
        !          1163: 
        !          1164:     /*
        !          1165:      * If this is a KernelServer, and the reply message contains
        !          1166:      * a receive right, we must check for the possibility of a
        !          1167:      * port/message circularity.  If queueing the reply message
        !          1168:      * would cause a circularity, we mark the reply message
        !          1169:      * with the circular bit.
        !          1170:      */
        !          1171: 
        !          1172:     if (IsKernelServer &&
        !          1173:        akCheck(arg->argKind, akbReturnSnd) &&
        !          1174:        ((arg->argType->itOutName == MACH_MSG_TYPE_PORT_RECEIVE) ||
        !          1175:         (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC)))
        !          1176:        WriteAdjustMsgCircular(file, arg);
        !          1177: }
        !          1178: 
        !          1179: /*
        !          1180:  * Handle reply arguments - fill in message types and copy arguments
        !          1181:  * that need to be copied.
        !          1182:  */
        !          1183: static void
        !          1184: WritePackReplyArgs(FILE *file, register const routine_t *rt)
        !          1185: {
        !          1186:     register const argument_t *arg;
        !          1187:     register const argument_t *lastVarArg;
        !          1188: 
        !          1189:     lastVarArg = argNULL;
        !          1190:     for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
        !          1191: 
        !          1192:        /*
        !          1193:         * Adjust message size and advance message pointer if
        !          1194:         * the last reply argument was variable-length and the
        !          1195:         * request position will change.
        !          1196:         */
        !          1197:        if (lastVarArg != argNULL &&
        !          1198:            lastVarArg->argReplyPos < arg->argReplyPos)
        !          1199:        {
        !          1200:            WriteAdjustMsgSize(file, lastVarArg);
        !          1201:            lastVarArg = argNULL;
        !          1202:        }
        !          1203: 
        !          1204:        /*
        !          1205:         * Copy the argument
        !          1206:         */
        !          1207:        WritePackArg(file, arg);
        !          1208: 
        !          1209:        /*
        !          1210:         * Remember whether this was variable-length.
        !          1211:         */
        !          1212:        if (akCheckAll(arg->argKind, akbReturnSnd|akbVariable))
        !          1213:            lastVarArg = arg;
        !          1214:     }
        !          1215: 
        !          1216:     /*
        !          1217:      * Finish the message size.
        !          1218:      */
        !          1219:     if (lastVarArg != argNULL)
        !          1220:        WriteFinishMsgSize(file, lastVarArg);
        !          1221: }
        !          1222: 
        !          1223: static void
        !          1224: WriteFieldDecl(FILE *file, const argument_t *arg)
        !          1225: {
        !          1226:     WriteFieldDeclPrim(file, arg, FetchServerType);
        !          1227: }
        !          1228: 
        !          1229: static void
        !          1230: WriteRoutine(FILE *file, register const routine_t *rt)
        !          1231: {
        !          1232:     fprintf(file, "\n");
        !          1233: 
        !          1234:     fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
        !          1235:     fprintf(file, "mig_internal void _X%s\n", rt->rtName);
        !          1236:     fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
        !          1237: 
        !          1238:     fprintf(file, "{\n");
        !          1239:     WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request");
        !          1240:     WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply, "Reply");
        !          1241: 
        !          1242:     WriteVarDecls(file, rt);
        !          1243: 
        !          1244:     WriteList(file, rt->rtArgs, WriteCheckDecl, akbRequestQC, "\n", "\n");
        !          1245:     WriteList(file, rt->rtArgs,
        !          1246:              IsKernelServer ? WriteTypeDeclOut : WriteTypeDeclIn,
        !          1247:              akbReplyInit, "\n", "\n");
        !          1248: 
        !          1249:     WriteList(file, rt->rtArgs, WriteLocalVarDecl,
        !          1250:              akbVarNeeded, ";\n", ";\n\n");
        !          1251:     WriteList(file, rt->rtArgs, WriteLocalPtrDecl,
        !          1252:              akbPointer, ";\n", ";\n\n");
        !          1253: 
        !          1254:     WriteCheckHead(file, rt);
        !          1255: 
        !          1256:     WriteTypeCheckRequestArgs(file, rt);
        !          1257:     WriteList(file, rt->rtArgs, WriteExtractArg, akbNone, "", "");
        !          1258: 
        !          1259:     WriteServerCall(file, rt);
        !          1260:     WriteGetReturnValue(file, rt);
        !          1261: 
        !          1262:     WriteReverseList(file, rt->rtArgs, WriteDestroyArg, akbDestroy, "", "");
        !          1263: 
        !          1264:     /*
        !          1265:      * For one-way routines, it doesn`t make sense to check the return
        !          1266:      * code, because we return immediately afterwards.  However,
        !          1267:      * kernel servers may want to deallocate port arguments - and the
        !          1268:      * deallocation must not be done if the return code is not KERN_SUCCESS.
        !          1269:      */
        !          1270:     if (rt->rtOneWay || rt->rtNoReplyArgs)
        !          1271:     {
        !          1272:        if (IsKernelServer)
        !          1273:        {
        !          1274:            if (rtCheckMaskFunction(rt->rtArgs, akbSendBody|akbSendRcv,
        !          1275:                                CheckDestroyPortArg))
        !          1276:            {
        !          1277:                WriteCheckReturnValue(file, rt);
        !          1278:            }
        !          1279:            WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg,
        !          1280:                         akbSendBody|akbSendRcv, "", "");
        !          1281:        }
        !          1282:     }
        !          1283:     else
        !          1284:     {
        !          1285:        WriteCheckReturnValue(file, rt);
        !          1286: 
        !          1287:        if (IsKernelServer)
        !          1288:            WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg,
        !          1289:                         akbSendBody|akbSendRcv, "", "");
        !          1290: 
        !          1291:        WriteReplyInit(file, rt);
        !          1292:        WritePackReplyArgs(file, rt);
        !          1293:        WriteReplyHead(file, rt);
        !          1294:     }
        !          1295: 
        !          1296:     fprintf(file, "}\n");
        !          1297: }
        !          1298: 
        !          1299: void
        !          1300: WriteServer(FILE *file, const statement_t *stats)
        !          1301: {
        !          1302:     register const statement_t *stat;
        !          1303: 
        !          1304:     WriteProlog(file);
        !          1305:     for (stat = stats; stat != stNULL; stat = stat->stNext)
        !          1306:        switch (stat->stKind)
        !          1307:        {
        !          1308:          case skRoutine:
        !          1309:            WriteRoutine(file, stat->stRoutine);
        !          1310:            break;
        !          1311:          case skImport:
        !          1312:          case skSImport:
        !          1313:            WriteImport(file, stat->stFileName);
        !          1314:            break;
        !          1315:          case skUImport:
        !          1316:            break;
        !          1317:          default:
        !          1318:            fatal("WriteServer(): bad statement_kind_t (%d)",
        !          1319:                  (int) stat->stKind);
        !          1320:        }
        !          1321:     WriteEpilog(file, stats);
        !          1322: }

unix.superglobalmegacorp.com

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