xref: /trueos/usr.bin/migcom/routine.h (revision 8b380be28230988e4ffc12352ae9f073bfd17633)
1 /*
2  * Copyright 1991-1998 by Open Software Foundation, Inc.
3  *              All Rights Reserved
4  *
5  * Permission to use, copy, modify, and distribute this software and
6  * its documentation for any purpose and without fee is hereby granted,
7  * provided that the above copyright notice appears in all copies and
8  * that both the copyright notice and this permission notice appear in
9  * supporting documentation.
10  *
11  * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
12  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13  * FOR A PARTICULAR PURPOSE.
14  *
15  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
16  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
18  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
19  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 /*
22  * cmk1.1
23  */
24 /*
25  * Mach Operating System
26  * Copyright (c) 1991,1990 Carnegie Mellon University
27  * All Rights Reserved.
28  *
29  * Permission to use, copy, modify and distribute this software and its
30  * documentation is hereby granted, provided that both the copyright
31  * notice and this permission notice appear in all copies of the
32  * software, derivative works or modified versions, and any portions
33  * thereof, and that both notices appear in supporting documentation.
34  *
35  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
36  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
37  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
38  *
39  * Carnegie Mellon requests users of this software to return to
40  *
41  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
42  *  School of Computer Science
43  *  Carnegie Mellon University
44  *  Pittsburgh PA 15213-3890
45  *
46  * any improvements or extensions that they make and grant Carnegie Mellon
47  * the rights to redistribute these changes.
48  */
49 /*
50  * 92/03/03  16:25:12  jeffreyh
51  * 	Changes from TRUNK
52  * 	[92/02/26  12:32:23  jeffreyh]
53  *
54  * 92/01/14  16:46:34  rpd
55  * 	Removed akbWasInOut.  Added akeCountInOut, argCInOut.
56  * 	[92/01/08            rpd]
57  *
58  * 92/01/03  20:29:52  dbg
59  * 	Add byReferenceUser and byReferenceServer to each argument, so
60  * 	they can be individually set.  Add akbPointer.
61  * 	[91/09/04            dbg]
62  *
63  * 91/08/28  11:17:17  jsb
64  * 	Removed Camelot and TrapRoutine support.
65  * 	Changed MsgKind to MsgSeqno.
66  * 	[91/08/12            rpd]
67  *
68  * 91/07/31  18:10:37  dbg
69  * 	Add akbIndefinite, argServerCopy.
70  * 	[91/04/10            dbg]
71  *
72  * 	Change argDeallocate to an enumerated type, to allow for
73  * 	user-specified deallocate flag.
74  *
75  * 	Add rtCheckMaskFunction.  Add rtNoReplyArgs to routine
76  * 	structure.
77  * 	[91/04/03            dbg]
78  *
79  * 91/02/05  17:55:28  mrt
80  * 	Changed to new Mach copyright
81  * 	[91/02/01  17:55:21  mrt]
82  *
83  * 90/06/02  15:05:23  rpd
84  * 	Created for new IPC.
85  * 	[90/03/26  21:12:57  rpd]
86  *
87  * 07-Apr-89  Richard Draves (rpd) at Carnegie-Mellon University
88  *	Extensive revamping.  Added polymorphic arguments.
89  *	Allow multiple variable-sized inline arguments in messages.
90  *
91  * 20-Dec-87  David Golub (dbg) at Carnegie-Mellon University
92  *	Added pointers to last Request and Reply arguments.
93  *	Added flag to show that (only) last argument is variable-sized.
94  *	Added argMultiplier field for count arguments, where parent
95  *	argument is itself a multiple of an IPC type.
96  *
97  * 16-Nov-87  David Golub (dbg) at Carnegie-Mellon University
98  *	Don't add akbVarNeeded attribute here - server.c can
99  *	better determine whether it is needed.
100  *
101  * 21-Aug-87  Mary Thompson (mrt) at Carnegie-Mellon University
102  *	Added argFlag field to argument_t
103  *
104  * 18-Aug-87  Mary Thompson (mrt) at Carnegie-Mellon University
105  *	Changed akTid to omit akServerArg
106  *	Changed arg_kind_t to u_int to make code more obvious and
107  *	to get rid of compiler warnings and to give hc a chance.
108  *	Changed flags on akTid, akDummy.
109  *
110  * 10-Aug-87  Mary Thompson (mrt) at Carnegie-Mellon University
111  *	Added defines need to make MsgType a legitimate argument type
112  *
113  * 28-May-87  Richard Draves (rpd) at Carnegie-Mellon University
114  *	Created.
115  */
116 
117 #ifndef	_ROUTINE_H
118 #define	_ROUTINE_H
119 
120 #include "type.h"
121 #include <mach/message.h>
122 #include <mach/boolean.h>
123 #include <sys/types.h>
124 
125 /* base kind arg */
126 #define akeNone		(0)
127 #define akeNormal	(1)	/* a normal, user-defined argument */
128 #define akeRequestPort	(2)	/* pointed at by rtRequestPort */
129 #define akeWaitTime	(3)	/* pointed at by rtWaitTime */
130 #define akeReplyPort	(4)	/* pointed at by rtReplyPort */
131 #define akeMsgOption	(5)	/* pointed at by rtMsgOption */
132 #define akeMsgSeqno	(6)	/* pointed at by rtMsgSeqno */
133 #define akeRetCode	(7)	/* pointed at by rtRetCode */
134 #define akeNdrCode	(8)	/* pointed at by rtNdrCode */
135 #define akeCount	(9)	/* a count arg for argParent */
136 #define akePoly		(10)	/* a poly arg for argParent */
137 #define	akeDealloc	(11)	/* a deallocate arg for argParent */
138 #define akeCountInOut   (12)  /* a count-in-out arg */
139 #define akeSameCount    (13)  /* a samecount case: in fact, a no count! */
140 #define akeSubCount     (14)  /* a array of array case: subordinate arrays count */
141 #define akeImplicit     (15)  /* an implicit argument, from the trailer */
142 #define akeSecToken     (16)  /* an argument from the trailer: the security token */
143 #define akeAuditToken   (17)  /* an argument from the trailer: the audit token */
144 #define akeContextToken (18)  /* an argument from the trailer: the context token */
145 #define akeSendTime     (19)  /* pointed at by rtWaitTime */
146 
147 
148 #define	akeBITS		(0x0000003f)
149 #define	akbRequest	(0x00000040)	/* has a msg_type in request */
150 #define	akbReply	(0x00000080)	/* has a msg_type in reply */
151 #define	akbUserArg	(0x00000100)	/* an arg on user-side */
152 #define	akbServerArg	(0x00000200)	/* an arg on server-side  */
153 #define akbSend		(0x00000400)	/* value carried in request */
154 #define akbSendBody	(0x00000800)	/* value carried in request body */
155 #define akbSendSnd	(0x00001000)	/* value stuffed into request */
156 #define akbSendRcv	(0x00002000)	/* value grabbed from request */
157 #define akbReturn	(0x00004000)	/* value carried in reply */
158 #define akbReturnBody	(0x00008000)	/* value carried in reply body */
159 #define akbReturnSnd	(0x00010000)	/* value stuffed into reply */
160 #define akbReturnRcv	(0x00020000)	/* value grabbed from reply */
161 #define akbReturnNdr      (0x00040000)  /* needs NDR conversion in reply */
162 #define akbReplyInit	(0x00080000)	/* reply value doesn't come from target routine */
163 #define akbReplyCopy	(0x00200000)	/* copy reply value from request */
164 #define akbVarNeeded	(0x00400000)	/* may need local var in server */
165 #define akbDestroy	(0x00800000)	/* call destructor function */
166 #define akbSendNdr        (0x04000000)  /* needs NDR conversion in request */
167 #define akbVariable	(0x01000000)	/* variable size inline data */
168 #define akbSendKPD 	(0x08000000)	/* the arg is sent in the Kernel Processed Data
169 					   section of the Request message */
170 #define akbReturnKPD 	(0x10000000)	/* the arg is sent in the Kernel Processed Data
171 					   section of the Reply message */
172 #define akbUserImplicit 	(0x20000000)	/* the arg is Impl */
173 #define akbServerImplicit 	(0x40000000)	/* the arg is Impl */
174 #define akbOverwrite 	(0x80000000)
175 /* be careful, there aren't many bits left */
176 
177 typedef u_int  arg_kind_t;
178 
179 /*
180  * akbRequest means msg_type/data fields are allocated in the request
181  * msg.  akbReply means msg_type/data fields are allocated in the
182  * reply msg.  These bits * control msg structure declarations packing,
183  * and checking of mach_msg_type_t fields.
184  *
185  * akbUserArg means this argument is an argument to the user-side stub.
186  * akbServerArg means this argument is an argument to
187  * the server procedure called by the server-side stub.
188  *
189  * The akbSend* and akbReturn* bits control packing/extracting values
190  * in the request and reply messages.
191  *
192  * akbSend means the argument's value is carried in the request msg.
193  * akbSendBody implies akbSend; the value is carried in the msg body.
194  * akbSendKPD is the equivalent of akbSendBody for Kernel Processed Data.
195  * akbSendSnd implies akbSend; the value is stuffed into the request.
196  * akbSendRcv implies akbSend; the value is pulled out of the request.
197  *
198  * akbReturn, akbReturnBody, akbReturnSnd, akbReturnRcv are defined
199  * similarly but apply to the reply message.
200  *
201  * User-side code generation (header.c, user.c) and associated code
202  * should use akbSendSnd and akbReturnRcv, but not akbSendRcv and
203  * akbReturnSnd.  Server-side code generation (server.c) is reversed.
204  * Code generation should use the more specific akb{Send,Return}{Snd,Rcv}
205  * bits when possible, instead of akb{Send,Return}.
206  *
207  * Note that akRetCode and akReturn lack any Return bits, although
208  * there is a value in the msg.  These guys are packed/unpacked
209  * with special code, unlike other arguments.
210  *
211  * akbReplyInit implies akbReply.  It means the server-side stub
212  * should initialize the field, because its value does not come
213  * from the execution of the target routine: the setting of the
214  * NDR record is the sole example (at the moment) of use of this flag.
215  *
216  * akbVariable means the argument has variable-sized inline data.
217  * It isn't currently used for code generation, but routine.c
218  * does use it internally.  It is added in rtAugmentArgKind.
219  *
220  * akbReplyCopy and akbVarNeeded help control code generation in the
221  * server-side stub.  The preferred method of handling data in the
222  * server-side stub avoids copying into/out-of local variables.  In
223  * arguments get passed directly to the server proc from the request msg.
224  * Out arguments get stuffed directly into the reply msg by the server proc.
225  * For InOut arguments, the server proc gets the address of the data in
226  * the request msg, and the resulting data gets copied to the reply msg.
227  * Some arguments need a local variable in the server-side stub.  The
228  * code extracts the data from the request msg into the variable, and
229  * stuff the reply msg from the variable.
230  *
231  * akbReplyCopy implies akbReply.  It means the data should get copied
232  * from the request msg to the reply msg after the server proc is called.
233  * It is only used by akInOut.  akTid doesn't need it because the tid
234  * data in the reply msg is initialized in the server demux function.
235  *
236  * akbVarNeeded means the argument needs a local variable in the
237  * server-side stub.  It is added in rtAugmentArgKind and
238  * rtCheckVariable.  An argument shouldn't have all three of
239  * akbReturnSnd, akbVarNeeded and akbReplyCopy, because this indicates
240  * the reply msg should be stuffed both ways.
241  *
242  * akbDestroy helps control code generation in the server-side stub.
243  * It means this argument has a destructor function which should be called.
244  *
245  * akbOverwrite is used to identify the arguments that have to put an entry in
246  * the scatter list (the message-template used by the User stub to specify
247  * where the out-of-line data sent by server has to land).
248  *
249  * akbUserImplicit (akbServerImplicit) is used to mark the arguments that
250  * correspond to implicit data (data generated by the kernel and inserted in
251  * the trailer).
252  *
253  * Header file generation (header.c) uses:
254  *	akbUserArg
255  *
256  * User stub generation (user.c) uses:
257  *	akbUserArg, akbRequest, akbReply, akbSendSnd,
258  *	akbSendBody, akbSendKPD, akbReturnRcv, akbOverwrite, akbUserImplicit
259  *
260  * Server stub generation (server.c) uses:
261  *	akbServerArg, akbRequest, akbReply, akbSendRcv, akbReturnSnd,
262  *	akbReplyCopy, akbVarNeeded, akbSendBody, akbServerImplicit
263  *
264  *
265  * During code generation, the routine, argument, and type data structures
266  * are read-only.  The code generation functions' output is their only
267  * side-effect.
268  *
269  *
270  * Style note:
271  * Code can use logical operators (|, &, ~) on akb values.
272  * ak values should be manipulated with the ak functions.
273  */
274 
275 /* various useful combinations */
276 
277 #define akbNone		(0)
278 #define akbAll		(~akbNone)
279 #define akbAllBits	(~akeBITS)
280 
281 #define akbSendBits	(akbSend|akbSendBody|akbSendSnd|akbSendRcv)
282 #define akbReturnBits	(akbReturn|akbReturnBody|akbReturnSnd|akbReturnRcv)
283 #define akbSendReturnBits	(akbSendBits|akbReturnBits)
284 
285 #define akNone		akeNone
286 
287 #define akIn		akAddFeature(akeNormal,				\
288 	akbUserArg|akbServerArg|akbRequest|akbSendBits)
289 
290 #define akOut		akAddFeature(akeNormal,				\
291 	akbUserArg|akbServerArg|akbReply|akbReturnBits)
292 
293 #define akServerImpl	akAddFeature(akeImplicit, \
294 	akbServerArg|akbServerImplicit|akbSend|akbSendRcv)
295 #define akUserImpl	akAddFeature(akeImplicit, \
296 	akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv)
297 
298 #define akServerSecToken akAddFeature(akeSecToken, \
299 	akbServerArg|akbServerImplicit|akbSend|akbSendRcv)
300 #define akUserSecToken akAddFeature(akeSecToken, \
301 	akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv)
302 
303 #define akSecToken akAddFeature(akeSecToken, \
304         akbServerArg|akbServerImplicit|akbSend|akbSendRcv| \
305         akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv)
306 
307 #define akServerAuditToken akAddFeature(akeAuditToken, \
308   akbServerArg|akbServerImplicit|akbSend|akbSendRcv)
309 #define akUserAuditToken akAddFeature(akeAuditToken, \
310   akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv)
311 #define akAuditToken akAddFeature(akeAuditToken, \
312         akbServerArg|akbServerImplicit|akbSend|akbSendRcv| \
313         akbUserArg|akbUserImplicit|akbReturn|akbReturnRcv)
314 
315 #define akServerContextToken akAddFeature(akeContextToken, \
316   akbServerArg|akbServerImplicit|akbSend|akbSendRcv)
317 
318 #define akMsgSeqno	akAddFeature(akeMsgSeqno,			\
319 	akbServerArg|akbServerImplicit|akbSend|akbSendRcv)
320 
321 #define akInOut		akAddFeature(akeNormal,				\
322 	akbUserArg|akbServerArg|akbRequest|akbReply|			\
323 	akbSendBits|akbReturnBits|akbReplyCopy)
324 
325 #define akRequestPort	akAddFeature(akeRequestPort,			\
326 	akbUserArg|akbServerArg|akbSend|akbSendSnd|akbSendRcv)
327 
328 #define akWaitTime	akAddFeature(akeWaitTime, akbUserArg)
329 
330 #define akSendTime  akAddFeature(akeSendTime, akbUserArg)
331 
332 #define akMsgOption	akAddFeature(akeMsgOption, akbUserArg)
333 
334 #define akReplyPort	akAddFeature(akeReplyPort,			\
335 	akbUserArg|akbServerArg|akbSend|akbSendSnd|akbSendRcv)
336 
337 #define akUReplyPort	akAddFeature(akeReplyPort,			\
338 	akbUserArg|akbSend|akbSendSnd|akbSendRcv)
339 
340 #define akSReplyPort	akAddFeature(akeReplyPort,			\
341 	akbServerArg|akbSend|akbSendSnd|akbSendRcv)
342 
343 #define akRetCode	akAddFeature(akeRetCode, akbReply|akbReturnBody)
344 
345 #define akCount		akAddFeature(akeCount,				\
346 	akbUserArg|akbServerArg)
347 
348 #define akPoly		akePoly
349 
350 #define	akDealloc	akAddFeature(akeDealloc, akbUserArg)
351 
352 #define akCountInOut	akAddFeature(akeCountInOut, akbRequest|akbSendBits)
353 
354 #define	akCheck(ak, bits)	((ak) & (bits))
355 #define akCheckAll(ak, bits)	(akCheck(ak, bits) == (bits))
356 #define akAddFeature(ak, bits)	((ak)|(bits))
357 #define akRemFeature(ak, bits)	((ak)&~(bits))
358 #define akIdent(ak)		((ak) & akeBITS)
359 
360 #define argIsIn(arg)	(akIdent(arg->argKind) == akeNormal && \
361 					akCheck(arg->argKind, akbRequest))
362 #define argIsOut(arg)	(akIdent(arg->argKind) == akeNormal && \
363 					akCheck(arg->argKind, akbReply))
364 
365 /*
366  * The arguments to a routine/function are linked in left-to-right order.
367  * argName is used for error messages and pretty-printing,
368  * not code generation.  Code generation shouldn't make any assumptions
369  * about the order of arguments, esp. count and poly arguments.
370  * (Unfortunately, code generation for inline variable-sized arguments
371  * does make such assumptions.)
372  *
373  * argVarName is the name used in generated code for function arguments
374  * and local variable names.  argMsgField is the name used in generated
375  * code for the field in msgs where the argument's value lives.
376  * argTTName is the name used in generated code for msg-type fields and
377  * static variables used to initialize those fields.  argPadName is the
378  * name used in generated code for a padding field in msgs.
379  *
380  * argFlags can be used to override the deallocate bits
381  * in the argument's type.  rtProcessArgFlags sets argDeallocate
382  * from it and the type.  Code generation shouldn't use
383  * argFlags.
384  *
385  * argCount, argPoly, and argDealloc get to the implicit count, poly,
386  * and dealloc arguments associated with the argument; they should be
387  * used instead of argNext.  In these implicit arguments, argParent is
388  * a pointer to the "real" arg.
389  *
390  * In count arguments, argMultiplier is a scaling factor applied to
391  * the count arg's value to get msg-type-number.  It is equal to
392  *	argParent->argType->itElement->itNumber
393  *
394  */
395 
396 typedef struct argument
397 {
398     /* if argKind == akReturn, then argName is name of the function */
399     identifier_t argName;
400     struct argument *argNext;
401 
402     arg_kind_t argKind;
403     ipc_type_t *argType;
404 						/* Kernel Processed Data */
405     mach_msg_descriptor_type_t argKPD_Type; 	/* KPD type: port, ool, port+ool */
406     void  (* argKPD_Template)();		/* KPD discipline for static templates */
407     void  (* argKPD_Init)();			/* KPD discipline for initializing */
408     void  (* argKPD_Pack)();			/* KPD discipline for packing */
409     void  (* argKPD_Extract)();			/* KPD discipline for extracting */
410     void  (* argKPD_TypeCheck)();		/* KPD discipline for type checking */
411 
412     string_t argVarName;	/* local variable and argument names */
413     string_t argMsgField;	/* message field's name */
414     string_t argTTName;		/* name for msg_type fields, static vars */
415     string_t argPadName;	/* name for pad field in msg */
416     string_t argSuffix;		/* name extension for KPDs */
417 
418     ipc_flags_t argFlags;
419     dealloc_t argDeallocate;	/* overrides argType->itDeallocate */
420     boolean_t argCountInOut;
421 
422     struct routine *argRoutine;	/* routine we are part of */
423 
424     struct argument *argCount;	/* our count arg, if present */
425     struct argument *argSubCount;	/* our sub-count arg, if present (variable subordinate arrays) */
426     struct argument *argCInOut;	/* our CountInOut arg, if present */
427     struct argument *argPoly;	/* our poly arg, if present */
428     struct argument *argDealloc;/* our dealloc arg, if present */
429     struct argument *argSameCount;	/* the arg to take the count from, if present */
430     struct argument *argParent;	/* in a count or poly arg, the base arg */
431     u_int argMultiplier;	/* for Count argument: parent is a multiple
432 				   of a basic IPC type.  Argument must be
433 				   multiplied by Multiplier to get IPC
434 				   number-of-elements. */
435 
436     /* how variable/inline args precede this one, in request and reply */
437     u_int argRequestPos;
438     u_int argReplyPos;
439     /* whether argument is by reference, on user and server side */
440     boolean_t	argByReferenceUser;
441     boolean_t	argByReferenceServer;
442 
443     boolean_t	argTempOnStack;	/* A temporary for the short-circuiting
444 				 * code when -maxonstack is used.
445 				 */
446 } argument_t;
447 
448 /*
449  * The various routine kinds' peculiarities are abstracted by rtCheckRoutine
450  * into attributes like rtOneWay, etc.  These are what
451  * code generation should use.  It is Bad Form for code generation to
452  * test rtKind.
453  */
454 
455 typedef enum
456 {
457     rkRoutine,
458     rkSimpleRoutine
459 } routine_kind_t;
460 
461 typedef struct routine
462 {
463     identifier_t rtName;
464     routine_kind_t rtKind;
465     argument_t *rtArgs;
466     u_int rtNumber;		/* used for making msg ids */
467 
468     identifier_t rtUserName;	/* user-visible name (UserPrefix + Name) */
469     identifier_t rtServerName;	/* server-side name (ServerPrefix + Name) */
470 
471     identifier_t rtErrorName;	/* error-handler name */
472 
473     boolean_t rtOneWay;		/* SimpleRoutine */
474 
475     boolean_t rtSimpleRequest;
476     boolean_t rtSimpleReply;
477 
478     u_int rtNumRequestVar;	/* number of variable/inline args in request */
479     u_int rtNumReplyVar;	/* number of variable/inline args in reply */
480 
481     u_int rtMaxRequestPos;	/* maximum of argRequestPos */
482     u_int rtMaxReplyPos;	/* maximum of argReplyPos */
483 
484     u_int rtRequestKPDs;	/* number of Kernel Processed Data entries */
485     u_int rtReplyKPDs;		/* number of Kernel Processed Data entries */
486     u_int rtOverwrite;		/* number of Overwrite entries */
487     u_int rtOverwriteKPDs;	/* number of entries in the Overwrite template */
488 
489     boolean_t rtNoReplyArgs;	/* if so, no reply message arguments beyond
490 				   what the server dispatch routine inserts */
491 
492     boolean_t rtRequestFits;	/* Request fits within onstack limit */
493     boolean_t rtReplyFits;	/* Reply fits within onstack limit */
494     boolean_t rtRequestUsedLimit;/* User type limit used in deciding whether
495                                     request fits within onstack limit */
496     boolean_t rtReplyUsedLimit; /* User type limit used in deciding whether
497                                    reply fits within onstack limit */
498     u_int rtRequestSizeKnown;   /* Max size of known portion of request */
499     u_int rtReplySizeKnown;     /* Max size of known portion of request */
500 
501     u_int rtServerImpl;		/* Implicit data requested */
502     u_int rtUserImpl;		/* Implicit data requested */
503 
504     /* distinguished arguments */
505     argument_t *rtRetCArg;	/* the Routine has this argument tagged as RetCode */
506     argument_t *rtRequestPort;	/* always non-NULL, defaults to first arg */
507     argument_t *rtReplyPort;	/* always non-NULL, defaults to Mig-supplied */
508     argument_t *rtRetCode;	/* always non-NULL */
509     argument_t *rtNdrCode;	/* always non-NULL */
510     argument_t *rtWaitTime;	/* if non-NULL, will use MACH_RCV_TIMEOUT */
511     argument_t *rtMsgOption;	/* always non-NULL, defaults to NONE */
512 
513     /* more info's used only when UseEventLogger is turned on */
514     u_int	rtCountPortsIn;    /* how many in-line Ports are sent */
515     u_int	rtCountOolPortsIn; /* how many out_of-line Ports are sent */
516     u_int	rtCountOolIn; 	   /* how many bytes out_of-line are sent */
517 
518     u_int	rtCountPortsOut;    /* how many in-line Ports are rcv'd */
519     u_int	rtCountOolPortsOut; /* how many out_of-line Ports are rcv'd */
520     u_int	rtCountOolOut; 	    /* how many bytes out_of-line are rcv'd */
521 
522     u_int	rtTempBytesOnStack; /* A temporary for the short-circuiting
523 				     * code when -maxonstack is used.
524 				     */
525 
526 } routine_t;
527 
528 #define rtNULL		((routine_t *) 0)
529 #define argNULL		((argument_t *) 0)
530 #define argKPD_NULL	((mach_msg_descriptor_type_t) -1)
531 
532 #define rtMessOnStack(rt) ((rt)->rtRequestFits && (rt)->rtReplyFits)
533 
534 /*
535  * These are the ways MiG organizes stub parameters
536  */
537 #define IS_VARIABLE_SIZED_UNTYPED(x)  ((x)->itVarArray && \
538                                        (x)->itInLine  && \
539                                       !(x)->itPortType)
540 #define IS_KERN_PROC_DATA(x)	     (!(x)->itInLine || (x)->itPortType)
541 #define IS_OPTIONAL_NATIVE(x)        ((x)->itNative && \
542                                       (x)->itNativePointer && \
543                                       (x)->itBadValue != NULL)
544 
545 /*
546  * I consider the case of fixed/variable bounded arrays of ports or ool or oolport
547  */
548 #define IS_MULTIPLE_KPD(x) 	((x)->itKPD_Number > 1)
549 /*
550  * I consider the case of MiG presenting data as it is inLine, even
551  * if it is sent/rcvd as out-of-line
552  */
553 #define IS_MIG_INLINE_EMUL(x) 		((x)->itMigInLine)
554 
555 extern u_int rtNumber;
556 /* rt->rtNumber will be initialized */
557 extern routine_t *rtAlloc(void);
558 /* skip a number */
559 extern void rtSkip(void);
560 
561 extern argument_t *argAlloc(void);
562 
563 extern boolean_t
564 rtCheckMask(argument_t *args, u_int mask);
565 
566 extern boolean_t
567 rtCheckMaskFunction(argument_t *args, u_int mask,
568 					boolean_t (*func)(argument_t *arg));
569 
570 extern routine_t *
571 rtMakeRoutine( identifier_t name, argument_t *args);
572 extern routine_t *
573 rtMakeSimpleRoutine(identifier_t name, argument_t *args);
574 
575 extern void rtPrintRoutine(routine_t *rt);
576 extern void rtCheckRoutine(routine_t *rt);
577 
578 extern const char *rtRoutineKindToStr(routine_kind_t rk);
579 
580 extern int rtCountArgDescriptors(argument_t *args, int *argcount);
581 
582 extern void rtMinRequestSize(FILE *file, routine_t *rt, const char *str);
583 extern void rtMinReplySize(FILE *file, routine_t *rt, const char *str);
584 
585 #define RPCUserStruct(arg)    (arg->argType->itStruct && arg->argType->itInLine)
586 
587 #define RPCString(arg)        (arg->argType->itString && arg->argType->itInLine)
588 
589 #define RPCOutStruct(arg)     (arg->argType->itStruct &&\
590 			       argIsOut(arg) && (! arg->argType->itVarArray))
591 #define RPCOutWord(arg)       (RPCUserStruct(arg) &&\
592 			       (arg->argType->itSize <= 32) &&\
593 			       (arg->argType->itNumber == 1) && argIsOut(arg))
594 
595 #define RPCPort(arg)          (arg->argKPD_Type == MACH_MSG_PORT_DESCRIPTOR)
596 
597 #define RPCPortArray(arg)     (arg->argKPD_Type == MACH_MSG_OOL_PORTS_DESCRIPTOR)
598 
599 #define RPCVariableArray(arg) ((arg->argType->itVarArray) &&\
600 			       !RPCPort(arg) && !RPCPortArray(arg))
601 
602 #define RPCFixedArray(arg)    (((! arg->argType->itVarArray) &&\
603 			       !RPCPort(arg) && !RPCPortArray(arg) &&\
604 			       (arg->argType->itNumber > 1) &&\
605 				!RPCUserStruct(arg)) ||\
606 			       RPCString(arg) ||\
607 			       RPCOutWord(arg) ||\
608 			       RPCOutStruct(arg))
609 
610 
611 #endif	/* _ROUTINE_H */
612 
613 
614 
615