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