|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: ! 27: #include <assert.h> ! 28: ! 29: #include "write.h" ! 30: #include "utils.h" ! 31: #include "global.h" ! 32: #include "error.h" ! 33: #include "cpu.h" ! 34: ! 35: static void ! 36: WriteIncludes(FILE *file) ! 37: { ! 38: fprintf(file, "#define EXPORT_BOOLEAN\n"); ! 39: fprintf(file, "#include <mach/boolean.h>\n"); ! 40: fprintf(file, "#include <mach/kern_return.h>\n"); ! 41: fprintf(file, "#include <mach/message.h>\n"); ! 42: fprintf(file, "#include <mach/mig_errors.h>\n"); ! 43: fprintf(file, "#include <mach/mig_support.h>\n"); ! 44: if (IsKernelServer) ! 45: fprintf(file, "#include <ipc/ipc_port.h>\n"); ! 46: fprintf(file, "\n"); ! 47: } ! 48: ! 49: static void ! 50: WriteGlobalDecls(FILE *file) ! 51: { ! 52: if (RCSId != strNULL) ! 53: WriteRCSDecl(file, strconcat(SubsystemName, "_server"), RCSId); ! 54: ! 55: /* Used for locations in the request message, *not* reply message. ! 56: Reply message locations aren't dependent on IsKernelServer. */ ! 57: ! 58: if (IsKernelServer) ! 59: { ! 60: fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n"); ! 61: fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)"); ! 62: fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n"); ! 63: fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n"); ! 64: fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)"); ! 65: fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n"); ! 66: } ! 67: else ! 68: { ! 69: fprintf(file, "#define msgh_request_port\tmsgh_local_port\n"); ! 70: fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)"); ! 71: fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n"); ! 72: fprintf(file, "#define msgh_reply_port\t\tmsgh_remote_port\n"); ! 73: fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)"); ! 74: fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n"); ! 75: } ! 76: fprintf(file, "\n"); ! 77: } ! 78: ! 79: static void ! 80: WriteProlog(FILE *file) ! 81: { ! 82: fprintf(file, "/* Module %s */\n", SubsystemName); ! 83: fprintf(file, "\n"); ! 84: ! 85: WriteIncludes(file); ! 86: WriteBogusDefines(file); ! 87: WriteGlobalDecls(file); ! 88: } ! 89: ! 90: ! 91: static void ! 92: WriteSymTabEntries(FILE *file, const statement_t *stats) ! 93: { ! 94: register const statement_t *stat; ! 95: register u_int current = 0; ! 96: ! 97: for (stat = stats; stat != stNULL; stat = stat->stNext) ! 98: if (stat->stKind == skRoutine) { ! 99: register num = stat->stRoutine->rtNumber; ! 100: const char *name = stat->stRoutine->rtName; ! 101: ! 102: while (++current <= num) ! 103: fprintf(file,"\t\t\t{ \"\", 0, 0 },\n"); ! 104: fprintf(file, "\t{ \"%s\", %d, _X%s },\n", ! 105: name, ! 106: SubsystemBase + current - 1, ! 107: name); ! 108: } ! 109: while (++current <= rtNumber) ! 110: fprintf(file,"\t{ \"\", 0, 0 },\n"); ! 111: } ! 112: ! 113: static void ! 114: WriteArrayEntries(FILE *file, const statement_t *stats) ! 115: { ! 116: register u_int current = 0; ! 117: register const statement_t *stat; ! 118: ! 119: for (stat = stats; stat != stNULL; stat = stat->stNext) ! 120: if (stat->stKind == skRoutine) ! 121: { ! 122: register const routine_t *rt = stat->stRoutine; ! 123: ! 124: while (current++ < rt->rtNumber) ! 125: fprintf(file, "\t\t0,\n"); ! 126: fprintf(file, "\t\t_X%s,\n", rt->rtName); ! 127: } ! 128: while (current++ < rtNumber) ! 129: fprintf(file, "\t\t\t0,\n"); ! 130: } ! 131: ! 132: static void ! 133: WriteEpilog(FILE *file, const statement_t *stats) ! 134: { ! 135: fprintf(file, "\n"); ! 136: ! 137: /* ! 138: * First, the symbol table ! 139: */ ! 140: fprintf(file, "static mig_routine_t %s_routines[] = {\n", ServerDemux); ! 141: ! 142: WriteArrayEntries(file, stats); ! 143: ! 144: fprintf(file, "};\n"); ! 145: fprintf(file, "\n"); ! 146: ! 147: /* ! 148: * Then, the server routine ! 149: */ ! 150: fprintf(file, "mig_external boolean_t %s\n", ServerDemux); ! 151: fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n"); ! 152: ! 153: fprintf(file, "{\n"); ! 154: fprintf(file, "\tregister mach_msg_header_t *InP = InHeadP;\n"); ! 155: ! 156: fprintf(file, "\tregister mig_reply_header_t *OutP = (mig_reply_header_t *) OutHeadP;\n"); ! 157: ! 158: fprintf(file, "\n"); ! 159: ! 160: WriteStaticDecl(file, itRetCodeType, ! 161: itRetCodeType->itDeallocate, itRetCodeType->itLongForm, ! 162: !IsKernelServer, "RetCodeType"); ! 163: fprintf(file, "\n"); ! 164: ! 165: fprintf(file, "\tregister mig_routine_t routine;\n"); ! 166: fprintf(file, "\n"); ! 167: ! 168: fprintf(file, "\tOutP->Head.msgh_bits = "); ! 169: fprintf(file, "MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InP->msgh_bits), 0);\n"); ! 170: fprintf(file, "\tOutP->Head.msgh_size = sizeof *OutP;\n"); ! 171: fprintf(file, "\tOutP->Head.msgh_remote_port = InP->msgh_reply_port;\n"); ! 172: fprintf(file, "\tOutP->Head.msgh_local_port = MACH_PORT_NULL;\n"); ! 173: fprintf(file, "\tOutP->Head.msgh_seqno = 0;\n"); ! 174: fprintf(file, "\tOutP->Head.msgh_id = InP->msgh_id + 100;\n"); ! 175: fprintf(file, "\n"); ! 176: WritePackMsgType(file, itRetCodeType, ! 177: itRetCodeType->itDeallocate, itRetCodeType->itLongForm, ! 178: !IsKernelServer, "OutP->RetCodeType", "RetCodeType"); ! 179: fprintf(file, "\n"); ! 180: ! 181: fprintf(file, "\tif ((InP->msgh_id > %d) || (InP->msgh_id < %d) ||\n", ! 182: SubsystemBase + rtNumber - 1, SubsystemBase); ! 183: fprintf(file, "\t ((routine = %s_routines[InP->msgh_id - %d]) == 0)) {\n", ! 184: ServerDemux, SubsystemBase); ! 185: fprintf(file, "\t\tOutP->RetCode = MIG_BAD_ID;\n"); ! 186: fprintf(file, "\t\treturn FALSE;\n"); ! 187: fprintf(file, "\t}\n"); ! 188: ! 189: /* Call appropriate routine */ ! 190: fprintf(file, "\t(*routine) (InP, &OutP->Head);\n"); ! 191: fprintf(file, "\treturn TRUE;\n"); ! 192: fprintf(file, "}\n"); ! 193: fprintf(file, "\n"); ! 194: ! 195: /* ! 196: * Then, the <subsystem>_server_routine routine ! 197: */ ! 198: fprintf(file, "mig_external mig_routine_t %s_routine\n", ServerDemux); ! 199: fprintf(file, "\t(const mach_msg_header_t *InHeadP)\n"); ! 200: ! 201: fprintf(file, "{\n"); ! 202: fprintf(file, "\tregister int msgh_id;\n"); ! 203: fprintf(file, "\n"); ! 204: fprintf(file, "\tmsgh_id = InHeadP->msgh_id - %d;\n", SubsystemBase); ! 205: fprintf(file, "\n"); ! 206: fprintf(file, "\tif ((msgh_id > %d) || (msgh_id < 0))\n", ! 207: rtNumber - 1); ! 208: fprintf(file, "\t\treturn 0;\n"); ! 209: fprintf(file, "\n"); ! 210: fprintf(file, "\treturn %s_routines[msgh_id];\n", ServerDemux); ! 211: fprintf(file, "}\n"); ! 212: fprintf(file, "\n"); ! 213: ! 214: /* symtab */ ! 215: ! 216: if (GenSymTab) { ! 217: fprintf(file,"\nmig_symtab_t _%sSymTab[] = {\n",SubsystemName); ! 218: WriteSymTabEntries(file,stats); ! 219: fprintf(file,"};\n"); ! 220: fprintf(file,"int _%sSymTabBase = %d;\n",SubsystemName,SubsystemBase); ! 221: fprintf(file,"int _%sSymTabEnd = %d;\n",SubsystemName,SubsystemBase+rtNumber); ! 222: } ! 223: } ! 224: ! 225: /* ! 226: * Returns the return type of the server-side work function. ! 227: * Suitable for "extern %s serverfunc()". ! 228: */ ! 229: static const char * ! 230: ServerSideType(const routine_t *rt) ! 231: { ! 232: if (rt->rtServerReturn == argNULL) ! 233: return "void"; ! 234: else ! 235: return rt->rtServerReturn->argType->itTransType; ! 236: } ! 237: ! 238: static void ! 239: WriteLocalVarDecl(FILE *file, register const argument_t *arg) ! 240: { ! 241: register const ipc_type_t *it = arg->argType; ! 242: ! 243: if (it->itInLine && it->itVarArray) ! 244: { ! 245: register const ipc_type_t *btype = it->itElement; ! 246: ! 247: fprintf(file, "\t%s %s[%d]", btype->itTransType, ! 248: arg->argVarName, it->itNumber/btype->itNumber); ! 249: } ! 250: else ! 251: fprintf(file, "\t%s %s", it->itTransType, arg->argVarName); ! 252: } ! 253: ! 254: static void ! 255: WriteLocalPtrDecl(FILE *file, register const argument_t *arg) ! 256: { ! 257: fprintf(file, "\t%s *%sP", ! 258: FetchServerType(arg->argType->itElement), ! 259: arg->argVarName); ! 260: } ! 261: ! 262: static void ! 263: WriteServerArgDecl(FILE *file, const argument_t *arg) ! 264: { ! 265: fprintf(file, "%s %s%s", ! 266: arg->argType->itTransType, ! 267: arg->argByReferenceServer ? "*" : "", ! 268: arg->argVarName); ! 269: } ! 270: ! 271: /* ! 272: * Writes the local variable declarations which are always ! 273: * present: InP, OutP, the server-side work function. ! 274: */ ! 275: static void ! 276: WriteVarDecls(FILE *file, const routine_t *rt) ! 277: { ! 278: int i; ! 279: boolean_t NeedMsghSize = FALSE; ! 280: boolean_t NeedMsghSizeDelta = FALSE; ! 281: ! 282: fprintf(file, "\tregister Request *In0P = (Request *) InHeadP;\n"); ! 283: for (i = 1; i <= rt->rtMaxRequestPos; i++) ! 284: fprintf(file, "\tregister Request *In%dP;\n", i); ! 285: fprintf(file, "\tregister Reply *OutP = (Reply *) OutHeadP;\n"); ! 286: ! 287: fprintf(file, "\tmig_external %s %s\n", ! 288: ServerSideType(rt), rt->rtServerName); ! 289: fprintf(file, "\t\t("); ! 290: WriteList(file, rt->rtArgs, WriteServerArgDecl, akbServerArg, ", ", ""); ! 291: fprintf(file, ");\n"); ! 292: fprintf(file, "\n"); ! 293: ! 294: if (!rt->rtSimpleFixedReply) ! 295: fprintf(file, "\tboolean_t msgh_simple;\n"); ! 296: else if (!rt->rtSimpleCheckRequest) ! 297: { ! 298: fprintf(file, "#if\tTypeCheck\n"); ! 299: fprintf(file, "\tboolean_t msgh_simple;\n"); ! 300: fprintf(file, "#endif\t/* TypeCheck */\n"); ! 301: fprintf(file, "\n"); ! 302: } ! 303: ! 304: /* if either request or reply is variable, we may need ! 305: msgh_size_delta and msgh_size */ ! 306: ! 307: if (rt->rtNumRequestVar > 0) ! 308: NeedMsghSize = TRUE; ! 309: if (rt->rtMaxRequestPos > 0) ! 310: NeedMsghSizeDelta = TRUE; ! 311: ! 312: if (rt->rtNumReplyVar > 1) ! 313: NeedMsghSize = TRUE; ! 314: if (rt->rtMaxReplyPos > 0) ! 315: NeedMsghSizeDelta = TRUE; ! 316: ! 317: if (NeedMsghSize) ! 318: fprintf(file, "\tunsigned int msgh_size;\n"); ! 319: if (NeedMsghSizeDelta) ! 320: fprintf(file, "\tunsigned int msgh_size_delta;\n"); ! 321: ! 322: if (NeedMsghSize || NeedMsghSizeDelta) ! 323: fprintf(file, "\n"); ! 324: } ! 325: ! 326: static void ! 327: WriteMsgError(FILE *file, const char *error_msg) ! 328: { ! 329: fprintf(file, "\t\t{ OutP->RetCode = %s; return; }\n", error_msg); ! 330: } ! 331: ! 332: static void ! 333: WriteReplyInit(FILE *file, const routine_t *rt) ! 334: { ! 335: boolean_t printed_nl = FALSE; ! 336: ! 337: if (rt->rtSimpleFixedReply) ! 338: { ! 339: if (!rt->rtSimpleSendReply) /* complex reply message */ ! 340: { ! 341: printed_nl = TRUE; ! 342: fprintf(file, "\n"); ! 343: fprintf(file, ! 344: "\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n"); ! 345: } ! 346: } ! 347: else ! 348: { ! 349: printed_nl = TRUE; ! 350: fprintf(file, "\n"); ! 351: fprintf(file, "\tmsgh_simple = %s;\n", ! 352: strbool(rt->rtSimpleSendReply)); ! 353: } ! 354: ! 355: if (rt->rtNumReplyVar == 0) ! 356: { ! 357: if (!printed_nl) ! 358: fprintf(file, "\n"); ! 359: fprintf(file, "\tOutP->Head.msgh_size = %d;\n", rt->rtReplySize); ! 360: } ! 361: } ! 362: ! 363: static void ! 364: WriteReplyHead(FILE *file, const routine_t *rt) ! 365: { ! 366: if ((!rt->rtSimpleFixedReply) || ! 367: (rt->rtNumReplyVar > 1)) ! 368: { ! 369: fprintf(file, "\n"); ! 370: if (rt->rtMaxReplyPos > 0) ! 371: fprintf(file, "\tOutP = (Reply *) OutHeadP;\n"); ! 372: } ! 373: ! 374: if (!rt->rtSimpleFixedReply) ! 375: { ! 376: fprintf(file, "\tif (!msgh_simple)\n"); ! 377: fprintf(file, ! 378: "\t\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n"); ! 379: } ! 380: if (rt->rtNumReplyVar > 1) ! 381: fprintf(file, "\tOutP->Head.msgh_size = msgh_size;\n"); ! 382: } ! 383: ! 384: static void ! 385: WriteCheckHead(FILE *file, const routine_t *rt) ! 386: { ! 387: fprintf(file, "#if\tTypeCheck\n"); ! 388: if (rt->rtNumRequestVar > 0) ! 389: fprintf(file, "\tmsgh_size = In0P->Head.msgh_size;\n"); ! 390: if (!rt->rtSimpleCheckRequest) ! 391: fprintf(file, "\tmsgh_simple = !(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);\n"); ! 392: ! 393: if (rt->rtNumRequestVar > 0) ! 394: fprintf(file, "\tif ((msgh_size < %d)", ! 395: rt->rtRequestSize); ! 396: else ! 397: fprintf(file, "\tif ((In0P->Head.msgh_size != %d)", ! 398: rt->rtRequestSize); ! 399: ! 400: if (rt->rtSimpleCheckRequest) ! 401: fprintf(file, " ||\n\t %s(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)", ! 402: rt->rtSimpleReceiveRequest ? "" : "!"); ! 403: fprintf(file, ")\n"); ! 404: WriteMsgError(file, "MIG_BAD_ARGUMENTS"); ! 405: fprintf(file, "#endif\t/* TypeCheck */\n"); ! 406: fprintf(file, "\n"); ! 407: } ! 408: ! 409: static void ! 410: WriteTypeCheck(FILE *file, register const argument_t *arg) ! 411: { ! 412: register const ipc_type_t *it = arg->argType; ! 413: register const routine_t *rt = arg->argRoutine; ! 414: ! 415: fprintf(file, "#if\tTypeCheck\n"); ! 416: if (akCheck(arg->argKind, akbRequestQC)) ! 417: fprintf(file, "\tif (* (int *) &In%dP->%s != * (int *) &%sCheck)\n", ! 418: arg->argRequestPos, arg->argTTName, arg->argVarName); ! 419: else ! 420: { ! 421: fprintf(file, "\tif ("); ! 422: if (!it->itIndefinite) { ! 423: fprintf(file, "(In%dP->%s%s.msgt_inline != %s) ||\n\t ", ! 424: arg->argRequestPos, arg->argTTName, ! 425: arg->argLongForm ? ".msgtl_header" : "", ! 426: strbool(it->itInLine)); ! 427: } ! 428: fprintf(file, "(In%dP->%s%s.msgt_longform != %s) ||\n", ! 429: arg->argRequestPos, arg->argTTName, ! 430: arg->argLongForm ? ".msgtl_header" : "", ! 431: strbool(arg->argLongForm)); ! 432: if (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC) ! 433: { ! 434: if (!rt->rtSimpleCheckRequest) ! 435: fprintf(file, "\t (MACH_MSG_TYPE_PORT_ANY(In%dP->%s.msgt%s_name) && msgh_simple) ||\n", ! 436: arg->argRequestPos, arg->argTTName, ! 437: arg->argLongForm ? "l" : ""); ! 438: } ! 439: else ! 440: fprintf(file, "\t (In%dP->%s.msgt%s_name != %s) ||\n", ! 441: arg->argRequestPos, arg->argTTName, ! 442: arg->argLongForm ? "l" : "", ! 443: it->itOutNameStr); ! 444: if (!it->itVarArray) ! 445: fprintf(file, "\t (In%dP->%s.msgt%s_number != %d) ||\n", ! 446: arg->argRequestPos, arg->argTTName, ! 447: arg->argLongForm ? "l" : "", ! 448: it->itNumber); ! 449: fprintf(file, "\t (In%dP->%s.msgt%s_size != %d))\n", ! 450: arg->argRequestPos, arg->argTTName, ! 451: arg->argLongForm ? "l" : "", ! 452: it->itSize); ! 453: } ! 454: WriteMsgError(file, "MIG_BAD_ARGUMENTS"); ! 455: fprintf(file, "#endif\t/* TypeCheck */\n"); ! 456: fprintf(file, "\n"); ! 457: } ! 458: ! 459: static void ! 460: WriteCheckArgSize(FILE *file, register const argument_t *arg) ! 461: { ! 462: register const ipc_type_t *ptype = arg->argType; ! 463: register const ipc_type_t *btype = ptype->itElement; ! 464: const argument_t *count = arg->argCount; ! 465: int multiplier = btype->itTypeSize / btype->itNumber; ! 466: ! 467: if (ptype->itIndefinite) { ! 468: /* ! 469: * Check descriptor. If out-of-line, use standard size. ! 470: */ ! 471: fprintf(file, "(In%dP->%s%s.msgt_inline) ? ", ! 472: arg->argRequestPos, ! 473: arg->argTTName, ! 474: arg->argLongForm ? ".msgtl_header" : ""); ! 475: } ! 476: ! 477: if (btype->itTypeSize % 4 != 0) ! 478: fprintf(file, "("); ! 479: ! 480: if (multiplier > 1) ! 481: fprintf(file, "%d * ", multiplier); ! 482: ! 483: fprintf(file, "In%dP->%s", arg->argRequestPos, count->argMsgField); ! 484: ! 485: /* If the base type size of the data field isn`t a multiple of 4, ! 486: we have to round up. */ ! 487: if (btype->itTypeSize % 4 != 0) ! 488: fprintf(file, " + 3) & ~3"); ! 489: ! 490: if (ptype->itIndefinite) { ! 491: fprintf(file, " : sizeof(%s *)", FetchServerType(btype)); ! 492: } ! 493: } ! 494: ! 495: static void ! 496: WriteCheckMsgSize(FILE *file, register const argument_t *arg) ! 497: { ! 498: register const routine_t *rt = arg->argRoutine; ! 499: ! 500: /* If there aren't any more In args after this, then ! 501: we can use the msgh_size_delta value directly in ! 502: the TypeCheck conditional. */ ! 503: ! 504: if (arg->argRequestPos == rt->rtMaxRequestPos) ! 505: { ! 506: fprintf(file, "#if\tTypeCheck\n"); ! 507: fprintf(file, "\tif (msgh_size != %d + (", rt->rtRequestSize); ! 508: WriteCheckArgSize(file, arg); ! 509: fprintf(file, "))\n"); ! 510: ! 511: WriteMsgError(file, "MIG_BAD_ARGUMENTS"); ! 512: fprintf(file, "#endif\t/* TypeCheck */\n"); ! 513: } ! 514: else ! 515: { ! 516: /* If there aren't any more variable-sized arguments after this, ! 517: then we must check for exact msg-size and we don't need to ! 518: update msgh_size. */ ! 519: ! 520: boolean_t LastVarArg = arg->argRequestPos+1 == rt->rtNumRequestVar; ! 521: ! 522: /* calculate the actual size in bytes of the data field. note ! 523: that this quantity must be a multiple of four. hence, if ! 524: the base type size isn't a multiple of four, we have to ! 525: round up. note also that btype->itNumber must ! 526: divide btype->itTypeSize (see itCalculateSizeInfo). */ ! 527: ! 528: fprintf(file, "\tmsgh_size_delta = "); ! 529: WriteCheckArgSize(file, arg); ! 530: fprintf(file, ";\n"); ! 531: fprintf(file, "#if\tTypeCheck\n"); ! 532: ! 533: /* Don't decrement msgh_size until we've checked that ! 534: it won't underflow. */ ! 535: ! 536: if (LastVarArg) ! 537: fprintf(file, "\tif (msgh_size != %d + msgh_size_delta)\n", ! 538: rt->rtRequestSize); ! 539: else ! 540: fprintf(file, "\tif (msgh_size < %d + msgh_size_delta)\n", ! 541: rt->rtRequestSize); ! 542: WriteMsgError(file, "MIG_BAD_ARGUMENTS"); ! 543: ! 544: if (!LastVarArg) ! 545: fprintf(file, "\tmsgh_size -= msgh_size_delta;\n"); ! 546: ! 547: fprintf(file, "#endif\t/* TypeCheck */\n"); ! 548: } ! 549: fprintf(file, "\n"); ! 550: } ! 551: ! 552: static const char * ! 553: InArgMsgField(register const argument_t *arg) ! 554: { ! 555: static char buffer[100]; ! 556: ! 557: /* ! 558: * Inside the kernel, the request and reply port fields ! 559: * really hold ipc_port_t values, not mach_port_t values. ! 560: * Hence we must cast the values. ! 561: */ ! 562: ! 563: if (IsKernelServer && ! 564: ((akIdent(arg->argKind) == akeRequestPort) || ! 565: (akIdent(arg->argKind) == akeReplyPort))) ! 566: sprintf(buffer, "(ipc_port_t) In%dP->%s", ! 567: arg->argRequestPos, arg->argMsgField); ! 568: else ! 569: sprintf(buffer, "In%dP->%s", ! 570: arg->argRequestPos, arg->argMsgField); ! 571: ! 572: return buffer; ! 573: } ! 574: ! 575: static void ! 576: WriteExtractArgValue(FILE *file, register const argument_t *arg) ! 577: { ! 578: register const ipc_type_t *it = arg->argType; ! 579: ! 580: if (arg->argMultiplier > 1) ! 581: WriteCopyType(file, it, "%s", "/* %s */ %s / %d", ! 582: arg->argVarName, InArgMsgField(arg), arg->argMultiplier); ! 583: else if (it->itInTrans != strNULL) ! 584: WriteCopyType(file, it, "%s", "/* %s */ %s(%s)", ! 585: arg->argVarName, it->itInTrans, InArgMsgField(arg)); ! 586: else ! 587: WriteCopyType(file, it, "%s", "/* %s */ %s", ! 588: arg->argVarName, InArgMsgField(arg)); ! 589: fprintf(file, "\n"); ! 590: } ! 591: ! 592: static void ! 593: WriteInitializeCount(FILE *file, register const argument_t *arg) ! 594: { ! 595: register const ipc_type_t *ptype = arg->argParent->argType; ! 596: register const ipc_type_t *btype = ptype->itElement; ! 597: ! 598: /* ! 599: * Initialize 'count' argument for variable-length inline OUT parameter ! 600: * with maximum allowed number of elements. ! 601: */ ! 602: ! 603: fprintf(file, "\t%s = %d;\n", arg->argVarName, ! 604: ptype->itNumber/btype->itNumber); ! 605: ! 606: /* ! 607: * If the user passed in a count, then we use the minimum. ! 608: * We can't let the user completely override our maximum, ! 609: * or the user might convince the server to overwrite the buffer. ! 610: */ ! 611: ! 612: if (arg->argCInOut != argNULL) { ! 613: const char *msgfield = InArgMsgField(arg->argCInOut); ! 614: ! 615: fprintf(file, "\tif (%s < %s)\n", msgfield, arg->argVarName); ! 616: fprintf(file, "\t\t%s = %s;\n", arg->argVarName, msgfield); ! 617: } ! 618: ! 619: fprintf(file, "\n"); ! 620: } ! 621: ! 622: static void ! 623: WriteInitializePtr(FILE *file, register const argument_t *arg) ! 624: { ! 625: if (akCheck(arg->argKind, akbVarNeeded)) ! 626: fprintf(file, "\t%sP = %s;\n", ! 627: arg->argVarName, arg->argVarName); ! 628: else ! 629: fprintf(file, "\t%sP = OutP->%s;\n", ! 630: arg->argVarName, arg->argMsgField); ! 631: } ! 632: ! 633: static void ! 634: WriteTypeCheckArg(FILE *file, register const argument_t *arg) ! 635: { ! 636: if (akCheck(arg->argKind, akbRequest)) { ! 637: WriteTypeCheck(file, arg); ! 638: ! 639: if (akCheck(arg->argKind, akbVariable)) ! 640: WriteCheckMsgSize(file, arg); ! 641: } ! 642: } ! 643: ! 644: static void ! 645: WriteAdjustRequestMsgPtr(FILE *file, register const argument_t *arg) ! 646: { ! 647: register const ipc_type_t *ptype = arg->argType; ! 648: ! 649: fprintf(file, ! 650: "\tIn%dP = (Request *) ((char *) In%dP + msgh_size_delta - %d);\n\n", ! 651: arg->argRequestPos+1, arg->argRequestPos, ! 652: ptype->itTypeSize + ptype->itPadSize); ! 653: } ! 654: ! 655: static void ! 656: WriteTypeCheckRequestArgs(FILE *file, register const routine_t *rt) ! 657: { ! 658: register const argument_t *arg; ! 659: register const argument_t *lastVarArg; ! 660: ! 661: lastVarArg = argNULL; ! 662: for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { ! 663: ! 664: /* ! 665: * Advance message pointer if the last request argument was ! 666: * variable-length and the request position will change. ! 667: */ ! 668: if (lastVarArg != argNULL && ! 669: lastVarArg->argRequestPos < arg->argRequestPos) ! 670: { ! 671: WriteAdjustRequestMsgPtr(file, lastVarArg); ! 672: lastVarArg = argNULL; ! 673: } ! 674: ! 675: /* ! 676: * Type-check the argument. ! 677: */ ! 678: WriteTypeCheckArg(file, arg); ! 679: ! 680: /* ! 681: * Remember whether this was variable-length. ! 682: */ ! 683: if (akCheckAll(arg->argKind, akbVariable|akbRequest)) ! 684: lastVarArg = arg; ! 685: } ! 686: } ! 687: ! 688: static void ! 689: WriteExtractArg(FILE *file, register const argument_t *arg) ! 690: { ! 691: if (akCheckAll(arg->argKind, akbSendRcv|akbVarNeeded)) ! 692: WriteExtractArgValue(file, arg); ! 693: ! 694: if ((akIdent(arg->argKind) == akeCount) && ! 695: akCheck(arg->argKind, akbReturnSnd)) ! 696: { ! 697: register ipc_type_t *ptype = arg->argParent->argType; ! 698: ! 699: if (ptype->itInLine && ptype->itVarArray) ! 700: WriteInitializeCount(file, arg); ! 701: } ! 702: ! 703: if (akCheckAll(arg->argKind, akbReturnSnd|akbPointer)) ! 704: WriteInitializePtr(file, arg); ! 705: } ! 706: ! 707: static void ! 708: WriteServerCallArg(FILE *file, register const argument_t *arg) ! 709: { ! 710: const ipc_type_t *it = arg->argType; ! 711: boolean_t NeedClose = FALSE; ! 712: ! 713: if (arg->argByReferenceServer) ! 714: fprintf(file, "&"); ! 715: ! 716: if ((it->itInTrans != strNULL) && ! 717: akCheck(arg->argKind, akbSendRcv) && ! 718: !akCheck(arg->argKind, akbVarNeeded)) ! 719: { ! 720: fprintf(file, "%s(", it->itInTrans); ! 721: NeedClose = TRUE; ! 722: } ! 723: ! 724: if (akCheck(arg->argKind, akbPointer)) ! 725: fprintf(file, "%sP", arg->argVarName); ! 726: else if (akCheck(arg->argKind, akbVarNeeded)) ! 727: fprintf(file, "%s", arg->argVarName); ! 728: else if (akCheck(arg->argKind, akbSendRcv)) { ! 729: if (akCheck(arg->argKind, akbIndefinite)) { ! 730: fprintf(file, "(In%dP->%s%s.msgt_inline) ", ! 731: arg->argRequestPos, ! 732: arg->argTTName, ! 733: arg->argLongForm ? ".msgtl_header" : ""); ! 734: fprintf(file, "? %s ", InArgMsgField(arg)); ! 735: fprintf(file, ": *((%s **)%s)", ! 736: FetchServerType(arg->argType->itElement), ! 737: InArgMsgField(arg)); ! 738: } ! 739: else ! 740: fprintf(file, "%s", InArgMsgField(arg)); ! 741: } ! 742: else ! 743: fprintf(file, "OutP->%s", arg->argMsgField); ! 744: ! 745: if (NeedClose) ! 746: fprintf(file, ")"); ! 747: ! 748: if (!arg->argByReferenceServer && (arg->argMultiplier > 1)) ! 749: fprintf(file, " / %d", arg->argMultiplier); ! 750: } ! 751: ! 752: static void ! 753: WriteDestroyArg(FILE *file, register const argument_t *arg) ! 754: { ! 755: register const ipc_type_t *it = arg->argType; ! 756: ! 757: if (akCheck(arg->argKind, akbIndefinite)) { ! 758: /* ! 759: * Deallocate only if out-of-line. ! 760: */ ! 761: argument_t *count = arg->argCount; ! 762: ipc_type_t *btype = it->itElement; ! 763: int multiplier = btype->itTypeSize / btype->itNumber; ! 764: ! 765: fprintf(file, "\tif (!In%dP->%s%s.msgt_inline)\n", ! 766: arg->argRequestPos, ! 767: arg->argTTName, ! 768: arg->argLongForm ? ".msgtl_header" : ""); ! 769: fprintf(file, "\t\t%smig_deallocate(* (vm_offset_t *) %s, ", ! 770: SubrPrefix, InArgMsgField(arg)); ! 771: if (multiplier > 1) ! 772: fprintf(file, "%d * ", multiplier); ! 773: fprintf(file, " %s);\n", InArgMsgField(count)); ! 774: } else { ! 775: if (akCheck(arg->argKind, akbVarNeeded)) ! 776: fprintf(file, "\t%s(%s);\n", it->itDestructor, arg->argVarName); ! 777: else ! 778: fprintf(file, "\t%s(%s);\n", it->itDestructor, ! 779: InArgMsgField(arg)); ! 780: } ! 781: } ! 782: ! 783: static void ! 784: WriteDestroyPortArg(FILE *file, register const argument_t *arg) ! 785: { ! 786: register const ipc_type_t *it = arg->argType; ! 787: ! 788: /* ! 789: * If a translated port argument occurs in the body of a request ! 790: * message, and the message is successfully processed, then the ! 791: * port right should be deallocated. However, the called function ! 792: * didn't see the port right; it saw the translation. So we have ! 793: * to release the port right for it. ! 794: */ ! 795: ! 796: if ((it->itInTrans != strNULL) && ! 797: (it->itOutName == MACH_MSG_TYPE_PORT_SEND)) ! 798: { ! 799: fprintf(file, "\n"); ! 800: fprintf(file, "\tif (IP_VALID(%s))\n", InArgMsgField(arg)); ! 801: fprintf(file, "\t\t%sipc_port_release_send(%s);\n", ! 802: SubrPrefix, InArgMsgField(arg)); ! 803: } ! 804: } ! 805: ! 806: /* ! 807: * Check whether WriteDestroyPortArg would generate any code for arg. ! 808: */ ! 809: static boolean_t ! 810: CheckDestroyPortArg(register const argument_t *arg) ! 811: { ! 812: register const ipc_type_t *it = arg->argType; ! 813: ! 814: if ((it->itInTrans != strNULL) && ! 815: (it->itOutName == MACH_MSG_TYPE_PORT_SEND)) ! 816: { ! 817: return TRUE; ! 818: } ! 819: return FALSE; ! 820: } ! 821: ! 822: static void ! 823: WriteServerCall(FILE *file, const routine_t *rt) ! 824: { ! 825: boolean_t NeedClose = FALSE; ! 826: ! 827: fprintf(file, "\t"); ! 828: if (rt->rtServerReturn != argNULL) ! 829: { ! 830: const argument_t *arg = rt->rtServerReturn; ! 831: const ipc_type_t *it = arg->argType; ! 832: ! 833: fprintf(file, "OutP->%s = ", arg->argMsgField); ! 834: if (it->itOutTrans != strNULL) ! 835: { ! 836: fprintf(file, "%s(", it->itOutTrans); ! 837: NeedClose = TRUE; ! 838: } ! 839: } ! 840: fprintf(file, "%s(", rt->rtServerName); ! 841: WriteList(file, rt->rtArgs, WriteServerCallArg, akbServerArg, ", ", ""); ! 842: if (NeedClose) ! 843: fprintf(file, ")"); ! 844: fprintf(file, ");\n"); ! 845: } ! 846: ! 847: static void ! 848: WriteGetReturnValue(FILE *file, register const routine_t *rt) ! 849: { ! 850: if (rt->rtServerReturn != rt->rtRetCode) ! 851: fprintf(file, "\tOutP->%s = KERN_SUCCESS;\n", ! 852: rt->rtRetCode->argMsgField); ! 853: } ! 854: ! 855: static void ! 856: WriteCheckReturnValue(FILE *file, register const routine_t *rt) ! 857: { ! 858: if (rt->rtServerReturn == rt->rtRetCode) ! 859: { ! 860: fprintf(file, "\tif (OutP->%s != KERN_SUCCESS)\n", ! 861: rt->rtRetCode->argMsgField); ! 862: fprintf(file, "\t\treturn;\n"); ! 863: } ! 864: } ! 865: ! 866: static void ! 867: WritePackArgType(FILE *file, register const argument_t *arg) ! 868: { ! 869: fprintf(file, "\n"); ! 870: ! 871: WritePackMsgType(file, arg->argType, ! 872: arg->argType->itIndefinite ? d_NO : arg->argDeallocate, ! 873: arg->argLongForm, !IsKernelServer, ! 874: "OutP->%s", "%s", arg->argTTName); ! 875: } ! 876: ! 877: static void ! 878: WritePackArgValue(FILE *file, register const argument_t *arg) ! 879: { ! 880: register const ipc_type_t *it = arg->argType; ! 881: ! 882: fprintf(file, "\n"); ! 883: ! 884: if (it->itInLine && it->itVarArray) { ! 885: ! 886: if (it->itString) { ! 887: /* ! 888: * Copy variable-size C string with mig_strncpy. ! 889: * Save the string length (+ 1 for trailing 0) ! 890: * in the argument`s count field. ! 891: */ ! 892: fprintf(file, ! 893: "\tOutP->%s = %smig_strncpy(OutP->%s, %s, %d);\n", ! 894: arg->argCount->argMsgField, ! 895: SubrPrefix, ! 896: arg->argMsgField, ! 897: arg->argVarName, ! 898: it->itNumber); ! 899: } ! 900: else { ! 901: register argument_t *count = arg->argCount; ! 902: register ipc_type_t *btype = it->itElement; ! 903: ! 904: /* Note btype->itNumber == count->argMultiplier */ ! 905: ! 906: if (it->itIndefinite) { ! 907: /* ! 908: * If we are packing argument, it must be from ! 909: * a local variable. ! 910: */ ! 911: fprintf(file, "\tif (%sP != %s) {\n", ! 912: arg->argVarName, ! 913: arg->argVarName); ! 914: fprintf(file, "\t\tOutP->%s%s.msgt_inline = FALSE;\n", ! 915: arg->argTTName, ! 916: arg->argLongForm ? ".msgtl_header" : ""); ! 917: if (arg->argDeallocate == d_YES) ! 918: fprintf(file, "\t\tOutP->%s%s.msgt_deallocate = TRUE;\n", ! 919: arg->argTTName, ! 920: arg->argLongForm ? ".msgtl_header" : ""); ! 921: else if (arg->argDeallocate == d_MAYBE) ! 922: fprintf(file, "\t\tOutP->%s%s.msgt_deallocate = %s;\n", ! 923: arg->argTTName, ! 924: arg->argLongForm ? ".msgtl_header" : "", ! 925: arg->argDealloc->argVarName); ! 926: fprintf(file, "\t\t*((%s **)OutP->%s) = %sP;\n", ! 927: FetchServerType(btype), ! 928: arg->argMsgField, ! 929: arg->argVarName); ! 930: if (!arg->argRoutine->rtSimpleFixedReply) ! 931: fprintf(file, "\t\tmsgh_simple = FALSE;\n"); ! 932: fprintf(file, "\t}\n\telse {\n\t"); ! 933: } ! 934: fprintf(file, "\tmemcpy(OutP->%s, %s, ", ! 935: arg->argMsgField, arg->argVarName); ! 936: if (btype->itTypeSize > 1) ! 937: fprintf(file, "%d * ", ! 938: btype->itTypeSize); ! 939: fprintf(file, "%s);\n", ! 940: count->argVarName); ! 941: if (it->itIndefinite) ! 942: fprintf(file, "\t}\n"); ! 943: } ! 944: } ! 945: else if (arg->argMultiplier > 1) ! 946: WriteCopyType(file, it, "OutP->%s", "/* %s */ %d * %s", ! 947: arg->argMsgField, ! 948: arg->argMultiplier, ! 949: arg->argVarName); ! 950: else if (it->itOutTrans != strNULL) ! 951: WriteCopyType(file, it, "OutP->%s", "/* %s */ %s(%s)", ! 952: arg->argMsgField, it->itOutTrans, arg->argVarName); ! 953: else ! 954: WriteCopyType(file, it, "OutP->%s", "/* %s */ %s", ! 955: arg->argMsgField, arg->argVarName); ! 956: } ! 957: ! 958: static void ! 959: WriteCopyArgValue(FILE *file, register const argument_t *arg) ! 960: { ! 961: fprintf(file, "\n"); ! 962: WriteCopyType(file, arg->argType, "/* %d */ OutP->%s", "In%dP->%s", ! 963: arg->argRequestPos, arg->argMsgField); ! 964: } ! 965: ! 966: static void ! 967: WriteAdjustMsgSimple(FILE *file, register const argument_t *arg) ! 968: { ! 969: /* akbVarNeeded must be on */ ! 970: ! 971: if (!arg->argRoutine->rtSimpleFixedReply) ! 972: { ! 973: fprintf(file, "\n"); ! 974: fprintf(file, "\tif (MACH_MSG_TYPE_PORT_ANY(%s))\n", arg->argVarName); ! 975: fprintf(file, "\t\tmsgh_simple = FALSE;\n"); ! 976: } ! 977: } ! 978: ! 979: static void ! 980: WriteAdjustMsgCircular(FILE *file, register const argument_t *arg) ! 981: { ! 982: fprintf(file, "\n"); ! 983: ! 984: if (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC) ! 985: fprintf(file, "\tif (%s == MACH_MSG_TYPE_PORT_RECEIVE)\n", ! 986: arg->argPoly->argVarName); ! 987: ! 988: /* ! 989: * The carried port right can be accessed in OutP->XXXX. Normally ! 990: * the server function stuffs it directly there. If it is InOut, ! 991: * then it has already been copied into the reply message. ! 992: * If the server function deposited it into a variable (perhaps ! 993: * because the reply message is variable-sized) then it has already ! 994: * been copied into the reply message. Note we must use InHeadP ! 995: * (or In0P->Head) and OutHeadP to access the message headers, ! 996: * because of the variable-sized messages. ! 997: */ ! 998: ! 999: fprintf(file, "\tif (IP_VALID((ipc_port_t) InHeadP->msgh_reply_port) &&\n"); ! 1000: fprintf(file, "\t IP_VALID((ipc_port_t) OutP->%s) &&\n", arg->argMsgField); ! 1001: fprintf(file, "\t %sipc_port_check_circularity((ipc_port_t) OutP->%s, (ipc_port_t) InHeadP->msgh_reply_port))\n", ! 1002: SubrPrefix, arg->argMsgField); ! 1003: fprintf(file, "\t\tOutHeadP->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;\n"); ! 1004: } ! 1005: ! 1006: /* ! 1007: * Calculate the size of a variable-length message field. ! 1008: */ ! 1009: static void ! 1010: WriteArgSize(FILE *file, register const argument_t *arg) ! 1011: { ! 1012: register const ipc_type_t *ptype = arg->argType; ! 1013: register int bsize = ptype->itElement->itTypeSize; ! 1014: register const argument_t *count = arg->argCount; ! 1015: ! 1016: if (ptype->itIndefinite) { ! 1017: /* ! 1018: * Check descriptor. If out-of-line, use standard size. ! 1019: */ ! 1020: fprintf(file, "(OutP->%s%s.msgt_inline) ? ", ! 1021: arg->argTTName, ! 1022: arg->argLongForm ? ".msgtl_header" : ""); ! 1023: } ! 1024: ! 1025: if (bsize % 4 != 0) ! 1026: fprintf(file, "("); ! 1027: ! 1028: if (bsize > 1) ! 1029: fprintf(file, "%d * ", bsize); ! 1030: if (ptype->itString) ! 1031: /* get count from descriptor in message */ ! 1032: fprintf(file, "OutP->%s", count->argMsgField); ! 1033: else ! 1034: /* get count from argument */ ! 1035: fprintf(file, "%s", count->argVarName); ! 1036: ! 1037: /* ! 1038: * If the base type size is not a multiple of sizeof(int) [4], ! 1039: * we have to round up. ! 1040: */ ! 1041: if (bsize % 4 != 0) ! 1042: fprintf(file, " + 3) & ~3"); ! 1043: ! 1044: if (ptype->itIndefinite) { ! 1045: fprintf(file, " : sizeof(%s *)", ! 1046: FetchServerType(ptype->itElement)); ! 1047: } ! 1048: } ! 1049: ! 1050: /* ! 1051: * Adjust message size and advance reply pointer. ! 1052: * Called after packing a variable-length argument that ! 1053: * has more arguments following. ! 1054: */ ! 1055: static void ! 1056: WriteAdjustMsgSize(FILE *file, register const argument_t *arg) ! 1057: { ! 1058: register routine_t *rt = arg->argRoutine; ! 1059: register ipc_type_t *ptype = arg->argType; ! 1060: ! 1061: /* There are more Out arguments. We need to adjust msgh_size ! 1062: and advance OutP, so we save the size of the current field ! 1063: in msgh_size_delta. */ ! 1064: ! 1065: fprintf(file, "\tmsgh_size_delta = "); ! 1066: WriteArgSize(file, arg); ! 1067: fprintf(file, ";\n"); ! 1068: ! 1069: if (rt->rtNumReplyVar == 1) ! 1070: /* We can still address the message header directly. Fill ! 1071: in the size field. */ ! 1072: ! 1073: fprintf(file, "\tOutP->Head.msgh_size = %d + msgh_size_delta;\n", ! 1074: rt->rtReplySize); ! 1075: else ! 1076: if (arg->argReplyPos == 0) ! 1077: /* First variable-length argument. The previous msgh_size value ! 1078: is the minimum reply size. */ ! 1079: ! 1080: fprintf(file, "\tmsgh_size = %d + msgh_size_delta;\n", ! 1081: rt->rtReplySize); ! 1082: else ! 1083: fprintf(file, "\tmsgh_size += msgh_size_delta;\n"); ! 1084: ! 1085: fprintf(file, ! 1086: "\tOutP = (Reply *) ((char *) OutP + msgh_size_delta - %d);\n", ! 1087: ptype->itTypeSize + ptype->itPadSize); ! 1088: } ! 1089: ! 1090: /* ! 1091: * Calculate the size of the message. Called after the ! 1092: * last argument has been packed. ! 1093: */ ! 1094: static void ! 1095: WriteFinishMsgSize(FILE *file, register const argument_t *arg) ! 1096: { ! 1097: /* No more Out arguments. If this is the only variable Out ! 1098: argument, we can assign to msgh_size directly. */ ! 1099: ! 1100: if (arg->argReplyPos == 0) { ! 1101: fprintf(file, "\tOutP->Head.msgh_size = %d + (", ! 1102: arg->argRoutine->rtReplySize); ! 1103: WriteArgSize(file, arg); ! 1104: fprintf(file, ");\n"); ! 1105: } ! 1106: else { ! 1107: fprintf(file, "\tmsgh_size += "); ! 1108: WriteArgSize(file, arg); ! 1109: fprintf(file, ";\n"); ! 1110: } ! 1111: } ! 1112: ! 1113: static void ! 1114: WritePackArg(FILE *file, register const argument_t *arg) ! 1115: { ! 1116: if (akCheck(arg->argKind, akbReplyInit)) ! 1117: WritePackArgType(file, arg); ! 1118: ! 1119: if ((akIdent(arg->argKind) == akePoly) && ! 1120: akCheck(arg->argKind, akbReturnSnd)) ! 1121: WriteAdjustMsgSimple(file, arg); ! 1122: ! 1123: if (akCheckAll(arg->argKind, akbReturnSnd|akbVarNeeded)) ! 1124: WritePackArgValue(file, arg); ! 1125: else if (akCheckAll(arg->argKind, akbReturnSnd|akbVariable)) { ! 1126: register const ipc_type_t *it = arg->argType; ! 1127: ! 1128: if (it->itString) { ! 1129: /* Need to call strlen to calculate the size of the argument. */ ! 1130: fprintf(file, "\tOutP->%s = strlen(OutP->%s) + 1;\n", ! 1131: arg->argCount->argMsgField, arg->argMsgField); ! 1132: } else if (it->itIndefinite) { ! 1133: /* ! 1134: * We know that array is in reply message. ! 1135: */ ! 1136: fprintf(file, "\tif (%sP != OutP->%s) {\n", ! 1137: arg->argVarName, ! 1138: arg->argMsgField); ! 1139: fprintf(file, "\t\tOutP->%s%s.msgt_inline = FALSE;\n", ! 1140: arg->argTTName, ! 1141: arg->argLongForm ? ".msgtl_header" : ""); ! 1142: if (arg->argDeallocate == d_YES) ! 1143: fprintf(file, "\t\tOutP->%s%s.msgt_deallocate = TRUE;\n", ! 1144: arg->argTTName, ! 1145: arg->argLongForm ? ".msgtl_header" : ""); ! 1146: else if (arg->argDeallocate == d_MAYBE) ! 1147: fprintf(file, "\t\tOutP->%s%s.msgt_deallocate = %s;\n", ! 1148: arg->argTTName, ! 1149: arg->argLongForm ? ".msgtl_header" : "", ! 1150: arg->argDealloc->argVarName); ! 1151: fprintf(file, "\t\t*((%s **)OutP->%s) = %sP;\n", ! 1152: FetchServerType(it->itElement), ! 1153: arg->argMsgField, ! 1154: arg->argVarName); ! 1155: if (!arg->argRoutine->rtSimpleFixedReply) ! 1156: fprintf(file, "\t\tmsgh_simple = FALSE;\n"); ! 1157: fprintf(file, "\t}\n"); ! 1158: } ! 1159: } ! 1160: ! 1161: if (akCheck(arg->argKind, akbReplyCopy)) ! 1162: WriteCopyArgValue(file, arg); ! 1163: ! 1164: /* ! 1165: * If this is a KernelServer, and the reply message contains ! 1166: * a receive right, we must check for the possibility of a ! 1167: * port/message circularity. If queueing the reply message ! 1168: * would cause a circularity, we mark the reply message ! 1169: * with the circular bit. ! 1170: */ ! 1171: ! 1172: if (IsKernelServer && ! 1173: akCheck(arg->argKind, akbReturnSnd) && ! 1174: ((arg->argType->itOutName == MACH_MSG_TYPE_PORT_RECEIVE) || ! 1175: (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC))) ! 1176: WriteAdjustMsgCircular(file, arg); ! 1177: } ! 1178: ! 1179: /* ! 1180: * Handle reply arguments - fill in message types and copy arguments ! 1181: * that need to be copied. ! 1182: */ ! 1183: static void ! 1184: WritePackReplyArgs(FILE *file, register const routine_t *rt) ! 1185: { ! 1186: register const argument_t *arg; ! 1187: register const argument_t *lastVarArg; ! 1188: ! 1189: lastVarArg = argNULL; ! 1190: for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { ! 1191: ! 1192: /* ! 1193: * Adjust message size and advance message pointer if ! 1194: * the last reply argument was variable-length and the ! 1195: * request position will change. ! 1196: */ ! 1197: if (lastVarArg != argNULL && ! 1198: lastVarArg->argReplyPos < arg->argReplyPos) ! 1199: { ! 1200: WriteAdjustMsgSize(file, lastVarArg); ! 1201: lastVarArg = argNULL; ! 1202: } ! 1203: ! 1204: /* ! 1205: * Copy the argument ! 1206: */ ! 1207: WritePackArg(file, arg); ! 1208: ! 1209: /* ! 1210: * Remember whether this was variable-length. ! 1211: */ ! 1212: if (akCheckAll(arg->argKind, akbReturnSnd|akbVariable)) ! 1213: lastVarArg = arg; ! 1214: } ! 1215: ! 1216: /* ! 1217: * Finish the message size. ! 1218: */ ! 1219: if (lastVarArg != argNULL) ! 1220: WriteFinishMsgSize(file, lastVarArg); ! 1221: } ! 1222: ! 1223: static void ! 1224: WriteFieldDecl(FILE *file, const argument_t *arg) ! 1225: { ! 1226: WriteFieldDeclPrim(file, arg, FetchServerType); ! 1227: } ! 1228: ! 1229: static void ! 1230: WriteRoutine(FILE *file, register const routine_t *rt) ! 1231: { ! 1232: fprintf(file, "\n"); ! 1233: ! 1234: fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName); ! 1235: fprintf(file, "mig_internal void _X%s\n", rt->rtName); ! 1236: fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n"); ! 1237: ! 1238: fprintf(file, "{\n"); ! 1239: WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request"); ! 1240: WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply, "Reply"); ! 1241: ! 1242: WriteVarDecls(file, rt); ! 1243: ! 1244: WriteList(file, rt->rtArgs, WriteCheckDecl, akbRequestQC, "\n", "\n"); ! 1245: WriteList(file, rt->rtArgs, ! 1246: IsKernelServer ? WriteTypeDeclOut : WriteTypeDeclIn, ! 1247: akbReplyInit, "\n", "\n"); ! 1248: ! 1249: WriteList(file, rt->rtArgs, WriteLocalVarDecl, ! 1250: akbVarNeeded, ";\n", ";\n\n"); ! 1251: WriteList(file, rt->rtArgs, WriteLocalPtrDecl, ! 1252: akbPointer, ";\n", ";\n\n"); ! 1253: ! 1254: WriteCheckHead(file, rt); ! 1255: ! 1256: WriteTypeCheckRequestArgs(file, rt); ! 1257: WriteList(file, rt->rtArgs, WriteExtractArg, akbNone, "", ""); ! 1258: ! 1259: WriteServerCall(file, rt); ! 1260: WriteGetReturnValue(file, rt); ! 1261: ! 1262: WriteReverseList(file, rt->rtArgs, WriteDestroyArg, akbDestroy, "", ""); ! 1263: ! 1264: /* ! 1265: * For one-way routines, it doesn`t make sense to check the return ! 1266: * code, because we return immediately afterwards. However, ! 1267: * kernel servers may want to deallocate port arguments - and the ! 1268: * deallocation must not be done if the return code is not KERN_SUCCESS. ! 1269: */ ! 1270: if (rt->rtOneWay || rt->rtNoReplyArgs) ! 1271: { ! 1272: if (IsKernelServer) ! 1273: { ! 1274: if (rtCheckMaskFunction(rt->rtArgs, akbSendBody|akbSendRcv, ! 1275: CheckDestroyPortArg)) ! 1276: { ! 1277: WriteCheckReturnValue(file, rt); ! 1278: } ! 1279: WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg, ! 1280: akbSendBody|akbSendRcv, "", ""); ! 1281: } ! 1282: } ! 1283: else ! 1284: { ! 1285: WriteCheckReturnValue(file, rt); ! 1286: ! 1287: if (IsKernelServer) ! 1288: WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg, ! 1289: akbSendBody|akbSendRcv, "", ""); ! 1290: ! 1291: WriteReplyInit(file, rt); ! 1292: WritePackReplyArgs(file, rt); ! 1293: WriteReplyHead(file, rt); ! 1294: } ! 1295: ! 1296: fprintf(file, "}\n"); ! 1297: } ! 1298: ! 1299: void ! 1300: WriteServer(FILE *file, const statement_t *stats) ! 1301: { ! 1302: register const statement_t *stat; ! 1303: ! 1304: WriteProlog(file); ! 1305: for (stat = stats; stat != stNULL; stat = stat->stNext) ! 1306: switch (stat->stKind) ! 1307: { ! 1308: case skRoutine: ! 1309: WriteRoutine(file, stat->stRoutine); ! 1310: break; ! 1311: case skImport: ! 1312: case skSImport: ! 1313: WriteImport(file, stat->stFileName); ! 1314: break; ! 1315: case skUImport: ! 1316: break; ! 1317: default: ! 1318: fatal("WriteServer(): bad statement_kind_t (%d)", ! 1319: (int) stat->stKind); ! 1320: } ! 1321: WriteEpilog(file, stats); ! 1322: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.