Annotation of Gnu-Mach/mig/routine.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1992,1991,1990 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "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: /*
                     28:  *  ABSTRACT:
                     29:  *   Provides the routine used by parser.c to generate
                     30:  *   routine structures for each routine statement.
                     31:  *   The parser generates a threaded list of statements
                     32:  *   of which the most interesting are the various kinds
                     33:  *   routine statments. The routine structure is defined
                     34:  *   in routine.h which includes it name, kind of routine
                     35:  *   and other information,
                     36:  *   a pointer to an argument list which contains the name
                     37:  *   and type information for each argument, and a list
                     38:  *   of distinguished arguments, eg.  Request and Reply
                     39:  *   ports, waittime, retcode etc.
                     40:  */
                     41: 
                     42: #include <stdio.h>
                     43: #include <stdlib.h>
                     44: 
                     45: #include "error.h"
                     46: #include "global.h"
                     47: #include "routine.h"
                     48: #include "message.h"
                     49: 
                     50: u_int rtNumber = 0;
                     51: 
                     52: routine_t *
                     53: rtAlloc(void)
                     54: {
                     55:     register routine_t *new;
                     56: 
                     57:     new = (routine_t *) calloc(1, sizeof *new);
                     58:     if (new == rtNULL)
                     59:        fatal("rtAlloc(): %s", unix_error_string(errno));
                     60:     new->rtNumber = rtNumber++;
                     61:     new->rtName = strNULL;
                     62:     new->rtErrorName = strNULL;
                     63:     new->rtUserName = strNULL;
                     64:     new->rtServerName = strNULL;
                     65: 
                     66:     return new;
                     67: }
                     68: 
                     69: void
                     70: rtSkip(int n)
                     71: {
                     72:     rtNumber += n;
                     73: }
                     74: 
                     75: argument_t *
                     76: argAlloc(void)
                     77: {
                     78:     static const argument_t prototype =
                     79:     {
                     80:        strNULL,                /* identifier_t argName */
                     81:        argNULL,                /* argument_t *argNext */
                     82:        akNone,                 /* arg_kind_t argKind */
                     83:        itNULL,                 /* ipc_type_t *argType */
                     84:        strNULL,                /* string_t argVarName */
                     85:        strNULL,                /* string_t argMsgField */
                     86:        strNULL,                /* string_t argTTName */
                     87:        strNULL,                /* string_t argPadName */
                     88:        flNone,                 /* ipc_flags_t argFlags */
                     89:        d_NO,                   /* dealloc_t argDeallocate */
                     90:        FALSE,                  /* boolean_t argLongForm */
                     91:        FALSE,                  /* boolean_t argServerCopy */
                     92:        FALSE,                  /* boolean_t argCountInOut */
                     93:        rtNULL,                 /* routine_t *argRoutine */
                     94:        argNULL,                /* argument_t *argCount */
                     95:        argNULL,                /* argument_t *argCInOut */
                     96:        argNULL,                /* argument_t *argPoly */
                     97:        argNULL,                /* argument_t *argDealloc */
                     98:        argNULL,                /* argument_t *argSCopy */
                     99:        argNULL,                /* argument_t *argParent */
                    100:        1,                      /* int argMultiplier */
                    101:        0,                      /* int argRequestPos */
                    102:        0,                      /* int argReplyPos */
                    103:        FALSE,                  /* boolean_t argByReferenceUser */
                    104:        FALSE                   /* boolean_t argByReferenceServer */
                    105:     };
                    106:     register argument_t *new;
                    107: 
                    108:     new = malloc(sizeof *new);
                    109:     if (new == argNULL)
                    110:        fatal("argAlloc(): %s", unix_error_string(errno));
                    111:     *new = prototype;
                    112:     return new;
                    113: }
                    114: 
                    115: routine_t *
                    116: rtMakeRoutine(identifier_t name, argument_t *args)
                    117: {
                    118:     register routine_t *rt = rtAlloc();
                    119: 
                    120:     rt->rtName = name;
                    121:     rt->rtKind = rkRoutine;
                    122:     rt->rtArgs = args;
                    123: 
                    124:     return rt;
                    125: }
                    126: 
                    127: routine_t *
                    128: rtMakeSimpleRoutine(identifier_t name, argument_t *args)
                    129: {
                    130:     register routine_t *rt = rtAlloc();
                    131: 
                    132:     rt->rtName = name;
                    133:     rt->rtKind = rkSimpleRoutine;
                    134:     rt->rtArgs = args;
                    135: 
                    136:     return rt;
                    137: }
                    138: 
                    139: routine_t *
                    140: rtMakeProcedure(identifier_t name, argument_t *args)
                    141: {
                    142:     register routine_t *rt = rtAlloc();
                    143: 
                    144:     rt->rtName = name;
                    145:     rt->rtKind = rkProcedure;
                    146:     rt->rtArgs = args;
                    147: 
                    148:     warn("Procedure %s: obsolete routine kind", name);
                    149: 
                    150:     return rt;
                    151: }
                    152: 
                    153: routine_t *
                    154: rtMakeSimpleProcedure(identifier_t name, argument_t *args)
                    155: {
                    156:     register routine_t *rt = rtAlloc();
                    157: 
                    158:     rt->rtName = name;
                    159:     rt->rtKind = rkSimpleProcedure;
                    160:     rt->rtArgs = args;
                    161: 
                    162:     warn("SimpleProcedure %s: obsolete routine kind", name);
                    163: 
                    164:     return rt;
                    165: }
                    166: 
                    167: routine_t *
                    168: rtMakeFunction(identifier_t name, argument_t *args, ipc_type_t *type)
                    169: {
                    170:     register routine_t *rt = rtAlloc();
                    171:     register argument_t *ret = argAlloc();
                    172: 
                    173:     ret->argName = name;
                    174:     ret->argKind = akReturn;
                    175:     ret->argType = type;
                    176:     ret->argNext = args;
                    177: 
                    178:     rt->rtName = name;
                    179:     rt->rtKind = rkFunction;
                    180:     rt->rtArgs = ret;
                    181: 
                    182:     warn("Function %s: obsolete routine kind", name);
                    183: 
                    184:     return rt;
                    185: }
                    186: 
                    187: const char *
                    188: rtRoutineKindToStr(routine_kind_t rk)
                    189: {
                    190:     switch (rk)
                    191:     {
                    192:       case rkRoutine:
                    193:        return "Routine";
                    194:       case rkSimpleRoutine:
                    195:        return "SimpleRoutine";
                    196:       case rkProcedure:
                    197:        return "Procedure";
                    198:       case rkSimpleProcedure:
                    199:        return "SimpleProcedure";
                    200:       case rkFunction:
                    201:        return "Function";
                    202:       default:
                    203:        fatal("rtRoutineKindToStr(%d): not a routine_kind_t", rk);
                    204:        /*NOTREACHED*/
                    205:     }
                    206: }
                    207: 
                    208: static void
                    209: rtPrintArg(register const argument_t *arg)
                    210: {
                    211:     register const ipc_type_t *it = arg->argType;
                    212: 
                    213:     if (!akCheck(arg->argKind, akbUserArg|akbServerArg) ||
                    214:        (akIdent(arg->argKind) == akeCount) ||
                    215:        (akIdent(arg->argKind) == akePoly))
                    216:        return;
                    217: 
                    218:     printf("\n\t");
                    219: 
                    220:     switch (akIdent(arg->argKind))
                    221:     {
                    222:       case akeRequestPort:
                    223:        printf("RequestPort");
                    224:        break;
                    225:       case akeReplyPort:
                    226:        printf("ReplyPort");
                    227:        break;
                    228:       case akeWaitTime:
                    229:        printf("WaitTime");
                    230:        break;
                    231:       case akeMsgOption:
                    232:        printf("MsgOption");
                    233:        break;
                    234:       case akeMsgSeqno:
                    235:        printf("MsgSeqno\t");
                    236:        break;
                    237:       default:
                    238:        if (akCheck(arg->argKind, akbRequest))
                    239:            if (akCheck(arg->argKind, akbSend))
                    240:                printf("In");
                    241:            else
                    242:                printf("(In)");
                    243:        if (akCheck(arg->argKind, akbReply))
                    244:            if (akCheck(arg->argKind, akbReturn))
                    245:                printf("Out");
                    246:            else
                    247:                printf("(Out)");
                    248:        printf("\t");
                    249:     }
                    250: 
                    251:     printf("\t%s: %s", arg->argName, it->itName);
                    252: 
                    253:     if (arg->argDeallocate != it->itDeallocate)
                    254:        if (arg->argDeallocate == d_YES)
                    255:            printf(", Dealloc");
                    256:        else if (arg->argDeallocate == d_MAYBE)
                    257:            printf(", Dealloc[]");
                    258:        else
                    259:            printf(", NotDealloc");
                    260: 
                    261:     if (arg->argLongForm != it->itLongForm)
                    262:        if (arg->argLongForm)
                    263:            printf(", IsLong");
                    264:        else
                    265:            printf(", IsNotLong");
                    266: 
                    267:     if (arg->argServerCopy)
                    268:        printf(", ServerCopy");
                    269: 
                    270:     if (arg->argCountInOut)
                    271:        printf(", CountInOut");
                    272: }
                    273: 
                    274: void
                    275: rtPrintRoutine(register const routine_t *rt)
                    276: {
                    277:     register const argument_t *arg;
                    278: 
                    279:     printf("%s (%d) %s(", rtRoutineKindToStr(rt->rtKind),
                    280:           rt->rtNumber, rt->rtName);
                    281: 
                    282:     for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
                    283:        rtPrintArg(arg);
                    284: 
                    285:     if (rt->rtKind == rkFunction)
                    286:        printf("): %s\n", rt->rtReturn->argType->itName);
                    287:     else
                    288:        printf(")\n");
                    289: 
                    290:     printf("\n");
                    291: }
                    292: 
                    293: /*
                    294:  * Determines appropriate value of msg-simple for the message,
                    295:  * and whether this value can vary at runtime.  (If it can vary,
                    296:  * then the simple value is optimistically returned as TRUE.)
                    297:  * Uses itInName values, so useful when sending messages.
                    298:  */
                    299: 
                    300: static void
                    301: rtCheckSimpleIn(const argument_t *args, u_int mask, boolean_t *fixed,
                    302:                boolean_t *simple)
                    303: {
                    304:     register const argument_t *arg;
                    305:     boolean_t MayBeComplex = FALSE;
                    306:     boolean_t MustBeComplex = FALSE;
                    307: 
                    308:     for (arg = args; arg != argNULL; arg = arg->argNext)
                    309:        if (akCheck(arg->argKind, mask))
                    310:        {
                    311:            register const ipc_type_t *it = arg->argType;
                    312: 
                    313:            if (it->itInName == MACH_MSG_TYPE_POLYMORPHIC)
                    314:                MayBeComplex = TRUE;
                    315: 
                    316:            if (it->itIndefinite)
                    317:                MayBeComplex = TRUE;
                    318: 
                    319:            if (MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
                    320:                !it->itInLine)
                    321:                MustBeComplex = TRUE;
                    322:        }
                    323: 
                    324:     *fixed = MustBeComplex || !MayBeComplex;
                    325:     *simple = !MustBeComplex;
                    326: }
                    327: 
                    328: /*
                    329:  * Determines appropriate value of msg-simple for the message,
                    330:  * and whether this value can vary at runtime.  (If it can vary,
                    331:  * then the simple value is optimistically returned as TRUE.)
                    332:  * Uses itOutName values, so useful when receiving messages
                    333:  * (and sending reply messages in KernelServer interfaces).
                    334:  */
                    335: 
                    336: static void
                    337: rtCheckSimpleOut(const argument_t *args, u_int mask, boolean_t *fixed,
                    338:                 boolean_t *simple)
                    339: {
                    340:     register const argument_t *arg;
                    341:     boolean_t MayBeComplex = FALSE;
                    342:     boolean_t MustBeComplex = FALSE;
                    343: 
                    344:     for (arg = args; arg != argNULL; arg = arg->argNext)
                    345:        if (akCheck(arg->argKind, mask))
                    346:        {
                    347:            register const ipc_type_t *it = arg->argType;
                    348: 
                    349:            if (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
                    350:                MayBeComplex = TRUE;
                    351: 
                    352:            if (it->itIndefinite)
                    353:                MayBeComplex = TRUE;
                    354: 
                    355:            if (MACH_MSG_TYPE_PORT_ANY(it->itOutName) ||
                    356:                !it->itInLine)
                    357:                MustBeComplex = TRUE;
                    358:        }
                    359: 
                    360:     *fixed = MustBeComplex || !MayBeComplex;
                    361:     *simple = !MustBeComplex;
                    362: }
                    363: 
                    364: static u_int
                    365: rtFindSize(const argument_t *args, u_int mask)
                    366: {
                    367:     register const argument_t *arg;
                    368:     u_int size = sizeof_mach_msg_header_t;
                    369: 
                    370:     for (arg = args; arg != argNULL; arg = arg->argNext)
                    371:        if (akCheck(arg->argKind, mask))
                    372:        {
                    373:            register ipc_type_t *it = arg->argType;
                    374: 
                    375:            if (arg->argLongForm) {
                    376:                /* might need proper alignment on 64bit archies */
                    377:                size = (size + word_size-1) & ~(word_size-1);
                    378:                size += sizeof_mach_msg_type_long_t;
                    379:            } else {
                    380:                register bs = (it->itSize / 8); /* in bytes */
                    381:                size += (bs > sizeof_mach_msg_type_t) ? bs : sizeof_mach_msg_type_t;
                    382:            }
                    383: 
                    384:            size += it->itMinTypeSize;
                    385:        }
                    386: 
                    387:     return size;
                    388: }
                    389: 
                    390: boolean_t
                    391: rtCheckMask(const argument_t *args, u_int mask)
                    392: {
                    393:     register const argument_t *arg;
                    394: 
                    395:     for (arg = args; arg != argNULL; arg = arg->argNext)
                    396:        if (akCheckAll(arg->argKind, mask))
                    397:            return TRUE;
                    398:     return FALSE;
                    399: }
                    400: 
                    401: boolean_t
                    402: rtCheckMaskFunction(const argument_t *args, u_int mask,
                    403:                    boolean_t (*func)(const argument_t *))
                    404: {
                    405:     register const argument_t *arg;
                    406: 
                    407:     for (arg = args; arg != argNULL; arg = arg->argNext)
                    408:        if (akCheckAll(arg->argKind, mask))
                    409:            if ((*func)(arg))
                    410:                return TRUE;
                    411:     return FALSE;
                    412: }
                    413: 
                    414: /* arg->argType may be NULL in this function */
                    415: 
                    416: static void
                    417: rtDefaultArgKind(const routine_t *rt, argument_t *arg)
                    418: {
                    419:     if ((arg->argKind == akNone) &&
                    420:        (rt->rtRequestPort == argNULL))
                    421:        arg->argKind = akRequestPort;
                    422: 
                    423:     if (arg->argKind == akNone)
                    424:        arg->argKind = akIn;
                    425: }
                    426: 
                    427: /*
                    428:  * Initializes arg->argDeallocate, arg->argLongForm,
                    429:  * arg->argServerCopy, arg->argCountInOut from arg->argFlags.
                    430:  */
                    431: 
                    432: static void
                    433: rtProcessArgFlags(register argument_t *arg)
                    434: {
                    435:     register const ipc_type_t *it = arg->argType;
                    436: 
                    437:     arg->argFlags = itCheckFlags(arg->argFlags, arg->argName);
                    438: 
                    439:     if (((IsKernelServer && akCheck(arg->argKind, akbReturn)) ||
                    440:         (IsKernelUser && akCheck(arg->argKind, akbSend))) &&
                    441:        (arg->argFlags & flDealloc) &&
                    442:        (it->itDeallocate == d_NO)) {
                    443:        /*
                    444:         *      For a KernelServer interface and an Out argument,
                    445:         *      or a KernelUser interface and an In argument,
                    446:         *      we avoid a possible spurious warning about the deallocate bit.
                    447:         *      For compatibility with Mach 2.5, the deallocate bit
                    448:         *      may need to be enabled on some inline arguments.
                    449:         */
                    450: 
                    451:        arg->argDeallocate = d_YES;
                    452:     } else
                    453:        arg->argDeallocate = itCheckDeallocate(it, arg->argFlags,
                    454:                                               it->itDeallocate, arg->argName);
                    455: 
                    456:     arg->argLongForm = itCheckIsLong(it, arg->argFlags,
                    457:                                     it->itLongForm, arg->argName);
                    458: 
                    459:     if (arg->argFlags & flServerCopy) {
                    460:        if (it->itIndefinite && akCheck(arg->argKind, akbSend))
                    461:            arg->argServerCopy = TRUE;
                    462:        else
                    463:            warn("%s: ServerCopy on argument is meaningless", arg->argName);
                    464:     }
                    465: 
                    466:     if (arg->argFlags & flCountInOut) {
                    467:        if (it->itVarArray && it->itInLine &&
                    468:            akCheck(arg->argKind, akbReply))
                    469:            arg->argCountInOut = TRUE;
                    470:        else
                    471:            warn("%s: CountInOut on argument is meaningless", arg->argName);
                    472:     }
                    473: }
                    474: 
                    475: static void
                    476: rtAugmentArgKind(argument_t *arg)
                    477: {
                    478:     register ipc_type_t *it = arg->argType;
                    479: 
                    480:     /* akbVariable means variable-sized inline. */
                    481: 
                    482:     if (it->itVarArray && it->itInLine)
                    483:     {
                    484:        if (akCheckAll(arg->argKind, akbRequest|akbReply))
                    485:            error("%s: Inline variable-sized arguments can't be InOut",
                    486:                  arg->argName);
                    487:        arg->argKind = akAddFeature(arg->argKind, akbVariable);
                    488: 
                    489:        /* akbIndefinite means inline or out-of-line */
                    490: 
                    491:        if (it->itIndefinite)
                    492:            arg->argKind = akAddFeature(arg->argKind, akbIndefinite);
                    493:     }
                    494: 
                    495:     /*
                    496:      * Kernel servers can't do quick-checking of request arguments
                    497:      * which are out-of-line or ports, because the deallocate bit isn't
                    498:      * predictable.  This is because the deallocate bit is preserved
                    499:      * at message copyin time and normalized during message copyout.
                    500:      * This accomodates old IPC programs which expect the deallocate
                    501:      * bit to be preserved.
                    502:      */
                    503: 
                    504:     if (akCheck(arg->argKind, akbRequest) &&
                    505:        !arg->argLongForm &&
                    506:        (it->itOutName != MACH_MSG_TYPE_POLYMORPHIC) &&
                    507:        !it->itVarArray &&
                    508:        !(IsKernelServer && (!it->itInLine ||
                    509:                             MACH_MSG_TYPE_PORT_ANY(it->itOutName))))
                    510:        arg->argKind = akAddFeature(arg->argKind, akbRequestQC);
                    511: 
                    512:     if (akCheck(arg->argKind, akbReply) &&
                    513:        !arg->argLongForm &&
                    514:        (it->itOutName != MACH_MSG_TYPE_POLYMORPHIC) &&
                    515:        !it->itVarArray)
                    516:        arg->argKind = akAddFeature(arg->argKind, akbReplyQC);
                    517: 
                    518:     /*
                    519:      * Need to use a local variable in the following cases:
                    520:      * 1) There is a translate-out function & the argument is being
                    521:      *    returned.  We need to translate it before it hits the message.
                    522:      * 2) There is a translate-in function & the argument is
                    523:      *    sent and returned.  We need a local variable for its address.
                    524:      * 3) There is a destructor function, which will be used
                    525:      *    (SendRcv and not ReturnSnd), and there is a translate-in
                    526:      *    function whose value must be saved for the destructor.
                    527:      * 4) This is a count arg, getting returned.  The count can't get
                    528:      *    stored directly into the msg-type, because the msg-type won't
                    529:      *    get initialized until later, and that would trash the count.
                    530:      * 5) This is a poly arg, getting returned.  The name can't get
                    531:      *    stored directly into the msg-type, because the msg-type won't
                    532:      *    get initialized until later, and that would trash the name.
                    533:      *  6) This is a dealloc arg, being returned.  The name can't be
                    534:      *    stored directly into the msg_type, because the msg-type
                    535:      *    field is a bit-field.
                    536:      */
                    537: 
                    538:     if (((it->itOutTrans != strNULL) &&
                    539:         akCheck(arg->argKind, akbReturnSnd)) ||
                    540:        ((it->itInTrans != strNULL) &&
                    541:         akCheckAll(arg->argKind, akbSendRcv|akbReturnSnd)) ||
                    542:        ((it->itDestructor != strNULL) &&
                    543:         akCheck(arg->argKind, akbSendRcv) &&
                    544:         !akCheck(arg->argKind, akbReturnSnd) &&
                    545:         (it->itInTrans != strNULL)) ||
                    546:        ((akIdent(arg->argKind) == akeCount) &&
                    547:         akCheck(arg->argKind, akbReturnSnd)) ||
                    548:        ((akIdent(arg->argKind) == akePoly) &&
                    549:         akCheck(arg->argKind, akbReturnSnd)) ||
                    550:        ((akIdent(arg->argKind) == akeDealloc) &&
                    551:         akCheck(arg->argKind, akbReturnSnd)))
                    552:     {
                    553:        arg->argKind = akRemFeature(arg->argKind, akbReplyCopy);
                    554:        arg->argKind = akAddFeature(arg->argKind, akbVarNeeded);
                    555:     }
                    556: 
                    557:     /*
                    558:      * If the argument is a variable-length array that can be passed in-line
                    559:      * or out-of-line, and is being returned, the server procedure
                    560:      * is passed a pointer to the buffer, which it can change.
                    561:      */
                    562:     if (it->itIndefinite &&
                    563:        akCheck(arg->argKind, akbReturnSnd))
                    564:     {
                    565:        arg->argKind = akAddFeature(arg->argKind, akbPointer);
                    566:     }
                    567: }
                    568: 
                    569: /* arg->argType may be NULL in this function */
                    570: 
                    571: static void
                    572: rtCheckRoutineArg(routine_t *rt, argument_t *arg)
                    573: {
                    574:     switch (akIdent(arg->argKind))
                    575:     {
                    576:       case akeRequestPort:
                    577:        if (rt->rtRequestPort != argNULL)
                    578:            warn("multiple RequestPort args in %s; %s won't be used",
                    579:                 rt->rtName, rt->rtRequestPort->argName);
                    580:        rt->rtRequestPort = arg;
                    581:        break;
                    582: 
                    583:       case akeReplyPort:
                    584:        if (akCheck (arg->argKind, akbUserArg))
                    585:        {
                    586:            if (rt->rtUReplyPort != argNULL)
                    587:                warn("multiple UserReplyPort args in %s; %s won't be used",
                    588:                     rt->rtName, rt->rtUReplyPort->argName);
                    589:            rt->rtUReplyPort = arg;
                    590:        }
                    591:        if (akCheck (arg->argKind, akbServerArg))
                    592:        {
                    593:            if (rt->rtSReplyPort != argNULL)
                    594:                warn("multiple ServerReplyPort args in %s; %s won't be used",
                    595:                     rt->rtName, rt->rtSReplyPort->argName);
                    596:            rt->rtSReplyPort = arg;
                    597:        }
                    598:        break;
                    599: 
                    600:       case akeWaitTime:
                    601:        if (rt->rtWaitTime != argNULL)
                    602:            warn("multiple WaitTime args in %s; %s won't be used",
                    603:                 rt->rtName, rt->rtWaitTime->argName);
                    604:        rt->rtWaitTime = arg;
                    605:        break;
                    606: 
                    607:       case akeMsgOption:
                    608:        if (rt->rtMsgOption != argNULL)
                    609:            warn("multiple MsgOption args in %s; %s won't be used",
                    610:                 rt->rtName, rt->rtMsgOption->argName);
                    611:        rt->rtMsgOption = arg;
                    612:        break;
                    613: 
                    614:       case akeMsgSeqno:
                    615:        if (rt->rtMsgSeqno != argNULL)
                    616:            warn("multiple MsgSeqno args in %s; %s won't be used",
                    617:                 rt->rtName, rt->rtMsgSeqno->argName);
                    618:        rt->rtMsgSeqno = arg;
                    619:        break;
                    620: 
                    621:       case akeReturn:
                    622:        if (rt->rtReturn != argNULL)
                    623:            warn("multiple Return args in %s; %s won't be used",
                    624:                 rt->rtName, rt->rtReturn->argName);
                    625:        rt->rtReturn = arg;
                    626:        break;
                    627: 
                    628:       default:
                    629:        break;
                    630:     }
                    631: }
                    632: 
                    633: /* arg->argType may be NULL in this function */
                    634: 
                    635: static void
                    636: rtSetArgDefaults(routine_t *rt, register argument_t *arg)
                    637: {
                    638:     arg->argRoutine = rt;
                    639:     if (arg->argVarName == strNULL)
                    640:        arg->argVarName = arg->argName;
                    641:     if (arg->argMsgField == strNULL)
                    642:        switch(akIdent(arg->argKind))
                    643:        {
                    644:          case akeRequestPort:
                    645:            arg->argMsgField = "Head.msgh_request_port";
                    646:            break;
                    647:          case akeReplyPort:
                    648:            arg->argMsgField = "Head.msgh_reply_port";
                    649:            break;
                    650:          case akeMsgSeqno:
                    651:            arg->argMsgField = "Head.msgh_seqno";
                    652:            break;
                    653:          default:
                    654:            arg->argMsgField = arg->argName;
                    655:            break;
                    656:        }
                    657:     if (arg->argTTName == strNULL)
                    658:        arg->argTTName = strconcat(arg->argName, "Type");
                    659:     if (arg->argPadName == strNULL)
                    660:        arg->argPadName = strconcat(arg->argName, "Pad");
                    661: 
                    662:     /*
                    663:      * The poly args for the request and reply ports have special defaults,
                    664:      * because their msg-type-name values aren't stored in normal fields.
                    665:      */
                    666: 
                    667:     if ((rt->rtRequestPort != argNULL) &&
                    668:        (rt->rtRequestPort->argPoly == arg) &&
                    669:        (arg->argType != itNULL)) {
                    670:        arg->argMsgField = "Head.msgh_bits";
                    671:        arg->argType->itInTrans = "MACH_MSGH_BITS_REQUEST";
                    672:     }
                    673: 
                    674:     if ((rt->rtUReplyPort != argNULL) &&
                    675:        (rt->rtUReplyPort->argPoly == arg) &&
                    676:        (arg->argType != itNULL)) {
                    677:        arg->argMsgField = "Head.msgh_bits";
                    678:        arg->argType->itInTrans = "MACH_MSGH_BITS_REPLY";
                    679:     }
                    680:     if ((rt->rtSReplyPort != argNULL) &&
                    681:        (rt->rtSReplyPort->argPoly == arg) &&
                    682:        (arg->argType != itNULL)) {
                    683:        arg->argMsgField = "Head.msgh_bits";
                    684:        arg->argType->itInTrans = "MACH_MSGH_BITS_REPLY";
                    685:     }
                    686: }
                    687: 
                    688: static void
                    689: rtAddCountArg(register argument_t *arg)
                    690: {
                    691:     register argument_t *count;
                    692: 
                    693:     count = argAlloc();
                    694:     count->argName = strconcat(arg->argName, "Cnt");
                    695:     count->argType = itMakeCountType();
                    696:     count->argParent = arg;
                    697:     count->argMultiplier = arg->argType->itElement->itNumber;
                    698:     count->argNext = arg->argNext;
                    699:     arg->argNext = count;
                    700:     arg->argCount = count;
                    701: 
                    702:     if (arg->argType->itString) {
                    703:        /* C String gets no Count argument on either side.
                    704:           There is no explicit field in the message -
                    705:           the count is passed as part of the descriptor. */
                    706:        count->argKind = akeCount;
                    707:        count->argVarName = (char *)0;
                    708:     } else
                    709:        count->argKind = akAddFeature(akCount,
                    710:                                  akCheck(arg->argKind, akbSendReturnBits));
                    711: 
                    712:     if (arg->argLongForm)
                    713:        count->argMsgField = strconcat(arg->argTTName,
                    714:                                       ".msgtl_number");
                    715:     else
                    716:        count->argMsgField = strconcat(arg->argTTName, ".msgt_number");
                    717: }
                    718: 
                    719: static void
                    720: rtAddCountInOutArg(register argument_t *arg)
                    721: {
                    722:     register argument_t *count;
                    723: 
                    724:     /*
                    725:      * The user sees a single count variable.  However, to get the
                    726:      * count passed from user to server for variable-sized inline OUT
                    727:      * arrays, we need two count arguments internally.  This is
                    728:      * because the count value lives in different message fields (and
                    729:      * is scaled differently) in the request and reply messages.
                    730:      *
                    731:      * The two variables have the same name to simplify code generation.
                    732:      *
                    733:      * This variable has a null argParent field because it has akbRequest.
                    734:      * For example, see rtCheckVariable.
                    735:      */
                    736: 
                    737:     count = argAlloc();
                    738:     count->argName = strconcat(arg->argName, "Cnt");
                    739:     count->argType = itMakeCountType();
                    740:     count->argParent = argNULL;
                    741:     count->argNext = arg->argNext;
                    742:     arg->argNext = count;
                    743:     (count->argCInOut = arg->argCount)->argCInOut = count;
                    744:     count->argKind = akCountInOut;
                    745: }
                    746: 
                    747: static void
                    748: rtAddPolyArg(register argument_t *arg)
                    749: {
                    750:     register const ipc_type_t *it = arg->argType;
                    751:     register argument_t *poly;
                    752:     arg_kind_t akbsend, akbreturn;
                    753: 
                    754:     poly = argAlloc();
                    755:     poly->argName = strconcat(arg->argName, "Poly");
                    756:     poly->argType = itMakePolyType();
                    757:     poly->argParent = arg;
                    758:     poly->argNext = arg->argNext;
                    759:     arg->argNext = poly;
                    760:     arg->argPoly = poly;
                    761: 
                    762:     /*
                    763:      * akbsend is bits added if the arg is In;
                    764:      * akbreturn is bits added if the arg is Out.
                    765:      * The mysterious business with KernelServer subsystems:
                    766:      * when packing Out arguments, they use OutNames instead
                    767:      * of InNames, and the OutName determines if they are poly-in
                    768:      * as well as poly-out.
                    769:      */
                    770: 
                    771:     akbsend = akbSend|akbSendBody;
                    772:     akbreturn = akbReturn|akbReturnBody;
                    773: 
                    774:     if (it->itInName == MACH_MSG_TYPE_POLYMORPHIC)
                    775:     {
                    776:        akbsend |= akbUserArg|akbSendSnd;
                    777:        if (!IsKernelServer)
                    778:            akbreturn |= akbServerArg|akbReturnSnd;
                    779:     }
                    780:     if (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
                    781:     {
                    782:        akbsend |= akbServerArg|akbSendRcv;
                    783:        akbreturn |= akbUserArg|akbReturnRcv;
                    784:        if (IsKernelServer)
                    785:            akbreturn |= akbServerArg|akbReturnSnd;
                    786:     }
                    787: 
                    788:     poly->argKind = akPoly;
                    789:     if (akCheck(arg->argKind, akbSend))
                    790:        poly->argKind = akAddFeature(poly->argKind,
                    791:                                     akCheck(arg->argKind, akbsend));
                    792:     if (akCheck(arg->argKind, akbReturn))
                    793:        poly->argKind = akAddFeature(poly->argKind,
                    794:                                     akCheck(arg->argKind, akbreturn));
                    795: 
                    796:     if (arg->argLongForm)
                    797:        poly->argMsgField = strconcat(arg->argTTName,
                    798:                                      ".msgtl_name");
                    799:     else
                    800:        poly->argMsgField = strconcat(arg->argTTName, ".msgt_name");
                    801: }
                    802: 
                    803: static void
                    804: rtAddDeallocArg(register argument_t *arg)
                    805: {
                    806:     register argument_t *dealloc;
                    807: 
                    808:     dealloc = argAlloc();
                    809:     dealloc->argName = strconcat(arg->argName, "Dealloc");
                    810:     dealloc->argType = itMakeDeallocType();
                    811:     dealloc->argParent = arg;
                    812:     dealloc->argNext = arg->argNext;
                    813:     arg->argNext = dealloc;
                    814:     arg->argDealloc = dealloc;
                    815: 
                    816:     /*
                    817:      * For Indefinite types, we leave out akbSendSnd and akbReturnSnd
                    818:      * so that the normal argument-packing is bypassed.  The special code
                    819:      * generated for the Indefinite argument handles the deallocate bit.
                    820:      * (It can only be enabled if the data is actually out-of-line.)
                    821:      */
                    822: 
                    823:     dealloc->argKind = akeDealloc;
                    824:     if (akCheck(arg->argKind, akbSend))
                    825:        dealloc->argKind = akAddFeature(dealloc->argKind,
                    826:                akCheck(arg->argKind,
                    827:                        akbUserArg|akbSend|akbSendBody|
                    828:                        (arg->argType->itIndefinite ? 0 : akbSendSnd)));
                    829:     if (akCheck(arg->argKind, akbReturn)) {
                    830:        dealloc->argKind = akAddFeature(dealloc->argKind,
                    831:                akCheck(arg->argKind,
                    832:                        akbServerArg|akbReturn|akbReturnBody|
                    833:                        (arg->argType->itIndefinite ? 0 : akbReturnSnd)));
                    834: 
                    835:        /*
                    836:         *  Without akbReturnSnd, rtAugmentArgKind will not add
                    837:         *  akbVarNeeded and rtAddByReference will not set
                    838:         *  argByReferenceServer.  So we do it here.
                    839:         */
                    840: 
                    841:        if (arg->argType->itIndefinite) {
                    842:            dealloc->argKind = akAddFeature(dealloc->argKind, akbVarNeeded);
                    843:            dealloc->argByReferenceServer = TRUE;
                    844:        }
                    845:     }
                    846: 
                    847:     if (arg->argLongForm)
                    848:        dealloc->argMsgField = strconcat(arg->argTTName,
                    849:                                         ".msgtl_header.msgt_deallocate");
                    850:     else
                    851:        dealloc->argMsgField = strconcat(arg->argTTName, ".msgt_deallocate");
                    852: 
                    853: }
                    854: 
                    855: static void
                    856: rtAddSCopyArg(register argument_t *arg)
                    857: {
                    858:     register argument_t *scopy;
                    859: 
                    860:     scopy = argAlloc();
                    861:     scopy->argName = strconcat(arg->argName, "SCopy");
                    862:     scopy->argType = itMakeDeallocType();
                    863:     scopy->argParent = arg;
                    864:     scopy->argNext = arg->argNext;
                    865:     arg->argNext = scopy;
                    866:     arg->argSCopy = scopy;
                    867: 
                    868:     scopy->argKind = akServerCopy;
                    869: 
                    870:     if (arg->argLongForm)
                    871:        scopy->argMsgField = strconcat(arg->argTTName,
                    872:                                        ".msgtl_header.msgt_inline");
                    873:     else
                    874:        scopy->argMsgField = strconcat(arg->argTTName, ".msgt_inline");
                    875: }
                    876: 
                    877: static void
                    878: rtCheckRoutineArgs(routine_t *rt)
                    879: {
                    880:     register argument_t *arg;
                    881: 
                    882:     for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
                    883:     {
                    884:        register const ipc_type_t *it = arg->argType;
                    885: 
                    886:        rtDefaultArgKind(rt, arg);
                    887:        rtCheckRoutineArg(rt, arg);
                    888: 
                    889:        /* need to set argTTName before adding implicit args */
                    890:        rtSetArgDefaults(rt, arg);
                    891: 
                    892:        /* the arg may not have a type (if there was some error in parsing it),
                    893:           in which case we don't want to do these steps. */
                    894: 
                    895:        if (it != itNULL)
                    896:        {
                    897:            /* need to set argLongForm before adding implicit args */
                    898:            rtProcessArgFlags(arg);
                    899:            rtAugmentArgKind(arg);
                    900: 
                    901:            /* args added here will get processed in later iterations */
                    902:            /* order of args is 'arg poly countinout count dealloc scopy' */
                    903: 
                    904:            if (arg->argServerCopy)
                    905:                rtAddSCopyArg(arg);
                    906:            if (arg->argDeallocate == d_MAYBE)
                    907:                rtAddDeallocArg(arg);
                    908:            if (it->itVarArray)
                    909:                rtAddCountArg(arg);
                    910:            if (arg->argCountInOut)
                    911:                rtAddCountInOutArg(arg);
                    912:            if ((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) ||
                    913:                (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC))
                    914:                rtAddPolyArg(arg);
                    915:        }
                    916:     }
                    917: }
                    918: 
                    919: static void
                    920: rtCheckArgTypes(routine_t *rt)
                    921: {
                    922:     if (rt->rtRequestPort == argNULL)
                    923:        error("%s %s doesn't have a server port argument",
                    924:              rtRoutineKindToStr(rt->rtKind), rt->rtName);
                    925: 
                    926:     if ((rt->rtKind == rkFunction) &&
                    927:        (rt->rtReturn == argNULL))
                    928:        error("Function %s doesn't have a return arg", rt->rtName);
                    929: 
                    930:     if ((rt->rtKind != rkFunction) &&
                    931:        (rt->rtReturn != argNULL))
                    932:        error("non-function %s has a return arg", rt->rtName);
                    933: 
                    934:     if ((rt->rtReturn == argNULL) && !rt->rtProcedure)
                    935:        rt->rtReturn = rt->rtRetCode;
                    936: 
                    937:     rt->rtServerReturn = rt->rtReturn;
                    938: 
                    939:     if ((rt->rtReturn != argNULL) &&
                    940:        (rt->rtReturn->argType != itNULL))
                    941:        itCheckReturnType(rt->rtReturn->argName,
                    942:                          rt->rtReturn->argType);
                    943: 
                    944:     if ((rt->rtRequestPort != argNULL) &&
                    945:        (rt->rtRequestPort->argType != itNULL))
                    946:        itCheckRequestPortType(rt->rtRequestPort->argName,
                    947:                               rt->rtRequestPort->argType);
                    948: 
                    949:     if ((rt->rtUReplyPort != argNULL) &&
                    950:        (rt->rtUReplyPort->argType != itNULL))
                    951:        itCheckReplyPortType(rt->rtUReplyPort->argName,
                    952:                             rt->rtUReplyPort->argType);
                    953:     if ((rt->rtSReplyPort != argNULL) &&
                    954:        (rt->rtSReplyPort->argType != itNULL))
                    955:        itCheckReplyPortType(rt->rtSReplyPort->argName,
                    956:                             rt->rtSReplyPort->argType);
                    957: 
                    958:     if ((rt->rtWaitTime != argNULL) &&
                    959:        (rt->rtWaitTime->argType != itNULL))
                    960:        itCheckIntType(rt->rtWaitTime->argName,
                    961:                       rt->rtWaitTime->argType);
                    962: 
                    963:     if ((rt->rtMsgOption != argNULL) &&
                    964:        (rt->rtMsgOption->argType != itNULL))
                    965:        itCheckIntType(rt->rtMsgOption->argName,
                    966:                       rt->rtMsgOption->argType);
                    967: 
                    968:     if ((rt->rtMsgSeqno != argNULL) &&
                    969:        (rt->rtMsgSeqno->argType != itNULL))
                    970:        itCheckNaturalType(rt->rtMsgSeqno->argName,
                    971:                       rt->rtMsgSeqno->argType);
                    972: }
                    973: 
                    974: /*
                    975:  * Check for arguments which are missing seemingly needed functions.
                    976:  * We make this check here instead of in itCheckDecl, because here
                    977:  * we can take into account what kind of argument the type is
                    978:  * being used with.
                    979:  *
                    980:  * These are warnings, not hard errors, because mig will generate
                    981:  * reasonable code in any case.  The generated code will work fine
                    982:  * if the ServerType and TransType are really the same, even though
                    983:  * they have different names.
                    984:  */
                    985: 
                    986: static void
                    987: rtCheckArgTrans(const routine_t *rt)
                    988: {
                    989:     register const argument_t *arg;
                    990: 
                    991:     /* the arg may not have a type (if there was some error in parsing it) */
                    992: 
                    993:     for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
                    994:     {
                    995:        register const ipc_type_t *it = arg->argType;
                    996: 
                    997:        if ((it != itNULL) &&
                    998:            !streql(it->itServerType, it->itTransType))
                    999:        {
                   1000:            if (akCheck(arg->argKind, akbSendRcv) &&
                   1001:                (it->itInTrans == strNULL))
                   1002:                warn("%s: argument has no in-translation function",
                   1003:                     arg->argName);
                   1004: 
                   1005:            if (akCheck(arg->argKind, akbReturnSnd) &&
                   1006:                (it->itOutTrans == strNULL))
                   1007:                warn("%s: argument has no out-translation function",
                   1008:                     arg->argName);
                   1009:        }
                   1010:     }
                   1011: }
                   1012: 
                   1013: /*
                   1014:  * Adds an implicit return-code argument.  It exists in the reply message,
                   1015:  * where it is the first piece of data.  Even if there is no reply
                   1016:  * message (rtOneWay is true), we generate the argument because
                   1017:  * the server-side stub needs a dummy reply msg to return error codes
                   1018:  * back to the server loop.
                   1019:  */
                   1020: 
                   1021: static void
                   1022: rtAddRetCode(routine_t *rt)
                   1023: {
                   1024:     register argument_t *arg = argAlloc();
                   1025: 
                   1026:     arg->argName = "RetCode";
                   1027:     arg->argType = itRetCodeType;
                   1028:     arg->argKind = akRetCode;
                   1029:     rt->rtRetCode = arg;
                   1030: 
                   1031:     /* add at beginning, so return-code is first in the reply message  */
                   1032:     arg->argNext = rt->rtArgs;
                   1033:     rt->rtArgs = arg;
                   1034: }
                   1035: 
                   1036: /*
                   1037:  *  Adds a dummy WaitTime argument to the function.
                   1038:  *  This argument doesn't show up in any C argument lists;
                   1039:  *  it implements the global WaitTime statement.
                   1040:  */
                   1041: 
                   1042: static void
                   1043: rtAddWaitTime(routine_t *rt, identifier_t name)
                   1044: {
                   1045:     register argument_t *arg = argAlloc();
                   1046:     argument_t **loc;
                   1047: 
                   1048:     arg->argName = "dummy WaitTime arg";
                   1049:     arg->argVarName = name;
                   1050:     arg->argType = itWaitTimeType;
                   1051:     arg->argKind = akeWaitTime;
                   1052:     rt->rtWaitTime = arg;
                   1053: 
                   1054:     /* add wait-time after msg-option, if possible */
                   1055: 
                   1056:     if (rt->rtMsgOption != argNULL)
                   1057:        loc = &rt->rtMsgOption->argNext;
                   1058:     else
                   1059:        loc = &rt->rtArgs;
                   1060: 
                   1061:     arg->argNext = *loc;
                   1062:     *loc = arg;
                   1063: 
                   1064:     rtSetArgDefaults(rt, arg);
                   1065: }
                   1066: 
                   1067: /*
                   1068:  *  Adds a dummy MsgOption argument to the function.
                   1069:  *  This argument doesn't show up in any C argument lists;
                   1070:  *  it implements the global MsgOption statement.
                   1071:  */
                   1072: 
                   1073: static void
                   1074: rtAddMsgOption(routine_t *rt, identifier_t name)
                   1075: {
                   1076:     register argument_t *arg = argAlloc();
                   1077:     argument_t **loc;
                   1078: 
                   1079:     arg->argName = "dummy MsgOption arg";
                   1080:     arg->argVarName = name;
                   1081:     arg->argType = itMsgOptionType;
                   1082:     arg->argKind = akeMsgOption;
                   1083:     rt->rtMsgOption = arg;
                   1084: 
                   1085:     /* add msg-option after msg-seqno */
                   1086: 
                   1087:     if (rt->rtMsgSeqno != argNULL)
                   1088:        loc = &rt->rtMsgSeqno->argNext;
                   1089:     else
                   1090:        loc = &rt->rtArgs;
                   1091: 
                   1092:     arg->argNext = *loc;
                   1093:     *loc = arg;
                   1094: 
                   1095:     rtSetArgDefaults(rt, arg);
                   1096: }
                   1097: 
                   1098: /*
                   1099:  *  Adds a dummy reply port argument to the function.  If USER is true, the
                   1100:  *  user reply port is set, otherwise the server.
                   1101:  */
                   1102: 
                   1103: static void
                   1104: rtAddDummyReplyPort(routine_t *rt, ipc_type_t *type, int user)
                   1105: {
                   1106:     register argument_t *arg = argAlloc();
                   1107:     argument_t **loc;
                   1108: 
                   1109:     arg->argName = "dummy ReplyPort arg";
                   1110:     arg->argVarName = "dummy ReplyPort arg";
                   1111:     arg->argType = type;
                   1112:     arg->argKind = akeReplyPort;
                   1113:     if (user)
                   1114:        rt->rtUReplyPort = arg;
                   1115:     else
                   1116:        rt->rtSReplyPort = arg;
                   1117: 
                   1118:     /* add the reply port after the request port */
                   1119: 
                   1120:     if (rt->rtRequestPort != argNULL)
                   1121:        loc = &rt->rtRequestPort->argNext;
                   1122:     else
                   1123:        loc = &rt->rtArgs;
                   1124: 
                   1125:     arg->argNext = *loc;
                   1126:     *loc = arg;
                   1127: 
                   1128:     rtSetArgDefaults(rt, arg);
                   1129: }
                   1130: 
                   1131: /*
                   1132:  * Initializes argRequestPos, argReplyPos, rtMaxRequestPos, rtMaxReplyPos,
                   1133:  * rtNumRequestVar, rtNumReplyVar, and adds akbVarNeeded to those arguments
                   1134:  * that need it because of variable-sized inline considerations.
                   1135:  *
                   1136:  * argRequestPos and argReplyPos get -1 if the value shouldn't be used.
                   1137:  */
                   1138: static void
                   1139: rtCheckVariable(register routine_t *rt)
                   1140: {
                   1141:     register argument_t *arg;
                   1142:     int NumRequestVar = 0;
                   1143:     int NumReplyVar = 0;
                   1144:     int MaxRequestPos = 0;
                   1145:     int MaxReplyPos = 0;
                   1146: 
                   1147:     for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
                   1148:        register argument_t *parent = arg->argParent;
                   1149: 
                   1150:        if (parent == argNULL) {
                   1151:            if (akCheck(arg->argKind, akbRequest|akbSend)) {
                   1152:                arg->argRequestPos = NumRequestVar;
                   1153:                MaxRequestPos = NumRequestVar;
                   1154:                if (akCheck(arg->argKind, akbVariable))
                   1155:                    NumRequestVar++;
                   1156:            } else
                   1157:                arg->argRequestPos = -1;
                   1158: 
                   1159:            if (akCheck(arg->argKind, akbReply|akbReturn)) {
                   1160:                arg->argReplyPos = NumReplyVar;
                   1161:                MaxReplyPos = NumReplyVar;
                   1162:                if (akCheck(arg->argKind, akbVariable))
                   1163:                    NumReplyVar++;
                   1164:            } else
                   1165:                arg->argReplyPos = -1;
                   1166:        } else {
                   1167:            arg->argRequestPos = parent->argRequestPos;
                   1168:            arg->argReplyPos = parent->argReplyPos;
                   1169:        }
                   1170: 
                   1171:        /* Out variables that follow a variable-sized field
                   1172:           need VarNeeded or ReplyCopy; they can't be stored
                   1173:           directly into the reply message. */
                   1174: 
                   1175:        if (akCheck(arg->argKind, akbReturnSnd) &&
                   1176:            !akCheck(arg->argKind, akbReplyCopy|akbVarNeeded) &&
                   1177:            (arg->argReplyPos > 0))
                   1178:            arg->argKind = akAddFeature(arg->argKind, akbVarNeeded);
                   1179:     }
                   1180: 
                   1181:     rt->rtNumRequestVar = NumRequestVar;
                   1182:     rt->rtNumReplyVar = NumReplyVar;
                   1183:     rt->rtMaxRequestPos = MaxRequestPos;
                   1184:     rt->rtMaxReplyPos = MaxReplyPos;
                   1185: }
                   1186: 
                   1187: /*
                   1188:  * Adds akbDestroy where needed.
                   1189:  */
                   1190: 
                   1191: static void
                   1192: rtCheckDestroy(register routine_t *rt)
                   1193: {
                   1194:     register argument_t *arg;
                   1195: 
                   1196:     for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
                   1197:        register const ipc_type_t *it = arg->argType;
                   1198: 
                   1199:        if(akCheck(arg->argKind, akbSendRcv) &&
                   1200:           !akCheck(arg->argKind, akbReturnSnd)) {
                   1201:           if ((it->itDestructor != strNULL) ||
                   1202:               (akCheck(arg->argKind, akbIndefinite) && !arg->argServerCopy))
                   1203:                arg->argKind = akAddFeature(arg->argKind, akbDestroy);
                   1204:        }
                   1205:     }
                   1206: }
                   1207: 
                   1208: /*
                   1209:  * Sets ByReferenceUser and ByReferenceServer.
                   1210:  */
                   1211: 
                   1212: static void
                   1213: rtAddByReference(register routine_t *rt)
                   1214: {
                   1215:     register argument_t *arg;
                   1216: 
                   1217:     for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
                   1218:        register const ipc_type_t *it = arg->argType;
                   1219: 
                   1220:        if (akCheck(arg->argKind, akbReturnRcv) &&
                   1221:            (it->itStruct || it->itIndefinite)) {
                   1222:            arg->argByReferenceUser = TRUE;
                   1223: 
                   1224:            /*
                   1225:             *  A CountInOut arg itself is not akbReturnRcv,
                   1226:             *  so we need to set argByReferenceUser specially.
                   1227:             */
                   1228: 
                   1229:            if (arg->argCInOut != argNULL)
                   1230:                arg->argCInOut->argByReferenceUser = TRUE;
                   1231:        }
                   1232: 
                   1233:        if (akCheck(arg->argKind, akbReturnSnd) &&
                   1234:            (it->itStruct || it->itIndefinite))
                   1235:            arg->argByReferenceServer = TRUE;
                   1236:     }
                   1237: }
                   1238: 
                   1239: void
                   1240: rtCheckRoutine(register routine_t *rt)
                   1241: {
                   1242:     /* Initialize random fields. */
                   1243: 
                   1244:     rt->rtErrorName = ErrorProc;
                   1245:     rt->rtOneWay = ((rt->rtKind == rkSimpleProcedure) ||
                   1246:                    (rt->rtKind == rkSimpleRoutine));
                   1247:     rt->rtProcedure = ((rt->rtKind == rkProcedure) ||
                   1248:                       (rt->rtKind == rkSimpleProcedure));
                   1249:     rt->rtUseError = rt->rtProcedure || (rt->rtKind == rkFunction);
                   1250:     rt->rtServerName = strconcat(ServerPrefix, rt->rtName);
                   1251:     rt->rtServerName = strconcat(RoutinePrefix, rt->rtServerName);
                   1252:     rt->rtUserName = strconcat(UserPrefix, rt->rtName);
                   1253:     rt->rtUserName = strconcat(RoutinePrefix, rt->rtUserName);
                   1254: 
                   1255:     /* Add implicit arguments. */
                   1256: 
                   1257:     rtAddRetCode(rt);
                   1258: 
                   1259:     /* Check out the arguments and their types.  Add count, poly
                   1260:        implicit args.  Any arguments added after rtCheckRoutineArgs
                   1261:        should have rtSetArgDefaults called on them. */
                   1262: 
                   1263:     rtCheckRoutineArgs(rt);
                   1264: 
                   1265:     /* Add dummy WaitTime and MsgOption arguments, if the routine
                   1266:        doesn't have its own args and the user specified global values. */
                   1267: 
                   1268:     if (rt->rtUReplyPort == argNULL)
                   1269:        if (rt->rtOneWay)
                   1270:            rtAddDummyReplyPort(rt, itZeroReplyPortType, 1);
                   1271:        else
                   1272:            rtAddDummyReplyPort(rt, itRealReplyPortType, 1);
                   1273:     if (rt->rtSReplyPort == argNULL)
                   1274:        if (rt->rtOneWay)
                   1275:            rtAddDummyReplyPort(rt, itZeroReplyPortType, 0);
                   1276:        else
                   1277:            rtAddDummyReplyPort(rt, itRealReplyPortType, 0);
                   1278: 
                   1279:     if (rt->rtMsgOption == argNULL)
                   1280:        if (MsgOption == strNULL)
                   1281:            rtAddMsgOption(rt, "MACH_MSG_OPTION_NONE");
                   1282:        else
                   1283:            rtAddMsgOption(rt, MsgOption);
                   1284: 
                   1285:     if ((rt->rtWaitTime == argNULL) &&
                   1286:        (WaitTime != strNULL))
                   1287:        rtAddWaitTime(rt, WaitTime);
                   1288: 
                   1289:     /* Now that all the arguments are in place, do more checking. */
                   1290: 
                   1291:     rtCheckArgTypes(rt);
                   1292:     rtCheckArgTrans(rt);
                   1293: 
                   1294:     if (rt->rtOneWay && rtCheckMask(rt->rtArgs, akbReturn))
                   1295:        error("%s %s has OUT argument",
                   1296:              rtRoutineKindToStr(rt->rtKind), rt->rtName);
                   1297: 
                   1298:     /* If there were any errors, don't bother calculating more info
                   1299:        that is only used in code generation anyway.  Therefore,
                   1300:        the following functions don't have to worry about null types. */
                   1301: 
                   1302:     if (errors > 0)
                   1303:        return;
                   1304: 
                   1305:     rtCheckSimpleIn(rt->rtArgs, akbRequest,
                   1306:                    &rt->rtSimpleFixedRequest,
                   1307:                    &rt->rtSimpleSendRequest);
                   1308:     rtCheckSimpleOut(rt->rtArgs, akbRequest,
                   1309:                     &rt->rtSimpleCheckRequest,
                   1310:                     &rt->rtSimpleReceiveRequest);
                   1311:     rt->rtRequestSize = rtFindSize(rt->rtArgs, akbRequest);
                   1312: 
                   1313:     if (IsKernelServer)
                   1314:        rtCheckSimpleOut(rt->rtArgs, akbReply,
                   1315:                         &rt->rtSimpleFixedReply,
                   1316:                         &rt->rtSimpleSendReply);
                   1317:     else
                   1318:        rtCheckSimpleIn(rt->rtArgs, akbReply,
                   1319:                        &rt->rtSimpleFixedReply,
                   1320:                        &rt->rtSimpleSendReply);
                   1321:     rtCheckSimpleOut(rt->rtArgs, akbReply,
                   1322:                     &rt->rtSimpleCheckReply,
                   1323:                     &rt->rtSimpleReceiveReply);
                   1324:     rt->rtReplySize = rtFindSize(rt->rtArgs, akbReply);
                   1325: 
                   1326:     rtCheckVariable(rt);
                   1327:     rtCheckDestroy(rt);
                   1328:     rtAddByReference(rt);
                   1329: 
                   1330:     if (rt->rtKind == rkFunction)
                   1331:        rt->rtNoReplyArgs = FALSE;
                   1332:     else
                   1333:        rt->rtNoReplyArgs = !rtCheckMask(rt->rtArgs, akbReturnSnd);
                   1334: }

unix.superglobalmegacorp.com

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