|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1992,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 ! 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 the ! 24: * rights to redistribute these changes. ! 25: */ ! 26: ! 27: #include <assert.h> ! 28: ! 29: #include "write.h" ! 30: #include "error.h" ! 31: #include "utils.h" ! 32: #include "global.h" ! 33: #include "mig_string.h" ! 34: #include "cpu.h" ! 35: ! 36: /************************************************************* ! 37: * Writes the standard includes. The subsystem specific ! 38: * includes are in <SubsystemName>.h and writen by ! 39: * header:WriteHeader. Called by WriteProlog. ! 40: *************************************************************/ ! 41: static void ! 42: WriteIncludes(FILE *file) ! 43: { ! 44: if (IsKernelServer) ! 45: { ! 46: /* ! 47: * We want to get the user-side definitions of types ! 48: * like task_t, ipc_space_t, etc. in mach/mach_types.h. ! 49: */ ! 50: ! 51: fprintf(file, "#undef\tKERNEL\n"); ! 52: ! 53: if (InternalHeaderFileName != strNULL) ! 54: { ! 55: register char *cp; ! 56: ! 57: /* Strip any leading path from InternalHeaderFileName. */ ! 58: cp = strrchr(InternalHeaderFileName, '/'); ! 59: if (cp == 0) ! 60: cp = InternalHeaderFileName; ! 61: else ! 62: cp++; /* skip '/' */ ! 63: fprintf(file, "#include \"%s\"\n", cp); ! 64: } ! 65: } ! 66: ! 67: if (UserHeaderFileName != strNULL) ! 68: { ! 69: register char *cp; ! 70: ! 71: /* Strip any leading path from UserHeaderFileName. */ ! 72: cp = strrchr(UserHeaderFileName, '/'); ! 73: if (cp == 0) ! 74: cp = UserHeaderFileName; ! 75: else ! 76: cp++; /* skip '/' */ ! 77: fprintf(file, "#include \"%s\"\n", cp); ! 78: } ! 79: ! 80: fprintf(file, "#define EXPORT_BOOLEAN\n"); ! 81: fprintf(file, "#include <mach/boolean.h>\n"); ! 82: fprintf(file, "#include <mach/kern_return.h>\n"); ! 83: fprintf(file, "#include <mach/message.h>\n"); ! 84: fprintf(file, "#include <mach/notify.h>\n"); ! 85: fprintf(file, "#include <mach/mach_types.h>\n"); ! 86: fprintf(file, "#include <mach/mig_errors.h>\n"); ! 87: fprintf(file, "#include <mach/mig_support.h>\n"); ! 88: fprintf(file, "#include <mach/msg_type.h>\n"); ! 89: fprintf(file, "/* LINTLIBRARY */\n"); ! 90: fprintf(file, "\n"); ! 91: } ! 92: ! 93: static void ! 94: WriteGlobalDecls(FILE *file) ! 95: { ! 96: if (RCSId != strNULL) ! 97: WriteRCSDecl(file, strconcat(SubsystemName, "_user"), RCSId); ! 98: ! 99: fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n"); ! 100: fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n"); ! 101: fprintf(file, "\n"); ! 102: } ! 103: ! 104: /************************************************************* ! 105: * Writes the standard #includes, #defines, and ! 106: * RCS declaration. Called by WriteUser. ! 107: *************************************************************/ ! 108: static void ! 109: WriteProlog(FILE *file) ! 110: { ! 111: WriteIncludes(file); ! 112: WriteBogusDefines(file); ! 113: WriteGlobalDecls(file); ! 114: } ! 115: ! 116: /*ARGSUSED*/ ! 117: static void ! 118: WriteEpilog(FILE *file) ! 119: { ! 120: } ! 121: ! 122: static const_string_t ! 123: WriteHeaderPortType(const argument_t *arg) ! 124: { ! 125: if (arg->argType->itInName == MACH_MSG_TYPE_POLYMORPHIC) ! 126: return arg->argPoly->argVarName; ! 127: else ! 128: return arg->argType->itInNameStr; ! 129: } ! 130: ! 131: static void ! 132: WriteRequestHead(FILE *file, const routine_t *rt) ! 133: { ! 134: if (rt->rtMaxRequestPos > 0) ! 135: fprintf(file, "\tInP = &Mess.In;\n"); ! 136: ! 137: if (rt->rtSimpleFixedRequest) { ! 138: fprintf(file, "\tInP->Head.msgh_bits ="); ! 139: if (!rt->rtSimpleSendRequest) ! 140: fprintf(file, " MACH_MSGH_BITS_COMPLEX|"); ! 141: fprintf(file, "\n"); ! 142: fprintf(file, "\t\tMACH_MSGH_BITS(%s, %s);\n", ! 143: WriteHeaderPortType(rt->rtRequestPort), ! 144: WriteHeaderPortType(rt->rtUReplyPort)); ! 145: } else { ! 146: fprintf(file, "\tInP->Head.msgh_bits = msgh_simple ?\n"); ! 147: fprintf(file, "\t\tMACH_MSGH_BITS(%s, %s) :\n", ! 148: WriteHeaderPortType(rt->rtRequestPort), ! 149: WriteHeaderPortType(rt->rtUReplyPort)); ! 150: fprintf(file, "\t\t(MACH_MSGH_BITS_COMPLEX|\n"); ! 151: fprintf(file, "\t\t MACH_MSGH_BITS(%s, %s));\n", ! 152: WriteHeaderPortType(rt->rtRequestPort), ! 153: WriteHeaderPortType(rt->rtUReplyPort)); ! 154: } ! 155: ! 156: fprintf(file, "\t/* msgh_size passed as argument */\n"); ! 157: ! 158: /* ! 159: * KernelUser stubs need to cast the request and reply ports ! 160: * from ipc_port_t to mach_port_t. ! 161: */ ! 162: ! 163: if (IsKernelUser) ! 164: fprintf(file, "\tInP->%s = (mach_port_t) %s;\n", ! 165: rt->rtRequestPort->argMsgField, ! 166: rt->rtRequestPort->argVarName); ! 167: else ! 168: fprintf(file, "\tInP->%s = %s;\n", ! 169: rt->rtRequestPort->argMsgField, ! 170: rt->rtRequestPort->argVarName); ! 171: ! 172: if (akCheck(rt->rtUReplyPort->argKind, akbUserArg)) { ! 173: if (IsKernelUser) ! 174: fprintf(file, "\tInP->%s = (mach_port_t) %s;\n", ! 175: rt->rtUReplyPort->argMsgField, ! 176: rt->rtUReplyPort->argVarName); ! 177: else ! 178: fprintf(file, "\tInP->%s = %s;\n", ! 179: rt->rtUReplyPort->argMsgField, ! 180: rt->rtUReplyPort->argVarName); ! 181: } else if (rt->rtOneWay || IsKernelUser) ! 182: fprintf(file, "\tInP->%s = MACH_PORT_NULL;\n", ! 183: rt->rtUReplyPort->argMsgField); ! 184: else ! 185: fprintf(file, "\tInP->%s = %smig_get_reply_port();\n", ! 186: rt->rtUReplyPort->argMsgField, SubrPrefix); ! 187: ! 188: fprintf(file, "\tInP->Head.msgh_seqno = 0;\n"); ! 189: fprintf(file, "\tInP->Head.msgh_id = %d;\n", rt->rtNumber + SubsystemBase); ! 190: } ! 191: ! 192: /************************************************************* ! 193: * Writes declarations for the message types, variables ! 194: * and return variable if needed. Called by WriteRoutine. ! 195: *************************************************************/ ! 196: static void ! 197: WriteVarDecls(FILE *file, const routine_t *rt) ! 198: { ! 199: fprintf(file, "\tunion {\n"); ! 200: fprintf(file, "\t\tRequest In;\n"); ! 201: if (!rt->rtOneWay) ! 202: fprintf(file, "\t\tReply Out;\n"); ! 203: fprintf(file, "\t} Mess;\n"); ! 204: fprintf(file, "\n"); ! 205: ! 206: fprintf(file, "\tregister Request *InP = &Mess.In;\n"); ! 207: if (!rt->rtOneWay) ! 208: fprintf(file, "\tregister Reply *OutP = &Mess.Out;\n"); ! 209: fprintf(file, "\n"); ! 210: ! 211: if (!rt->rtOneWay || rt->rtProcedure) ! 212: fprintf(file, "\tmach_msg_return_t msg_result;\n"); ! 213: ! 214: if (!rt->rtSimpleFixedRequest) ! 215: fprintf(file, "\tboolean_t msgh_simple = %s;\n", ! 216: strbool(rt->rtSimpleSendRequest)); ! 217: else if (!rt->rtOneWay && ! 218: !(rt->rtSimpleCheckReply && rt->rtSimpleReceiveReply)) { ! 219: fprintf(file, "#if\tTypeCheck\n"); ! 220: fprintf(file, "\tboolean_t msgh_simple;\n"); ! 221: fprintf(file, "#endif\t/* TypeCheck */\n"); ! 222: } ! 223: ! 224: if (rt->rtNumRequestVar > 0) ! 225: fprintf(file, "\tunsigned int msgh_size;\n"); ! 226: else if (!rt->rtOneWay && !rt->rtNoReplyArgs) ! 227: { ! 228: fprintf(file, "#if\tTypeCheck\n"); ! 229: fprintf(file, "\tunsigned int msgh_size;\n"); ! 230: fprintf(file, "#endif\t/* TypeCheck */\n"); ! 231: } ! 232: ! 233: /* if either request or reply is variable, we need msgh_size_delta */ ! 234: if ((rt->rtMaxRequestPos > 0) || ! 235: (rt->rtMaxReplyPos > 0)) ! 236: fprintf(file, "\tunsigned int msgh_size_delta;\n"); ! 237: ! 238: fprintf(file, "\n"); ! 239: } ! 240: ! 241: /************************************************************* ! 242: * Writes code to call the user provided error procedure ! 243: * when a MIG error occurs. Called by WriteMsgSend, ! 244: * WriteMsgCheckReceive, WriteMsgSendReceive, WriteCheckIdentity, ! 245: * WriteRetCodeCheck, WriteTypeCheck, WritePackArgValue. ! 246: *************************************************************/ ! 247: static void ! 248: WriteMsgError(FILE *file, const routine_t *rt, const char *error_msg) ! 249: { ! 250: if (rt->rtProcedure) ! 251: fprintf(file, "\t\t{ %s(%s); return; }\n", rt->rtErrorName, error_msg); ! 252: else if (rt->rtReturn != rt->rtRetCode) ! 253: { ! 254: fprintf(file, "\t\t{ %s(%s); ", rt->rtErrorName, error_msg); ! 255: if (rt->rtNumReplyVar > 0) ! 256: fprintf(file, "OutP = &Mess.Out; "); ! 257: fprintf(file, "return OutP->%s; }\n", rt->rtReturn->argMsgField); ! 258: } ! 259: else ! 260: fprintf(file, "\t\treturn %s;\n", error_msg); ! 261: } ! 262: ! 263: /************************************************************* ! 264: * Writes the send call when there is to be no subsequent ! 265: * receive. Called by WriteRoutine for SimpleProcedures ! 266: * or SimpleRoutines ! 267: *************************************************************/ ! 268: static void ! 269: WriteMsgSend(FILE *file, const routine_t *rt) ! 270: { ! 271: const char *MsgResult = (rt->rtProcedure) ! 272: ? "msg_result =" ! 273: : "return"; ! 274: ! 275: char SendSize[24]; ! 276: ! 277: if (rt->rtNumRequestVar == 0) ! 278: sprintf(SendSize, "%d", rt->rtRequestSize); ! 279: else ! 280: strcpy(SendSize, "msgh_size"); ! 281: ! 282: if (IsKernelUser) ! 283: { ! 284: fprintf(file, "\t%s %smach_msg_send_from_kernel(", ! 285: MsgResult, SubrPrefix); ! 286: fprintf(file, "&InP->Head, %s);\n", SendSize); ! 287: } ! 288: else ! 289: { ! 290: fprintf(file, "\t%s %smach_msg(&InP->Head, MACH_SEND_MSG|%s, %s, 0,", ! 291: MsgResult, ! 292: SubrPrefix, ! 293: rt->rtMsgOption->argVarName, ! 294: SendSize); ! 295: fprintf(file, ! 296: " MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);\n" ! 297: ); ! 298: } ! 299: ! 300: if (rt->rtProcedure) ! 301: { ! 302: fprintf(file, "\tif (msg_result != MACH_MSG_SUCCESS)\n"); ! 303: WriteMsgError(file, rt, "msg_result"); ! 304: } ! 305: } ! 306: ! 307: /************************************************************* ! 308: * Writes to code to check for error returns from receive. ! 309: * Called by WriteMsgSendReceive and WriteMsgRPC ! 310: *************************************************************/ ! 311: static void ! 312: WriteMsgCheckReceive(FILE *file, const routine_t *rt, const char *success) ! 313: { ! 314: fprintf(file, "\tif (msg_result != %s) {\n", success); ! 315: if (!akCheck(rt->rtUReplyPort->argKind, akbUserArg) && !IsKernelUser) ! 316: { ! 317: /* If we aren't using a user-supplied reply port, ! 318: then deallocate the reply port on any message transmission ! 319: errors. */ ! 320: fprintf(file, "\t\t%smig_dealloc_reply_port(%s);\n", ! 321: SubrPrefix, "InP->Head.msgh_reply_port"); ! 322: } ! 323: WriteMsgError(file, rt, "msg_result"); ! 324: fprintf(file, "\t}\n"); ! 325: ! 326: /* ! 327: * If not using a user supplied reply port, tell the port ! 328: * allocator we're done with the port. ! 329: */ ! 330: if (!akCheck(rt->rtUReplyPort->argKind, akbUserArg) && !IsKernelUser) ! 331: { ! 332: fprintf(file, "\t%smig_put_reply_port(InP->Head.msgh_reply_port);\n", ! 333: SubrPrefix); ! 334: } ! 335: } ! 336: ! 337: /************************************************************* ! 338: * Writes the send and receive calls and code to check ! 339: * for errors. Normally the rpc code is generated instead ! 340: * although, the subsytem can be compiled with the -R option ! 341: * which will cause this code to be generated. Called by ! 342: * WriteRoutine if UseMsgRPC option is false. ! 343: *************************************************************/ ! 344: static void ! 345: WriteMsgSendReceive(FILE *file, const routine_t *rt) ! 346: { ! 347: char SendSize[24]; ! 348: ! 349: if (rt->rtNumRequestVar == 0) ! 350: sprintf(SendSize, "%d", rt->rtRequestSize); ! 351: else ! 352: strcpy(SendSize, "msgh_size"); ! 353: ! 354: fprintf(file, "\tmsg_result = %smach_msg(&InP->Head, MACH_SEND_MSG|%s, %s, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);\n", ! 355: SubrPrefix, ! 356: rt->rtMsgOption->argVarName, ! 357: SendSize); ! 358: ! 359: fprintf(file, "\tif (msg_result != MACH_MSG_SUCCESS)\n"); ! 360: WriteMsgError(file, rt, "msg_result"); ! 361: fprintf(file, "\n"); ! 362: ! 363: fprintf(file, "\tmsg_result = %smach_msg(&OutP->Head, MACH_RCV_MSG|%s%s, 0, sizeof(Reply), InP->Head.msgh_local_port, %s, MACH_PORT_NULL);\n", ! 364: SubrPrefix, ! 365: rt->rtMsgOption->argVarName, ! 366: rt->rtWaitTime != argNULL ? "|MACH_RCV_TIMEOUT" : "", ! 367: rt->rtWaitTime != argNULL ? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE"); ! 368: WriteMsgCheckReceive(file, rt, "MACH_MSG_SUCCESS"); ! 369: fprintf(file, "\n"); ! 370: } ! 371: ! 372: /************************************************************* ! 373: * Writes the rpc call and the code to check for errors. ! 374: * This is the default code to be generated. Called by WriteRoutine ! 375: * for all routine types except SimpleProcedure and SimpleRoutine. ! 376: *************************************************************/ ! 377: static void ! 378: WriteMsgRPC(FILE *file, const routine_t *rt) ! 379: { ! 380: char SendSize[24]; ! 381: ! 382: if (rt->rtNumRequestVar == 0) ! 383: sprintf(SendSize, "%d", rt->rtRequestSize); ! 384: else ! 385: strcpy(SendSize, "msgh_size"); ! 386: ! 387: if (IsKernelUser) ! 388: fprintf(file, "\tmsg_result = %smach_msg_rpc_from_kernel(&InP->Head, %s, sizeof(Reply));\n", ! 389: SubrPrefix, ! 390: SendSize); ! 391: else ! 392: fprintf(file, "\tmsg_result = %smach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|%s%s, %s, sizeof(Reply), InP->Head.msgh_reply_port, %s, MACH_PORT_NULL);\n", ! 393: SubrPrefix, ! 394: rt->rtMsgOption->argVarName, ! 395: rt->rtWaitTime != argNULL ? "|MACH_RCV_TIMEOUT" : "", ! 396: SendSize, ! 397: rt->rtWaitTime != argNULL? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE"); ! 398: WriteMsgCheckReceive(file, rt, "MACH_MSG_SUCCESS"); ! 399: fprintf(file, "\n"); ! 400: } ! 401: ! 402: /************************************************************* ! 403: * Sets the correct value of the dealloc flag and calls ! 404: * Utils:WritePackMsgType to fill in the ipc msg type word(s) ! 405: * in the request message. Called by WriteRoutine for each ! 406: * argument that is to be sent in the request message. ! 407: *************************************************************/ ! 408: static void ! 409: WritePackArgType(FILE *file, const argument_t *arg) ! 410: { ! 411: WritePackMsgType(file, arg->argType, ! 412: arg->argType->itIndefinite ? d_NO : arg->argDeallocate, ! 413: arg->argLongForm, TRUE, ! 414: "InP->%s", "%s", arg->argTTName); ! 415: fprintf(file, "\n"); ! 416: } ! 417: ! 418: /************************************************************* ! 419: * Writes code to copy an argument into the request message. ! 420: * Called by WriteRoutine for each argument that is to placed ! 421: * in the request message. ! 422: *************************************************************/ ! 423: static void ! 424: WritePackArgValue(FILE *file, register const argument_t *arg) ! 425: { ! 426: register const ipc_type_t *it = arg->argType; ! 427: register const char *ref = arg->argByReferenceUser ? "*" : ""; ! 428: ! 429: if (it->itInLine && it->itVarArray) { ! 430: ! 431: if (it->itString) { ! 432: /* ! 433: * Copy variable-size C string with mig_strncpy. ! 434: * Save the string length (+ 1 for trailing 0) ! 435: * in the argument`s count field. ! 436: */ ! 437: fprintf(file, ! 438: "\tInP->%s = %smig_strncpy(InP->%s, %s, %d);\n", ! 439: arg->argCount->argMsgField, ! 440: SubrPrefix, ! 441: arg->argMsgField, ! 442: arg->argVarName, ! 443: it->itNumber); ! 444: } ! 445: else { ! 446: ! 447: /* ! 448: * Copy in variable-size inline array with memcpy, ! 449: * after checking that number of elements doesn`t ! 450: * exceed declared maximum. ! 451: */ ! 452: register const argument_t *count = arg->argCount; ! 453: register const char *countRef = count->argByReferenceUser ? "*" :""; ! 454: register const ipc_type_t *btype = it->itElement; ! 455: ! 456: /* Note btype->itNumber == count->argMultiplier */ ! 457: ! 458: fprintf(file, "\tif (%s%s > %d) {\n", ! 459: countRef, count->argVarName, ! 460: it->itNumber/btype->itNumber); ! 461: if (it->itIndefinite) { ! 462: fprintf(file, "\t\tInP->%s%s.msgt_inline = FALSE;\n", ! 463: arg->argTTName, ! 464: arg->argLongForm ? ".msgtl_header" : ""); ! 465: if (arg->argDeallocate == d_YES) ! 466: fprintf(file, "\t\tInP->%s%s.msgt_deallocate = TRUE;\n", ! 467: arg->argTTName, ! 468: arg->argLongForm ? ".msgtl_header" : ""); ! 469: else if (arg->argDeallocate == d_MAYBE) ! 470: fprintf(file, "\t\tInP->%s%s.msgt_deallocate = %s%s;\n", ! 471: arg->argTTName, ! 472: arg->argLongForm ? ".msgtl_header" : "", ! 473: arg->argDealloc->argByReferenceUser ? "*" : "", ! 474: arg->argDealloc->argVarName); ! 475: fprintf(file, "\t\t*((%s **)InP->%s) = %s%s;\n", ! 476: FetchUserType(btype), ! 477: arg->argMsgField, ! 478: ref, arg->argVarName); ! 479: if (!arg->argRoutine->rtSimpleFixedRequest) ! 480: fprintf(file, "\t\tmsgh_simple = FALSE;\n"); ! 481: } ! 482: else ! 483: WriteMsgError(file, arg->argRoutine, "MIG_ARRAY_TOO_LARGE"); ! 484: ! 485: fprintf(file, "\t}\n\telse {\n"); ! 486: ! 487: fprintf(file, "\t\tmemcpy(InP->%s, %s%s, ", arg->argMsgField, ! 488: ref, arg->argVarName); ! 489: if (btype->itTypeSize > 1) ! 490: fprintf(file, "%d * ", btype->itTypeSize); ! 491: fprintf(file, "%s%s);\n", ! 492: countRef, count->argVarName); ! 493: fprintf(file, "\t}\n"); ! 494: } ! 495: } ! 496: else if (arg->argMultiplier > 1) ! 497: WriteCopyType(file, it, "InP->%s", "/* %s */ %d * %s%s", ! 498: arg->argMsgField, arg->argMultiplier, ! 499: ref, arg->argVarName); ! 500: else ! 501: WriteCopyType(file, it, "InP->%s", "/* %s */ %s%s", ! 502: arg->argMsgField, ref, arg->argVarName); ! 503: fprintf(file, "\n"); ! 504: } ! 505: ! 506: static void ! 507: WriteAdjustMsgSimple(FILE *file, register const argument_t *arg) ! 508: { ! 509: if (!arg->argRoutine->rtSimpleFixedRequest) ! 510: { ! 511: register const char *ref = arg->argByReferenceUser ? "*" : ""; ! 512: ! 513: fprintf(file, "\tif (MACH_MSG_TYPE_PORT_ANY(%s%s))\n", ! 514: ref, arg->argVarName); ! 515: fprintf(file, "\t\tmsgh_simple = FALSE;\n"); ! 516: fprintf(file, "\n"); ! 517: } ! 518: } ! 519: ! 520: /* ! 521: * Calculate the size of a variable-length message field. ! 522: */ ! 523: static void ! 524: WriteArgSize(FILE *file, register const argument_t *arg) ! 525: { ! 526: register const ipc_type_t *ptype = arg->argType; ! 527: register int bsize = ptype->itElement->itTypeSize; ! 528: register const argument_t *count = arg->argCount; ! 529: ! 530: if (ptype->itIndefinite) { ! 531: /* ! 532: * Check descriptor. If out-of-line, use standard size. ! 533: */ ! 534: fprintf(file, "(InP->%s%s.msgt_inline) ? ", ! 535: arg->argTTName, arg->argLongForm ? ".msgtl_header" : ""); ! 536: } ! 537: if (bsize % 4 != 0) ! 538: fprintf(file, "("); ! 539: ! 540: if (bsize > 1) ! 541: fprintf(file, "%d * ", bsize); ! 542: ! 543: if (ptype->itString) ! 544: /* get count from descriptor in message */ ! 545: fprintf(file, "InP->%s", count->argMsgField); ! 546: else ! 547: /* get count from argument */ ! 548: fprintf(file, "%s%s", ! 549: count->argByReferenceUser ? "*" : "", ! 550: count->argVarName); ! 551: ! 552: /* ! 553: * If the base type size is not a multiple of sizeof(int) [4], ! 554: * we have to round up. ! 555: */ ! 556: if (bsize % 4 != 0) ! 557: fprintf(file, " + 3) & ~3"); ! 558: ! 559: if (ptype->itIndefinite) { ! 560: fprintf(file, " : sizeof(%s *)", ! 561: FetchUserType(ptype->itElement)); ! 562: } ! 563: } ! 564: ! 565: /* ! 566: * Adjust message size and advance request pointer. ! 567: * Called after packing a variable-length argument that ! 568: * has more arguments following. ! 569: */ ! 570: static void ! 571: WriteAdjustMsgSize(FILE *file, register const argument_t *arg) ! 572: { ! 573: register const ipc_type_t *ptype = arg->argType; ! 574: ! 575: /* There are more In arguments. We need to adjust msgh_size ! 576: and advance InP, so we save the size of the current field ! 577: in msgh_size_delta. */ ! 578: ! 579: fprintf(file, "\tmsgh_size_delta = "); ! 580: WriteArgSize(file, arg); ! 581: fprintf(file, ";\n"); ! 582: ! 583: if (arg->argRequestPos == 0) ! 584: /* First variable-length argument. The previous msgh_size value ! 585: is the minimum request size. */ ! 586: ! 587: fprintf(file, "\tmsgh_size = %d + msgh_size_delta;\n", ! 588: arg->argRoutine->rtRequestSize); ! 589: else ! 590: fprintf(file, "\tmsgh_size += msgh_size_delta;\n"); ! 591: ! 592: fprintf(file, ! 593: "\tInP = (Request *) ((char *) InP + msgh_size_delta - %d);\n", ! 594: ptype->itTypeSize + ptype->itPadSize); ! 595: } ! 596: ! 597: /* ! 598: * Calculate the size of the message. Called after the ! 599: * last argument has been packed. ! 600: */ ! 601: static void ! 602: WriteFinishMsgSize(FILE *file, register const argument_t *arg) ! 603: { ! 604: /* No more In arguments. If this is the only variable In ! 605: argument, the previous msgh_size value is the minimum ! 606: request size. */ ! 607: ! 608: if (arg->argRequestPos == 0) { ! 609: fprintf(file, "\tmsgh_size = %d + (", ! 610: arg->argRoutine->rtRequestSize); ! 611: WriteArgSize(file, arg); ! 612: fprintf(file, ");\n"); ! 613: } ! 614: else { ! 615: fprintf(file, "\tmsgh_size += "); ! 616: WriteArgSize(file, arg); ! 617: fprintf(file, ";\n"); ! 618: } ! 619: } ! 620: ! 621: static void ! 622: WriteInitializeCount(FILE *file, register const argument_t *arg) ! 623: { ! 624: register const ipc_type_t *ptype = arg->argCInOut->argParent->argType; ! 625: register const ipc_type_t *btype = ptype->itElement; ! 626: ! 627: fprintf(file, "\tif (%s%s < %d)\n", ! 628: arg->argByReferenceUser ? "*" : "", ! 629: arg->argVarName, ! 630: ptype->itNumber/btype->itNumber); ! 631: fprintf(file, "\t\tInP->%s = %s%s;\n", ! 632: arg->argMsgField, ! 633: arg->argByReferenceUser ? "*" : "", ! 634: arg->argVarName); ! 635: fprintf(file, "\telse\n"); ! 636: fprintf(file, "\t\tInP->%s = %d;\n", ! 637: arg->argMsgField, ptype->itNumber/btype->itNumber); ! 638: fprintf(file, "\n"); ! 639: } ! 640: ! 641: /* ! 642: * Called for every argument. Responsible for packing that ! 643: * argument into the request message. ! 644: */ ! 645: static void ! 646: WritePackArg(FILE *file, register const argument_t *arg) ! 647: { ! 648: if (akCheck(arg->argKind, akbRequest)) ! 649: WritePackArgType(file, arg); ! 650: ! 651: if ((akIdent(arg->argKind) == akePoly) && ! 652: akCheckAll(arg->argKind, akbSendSnd|akbUserArg)) ! 653: WriteAdjustMsgSimple(file, arg); ! 654: ! 655: if ((akIdent(arg->argKind) == akeCountInOut) && ! 656: akCheck(arg->argKind, akbSendSnd)) ! 657: WriteInitializeCount(file, arg); ! 658: else if (akCheckAll(arg->argKind, akbSendSnd|akbSendBody)) ! 659: WritePackArgValue(file, arg); ! 660: } ! 661: ! 662: /* ! 663: * Generate code to fill in all of the request arguments and their ! 664: * message types. ! 665: */ ! 666: static void ! 667: WriteRequestArgs(FILE *file, register const routine_t *rt) ! 668: { ! 669: register const argument_t *arg; ! 670: register const argument_t *lastVarArg; ! 671: ! 672: lastVarArg = argNULL; ! 673: for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) ! 674: { ! 675: /* ! 676: * Adjust message size and advance message pointer if ! 677: * the last request argument was variable-length and the ! 678: * request position will change. ! 679: */ ! 680: if (lastVarArg != argNULL && ! 681: lastVarArg->argRequestPos < arg->argRequestPos) ! 682: { ! 683: WriteAdjustMsgSize(file, lastVarArg); ! 684: lastVarArg = argNULL; ! 685: } ! 686: ! 687: /* ! 688: * Copy the argument ! 689: */ ! 690: WritePackArg(file, arg); ! 691: ! 692: /* ! 693: * Remember whether this was variable-length. ! 694: */ ! 695: if (akCheckAll(arg->argKind, akbSendSnd|akbSendBody|akbVariable)) ! 696: lastVarArg = arg; ! 697: } ! 698: ! 699: /* ! 700: * Finish the message size. ! 701: */ ! 702: if (lastVarArg != argNULL) ! 703: WriteFinishMsgSize(file, lastVarArg); ! 704: } ! 705: ! 706: /************************************************************* ! 707: * Writes code to check that the return msgh_id is correct and that ! 708: * the size of the return message is correct. Called by ! 709: * WriteRoutine. ! 710: *************************************************************/ ! 711: static void ! 712: WriteCheckIdentity(FILE *file, const routine_t *rt) ! 713: { ! 714: fprintf(file, "\tif (OutP->Head.msgh_id != %d) {\n", ! 715: rt->rtNumber + SubsystemBase + 100); ! 716: fprintf(file, "\t\tif (OutP->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)\n"); ! 717: WriteMsgError(file, rt, "MIG_SERVER_DIED"); ! 718: fprintf(file, "\t\telse {\n"); ! 719: fprintf(file, "\t\t\t%smig_dealloc_reply_port(%s);\n\t", ! 720: SubrPrefix,"InP->Head.msgh_reply_port"); ! 721: WriteMsgError(file, rt, "MIG_REPLY_MISMATCH"); ! 722: fprintf(file, "\t\t}\n\t}\n"); ! 723: fprintf(file, "\n"); ! 724: fprintf(file, "#if\tTypeCheck\n"); ! 725: ! 726: if (rt->rtSimpleCheckReply && rt->rtSimpleReceiveReply) ! 727: { ! 728: /* Expecting a simple message. We can factor out the check for ! 729: a simple message, since the error reply message is also simple. ! 730: */ ! 731: ! 732: if (!rt->rtNoReplyArgs) ! 733: fprintf(file, "\tmsgh_size = OutP->Head.msgh_size;\n\n"); ! 734: ! 735: fprintf(file, ! 736: "\tif ((OutP->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n"); ! 737: if (rt->rtNoReplyArgs) ! 738: fprintf(file, "\t (OutP->Head.msgh_size != %d))\n", ! 739: rt->rtReplySize); ! 740: else { ! 741: fprintf(file, "\t ((msgh_size %s %d) &&\n", ! 742: (rt->rtNumReplyVar > 0) ? "<" : "!=", ! 743: rt->rtReplySize); ! 744: fprintf(file, "\t ((msgh_size != sizeof(mig_reply_header_t)) ||\n"); ! 745: fprintf(file, "\t (OutP->RetCode == KERN_SUCCESS))))\n"); ! 746: } ! 747: } ! 748: else { ! 749: /* Expecting a complex message, or may vary at run time. */ ! 750: ! 751: fprintf(file, "\tmsgh_size = OutP->Head.msgh_size;\n"); ! 752: fprintf(file, "\tmsgh_simple = !(OutP->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);\n"); ! 753: fprintf(file, "\n"); ! 754: ! 755: fprintf(file, "\tif (((msgh_size %s %d)", ! 756: (rt->rtNumReplyVar > 0) ? "<" : "!=", ! 757: rt->rtReplySize); ! 758: ! 759: if (rt->rtSimpleCheckReply) ! 760: /* if rtSimpleReceiveReply was true, then we would have ! 761: executed the code above. So we know that the message ! 762: is complex. */ ! 763: fprintf(file, " || msgh_simple"); ! 764: fprintf(file, ") &&\n"); ! 765: ! 766: fprintf(file, "\t ((msgh_size != sizeof(mig_reply_header_t)) ||\n"); ! 767: fprintf(file, "\t !msgh_simple ||\n"); ! 768: fprintf(file, "\t (OutP->RetCode == KERN_SUCCESS)))\n"); ! 769: } ! 770: WriteMsgError(file, rt, "MIG_TYPE_ERROR"); ! 771: fprintf(file, "#endif\t/* TypeCheck */\n"); ! 772: fprintf(file, "\n"); ! 773: } ! 774: ! 775: /************************************************************* ! 776: * Write code to generate error handling code if the RetCode ! 777: * argument of a Routine is not KERN_SUCCESS. ! 778: *************************************************************/ ! 779: static void ! 780: WriteRetCodeCheck(FILE *file, const routine_t *rt) ! 781: { ! 782: fprintf(file, "\tif (OutP->RetCode != KERN_SUCCESS)\n"); ! 783: WriteMsgError(file, rt, "OutP->RetCode"); ! 784: fprintf(file, "\n"); ! 785: } ! 786: ! 787: /************************************************************* ! 788: * Writes code to check that the type of each of the arguments ! 789: * in the reply message is what is expected. Called by ! 790: * WriteRoutine for each argument in the reply message. ! 791: *************************************************************/ ! 792: static void ! 793: WriteTypeCheck(FILE *file, register const argument_t *arg) ! 794: { ! 795: register const ipc_type_t *it = arg->argType; ! 796: register const routine_t *rt = arg->argRoutine; ! 797: ! 798: fprintf(file, "#if\tTypeCheck\n"); ! 799: if (akCheck(arg->argKind, akbReplyQC)) ! 800: { ! 801: fprintf(file, "\tif (* (int *) &OutP->%s != * (int *) &%sCheck)\n", ! 802: arg->argTTName, arg->argVarName); ! 803: } ! 804: else ! 805: { ! 806: fprintf(file, "\tif ("); ! 807: if (!it->itIndefinite) { ! 808: fprintf(file, "(OutP->%s%s.msgt_inline != %s) ||\n\t ", ! 809: arg->argTTName, ! 810: arg->argLongForm ? ".msgtl_header" : "", ! 811: strbool(it->itInLine)); ! 812: } ! 813: fprintf(file, "(OutP->%s%s.msgt_longform != %s) ||\n", ! 814: arg->argTTName, ! 815: arg->argLongForm ? ".msgtl_header" : "", ! 816: strbool(arg->argLongForm)); ! 817: if (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC) ! 818: { ! 819: if (!rt->rtSimpleCheckReply) ! 820: fprintf(file, "\t (MACH_MSG_TYPE_PORT_ANY(OutP->%s.msgt%s_name) && msgh_simple) ||\n", ! 821: arg->argTTName, ! 822: arg->argLongForm ? "l" : ""); ! 823: } ! 824: else ! 825: fprintf(file, "\t (OutP->%s.msgt%s_name != %s) ||\n", ! 826: arg->argTTName, ! 827: arg->argLongForm ? "l" : "", ! 828: it->itOutNameStr); ! 829: if (!it->itVarArray) ! 830: fprintf(file, "\t (OutP->%s.msgt%s_number != %d) ||\n", ! 831: arg->argTTName, ! 832: arg->argLongForm ? "l" : "", ! 833: it->itNumber); ! 834: fprintf(file, "\t (OutP->%s.msgt%s_size != %d))\n", ! 835: arg->argTTName, ! 836: arg->argLongForm ? "l" : "", ! 837: it->itSize); ! 838: } ! 839: WriteMsgError(file, rt, "MIG_TYPE_ERROR"); ! 840: fprintf(file, "#endif\t/* TypeCheck */\n"); ! 841: fprintf(file, "\n"); ! 842: } ! 843: ! 844: static void ! 845: WriteCheckArgSize(FILE *file, register const argument_t *arg) ! 846: { ! 847: register const ipc_type_t *ptype = arg->argType; ! 848: register const ipc_type_t *btype = ptype->itElement; ! 849: const argument_t *count = arg->argCount; ! 850: int multiplier = btype->itTypeSize / btype->itNumber; ! 851: ! 852: if (ptype->itIndefinite) { ! 853: /* ! 854: * Check descriptor. If out-of-line, use standard size. ! 855: */ ! 856: fprintf(file, "(OutP->%s%s.msgt_inline) ? ", ! 857: arg->argTTName, arg->argLongForm ? ".msgtl_header" : ""); ! 858: } ! 859: ! 860: if (btype->itTypeSize % 4 != 0) ! 861: fprintf(file, "("); ! 862: ! 863: if (multiplier > 1) ! 864: fprintf(file, "%d * ", multiplier); ! 865: ! 866: fprintf(file, "OutP->%s", count->argMsgField); ! 867: ! 868: /* If the base type size of the data field isn`t a multiple of 4, ! 869: we have to round up. */ ! 870: if (btype->itTypeSize % 4 != 0) ! 871: fprintf(file, " + 3) & ~3"); ! 872: ! 873: if (ptype->itIndefinite) ! 874: fprintf(file, " : sizeof(%s *)", FetchUserType(btype)); ! 875: } ! 876: ! 877: static void ! 878: WriteCheckMsgSize(FILE *file, register const argument_t *arg) ! 879: { ! 880: register const routine_t *rt = arg->argRoutine; ! 881: ! 882: /* If there aren't any more Out args after this, then ! 883: we can use the msgh_size_delta value directly in ! 884: the TypeCheck conditional. */ ! 885: ! 886: if (arg->argReplyPos == rt->rtMaxReplyPos) ! 887: { ! 888: fprintf(file, "#if\tTypeCheck\n"); ! 889: fprintf(file, "\tif (msgh_size != %d + (", ! 890: rt->rtReplySize); ! 891: WriteCheckArgSize(file, arg); ! 892: fprintf(file, "))\n"); ! 893: ! 894: WriteMsgError(file, rt, "MIG_TYPE_ERROR"); ! 895: fprintf(file, "#endif\t/* TypeCheck */\n"); ! 896: } ! 897: else ! 898: { ! 899: /* If there aren't any more variable-sized arguments after this, ! 900: then we must check for exact msg-size and we don't need ! 901: to update msgh_size. */ ! 902: ! 903: boolean_t LastVarArg = arg->argReplyPos+1 == rt->rtNumReplyVar; ! 904: ! 905: /* calculate the actual size in bytes of the data field. note ! 906: that this quantity must be a multiple of four. hence, if ! 907: the base type size isn't a multiple of four, we have to ! 908: round up. note also that btype->itNumber must ! 909: divide btype->itTypeSize (see itCalculateSizeInfo). */ ! 910: ! 911: fprintf(file, "\tmsgh_size_delta = "); ! 912: WriteCheckArgSize(file, arg); ! 913: fprintf(file, ";\n"); ! 914: fprintf(file, "#if\tTypeCheck\n"); ! 915: ! 916: /* Don't decrement msgh_size until we've checked that ! 917: it won't underflow. */ ! 918: ! 919: if (LastVarArg) ! 920: fprintf(file, "\tif (msgh_size != %d + msgh_size_delta)\n", ! 921: rt->rtReplySize); ! 922: else ! 923: fprintf(file, "\tif (msgh_size < %d + msgh_size_delta)\n", ! 924: rt->rtReplySize); ! 925: WriteMsgError(file, rt, "MIG_TYPE_ERROR"); ! 926: ! 927: if (!LastVarArg) ! 928: fprintf(file, "\tmsgh_size -= msgh_size_delta;\n"); ! 929: ! 930: fprintf(file, "#endif\t/* TypeCheck */\n"); ! 931: } ! 932: fprintf(file, "\n"); ! 933: } ! 934: ! 935: /************************************************************* ! 936: * Write code to copy an argument from the reply message ! 937: * to the parameter. Called by WriteRoutine for each argument ! 938: * in the reply message. ! 939: *************************************************************/ ! 940: static void ! 941: WriteExtractArgValue(FILE *file, register const argument_t *arg) ! 942: { ! 943: register const ipc_type_t *argType = arg->argType; ! 944: register const char *ref = arg->argByReferenceUser ? "*" : ""; ! 945: ! 946: if (argType->itInLine && argType->itVarArray) { ! 947: ! 948: if (argType->itString) { ! 949: /* ! 950: * Copy out variable-size C string with mig_strncpy. ! 951: */ ! 952: fprintf(file, "\t(void) %smig_strncpy(%s%s, OutP->%s, %d);\n", ! 953: SubrPrefix, ! 954: ref, ! 955: arg->argVarName, ! 956: arg->argMsgField, ! 957: argType->itNumber); ! 958: } ! 959: else if (argType->itIndefinite) { ! 960: /* ! 961: * If data was returned out-of-line, ! 962: * change user`s pointer to point to it. ! 963: * If data was returned in-line but doesn`t fit, ! 964: * allocate a new buffer, copy the data to it, ! 965: * and change user`s pointer to point to it. ! 966: * If data was returned in-line and fits, ! 967: * copy to buffer. ! 968: */ ! 969: const argument_t *count = arg->argCount; ! 970: const char *countRef = count->argByReferenceUser ? "*" : ""; ! 971: const ipc_type_t *btype = argType->itElement; ! 972: ! 973: fprintf(file, "\tif (!OutP->%s%s.msgt_inline)\n", ! 974: arg->argTTName, ! 975: arg->argLongForm ? ".msgtl_header" : ""); ! 976: fprintf(file, "\t %s%s = *((%s **)OutP->%s);\n", ! 977: ref, arg->argVarName, ! 978: FetchUserType(btype), arg->argMsgField); ! 979: fprintf(file, "\telse if (OutP->%s", count->argMsgField); ! 980: if (btype->itNumber > 1) ! 981: fprintf(file, " / %d", btype->itNumber); ! 982: fprintf(file, " > %s%s) {\n", countRef, count->argVarName); ! 983: fprintf(file, "\t %smig_allocate((vm_offset_t *)%s,\n\t\t", ! 984: SubrPrefix, arg->argVarName); /* no ref! */ ! 985: if (btype->itTypeSize != btype->itNumber) ! 986: fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber); ! 987: fprintf(file, "OutP->%s);\n", count->argMsgField); ! 988: fprintf(file, "\t memcpy(%s%s, OutP->%s, ", ref, arg->argVarName, ! 989: arg->argMsgField); ! 990: if (btype->itTypeSize != btype->itNumber) ! 991: fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber); ! 992: fprintf(file, "OutP->%s);\n", count->argMsgField); ! 993: fprintf(file, "\t}\n"); ! 994: fprintf(file, "\telse {\n"); ! 995: ! 996: fprintf(file, "\t memcpy(%s%s, OutP->%s, ", ref, arg->argVarName, ! 997: arg->argMsgField); ! 998: if (btype->itTypeSize != btype->itNumber) ! 999: fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber); ! 1000: fprintf(file, "OutP->%s);\n", count->argMsgField); ! 1001: fprintf(file, "\t}\n"); ! 1002: } ! 1003: else { ! 1004: ! 1005: /* ! 1006: * Copy out variable-size inline array with memcpy, ! 1007: * after checking that number of elements doesn`t ! 1008: * exceed user`s maximum. ! 1009: */ ! 1010: register const argument_t *count = arg->argCount; ! 1011: register const char *countRef = count->argByReferenceUser ? "*" :""; ! 1012: register const ipc_type_t *btype = argType->itElement; ! 1013: ! 1014: /* Note count->argMultiplier == btype->itNumber */ ! 1015: ! 1016: fprintf(file, "\tif (OutP->%s", count->argMsgField); ! 1017: if (btype->itNumber > 1) ! 1018: fprintf(file, " / %d", btype->itNumber); ! 1019: fprintf(file, " > %s%s) {\n", ! 1020: countRef, count->argVarName); ! 1021: ! 1022: /* ! 1023: * If number of elements is too many for user receiving area, ! 1024: * fill user`s area as much as possible. Return the correct ! 1025: * number of elements. ! 1026: */ ! 1027: fprintf(file, "\t\tmemcpy(%s%s, OutP->%s, ", ref, arg->argVarName, ! 1028: arg->argMsgField); ! 1029: if (btype->itTypeSize > 1) ! 1030: fprintf(file, "%d * ", btype->itTypeSize); ! 1031: fprintf(file, "%s%s);\n", ! 1032: countRef, count->argVarName); ! 1033: ! 1034: fprintf(file, "\t\t%s%s = OutP->%s", ! 1035: countRef, count->argVarName, count->argMsgField); ! 1036: if (btype->itNumber > 1) ! 1037: fprintf(file, " / %d", btype->itNumber); ! 1038: fprintf(file, ";\n"); ! 1039: WriteMsgError(file,arg->argRoutine, "MIG_ARRAY_TOO_LARGE"); ! 1040: ! 1041: fprintf(file, "\t}\n\telse {\n"); ! 1042: ! 1043: fprintf(file, "\t\tmemcpy(%s%s, OutP->%s, ", ref, arg->argVarName, ! 1044: arg->argMsgField); ! 1045: if (btype->itTypeSize != btype->itNumber) ! 1046: fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber); ! 1047: fprintf(file, "OutP->%s);\n", count->argMsgField); ! 1048: fprintf(file, "\t}\n"); ! 1049: } ! 1050: } ! 1051: else if (arg->argMultiplier > 1) ! 1052: WriteCopyType(file, argType, ! 1053: "%s%s", "/* %s%s */ OutP->%s / %d", ! 1054: ref, arg->argVarName, arg->argMsgField, ! 1055: arg->argMultiplier); ! 1056: else ! 1057: WriteCopyType(file, argType, ! 1058: "%s%s", "/* %s%s */ OutP->%s", ! 1059: ref, arg->argVarName, arg->argMsgField); ! 1060: fprintf(file, "\n"); ! 1061: } ! 1062: ! 1063: static void ! 1064: WriteExtractArg(FILE *file, register const argument_t *arg) ! 1065: { ! 1066: register const routine_t *rt = arg->argRoutine; ! 1067: ! 1068: if (akCheck(arg->argKind, akbReply)) ! 1069: WriteTypeCheck(file, arg); ! 1070: ! 1071: if (akCheckAll(arg->argKind, akbVariable|akbReply)) ! 1072: WriteCheckMsgSize(file, arg); ! 1073: ! 1074: /* Now that the RetCode is type-checked, check its value. ! 1075: Must abort immediately if it isn't KERN_SUCCESS, because ! 1076: in that case the reply message is truncated. */ ! 1077: ! 1078: if (arg == rt->rtRetCode) ! 1079: WriteRetCodeCheck(file, rt); ! 1080: ! 1081: if (akCheckAll(arg->argKind, akbReturnRcv)) ! 1082: WriteExtractArgValue(file, arg); ! 1083: } ! 1084: ! 1085: static void ! 1086: WriteAdjustReplyMsgPtr(FILE *file, register const argument_t *arg) ! 1087: { ! 1088: register const ipc_type_t *ptype = arg->argType; ! 1089: ! 1090: fprintf(file, ! 1091: "\tOutP = (Reply *) ((char *) OutP + msgh_size_delta - %d);\n\n", ! 1092: ptype->itTypeSize + ptype->itPadSize); ! 1093: } ! 1094: ! 1095: static void ! 1096: WriteReplyArgs(FILE *file, register const routine_t *rt) ! 1097: { ! 1098: register const argument_t *arg; ! 1099: register const argument_t *lastVarArg; ! 1100: ! 1101: lastVarArg = argNULL; ! 1102: for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { ! 1103: ! 1104: /* ! 1105: * Advance message pointer if the last reply argument was ! 1106: * variable-length and the reply position will change. ! 1107: */ ! 1108: if (lastVarArg != argNULL && ! 1109: lastVarArg->argReplyPos < arg->argReplyPos) ! 1110: { ! 1111: WriteAdjustReplyMsgPtr(file, lastVarArg); ! 1112: lastVarArg = argNULL; ! 1113: } ! 1114: ! 1115: /* ! 1116: * Copy the argument ! 1117: */ ! 1118: WriteExtractArg(file, arg); ! 1119: ! 1120: /* ! 1121: * Remember whether this was variable-length. ! 1122: */ ! 1123: if (akCheckAll(arg->argKind, akbReturnRcv|akbVariable)) ! 1124: lastVarArg = arg; ! 1125: } ! 1126: } ! 1127: ! 1128: /************************************************************* ! 1129: * Writes code to return the return value. Called by WriteRoutine ! 1130: * for routines and functions. ! 1131: *************************************************************/ ! 1132: static void ! 1133: WriteReturnValue(FILE *file, const routine_t *rt) ! 1134: { ! 1135: if (rt->rtReturn == rt->rtRetCode) ! 1136: /* If returning RetCode, we have already checked that it is ! 1137: KERN_SUCCESS */ ! 1138: fprintf(file, "\treturn KERN_SUCCESS;\n"); ! 1139: ! 1140: else ! 1141: { ! 1142: if (rt->rtNumReplyVar > 0) ! 1143: fprintf(file, "\tOutP = &Mess.Out;\n"); ! 1144: ! 1145: fprintf(file, "\treturn OutP->%s;\n", rt->rtReturn->argMsgField); ! 1146: } ! 1147: } ! 1148: ! 1149: /************************************************************* ! 1150: * Writes the elements of the message type declaration: the ! 1151: * msg_type structure, the argument itself and any padding ! 1152: * that is required to make the argument a multiple of 4 bytes. ! 1153: * Called by WriteRoutine for all the arguments in the request ! 1154: * message first and then the reply message. ! 1155: *************************************************************/ ! 1156: static void ! 1157: WriteFieldDecl(FILE *file, const argument_t *arg) ! 1158: { ! 1159: WriteFieldDeclPrim(file, arg, FetchUserType); ! 1160: } ! 1161: ! 1162: static void ! 1163: WriteStubDecl(FILE *file, register const routine_t *rt) ! 1164: { ! 1165: fprintf(file, "\n"); ! 1166: fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName); ! 1167: fprintf(file, "mig_external %s %s\n", ReturnTypeStr(rt), rt->rtUserName); ! 1168: fprintf(file, "(\n"); ! 1169: WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n"); ! 1170: fprintf(file, ")\n"); ! 1171: fprintf(file, "{\n"); ! 1172: } ! 1173: ! 1174: /************************************************************* ! 1175: * Writes all the code comprising a routine body. Called by ! 1176: * WriteUser for each routine. ! 1177: *************************************************************/ ! 1178: static void ! 1179: WriteRoutine(FILE *file, register const routine_t *rt) ! 1180: { ! 1181: /* write the stub's declaration */ ! 1182: ! 1183: WriteStubDecl(file, rt); ! 1184: ! 1185: /* typedef of structure for Request and Reply messages */ ! 1186: ! 1187: WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request"); ! 1188: if (!rt->rtOneWay) ! 1189: WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply, "Reply"); ! 1190: ! 1191: /* declarations for local vars: Union of Request and Reply messages, ! 1192: InP, OutP and return value */ ! 1193: ! 1194: WriteVarDecls(file, rt); ! 1195: ! 1196: /* declarations and initializations of the mach_msg_type_t variables ! 1197: for each argument */ ! 1198: ! 1199: WriteList(file, rt->rtArgs, WriteTypeDeclIn, akbRequest, "\n", "\n"); ! 1200: if (!rt->rtOneWay) ! 1201: WriteList(file, rt->rtArgs, WriteCheckDecl, akbReplyQC, "\n", "\n"); ! 1202: ! 1203: /* fill in all the request message types and then arguments */ ! 1204: ! 1205: WriteRequestArgs(file, rt); ! 1206: ! 1207: /* fill in request message head */ ! 1208: ! 1209: WriteRequestHead(file, rt); ! 1210: fprintf(file, "\n"); ! 1211: ! 1212: /* Write the send/receive or rpc call */ ! 1213: ! 1214: if (rt->rtOneWay) ! 1215: WriteMsgSend(file, rt); ! 1216: else ! 1217: { ! 1218: if (UseMsgRPC) ! 1219: WriteMsgRPC(file, rt); ! 1220: else ! 1221: WriteMsgSendReceive(file, rt); ! 1222: ! 1223: /* Check the values that are returned in the reply message */ ! 1224: ! 1225: WriteCheckIdentity(file, rt); ! 1226: ! 1227: /* If the reply message has no Out parameters or return values ! 1228: other than the return code, we can type-check it and ! 1229: return it directly. */ ! 1230: ! 1231: if (rt->rtNoReplyArgs) ! 1232: { ! 1233: WriteTypeCheck(file, rt->rtRetCode); ! 1234: ! 1235: fprintf(file, "\treturn OutP->RetCode;\n"); ! 1236: } ! 1237: else { ! 1238: WriteReplyArgs(file, rt); ! 1239: ! 1240: /* return the return value, if any */ ! 1241: ! 1242: if (rt->rtProcedure) ! 1243: fprintf(file, "\t/* Procedure - no return needed */\n"); ! 1244: else ! 1245: WriteReturnValue(file, rt); ! 1246: } ! 1247: } ! 1248: ! 1249: fprintf(file, "}\n"); ! 1250: } ! 1251: ! 1252: /************************************************************* ! 1253: * Writes out the xxxUser.c file. Called by mig.c ! 1254: *************************************************************/ ! 1255: void ! 1256: WriteUser(FILE *file, const statement_t *stats) ! 1257: { ! 1258: register const statement_t *stat; ! 1259: ! 1260: WriteProlog(file); ! 1261: for (stat = stats; stat != stNULL; stat = stat->stNext) ! 1262: switch (stat->stKind) ! 1263: { ! 1264: case skRoutine: ! 1265: WriteRoutine(file, stat->stRoutine); ! 1266: break; ! 1267: case skImport: ! 1268: case skUImport: ! 1269: WriteImport(file, stat->stFileName); ! 1270: break; ! 1271: case skSImport: ! 1272: break; ! 1273: default: ! 1274: fatal("WriteUser(): bad statement_kind_t (%d)", ! 1275: (int) stat->stKind); ! 1276: } ! 1277: WriteEpilog(file); ! 1278: } ! 1279: ! 1280: /************************************************************* ! 1281: * Writes out individual .c user files for each routine. Called by mig.c ! 1282: *************************************************************/ ! 1283: void ! 1284: WriteUserIndividual(const statement_t *stats) ! 1285: { ! 1286: register const statement_t *stat; ! 1287: ! 1288: for (stat = stats; stat != stNULL; stat = stat->stNext) ! 1289: switch (stat->stKind) ! 1290: { ! 1291: case skRoutine: ! 1292: { ! 1293: FILE *file; ! 1294: register char *filename; ! 1295: ! 1296: filename = strconcat(UserFilePrefix, ! 1297: strconcat(stat->stRoutine->rtName, ".c")); ! 1298: file = fopen(filename, "w"); ! 1299: if (file == NULL) ! 1300: fatal("fopen(%s): %s", filename, ! 1301: unix_error_string(errno)); ! 1302: WriteProlog(file); ! 1303: ! 1304: { ! 1305: /* Write all the imports. */ ! 1306: const statement_t *s; ! 1307: for (s = stats; s != stNULL; s = s->stNext) ! 1308: switch (s->stKind) ! 1309: { ! 1310: case skImport: ! 1311: case skUImport: ! 1312: WriteImport(file, s->stFileName); ! 1313: break; ! 1314: } ! 1315: } ! 1316: ! 1317: WriteRoutine(file, stat->stRoutine); ! 1318: WriteEpilog(file); ! 1319: fclose(file); ! 1320: strfree(filename); ! 1321: } ! 1322: break; ! 1323: case skImport: ! 1324: case skUImport: ! 1325: break; ! 1326: case skSImport: ! 1327: break; ! 1328: default: ! 1329: fatal("WriteUserIndividual(): bad statement_kind_t (%d)", ! 1330: (int) stat->stKind); ! 1331: } ! 1332: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.