|
|
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.