Annotation of Gnu-Mach/mig/routine.h, revision 1.1

1.1     ! root        1: /* 
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1991,1990 Carnegie Mellon University
        !             4:  * All Rights Reserved.
        !             5:  * 
        !             6:  * Permission to use, copy, modify and distribute this software and its
        !             7:  * documentation is hereby granted, provided that both the copyright
        !             8:  * notice and this permission notice appear in all copies of the
        !             9:  * software, derivative works or modified versions, and any portions
        !            10:  * thereof, and that both notices appear in supporting documentation.
        !            11:  * 
        !            12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            15:  * 
        !            16:  * Carnegie Mellon requests users of this software to return to
        !            17:  * 
        !            18:  *  Software Distribution Coordinator  or  [email protected]
        !            19:  *  School of Computer Science
        !            20:  *  Carnegie Mellon University
        !            21:  *  Pittsburgh PA 15213-3890
        !            22:  * 
        !            23:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            24:  * the rights to redistribute these changes.
        !            25:  */
        !            26: 
        !            27: #ifndef        _ROUTINE_H
        !            28: #define        _ROUTINE_H
        !            29: 
        !            30: #include <sys/types.h>
        !            31: 
        !            32: #include "boolean.h"
        !            33: #include "type.h"
        !            34: 
        !            35: /* base kind arg */
        !            36: #define akeNone                (0)
        !            37: #define akeNormal      (1)     /* a normal, user-defined argument */
        !            38: #define akeRequestPort (2)     /* pointed at by rtRequestPort */
        !            39: #define akeWaitTime    (3)     /* pointed at by rtWaitTime */
        !            40: #define akeReplyPort   (4)     /* pointed at by rtReplyPort */
        !            41: #define akeMsgOption   (5)     /* pointed at by rtMsgOption */
        !            42: #define akeMsgSeqno    (6)     /* pointed at by rtMsgSeqno */
        !            43: #define akeRetCode     (7)     /* pointed at by rtRetCode/rtReturn */
        !            44: #define akeReturn      (8)     /* pointed at by rtReturn */
        !            45: #define akeCount       (9)     /* a count arg for argParent */
        !            46: #define akePoly                (10)    /* a poly arg for argParent */
        !            47: #define        akeDealloc      (11)    /* a deallocate arg for argParent */
        !            48: #define        akeServerCopy   (12)    /* a server-copy arg for argParent */
        !            49: #define akeCountInOut  (13)    /* a count-in-out arg */
        !            50: 
        !            51: #define        akeBITS         (0x0000003f)
        !            52: #define        akbRequest      (0x00000040)    /* has a msg_type in request */
        !            53: #define        akbReply        (0x00000080)    /* has a msg_type in reply */
        !            54: #define        akbUserArg      (0x00000100)    /* an arg on user-side */
        !            55: #define        akbServerArg    (0x00000200)    /* an arg on server-side  */
        !            56: #define akbSend                (0x00000400)    /* value carried in request */
        !            57: #define akbSendBody    (0x00000800)    /* value carried in request body */
        !            58: #define akbSendSnd     (0x00001000)    /* value stuffed into request */
        !            59: #define akbSendRcv     (0x00002000)    /* value grabbed from request */
        !            60: #define akbReturn      (0x00004000)    /* value carried in reply */
        !            61: #define akbReturnBody  (0x00008000)    /* value carried in reply body */
        !            62: #define akbReturnSnd   (0x00010000)    /* value stuffed into reply */
        !            63: #define akbReturnRcv   (0x00020000)    /* value grabbed from reply */
        !            64: #define akbReplyInit   (0x00040000)    /* reply msg-type must be init'ed */
        !            65: #define akbRequestQC   (0x00080000)    /* msg_type can be checked quickly */
        !            66: #define akbReplyQC     (0x00100000)    /* msg_type can be checked quickly */
        !            67: #define akbReplyCopy   (0x00200000)    /* copy reply value from request */
        !            68: #define akbVarNeeded   (0x00400000)    /* may need local var in server */
        !            69: #define akbDestroy     (0x00800000)    /* call destructor function */
        !            70: #define akbVariable    (0x01000000)    /* variable size inline data */
        !            71: #define        akbIndefinite   (0x02000000)    /* variable size, inline or out */
        !            72: #define        akbPointer      (0x04000000)    /* server gets a pointer to the
        !            73:                                           real buffer */
        !            74: /* be careful, there aren't many bits left */
        !            75: 
        !            76: typedef u_int  arg_kind_t;
        !            77: 
        !            78: /*
        !            79:  * akbRequest means msg_type/data fields are allocated in the request
        !            80:  * msg.  akbReply means msg_type/data fields are allocated in the
        !            81:  * reply msg.  These bits (with akbReplyInit, akbRequestQC, akbReplyQC)
        !            82:  * control msg structure declarations packing, and checking of
        !            83:  * mach_msg_type_t fields.
        !            84:  *
        !            85:  * akbUserArg means this argument is an argument to the user-side stub.
        !            86:  * akbServerArg means this argument is an argument to
        !            87:  * the server procedure called by the server-side stub.
        !            88:  *
        !            89:  * The akbSend* and akbReturn* bits control packing/extracting values
        !            90:  * in the request and reply messages.
        !            91:  *
        !            92:  * akbSend means the argument's value is carried in the request msg.
        !            93:  * akbSendBody implies akbSend; the value is carried in the msg body.
        !            94:  * akbSendSnd implies akbSend; the value is stuffed into the request.
        !            95:  * akbSendRcv implies akbSend; the value is pulled out of the request.
        !            96:  *
        !            97:  * akbReturn, akbReturnBody, akbReturnSnd, akbReturnRcv are defined
        !            98:  * similarly but apply to the reply message.
        !            99:  *
        !           100:  * User-side code generation (header.c, user.c) and associated code
        !           101:  * should use akbSendSnd and akbReturnRcv, but not akbSendRcv and
        !           102:  * akbReturnSnd.  Server-side code generation (server.c) is reversed.
        !           103:  * Code generation should use the more specific akb{Send,Return}{Snd,Rcv}
        !           104:  * bits when possible, instead of akb{Send,Return}.
        !           105:  *
        !           106:  * Note that akRetCode and akReturn lack any Return bits, although
        !           107:  * there is a value in the msg.  These guys are packed/unpacked
        !           108:  * with special code, unlike other arguments.
        !           109:  *
        !           110:  * akbReplyInit implies akbReply.  It means the server-side stub
        !           111:  * should initialize the argument's msg_type field in the reply msg.
        !           112:  * Some special arguments (RetCode, Dummy, Tid) have their msg_type
        !           113:  * fields in the reply message initialized by the server demux
        !           114:  * function; these arguments have akbReply but not akbReplyInit.
        !           115:  *
        !           116:  * akbRequestQC implies akbRequest.  If it's on, then the
        !           117:  * mach_msg_type_t value in the request message can be checked quickly
        !           118:  * (by casting to an int and checking with a single comparison).
        !           119:  * akbReplyQC has the analogous meaning with respect to akbReply.
        !           120:  *
        !           121:  * akbVariable means the argument has variable-sized inline data.
        !           122:  * It isn't currently used for code generation, but routine.c
        !           123:  * does use it internally.  It is added in rtAugmentArgKind.
        !           124:  *
        !           125:  * akbReplyCopy and akbVarNeeded help control code generation in the
        !           126:  * server-side stub.  The preferred method of handling data in the
        !           127:  * server-side stub avoids copying into/out-of local variables.  In
        !           128:  * arguments get passed directly to the server proc from the request msg.
        !           129:  * Out arguments get stuffed directly into the reply msg by the server proc.
        !           130:  * For InOut arguments, the server proc gets the address of the data in
        !           131:  * the request msg, and the resulting data gets copied to the reply msg.
        !           132:  * Some arguments need a local variable in the server-side stub.  The
        !           133:  * code extracts the data from the request msg into the variable, and
        !           134:  * stuff the reply msg from the variable.
        !           135:  *
        !           136:  * akbReplyCopy implies akbReply.  It means the data should get copied
        !           137:  * from the request msg to the reply msg after the server proc is called.
        !           138:  * It is only used by akInOut.  akTid doesn't need it because the tid
        !           139:  * data in the reply msg is initialized in the server demux function.
        !           140:  *
        !           141:  * akbVarNeeded means the argument needs a local variable in the
        !           142:  * server-side stub.  It is added in rtAugmentArgKind and
        !           143:  * rtCheckVariable.  An argument shouldn't have all three of
        !           144:  * akbReturnSnd, akbVarNeeded and akbReplyCopy, because this indicates
        !           145:  * the reply msg should be stuffed both ways.
        !           146:  *
        !           147:  * akbDestroy helps control code generation in the server-side stub.
        !           148:  * It means this argument has a destructor function which should be called.
        !           149:  *
        !           150:  * Header file generation (header.c) uses:
        !           151:  *     akbUserArg
        !           152:  *
        !           153:  * User stub generation (user.c) uses:
        !           154:  *     akbUserArg, akbRequest, akbReply, akbSendSnd,
        !           155:  *     akbSendBody, akbReturnRcv, akbReplyQC
        !           156:  *
        !           157:  * Server stub generation (server.c) uses:
        !           158:  *     akbServerArg, akbRequest, akbReply, akbSendRcv, akbReturnSnd,
        !           159:  *     akbReplyInit, akbReplyCopy, akbVarNeeded, akbSendBody, akbRequestQC
        !           160:  *
        !           161:  *
        !           162:  * During code generation, the routine, argument, and type data structures
        !           163:  * are read-only.  The code generation functions' output is their only
        !           164:  * side-effect.
        !           165:  *
        !           166:  *
        !           167:  * Style note:
        !           168:  * Code can use logical operators (|, &, ~) on akb values.
        !           169:  * ak values should be manipulated with the ak functions.
        !           170:  */
        !           171: 
        !           172: /* various useful combinations */
        !           173: 
        !           174: #define akbNone                (0)
        !           175: #define akbAll         (~akbNone)
        !           176: #define akbAllBits     (~akeBITS)
        !           177: 
        !           178: #define akbSendBits    (akbSend|akbSendBody|akbSendSnd|akbSendRcv)
        !           179: #define akbReturnBits  (akbReturn|akbReturnBody|akbReturnSnd|akbReturnRcv)
        !           180: #define akbSendReturnBits      (akbSendBits|akbReturnBits)
        !           181: 
        !           182: #define akNone         akeNone
        !           183: 
        !           184: #define akIn           akAddFeature(akeNormal,                         \
        !           185:        akbUserArg|akbServerArg|akbRequest|akbSendBits)
        !           186: 
        !           187: #define akOut          akAddFeature(akeNormal,                         \
        !           188:        akbUserArg|akbServerArg|akbReply|akbReturnBits|akbReplyInit)
        !           189: 
        !           190: #define akInOut                akAddFeature(akeNormal,                         \
        !           191:        akbUserArg|akbServerArg|akbRequest|akbReply|                    \
        !           192:        akbSendBits|akbReturnBits|akbReplyInit|akbReplyCopy)
        !           193: 
        !           194: #define akRequestPort  akAddFeature(akeRequestPort,                    \
        !           195:        akbUserArg|akbServerArg|akbSend|akbSendSnd|akbSendRcv)
        !           196: 
        !           197: #define akWaitTime     akAddFeature(akeWaitTime, akbUserArg)
        !           198: 
        !           199: #define akMsgOption    akAddFeature(akeMsgOption, akbUserArg)
        !           200: 
        !           201: #define akMsgSeqno     akAddFeature(akeMsgSeqno,                       \
        !           202:        akbServerArg|akbSend|akbSendRcv)
        !           203: 
        !           204: #define akReplyPort    akAddFeature(akeReplyPort,                      \
        !           205:        akbUserArg|akbServerArg|akbSend|akbSendSnd|akbSendRcv)
        !           206: 
        !           207: #define akUReplyPort   akAddFeature(akeReplyPort,                      \
        !           208:        akbUserArg|akbSend|akbSendSnd|akbSendRcv)
        !           209: 
        !           210: #define akSReplyPort   akAddFeature(akeReplyPort,                      \
        !           211:        akbServerArg|akbSend|akbSendSnd|akbSendRcv)
        !           212: 
        !           213: #define akRetCode      akAddFeature(akeRetCode, akbReply)
        !           214: 
        !           215: #define akReturn       akAddFeature(akeReturn,                         \
        !           216:        akbReply|akbReplyInit)
        !           217: 
        !           218: #define akCount                akAddFeature(akeCount,                          \
        !           219:        akbUserArg|akbServerArg)
        !           220: 
        !           221: #define akPoly         akePoly
        !           222: 
        !           223: #define        akDealloc       akAddFeature(akeDealloc, akbUserArg)
        !           224: 
        !           225: #define        akServerCopy    akAddFeature(akeServerCopy, akbServerArg|akbSendRcv)
        !           226: 
        !           227: #define akCountInOut   akAddFeature(akeCountInOut, akbRequest|akbSendBits)
        !           228: 
        !           229: #define        akCheck(ak, bits)       ((ak) & (bits))
        !           230: #define akCheckAll(ak, bits)   (akCheck(ak, bits) == (bits))
        !           231: #define akAddFeature(ak, bits) ((ak)|(bits))
        !           232: #define akRemFeature(ak, bits) ((ak)&~(bits))
        !           233: #define akIdent(ak)            ((ak) & akeBITS)
        !           234: 
        !           235: /*
        !           236:  * The arguments to a routine/function are linked in left-to-right order.
        !           237:  * argName is used for error messages and pretty-printing,
        !           238:  * not code generation.  Code generation shouldn't make any assumptions
        !           239:  * about the order of arguments, esp. count and poly arguments.
        !           240:  * (Unfortunately, code generation for inline variable-sized arguments
        !           241:  * does make such assumptions.)
        !           242:  *
        !           243:  * argVarName is the name used in generated code for function arguments
        !           244:  * and local variable names.  argMsgField is the name used in generated
        !           245:  * code for the field in msgs where the argument's value lives.
        !           246:  * argTTName is the name used in generated code for msg-type fields and
        !           247:  * static variables used to initialize those fields.  argPadName is the
        !           248:  * name used in generated code for a padding field in msgs.
        !           249:  *
        !           250:  * argFlags can be used to override the deallocate and longform bits
        !           251:  * in the argument's type.  rtProcessArgFlags sets argDeallocate and
        !           252:  * argLongForm from it and the type.  Code generation shouldn't use
        !           253:  * argFlags.
        !           254:  *
        !           255:  * argCount, argPoly, and argDealloc get to the implicit count, poly,
        !           256:  * and dealloc arguments associated with the argument; they should be
        !           257:  * used instead of argNext.  In these implicit arguments, argParent is
        !           258:  * a pointer to the "real" arg.
        !           259:  *
        !           260:  * In count arguments, argMultiplier is a scaling factor applied to
        !           261:  * the count arg's value to get msg-type-number.  It is equal to
        !           262:  *     argParent->argType->itElement->itNumber
        !           263:  */
        !           264: 
        !           265: typedef struct argument
        !           266: {
        !           267:     /* if argKind == akReturn, then argName is name of the function */
        !           268:     identifier_t argName;
        !           269:     struct argument *argNext;
        !           270: 
        !           271:     arg_kind_t argKind;
        !           272:     ipc_type_t *argType;
        !           273: 
        !           274:     const_string_t argVarName; /* local variable and argument names */
        !           275:     const_string_t argMsgField;        /* message field's name */
        !           276:     const_string_t argTTName;  /* name for msg_type fields, static vars */
        !           277:     const_string_t argPadName; /* name for pad field in msg */
        !           278: 
        !           279:     ipc_flags_t argFlags;
        !           280:     dealloc_t argDeallocate;   /* overrides argType->itDeallocate */
        !           281:     boolean_t argLongForm;     /* overrides argType->itLongForm */
        !           282:     boolean_t argServerCopy;
        !           283:     boolean_t argCountInOut;
        !           284: 
        !           285:     struct routine *argRoutine;        /* routine we are part of */
        !           286: 
        !           287:     struct argument *argCount; /* our count arg, if present */
        !           288:     struct argument *argCInOut;        /* our CountInOut arg, if present */
        !           289:     struct argument *argPoly;  /* our poly arg, if present */
        !           290:     struct argument *argDealloc;/* our dealloc arg, if present */
        !           291:     struct argument *argSCopy; /* our serverCopy arg, if present */
        !           292:     struct argument *argParent;        /* in a count or poly arg, the base arg */
        !           293:     int argMultiplier;         /* for Count argument: parent is a multiple
        !           294:                                   of a basic IPC type.  Argument must be
        !           295:                                   multiplied by Multiplier to get IPC
        !           296:                                   number-of-elements. */
        !           297: 
        !           298:     /* how variable/inline args precede this one, in request and reply */
        !           299:     int argRequestPos;
        !           300:     int argReplyPos;
        !           301:     /* whether argument is by reference, on user and server side */
        !           302:     boolean_t  argByReferenceUser;
        !           303:     boolean_t  argByReferenceServer;
        !           304: } argument_t;
        !           305: 
        !           306: /*
        !           307:  * The various routine kinds' peculiarities are abstracted by rtCheckRoutine
        !           308:  * into attributes like rtOneWay, rtProcedure, etc.  These are what
        !           309:  * code generation should use.  It is Bad Form for code generation to
        !           310:  * test rtKind.
        !           311:  */
        !           312: 
        !           313: typedef enum
        !           314: {
        !           315:     rkRoutine,
        !           316:     rkSimpleRoutine,
        !           317:     rkSimpleProcedure,
        !           318:     rkProcedure,
        !           319:     rkFunction,
        !           320: } routine_kind_t;
        !           321: 
        !           322: typedef struct routine
        !           323: {
        !           324:     identifier_t rtName;
        !           325:     routine_kind_t rtKind;
        !           326:     argument_t *rtArgs;
        !           327:     u_int rtNumber;            /* used for making msg ids */
        !           328: 
        !           329:     identifier_t rtUserName;   /* user-visible name (UserPrefix + Name) */
        !           330:     identifier_t rtServerName; /* server-side name (ServerPrefix + Name) */
        !           331: 
        !           332:     /* rtErrorName is only used for Procs, SimpleProcs, & Functions */
        !           333:     identifier_t rtErrorName;  /* error-handler name */
        !           334: 
        !           335:     boolean_t rtOneWay;                /* SimpleProcedure or SimpleRoutine */
        !           336:     boolean_t rtProcedure;     /* Procedure or SimpleProcedure */
        !           337:     boolean_t rtUseError;      /* Procedure or Function */
        !           338: 
        !           339:     boolean_t rtSimpleFixedRequest;    /* fixed msg-simple value in request */
        !           340:     boolean_t rtSimpleSendRequest;     /* in any case, initial value */
        !           341:     boolean_t rtSimpleCheckRequest;    /* check msg-simple in request */
        !           342:     boolean_t rtSimpleReceiveRequest;  /* if so, the expected value */
        !           343: 
        !           344:     boolean_t rtSimpleFixedReply;      /* fixed msg-simple value in reply */
        !           345:     boolean_t rtSimpleSendReply;       /* in any case, initial value */
        !           346:     boolean_t rtSimpleCheckReply;      /* check msg-simple in reply */
        !           347:     boolean_t rtSimpleReceiveReply;    /* if so, the expected value */
        !           348: 
        !           349:     u_int rtRequestSize;       /* minimal size of a legal request msg */
        !           350:     u_int rtReplySize;         /* minimal size of a legal reply msg */
        !           351: 
        !           352:     int rtNumRequestVar;       /* number of variable/inline args in request */
        !           353:     int rtNumReplyVar;         /* number of variable/inline args in reply */
        !           354: 
        !           355:     int rtMaxRequestPos;       /* maximum of argRequestPos */
        !           356:     int rtMaxReplyPos;         /* maximum of argReplyPos */
        !           357: 
        !           358:     boolean_t rtNoReplyArgs;   /* if so, no reply message arguments beyond
        !           359:                                   what the server dispatch routine inserts */
        !           360: 
        !           361:     /* distinguished arguments */
        !           362:     argument_t *rtRequestPort; /* always non-NULL, defaults to first arg */
        !           363:     argument_t *rtUReplyPort;  /* always non-NULL, defaults to Mig-supplied */
        !           364:     argument_t *rtSReplyPort;  /* always non-NULL, defaults to Mig-supplied */
        !           365:     argument_t *rtReturn;      /* non-NULL unless rtProcedure */
        !           366:     argument_t *rtServerReturn;        /* NULL or rtReturn  */
        !           367:     argument_t *rtRetCode;     /* always non-NULL */
        !           368:     argument_t *rtWaitTime;    /* if non-NULL, will use MACH_RCV_TIMEOUT */
        !           369:     argument_t *rtMsgOption;   /* always non-NULL, defaults to NONE */
        !           370:     argument_t *rtMsgSeqno;    /* if non-NULL, server gets passed seqno */
        !           371: } routine_t;
        !           372: 
        !           373: #define rtNULL         ((routine_t *) 0)
        !           374: #define argNULL                ((argument_t *) 0)
        !           375: 
        !           376: extern u_int rtNumber;
        !           377: /* rt->rtNumber will be initialized */
        !           378: extern routine_t *rtAlloc(void);
        !           379: /* skip a number */
        !           380: extern void rtSkip(int);
        !           381: 
        !           382: extern argument_t *argAlloc(void);
        !           383: 
        !           384: extern boolean_t rtCheckMask(const argument_t *args, u_int mask);
        !           385: 
        !           386: extern boolean_t rtCheckMaskFunction(const argument_t *args, u_int mask,
        !           387:                                     boolean_t (*func)(const argument_t *arg));
        !           388: 
        !           389: extern routine_t *rtMakeRoutine(identifier_t name, argument_t *args);
        !           390: extern routine_t *rtMakeSimpleRoutine(identifier_t name, argument_t *args);
        !           391: extern routine_t *rtMakeProcedure(identifier_t name, argument_t *args);
        !           392: extern routine_t *rtMakeSimpleProcedure(identifier_t name, argument_t *args);
        !           393: extern routine_t *rtMakeFunction(identifier_t name, argument_t *args,
        !           394:                                 ipc_type_t *type);
        !           395: 
        !           396: extern void rtPrintRoutine(const routine_t *rt);
        !           397: extern void rtCheckRoutine(routine_t *rt);
        !           398: 
        !           399: extern const char *rtRoutineKindToStr(routine_kind_t rk);
        !           400: 
        !           401: #endif /* _ROUTINE_H */

unix.superglobalmegacorp.com

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