xref: /trueos/usr.bin/migcom/type.c (revision f6b8f3399966a8460b08bd3a069bb78c50b691e3)
1 /*-
2  * Copyright (c) 2014, Matthew Macy <kmacy@FreeBSD.ORG>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice unmodified, this list of conditions, and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 /*
28  * Copyright 1991-1998 by Open Software Foundation, Inc.
29  *              All Rights Reserved
30  *
31  * Permission to use, copy, modify, and distribute this software and
32  * its documentation for any purpose and without fee is hereby granted,
33  * provided that the above copyright notice appears in all copies and
34  * that both the copyright notice and this permission notice appear in
35  * supporting documentation.
36  *
37  * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
38  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
39  * FOR A PARTICULAR PURPOSE.
40  *
41  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
42  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
43  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
44  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
45  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
46  */
47 /*
48  * cmk1.1
49  */
50 /*
51  * Mach Operating System
52  * Copyright (c) 1991,1990 Carnegie Mellon University
53  * All Rights Reserved.
54  *
55  * Permission to use, copy, modify and distribute this software and its
56  * documentation is hereby granted, provided that both the copyright
57  * notice and this permission notice appear in all copies of the
58  * software, derivative works or modified versions, and any portions
59  * thereof, and that both notices appear in supporting documentation.
60  *
61  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
62  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
63  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
64  *
65  * Carnegie Mellon requests users of this software to return to
66  *
67  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
68  *  School of Computer Science
69  *  Carnegie Mellon University
70  *  Pittsburgh PA 15213-3890
71  *
72  * any improvements or extensions that they make and grant Carnegie Mellon
73  * the rights to redistribute these changes.
74  */
75 /*
76  * 92/03/03  16:25:23  jeffreyh
77  * 	Changes from TRUNK
78  * 	[92/02/26  12:32:39  jeffreyh]
79  *
80  * 92/01/14  16:46:47  rpd
81  * 	Changed Indefinite types from MustBeLong to ShouldBeLong.
82  * 	Added itCheckFlags, itCheckDeallocate, itCheckIsLong.
83  * 	Removed itServerCopy.
84  * 	[92/01/09            rpd]
85  *
86  * 91/08/28  11:17:27  jsb
87  * 	Removed itMsgKindType.
88  * 	[91/08/12            rpd]
89  *
90  * 91/07/31  18:11:12  dbg
91  * 	Indefinite-length inline arrays.
92  *
93  * 	Change itDeallocate to an enumerated type, to allow for
94  * 	user-specified deallocate flag.
95  *
96  * 	Add itCStringDecl.
97  * 	[91/07/17            dbg]
98  *
99  * 91/06/25  10:32:09  rpd
100  * 	Changed itCalculateNameInfo to change type names from mach_port_t
101  * 	to ipc_port_t for KernelServer and KernelUser interfaces.
102  * 	[91/05/28            rpd]
103  *
104  * 91/02/05  17:56:02  mrt
105  * 	Changed to new Mach copyright
106  * 	[91/02/01  17:56:12  mrt]
107  *
108  * 90/06/02  15:05:54  rpd
109  * 	Created for new IPC.
110  * 	[90/03/26  21:14:07  rpd]
111  *
112  * 07-Apr-89  Richard Draves (rpd) at Carnegie-Mellon University
113  *	Extensive revamping.  Added polymorphic arguments.
114  *	Allow multiple variable-sized inline arguments in messages.
115  *
116  * 17-Aug-88  Mary Thompson (mrt) at Carnegie-Mellon University
117  *	Removed translation of MSG_TYPE_INVALID as that type
118  *	is no longer defined by the kernel.
119  *
120  * 19-Feb-88  Mary Thompson (mrt) at Carnegie-Mellon University
121  *	Changed itPrintTrans and itPrintDecl to reflect new translation syntax.
122  *	Changed itCheckDecl to set itServerType to itType if is is strNULL.
123  *
124  *  4-Feb-88  Mary Thompson (mrt) at Carnegie-Mellon University
125  *	Added a check to itCheckDecl to make sure that in-line
126  *	variable length arrays have a non-zero maximum length.
127  *
128  * 22-Dec-87  David Golub (dbg) at Carnegie-Mellon University
129  *	Removed warning message for translation.
130  *
131  * 16-Nov-87  David Golub (dbg) at Carnegie-Mellon University
132  *	Changed itVarArrayDecl to take a 'max' parameter for maximum
133  *	number of elements, and to make type not be 'struct'.
134  *	Added itDestructor.
135  *
136  * 18-Aug-87  Mary Thompson (mrt) at Carnegie-Mellon University
137  *	Added initialization of itPortType
138  *
139  * 14-Aug-87  Mary Thompson (mrt) at Carnegie-Mellon University
140  *	Added initialization for itTidType
141  *
142  * 15-Jun-87  David Black (dlb) at Carnegie-Mellon University
143  *	Fixed prototype for itAlloc; was missing itServerType field.
144  *
145  * 10-Jun-87  Mary Thompson (mrt) at Carnegie-Mellon University
146  *	Removed extern from procedure definitions to make hi-c happy
147  *	Changed the c type names of itDummyType from caddr_t to
148  *	char * and of itCountType from u_int to unsigned int to
149  *	eliminate the need to import sys/types.h into the mig generated
150  *	code.
151  *
152  * 28-May-87  Richard Draves (rpd) at Carnegie-Mellon University
153  *	Created.
154  */
155 
156 #include <stdio.h>
157 
158 #include "type.h"
159 #include <sys/types.h>
160 #include <mach/message.h>
161 #include <mach/std_types.h>
162 #include <mach/ndr.h>
163 #include "mig_machine.h"
164 #include "routine.h"
165 #include "error.h"
166 #include "alloc.h"
167 #include "global.h"
168 #include "strdefs.h"
169 
170 #define PortSize  (sizeof (mach_port_t) * NBBY)
171 
172 ipc_type_t *itRetCodeType;      /* used for return codes */
173 ipc_type_t *itNdrCodeType;      /* used for NDR format labels */
174 ipc_type_t *itDummyType;        /* used for camelot dummy args */
175 ipc_type_t *itTidType;          /* used for camelot tids */
176 ipc_type_t *itRequestPortType;  /* used for default Request port arg */
177 ipc_type_t *itZeroReplyPortType;/* used for dummy Reply port arg */
178 ipc_type_t *itRealReplyPortType;/* used for default Reply port arg */
179 ipc_type_t *itWaitTimeType;     /* used for dummy WaitTime args */
180 ipc_type_t *itMsgOptionType;    /* used for dummy MsgOption args */
181 
182 static ipc_type_t *list = itNULL;
183 
184 static string_t machine_integer_name;
185 static u_int machine_integer_size;
186 static u_int machine_integer_bits;
187 
188 /*
189  *  Searches for a named type.  We use a simple
190  *  self-organizing linked list.
191  */
192 ipc_type_t *
itLookUp(identifier_t name)193 itLookUp(identifier_t name)
194 {
195 	register ipc_type_t *it, **last;
196 
197 	for (it = *(last = &list); it != itNULL; it = *(last = &it->itNext))
198 		if (streql(name, it->itName))
199 		{
200 			/* move this type to the front of the list */
201 			*last = it->itNext;
202 			it->itNext = list;
203 			list = it;
204 
205 			return it;
206 		}
207 
208 	return itNULL;
209 }
210 
211 /*
212  *  Enters a new name-type association into
213  *  our self-organizing linked list.
214  */
215 void
itInsert(identifier_t name,ipc_type_t * it)216 itInsert(identifier_t name, ipc_type_t *it)
217 {
218 	it->itName = name;
219 	it->itNext = list;
220 	list = it;
221 }
222 
223 static ipc_type_t *
itAlloc(void)224 itAlloc(void)
225 {
226 	static ipc_type_t prototype =
227 		{
228 			strNULL,  /* identifier_t itName */
229 			0,        /* ipc_type_t *itNext */
230 			0,        /* u_int itTypeSize */
231 			0,        /* u_int itPadSize */
232 			0,        /* u_int itMinTypeSize */
233 			0,        /* u_int itInName */
234 			0,        /* u_int itOutName */
235 			0,        /* u_int itSize */
236 			1,        /* u_int itNumber */
237 			0,        /* u_int itKPD_Number */
238 			TRUE,     /* boolean_t itInLine */
239 			FALSE,    /* boolean_t itMigInLine */
240 			FALSE,    /* boolean_t itPortType */
241 			strNULL,  /* string_t itInNameStr */
242 			strNULL,  /* string_t itOutNameStr */
243 			TRUE,     /* boolean_t itStruct */
244 			FALSE,    /* boolean_t itString */
245 			FALSE,    /* boolean_t itVarArray */
246 			FALSE,    /* boolean_t itNoOptArray */
247 			FALSE,    /* boolean_t itNative */
248 			FALSE,    /* boolean_t itNativePointer */
249 			itNULL,   /* ipc_type_t *itElement */
250 			strNULL,  /* identifier_t itUserType */
251 			strNULL,  /* identifier_t itServerType */
252 			strNULL,  /* identifier_t itTransType */
253 			strNULL,  /* identifier_t itUserKPDType */
254 			strNULL,  /* identifier_t itServerKPDType */
255 			strNULL,  /* identifier_t itInTrans */
256 			strNULL,  /* identifier_t itOutTrans */
257 			strNULL  /* identifier_t itDestructor */
258 		};
259 	register ipc_type_t *new;
260 
261 	new = (ipc_type_t *) malloc(sizeof *new);
262 	if (new == itNULL)
263 		fatal("itAlloc(): %s", strerror(errno));
264 	*new = prototype;
265 	return new;
266 }
267 
268 /*
269  * Convert an IPC type-name into a string.
270  */
271 static const char *
itNameToString(u_int name)272 itNameToString(u_int name)
273 {
274 	char buffer[100];
275 
276 	(void) sprintf(buffer, "%u", name);
277 	return strmake(buffer);
278 }
279 
280 /*
281  * Calculate itTypeSize, itPadSize, itMinTypeSize
282  * Every type needs this info; it is recalculated
283  * when itInLine, itNumber, or itSize changes.
284  */
285 static void
itCalculateSizeInfo(register ipc_type_t * it)286 itCalculateSizeInfo(register ipc_type_t *it)
287 {
288 	if (!IS_KERN_PROC_DATA(it))
289 	{
290 		u_int bytes = (it->itNumber * it->itSize + 7) / 8;
291 		u_int padding = machine_padding(bytes);
292 
293 		it->itTypeSize = bytes;
294 		it->itPadSize = padding;
295 		if (IS_VARIABLE_SIZED_UNTYPED(it)) {
296 			/*
297 			 * for these arrays, the argCount is not a akbRequest|akbReply,
298 			 * therefore we need to account here for the space of the count
299 			 * (itMinTypeSize is used only in rtFindSize)
300 			 */
301 			it->itMinTypeSize = sizeof (mach_msg_type_number_t);
302 			/*
303 			 * NDR encoded VarString carry the extra offset 4-bytes fields
304 			 * for MIG, it should be always 0;
305 			 */
306 			if (it->itString)
307 				it->itMinTypeSize += sizeof (mach_msg_type_number_t);
308 		} else
309 			it->itMinTypeSize = bytes + padding;
310     } else {
311 		/*
312 		 * 1) ports 2) OOL 3) ports OOL
313 		 * all have the same size = sizeof(mach_msg_descriptor_t)
314 		 */
315 		u_int bytes;
316 		if (IS_MULTIPLE_KPD(it))
317 			bytes = it->itKPD_Number * sizeof(mach_msg_descriptor_t);
318 		else
319 			bytes = sizeof(mach_msg_descriptor_t);
320 
321 		it->itTypeSize = bytes;
322 		it->itPadSize = 0;
323 		it->itMinTypeSize = bytes;
324 	}
325 
326 	/* Unfortunately, these warning messages can't give a type name;
327 	   we haven't seen a name yet (it might stay anonymous.) */
328 
329 	if ((it->itTypeSize == 0) && !it->itVarArray && !it->itNative)
330 		warn("sizeof(%s) == 0");
331 }
332 
333 /*
334  * Fill in default values for some fields used in code generation:
335  *  itInNameStr, itOutNameStr, itUserType, itServerType, itTransType
336  * Every argument's type should have these values filled in.
337  */
338 static void
itCalculateNameInfo(register ipc_type_t * it)339 itCalculateNameInfo(register ipc_type_t *it)
340 {
341 	if (it->itInNameStr == strNULL)
342 		it->itInNameStr = strmake(itNameToString(it->itInName));
343 	if (it->itOutNameStr == strNULL)
344 		it->itOutNameStr = strmake(itNameToString(it->itOutName));
345 
346 	if (it->itUserType == strNULL)
347 		it->itUserType = it->itName;
348 	if (it->itServerType == strNULL)
349 		it->itServerType = it->itName;
350 #if 0
351 	/*
352 	 *  KernelServer and KernelUser interfaces get special treatment here.
353 	 *  On the kernel side of the interface, ports are really internal
354 	 *  port pointers (ipc_port_t), not port names (mach_port_t).
355 	 *  At this point, we don't know if the argument is in or out,
356 	 *  so we don't know if we should look at itInName or itOutName.
357 	 *  Looking at both should be OK.
358 	 *
359 	 *  This is definitely a hack, but I think it is cleaner than
360 	 *  mucking with type declarations throughout the kernel .def files,
361 	 *  hand-conditionalizing on KERNEL_SERVER and KERNEL_USER.
362 	 */
363 
364 	if (IsKernelServer &&
365 		streql(it->itServerType, "mach_port_t") &&
366 		(((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) &&
367 		  (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) ||
368 		 MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
369 		 MACH_MSG_TYPE_PORT_ANY(it->itOutName)))
370 		it->itServerType = "ipc_port_t";
371 
372 	if (IsKernelUser &&
373 		streql(it->itUserType, "mach_port_t") &&
374 		(((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) &&
375 		  (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) ||
376 		 MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
377 		 MACH_MSG_TYPE_PORT_ANY(it->itOutName)))
378 		it->itUserType = "ipc_port_t";
379 #endif /* 0 */
380 
381 	if (it->itTransType == strNULL)
382 		it->itTransType = it->itServerType;
383 }
384 
385 /******************************************************
386  *  Checks for non-implemented types, conflicting type
387  *  flags and whether the long or short form of msg type
388  *  descriptor is appropriate. Called after each type statement
389  *  is parsed.
390  ******************************************************/
391 static void
itCheckDecl(identifier_t name,register ipc_type_t * it)392 itCheckDecl(identifier_t name, register ipc_type_t *it)
393 {
394 	it->itName = name;
395 
396 	itCalculateNameInfo(it);
397 
398 	/* do a bit of error checking, mostly necessary because of
399 	   limitations in Mig */
400 
401 	if (it->itVarArray) {
402 		if ((it->itInTrans != strNULL) || (it->itOutTrans != strNULL))
403 			error("%s: can't translate variable-sized arrays", name);
404 
405 		if (it->itDestructor != strNULL)
406 			error("%s: can't destroy variable-sized array", name);
407 	}
408 }
409 
410 /*
411  *  Pretty-prints translation/destruction/type information.
412  */
413 static void
itPrintTrans(register ipc_type_t * it)414 itPrintTrans(register ipc_type_t *it)
415 {
416 	if (!streql(it->itName, it->itUserType))
417 		printf("\tCUserType:\t%s\n", it->itUserType);
418 
419 	if (!streql(it->itName, it->itServerType))
420 		printf("\tCServerType:\t%s\n", it->itServerType);
421 
422 	if (it->itInTrans != strNULL)
423 		printf("\tInTran:\t\t%s %s(%s)\n",
424 			   it->itTransType, it->itInTrans, it->itServerType);
425 
426 	if (it->itOutTrans != strNULL)
427 		printf("\tOutTran:\t%s %s(%s)\n",
428 			   it->itServerType, it->itOutTrans, it->itTransType);
429 
430 	if (it->itDestructor != strNULL)
431 		printf("\tDestructor:\t%s(%s)\n", it->itDestructor, it->itTransType);
432 }
433 
434 /*
435  *  Pretty-prints type declarations.
436  */
437 static void
itPrintDecl(identifier_t name,ipc_type_t * it)438 itPrintDecl(identifier_t name, ipc_type_t *it)
439 {
440 	printf("Type %s = ", name);
441 	if (!it->itInLine)
442 		printf("^ ");
443 	if (it->itVarArray)
444 		if (it->itNumber == 0 || it->itMigInLine)
445 			printf("array [] of ");
446 		else
447 			printf("array [*:%d] of ", it->itNumber);
448     else if (it->itStruct && ((it->itNumber != 1) ||
449                               (it->itInName == MACH_MSG_TYPE_STRING_C)))
450 		printf("struct [%d] of ", it->itNumber);
451     else if (it->itNumber != 1)
452 		printf("array [%d] of ", it->itNumber);
453 
454 	if (streql(it->itInNameStr, it->itOutNameStr))
455 		printf("(%s,", it->itInNameStr);
456 	else
457 		printf("(%s|%s", it->itInNameStr, it->itOutNameStr);
458 
459 	printf(" %d)\n", it->itSize);
460 
461 	itPrintTrans(it);
462 
463 	printf("\n");
464 }
465 
466 /*
467  *  Handles named type-specs, which can occur in type
468  *  declarations or in argument lists.  For example,
469  * type foo = type-spec; // itInsert will get called later
470  * routine foo(arg : bar = type-spec); // itInsert won't get called
471  */
472 void
itTypeDecl(identifier_t name,ipc_type_t * it)473 itTypeDecl(identifier_t name, ipc_type_t *it)
474 {
475 	itCheckDecl(name, it);
476 
477 	if (BeVerbose)
478 		itPrintDecl(name, it);
479 }
480 
481 /*
482  *  Handles declarations like
483  * type new = name;
484  * type new = inname|outname;
485  */
486 ipc_type_t *
itShortDecl(u_int inname,string_t instr,u_int outname,string_t outstr,u_int defsize)487 itShortDecl(u_int inname,  string_t instr, u_int outname, string_t outstr, u_int defsize)
488 {
489 	register ipc_type_t *it;
490 
491 	if (defsize == 0)
492 		error("must use full IPC type decl");
493 
494 	it = itAlloc();
495 	it->itInName = inname;
496 	it->itInNameStr = instr;
497 	it->itOutName = outname;
498 	it->itOutNameStr = outstr;
499 	it->itSize = defsize;
500 	if (inname == MACH_MSG_TYPE_STRING_C)
501 	{
502 		it->itStruct = FALSE;
503 		it->itString = TRUE;
504 	}
505 	/*
506 	 * I check only inname, because outname
507 	 * has to be a port as well (polymorphic types
508 	 * are now restricted to port rights)
509 	 */
510 	if (MACH_MSG_TYPE_PORT_ANY(inname) ||
511 		inname == MACH_MSG_TYPE_POLYMORPHIC) {
512 		it->itPortType = TRUE;
513 		it->itKPD_Number = 1;
514 	}
515 
516 	itCalculateSizeInfo(it);
517 	return it;
518 }
519 
520 static ipc_type_t *
itCopyType(ipc_type_t * old)521 itCopyType(ipc_type_t *old)
522 {
523 	register ipc_type_t *new = itAlloc();
524 
525 	*new = *old;
526 	new->itName = strNULL;
527 	new->itNext = itNULL;
528 	new->itElement = old;
529 
530 	/* size info still valid */
531 	return new;
532 }
533 
534 /*
535  * A call to itCopyType is almost always followed with itResetType.
536  * The exception is itPrevDecl.  Also called before adding any new
537  * translation/destruction/type info (see parser.y).
538  *
539  * type new = old; // new doesn't get old's info
540  * type new = array[*:10] of old;
541  * // new doesn't get old's info, but new->itElement does
542  * type new = array[*:10] of struct[3] of old;
543  * // new and new->itElement don't get old's info
544  */
545 
546 ipc_type_t *
itResetType(ipc_type_t * old)547 itResetType(ipc_type_t *old)
548 {
549 	/* reset all special translation/destruction/type info */
550 
551 	old->itInTrans = strNULL;
552 	old->itOutTrans = strNULL;
553 	old->itDestructor = strNULL;
554 	old->itUserType = strNULL;
555 	old->itServerType = strNULL;
556 	old->itTransType = strNULL;
557 	return old;
558 }
559 
560 /*
561  *  Handles the declaration
562  * type new = old;
563  */
564 ipc_type_t *
itPrevDecl(identifier_t name)565 itPrevDecl(identifier_t name)
566 {
567 	register ipc_type_t *old;
568 
569 	old = itLookUp(name);
570 	if (old == itNULL) {
571 		error("type '%s' not defined", name);
572 		return itAlloc();
573 	}
574 	else
575 		return itCopyType(old);
576 }
577 
578 /*
579  *  Handles the declarations
580  * type new = array[] of old; // number is oo
581  * type new = array[*] of old; // number is oo
582  * type new = array[*:number] of old;
583  */
584 ipc_type_t *
itVarArrayDecl(u_int number,register ipc_type_t * old)585 itVarArrayDecl(u_int number, register ipc_type_t *old)
586 {
587 	register ipc_type_t *it = itResetType(itCopyType(old));
588 
589 	if (!it->itInLine) {
590 		/* already an initialized KPD */
591 		if (it->itKPD_Number != 1 || !number)
592 			error("IPC type decl is too complicated for Kernel Processed Data");
593 		it->itKPD_Number *= number;
594 		it->itNumber = 1;
595 		it->itInLine = FALSE;
596 		it->itStruct = FALSE;
597     } else if (it->itVarArray)
598 		error("IPC type decl is too complicated");
599 	else if (number) {
600 		it->itNumber *= number;
601 		/*
602 		 * Bounded [Scalar, Port] VarArray: in-line!
603 		 */
604 		it->itInLine = TRUE;
605 		it->itStruct = FALSE;
606 		if (it->itPortType)
607 			it->itKPD_Number *= number;
608     } else {
609 		it->itNumber = 0;
610 		/*
611 		 * UnBounded [Scalar, Port] VarArray: always in-line
612 		 * interface and out-of-line mechanism!
613 		 */
614 		it->itMigInLine = TRUE;
615 		it->itInLine = FALSE;
616 		it->itStruct = TRUE;
617 		it->itKPD_Number = 1;
618 	}
619 
620 	it->itVarArray = TRUE;
621 	it->itString = FALSE;
622 
623 	itCalculateSizeInfo(it);
624 	return it;
625 }
626 
627 /*
628  *  Handles the declaration
629  * type new = array[number] of old;
630  */
631 ipc_type_t *
itArrayDecl(u_int number,ipc_type_t * old)632 itArrayDecl(u_int number, ipc_type_t *old)
633 {
634 	register ipc_type_t *it = itResetType(itCopyType(old));
635 
636 	if (!it->itInLine) {
637 		/* already an initialized KPD */
638 		if (it->itKPD_Number != 1)
639 			error("IPC type decl is too complicated for Kernel Processed Data");
640 		it->itKPD_Number *= number;
641 		it->itNumber = 1;
642 		it->itStruct = FALSE;
643 		it->itString = FALSE;
644 		it->itVarArray = FALSE;
645     } else if (it->itVarArray)
646 		error("IPC type decl is too complicated");
647 	else {
648 		it->itNumber *= number;
649 		it->itStruct = FALSE;
650 		it->itString = FALSE;
651 		if (it->itPortType)
652 			it->itKPD_Number *= number;
653 	}
654 
655 	itCalculateSizeInfo(it);
656 	return it;
657 }
658 
659 /*
660  *  Handles the declaration
661  * type new = ^ old;
662  */
663 ipc_type_t *
itPtrDecl(ipc_type_t * it)664 itPtrDecl(ipc_type_t *it)
665 {
666 	if (!it->itInLine && !it->itMigInLine)
667 		error("IPC type decl is already defined to be Out-Of-Line");
668 	it->itInLine = FALSE;
669 	it->itStruct = TRUE;
670 	it->itString = FALSE;
671 	it->itMigInLine = FALSE;
672 	it->itKPD_Number = 1;
673 
674 	itCalculateSizeInfo(it);
675 	return it;
676 }
677 
678 /*
679  *  Handles the declaration
680  * type new = struct[number] of old;
681  */
682 ipc_type_t *
itStructDecl(u_int number,ipc_type_t * old)683 itStructDecl(u_int number, ipc_type_t *old)
684 {
685 	register ipc_type_t *it = itResetType(itCopyType(old));
686 
687 	if (!it->itInLine || it->itVarArray)
688 		error("IPC type decl is too complicated");
689 	it->itNumber *= number;
690 	it->itStruct = TRUE;
691 	it->itString = FALSE;
692 
693 	itCalculateSizeInfo(it);
694 	return it;
695 }
696 
697 /*
698  * Treat 'c_string[n]' as
699  * 'array[n] of (MSG_TYPE_STRING_C, 8)'
700  */
701 ipc_type_t *
itCStringDecl(u_int count,boolean_t varying)702 itCStringDecl(u_int count, boolean_t varying)
703 {
704 	register ipc_type_t *it;
705 	register ipc_type_t *itElement;
706 
707     itElement = itShortDecl(MACH_MSG_TYPE_STRING_C,
708 							"MACH_MSG_TYPE_STRING_C",
709 							MACH_MSG_TYPE_STRING_C,
710 							"MACH_MSG_TYPE_STRING_C",
711 							8);
712 	itCheckDecl("char", itElement);
713 
714 	it = itResetType(itCopyType(itElement));
715 	it->itNumber = count;
716 	it->itVarArray = varying;
717 	it->itStruct = FALSE;
718 	it->itString = TRUE;
719 
720 	itCalculateSizeInfo(it);
721 	return it;
722 }
723 
724 extern ipc_type_t *
itMakeSubCountType(u_int count,boolean_t varying,string_t name __unused)725 itMakeSubCountType(u_int count, boolean_t varying, string_t name __unused)
726 {
727 	register ipc_type_t *it;
728 	register ipc_type_t *itElement;
729 
730     itElement = itShortDecl(machine_integer_size,
731 							machine_integer_name,
732 							machine_integer_size,
733 							machine_integer_name,
734 							machine_integer_bits);
735 	itCheckDecl("mach_msg_type_number_t", itElement);
736 
737 	it = itResetType(itCopyType(itElement));
738 	it->itNumber = count;
739 	/*
740 	 * I cannot consider it as a Fixed array, otherwise MiG will try
741 	 * to follow the path for efficient copy of arrays
742 	 */
743 	it->itVarArray = FALSE;
744 	it->itStruct = FALSE;
745 	it->itString = FALSE;
746 	it->itInLine = TRUE;
747 	it->itName = "mach_msg_type_number_t *";
748 	if (varying)
749 		it->itVarArray = TRUE;
750 	else
751 		/* to skip the optimized copy of fixed array: in fact we need to
752 		 * reference each element and we also miss a user type for it */
753 		it->itNoOptArray = TRUE;
754 
755 	itCalculateSizeInfo(it);
756 	itCalculateNameInfo(it);
757 	return it;
758 }
759 
760 extern ipc_type_t *
itMakeCountType(void)761 itMakeCountType(void)
762 {
763 	ipc_type_t *it = itAlloc();
764 
765 	it->itName = "mach_msg_type_number_t";
766 	it->itInName = machine_integer_size;
767 	it->itInNameStr = machine_integer_name;
768 	it->itOutName = machine_integer_size;
769 	it->itOutNameStr = machine_integer_name;
770 	it->itSize = machine_integer_bits;
771 
772 	itCalculateSizeInfo(it);
773 	itCalculateNameInfo(it);
774 	return it;
775 }
776 
777 extern ipc_type_t *
itMakePolyType(void)778 itMakePolyType(void)
779 {
780 	ipc_type_t *it = itAlloc();
781 
782 	it->itName = "mach_msg_type_name_t";
783 	it->itInName = machine_integer_size;
784 	it->itInNameStr = machine_integer_name;
785 	it->itOutName = machine_integer_size;
786 	it->itOutNameStr = machine_integer_name;
787 	it->itSize = machine_integer_bits;
788 
789 	itCalculateSizeInfo(it);
790 	itCalculateNameInfo(it);
791 	return it;
792 }
793 
794 extern ipc_type_t *
itMakeDeallocType(void)795 itMakeDeallocType(void)
796 {
797 	ipc_type_t *it = itAlloc();
798 
799 	it->itName = "boolean_t";
800 	it->itInName = MACH_MSG_TYPE_BOOLEAN;
801 	it->itInNameStr = "MACH_MSG_TYPE_BOOLEAN";
802 	it->itOutName = MACH_MSG_TYPE_BOOLEAN;
803 	it->itOutNameStr = "MACH_MSG_TYPE_BOOLEAN";
804 	it->itSize = machine_integer_bits;
805 
806 	itCalculateSizeInfo(it);
807 	itCalculateNameInfo(it);
808 	return it;
809 }
810 
811 extern ipc_type_t *
812 itNativeType(id, ptr, badval)
813     identifier_t id;
814     boolean_t ptr;
815     identifier_t badval;
816 {
817 	ipc_type_t *it = itAlloc();
818 
819 	it->itInName = MACH_MSG_TYPE_BYTE;
820 	it->itInNameStr = "MACH_MSG_TYPE_BYTE";
821 	it->itOutName = MACH_MSG_TYPE_BYTE;
822 	it->itOutNameStr = "MACH_MSG_TYPE_BYTE";
823 	it->itInLine = TRUE;
824 	it->itNative = TRUE;
825 	it->itNativePointer = ptr;
826 	it->itServerType = id;
827 	it->itUserType = id;
828 	it->itTransType = id;
829 	it->itBadValue = badval;
830 
831 	itCalculateSizeInfo(it);
832 	itCalculateNameInfo(it);
833 	return it;
834 }
835 
836 /*
837  *  Initializes the pre-defined types.
838  */
839 void
init_type(void)840 init_type(void)
841 {
842 	u_int size;
843 
844 	size = NBBY * sizeof (natural_t);
845 	if (size == 32) {
846 		machine_integer_name = "MACH_MSG_TYPE_INTEGER_32";
847 		machine_integer_size = MACH_MSG_TYPE_INTEGER_32;
848 	}
849 	else if (size == 64) {
850 		machine_integer_name = "MACH_MSG_TYPE_INTEGER_64";
851 		machine_integer_size = MACH_MSG_TYPE_INTEGER_64;
852 	}
853 	else
854 		error("init_type unknown size %d", size);
855 
856 	machine_integer_bits = size;
857 
858 	itRetCodeType = itAlloc();
859 	itRetCodeType->itName = "kern_return_t";
860 	itRetCodeType->itInName = machine_integer_size;
861 	itRetCodeType->itInNameStr = machine_integer_name;
862 	itRetCodeType->itOutName = machine_integer_size;
863 	itRetCodeType->itOutNameStr = machine_integer_name;
864 	itRetCodeType->itSize = machine_integer_bits;
865 	itCalculateSizeInfo(itRetCodeType);
866 	itCalculateNameInfo(itRetCodeType);
867 
868 	itNdrCodeType = itAlloc();
869 	itNdrCodeType->itName = "NDR_record_t";
870 	itNdrCodeType->itInName = 0;
871 	itNdrCodeType->itInNameStr = "NDR_record_t";
872 	itNdrCodeType->itOutName = 0;
873 	itNdrCodeType->itOutNameStr = "NDR_record_t";
874 	itNdrCodeType->itSize = sizeof(NDR_record_t) * 8;
875 	itCalculateSizeInfo(itNdrCodeType);
876 	itCalculateNameInfo(itNdrCodeType);
877 
878 	itDummyType = itAlloc();
879 	itDummyType->itName = "char *";
880 	itDummyType->itInName = MACH_MSG_TYPE_UNSTRUCTURED;
881 	itDummyType->itInNameStr = "MACH_MSG_TYPE_UNSTRUCTURED";
882 	itDummyType->itOutName = MACH_MSG_TYPE_UNSTRUCTURED;
883 	itDummyType->itOutNameStr = "MACH_MSG_TYPE_UNSTRUCTURED";
884 	itDummyType->itSize = PortSize;
885 	itCalculateSizeInfo(itDummyType);
886 	itCalculateNameInfo(itDummyType);
887 
888 	itTidType = itAlloc();
889 	itTidType->itName = "tid_t";
890 	itTidType->itInName = machine_integer_size;
891 	itTidType->itInNameStr = machine_integer_name;
892 	itTidType->itOutName = machine_integer_size;
893 	itTidType->itOutNameStr = machine_integer_name;
894 	itTidType->itSize = machine_integer_bits;
895 	itTidType->itNumber = 6;
896 	itCalculateSizeInfo(itTidType);
897 	itCalculateNameInfo(itTidType);
898 
899 	itRequestPortType = itAlloc();
900 	itRequestPortType->itName = "mach_port_t";
901 	itRequestPortType->itInName = MACH_MSG_TYPE_COPY_SEND;
902 	itRequestPortType->itInNameStr = "MACH_MSG_TYPE_COPY_SEND";
903 	itRequestPortType->itOutName = MACH_MSG_TYPE_PORT_SEND;
904 	itRequestPortType->itOutNameStr = "MACH_MSG_TYPE_PORT_SEND";
905 	itRequestPortType->itSize = PortSize;
906 	itCalculateSizeInfo(itRequestPortType);
907 	itCalculateNameInfo(itRequestPortType);
908 
909 	itZeroReplyPortType = itAlloc();
910 	itZeroReplyPortType->itName = "mach_port_t";
911 	itZeroReplyPortType->itInName = 0;
912 	itZeroReplyPortType->itInNameStr = "0";
913 	itZeroReplyPortType->itOutName = 0;
914 	itZeroReplyPortType->itOutNameStr = "0";
915 	itZeroReplyPortType->itSize = PortSize;
916 	itCalculateSizeInfo(itZeroReplyPortType);
917 	itCalculateNameInfo(itZeroReplyPortType);
918 
919 	itRealReplyPortType = itAlloc();
920 	itRealReplyPortType->itName = "mach_port_t";
921 	itRealReplyPortType->itInName = MACH_MSG_TYPE_MAKE_SEND_ONCE;
922 	itRealReplyPortType->itInNameStr = "MACH_MSG_TYPE_MAKE_SEND_ONCE";
923 	itRealReplyPortType->itOutName = MACH_MSG_TYPE_PORT_SEND_ONCE;
924 	itRealReplyPortType->itOutNameStr = "MACH_MSG_TYPE_PORT_SEND_ONCE";
925 	itRealReplyPortType->itSize = PortSize;
926 	itCalculateSizeInfo(itRealReplyPortType);
927 	itCalculateNameInfo(itRealReplyPortType);
928 
929 	itWaitTimeType = itMakeCountType();
930 	itMsgOptionType = itMakeCountType();
931 }
932 
933 /******************************************************
934  *  Make sure return values of functions are assignable.
935  ******************************************************/
936 void
itCheckReturnType(identifier_t name,ipc_type_t * it)937 itCheckReturnType(identifier_t name, ipc_type_t *it)
938 {
939 	if (!it->itStruct)
940 		error("type of %s is too complicated", name);
941 	if ((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) ||
942 		(it->itOutName == MACH_MSG_TYPE_POLYMORPHIC))
943 		error("type of %s can't be polymorphic", name);
944 }
945 
946 
947 /******************************************************
948  *  Called by routine.c to check that request ports are
949  *  simple and correct ports with send rights.
950  ******************************************************/
951 void
itCheckRequestPortType(identifier_t name,ipc_type_t * it)952 itCheckRequestPortType(identifier_t name, ipc_type_t *it)
953 {
954 /*    error("Port size = %d %d name = %s\n", PortSize, it->itSize, it->itName);
955 	  error("server = %s user = %x\n",it->itServerType, it->itUserType);
956 */
957 	if (((it->itOutName != MACH_MSG_TYPE_PORT_SEND) &&
958 		 (it->itOutName != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
959 		 (it->itOutName != MACH_MSG_TYPE_POLYMORPHIC)) ||
960 		(it->itNumber != 1) ||
961 		(it->itSize != PortSize) ||
962 		!it->itInLine ||
963 		!it->itStruct ||
964 		it->itVarArray)
965 		error("argument %s isn't a proper request port", name);
966 }
967 
968 
969 /******************************************************
970  *  Called by routine.c to check that reply ports are
971  *  simple and correct ports with send rights.
972  ******************************************************/
973 void
itCheckReplyPortType(identifier_t name,ipc_type_t * it)974 itCheckReplyPortType(identifier_t name, ipc_type_t *it)
975 {
976 	if (((it->itOutName != MACH_MSG_TYPE_PORT_SEND) &&
977 		 (it->itOutName != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
978 		 (it->itOutName != MACH_MSG_TYPE_POLYMORPHIC) &&
979 		 (it->itOutName != 0)) ||
980 		(it->itNumber != 1) ||
981 		(it->itSize != PortSize) ||
982 		!it->itInLine ||
983 		!it->itStruct ||
984 		it->itVarArray)
985 		error("argument %s isn't a proper reply port", name);
986 }
987 
988 
989 /******************************************************
990  *  Used by routine.c to check that WaitTime is a
991  *  simple bit machine_integer_bits integer.
992  ******************************************************/
993 void
itCheckIntType(identifier_t name,ipc_type_t * it)994 itCheckIntType(identifier_t name, ipc_type_t *it)
995 {
996 	if ((it->itInName != machine_integer_size) ||
997 		(it->itOutName != machine_integer_size) ||
998 		(it->itNumber != 1) ||
999 		(it->itSize != machine_integer_bits) ||
1000 		!it->itInLine ||
1001 		!it->itStruct ||
1002 		it->itVarArray)
1003 		error("argument %s isn't a proper integer", name);
1004 }
1005 
1006 void
itCheckTokenType(identifier_t name,ipc_type_t * it)1007 itCheckTokenType(identifier_t name, ipc_type_t *it)
1008 {
1009 	if (it->itMigInLine || it->itNoOptArray || it->itString ||
1010 		it->itTypeSize != 8 || !it->itInLine || !it->itStruct ||
1011 		it->itVarArray || it->itPortType)
1012 		error("argument %s isn't a proper Token", name);
1013 }
1014