1/* 2 * Copyright (c) 1999-2002, 2008 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 <mach/message.h> 50#include <stdarg.h> 51#include <stdlib.h> 52#include "routine.h" 53#include "write.h" 54#include "global.h" 55#include "utils.h" 56#include "error.h" 57 58extern char *MessFreeRoutine; 59 60void 61WriteIdentificationString(FILE *file) 62{ 63 extern char * GenerationDate; 64 65 fprintf(file, "/*\n"); 66 fprintf(file, " * IDENTIFICATION:\n"); 67 fprintf(file, " * stub generated %s", GenerationDate); 68 fprintf(file, " * with a MiG generated by " MIG_VERSION "\n"); 69 fprintf(file, " * OPTIONS: \n"); 70 if (IsKernelUser) 71 fprintf(file, " *\tKernelUser\n"); 72 if (IsKernelServer) 73 fprintf(file, " *\tKernelServer\n"); 74 if (!UseMsgRPC) 75 fprintf(file, " *\t-R (no RPC calls)\n"); 76 fprintf(file, " */\n"); 77} 78 79void 80WriteMigExternal(FILE *file) 81{ 82 fprintf(file, "#ifdef\tmig_external\n"); 83 fprintf(file, "mig_external\n"); 84 fprintf(file, "#else\n"); 85 fprintf(file, "extern\n"); 86 fprintf(file, "#endif\t/* mig_external */\n"); 87} 88 89void 90WriteMigInternal(FILE *file) 91{ 92 fprintf(file, "#ifdef\tmig_internal\n"); 93 fprintf(file, "mig_internal\n"); 94 fprintf(file, "#else\n"); 95 fprintf(file, "static\n"); 96 fprintf(file, "#endif\t/* mig_internal */\n"); 97} 98 99void 100WriteImport(FILE *file, string_t filename) 101{ 102 fprintf(file, "#include %s\n", filename); 103} 104 105void 106WriteImplImports(FILE *file, statement_t *stats, boolean_t isuser) 107{ 108 register statement_t *stat; 109 110 for (stat = stats; stat != stNULL; stat = stat->stNext) 111 switch (stat->stKind) { 112 113 case skImport: 114 case skIImport: 115 WriteImport(file, stat->stFileName); 116 break; 117 118 case skSImport: 119 if (!isuser) 120 WriteImport(file, stat->stFileName); 121 break; 122 123 case skUImport: 124 if (isuser) 125 WriteImport(file, stat->stFileName); 126 break; 127 128 case skRoutine: 129 case skDImport: 130 break; 131 132 default: 133 fatal("WriteImplImport(): bad statement_kind_t (%d)", (int) stat->stKind); 134 } 135} 136 137void 138WriteRCSDecl(FILE *file, identifier_t name, string_t rcs) 139{ 140 fprintf(file, "#ifndef\tlint\n"); 141 fprintf(file, "#if\tUseExternRCSId\n"); 142 fprintf(file, "%s char %s_rcsid[] = %s;\n", (BeAnsiC) ? "const" : "", name, rcs); 143 fprintf(file, "#else\t/* UseExternRCSId */\n"); 144 fprintf(file, "static %s char rcsid[] = %s;\n", (BeAnsiC) ? "const" : "", rcs); 145 fprintf(file, "#endif\t/* UseExternRCSId */\n"); 146 fprintf(file, "#endif\t/* lint */\n"); 147 fprintf(file, "\n"); 148} 149 150static void 151WriteOneApplDefault(FILE *file, char *word1, char *word2, char *word3) 152{ 153 char buf[50]; 154 155 sprintf(buf, "__%s%s%s", word1, word2, word3); 156 fprintf(file, "#ifndef\t%s\n", buf); 157 fprintf(file, "#define\t%s(_NUM_, _NAME_)\n", buf); 158 fprintf(file, "#endif\t/* %s */\n", buf); 159 fprintf(file, "\n"); 160} 161 162void 163WriteApplDefaults(FILE *file, char *dir) 164{ 165 WriteOneApplDefault(file, "Declare", dir, "Rpc"); 166 WriteOneApplDefault(file, "Before", dir, "Rpc"); 167 WriteOneApplDefault(file, "After", dir, "Rpc"); 168 WriteOneApplDefault(file, "Declare", dir, "Simple"); 169 WriteOneApplDefault(file, "Before", dir, "Simple"); 170 WriteOneApplDefault(file, "After", dir, "Simple"); 171} 172 173void 174WriteApplMacro(FILE *file, char *dir, char *when, routine_t *rt) 175{ 176 char *what = (rt->rtOneWay) ? "Simple" : "Rpc"; 177 178 fprintf(file, "\t__%s%s%s(%d, \"%s\")\n", when, dir, what, SubsystemBase + rt->rtNumber, rt->rtName); 179} 180 181 182void 183WriteBogusDefines(FILE *file) 184{ 185 fprintf(file, "#ifndef\tmig_internal\n"); 186 fprintf(file, "#define\tmig_internal\tstatic __inline__\n"); 187 fprintf(file, "#endif\t/* mig_internal */\n"); 188 fprintf(file, "\n"); 189 190 fprintf(file, "#ifndef\tmig_external\n"); 191 fprintf(file, "#define mig_external\n"); 192 fprintf(file, "#endif\t/* mig_external */\n"); 193 fprintf(file, "\n"); 194 195 fprintf(file, "#if\t!defined(__MigTypeCheck) && defined(TypeCheck)\n"); 196 fprintf(file, "#define\t__MigTypeCheck\t\tTypeCheck\t/* Legacy setting */\n"); 197 fprintf(file, "#endif\t/* !defined(__MigTypeCheck) */\n"); 198 fprintf(file, "\n"); 199 200 fprintf(file, "#if\t!defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)\n"); 201 fprintf(file, "#define\t__MigKernelSpecificCode\t_MIG_KERNEL_SPECIFIC_CODE_\t/* Legacy setting */\n"); 202 fprintf(file, "#endif\t/* !defined(__MigKernelSpecificCode) */\n"); 203 fprintf(file, "\n"); 204 205 fprintf(file, "#ifndef\tLimitCheck\n"); 206 fprintf(file, "#define\tLimitCheck 0\n"); 207 fprintf(file, "#endif\t/* LimitCheck */\n"); 208 fprintf(file, "\n"); 209 210 fprintf(file, "#ifndef\tmin\n"); 211 fprintf(file, "#define\tmin(a,b) ( ((a) < (b))? (a): (b) )\n"); 212 fprintf(file, "#endif\t/* min */\n"); 213 fprintf(file, "\n"); 214 215 fprintf(file, "#if !defined(_WALIGN_)\n"); 216 fprintf(file, "#define _WALIGN_(x) (((x) + %d) & ~%d)\n", (int)(itWordAlign - 1), (int)(itWordAlign - 1)); 217 fprintf(file, "#endif /* !defined(_WALIGN_) */\n"); 218 fprintf(file, "\n"); 219 220 fprintf(file, "#if !defined(_WALIGNSZ_)\n"); 221 fprintf(file, "#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))\n"); 222 fprintf(file, "#endif /* !defined(_WALIGNSZ_) */\n"); 223 fprintf(file, "\n"); 224 225 fprintf(file, "#ifndef\tUseStaticTemplates\n"); 226 if (BeAnsiC) { 227 fprintf(file, "#define\tUseStaticTemplates\t0\n"); 228 } 229 else { 230 fprintf(file, "#if\t%s\n", NewCDecl); 231 fprintf(file, "#define\tUseStaticTemplates\t0\n"); 232 fprintf(file, "#endif\t/* %s */\n", NewCDecl); 233 } 234 fprintf(file, "#endif\t/* UseStaticTemplates */\n"); 235 fprintf(file, "\n"); 236 237} 238 239void 240WriteList(FILE *file, argument_t *args, void (*func)(), u_int mask, char *between, char *after) 241{ 242 register argument_t *arg; 243 register boolean_t sawone = FALSE; 244 245 for (arg = args; arg != argNULL; arg = arg->argNext) 246 if (akCheckAll(arg->argKind, mask)) { 247 if (sawone) 248 fprintf(file, "%s", between); 249 sawone = TRUE; 250 251 (*func)(file, arg); 252 } 253 254 if (sawone) 255 fprintf(file, "%s", after); 256} 257 258 259static boolean_t 260WriteReverseListPrim(FILE *file, register argument_t *arg, void (*func)(), u_int mask, char *between) 261{ 262 boolean_t sawone = FALSE; 263 264 if (arg != argNULL) { 265 sawone = WriteReverseListPrim(file, arg->argNext, func, mask, between); 266 267 if (akCheckAll(arg->argKind, mask)) { 268 if (sawone) 269 fprintf(file, "%s", between); 270 sawone = TRUE; 271 272 (*func)(file, arg); 273 } 274 } 275 276 return sawone; 277} 278 279void 280WriteReverseList(FILE *file, argument_t *args, void (*func)(), u_int mask, char *between, char *after) 281{ 282 boolean_t sawone; 283 284 sawone = WriteReverseListPrim(file, args, func, mask, between); 285 286 if (sawone) 287 fprintf(file, "%s", after); 288} 289 290void 291WriteNameDecl(FILE *file, argument_t *arg) 292{ 293 fprintf(file, "%s", arg->argVarName); 294} 295 296void 297WriteUserVarDecl(FILE *file, argument_t *arg) 298{ 299 boolean_t pointer = (arg->argByReferenceUser ||arg->argType->itNativePointer); 300 char *ref = (pointer) ? "*" : ""; 301 char *cnst = ((arg->argFlags & flConst) && 302 (IS_VARIABLE_SIZED_UNTYPED(arg->argType) || 303 arg->argType->itNoOptArray || arg->argType->itString)) ? "const " : ""; 304 305 fprintf(file, "\t%s%s %s%s", cnst, arg->argType->itUserType, ref, arg->argVarName); 306} 307 308void 309WriteServerVarDecl(FILE *file, argument_t *arg) 310{ 311 char *ref = (arg->argByReferenceServer || 312 arg->argType->itNativePointer) ? "*" : ""; 313 char *cnst = ((arg->argFlags & flConst) && 314 (IS_VARIABLE_SIZED_UNTYPED(arg->argType) || 315 arg->argType->itNoOptArray || arg->argType->itString)) ? "const " : ""; 316 317 fprintf(file, "\t%s%s %s%s", cnst, arg->argType->itTransType, ref, arg->argVarName); 318} 319 320char * 321ReturnTypeStr(routine_t *rt) 322{ 323 return rt->rtRetCode->argType->itUserType; 324} 325 326char * 327FetchUserType(ipc_type_t *it) 328{ 329 return it->itUserType; 330} 331 332char * 333FetchServerType(ipc_type_t *it) 334{ 335 return it->itServerType; 336} 337 338char * 339FetchKPDType(ipc_type_t *it) 340{ 341 return it->itKPDType; 342} 343 344void 345WriteTrailerDecl(FILE *file, boolean_t trailer) 346{ 347 if (trailer) 348 fprintf(file, "\t\tmach_msg_max_trailer_t trailer;\n"); 349 else 350 fprintf(file, "\t\tmach_msg_trailer_t trailer;\n"); 351} 352 353void 354WriteFieldDeclPrim(FILE *file, argument_t *arg, char *(*tfunc)()) 355{ 356 register ipc_type_t *it = arg->argType; 357 358 if (IS_VARIABLE_SIZED_UNTYPED(it) || it->itNoOptArray) { 359 register argument_t *count = arg->argCount; 360 register ipc_type_t *btype = it->itElement; 361 362 /* 363 * Build our own declaration for a varying array: 364 * use the element type and maximum size specified. 365 * Note arg->argCount->argMultiplier == btype->itNumber. 366 */ 367 /* 368 * NDR encoded VarStrings requires the offset field. 369 * Since it is not used, it wasn't worthwhile to create an extra 370 * parameter 371 */ 372 if (it->itString) 373 fprintf(file, "\t\t%s %sOffset; /* MiG doesn't use it */\n", (*tfunc)(count->argType), arg->argName); 374 375 if (!(arg->argFlags & flSameCount) && !it->itNoOptArray) 376 /* in these cases we would have a count, which we don't want */ 377 fprintf(file, "\t\t%s %s;\n", (*tfunc)(count->argType), count->argMsgField); 378 fprintf(file, "\t\t%s %s[%d];", (*tfunc)(btype), arg->argMsgField, it->itNumber/btype->itNumber); 379 } 380 else if (IS_MULTIPLE_KPD(it)) 381 fprintf(file, "\t\t%s %s[%d];", (*tfunc)(it), arg->argMsgField, it->itKPD_Number); 382 else if (IS_OPTIONAL_NATIVE(it)) { 383 fprintf(file, "\t\tboolean_t __Present__%s;\n", arg->argMsgField); 384 fprintf(file, "\t\tunion {\n"); 385 fprintf(file, "\t\t %s __Real__%s;\n", (*tfunc)(it), arg->argMsgField); 386 fprintf(file, "\t\t char __Phony__%s[_WALIGNSZ_(%s)];\n", arg->argMsgField, (*tfunc)(it)); 387 fprintf(file, "\t\t} %s;", arg->argMsgField); 388 } 389 else { 390 /* either simple KPD or simple in-line */ 391 fprintf(file, "\t\t%s %s;", (*tfunc)(it), arg->argMsgField); 392 } 393 394 /* Kernel Processed Data has always PadSize = 0 */ 395 if (it->itPadSize != 0) 396 fprintf(file, "\n\t\tchar %s[%d];", arg->argPadName, it->itPadSize); 397} 398 399void 400WriteKPDFieldDecl(FILE *file, argument_t *arg) 401{ 402 if (akCheck(arg->argKind, akbSendKPD) || 403 akCheck(arg->argKind, akbReturnKPD)) 404 WriteFieldDeclPrim(file, arg, FetchKPDType); 405 else 406 WriteFieldDeclPrim(file, arg, FetchServerType); 407} 408 409void 410WriteStructDecl( 411 FILE *file, 412 argument_t *args, 413 void (*func)(), 414 u_int mask, 415 char *name, 416 boolean_t simple, 417 boolean_t trailer, 418 boolean_t trailer_t, 419 boolean_t template_only) 420{ 421 fprintf(file, "\n#ifdef __MigPackStructs\n#pragma pack(%lu)\n#endif\n",sizeof(natural_t)); 422 fprintf(file, "\ttypedef struct {\n"); 423 fprintf(file, "\t\tmach_msg_header_t Head;\n"); 424 if (simple == FALSE) { 425 fprintf(file, "\t\t/* start of the kernel processed data */\n"); 426 fprintf(file, "\t\tmach_msg_body_t msgh_body;\n"); 427 if (mask == akbRequest) 428 WriteList(file, args, func, mask | akbSendKPD, "\n", "\n"); 429 else 430 WriteList(file, args, func, mask | akbReturnKPD, "\n", "\n"); 431 fprintf(file, "\t\t/* end of the kernel processed data */\n"); 432 } 433 if (!template_only) { 434 if (mask == akbRequest) 435 WriteList(file, args, func, mask | akbSendBody, "\n", "\n"); 436 437 else 438 WriteList(file, args, func, mask | akbReturnBody, "\n", "\n"); 439 if (trailer) 440 WriteTrailerDecl(file, trailer_t); 441 } 442 fprintf(file, "\t} %s;\n", name); 443 fprintf(file, "#ifdef __MigPackStructs\n#pragma pack()\n#endif\n"); 444} 445 446void 447WriteTemplateDeclIn(FILE *file, register argument_t *arg) 448{ 449 (*arg->argKPD_Template)(file, arg, TRUE); 450} 451 452void 453WriteTemplateDeclOut(FILE *file, register argument_t *arg) 454{ 455 (*arg->argKPD_Template)(file, arg, FALSE); 456} 457 458void 459WriteTemplateKPD_port(FILE *file, argument_t *arg, boolean_t in) 460{ 461 register ipc_type_t *it = arg->argType; 462 463 fprintf(file, "#if\tUseStaticTemplates\n"); 464 fprintf(file, "\tconst static %s %s = {\n", it->itKPDType, arg->argTTName); 465 466 fprintf(file, "\t\t/* name = */\t\tMACH_PORT_NULL,\n"); 467 fprintf(file, "\t\t/* pad1 = */\t\t0,\n"); 468 fprintf(file, "\t\t/* pad2 = */\t\t0,\n"); 469 fprintf(file, "\t\t/* disp = */\t\t%s,\n", in ? it->itInNameStr: it->itOutNameStr); 470 fprintf(file, "\t\t/* type = */\t\tMACH_MSG_PORT_DESCRIPTOR,\n"); 471 472 fprintf(file, "\t};\n"); 473 fprintf(file, "#endif\t/* UseStaticTemplates */\n"); 474} 475 476void 477WriteTemplateKPD_ool(FILE *file, argument_t *arg, boolean_t in) 478{ 479 register ipc_type_t *it = arg->argType; 480 481 fprintf(file, "#if\tUseStaticTemplates\n"); 482 fprintf(file, "\tconst static %s %s = {\n", it->itKPDType, arg->argTTName); 483 484 if (IS_MULTIPLE_KPD(it)) 485 it = it->itElement; 486 487 fprintf(file, "\t\t/* addr = */\t\t(void *)0,\n"); 488 if (it->itVarArray) 489 fprintf(file, "\t\t/* size = */\t\t0,\n"); 490 else 491 fprintf(file, "\t\t/* size = */\t\t%d,\n", (it->itNumber * it->itSize + 7)/8); 492 fprintf(file, "\t\t/* deal = */\t\t%s,\n", (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE"); 493 /* the d_MAYBE case will be fixed runtime */ 494 fprintf(file, "\t\t/* copy = */\t\t%s,\n", (arg->argFlags & flPhysicalCopy) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY"); 495 /* the PHYSICAL COPY flag has not been established yet */ 496 fprintf(file, "\t\t/* pad2 = */\t\t0,\n"); 497 fprintf(file, "\t\t/* type = */\t\tMACH_MSG_OOL_DESCRIPTOR,\n"); 498 499 fprintf(file, "\t};\n"); 500 fprintf(file, "#endif\t/* UseStaticTemplates */\n"); 501} 502 503void 504WriteTemplateKPD_oolport(FILE *file, argument_t *arg, boolean_t in) 505{ 506 register ipc_type_t *it = arg->argType; 507 508 fprintf(file, "#if\tUseStaticTemplates\n"); 509 fprintf(file, "\tconst static %s %s = {\n", it->itKPDType, arg->argTTName); 510 511 if (IS_MULTIPLE_KPD(it)) 512 it = it->itElement; 513 514 fprintf(file, "\t\t/* addr = */\t\t(void *)0,\n"); 515 if (!it->itVarArray) 516 fprintf(file, "\t\t/* coun = */\t\t%d,\n", it->itNumber); 517 else 518 fprintf(file, "\t\t/* coun = */\t\t0,\n"); 519 fprintf(file, "\t\t/* deal = */\t\t%s,\n", (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE"); 520 fprintf(file, "\t\t/* copy is meaningful only in overwrite mode */\n"); 521 fprintf(file, "\t\t/* copy = */\t\tMACH_MSG_PHYSICAL_COPY,\n"); 522 fprintf(file, "\t\t/* disp = */\t\t%s,\n", in ? it->itInNameStr: it->itOutNameStr); 523 fprintf(file, "\t\t/* type = */\t\tMACH_MSG_OOL_PORTS_DESCRIPTOR,\n"); 524 525 fprintf(file, "\t};\n"); 526 fprintf(file, "#endif\t/* UseStaticTemplates */\n"); 527} 528 529void 530WriteReplyTypes(FILE *file, statement_t *stats) 531{ 532 register statement_t *stat; 533 534 fprintf(file, "/* typedefs for all replies */\n\n"); 535 fprintf(file, "#ifndef __Reply__%s_subsystem__defined\n", SubsystemName); 536 fprintf(file, "#define __Reply__%s_subsystem__defined\n", SubsystemName); 537 for (stat = stats; stat != stNULL; stat = stat->stNext) { 538 if (stat->stKind == skRoutine) { 539 register routine_t *rt; 540 char str[MAX_STR_LEN]; 541 542 rt = stat->stRoutine; 543 sprintf(str, "__Reply__%s_t", rt->rtName); 544 WriteStructDecl(file, rt->rtArgs, WriteKPDFieldDecl, akbReply, str, rt->rtSimpleReply, FALSE, FALSE, FALSE); 545 } 546 } 547 fprintf(file, "#endif /* !__Reply__%s_subsystem__defined */\n", SubsystemName); 548 fprintf(file, "\n"); 549} 550 551void 552WriteRequestTypes(FILE *file, statement_t *stats) 553{ 554 register statement_t *stat; 555 556 fprintf(file, "/* typedefs for all requests */\n\n"); 557 fprintf(file, "#ifndef __Request__%s_subsystem__defined\n", SubsystemName); 558 fprintf(file, "#define __Request__%s_subsystem__defined\n", SubsystemName); 559 for (stat = stats; stat != stNULL; stat = stat->stNext) { 560 if (stat->stKind == skRoutine) { 561 register routine_t *rt; 562 char str[MAX_STR_LEN]; 563 564 rt = stat->stRoutine; 565 sprintf(str, "__Request__%s_t", rt->rtName); 566 WriteStructDecl(file, rt->rtArgs, WriteKPDFieldDecl, akbRequest, str, rt->rtSimpleRequest, FALSE, FALSE, FALSE); 567 } 568 } 569 fprintf(file, "#endif /* !__Request__%s_subsystem__defined */\n", SubsystemName); 570 fprintf(file, "\n"); 571} 572 573void 574WriteNDRConvertArgDecl(FILE *file, argument_t *arg, char *convert, char *dir) 575{ 576 argument_t *count = arg->argCount; 577 argument_t *parent = arg->argParent; 578 char *carg = (count) ? ", c" : ""; 579 routine_t *rt = arg->argRoutine; 580 ipc_type_t *ptype = arg->argType; 581 ipc_type_t *btype; 582 int multi, array; 583 char domain[MAX_STR_LEN]; 584 585 fprintf(file, "#ifndef __NDR_convert__%s__%s__%s_t__%s__defined\n#", convert, dir, rt->rtName, arg->argMsgField); 586 587 for (btype = ptype, multi = (!parent) ? arg->argMultiplier : 1, array = 0; 588 btype; 589 ptype = btype, array += ptype->itVarArray, btype = btype->itElement) { 590 char *bttype; 591 592 if (btype->itNumber < ptype->itNumber && !ptype->itVarArray && !parent) { 593 multi *= ptype->itNumber / btype->itNumber; 594 if (!btype->itString) 595 continue; 596 } 597 else if (array && ptype->itVarArray) 598 continue; 599 if (btype != ptype) 600 fprintf(file, "#el"); 601 602 bttype = (multi > 1 && btype->itString) ? "string" : FetchServerType(btype); 603 sprintf(domain, "__%s", SubsystemName); 604 do { 605 fprintf(file, "if\tdefined(__NDR_convert__%s%s__%s__defined)\n", convert, domain, bttype); 606 fprintf(file, "#define\t__NDR_convert__%s__%s__%s_t__%s__defined\n", convert, dir, rt->rtName, arg->argMsgField); 607 fprintf(file, "#define\t__NDR_convert__%s__%s__%s_t__%s(a, f%s) \\\n\t", convert, dir, rt->rtName, arg->argMsgField, carg); 608 if (multi > 1) { 609 if (array) { 610 if (btype->itString) 611 fprintf(file, "__NDR_convert__2DARRAY((%s *)(a), f, %d, c, ", bttype, multi); 612 else 613 fprintf(file, "__NDR_convert__ARRAY((%s *)(a), f, %d * (c), ", bttype, multi); 614 } 615 else if (!btype->itString) 616 fprintf(file, "__NDR_convert__ARRAY((%s *)(a), f, %d, ", bttype, multi); 617 } 618 else if (array) 619 fprintf(file, "__NDR_convert__ARRAY((%s *)(a), f, c, ", bttype); 620 fprintf(file, "__NDR_convert__%s%s__%s", convert, domain, bttype); 621 if (multi > 1) { 622 if (!array && btype->itString) 623 fprintf(file, "(a, f, %d", multi); 624 } 625 else if (!array) 626 fprintf(file, "((%s *)(a), f%s", bttype, carg); 627 fprintf(file, ")\n"); 628 } while (strcmp(domain, "") && (domain[0] = '\0', fprintf(file, "#el"))); 629 } 630 fprintf(file, "#endif /* defined(__NDR_convert__*__defined) */\n"); 631 fprintf(file, "#endif /* __NDR_convert__%s__%s__%s_t__%s__defined */\n\n", convert, dir, rt->rtName, arg->argMsgField); 632} 633 634/* 635 * Like vfprintf, but omits a leading comment in the format string 636 * and skips the items that would be printed by it. Only %s, %d, 637 * and %f are recognized. 638 */ 639void 640SkipVFPrintf(FILE *file, register char *fmt, va_list pvar) 641{ 642 if (*fmt == 0) 643 return; /* degenerate case */ 644 645 if (fmt[0] == '/' && fmt[1] == '*') { 646 /* Format string begins with C comment. Scan format 647 string until end-comment delimiter, skipping the 648 items in pvar that the enclosed format items would 649 print. */ 650 651 register int c; 652 653 fmt += 2; 654 for (;;) { 655 c = *fmt++; 656 if (c == 0) 657 return; /* nothing to format */ 658 if (c == '*') { 659 if (*fmt == '/') { 660 break; 661 } 662 } 663 else if (c == '%') { 664 /* Field to skip */ 665 c = *fmt++; 666 switch (c) { 667 668 case 's': 669 (void) va_arg(pvar, char *); 670 break; 671 672 case 'd': 673 (void) va_arg(pvar, int); 674 break; 675 676 case 'f': 677 (void) va_arg(pvar, double); 678 break; 679 680 case '\0': 681 return; /* error - fmt ends with '%' */ 682 683 default: 684 break; 685 } 686 } 687 } 688 /* End of comment. To be pretty, skip 689 the space that follows. */ 690 fmt++; 691 if (*fmt == ' ') 692 fmt++; 693 } 694 695 /* Now format the string. */ 696 (void) vfprintf(file, fmt, pvar); 697} 698 699static void 700vWriteCopyType(FILE *file, ipc_type_t *it, char *left, char *right, va_list pvar) 701{ 702 va_list pvar2; 703 va_copy(pvar2, pvar); 704 705 if (it->itStruct) { 706 707 fprintf(file, "\t"); 708 (void) SkipVFPrintf(file, left, pvar); 709 fprintf(file, " = "); 710 (void) SkipVFPrintf(file, right, pvar2); 711 fprintf(file, ";\n"); 712 } 713 else if (it->itString) { 714 fprintf(file, "\t(void) mig_strncpy("); 715 (void) SkipVFPrintf(file, left, pvar); 716 fprintf(file, ", "); 717 (void) SkipVFPrintf(file, right, pvar2); 718 fprintf(file, ", %d);\n", it->itTypeSize); 719 } 720 else { 721 fprintf(file, "\t{ typedef struct { char data[%d]; } *sp;\n", it->itTypeSize); 722 fprintf(file, "\t * (sp) "); 723 (void) SkipVFPrintf(file, left, pvar); 724 fprintf(file, " = * (sp) "); 725 (void) SkipVFPrintf(file, right, pvar2); 726 fprintf(file, ";\n\t}\n"); 727 } 728 729 va_end(pvar2); 730} 731 732 733/*ARGSUSED*/ 734/*VARARGS4*/ 735void 736WriteCopyType(FILE *file, ipc_type_t *it, char *left, char *right, ...) 737{ 738 va_list pvar; 739 va_start(pvar, right); 740 741 vWriteCopyType(file, it, left, right, pvar); 742 743 va_end(pvar); 744} 745 746 747/*ARGSUSED*/ 748/*VARARGS4*/ 749void 750WriteCopyArg(FILE *file, argument_t *arg, char *left, char *right, ...) 751{ 752 va_list pvar; 753 va_start(pvar, right); 754 755 { 756 ipc_type_t *it = arg->argType; 757 if (it->itVarArray && !it->itString) { 758 fprintf(file, "\t (void)memcpy("); 759 (void) SkipVFPrintf(file, left, pvar); 760 va_end(pvar); 761 fprintf(file, ", "); 762 va_start(pvar, right); 763 (void) SkipVFPrintf(file, right, pvar); 764 fprintf(file, ", %s);\n", arg->argCount->argVarName); 765 } 766 else 767 vWriteCopyType(file, it, left, right, pvar); 768 } 769 770 va_end(pvar); 771} 772 773 774/* 775 * Global KPD disciplines 776 */ 777void 778KPD_error(FILE *file, argument_t *arg) 779{ 780 printf("MiG internal error: argument is %s\n", arg->argVarName); 781 exit(1); 782} 783 784void 785KPD_noop(FILE *file, argument_t *arg) 786{ 787 /* Nothing to see here, people. Move it along... */ 788} 789 790static void 791WriteStringDynArgs(argument_t *args, u_int mask, string_t InPOutP, string_t *str_oolports, string_t *str_ool) 792{ 793 argument_t *arg; 794 char loc[100], sub[20]; 795 string_t tmp_str1 = ""; 796 string_t tmp_str2 = ""; 797 int cnt, multiplier = 1; 798 boolean_t test, complex = FALSE; 799 800 for (arg = args; arg != argNULL; arg = arg->argNext) { 801 ipc_type_t *it = arg->argType; 802 803 if (IS_MULTIPLE_KPD(it)) { 804 test = it->itVarArray || it->itElement->itVarArray; 805 if (test) { 806 multiplier = it->itKPD_Number; 807 it = it->itElement; 808 complex = TRUE; 809 } 810 } 811 else 812 test = it->itVarArray; 813 814 cnt = multiplier; 815 while (cnt) { 816 if (complex) 817 sprintf(sub, "[%d]", multiplier - cnt); 818 if (akCheck(arg->argKind, mask) && 819 it->itPortType && !it->itInLine && test) { 820 sprintf(loc, " + %s->%s%s.count", InPOutP, arg->argMsgField, complex ? sub : ""); 821 tmp_str1 = strconcat(tmp_str1, loc); 822 } 823 if (akCheck(arg->argKind, mask) && 824 !it->itInLine && !it->itPortType && test) { 825 sprintf(loc, " + %s->%s%s.size", InPOutP, arg->argMsgField, complex ? sub : ""); 826 tmp_str2 = strconcat(tmp_str2, loc); 827 } 828 cnt--; 829 } 830 } 831 *str_oolports = tmp_str1; 832 *str_ool = tmp_str2; 833} 834 835/* 836 * Utilities for Logging Events that happen at the stub level 837 */ 838void 839WriteLogMsg(FILE *file, routine_t *rt, int where, int what) 840{ 841 string_t ptr_str; 842 string_t StringOolPorts = strNULL; 843 string_t StringOOL = strNULL; 844 u_int ports, oolports, ool; 845 string_t event; 846 847 fprintf(file, "\n#if MIG_DEBUG\n"); 848 if (where == LOG_USER) 849 fprintf(file, "\tLOG_TRACE(MACH_MSG_LOG_USER,\n"); 850 else 851 fprintf(file, "\tLOG_TRACE(MACH_MSG_LOG_SERVER,\n"); 852 if (where == LOG_USER && what == LOG_REQUEST) { 853 ptr_str = "InP"; 854 event = "MACH_MSG_REQUEST_BEING_SENT"; 855 } 856 else if (where == LOG_USER && what == LOG_REPLY) { 857 ptr_str = "Out0P"; 858 event = "MACH_MSG_REPLY_BEING_RCVD"; 859 } 860 else if (where == LOG_SERVER && what == LOG_REQUEST) { 861 ptr_str = "In0P"; 862 event = "MACH_MSG_REQUEST_BEING_RCVD"; 863 } 864 else { 865 ptr_str = "OutP"; 866 event = "MACH_MSG_REPLY_BEING_SENT"; 867 } 868 WriteStringDynArgs(rt->rtArgs, (what == LOG_REQUEST) ? akbSendKPD : akbReturnKPD, ptr_str, &StringOolPorts, &StringOOL); 869 fprintf(file, "\t\t%s,\n", event); 870 fprintf(file, "\t\t%s->Head.msgh_id,\n", ptr_str); 871 if (where == LOG_USER && what == LOG_REQUEST) { 872 if (rt->rtNumRequestVar) 873 fprintf(file, "\t\tmsgh_size,\n"); 874 else 875 fprintf(file, "\t\t(mach_msg_size_t)sizeof(Request),\n"); 876 } 877 else 878 fprintf(file, "\t\t%s->Head.msgh_size,\n", ptr_str); 879 if ((what == LOG_REQUEST && rt->rtSimpleRequest == FALSE) || 880 (what == LOG_REPLY && rt->rtSimpleReply == FALSE)) 881 fprintf(file, "\t\t%s->msgh_body.msgh_descriptor_count,\n", ptr_str); 882 else 883 fprintf(file, "\t\t0, /* Kernel Proc. Data entries */\n"); 884 if (what == LOG_REQUEST) { 885 fprintf(file, "\t\t0, /* RetCode */\n"); 886 ports = rt->rtCountPortsIn; 887 oolports = rt->rtCountOolPortsIn; 888 ool = rt->rtCountOolIn; 889 } 890 else { 891 if (akCheck(rt->rtRetCode->argKind, akbReply)) 892 fprintf(file, "\t\t%s->RetCode,\n", ptr_str); 893 else 894 fprintf(file, "\t\t0, /* RetCode */\n"); 895 ports = rt->rtCountPortsOut; 896 oolports = rt->rtCountOolPortsOut; 897 ool = rt->rtCountOolOut; 898 } 899 fprintf(file, "\t\t/* Ports */\n"); 900 fprintf(file, "\t\t%d,\n", ports); 901 fprintf(file, "\t\t/* Out-of-Line Ports */\n"); 902 fprintf(file, "\t\t%d", oolports); 903 if (StringOolPorts != strNULL) 904 fprintf(file, "%s,\n", StringOolPorts); 905 else 906 fprintf(file, ",\n"); 907 fprintf(file, "\t\t/* Out-of-Line Bytes */\n"); 908 fprintf(file, "\t\t%d", ool); 909 if (StringOOL != strNULL) 910 fprintf(file, "%s,\n", StringOOL); 911 else 912 fprintf(file, ",\n"); 913 fprintf(file, "\t\t__FILE__, __LINE__);\n"); 914 fprintf(file, "#endif /* MIG_DEBUG */\n\n"); 915} 916 917void 918WriteLogDefines(FILE *file, string_t who) 919{ 920 fprintf(file, "#if MIG_DEBUG\n"); 921 fprintf(file, "#define LOG_W_E(X)\tLOG_ERRORS(%s, \\\n", who); 922 fprintf(file, "\t\t\tMACH_MSG_ERROR_WHILE_PARSING, (void *)(X), __FILE__, __LINE__)\n"); 923 fprintf(file, "#else /* MIG_DEBUG */\n"); 924 fprintf(file, "#define LOG_W_E(X)\n"); 925 fprintf(file, "#endif /* MIG_DEBUG */\n"); 926 fprintf(file, "\n"); 927} 928 929/* common utility to report errors */ 930void 931WriteReturnMsgError(FILE *file, routine_t *rt, boolean_t isuser, argument_t *arg, string_t error) 932{ 933 char space[MAX_STR_LEN]; 934 string_t string = &space[0]; 935 936 if (UseEventLogger && arg != argNULL) 937 sprintf(string, "LOG_W_E(\"%s\"); ", arg->argVarName); 938 else 939 string = ""; 940 941 fprintf(file, "\t\t{ "); 942 943 if (isuser) { 944 if (! rtMessOnStack(rt)) 945 fprintf(file, "%s((char *) Mess, (mach_msg_size_t)sizeof(*Mess)); ", MessFreeRoutine); 946 947 fprintf(file, "%sreturn %s; }\n", string, error); 948 } 949 else 950 fprintf(file, "%sMIG_RETURN_ERROR(OutP, %s); }\n", string, error); 951} 952 953/* executed iff elements are defined */ 954void 955WriteCheckTrailerHead(FILE *file, routine_t *rt, boolean_t isuser) 956{ 957 string_t who = (isuser) ? "Out0P" : "In0P"; 958 959 fprintf(file, "\tTrailerP = (mach_msg_max_trailer_t *)((vm_offset_t)%s +\n", who); 960 fprintf(file, "\t\tround_msg(%s->Head.msgh_size));\n", who); 961 fprintf(file, "\tif (TrailerP->msgh_trailer_type != MACH_MSG_TRAILER_FORMAT_0)\n"); 962 if (isuser) 963 fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); 964 else 965 fprintf(file, "\t\t{ MIG_RETURN_ERROR(%s, MIG_TRAILER_ERROR); }\n", who); 966 967 fprintf(file, "#if\t__MigTypeCheck\n"); 968 fprintf(file, "\ttrailer_size = TrailerP->msgh_trailer_size -\n"); 969 fprintf(file, "\t\t(mach_msg_size_t)(sizeof(mach_msg_trailer_type_t) - sizeof(mach_msg_trailer_size_t));\n"); 970 fprintf(file, "#endif\t/* __MigTypeCheck */\n"); 971} 972 973/* executed iff elements are defined */ 974void 975WriteCheckTrailerSize(FILE *file, boolean_t isuser, register argument_t *arg) 976{ 977 fprintf(file, "#if\t__MigTypeCheck\n"); 978 if (akIdent(arg->argKind) == akeMsgSeqno) { 979 fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(mach_port_seqno_t))\n"); 980 if (isuser) 981 fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); 982 else 983 fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n"); 984 fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(mach_port_seqno_t);\n"); 985 } 986 else if (akIdent(arg->argKind) == akeSecToken) { 987 fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(security_token_t))\n"); 988 if (isuser) 989 fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); 990 else 991 fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n"); 992 fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(security_token_t);\n"); 993 } 994 else if (akIdent(arg->argKind) == akeAuditToken) { 995 fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(audit_token_t))\n"); 996 if (isuser) 997 fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); 998 else 999 fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n"); 1000 fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(audit_token_t);\n"); 1001 } 1002 else if (akIdent(arg->argKind) == akeContextToken) { 1003 fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(mach_vm_address_t))\n"); 1004 if (isuser) 1005 fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); 1006 else 1007 fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n"); 1008 fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(mach_vm_address_t);\n"); 1009 } 1010 fprintf(file, "#endif\t/* __MigTypeCheck */\n"); 1011} 1012 1013