bootstrap_cmds/migcom.tproj/type.c

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