Annotation of Gnu-Mach/mig/server.c, revision 1.1.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.