1 /*-
2 * Copyright (c) 2014, Matthew Macy <kmacy@FreeBSD.ORG>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27 /*
28 * Copyright 1991-1998 by Open Software Foundation, Inc.
29 * All Rights Reserved
30 *
31 * Permission to use, copy, modify, and distribute this software and
32 * its documentation for any purpose and without fee is hereby granted,
33 * provided that the above copyright notice appears in all copies and
34 * that both the copyright notice and this permission notice appear in
35 * supporting documentation.
36 *
37 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
38 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
39 * FOR A PARTICULAR PURPOSE.
40 *
41 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
42 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
43 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
44 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
45 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
46 */
47 /*
48 * cmk1.1
49 */
50 /*
51 * Mach Operating System
52 * Copyright (c) 1991,1990 Carnegie Mellon University
53 * All Rights Reserved.
54 *
55 * Permission to use, copy, modify and distribute this software and its
56 * documentation is hereby granted, provided that both the copyright
57 * notice and this permission notice appear in all copies of the
58 * software, derivative works or modified versions, and any portions
59 * thereof, and that both notices appear in supporting documentation.
60 *
61 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
62 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
63 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
64 *
65 * Carnegie Mellon requests users of this software to return to
66 *
67 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
68 * School of Computer Science
69 * Carnegie Mellon University
70 * Pittsburgh PA 15213-3890
71 *
72 * any improvements or extensions that they make and grant Carnegie the
73 * rights to redistribute these changes.
74 */
75 /*
76 * 29-Sep-92 John Loverso (loverso) at Open Software Foundation
77 * Changes to deallocate memory on various error codes
78 *
79 * 92/03/03 16:25:33 jeffreyh
80 * Changes from TRUNK
81 * [92/02/26 12:32:55 jeffreyh]
82 *
83 * 92/01/14 16:46:59 rpd
84 * Changed CountInOut code generation, to send the minimum
85 * of the reply msg buffer size and the user's buffer size.
86 * [92/01/13 rpd]
87 *
88 * Fixed WriteExtractArgValue/itIndefinite, in the case when
89 * the data is in-line but doesn't fit.
90 * Fixed Indefinite code generation, to allow short type descriptors.
91 * Added deallocate bit handling to Indefinite code generation.
92 * [92/01/08 rpd]
93 *
94 * 92/01/03 20:30:38 dbg
95 * Redo handling of OUT arrays that are passed in-line or
96 * out-of-line. Treat more like out-of-line arrays:
97 * user allocates buffer and pointer
98 * fills in pointer with buffer address
99 * passes pointer to stub
100 * stub copies data to *pointer, or changes pointer
101 * User can always use *pointer.
102 *
103 * Change argByReferenceUser to a field in argument_t.
104 * [91/09/04 dbg]
105 *
106 * 91/08/28 11:17:34 jsb
107 * Added MIG_SERVER_DIED.
108 * [91/08/21 rpd]
109 * Removed Camelot and TrapRoutine support.
110 * Changed MsgKind to MsgSeqno.
111 * [91/08/12 rpd]
112 *
113 * 91/07/31 18:11:31 dbg
114 * Allow indefinite-length variable arrays. They may be copied
115 * either in-line or out-of-line, depending on size.
116 *
117 * Copy variable-length C Strings with mig_strncpy, to combine
118 * 'strcpy' and 'strlen' operations.
119 *
120 * New method for advancing request message pointer past
121 * variable-length arguments. We no longer have to know the order
122 * of variable-length arguments and their count arguments.
123 *
124 * Remove redundant assignments (to msgh_simple, msgh_size) in
125 * generated code.
126 * [91/07/17 dbg]
127 *
128 * 91/06/26 14:39:44 rpd
129 * Removed the dummy user initialization function,
130 * which was kept for backwards-compatibility.
131 * [91/06/26 rpd]
132 *
133 * 91/06/25 10:32:22 rpd
134 * Cast request and reply ports to mach_port_t in KernelUser stubs.
135 * [91/05/27 rpd]
136 *
137 * Changed HeaderFileName to UserHeaderFileName.
138 * Changed WriteVarDecl to WriteUserVarDecl.
139 * [91/05/23 rpd]
140 *
141 * 91/02/05 17:56:20 mrt
142 * Changed to new Mach copyright
143 * [91/02/01 17:56:28 mrt]
144 *
145 * 90/06/19 23:01:20 rpd
146 * Added UserFilePrefix support.
147 * [90/06/03 rpd]
148 *
149 * 90/06/02 15:06:03 rpd
150 * Created for new IPC.
151 * [90/03/26 21:14:40 rpd]
152 *
153 * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
154 * Extensive revamping. Added polymorphic arguments.
155 * Allow multiple variable-sized inline arguments in messages.
156 *
157 * 21-Feb-89 David Golub (dbg) at Carnegie-Mellon University
158 * Get name for header file from HeaderFileName, since it can
159 * change.
160 *
161 * 8-Feb-89 David Golub (dbg) at Carnegie-Mellon University
162 * Added WriteUserIndividual to put each user-side routine in its
163 * own file.
164 *
165 * 8-Jul-88 Mary Thompson (mrt) at Carnegie-Mellon University
166 * Declared routines to be mig_external instead of extern,
167 * where mig_external is conditionally defined in <subsystem>.h.
168 * The Avalon folks want to define mig_external to be static
169 * in their compilations because they inlcude the User.c code in
170 * their programs.
171 *
172 * 23-Feb-88 Mary Thompson (mrt) at Carnegie-Mellon University
173 * Changed the include of camelot_types.h to cam/camelot_types.h
174 *
175 * 19-Feb-88 Mary Thompson (mrt) at Carnegie-Mellon University
176 * Added comments for each routine. Called WriteMsgError
177 * for MIG_ARRAY_TOO_LARGE errors.
178 *
179 * 19-Jan-88 David Golub (dbg) at Carnegie-Mellon University
180 * Change variable-length inline array declarations to use
181 * maximum size specified to Mig. Make message variable
182 * length if the last item in the message is variable-length
183 * and inline. Use argMultiplier field to convert between
184 * argument and IPC element counts.
185 *
186 * 19-Jan-88 Mary Thompson (mrt) at Carnegie-Mellon University
187 * In WriteInitRoutine changed reference from reply_port; to reply_port++;
188 * for lint code.
189 *
190 * 17-Jan-88 David Detlefs (dld) at Carnegie-Mellon University
191 * Modified to produce C++ compatible code via #ifdefs.
192 * All changes have to do with argument declarations.
193 *
194 * 16-Nov-87 David Golub (dbg) at Carnegie-Mellon University
195 * Handle variable-length inline arrays.
196 *
197 * 22-Oct-87 Mary Thompson (mrt) at Carnegie-Mellon University
198 * Added a reference to rep_port in the InitRoutine
199 * with an ifdef lint conditional.
200 *
201 * 22-Sep-87 Mary Thompson (mrt) at Carnegie-Mellon University
202 * Fixed check for TransId to be a not equal test
203 * rather than an equal test.
204 *
205 * 2-Sep-87 Mary Thompson (mrt) at Carnegie-Mellon University
206 * Changed WriteCheckIdentity to check TransId instead
207 * of msgh_id for a returned camelot reply
208 *
209 * 24-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
210 * Added a LINTLIBRARY line to keep lint
211 * from complaining about routines that are not used.
212 *
213 * 21-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
214 * Added Flag parameter to WritePackMsgType.
215 *
216 * 12-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
217 * Made various camelot changes: include of camelot_types.h
218 * Check for death_pill before correct msg-id.
219 *
220 * 10-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
221 * Renamed get_reply_port and dealloc_reply_port to
222 * mig_get_reply_port and mig_dealloc_reply_port.
223 * Fixed WriteRequestHead to handle MsgType parameter.
224 *
225 * 3-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
226 * Fixed to generate code that is the same for multi-threaded and
227 * single threaded use. Gets reply port from library routine
228 * get_reply_port and deallocates with routine
229 * dealloc_reply_port. Removed all routines in mig interface code
230 * to keep track of the reply port. The init routine still exists
231 * but does nothing.
232 *
233 * 29-Jul_87 Mary Thompson (mrt) at Carnegie-Mellon University
234 * Fixed call to WriteVarDecl to use correspond to
235 * the changes that were made in that routine.
236 *
237 * 16-Jul-87 Robert Sansom (rds) at Carnegie Mellon University
238 * Added write of MsgType to WriteSetMsgTypeRoutine.
239 *
240 * 8-Jun-87 Mary Thompson (mrt) at Carnegie-Mellon University
241 * Removed #include of sys/types.h from WriteIncludes.
242 * Changed the KERNEL include from ../h to sys/
243 * Removed extern from WriteUser to make hi-c happy
244 *
245 * 28-May-87 Richard Draves (rpd) at Carnegie-Mellon University
246 * Created.
247 */
248
249 #include <assert.h>
250 #include <stdlib.h>
251
252 #include <mach/message.h>
253 #include "write.h"
254 #include "error.h"
255 #include "utils.h"
256 #include "global.h"
257 #include "alloc.h"
258
259 const char *MessAllocRoutine = "mig_user_allocate";
260 const char *MessFreeRoutine = "mig_user_deallocate";
261
262 static char stRetCode[] = "ReturnValue";
263 static char stRetNone[] = "";
264
265 void WriteLogDefines();
266 void WriteIdentificationString();
267
268 static void
WriteKPD_Iterator(FILE * file,boolean_t in,boolean_t overwrite,boolean_t varying,argument_t * arg,boolean_t bracket)269 WriteKPD_Iterator(FILE *file, boolean_t in, boolean_t overwrite, boolean_t varying, argument_t *arg, boolean_t bracket)
270 {
271 register ipc_type_t *it = arg->argType;
272 char string[MAX_STR_LEN];
273
274 fprintf(file, "\t{\n");
275 fprintf(file, "\t register\t%s\t*ptr;\n", it->itKPDType);
276 fprintf(file, "\t register int\ti");
277 if (varying && !in)
278 fprintf(file, ", j");
279 fprintf(file, ";\n\n");
280
281 if (in)
282 sprintf(string, "InP");
283 else if (overwrite)
284 sprintf(string, "InOvTemplate");
285 else
286 sprintf(string, "Out%dP", arg->argRequestPos);
287
288 fprintf(file, "\t ptr = &%s->%s[0];\n", string, arg->argMsgField);
289
290 if (varying) {
291 register argument_t *count = arg->argCount;
292 register const char *cref = count->argByReferenceUser ? "*" : "";
293
294 if (in || overwrite) {
295 fprintf(file, "\t if (%s%s > %d)\n", cref, count->argVarName,
296 it->itKPD_Number);
297 WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE");
298 fprintf(file, "\t for (i = 0; i < %s%s; ptr++, i++) %s\n",
299 cref, count->argVarName, (bracket) ? "{" : "");
300 } else {
301 fprintf(file, "\t j = min(Out%dP->%s, %s%s);\n", count->argReplyPos,
302 count->argVarName, cref, count->argVarName);
303 fprintf(file, "\t for (i = 0; i < j; ptr++, i++) %s\n",
304 (bracket) ? "{" : "");
305 }
306 } else
307 fprintf(file, "\t for (i = 0; i < %d; ptr++, i++) %s\n", it->itKPD_Number,
308 (bracket) ? "{" : "");
309 }
310
311 /*************************************************************
312 * Writes the standard includes. The subsystem specific
313 * includes are in <SubsystemName>.h and writen by
314 * header:WriteHeader. Called by WriteProlog.
315 *************************************************************/
316 static void
WriteMyIncludes(FILE * file,statement_t * stats)317 WriteMyIncludes(FILE *file, statement_t *stats)
318 {
319 #ifdef MIG_KERNEL_PORT_CONVERSION
320 if (IsKernelServer)
321 {
322 /*
323 * We want to get the user-side definitions of types
324 * like task_t, ipc_space_t, etc. in mach/mach_types.h.
325 */
326
327 fprintf(file, "#undef\tMACH_KERNEL\n");
328
329 if (InternalHeaderFileName != strNULL)
330 {
331 register const char *cp;
332
333 /* Strip any leading path from InternalHeaderFileName. */
334 cp = strrchr(InternalHeaderFileName, '/');
335 if (cp == 0)
336 cp = InternalHeaderFileName;
337 else
338 cp++; /* skip '/' */
339 fprintf(file, "#include \"%s\"\n", cp);
340 }
341 }
342 #endif
343
344 if (UserHeaderFileName == strNULL || UseSplitHeaders)
345 WriteIncludes(file, TRUE, FALSE);
346 if (UserHeaderFileName != strNULL)
347 {
348 register const char *cp;
349
350 /* Strip any leading path from UserHeaderFileName. */
351 cp = strrchr(UserHeaderFileName, '/');
352 if (cp == 0)
353 cp = UserHeaderFileName;
354 else
355 cp++; /* skip '/' */
356 fprintf(file, "#include \"%s\"\n", cp);
357 }
358 if (UseSplitHeaders)
359 WriteImplImports(file, stats, TRUE);
360
361 if (UseEventLogger) {
362 if (IsKernelUser) {
363 fprintf(file, "#if\t__MigKernelSpecificCode\n");
364 fprintf(file, "#include <mig_debug.h>\n");
365 fprintf(file, "#endif\t/* __MigKernelSpecificCode */\n");
366 }
367 fprintf(file, "#if MIG_DEBUG\n");
368 fprintf(file, "#include <mach/mig_log.h>\n");
369 fprintf(file, "#endif /* MIG_DEBUG */\n");
370 }
371 fprintf(file, "/* LINTLIBRARY */\n");
372 fprintf(file, "\n");
373 if (!BeAnsiC) {
374 fprintf(file, "#if\t%s\n", NewCDecl);
375 fprintf(file, "#else\t/* %s */\n", NewCDecl);
376 fprintf(file, "extern mach_port_t mig_get_reply_port();\n");
377 fprintf(file, "extern void mig_dealloc_reply_port();\n");
378 fprintf(file, "extern char *%s();\n", MessAllocRoutine);
379 fprintf(file, "extern void %s();\n", MessFreeRoutine);
380 fprintf(file, "#endif\t/* %s */\n", NewCDecl);
381 }
382 fprintf(file, "\n");
383 }
384
385 static void
WriteGlobalDecls(FILE * file)386 WriteGlobalDecls(FILE *file)
387 {
388 if (RCSId != strNULL)
389 WriteRCSDecl(file, strconcat(SubsystemName, "_user"), RCSId);
390
391 fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n");
392 fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n");
393 fprintf(file, "\n");
394 if (UseEventLogger)
395 WriteLogDefines(file, "MACH_MSG_LOG_USER");
396 fprintf(file, "\n");
397 }
398
399 static void
WriteOneMachErrorDefine(FILE * file,const char * name,boolean_t timeout)400 WriteOneMachErrorDefine(FILE *file, const char *name, boolean_t timeout)
401 {
402 fprintf(file, "#ifndef\t%s\n", name);
403 fprintf(file, "#define\t%s(_R_) { \\\n", name);
404 fprintf(file, "\tswitch (_R_) { \\\n");
405 fprintf(file, "\tcase MACH_SEND_INVALID_REPLY: \\\n");
406 fprintf(file, "\tcase MACH_RCV_INVALID_NAME: \\\n");
407 fprintf(file, "\tcase MACH_RCV_IN_SET: \\\n");
408 fprintf(file, "\tcase MACH_RCV_PORT_DIED: \\\n");
409 fprintf(file, "\tcase MACH_RCV_PORT_CHANGED: \\\n");
410 fprintf(file, "\tcase MACH_SEND_INVALID_MEMORY: \\\n");
411 fprintf(file, "\tcase MACH_SEND_INVALID_RIGHT: \\\n");
412 fprintf(file, "\tcase MACH_SEND_INVALID_TYPE: \\\n");
413 fprintf(file, "\tcase MACH_SEND_MSG_TOO_SMALL: \\\n");
414 fprintf(file, "\tcase MACH_SEND_INVALID_RT_OOL_SIZE: \\\n");
415 if (timeout)
416 fprintf(file, "\tcase MACH_RCV_TIMED_OUT: \\\n");
417 fprintf(file, "\t\tmig_dealloc_reply_port(InP->Head.msgh_reply_port); \\\n");
418 fprintf(file, "\t} \\\n}\n");
419 fprintf(file, "#endif\t/* %s */\n", name);
420 fprintf(file, "\n");
421 }
422
423 static void
WriteMachErrorDefines(FILE * file)424 WriteMachErrorDefines(FILE *file)
425 {
426 WriteOneMachErrorDefine(file, "__MachMsgErrorWithTimeout", TRUE);
427 WriteOneMachErrorDefine(file, "__MachMsgErrorWithoutTimeout", FALSE);
428 }
429
430 static void
WriteMIGCheckDefines(FILE * file)431 WriteMIGCheckDefines(FILE *file)
432 {
433 fprintf(file, "#define\t__MIG_check__Reply__%s_subsystem__ 1\n", SubsystemName);
434 fprintf(file, "\n");
435 }
436
437 static void
WriteNDRDefines(FILE * file)438 WriteNDRDefines(FILE *file)
439 {
440 fprintf(file, "#define\t__NDR_convert__Reply__%s_subsystem__ 1\n", SubsystemName);
441 fprintf(file, "#define\t__NDR_convert__mig_reply_error_subsystem__ 1\n");
442 fprintf(file, "\n");
443 }
444
445 /*************************************************************
446 * Writes the standard #includes, #defines, and
447 * RCS declaration. Called by WriteUser.
448 *************************************************************/
449 static void
WriteProlog(FILE * file,statement_t * stats)450 WriteProlog(FILE *file, statement_t *stats)
451 {
452 WriteIdentificationString(file);
453 WriteMIGCheckDefines(file);
454 if (CheckNDR)
455 WriteNDRDefines(file);
456 WriteMyIncludes(file, stats);
457 WriteBogusDefines(file);
458 WriteMachErrorDefines(file);
459 WriteApplDefaults(file, "Send");
460 WriteGlobalDecls(file);
461 }
462
463 /*ARGSUSED*/
464 static void
WriteEpilog(FILE * file __unused)465 WriteEpilog(FILE *file __unused)
466 {
467 }
468
469 static string_t
WriteHeaderPortType(argument_t * arg)470 WriteHeaderPortType(argument_t *arg)
471 {
472 if (arg->argType->itInName == MACH_MSG_TYPE_POLYMORPHIC)
473 return arg->argPoly->argVarName;
474 else
475 return arg->argType->itInNameStr;
476 }
477
478 static void
WriteRequestHead(FILE * file,routine_t * rt)479 WriteRequestHead(FILE *file, routine_t *rt)
480 {
481 if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest)
482 fprintf(file, "ready_to_send:\n");
483
484 if (rt->rtMaxRequestPos > 0) {
485 if (rt->rtOverwrite)
486 fprintf(file, "\tInP = &MessRequest;\n");
487 else
488 fprintf(file, "\tInP = &Mess%sIn;\n",
489 (rtMessOnStack(rt) ? "." : "->"));
490 }
491 fprintf(file, "\tInP->Head.msgh_bits =");
492 if (rt->rtRetCArg == argNULL && !rt->rtSimpleRequest)
493 fprintf(file, " MACH_MSGH_BITS_COMPLEX|");
494 fprintf(file, "\n");
495 fprintf(file, "\t\tMACH_MSGH_BITS(%s, %s);\n",
496 WriteHeaderPortType(rt->rtRequestPort),
497 WriteHeaderPortType(rt->rtReplyPort));
498 if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
499 fprintf(file, "\tif (!%s)\n", rt->rtRetCArg->argVarName);
500 fprintf(file, "\t\tInP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n");
501 }
502
503
504 fprintf(file, "\t/* msgh_size passed as argument */\n");
505
506 /*
507 * KernelUser stubs need to cast the request and reply ports
508 * from ipc_port_t to mach_port_t.
509 */
510
511 #ifdef MIG_KERNEL_PORT_CONVERSION
512 if (IsKernelUser)
513 fprintf(file, "\tInP->%s = (mach_port_t) %s;\n",
514 rt->rtRequestPort->argMsgField,
515 rt->rtRequestPort->argVarName);
516 else
517 #endif
518 fprintf(file, "\tInP->%s = %s;\n",
519 rt->rtRequestPort->argMsgField,
520 rt->rtRequestPort->argVarName);
521
522 if (akCheck(rt->rtReplyPort->argKind, akbUserArg)) {
523 #ifdef MIG_KERNEL_PORT_CONVERSION
524 if (IsKernelUser)
525 fprintf(file, "\tInP->%s = (mach_port_t) %s;\n", rt->rtReplyPort->argMsgField, rt->rtReplyPort->argVarName);
526 else
527 #endif
528 fprintf(file, "\tInP->%s = %s;\n", rt->rtReplyPort->argMsgField, rt->rtReplyPort->argVarName);
529 }
530 else if (rt->rtOneWay)
531 fprintf(file, "\tInP->%s = MACH_PORT_NULL;\n", rt->rtReplyPort->argMsgField);
532 else
533 fprintf(file, "\tInP->%s = mig_get_reply_port();\n", rt->rtReplyPort->argMsgField);
534
535 fprintf(file, "\tInP->Head.msgh_id = %d;\n", rt->rtNumber + SubsystemBase);
536
537
538 if (IsVoucherCodeAllowed && !IsKernelUser && !IsKernelServer) {
539 fprintf(file, "\t\n/* BEGIN VOUCHER CODE */\n\n");
540 fprintf(file, "#ifdef USING_VOUCHERS\n");
541 fprintf(file, "\tif (voucher_mach_msg_set != NULL) {\n");
542 fprintf(file, "\t\tvoucher_mach_msg_set(&InP->Head);\n");
543 fprintf(file, "\t}\n");
544 fprintf(file, "#endif // USING_VOUCHERS\n");
545 fprintf(file, "\t\n/* END VOUCHER CODE */\n");
546 }
547 }
548
549 /*************************************************************
550 * Writes declarations for the message types, variables
551 * and return variable if needed. Called by WriteRoutine.
552 *************************************************************/
553 static void
WriteVarDecls(FILE * file,routine_t * rt)554 WriteVarDecls(FILE *file, routine_t *rt)
555 {
556 register u_int i;
557
558 if (rt->rtOverwrite) {
559 fprintf(file, "\tRequest MessRequest;\n");
560 fprintf(file, "\tRequest *InP = &MessRequest;\n\n");
561
562 fprintf(file, "\tunion {\n");
563 fprintf(file, "\t\tOverwriteTemplate In;\n");
564 fprintf(file, "\t\tReply Out;\n");
565 fprintf(file, "\t} MessReply;\n");
566
567 fprintf(file, "\tOverwriteTemplate *InOvTemplate = &MessReply.In;\n");
568 fprintf(file, "\tReply *Out0P = &MessReply.Out;\n");
569 for (i = 1; i <= rt->rtMaxReplyPos; i++)
570 fprintf(file, "\t" "Reply *Out%dP = NULL;\n", i);
571 }
572 else {
573 if (rtMessOnStack(rt))
574 fprintf(file, "\tunion {\n");
575 else
576 fprintf(file, "\tunion %sMessU {\n", rt->rtName);
577 fprintf(file, "\t\tRequest In;\n");
578 if (!rt->rtOneWay)
579 fprintf(file, "\t\tReply Out;\n");
580 if (rtMessOnStack(rt))
581 fprintf(file, "\t} Mess;\n");
582 else
583 fprintf(file, "\t} *Mess = (union %sMessU *) %s(sizeof(*Mess));\n",
584 rt->rtName, MessAllocRoutine);
585 fprintf(file, "\n");
586
587 fprintf(file, "\tRequest *InP = &Mess%sIn;\n", (rtMessOnStack(rt) ? "." : "->"));
588 if (!rt->rtOneWay) {
589 fprintf(file, "\tReply *Out0P = &Mess%sOut;\n", (rtMessOnStack(rt) ? "." : "->"));
590 for (i = 1; i <= rt->rtMaxReplyPos; i++)
591 fprintf(file, "\t" "Reply *Out%dP = NULL;\n", i);
592 }
593 }
594
595 fprintf(file, "\n");
596
597 fprintf(file, "\tmach_msg_return_t msg_result;\n");
598
599 /* if request is variable, we need msgh_size_delta and msgh_size */
600 if (rt->rtNumRequestVar > 0)
601 fprintf(file, "\tunsigned int msgh_size;\n");
602 if (rt->rtMaxRequestPos > 0)
603 fprintf(file, "\tunsigned int msgh_size_delta;\n");
604 if (rt->rtNumRequestVar > 1 || rt->rtMaxRequestPos > 0)
605 fprintf(file, "\n");
606
607 if (rt->rtUserImpl) {
608 fprintf(file, "\tmach_msg_max_trailer_t *TrailerP;\n");
609 fprintf(file, "#if\t__MigTypeCheck\n");
610 fprintf(file, "\tunsigned int trailer_size;\n");
611 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
612 }
613 fprintf(file, "\n");
614 fprintf(file, "#ifdef\t__MIG_check__Reply__%s_t__defined\n", rt->rtName);
615 fprintf(file, "\tkern_return_t check_result;\n");
616 fprintf(file, "#endif\t/* __MIG_check__Reply__%s_t__defined */\n", rt->rtName);
617 fprintf(file, "\n");
618 WriteApplMacro(file, "Send", "Declare", rt);
619 fprintf(file, "\n");
620 }
621
622 static void
WriteReturn(FILE * file,routine_t * rt,const char * before,const char * value,const char * after)623 WriteReturn(FILE *file, routine_t *rt, const char *before, const char *value, const char *after)
624 {
625 if (rtMessOnStack(rt) && value != stRetCode)
626 {
627 /* get the easy case (no braces needed) out of the way */
628 fprintf(file, "%sreturn%s%s;%s",
629 before, (*value ? " " : ""), value, after);
630 return;
631 }
632
633 /* get the easy case (no braces needed) out of the way */
634 if (rtMessOnStack(rt))
635 {
636 if (value == stRetNone)
637 fprintf(file, "%sreturn;%s",
638 before, after);
639 else if (value == stRetCode)
640 fprintf(file, "%sreturn Out0P->RetCode;%s",
641 before, after);
642 else
643 fprintf(file, "%sreturn %s;%s",
644 before, value, after);
645 return;
646 }
647
648 if (value == stRetCode) {
649 fprintf(file, "%s{\n%s\t%s ReturnValue;\n", before, before, ReturnTypeStr(rt));
650 fprintf(file, "%s\tReturnValue = Out0P->RetCode;\n%s\t", before, before);
651 }
652 else {
653 fprintf(file, "%s{ ", before);
654 }
655
656 fprintf(file, "%s((char *) Mess, sizeof(*Mess)); ", MessFreeRoutine);
657
658 if (value == stRetCode)
659 fprintf(file, "return ReturnValue;\n%s}%s", before, after);
660 else if (value == stRetNone)
661 fprintf(file, "return; }%s", after);
662 else
663 fprintf(file, "return %s; }%s", value, after);
664 }
665
666 static void
WriteRetCodeArg(FILE * file,register routine_t * rt)667 WriteRetCodeArg(FILE *file, register routine_t *rt)
668 {
669 if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
670 register argument_t *arg = rt->rtRetCArg;
671
672 fprintf(file, "\tif (%s) {\n", arg->argVarName);
673 fprintf(file, "\t\t((mig_reply_error_t *)InP)->RetCode = %s;\n", arg->argVarName);
674 fprintf(file, "\t\t((mig_reply_error_t *)InP)->NDR = NDR_record;\n");
675 fprintf(file, "\t\tgoto ready_to_send;\n");
676 fprintf(file, "\t}\n\n");
677 }
678 }
679
680 /*************************************************************
681 * Writes the logic to check for a message send timeout, and
682 * deallocate any relocated ool data so as not to leak.
683 *************************************************************/
684 static void
WriteMsgCheckForTimeout(FILE * file,routine_t * rt)685 WriteMsgCheckForTimeout(FILE *file, routine_t *rt)
686 {
687 if (rt->rtWaitTime != argNULL) { /* no reason to test for timeout if no timeout was specified... */
688 argument_t *arg_ptr;
689 fputs("\n\t" "if (msg_result == MACH_SEND_TIMED_OUT) {" "\n", file);
690
691 // iterate over arg list
692 for (arg_ptr = rt->rtArgs; arg_ptr != NULL; arg_ptr = arg_ptr->argNext) {
693
694 // if argument contains ool data
695 if (akCheck(arg_ptr->argKind, akbSendKPD) && arg_ptr->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {
696 // generate code to test current arg address vs. address before the msg_send call
697 // if not at the same address, mig_deallocate the argument
698 fprintf(file, "\t\tif((vm_offset_t) InP->%s.address != (vm_offset_t) %s)\n",
699 arg_ptr->argVarName, arg_ptr->argVarName);
700 fprintf(file, "\t\t\t" "mig_deallocate((vm_offset_t) InP->%s.address, "
701 "(vm_size_t) InP->%s.size);\n", arg_ptr->argVarName, arg_ptr->argVarName);
702 }
703 }
704
705 fputs("\t" "}" "\n\n", file);
706 }
707 return;
708 }
709
710 /*************************************************************
711 * Writes the send call when there is to be no subsequent
712 * receive. Called by WriteRoutine SimpleRoutines
713 *************************************************************/
714 static void
WriteMsgSend(FILE * file,routine_t * rt)715 WriteMsgSend(FILE *file, routine_t *rt)
716 {
717 const char *SendSize = "";
718 char string[MAX_STR_LEN];
719
720 if (rt->rtNumRequestVar == 0)
721 SendSize = "sizeof(Request)";
722 else
723 SendSize = "msgh_size";
724
725 if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
726 sprintf(string, "(%s) ? sizeof(mig_reply_error_t) : ",
727 rt->rtRetCArg->argVarName);
728 SendSize = strconcat(string, SendSize);
729 }
730
731 if (IsKernelUser) {
732 fprintf(file, "#if\t__MigKernelSpecificCode\n");
733 fprintf(file, "\tmsg_result = mach_msg_send_from_kernel(");
734 fprintf(file, "&InP->Head, %s);\n", SendSize);
735 fprintf(file, "#else\n");
736 }
737 fprintf(file, "\tmsg_result = mach_msg("
738 "&InP->Head, MACH_SEND_MSG|%s%s, %s, 0, MACH_PORT_NULL, %s, MACH_PORT_NULL);\n",
739 rt->rtWaitTime !=argNULL ? "MACH_SEND_TIMEOUT|" : "",
740 rt->rtMsgOption->argVarName,
741 SendSize,
742 rt->rtWaitTime != argNULL ? rt->rtWaitTime->argVarName:"MACH_MSG_TIMEOUT_NONE");
743
744 if (IsKernelUser) {
745 fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
746 }
747 WriteApplMacro(file, "Send", "After", rt);
748
749 WriteMsgCheckForTimeout(file, rt);
750
751 WriteReturn(file, rt, "\t", "msg_result", "\n");
752 }
753
754 /*************************************************************
755 * Writes to code to check for error returns from receive.
756 * Called by WriteMsgSendReceive and WriteMsgRPC
757 *************************************************************/
758 static void
WriteMsgCheckReceive(FILE * file,routine_t * rt,const char * success)759 WriteMsgCheckReceive(FILE *file, routine_t *rt, const char *success)
760 {
761 fprintf(file, "\tif (msg_result != %s) {\n", success);
762 if (!akCheck(rt->rtReplyPort->argKind, akbUserArg) && !IsKernelUser)
763 {
764 /* If we aren't using a user-supplied reply port, then
765 deallocate the reply port when it is invalid or
766 for TIMED_OUT errors. */
767 #ifdef DeallocOnAnyError
768 fprintf(file,
769 "\t\tmig_dealloc_reply_port(InP->Head.msgh_reply_port);\n");
770 #else
771 if (rt->rtWaitTime != argNULL)
772 fprintf(file, "\t\t__MachMsgErrorWithTimeout(msg_result);\n");
773 else
774 fprintf(file, "\t\t__MachMsgErrorWithoutTimeout(msg_result);\n");
775 #endif
776 }
777 WriteReturnMsgError(file, rt, TRUE, argNULL, "msg_result");
778 fprintf(file, "\t}\n");
779 }
780
781 /*************************************************************
782 * Writes the send and receive calls and code to check
783 * for errors. Normally the rpc code is generated instead
784 * although, the subsytem can be compiled with the -R option
785 * which will cause this code to be generated. Called by
786 * WriteRoutine if UseMsgRPC option is false.
787 *************************************************************/
788 static void
WriteMsgSendReceive(FILE * file,routine_t * rt)789 WriteMsgSendReceive(FILE *file, routine_t *rt)
790 {
791 const char *SendSize = "";
792 char string[MAX_STR_LEN];
793
794 if (rt->rtNumRequestVar == 0)
795 SendSize = "sizeof(Request)";
796 else
797 SendSize = "msgh_size";
798
799 if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
800 sprintf(string, "(%s) ? sizeof(mig_reply_error_t) : ",
801 rt->rtRetCArg->argVarName);
802 SendSize = strconcat(string, SendSize);
803 }
804
805 /* IsKernelUser to be done! */
806 fprintf(file, "\tmsg_result = mach_msg(&InP->Head, MACH_SEND_MSG|%s%s, %s, 0, ", rt->rtWaitTime != argNULL ? "MACH_SEND_TIMEOUT|" : "", rt->rtMsgOption->argVarName, SendSize);
807 fprintf(file, " MACH_PORT_NULL, %s, MACH_PORT_NULL);\n",
808 #if !USE_IMMEDIATE_SEND_TIMEOUT
809 (rt->rtWaitTime != argNULL) ? rt->rtWaitTime->argVarName :
810 #endif
811 "MACH_MSG_TIMEOUT_NONE");
812 fprintf(file, "\tif (msg_result != MACH_MSG_SUCCESS)\n");
813 WriteReturnMsgError(file, rt, TRUE, argNULL, "msg_result");
814 fprintf(file, "\n");
815
816 fprintf(file, "\tmsg_result = mach_msg(&Out0P->Head, MACH_RCV_MSG|%s%s%s, 0, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_local_port, %s, MACH_PORT_NULL);\n",
817 rt->rtUserImpl != 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "",
818 (rt->rtWaitTime != argNULL && akIdent(rt->rtWaitTime->argKind) == akeWaitTime) ? "MACH_RCV_TIMEOUT|" : "",
819 rt->rtMsgOption->argVarName,
820 (rt->rtWaitTime != argNULL && akIdent(rt->rtWaitTime->argKind) == akeWaitTime) ? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE");
821 WriteApplMacro(file, "Send", "After", rt);
822 WriteMsgCheckReceive(file, rt, "MACH_MSG_SUCCESS");
823 fprintf(file, "\n");
824 }
825
826 /*************************************************************
827 * Writes the rpc call and the code to check for errors.
828 * This is the default code to be generated. Called by WriteRoutine
829 * for all routine types except SimpleRoutine.
830 *************************************************************/
831 static void
WriteMsgRPC(FILE * file,routine_t * rt)832 WriteMsgRPC(FILE *file, routine_t *rt)
833 {
834 const char *SendSize = "";
835 char string[MAX_STR_LEN];
836
837 if (rt->rtNumRequestVar == 0)
838 SendSize = "sizeof(Request)";
839 else
840 SendSize = "msgh_size";
841
842 if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
843 sprintf(string, "(%s) ? (mach_msg_size_t)sizeof(mig_reply_error_t) : ", rt->rtRetCArg->argVarName);
844 SendSize = strconcat(string, SendSize);
845 }
846
847 if (IsKernelUser) {
848 fprintf(file, "#if\t(__MigKernelSpecificCode) || (_MIG_KERNELSPECIFIC_CODE_)\n");
849 fprintf(file, "\tmsg_result = mach_msg_rpc_from_kernel(&InP->Head, %s, (mach_msg_size_t)sizeof(Reply));\n", SendSize);
850 fprintf(file, "#else\n");
851 }
852 if (rt->rtOverwrite) {
853 fprintf(file, "\tmsg_result = mach_msg_overwrite(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_RCV_OVERWRITE|%s%s%s, %s, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, %s, MACH_PORT_NULL, ",
854 rt->rtUserImpl != 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "",
855 rt->rtWaitTime != argNULL ?
856 (akIdent(rt->rtWaitTime->argKind) == akeWaitTime ? "MACH_SEND_TIMEOUT|MACH_RCV_TIMEOUT|" : "MACH_SEND_TIMEOUT|") : "",
857 rt->rtMsgOption->argVarName,
858 SendSize,
859 rt->rtWaitTime != argNULL? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE");
860 fprintf(file, " &InOvTemplate->Head, (mach_msg_size_t)sizeof(OverwriteTemplate));\n");
861 }
862 else {
863 fprintf(file, "\tmsg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|%s%s%s, %s, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, %s, MACH_PORT_NULL);\n",
864 rt->rtUserImpl != 0 ? "MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|" : "",
865 rt->rtWaitTime != argNULL ?
866 (akIdent(rt->rtWaitTime->argKind) == akeWaitTime ? "MACH_SEND_TIMEOUT|MACH_RCV_TIMEOUT|" : "MACH_SEND_TIMEOUT|") : "",
867 rt->rtMsgOption->argVarName,
868 SendSize,
869 rt->rtWaitTime != argNULL? rt->rtWaitTime->argVarName : "MACH_MSG_TIMEOUT_NONE");
870 }
871 if (IsKernelUser)
872 fprintf(file,"#endif /* __MigKernelSpecificCode */\n");
873 WriteApplMacro(file, "Send", "After", rt);
874
875 WriteMsgCheckForTimeout(file, rt);
876
877 WriteMsgCheckReceive(file, rt, "MACH_MSG_SUCCESS");
878 fprintf(file, "\n");
879 }
880
881 /*
882 * argKPD_Pack discipline for Port types.
883 */
884 static void
WriteKPD_port(FILE * file,register argument_t * arg)885 WriteKPD_port(FILE *file, register argument_t *arg)
886 {
887 register ipc_type_t *it = arg->argType;
888 const char *subindex = "";
889 const char *recast = "";
890 char firststring[MAX_STR_LEN];
891 char string[MAX_STR_LEN];
892 const char *ref = arg->argByReferenceUser ? "*" : "";
893 ipc_type_t *real_it;
894
895 if (IS_MULTIPLE_KPD(it)) {
896 WriteKPD_Iterator(file, TRUE, FALSE, it->itVarArray, arg, TRUE);
897 (void)sprintf(firststring, "\t*ptr");
898 (void)sprintf(string, "\tptr->");
899 subindex = "[i]";
900 real_it = it->itElement;
901 } else {
902 (void)sprintf(firststring, "InP->%s", arg->argMsgField);
903 (void)sprintf(string, "InP->%s.", arg->argMsgField);
904 real_it = it;
905 }
906
907 #ifdef MIG_KERNEL_PORT_CONVERSION
908 if (IsKernelUser && streql(real_it->itUserType, "ipc_port_t"))
909 recast = "(mach_port_t)";
910 #endif
911 fprintf(file, "#if\tUseStaticTemplates\n");
912 fprintf(file, "\t%s = %s;\n", firststring,
913 arg->argTTName);
914 /* ref is required also in the Request part, because of inout parameters */
915 fprintf(file, "\t%sname = %s%s%s%s;\n", string,
916 recast, ref, arg->argVarName, subindex);
917 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendSnd)) {
918 register argument_t *poly = arg->argPoly;
919
920 fprintf(file, "\t%sdisposition = %s%s;\n", string,
921 poly->argByReferenceUser ? "*" : "", poly->argVarName);
922 }
923 fprintf(file, "#else\t/* UseStaticTemplates */\n");
924 fprintf(file, "\t%sname = %s%s%s%s;\n", string,
925 recast, ref, arg->argVarName, subindex);
926 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendSnd)) {
927 register argument_t *poly = arg->argPoly;
928
929 fprintf(file, "\t%sdisposition = %s%s;\n", string,
930 poly->argByReferenceUser ? "*" : "", poly->argVarName);
931 } else
932 fprintf(file, "\t%sdisposition = %s;\n", string,
933 it->itInNameStr);
934 fprintf(file, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string);
935 fprintf(file, "#endif\t/* UseStaticTemplates */\n");
936 if (IS_MULTIPLE_KPD(it)) {
937 fprintf(file, "\t }\n");
938 if (it->itVarArray) {
939 fprintf(file, "\t for (i = %s; i < %d; ptr++, i++) {\n",
940 arg->argCount->argVarName, it->itKPD_Number);
941 /* fill the rest of the statically allocated KPD entries with MACH_PORT_NULL */
942 fprintf(file, "#if\tUseStaticTemplates\n");
943 fprintf(file, "\t%s = %s;\n", firststring,
944 arg->argTTName);
945 fprintf(file, "#else\t/* UseStaticTemplates */\n");
946 fprintf(file, "\t%sname = MACH_PORT_NULL;\n", string);
947 fprintf(file, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string);
948 fprintf(file, "#endif\t/* UseStaticTemplates */\n");
949 fprintf(file, "\t }\n");
950 }
951 fprintf(file, "\t}\n");
952 }
953 fprintf(file, "\n");
954 }
955
956 static void
WriteKPD_ool_varsize(FILE * file,argument_t * arg,const char * who,const char * where,boolean_t iscomplex)957 WriteKPD_ool_varsize(FILE *file, argument_t *arg, const char *who, const char *where, boolean_t iscomplex)
958 {
959 register ipc_type_t *it = arg->argType;
960 register argument_t *count;
961 const char *cref;
962
963 if (iscomplex) {
964 it = it->itElement;
965 count = arg->argSubCount;
966 } else
967 count = arg->argCount;
968 cref = count->argByReferenceUser ? "*" : "";
969
970 /* size has to be expressed in bytes! */
971 if (count->argMultiplier > 1 || it->itSize > 8)
972 fprintf(file, "\t%s->%s = %s%s%s * %d;\n", who, where,
973 cref, count->argVarName,
974 (iscomplex)? "[i]" : "",
975 count->argMultiplier * it->itSize / 8);
976 else
977 fprintf(file, "\t%s->%s = %s%s%s;\n", who, where,
978 cref, count->argVarName,
979 (iscomplex)? "[i]" : "");
980 }
981
982 /*
983 * argKPD_Pack discipline for out-of-line types.
984 */
985 static void
WriteKPD_ool(FILE * file,register argument_t * arg)986 WriteKPD_ool(FILE *file, register argument_t *arg)
987 {
988 register ipc_type_t *it = arg->argType;
989 const char *ref = arg->argByReferenceUser ? "*" : "";
990 char firststring[MAX_STR_LEN];
991 char string[MAX_STR_LEN];
992 boolean_t VarArray;
993 u_int howmany, howbig;
994 const char *subindex;
995
996 if (IS_MULTIPLE_KPD(it)) {
997 WriteKPD_Iterator(file, TRUE, FALSE, it->itVarArray, arg, TRUE);
998 (void)sprintf(firststring, "\t*ptr");
999 (void)sprintf(string, "\tptr->");
1000 VarArray = it->itElement->itVarArray;
1001 howmany = it->itElement->itNumber;
1002 howbig = it->itElement->itSize;
1003 subindex = "[i]";
1004 } else {
1005 (void)sprintf(firststring, "InP->%s", arg->argMsgField);
1006 (void)sprintf(string, "InP->%s.", arg->argMsgField);
1007 VarArray = it->itVarArray;
1008 howmany = it->itNumber;
1009 howbig = it->itSize;
1010 subindex = "";
1011 }
1012
1013 fprintf(file, "#if\tUseStaticTemplates\n");
1014
1015 fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
1016 fprintf(file, "\t%saddress = (void *)(%s%s%s);\n",
1017 string, ref, arg->argVarName, subindex);
1018 if (VarArray) {
1019 if (IS_MULTIPLE_KPD(it))
1020 WriteKPD_ool_varsize(file, arg, "\tptr", "size", TRUE);
1021 else
1022 WriteKPD_ool_varsize(file, arg, "InP",
1023 strconcat(arg->argMsgField, ".size"), FALSE);
1024 }
1025 if (arg->argDeallocate == d_MAYBE)
1026 fprintf(file, "\t%sdeallocate = %s;\n",
1027 string, arg->argDealloc->argVarName);
1028
1029 fprintf(file, "#else\t/* UseStaticTemplates */\n");
1030
1031 fprintf(file, "\t%saddress = (void *)(%s%s%s);\n",
1032 string, ref, arg->argVarName, subindex);
1033 if (VarArray)
1034 if (IS_MULTIPLE_KPD(it))
1035 WriteKPD_ool_varsize(file, arg, "\tptr", "size", TRUE);
1036 else
1037 WriteKPD_ool_varsize(file, arg, "InP",
1038 strconcat(arg->argMsgField, ".size"), FALSE);
1039 else
1040 fprintf(file, "\t%ssize = %d;\n", string,
1041 (howmany * howbig + 7)/8);
1042 if (arg->argDeallocate == d_MAYBE)
1043 fprintf(file, "\t%sdeallocate = %s;\n", string,
1044 arg->argDealloc->argVarName);
1045 else
1046 fprintf(file, "\t%sdeallocate = %s;\n", string,
1047 (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE");
1048 fprintf(file, "\t%scopy = %s;\n", string,
1049 (arg->argFlags & flPhysicalCopy) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY");
1050 #ifdef ALIGNMENT
1051 fprintf(file, "\t%salignment = MACH_MSG_ALIGN_%d;\n", string,
1052 (it->itElement->itSize < 8) ? 1 : it->itElement->itSize / 8);
1053 #endif
1054 fprintf(file, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string);
1055
1056 fprintf(file, "#endif\t/* UseStaticTemplates */\n");
1057 if (IS_MULTIPLE_KPD(it)) {
1058 fprintf(file, "\t }\n");
1059 if (it->itVarArray) {
1060 fprintf(file, "\t for (i = %s; i < %d; ptr++, i++) {\n",
1061 arg->argCount->argVarName, it->itKPD_Number);
1062 /* fill the rest of the statically allocated KPD entries with size NULL */
1063 fprintf(file, "#if\tUseStaticTemplates\n");
1064 fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
1065 if (!VarArray)
1066 fprintf(file, "\t%ssize = 0;\n", string);
1067 /* otherwise the size in the template would be != 0! */
1068 fprintf(file, "#else\t/* UseStaticTemplates */\n");
1069 fprintf(file, "\t%ssize = 0;\n", string);
1070 fprintf(file, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string);
1071 fprintf(file, "#endif\t/* UseStaticTemplates */\n");
1072 fprintf(file, "\t }\n");
1073 }
1074 fprintf(file, "\t}\n");
1075 }
1076 fprintf(file, "\n");
1077 }
1078
1079 /*
1080 * argKPD_Pack discipline for out-of-line Port types.
1081 */
1082 static void
WriteKPD_oolport(FILE * file,register argument_t * arg)1083 WriteKPD_oolport(FILE *file, register argument_t *arg)
1084 {
1085 register ipc_type_t *it = arg->argType;
1086 const char *ref = arg->argByReferenceUser ? "*" : "";
1087 register argument_t *count;
1088 boolean_t VarArray;
1089 string_t howstr;
1090 u_int howmany;
1091 const char *subindex;
1092 char firststring[MAX_STR_LEN];
1093 char string[MAX_STR_LEN];
1094
1095 if (IS_MULTIPLE_KPD(it)) {
1096 WriteKPD_Iterator(file, TRUE, FALSE, it->itVarArray, arg, TRUE);
1097 (void)sprintf(firststring, "\t*ptr");
1098 (void)sprintf(string, "\tptr->");
1099 VarArray = it->itElement->itVarArray;
1100 howmany = it->itElement->itNumber;
1101 howstr = it->itElement->itInNameStr;
1102 count = arg->argSubCount;
1103 subindex = "[i]";
1104 } else {
1105 (void)sprintf(firststring, "InP->%s", arg->argMsgField);
1106 (void)sprintf(string, "InP->%s.", arg->argMsgField);
1107 VarArray = it->itVarArray;
1108 howmany = it->itNumber;
1109 howstr = it->itInNameStr;
1110 count = arg->argCount;
1111 subindex = "";
1112 }
1113
1114 fprintf(file, "#if\tUseStaticTemplates\n");
1115
1116 fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
1117 fprintf(file, "\t%saddress = (void *)(%s%s%s);\n", string,
1118 ref, arg->argVarName, subindex);
1119 if (VarArray)
1120 fprintf(file, "\t%scount = %s%s%s;\n", string,
1121 count->argByReferenceUser ? "*" : "",
1122 count->argVarName, subindex);
1123 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendSnd)) {
1124 register argument_t *poly = arg->argPoly;
1125 const char *pref = poly->argByReferenceUser ? "*" : "";
1126
1127 fprintf(file, "\t%sdisposition = %s%s;\n", string,
1128 pref, poly->argVarName);
1129 }
1130 if (arg->argDeallocate == d_MAYBE)
1131 fprintf(file, "\t%sdeallocate = %s;\n", string,
1132 arg->argDealloc->argVarName);
1133
1134 fprintf(file, "#else\t/* UseStaticTemplates */\n");
1135
1136 fprintf(file, "\t%saddress = (void *)(%s%s%s);\n",
1137 string, ref, arg->argVarName, subindex);
1138 if (VarArray)
1139 fprintf(file, "\t%scount = %s%s%s;\n", string,
1140 count->argByReferenceUser ? "*" : "",
1141 count->argVarName, subindex);
1142 else
1143 fprintf(file, "\t%scount = %d;\n", string,
1144 howmany);
1145 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendSnd)) {
1146 register argument_t *poly = arg->argPoly;
1147 const char *pref = poly->argByReferenceUser ? "*" : "";
1148
1149 fprintf(file, "\t%sdisposition = %s%s;\n",
1150 string, pref, poly->argVarName);
1151 } else
1152 fprintf(file, "\t%sdisposition = %s;\n",
1153 string, howstr);
1154 if (arg->argDeallocate == d_MAYBE)
1155 fprintf(file, "\t%sdeallocate = %s;\n", string,
1156 arg->argDealloc->argVarName);
1157 else
1158 fprintf(file, "\t%sdeallocate = %s;\n", string,
1159 (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE");
1160 fprintf(file, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string);
1161
1162 fprintf(file, "#endif\t/* UseStaticTemplates */\n");
1163 fprintf(file, "\n");
1164
1165 if (IS_MULTIPLE_KPD(it)) {
1166 fprintf(file, "\t }\n");
1167 if (it->itVarArray) {
1168 fprintf(file, "\t for (i = %s; i < %d; ptr++, i++) {\n",
1169 arg->argCount->argVarName, it->itKPD_Number);
1170 /* fill the rest of the statically allocated KPD entries with size NULL */
1171 fprintf(file, "#if\tUseStaticTemplates\n");
1172 fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
1173 if (!VarArray)
1174 fprintf(file, "\t%scount = 0;\n", string);
1175 /* otherwise the size in the template would be != 0! */
1176 fprintf(file, "#else\t/* UseStaticTemplates */\n");
1177 fprintf(file, "\t%scount = 0;\n", string);
1178 fprintf(file, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string);
1179 fprintf(file, "#endif\t/* UseStaticTemplates */\n");
1180 fprintf(file, "\t }\n");
1181 }
1182 fprintf(file, "\t}\n");
1183 }
1184 fprintf(file, "\n");
1185 }
1186
1187 static void
WriteOverwriteTemplate(FILE * file,routine_t * rt)1188 WriteOverwriteTemplate(FILE *file, routine_t *rt)
1189 {
1190 register argument_t *arg;
1191 char string[MAX_STR_LEN];
1192 const char *subindex = "";
1193 boolean_t finish = FALSE;
1194
1195 fprintf(file, "\t/* Initialize the template for overwrite */\n");
1196 fprintf(file, "\tInOvTemplate->msgh_body.msgh_descriptor_count = %d;\n",
1197 rt->rtOverwriteKPDs);
1198 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
1199 register ipc_type_t *it = arg->argType;
1200 const char *ref = arg->argByReferenceUser ? "*" : "";
1201 argument_t *count;
1202 const char *cref;
1203 boolean_t VarIndex;
1204 u_int howmany, howbig;
1205
1206 if (akCheck(arg->argKind, akbOverwrite)) {
1207 if (arg->argFlags & flOverwrite) {
1208 if (IS_MULTIPLE_KPD(it)) {
1209 WriteKPD_Iterator(file, FALSE, TRUE, it->itVarArray, arg, TRUE);
1210 if (it->itVarArray)
1211 finish = TRUE;
1212 sprintf(string, "\tptr->");
1213 subindex = "[i]";
1214 count = arg->argSubCount;
1215 VarIndex = it->itElement->itVarArray;
1216 howmany = it->itElement->itNumber;
1217 howbig = it->itElement->itSize;
1218 } else {
1219 sprintf(string, "InOvTemplate->%s.", arg->argMsgField);
1220 subindex = "";
1221 count = arg->argCount;
1222 VarIndex = it->itVarArray;
1223 howmany = it->itNumber;
1224 howbig = it->itSize;
1225 }
1226
1227 fprintf(file, "\t%saddress = (void *) %s%s%s;\n", string,
1228 ref, arg->argVarName, subindex);
1229
1230 if (it->itPortType) {
1231 fprintf(file, "\t%scount = ", string);
1232 if (VarIndex) {
1233 cref = count->argByReferenceUser ? "*" : "";
1234 fprintf(file, "%s%s%s;\n", cref, count->argVarName, subindex);
1235 } else
1236 fprintf(file, "%d;\n", howmany);
1237 } else {
1238 fprintf(file, "\t%ssize = ", string);
1239 if (VarIndex) {
1240 cref = count->argByReferenceUser ? "*" : "";
1241 if (count->argMultiplier > 1 || howbig > 8)
1242 fprintf(file, "%s%s%s * %d;\n", cref, count->argVarName, subindex,
1243 count->argMultiplier * howbig / 8);
1244 else
1245 fprintf(file, "%s%s%s;\n", cref, count->argVarName, subindex);
1246 }
1247 else
1248 fprintf(file, "\t%ssize = %d;\n", string, (howmany * howbig + 7)/8);
1249 }
1250 fprintf(file, "\t%scopy = MACH_MSG_OVERWRITE;\n", string);
1251 fprintf(file, "\t%stype = MACH_MSG_OOL_%sDESCRIPTOR;\n", string,
1252 (it->itPortType) ? "PORTS_" : "");
1253 if (IS_MULTIPLE_KPD(it))
1254 fprintf(file, "\t }\n");
1255 if (finish) {
1256 fprintf(file, "\t for (i = %s%s; i < %d; ptr++, i++) {\n",
1257 (arg->argCount->argByReferenceUser) ? "*" : "",
1258 arg->argCount->argVarName, it->itKPD_Number);
1259 fprintf(file, "\t\tptr->copy = MACH_MSG_ALLOCATE;\n");
1260 fprintf(file, "\t\tptr->type = MACH_MSG_OOL_%sDESCRIPTOR;\n",
1261 (it->itPortType) ? "PORTS_" : "");
1262 fprintf(file, "\t }\n");
1263 }
1264 if (IS_MULTIPLE_KPD(it))
1265 fprintf(file, "\t}\n");
1266 } else {
1267 /* just a placeholder */
1268 if (IS_MULTIPLE_KPD(it)) {
1269 WriteKPD_Iterator(file, FALSE, TRUE, FALSE, arg, TRUE);
1270 fprintf(file, "\t\tptr->copy = MACH_MSG_ALLOCATE;\n");
1271 fprintf(file, "\t\tptr->type = MACH_MSG_OOL_%sDESCRIPTOR;\n",
1272 (it->itPortType) ? "PORTS_" : "");
1273 fprintf(file, "\t }\n\t}\n");
1274 }
1275 else {
1276 fprintf(file, "\tInOvTemplate->%s.copy = MACH_MSG_ALLOCATE;\n", arg->argMsgField);
1277 /* not sure whether this is needed */
1278 fprintf(file, "\tInOvTemplate->%s.type = MACH_MSG_OOL_%sDESCRIPTOR;\n",
1279 arg->argMsgField, (it->itPortType) ? "PORTS_" : "");
1280 }
1281 }
1282 }
1283 }
1284 fprintf(file, "\n");
1285 }
1286
1287 /*************************************************************
1288 * Writes code to copy an argument into the request message.
1289 * Called by WriteRoutine for each argument that is to placed
1290 * in the request message.
1291 *************************************************************/
1292
1293 static void
WritePackArgValueNormal(FILE * file,register argument_t * arg)1294 WritePackArgValueNormal(FILE *file, register argument_t *arg)
1295 {
1296 register ipc_type_t *it = arg->argType;
1297 const char *ref = (arg->argByReferenceUser ||
1298 it->itNativePointer) ? "*" : "";
1299
1300 if (IS_VARIABLE_SIZED_UNTYPED(it) || it->itNoOptArray) {
1301 if (it->itString) {
1302 /*
1303 * Copy variable-size C string with mig_strncpy.
1304 * Save the string length (+ 1 for trailing 0)
1305 * in the argument`s count field.
1306 */
1307 fprintf(file,
1308 "\tInP->%s = mig_strncpy(InP->%s, %s, %d);\n",
1309 arg->argCount->argMsgField,
1310 arg->argMsgField,
1311 arg->argVarName,
1312 it->itNumber);
1313 } else if (it->itNoOptArray)
1314 fprintf(file, "\t(void)memcpy((char *) InP->%s, (const char *) %s%s, %d);\n",
1315 arg->argMsgField, ref, arg->argVarName, it->itTypeSize);
1316 else {
1317
1318 /*
1319 * Copy in variable-size inline array with (void)memcpy,
1320 * after checking that number of elements doesn`t
1321 * exceed declared maximum.
1322 */
1323 register argument_t *count = arg->argCount;
1324 const char *countRef = count->argByReferenceUser ? "*" : "";
1325 register ipc_type_t *btype = it->itElement;
1326
1327 /* Note btype->itNumber == count->argMultiplier */
1328
1329 if (akIdent(arg->argKind) != akeSubCount) {
1330 /* we skip the SubCount case, as we have already taken care of */
1331 fprintf(file, "\tif (%s%s > %d) {\n",
1332 countRef, count->argVarName,
1333 it->itNumber/btype->itNumber);
1334 WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE");
1335 fprintf(file, "\t}\n");
1336 }
1337
1338 fprintf(file, "\t(void)memcpy((char *) InP->%s, (const char *) %s%s, ",
1339 arg->argMsgField, ref, arg->argVarName);
1340 if (btype->itTypeSize > 1)
1341 fprintf(file, "%d * ", btype->itTypeSize);
1342 fprintf(file, "%s%s);\n", countRef, count->argVarName);
1343 }
1344 }
1345 else if (IS_OPTIONAL_NATIVE(it)) {
1346 fprintf(file, "\tif ((InP->__Present__%s = (%s != %s))) {\n",
1347 arg->argMsgField, arg->argVarName, it->itBadValue);
1348 WriteCopyType(file, it, "\tInP->%s.__Real__%s", "/* %s%s */ %s%s",
1349 arg->argMsgField, arg->argMsgField,
1350 ref, arg->argVarName);
1351 fprintf(file, "\t}\n");
1352 }
1353 else
1354 WriteCopyType(file, it, "InP->%s", "/* %s */ %s%s",
1355 arg->argMsgField, ref, arg->argVarName);
1356 fprintf(file, "\n");
1357 }
1358
1359 /*
1360 * Calculate the size of a variable-length message field.
1361 */
1362 static void
WriteArgSizeVariable(FILE * file,register argument_t * arg,ipc_type_t * ptype)1363 WriteArgSizeVariable(FILE *file, register argument_t *arg, ipc_type_t *ptype)
1364 {
1365 register int bsize = ptype->itElement->itTypeSize;
1366 register argument_t *count = arg->argCount;
1367
1368 if (PackMsg == FALSE) {
1369 fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize);
1370 return;
1371 }
1372
1373 /* If the base type size of the data field isn`t a multiple of 4,
1374 we have to round up. */
1375 if (bsize % itWordAlign != 0)
1376 fprintf(file, "_WALIGN_");
1377 fprintf(file, "(");
1378 if (bsize > 1)
1379 fprintf(file, "%d * ", bsize);
1380 if (ptype->itString)
1381 /* get count from descriptor in message */
1382 fprintf(file, "InP->%s", count->argMsgField);
1383 else
1384 /* get count from argument */
1385 fprintf(file, "%s%s",
1386 count->argByReferenceUser ? "*" : "",
1387 count->argVarName);
1388 fprintf(file, ")");
1389 }
1390
1391 static void
WriteArgSizeOptional(FILE * file,argument_t * arg,ipc_type_t * ptype)1392 WriteArgSizeOptional(FILE *file, argument_t *arg, ipc_type_t *ptype)
1393 {
1394
1395 fprintf(file, "(InP->__Present__%s ? _WALIGNSZ_(%s) : 0)",
1396 arg->argVarName, ptype->itUserType);
1397 }
1398
1399 static void
WriteArgSize(FILE * file,argument_t * arg)1400 WriteArgSize(FILE *file, argument_t *arg)
1401
1402 {
1403 ipc_type_t *ptype = arg->argType;
1404
1405 if (IS_OPTIONAL_NATIVE(ptype))
1406 WriteArgSizeOptional(file, arg, ptype);
1407 else
1408 WriteArgSizeVariable(file, arg, ptype);
1409 }
1410
1411 /*
1412 * Adjust message size and advance request pointer.
1413 * Called after packing a variable-length argument that
1414 * has more arguments following.
1415 */
1416 static void
WriteAdjustMsgSize(FILE * file,register argument_t * arg)1417 WriteAdjustMsgSize(FILE *file, register argument_t *arg)
1418 {
1419 register ipc_type_t *ptype = arg->argType;
1420
1421 /* There are more In arguments. We need to adjust msgh_size
1422 and advance InP, so we save the size of the current field
1423 in msgh_size_delta. */
1424
1425 fprintf(file, "\tmsgh_size_delta = ");
1426 WriteArgSize(file, arg);
1427 fprintf(file, ";\n");
1428
1429 if (arg->argRequestPos == 0) {
1430 /* First variable-length argument. The previous msgh_size value
1431 is the minimum request size. */
1432
1433 fprintf(file, "\tmsgh_size = ");
1434 rtMinRequestSize(file, arg->argRoutine, "Request");
1435 fprintf(file, " + msgh_size_delta;\n");
1436 } else
1437 fprintf(file, "\tmsgh_size += msgh_size_delta;\n");
1438
1439 if (PackMsg == TRUE) {
1440 fprintf(file,
1441 "\tInP = (Request *) ((pointer_t) InP + msgh_size_delta - ");
1442 if (IS_OPTIONAL_NATIVE(ptype))
1443 fprintf(file,
1444 "_WALIGNSZ_(%s)",
1445 ptype->itUserType);
1446 else
1447 fprintf(file,
1448 "%d",
1449 ptype->itTypeSize + ptype->itPadSize);
1450 fprintf(file,
1451 ");\n\n");
1452 }
1453 }
1454
1455 /*
1456 * Calculate the size of the message. Called after the
1457 * last argument has been packed.
1458 */
1459 static void
WriteFinishMsgSize(FILE * file,register argument_t * arg)1460 WriteFinishMsgSize(FILE *file, register argument_t *arg)
1461 {
1462 /* No more In arguments. If this is the only variable In
1463 argument, the previous msgh_size value is the minimum
1464 request size. */
1465
1466 if (arg->argRequestPos == 0) {
1467 fprintf(file, "\tmsgh_size = ");
1468 rtMinRequestSize(file, arg->argRoutine, "Request");
1469 fprintf(file, " + (");
1470 WriteArgSize(file, arg);
1471 fprintf(file, ");\n");
1472 }
1473 else {
1474 fprintf(file, "\tmsgh_size += ");
1475 WriteArgSize(file, arg);
1476 fprintf(file, ";\n");
1477 }
1478 }
1479
1480 static void
WriteInitializeCount(FILE * file,register argument_t * arg)1481 WriteInitializeCount(FILE *file, register argument_t *arg)
1482 {
1483 register ipc_type_t *ptype = arg->argCInOut->argParent->argType;
1484 register ipc_type_t *btype = ptype->itElement;
1485
1486 fprintf(file, "\tif (%s%s < %d)\n",
1487 arg->argByReferenceUser ? "*" : "",
1488 arg->argVarName,
1489 ptype->itNumber/btype->itNumber);
1490 fprintf(file, "\t\tInP->%s = %s%s;\n",
1491 arg->argMsgField,
1492 arg->argByReferenceUser ? "*" : "",
1493 arg->argVarName);
1494 fprintf(file, "\telse\n");
1495 fprintf(file, "\t\tInP->%s = %d;\n",
1496 arg->argMsgField, ptype->itNumber/btype->itNumber);
1497 fprintf(file, "\n");
1498 }
1499
1500 /*
1501 * Generate code to fill in all of the request arguments and their
1502 * message types.
1503 */
1504 static void
WriteRequestArgs(FILE * file,register routine_t * rt)1505 WriteRequestArgs(FILE *file, register routine_t *rt)
1506 {
1507 register argument_t *arg;
1508 register argument_t *lastVarArg;
1509
1510 /*
1511 * 1. The Kernel Processed Data
1512 */
1513 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
1514 if (akCheckAll(arg->argKind, akbSendSnd|akbSendKPD))
1515 (*arg->argKPD_Pack)(file, arg);
1516
1517 /*
1518 * 2. The Data Stream
1519 */
1520 lastVarArg = argNULL;
1521 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
1522 /*
1523 * Adjust message size and advance message pointer if
1524 * the last request argument was variable-length and the
1525 * request position will change.
1526 */
1527 if (lastVarArg != argNULL &&
1528 lastVarArg->argRequestPos < arg->argRequestPos)
1529 {
1530 WriteAdjustMsgSize(file, lastVarArg);
1531 lastVarArg = argNULL;
1532 }
1533
1534 if ((akIdent(arg->argKind) == akeCountInOut) &&
1535 akCheck(arg->argKind, akbSendSnd))
1536 WriteInitializeCount(file, arg);
1537 else if (akCheckAll(arg->argKind, akbSendSnd|akbSendBody))
1538 WritePackArgValueNormal(file, arg);
1539 /*
1540 * Remember whether this was variable-length.
1541 */
1542 if (akCheckAll(arg->argKind, akbSendSnd|akbSendBody|akbVariable))
1543 lastVarArg = arg;
1544 }
1545 /*
1546 * Finish the message size.
1547 */
1548 if (lastVarArg != argNULL)
1549 WriteFinishMsgSize(file, lastVarArg);
1550 }
1551
1552 /*************************************************************
1553 * Writes code to check that the return msgh_id is correct and that
1554 * the size of the return message is correct. Called by
1555 * WriteRoutine.
1556 *************************************************************/
1557 static void
WriteCheckIdentity(FILE * file,routine_t * rt)1558 WriteCheckIdentity(FILE *file, routine_t *rt)
1559 {
1560 fprintf(file, "\tif (Out0P->Head.msgh_id != %d) {\n",
1561 rt->rtNumber + SubsystemBase + 100);
1562 fprintf(file, "\t if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)\n");
1563 fprintf(file, "\t\t{ return MIG_SERVER_DIED; }\n");
1564 fprintf(file, "\t else\n");
1565 fprintf(file, "\t\t{ return MIG_REPLY_MISMATCH; }\n");
1566 fprintf(file, "\t}\n");
1567 fprintf(file, "\n");
1568 if (!rt->rtSimpleReply)
1569 fprintf(file, "\tmsgh_simple = !(Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);\n");
1570 fprintf(file, "#if\t__MigTypeCheck\n");
1571
1572 if (!rt->rtNoReplyArgs)
1573 fprintf(file, "\tmsgh_size = Out0P->Head.msgh_size;\n\n");
1574
1575 if (rt->rtSimpleReply)
1576 {
1577 /* Expecting a simple message. We can factor out the check for
1578 a simple message, since the error reply message is also simple.
1579 */
1580 fprintf(file,
1581 "\tif ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n");
1582 if (rt->rtNoReplyArgs)
1583 fprintf(file, "\t (Out0P->Head.msgh_size != sizeof(__Reply)))\n");
1584 else {
1585 /*
1586 * We have an error iff:
1587 * 1) the message size is not the one expected AND
1588 * 2) the message size is also different from sizeof(mig_reply_error_t)
1589 * or the RetCode == KERN_SUCCESS
1590 */
1591 if (rt->rtNumReplyVar > 0) {
1592 fprintf(file, "\t ((msgh_size > sizeof(__Reply) || msgh_size < ");
1593 rtMinReplySize(file, rt, "__Reply");
1594 fprintf(file, ") &&\n");
1595 } else
1596 fprintf(file, "\t ((msgh_size != sizeof(__Reply)) &&\n");
1597 fprintf(file, "\t (msgh_size != sizeof(mig_reply_error_t) ||\n");
1598 fprintf(file, "\t Out0P->RetCode == KERN_SUCCESS)))\n");
1599 }
1600 }
1601 else {
1602 /* Expecting a complex message. */
1603
1604 fprintf(file, "\tif ((msgh_simple || Out0P->msgh_body.msgh_descriptor_count != %d ||\n",
1605 rt->rtReplyKPDs);
1606 if (rt->rtNumReplyVar > 0) {
1607 fprintf(file, "\t msgh_size < ");
1608 rtMinReplySize(file, rt, "__Reply");
1609 fprintf(file, " || msgh_size > sizeof(__Reply)) &&\n");
1610 } else
1611 fprintf(file, "\t msgh_size != sizeof(__Reply)) &&\n");
1612 fprintf(file, "\t (!msgh_simple || msgh_size != sizeof(mig_reply_error_t) ||\n");
1613 fprintf(file, "\t ((mig_reply_error_t *)Out0P)->RetCode == KERN_SUCCESS))\n");
1614 }
1615 fprintf(file, "\t\t{ return MIG_TYPE_ERROR ; }\n");
1616 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
1617 fprintf(file, "\n");
1618 }
1619
1620 /*************************************************************
1621 * Write code to generate error handling code if the RetCode
1622 * argument of a Routine is not KERN_SUCCESS.
1623 *************************************************************/
1624 static void
WriteRetCodeCheck(FILE * file,routine_t * rt)1625 WriteRetCodeCheck(FILE *file, routine_t *rt)
1626 {
1627 if (rt->rtSimpleReply)
1628 fprintf(file, "\tif (Out0P->RetCode != KERN_SUCCESS) {\n");
1629 else
1630 fprintf(file, "\tif (msgh_simple) {\n");
1631 if (CheckNDR) {
1632 fprintf(file, "#ifdef\t__NDR_convert__mig_reply_error_t__defined\n");
1633 fprintf(file, "\t\t__NDR_convert__mig_reply_error_t((mig_reply_error_t *)Out0P);\n");
1634 fprintf(file, "#endif\t/* __NDR_convert__mig_reply_error_t__defined */\n");
1635 }
1636 fprintf(file, "\t\treturn ((mig_reply_error_t *)Out0P)->RetCode;\n");
1637 fprintf(file, "\t}\n");
1638 fprintf(file, "\n");
1639 }
1640
1641 /*
1642 * argKPD_TypeCheck discipline for Port types.
1643 */
1644 static void
WriteTCheckKPD_port(FILE * file,register argument_t * arg)1645 WriteTCheckKPD_port(FILE *file, register argument_t *arg)
1646 {
1647 register ipc_type_t *it = arg->argType;
1648 const char *tab = "";
1649 char string[MAX_STR_LEN];
1650 boolean_t close = FALSE;
1651
1652 if (IS_MULTIPLE_KPD(it)) {
1653 WriteKPD_Iterator(file, FALSE, FALSE, FALSE, arg, TRUE);
1654 (void)sprintf(string, "ptr->");
1655 tab = "\t";
1656 close = TRUE;
1657 } else
1658 (void)sprintf(string, "Out%dP->%s.", arg->argReplyPos, arg->argMsgField);
1659 fprintf(file, "\t%sif (%stype != MACH_MSG_PORT_DESCRIPTOR",
1660 tab, string);
1661 if (arg->argPoly == argNULL && !it->itVarArray)
1662 /* we can't check disposition when poly or VarArray,
1663 (because some of the entries could be empty) */
1664 fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, it->itOutNameStr);
1665 fprintf(file,
1666 ") {\n"
1667 "\t\t%s" "return MIG_TYPE_ERROR;\n"
1668 "\t%s" "}\n"
1669 , tab, tab);
1670 if (close)
1671 fprintf(file, "\t }\n\t}\n");
1672 }
1673
1674 /*
1675 * argKPD_TypeCheck discipline for out-of-line types.
1676 */
1677 static void
WriteTCheckKPD_ool(FILE * file,register argument_t * arg)1678 WriteTCheckKPD_ool(FILE *file, register argument_t *arg)
1679 {
1680 register ipc_type_t *it = arg->argType;
1681 const char *tab;
1682 char string[MAX_STR_LEN];
1683 boolean_t test;
1684 u_int howmany, howbig;
1685
1686 if (IS_MULTIPLE_KPD(it)) {
1687 WriteKPD_Iterator(file, FALSE, FALSE, FALSE, arg, TRUE);
1688 tab = "\t";
1689 sprintf(string, "ptr->");
1690 howmany = it->itElement->itNumber;
1691 howbig = it->itElement->itSize;
1692 test = !it->itVarArray && !it->itElement->itVarArray;
1693 } else {
1694 tab = "";
1695 sprintf(string, "Out%dP->%s.", arg->argReplyPos, arg->argMsgField);
1696 howmany = it->itNumber;
1697 howbig = it->itSize;
1698 test = !it->itVarArray;
1699 }
1700
1701 fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_DESCRIPTOR", tab, string);
1702 if (test)
1703 /* if VarArray we may use no-op; if itElement->itVarArray size might change */
1704 fprintf(file, " ||\n\t%s %ssize != %d", tab, string, (howmany * howbig + 7)/8);
1705 fprintf(file,
1706 ") {\n"
1707 "\t\t%s" "return MIG_TYPE_ERROR;\n"
1708 "\t%s" "}\n"
1709 , tab, tab);
1710 if (IS_MULTIPLE_KPD(it))
1711 fprintf(file, "\t }\n\t}\n");
1712 }
1713
1714 /*
1715 * argKPD_TypeCheck discipline for out-of-line Port types.
1716 */
1717 static void
WriteTCheckKPD_oolport(FILE * file,register argument_t * arg)1718 WriteTCheckKPD_oolport(FILE *file, register argument_t *arg)
1719 {
1720 register ipc_type_t *it = arg->argType;
1721 const char *tab;
1722 char string[MAX_STR_LEN];
1723 boolean_t test;
1724 u_int howmany;
1725 const char *howstr;
1726
1727 if (IS_MULTIPLE_KPD(it)) {
1728 WriteKPD_Iterator(file, FALSE, FALSE, FALSE, arg, TRUE);
1729 tab = "\t";
1730 sprintf(string, "ptr->");
1731 howmany = it->itElement->itNumber;
1732 test = !it->itVarArray && !it->itElement->itVarArray;
1733 howstr = it->itElement->itOutNameStr;
1734 } else {
1735 tab = "";
1736 sprintf(string, "Out%dP->%s.", arg->argReplyPos, arg->argMsgField);
1737 howmany = it->itNumber;
1738 test = !it->itVarArray;
1739 howstr = it->itOutNameStr;
1740 }
1741
1742 fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_PORTS_DESCRIPTOR", tab, string);
1743 if (test)
1744 /* if VarArray we may use no-op; if itElement->itVarArray size might change */
1745 fprintf(file, " ||\n\t%s %scount != %d", tab, string, howmany);
1746 if (arg->argPoly == argNULL)
1747 fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, howstr);
1748 fprintf(file, ") {\n"
1749 "\t\t%s" "return MIG_TYPE_ERROR;\n"
1750 "\t%s" "}\n"
1751 ,tab, tab);
1752 if (IS_MULTIPLE_KPD(it))
1753 fprintf(file, "\t }\n\t}\n");
1754 }
1755
1756 /*************************************************************
1757 * Writes code to check that the type of each of the arguments
1758 * in the reply message is what is expected. Called by
1759 * WriteRoutine for each out && typed argument in the reply message.
1760 *************************************************************/
1761 static void
WriteTypeCheck(FILE * file,register argument_t * arg)1762 WriteTypeCheck(FILE *file, register argument_t *arg)
1763 {
1764 fprintf(file, "#if\t__MigTypeCheck\n");
1765 (*arg->argKPD_TypeCheck)(file, arg);
1766 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
1767 }
1768
1769
1770 /*
1771 * argKPD_Extract discipline for Port types.
1772 */
1773 static void
WriteExtractKPD_port(FILE * file,register argument_t * arg)1774 WriteExtractKPD_port(FILE *file, register argument_t *arg)
1775 {
1776 register ipc_type_t *it = arg->argType;
1777 const char *ref = arg->argByReferenceUser ? "*" : "";
1778 const char *subindex;
1779 const char *recast = "";
1780 ipc_type_t *real_it;
1781
1782 real_it = (IS_MULTIPLE_KPD(it)) ? it->itElement : it;
1783 #ifdef MIG_KERNEL_PORT_CONVERSION
1784 if (IsKernelUser && streql(real_it->itUserType, "ipc_port_t"))
1785 recast = "(mach_port_t)";
1786 #endif
1787 if (IS_MULTIPLE_KPD(it)) {
1788 WriteKPD_Iterator(file, FALSE, FALSE, it->itVarArray, arg, FALSE);
1789
1790 fprintf(file, "\t\t%s[i] = %sptr->name;\n",
1791 arg->argVarName, recast);
1792 if (it->itVarArray) {
1793 register argument_t *count = arg->argCount;
1794 const char *cref = count->argByReferenceUser ? "*" : "";
1795
1796 fprintf(file, "\t if (Out%dP->%s > %s%s)\n", count->argReplyPos,
1797 count->argVarName, cref, count->argVarName);
1798 WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE");
1799 }
1800 fprintf(file, "\t}\n");
1801 subindex = "[0]";
1802 }
1803 else {
1804 fprintf(file, "\t%s%s = %sOut%dP->%s.name;\n", ref, arg->argVarName, recast, arg->argReplyPos, arg->argMsgField);
1805 subindex = "";
1806 }
1807
1808 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnRcv)) {
1809 register argument_t *poly = arg->argPoly;
1810 const char *pref = poly->argByReferenceUser ? "*" : "";
1811
1812 fprintf(file, "\t%s%s = Out%dP->%s%s.disposition;\n",
1813 pref, poly->argVarName, arg->argReplyPos, arg->argMsgField, subindex);
1814 }
1815 }
1816
1817 /*
1818 * argKPD_Extract discipline for out-of-line types.
1819 */
1820 static void
WriteExtractKPD_ool(FILE * file,register argument_t * arg)1821 WriteExtractKPD_ool(FILE *file, register argument_t *arg)
1822 {
1823 const char *ref = arg->argByReferenceUser ? "*" : "";
1824 register ipc_type_t *it = arg->argType;
1825
1826 if (IS_MULTIPLE_KPD(it)) {
1827 WriteKPD_Iterator(file, FALSE, FALSE, it->itVarArray, arg, FALSE);
1828 fprintf(file, "\t\t%s[i] = ptr->address;\n",
1829 arg->argVarName);
1830 fprintf(file, "\t}\n");
1831 } else
1832 fprintf(file, "\t%s%s = (%s)(Out%dP->%s.address);\n",
1833 ref, arg->argVarName, arg->argType->itUserType,
1834 arg->argReplyPos, arg->argMsgField);
1835 /*
1836 * In case of variable sized arrays,
1837 * the count field will be retrieved from the untyped
1838 * section of the message
1839 */
1840 }
1841
1842 /*
1843 * argKPD_Extract discipline for out-of-line Port types.
1844 */
1845 static void
WriteExtractKPD_oolport(FILE * file,register argument_t * arg)1846 WriteExtractKPD_oolport(FILE *file, register argument_t *arg)
1847 {
1848 const char *ref = arg->argByReferenceUser ? "*" : "";
1849 register ipc_type_t *it = arg->argType;
1850 const char *subindex;
1851
1852 if (IS_MULTIPLE_KPD(it)) {
1853 WriteKPD_Iterator(file, FALSE, FALSE, it->itVarArray, arg, FALSE);
1854 fprintf(file, "\t\t%s[i] = ptr->address;\n",
1855 arg->argVarName);
1856 fprintf(file, "\t}\n");
1857 subindex = "[0]";
1858 }
1859 else {
1860 fprintf(file, "\t%s%s = (%s)(Out%dP->%s.address);\n", ref, arg->argVarName, arg->argType->itUserType, arg->argReplyPos, arg->argMsgField);
1861 subindex = "";
1862 }
1863 /*
1864 * In case of variable sized arrays,
1865 * the count field will be retrieved from the untyped
1866 * section of the message
1867 */
1868 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnRcv)) {
1869 register argument_t *poly = arg->argPoly;
1870 const char *pref = poly->argByReferenceUser ? "*" : "";
1871
1872 fprintf(file, "\t%s%s = Out%dP->%s%s.disposition;\n",
1873 pref, poly->argVarName, arg->argReplyPos, arg->argMsgField, subindex);
1874 }
1875 }
1876
1877 /*************************************************************
1878 * Write code to copy an argument from the reply message
1879 * to the parameter. Called by WriteRoutine for each argument
1880 * in the reply message.
1881 *************************************************************/
1882
1883 static void
WriteExtractArgValueNormal(FILE * file,register argument_t * arg)1884 WriteExtractArgValueNormal(FILE *file, register argument_t *arg)
1885 {
1886 register ipc_type_t *argType = arg->argType;
1887 const char *ref = arg->argByReferenceUser ? "*" : "";
1888 char who[20];
1889
1890 if (akCheck(arg->argKind, akbUserImplicit))
1891 sprintf(who, "TrailerP");
1892 else
1893 sprintf(who, "Out%dP", arg->argReplyPos);
1894
1895 if (IS_VARIABLE_SIZED_UNTYPED(argType) || argType->itNoOptArray) {
1896 if (argType->itString) {
1897 /*
1898 * Copy out variable-size C string with mig_strncpy.
1899 */
1900 fprintf(file, "\t(void) mig_strncpy(%s%s, %s->%s, %d);\n",
1901 ref,
1902 arg->argVarName,
1903 who,
1904 arg->argMsgField,
1905 argType->itNumber);
1906 }
1907 else if (argType->itNoOptArray)
1908 fprintf(file, "\t(void)memcpy((char *) %s%s, (const char *) %s->%s, %d);\n",
1909 ref, arg->argVarName, who, arg->argMsgField, argType->itTypeSize);
1910 else {
1911
1912 /*
1913 * Copy out variable-size inline array with (void)memcpy,
1914 * after checking that number of elements doesn`t
1915 * exceed user`s maximum.
1916 */
1917 register argument_t *count = arg->argCount;
1918 const char *countRef = count->argByReferenceUser ? "*" : "";
1919 register ipc_type_t *btype = argType->itElement;
1920
1921 /* Note count->argMultiplier == btype->itNumber */
1922 /* Note II: trailer logic isn't supported in this case */
1923 fprintf(file, "\tif (Out%dP->%s", count->argReplyPos, count->argMsgField);
1924 if (arg->argCountInOut) {
1925 fprintf(file, " > %s%s) {\n", countRef, count->argVarName);
1926 }
1927 else {
1928 fprintf(file, " > %d) {\n", argType->itNumber/btype->itNumber);
1929 }
1930
1931 /*
1932 * If number of elements is too many for user receiving area,
1933 * fill user`s area as much as possible. Return the correct
1934 * number of elements.
1935 */
1936 fprintf(file, "\t\t(void)memcpy((char *) %s%s, (const char *) Out%dP->%s, ",
1937 ref, arg->argVarName, arg->argReplyPos, arg->argMsgField);
1938 if (btype->itTypeSize > 1)
1939 fprintf(file, "%d * ", btype->itTypeSize);
1940 if (arg->argCountInOut) {
1941 fprintf(file, " %s%s);\n", countRef, count->argVarName);
1942 }
1943 else {
1944 fprintf(file, " %d);\n", argType->itNumber/btype->itNumber);
1945 }
1946 fprintf(file, "\t\t%s%s = Out%dP->%s", countRef, count->argVarName, count->argReplyPos, count->argMsgField);
1947 fprintf(file, ";\n");
1948 WriteReturnMsgError(file, arg->argRoutine, TRUE, arg, "MIG_ARRAY_TOO_LARGE");
1949
1950 fprintf(file, "\t}\n");
1951
1952 fprintf(file, "\t(void)memcpy((char *) %s%s, (const char *) Out%dP->%s, ",
1953 ref, arg->argVarName, arg->argReplyPos, arg->argMsgField);
1954 if (btype->itTypeSize > 1)
1955 fprintf(file, "%d * ",
1956 btype->itTypeSize);
1957 fprintf(file, "Out%dP->%s);\n",
1958 count->argReplyPos, count->argMsgField);
1959 }
1960 }
1961 else
1962 WriteCopyType(file, argType,
1963 "%s%s", "/* %s%s */ %s->%s",
1964 ref, arg->argVarName, who, arg->argMsgField);
1965 fprintf(file, "\n");
1966 }
1967
1968 static void
WriteCalcArgSize(FILE * file,register argument_t * arg)1969 WriteCalcArgSize(FILE *file, register argument_t *arg)
1970 {
1971 register ipc_type_t *ptype = arg->argType;
1972 register ipc_type_t *btype = ptype->itElement;
1973 argument_t *count = arg->argCount;
1974 int multiplier = btype->itTypeSize;
1975
1976 /* If the base type size of the data field isn`t a multiple of 4,
1977 we have to round up. */
1978 if (btype->itTypeSize % itWordAlign != 0)
1979 fprintf(file, "_WALIGN_(");
1980
1981 fprintf(file, "Out%dP->%s", count->argReplyPos, count->argMsgField);
1982 if (multiplier > 1)
1983 fprintf(file, " * %d", multiplier);
1984
1985 if (btype->itTypeSize % itWordAlign != 0)
1986 fprintf(file, ")");
1987 }
1988
1989 static void
WriteCheckArgSize(FILE * file,routine_t * rt,argument_t * arg,const char * comparator)1990 WriteCheckArgSize(FILE *file, routine_t *rt, argument_t *arg, const char *comparator)
1991 {
1992 register ipc_type_t *ptype = arg->argType;
1993 register ipc_type_t *btype = ptype->itElement;
1994 argument_t *count = arg->argCount;
1995 int multiplier = btype->itTypeSize;
1996
1997 fprintf(file, "\tif (((msgh_size - ");
1998 rtMinReplySize(file, rt, "__Reply");
1999 fprintf(file, ")");
2000 if (multiplier > 1)
2001 fprintf(file, " / %d", multiplier);
2002 fprintf(file, "< Out%dP->%s) ||\n", count->argReplyPos, count->argMsgField);
2003 fprintf(file, "\t (msgh_size %s ", comparator);
2004 rtMinReplySize(file, rt, "__Reply");
2005 fprintf(file, " + ");
2006 WriteCalcArgSize(file, arg);
2007 fprintf(file, ")");
2008 fprintf(file, ")\n\t\t{ return MIG_TYPE_ERROR ; }\n");
2009 }
2010
2011
2012 /* NDR Conversion routines */
2013
2014
2015 static void
WriteReplyNDRConvertIntRepArgCond(FILE * file,argument_t * arg)2016 WriteReplyNDRConvertIntRepArgCond(FILE *file, argument_t *arg)
2017 {
2018 routine_t *rt = arg->argRoutine;
2019
2020 fprintf(file, "defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
2021 }
2022
2023 static void
WriteReplyNDRConvertCharRepArgCond(FILE * file,argument_t * arg)2024 WriteReplyNDRConvertCharRepArgCond(FILE *file, argument_t *arg)
2025 {
2026 routine_t *rt = arg->argRoutine;
2027
2028 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
2029 fprintf(file, "defined(__NDR_convert__char_rep__Reply__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
2030 else
2031 fprintf(file, "0");
2032 }
2033
2034 static void
WriteReplyNDRConvertFloatRepArgCond(FILE * file,argument_t * arg)2035 WriteReplyNDRConvertFloatRepArgCond(FILE *file, argument_t *arg)
2036 {
2037 routine_t *rt = arg->argRoutine;
2038
2039 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
2040 fprintf(file, "defined(__NDR_convert__float_rep__Reply__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
2041 else
2042 fprintf(file, "0");
2043 }
2044
2045 static void
WriteReplyNDRConvertIntRepArgDecl(FILE * file,argument_t * arg)2046 WriteReplyNDRConvertIntRepArgDecl(FILE *file, argument_t *arg)
2047 {
2048 WriteNDRConvertArgDecl(file, arg, "int_rep", "Reply");
2049 }
2050
2051 static void
WriteReplyNDRConvertCharRepArgDecl(FILE * file,argument_t * arg)2052 WriteReplyNDRConvertCharRepArgDecl(FILE *file, argument_t *arg)
2053 {
2054 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
2055 WriteNDRConvertArgDecl(file, arg, "char_rep", "Reply");
2056 }
2057
2058 static void
WriteReplyNDRConvertFloatRepArgDecl(FILE * file,argument_t * arg)2059 WriteReplyNDRConvertFloatRepArgDecl(FILE *file, argument_t *arg)
2060 {
2061 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
2062 WriteNDRConvertArgDecl(file, arg, "float_rep", "Reply");
2063 }
2064
2065
2066
2067 static void
WriteReplyNDRConvertArgUse(FILE * file,argument_t * arg,const char * convert)2068 WriteReplyNDRConvertArgUse(FILE *file, argument_t *arg, const char *convert)
2069 {
2070 routine_t *rt = arg->argRoutine;
2071 argument_t *count = arg->argCount;
2072 char argname[MAX_STR_LEN];
2073
2074 if ((akIdent(arg->argKind) == akeCount || akIdent(arg->argKind) == akeCountInOut) &&
2075 (arg->argParent && akCheck(arg->argParent->argKind, akbReturnNdr)))
2076 return;
2077
2078 if (arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {
2079 if (count && !arg->argSameCount && !strcmp(convert, "int_rep")) {
2080 fprintf(file, "#if defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)\n", rt->rtName, count->argMsgField);
2081 fprintf(file, "\t\t__NDR_convert__int_rep__Reply__%s_t__%s(&Out%dP->%s, Out%dP->NDR.int_rep);\n", rt->rtName, count->argMsgField, count->argReplyPos, count->argMsgField, count->argReplyPos);
2082 fprintf(file, "#endif\t/* __NDR_convert__int_rep__Reply__%s_t__%s__defined */\n", rt->rtName, count->argMsgField);
2083 }
2084
2085 sprintf(argname, "(%s)(Out%dP->%s.address)", FetchServerType(arg->argType), arg->argReplyPos, arg->argMsgField);
2086 }
2087 else {
2088 sprintf(argname, "&Out%dP->%s", arg->argReplyPos, arg->argMsgField);
2089 }
2090
2091 fprintf(file, "#if defined(__NDR_convert__%s__Reply__%s_t__%s__defined)\n", convert, rt->rtName, arg->argMsgField);
2092 fprintf(file, "\t\t__NDR_convert__%s__Reply__%s_t__%s(%s, Out0P->NDR.%s", convert, rt->rtName, arg->argMsgField, argname, convert);
2093 if (count)
2094 fprintf(file, ", Out%dP->%s", count->argReplyPos, count->argMsgField);
2095 fprintf(file, ");\n");
2096 fprintf(file, "#endif /* __NDR_convert__%s__Reply__%s_t__%s__defined */\n", convert, rt->rtName, arg->argMsgField);
2097 }
2098
2099 static void
WriteReplyNDRConvertIntRepOneArgUse(FILE * file,argument_t * arg)2100 WriteReplyNDRConvertIntRepOneArgUse(FILE *file, argument_t *arg)
2101 {
2102 routine_t *rt = arg->argRoutine;
2103
2104 fprintf(file, "#if defined(__NDR_convert__int_rep__Reply__%s_t__%s__defined)\n", rt->rtName, arg->argMsgField);
2105 fprintf(file, "\tif (Out0P->NDR.int_rep != NDR_record.int_rep)\n");
2106 fprintf(file, "\t\t__NDR_convert__int_rep__Reply__%s_t__%s(&Out%dP->%s, Out%dP->NDR.int_rep);\n", rt->rtName, arg->argMsgField, arg->argReplyPos, arg->argMsgField, arg->argReplyPos);
2107 fprintf(file, "#endif\t/* __NDR_convert__int_rep__Reply__%s_t__%s__defined */\n", rt->rtName, arg->argMsgField);
2108 }
2109
2110 static void
WriteReplyNDRConvertIntRepArgUse(FILE * file,argument_t * arg)2111 WriteReplyNDRConvertIntRepArgUse(FILE *file, argument_t *arg)
2112 {
2113 WriteReplyNDRConvertArgUse(file, arg, "int_rep");
2114 }
2115
2116 static void
WriteReplyNDRConvertCharRepArgUse(FILE * file,argument_t * arg)2117 WriteReplyNDRConvertCharRepArgUse(FILE *file, argument_t *arg)
2118 {
2119 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
2120 WriteReplyNDRConvertArgUse(file, arg, "char_rep");
2121 }
2122
2123 static void
WriteReplyNDRConvertFloatRepArgUse(FILE * file,argument_t * arg)2124 WriteReplyNDRConvertFloatRepArgUse(FILE *file, argument_t *arg)
2125 {
2126 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) !=akeCountInOut && akIdent(arg->argKind) != akeRetCode)
2127 WriteReplyNDRConvertArgUse(file, arg, "float_rep");
2128 }
2129
2130 static void
WriteCheckMsgSize(FILE * file,register argument_t * arg)2131 WriteCheckMsgSize(FILE *file, register argument_t *arg)
2132 {
2133 register routine_t *rt = arg->argRoutine;
2134
2135 /* If there aren't any more Out args after this, then
2136 we can use the msgh_size_delta value directly in
2137 the TypeCheck conditional. */
2138
2139 if (CheckNDR && arg->argCount && !arg->argSameCount)
2140 WriteReplyNDRConvertIntRepOneArgUse(file, arg->argCount);
2141
2142 if (arg->argReplyPos == rt->rtMaxReplyPos) {
2143 fprintf(file, "#if\t__MigTypeCheck\n");
2144
2145 /*
2146 * emit code to verify that the server-code-provided count does not exceed the maximum count allowed by the type.
2147 */
2148 fprintf(file, "\t" "if ( Out%dP->%s > %d )\n", arg->argCount->argReplyPos, arg->argCount->argMsgField, arg->argType->itNumber);
2149 fputs("\t\t" "return MIG_TYPE_ERROR;\n", file);
2150 /* ...end... */
2151
2152 WriteCheckArgSize(file, rt, arg, "!=");
2153
2154 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
2155 }
2156 else {
2157 /* If there aren't any more variable-sized arguments after this,
2158 then we must check for exact msg-size and we don't need
2159 to update msgh_size. */
2160
2161 boolean_t LastVarArg = arg->argReplyPos+1 == rt->rtNumReplyVar;
2162
2163 /* calculate the actual size in bytes of the data field. note
2164 that this quantity must be a multiple of four. hence, if
2165 the base type size isn't a multiple of four, we have to
2166 round up. note also that btype->itNumber must
2167 divide btype->itTypeSize (see itCalculateSizeInfo). */
2168
2169 fprintf(file, "\tmsgh_size_delta = ");
2170 WriteCalcArgSize(file, arg);
2171 fprintf(file, ";\n");
2172 fprintf(file, "#if\t__MigTypeCheck\n");
2173
2174 /*
2175 * Advance message pointer if the last reply argument was
2176 * variable-length and the reply position will change.
2177 */
2178 fprintf(file, "\t" "if ( Out%dP->%s > %d )\n", arg->argCount->argReplyPos, arg->argCount->argMsgField, arg->argType->itNumber);
2179 fputs("\t\t" "return MIG_TYPE_ERROR;\n", file);
2180 /* ...end... */
2181
2182 WriteCheckArgSize(file, rt, arg, LastVarArg ? "!=" : "<");
2183
2184 if (!LastVarArg)
2185 fprintf(file, "\tmsgh_size -= msgh_size_delta;\n");
2186
2187 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
2188 }
2189 fprintf(file, "\n");
2190 }
2191
2192 static void
WriteAdjustReplyMsgPtr(FILE * file,register argument_t * arg)2193 WriteAdjustReplyMsgPtr(FILE *file, register argument_t *arg)
2194 {
2195 register ipc_type_t *ptype = arg->argType;
2196
2197 fprintf(file, "\t*Out%dPP = Out%dP = (__Reply *) ((pointer_t) Out%dP + msgh_size_delta - %d);\n\n",
2198 arg->argReplyPos+1, arg->argReplyPos +1, arg->argReplyPos, ptype->itTypeSize + ptype->itPadSize);
2199 }
2200
2201 static void
WriteReplyArgs(FILE * file,register routine_t * rt)2202 WriteReplyArgs(FILE *file, register routine_t *rt)
2203 {
2204 register argument_t *arg;
2205
2206 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
2207 if (akCheckAll(arg->argKind, akbReturnRcv|akbReturnBody)) {
2208 WriteExtractArgValueNormal(file, arg);
2209 }
2210 else if (akCheckAll(arg->argKind, akbReturnRcv|akbReturnKPD)) {
2211 /*
2212 * KPDs have argReplyPos 0, therefore they escape the above logic
2213 */
2214 (*arg->argKPD_Extract)(file, arg);
2215 }
2216 else if (akCheck(arg->argKind, akbUserImplicit)) {
2217 WriteExtractArgValueNormal(file, arg);
2218 }
2219 }
2220 }
2221
2222 /*************************************************************
2223 * Writes code to return the return value. Called by WriteRoutine
2224 * for routines and functions.
2225 *************************************************************/
2226 static void
WriteReturnValue(FILE * file,routine_t * rt)2227 WriteReturnValue(FILE *file, routine_t *rt)
2228 {
2229 /* If returning RetCode, we have already checked that it is KERN_SUCCESS */
2230 WriteReturn(file, rt, "\t", "KERN_SUCCESS", "\n");
2231 }
2232
2233 /*************************************************************
2234 * Writes the elements of the message type declaration: the
2235 * msg_type structure, the argument itself and any padding
2236 * that is required to make the argument a multiple of 4 bytes.
2237 * Called by WriteRoutine for all the arguments in the request
2238 * message first and then the reply message.
2239 *************************************************************/
2240 static void
WriteFieldDecl(FILE * file,argument_t * arg)2241 WriteFieldDecl(FILE *file, argument_t *arg)
2242 {
2243 if (akCheck(arg->argKind, akbSendKPD) ||
2244 akCheck(arg->argKind, akbReturnKPD))
2245 WriteFieldDeclPrim(file, arg, FetchKPDType);
2246 else
2247 WriteFieldDeclPrim(file, arg, FetchUserType);
2248 }
2249
2250 /* Fill in the string with an expression that refers to the size
2251 * of the specified array:
2252 */
2253 static void
GetArraySize(register argument_t * arg,char * size)2254 GetArraySize(register argument_t *arg, char *size)
2255 {
2256 register ipc_type_t *it = arg->argType;
2257
2258 if (it->itVarArray) {
2259 if (arg->argCount->argByReferenceUser) {
2260 sprintf(size, "*%s", arg->argCount->argVarName);
2261 } else
2262 sprintf(size, "%s", arg->argCount->argVarName);
2263 } else {
2264 sprintf(size, "%d", (it->itNumber * it->itSize + 7) / 8);
2265 }
2266 }
2267
2268
2269 static void
WriteRPCPortDisposition(FILE * file,register argument_t * arg)2270 WriteRPCPortDisposition(FILE *file, register argument_t *arg)
2271 {
2272 /*
2273 * According to the MIG specification, the port disposition could be different
2274 * on input and output. If we stay with this then a new bitfield will have
2275 * to be added. Right now the port disposition is the same for in and out cases.
2276 */
2277 switch(arg->argType->itInName)
2278 {
2279
2280 case MACH_MSG_TYPE_MOVE_RECEIVE:
2281 fprintf(file, " | MACH_RPC_MOVE_RECEIVE");
2282 break;
2283
2284 case MACH_MSG_TYPE_MOVE_SEND:
2285 fprintf(file, " | MACH_RPC_MOVE_SEND");
2286 break;
2287
2288 case MACH_MSG_TYPE_MOVE_SEND_ONCE:
2289 fprintf(file, " | MACH_RPC_MOVE_SEND_ONCE");
2290 break;
2291
2292 case MACH_MSG_TYPE_COPY_SEND:
2293 fprintf(file, " | MACH_RPC_COPY_SEND");
2294 break;
2295
2296 case MACH_MSG_TYPE_MAKE_SEND:
2297 fprintf(file, " | MACH_RPC_MAKE_SEND");
2298 break;
2299
2300 case MACH_MSG_TYPE_MAKE_SEND_ONCE:
2301 fprintf(file, " | MACH_RPC_MAKE_SEND_ONCE");
2302 break;
2303 }
2304 }
2305
2306 static void
WriteRPCArgDescriptor(FILE * file,register argument_t * arg,int offset)2307 WriteRPCArgDescriptor(FILE *file, register argument_t *arg, int offset)
2308 {
2309 fprintf(file, " {\n 0 ");
2310 if (RPCPort(arg))
2311 {
2312 fprintf(file, "| MACH_RPC_PORT ");
2313 if (arg->argType->itNumber > 1)
2314 fprintf(file, "| MACH_RPC_ARRAY ");
2315 if (arg->argType->itVarArray)
2316 fprintf(file, "| MACH_RPC_VARIABLE ");
2317 WriteRPCPortDisposition(file, arg);
2318 }
2319 else if (RPCPortArray(arg))
2320 {
2321 fprintf(file, "| MACH_RPC_PORT_ARRAY ");
2322 if (arg->argType->itVarArray)
2323 fprintf(file, "| MACH_RPC_VARIABLE ");
2324 WriteRPCPortDisposition(file, arg);
2325 }
2326 else if (RPCFixedArray(arg))
2327 fprintf(file, "| MACH_RPC_ARRAY_FIXED ");
2328 else if (RPCVariableArray(arg))
2329 fprintf(file, "| MACH_RPC_ARRAY_VARIABLE ");
2330 if (argIsIn(arg))
2331 fprintf(file, " | MACH_RPC_IN ");
2332 if (argIsOut(arg))
2333 fprintf(file, " | MACH_RPC_OUT ");
2334 if ((! arg->argType->itInLine) && (! arg->argType->itMigInLine))
2335 fprintf(file, " | MACH_RPC_POINTER ");
2336 if (arg->argFlags & flDealloc)
2337 fprintf(file, " | MACH_RPC_DEALLOCATE ");
2338 if (arg->argFlags & flPhysicalCopy)
2339 fprintf(file, " | MACH_RPC_PHYSICAL_COPY ");
2340 fprintf(file, ",\n");
2341 fprintf(file, " %d,\n", (arg->argType->itSize / 8));
2342 fprintf(file, " %d,\n", arg->argType->itNumber);
2343 fprintf(file, " %d,\n },\n", offset);
2344 }
2345
2346 void
WriteRPCRoutineDescriptor(FILE * file,routine_t * rt __unused,int arg_count,int descr_count,string_t stub_routine,string_t sig_array)2347 WriteRPCRoutineDescriptor(FILE *file, routine_t *rt __unused, int arg_count,
2348 int descr_count,
2349 string_t stub_routine, string_t sig_array)
2350 {
2351
2352 fprintf(file, " { (mig_impl_routine_t) 0,\n\
2353 (mig_stub_routine_t) %s, ",
2354 stub_routine);
2355 fprintf(file, "%d, %d, %s }", arg_count, descr_count, sig_array);
2356 }
2357
2358 void
WriteRPCRoutineArgDescriptor(FILE * file,register routine_t * rt)2359 WriteRPCRoutineArgDescriptor(FILE *file, register routine_t *rt)
2360 {
2361 register argument_t *arg;
2362 int offset = 0;
2363 int size = 0;
2364
2365 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
2366 {
2367 boolean_t compound = arg->argType->itStruct && arg->argType->itInLine;
2368
2369 if (RPCPort(arg) || RPCPortArray(arg) ||
2370 RPCFixedArray(arg) || RPCVariableArray(arg))
2371 {
2372 WriteRPCArgDescriptor(file, arg, offset);
2373 size = 4;
2374 }
2375 if (! size)
2376 {
2377 if (compound)
2378 size = arg->argType->itNumber * (arg->argType->itSize / 8);
2379 else
2380 size = (arg->argType->itSize / 8);
2381 }
2382 if (akCheck(arg->argKind, akbServerArg))
2383 offset += size;
2384 size = 0;
2385 }
2386 }
2387
2388
2389 static void
WriteRPCSignature(FILE * file,register routine_t * rt)2390 WriteRPCSignature(FILE *file, register routine_t *rt)
2391 {
2392 int arg_count = 0;
2393 int descr_count = 0;
2394
2395 fprintf(file, " kern_return_t rtn;\n");
2396 descr_count = rtCountArgDescriptors(rt->rtArgs, &arg_count);
2397 fprintf(file, " const static struct\n {\n");
2398 fprintf(file, " struct rpc_routine_descriptor rd;\n");
2399 fprintf(file, " struct rpc_routine_arg_descriptor rad[%d];\n", descr_count);
2400 fprintf(file, " } sig =\n {\n");
2401 WriteRPCRoutineDescriptor(file, rt, arg_count, descr_count, "0", "sig.rad, 0");
2402 fprintf(file, ",\n");
2403 fprintf(file, " {\n");
2404 WriteRPCRoutineArgDescriptor(file, rt);
2405 fprintf(file, "\n }\n");
2406 fprintf(file, "\n };\n\n");
2407 }
2408
2409 static void
WriteRPCCall(FILE * file,register routine_t * rt)2410 WriteRPCCall(FILE *file, register routine_t *rt)
2411 {
2412 register argument_t *arg;
2413 register int i;
2414
2415 i = 0;
2416 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
2417 if (akIdent(arg->argKind) == akeRequestPort) {
2418 fprintf(file, " rtn = (MACH_RPC(&sig, (mach_msg_size_t)sizeof(sig), %d, %s,\n", rt->rtNumber + SubsystemBase, arg->argVarName);
2419 fprintf(file, " (%s", arg->argVarName);
2420 }
2421 else if (akCheck(arg->argKind, akbServerArg))
2422 {
2423 if (i && (i++ % 6 == 0))
2424 fprintf(file, ",\n ");
2425 else
2426 fprintf(file, ", ");
2427 fprintf(file, "%s", arg->argVarName);
2428 }
2429 }
2430 fprintf(file, ")));\n");
2431 fprintf(file, "\n");
2432 fprintf(file, " if (rtn != KERN_NO_ACCESS) return rtn;\n\n");
2433 fprintf(file, "/* The following message rpc code is generated for the network case */\n\n");
2434 }
2435
2436 static int
CheckRPCCall(register routine_t * rt)2437 CheckRPCCall(register routine_t *rt)
2438 {
2439 register argument_t *arg;
2440 register int i;
2441
2442 i = 0;
2443 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
2444 {
2445 if (akCheck(arg->argKind, akbUserArg) &&
2446 ((arg->argType->itOutName == (u_int)-1) || (arg->argType->itInName == (u_int)-1)))
2447 {
2448 return FALSE;
2449 }
2450 if (arg->argFlags & flMaybeDealloc)
2451 {
2452 return FALSE;
2453 }
2454 }
2455 return TRUE;
2456 }
2457
2458 static void
WriteRPCRoutine(FILE * file,register routine_t * rt)2459 WriteRPCRoutine(FILE *file, register routine_t *rt)
2460 {
2461 if (CheckRPCCall(rt))
2462 {
2463 WriteRPCSignature(file, rt);
2464 WriteRPCCall(file, rt);
2465 }
2466 }
2467
2468 /********************** End UserRPCTrap Routines*************************/
2469
2470 /* Process an IN/INOUT arg before the short-circuited RPC */
2471 static void
WriteShortCircInArgBefore(FILE * file,register argument_t * arg)2472 WriteShortCircInArgBefore(FILE *file, register argument_t *arg)
2473 {
2474 register ipc_type_t *it = arg->argType;
2475 char size[128];
2476
2477 fprintf(file, "\n\t/* IN %s: */\n", arg->argVarName);
2478
2479 if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) {
2480 switch (arg->argKPD_Type) {
2481
2482 case MACH_MSG_PORT_DESCRIPTOR:
2483 break;
2484
2485 case MACH_MSG_OOL_DESCRIPTOR:
2486 /* Arg is an out-of-line array: */
2487 if (!(arg->argFlags & flDealloc) &&
2488 (!(arg->argFlags & flAuto) || !(arg->argFlags & flConst))) {
2489 /* Need to map a copy of the array: */
2490 GetArraySize(arg, size);
2491 fprintf(file, "\t(void)vm_read(mach_task_self(),\n");
2492 fprintf(file, "\t\t (vm_address_t) %s%s, %s, (vm_address_t *) &_%sTemp_, &_MIG_Ignore_Count_);\n",
2493 (arg->argByReferenceUser ? "*" : ""),
2494 arg->argVarName, size, arg->argVarName);
2495 /* Point argument at the copy: */
2496 fprintf(file, "\t*(char **)&%s%s = _%sTemp_;\n",
2497 (arg->argByReferenceUser ? "*" : ""),
2498 arg->argVarName,
2499 arg->argVarName);
2500 } else if ((arg->argFlags & flDealloc) &&
2501 ((arg->argFlags & flAuto) || it->itMigInLine)) {
2502 /* Point the temp var at the original argument: */
2503 fprintf(file, "\t_%sTemp_ = (char *) %s%s;\n",
2504 arg->argVarName,
2505 (arg->argByReferenceUser ? "*" : ""),
2506 arg->argVarName);
2507 }
2508 break;
2509 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
2510 break;
2511 default:
2512 printf("MiG internal error: type of kernel processed data unknown\n");
2513 exit(1);
2514 } /* end of switch */
2515 } else if (it->itNumber > 1) {
2516 if (it->itStruct) {
2517 /* Arg is a struct -- nothing to do. */
2518 } else {
2519 /* Arg is a C string or an in-line array: */
2520 if (!argIsOut(arg) && !(arg->argFlags & flConst)) {
2521 /* Have to copy it into a temp. Use a stack var, if this would
2522 * not overflow the -maxonstack specification:
2523 */
2524 if (it->itTypeSize <= sizeof(char *) ||
2525 rtMessOnStack(arg->argRoutine) ||
2526 arg->argRoutine->rtTempBytesOnStack +
2527 it->itTypeSize <= (u_int)MaxMessSizeOnStack) {
2528 fprintf(file, "\t{ char _%sTemp_[%d];\n",
2529 arg->argVarName, it->itTypeSize);
2530 arg->argRoutine->rtTempBytesOnStack += it->itTypeSize;
2531 arg->argTempOnStack = TRUE;
2532 }
2533 else {
2534 fprintf(file, "\t{ _%sTemp_ = (char *) %s(%d);\n", arg->argVarName, MessAllocRoutine, it->itTypeSize);
2535 arg->argTempOnStack = FALSE;
2536 }
2537 WriteCopyArg(file, arg, "_%sTemp_", "/* %s */ (char *) %s",
2538 arg->argVarName, arg->argVarName);
2539 /* Point argument at temp: */
2540 fprintf(file, "\t *(char **)&%s%s = _%sTemp_;\n",
2541 (arg->argByReferenceUser ? "*" : ""),
2542 arg->argVarName,
2543 arg->argVarName);
2544 fprintf(file, "\t}\n");
2545 }
2546 }
2547 }
2548 }
2549
2550
2551 /* Process an INOUT/OUT arg before the short-circuited RPC */
2552 static void
WriteShortCircOutArgBefore(FILE * file,register argument_t * arg)2553 WriteShortCircOutArgBefore(FILE *file, register argument_t *arg)
2554 {
2555 register ipc_type_t *it = arg->argType;
2556
2557 fprintf(file, "\n\t/* OUT %s: */\n", arg->argVarName);
2558
2559
2560 fprintf(file, "\n\t/* OUT %s: */\n", arg->argVarName);
2561
2562 if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) {
2563 switch (arg->argKPD_Type) {
2564 case MACH_MSG_PORT_DESCRIPTOR:
2565 break;
2566 case MACH_MSG_OOL_DESCRIPTOR:
2567 /* Arg is an out-of-line array: */
2568 if (!argIsIn(arg) && (arg->argFlags & flOverwrite)) {
2569 /* Point the temp var at the original argument: */
2570 fprintf(file, "\t _%sTemp_ = (char *) %s%s;\n",
2571 arg->argVarName,
2572 (arg->argByReferenceUser ? "*" : ""),
2573 arg->argVarName);
2574 }
2575 break;
2576 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
2577 break;
2578 default:
2579 printf("MiG internal error: type of kernel processed data unknown\n");
2580 exit(1);
2581 } /* end of switch */
2582 } else if (it->itNumber > 1) {
2583 /* Arg is an in-line array: */
2584 }
2585 }
2586
2587
2588
2589 /* Process an IN arg after the short-circuited RPC */
2590 static void
WriteShortCircInArgAfter(FILE * file,register argument_t * arg)2591 WriteShortCircInArgAfter(FILE *file, register argument_t *arg)
2592 {
2593 register ipc_type_t *it = arg->argType;
2594 char size[128];
2595
2596 fprintf(file, "\n\t/* IN %s: */\n", arg->argVarName);
2597
2598 if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) {
2599 switch (arg->argKPD_Type) {
2600
2601 case MACH_MSG_PORT_DESCRIPTOR:
2602 break;
2603
2604 case MACH_MSG_OOL_DESCRIPTOR:
2605 /* Arg is an out-of-line array: */
2606 GetArraySize(arg, size);
2607 if ((!(arg->argFlags & flAuto) && it->itMigInLine) ||
2608 ((arg->argFlags & flAuto) &&
2609 ((arg->argFlags & flDealloc) ||
2610 !(arg->argFlags & flConst))
2611 )) {
2612 /* Need to dealloc the temporary: */
2613 fprintf(file, "\t(void)vm_deallocate(mach_task_self(),");
2614 fprintf(file, " (vm_address_t *) _%sTemp_, %s);\n",
2615 arg->argVarName, size);
2616 }
2617 break;
2618 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
2619 break;
2620 default:
2621 printf("MiG internal error: type of kernel processed data unknown\n");
2622 exit(1);
2623 } /* end of switch */
2624 } else if (it->itNumber > 1) {
2625 if (it->itStruct) {
2626 /* Arg is a struct -- nothing to do. */
2627 } else {
2628 /* Arg is a C string or an in-line array: */
2629 if (!argIsOut(arg) && !(arg->argFlags & flConst)) {
2630 /* A temp needs to be deallocated, if not on stack: */
2631 if (!arg->argTempOnStack) {
2632 fprintf(file, "\t%s(_%sTemp_, %d);\n",
2633 MessFreeRoutine, arg->argVarName, it->itTypeSize);
2634 }
2635 }
2636 }
2637 }
2638 }
2639
2640 static void
WriteShortCircOutArgAfter(FILE * file,register argument_t * arg)2641 WriteShortCircOutArgAfter(FILE *file, register argument_t *arg)
2642 {
2643 register ipc_type_t *it = arg->argType;
2644 char size[128];
2645
2646 fprintf(file, "\n\t/* OUT %s: */\n", arg->argVarName);
2647
2648 if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) {
2649 switch (arg->argKPD_Type) {
2650
2651 case MACH_MSG_PORT_DESCRIPTOR:
2652 break;
2653
2654 case MACH_MSG_OOL_DESCRIPTOR:
2655 /* Arg is an out-of-line array: */
2656
2657 /* Calculate size of array: */
2658 GetArraySize(arg, size);
2659 if (!(arg->argFlags & flDealloc) || (arg->argFlags & flOverwrite)) {
2660 /* Copy argument to vm_allocated Temp: */
2661 fprintf(file, "\t(void)vm_read(mach_task_self(),\n");
2662 fprintf(file, "\t\t (vm_address_t) %s%s, %s, (vm_address_t *) &_%sTemp_, &_MIG_Ignore_Count_);\n",
2663 (arg->argByReferenceUser ? "*" : ""),
2664 arg->argVarName, size, arg->argVarName);
2665 if (!argIsIn(arg) && (arg->argFlags & flDealloc) &&
2666 (arg->argFlags & flOverwrite)) {
2667 /* Deallocate argument returned by server */
2668 fprintf(file, "\t(void)vm_deallocate(mach_task_self(),");
2669 fprintf(file, " (vm_address_t *) %s%s, %s);\n",
2670 (arg->argByReferenceUser ? "*" : ""),
2671 arg->argVarName, size);
2672 }
2673 /* Point argument at new temporary: */
2674 fprintf(file, "\t*(char **)&%s%s = _%sTemp_;\n",
2675 (arg->argByReferenceUser ? "*" : ""),
2676 arg->argVarName,
2677 arg->argVarName);
2678 }
2679 break;
2680 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
2681 break;
2682 default:
2683 printf("MiG internal error: type of kernel processed data unknown\n");
2684 exit(1);
2685 } /* end of switch */
2686 } else if (it->itNumber != 1) {
2687 /* Arg is an in-line array: */
2688 }
2689 }
2690
2691
2692 static void
WriteShortCircRPC(FILE * file,register routine_t * rt)2693 WriteShortCircRPC(FILE *file, register routine_t *rt)
2694 {
2695 register argument_t *arg;
2696 register int server_argc, i;
2697 boolean_t ShortCircOkay = TRUE;
2698 boolean_t first_OOL_arg = TRUE;
2699
2700 fprintf(file, " if (0 /* Should be: !(%s & 0x3) XXX */) {\n",
2701 rt->rtRequestPort->argVarName);
2702
2703 if (rt->rtOneWay) {
2704 /* Do not short-circuit simple routines: */
2705 ShortCircOkay = FALSE;
2706 } else {
2707 /* Scan for any types we can't yet handle. If found, give up on short-
2708 * circuiting and fall back to mach_msg:
2709 */
2710 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
2711 if (arg->argFlags & flMaybeDealloc) {
2712 ShortCircOkay = FALSE;
2713 break;
2714 }
2715 /* Can't yet handle ports: */
2716 if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD) &&
2717 (arg->argKPD_Type == MACH_MSG_PORT_DESCRIPTOR ||
2718 arg->argKPD_Type == MACH_MSG_OOL_PORTS_DESCRIPTOR)) {
2719 ShortCircOkay = FALSE;
2720 break;
2721 }
2722 }
2723 }
2724
2725 if (ShortCircOkay) {
2726
2727 fprintf(file,
2728 " rpc_subsystem_t subsystem = ((rpc_port_t)%s)->rp_subsystem;\n",
2729 rt->rtRequestPort->argVarName);
2730 fprintf(file, "\n");
2731 fprintf(file, " if (subsystem && subsystem->start == %d) {\n",
2732 SubsystemBase);
2733 fprintf(file, "\tkern_return_t rtn;\n");
2734 fprintf(file, "\n");
2735
2736 /* Declare temp vars for out-of-line array args, and for all array
2737 * args, if -maxonstack has forced us to allocate in-line arrays
2738 * off the stack:
2739 */
2740 rt->rtTempBytesOnStack = 0;
2741 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
2742 arg->argTempOnStack = FALSE;
2743 if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD) &&
2744 arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {
2745 if (first_OOL_arg) {
2746 /* Need a garbage temporary to hold the datacount
2747 * returned by vm_read, which we always ignore:
2748 */
2749 fprintf(file,
2750 "\tmach_msg_type_number_t _MIG_Ignore_Count_;\n");
2751 first_OOL_arg = FALSE;
2752 }
2753 } else if (!rtMessOnStack(rt) &&
2754 arg->argType->itNumber > 1 && !arg->argType->itStruct) {
2755 } else
2756 continue;
2757 fprintf(file, "\tchar *_%sTemp_;\n", arg->argVarName);
2758 rt->rtTempBytesOnStack += sizeof(char *);
2759 }
2760
2761 /* Process the IN arguments, in order: */
2762
2763 fprintf(file, "\t/* Pre-Process the IN arguments: */\n");
2764 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
2765 if (argIsIn(arg))
2766 WriteShortCircInArgBefore(file, arg);
2767 if (argIsOut(arg))
2768 WriteShortCircOutArgBefore(file, arg);
2769 }
2770 fprintf(file, "\n");
2771
2772 /* Count the number of server args: */
2773 server_argc = 0;
2774 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
2775 if (akCheck(arg->argKind, akbServerArg))
2776 server_argc++;
2777
2778 /* Call RPC_SIMPLE to switch to server stack and function: */
2779 i = 0;
2780 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
2781 if (akIdent(arg->argKind) == akeRequestPort) {
2782 fprintf(file, "\trtn = RPC_SIMPLE(%s, %d, %d, (",
2783 arg->argVarName, rt->rtNumber + SubsystemBase,
2784 server_argc);
2785 fprintf(file, "%s", arg->argVarName);
2786 } else if (akCheck(arg->argKind, akbServerArg)) {
2787 if (i++ % 6 == 0)
2788 fprintf(file, ",\n\t\t");
2789 else
2790 fprintf(file, ", ");
2791 fprintf(file, "%s", arg->argVarName);
2792 }
2793 }
2794 fprintf(file, "));\n");
2795 fprintf(file, "\n");
2796
2797 /* Process the IN and OUT arguments, in order: */
2798 fprintf(file, "\t/* Post-Process the IN and OUT arguments: */\n");
2799 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
2800 if (argIsIn(arg))
2801 WriteShortCircInArgAfter(file, arg);
2802 if (argIsOut(arg))
2803 WriteShortCircOutArgAfter(file, arg);
2804 }
2805 fprintf(file, "\n");
2806
2807 fprintf(file, "\treturn rtn;\n");
2808 fprintf(file, " }\n");
2809 }
2810
2811 /* In latest design, the following is not necessary, because in
2812 * kernel-loaded tasks, the Mach port name is the same as the handle
2813 * used by the RPC mechanism, namely a pointer to the ipc_port, and
2814 * in user-mode tasks, the Mach port name gets renamed to be a pointer
2815 * to the user-mode rpc_port_t struct.
2816 */
2817 #if 0
2818 if (IsKernelUser)
2819 fprintf(file, " %s = (ipc_port_t)%s->rp_receiver_name;\n",
2820 rt->rtRequestPort->argVarName,
2821 rt->rtRequestPort->argVarName);
2822 else
2823 fprintf(file, " %s = ((rpc_port_t)%s)->rp_receiver_name;\n",
2824 rt->rtRequestPort->argVarName,
2825 rt->rtRequestPort->argVarName);
2826 #endif
2827
2828 fprintf(file, " }\n");
2829 }
2830
2831 static void
WriteStubDecl(FILE * file,register routine_t * rt)2832 WriteStubDecl(FILE *file, register routine_t *rt)
2833 {
2834 fprintf(file, "\n");
2835 fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
2836 fprintf(file, "mig_external %s %s\n", ReturnTypeStr(rt), rt->rtUserName);
2837 if (BeAnsiC) {
2838 fprintf(file, "(\n");
2839 WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n");
2840 fprintf(file, ")\n");
2841 } else {
2842 fprintf(file, "#if\t%s\n", NewCDecl);
2843 fprintf(file, "(\n");
2844 WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n");
2845 fprintf(file, ")\n");
2846 fprintf(file, "#else\n");
2847 fprintf(file, "\t(");
2848 WriteList(file, rt->rtArgs, WriteNameDecl, akbUserArg, ", ", "");
2849 fprintf(file, ")\n");
2850 WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ";\n", ";\n");
2851 fprintf(file, "#endif\t/* %s */\n", NewCDecl);
2852 }
2853 fprintf(file, "{\n");
2854 }
2855
2856 static void
InitKPD_Disciplines(argument_t * args)2857 InitKPD_Disciplines(argument_t *args)
2858 {
2859 argument_t *arg;
2860 extern void KPD_noop();
2861 extern void KPD_error();
2862 extern void WriteTemplateKPD_port();
2863 extern void WriteTemplateKPD_ool();
2864 extern void WriteTemplateKPD_oolport();
2865
2866 /*
2867 * WriteKPD_port, WriteExtractKPD_port,
2868 * WriteKPD_ool, WriteExtractKPD_ool,
2869 * WriteKPD_oolport, WriteExtractKPD_oolport
2870 * are local to this module (which is the reason why this initialization
2871 * takes place here rather than in utils.c).
2872 * Common routines for user and server will be established SOON, and
2873 * all of them (including the initialization) will be transfert to
2874 * utils.c
2875 * All the KPD disciplines are defaulted to be KPD_error().
2876 * Note that akbSendKPD and akbReturnKPd are not exclusive,
2877 * because of inout type of parameters.
2878 */
2879 for (arg = args; arg != argNULL; arg = arg->argNext)
2880 if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD))
2881 switch (arg->argKPD_Type) {
2882
2883 case MACH_MSG_PORT_DESCRIPTOR:
2884 arg->argKPD_Init = KPD_noop;
2885 if akCheck(arg->argKind, akbSendKPD) {
2886 arg->argKPD_Template = WriteTemplateKPD_port;
2887 arg->argKPD_Pack = WriteKPD_port;
2888 }
2889 if akCheck(arg->argKind, akbReturnKPD) {
2890 arg->argKPD_Extract = WriteExtractKPD_port;
2891 arg->argKPD_TypeCheck = WriteTCheckKPD_port;
2892 }
2893 break;
2894
2895 case MACH_MSG_OOL_DESCRIPTOR:
2896 arg->argKPD_Init = KPD_noop;
2897 if akCheck(arg->argKind, akbSendKPD) {
2898 arg->argKPD_Template = WriteTemplateKPD_ool;
2899 arg->argKPD_Pack = WriteKPD_ool;
2900 }
2901 if akCheck(arg->argKind, akbReturnKPD) {
2902 arg->argKPD_TypeCheck = WriteTCheckKPD_ool;
2903 arg->argKPD_Extract = WriteExtractKPD_ool;
2904 }
2905 break;
2906
2907 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
2908 arg->argKPD_Init = KPD_noop;
2909 if akCheck(arg->argKind, akbSendKPD) {
2910 arg->argKPD_Template = WriteTemplateKPD_oolport;
2911 arg->argKPD_Pack = WriteKPD_oolport;
2912 }
2913 if akCheck(arg->argKind, akbReturnKPD) {
2914 arg->argKPD_TypeCheck = WriteTCheckKPD_oolport;
2915 arg->argKPD_Extract = WriteExtractKPD_oolport;
2916 }
2917 break;
2918
2919 default:
2920 printf("MiG internal error: type of kernel processed data unknown\n");
2921 exit(1);
2922 } /* end of switch */
2923 }
2924
2925 static void
WriteLimitCheck(FILE * file,routine_t * rt)2926 WriteLimitCheck(FILE *file, routine_t *rt)
2927 {
2928 if (MaxMessSizeOnStack == -1 || UserTypeLimit == -1)
2929 return;
2930 if (!rt->rtRequestUsedLimit && !rt->rtReplyUsedLimit)
2931 return;
2932 fprintf(file, "#if LimitCheck\n");
2933 if (rt->rtRequestUsedLimit) {
2934 if (rt->rtRequestFits) {
2935 fprintf(file, "\tif ((sizeof(Request) - %d) > %d)\n",
2936 rt->rtRequestSizeKnown, UserTypeLimit);
2937 fprintf(file, "\t __RequestOnStackAbort(%d, \"%s\");\n",
2938 SubsystemBase + rt->rtNumber, rt->rtName);
2939 } else if (rt->rtReplyFits) {
2940 fprintf(file, "\tif (sizeof(Request) < %d)\n",
2941 MaxMessSizeOnStack);
2942 fprintf(file, "\t __MessageOffStackNote(%d, \"%s\");\n",
2943 SubsystemBase + rt->rtNumber, rt->rtName);
2944 }
2945 }
2946 if (rt->rtReplyUsedLimit) {
2947 if (rt->rtReplyFits) {
2948 fprintf(file, "\tif ((sizeof(Reply) - %d) > %d)\n",
2949 rt->rtReplySizeKnown, UserTypeLimit);
2950 fprintf(file, "\t __ReplyOnStackAbort(%d, \"%s\");\n",
2951 SubsystemBase + rt->rtNumber, rt->rtName);
2952 } else if (rt->rtRequestFits) {
2953 fprintf(file, "\tif (sizeof(Reply) < %d)\n",
2954 MaxMessSizeOnStack);
2955 fprintf(file, "\t __MessageOffStackNote(%d, \"%s\");\n",
2956 SubsystemBase + rt->rtNumber, rt->rtName);
2957 }
2958 }
2959 if (rt->rtRequestUsedLimit && rt->rtReplyUsedLimit &&
2960 ! (rt->rtRequestFits || rt->rtReplyFits)) {
2961 fprintf(file, "\tif (sizeof(Request) < %d \n",
2962 MaxMessSizeOnStack);
2963 fprintf(file, "&& sizeof(Reply) < %d)\n",
2964 MaxMessSizeOnStack);
2965 fprintf(file, "\t __MessageOffStackNote(%d, \"%s\");\n",
2966 SubsystemBase + rt->rtNumber, rt->rtName);
2967 }
2968 fprintf(file, "#endif /* LimitCheck */\n");
2969 }
2970
2971 static void
WriteCheckReply(FILE * file,routine_t * rt)2972 WriteCheckReply(FILE *file, routine_t *rt)
2973 {
2974 u_int i;
2975
2976 /* initialize the disciplines for the handling of KPDs */
2977 InitKPD_Disciplines(rt->rtArgs);
2978
2979 if (rt->rtOneWay)
2980 return;
2981
2982 fprintf(file, "\n");
2983 fprintf(file, "#if ( __MigTypeCheck ");
2984 if (CheckNDR)
2985 fprintf(file, "|| __NDR_convert__ ");
2986 fprintf(file, ")\n");
2987 fprintf(file, "#if __MIG_check__Reply__%s_subsystem__\n", SubsystemName);
2988 fprintf(file, "#if !defined(__MIG_check__Reply__%s_t__defined)\n", rt->rtName);
2989 fprintf(file, "#define __MIG_check__Reply__%s_t__defined\n", rt->rtName);
2990 if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbReply)) {
2991 WriteList(file, rt->rtArgs, WriteReplyNDRConvertIntRepArgDecl, akbReturnNdr, "\n", "\n");
2992 WriteList(file, rt->rtArgs, WriteReplyNDRConvertCharRepArgDecl, akbReturnNdr, "\n", "\n");
2993 WriteList(file, rt->rtArgs, WriteReplyNDRConvertFloatRepArgDecl, akbReturnNdr, "\n", "\n");
2994 }
2995 fprintf(file, "\n");
2996 fprintf(file, "mig_internal kern_return_t __MIG_check__Reply__%s_t(__Reply__%s_t *Out0P", rt->rtName, rt->rtName);
2997 for (i = 1; i <= rt->rtMaxReplyPos; i++)
2998 fprintf(file, ", __Reply__%s_t **Out%dPP", rt->rtName, i);
2999 fprintf(file, ")\n{\n");
3000
3001
3002 fprintf(file, "\n\ttypedef __Reply__%s_t __Reply;\n", rt->rtName);
3003 for (i = 1; i <= rt->rtMaxReplyPos; i++)
3004 fprintf(file, "\t__Reply *Out%dP;\n", i);
3005 if (!rt->rtSimpleReply)
3006 fprintf(file, "\tboolean_t msgh_simple;\n");
3007 if (!rt->rtNoReplyArgs) {
3008 fprintf(file, "#if\t__MigTypeCheck\n");
3009 fprintf(file, "\tunsigned int msgh_size;\n");
3010 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
3011 }
3012 if (rt->rtMaxReplyPos > 0)
3013 fprintf(file, "\tunsigned int msgh_size_delta;\n");
3014 if (rt->rtNumReplyVar > 0 || rt->rtMaxReplyPos > 0)
3015 fprintf(file, "\n");
3016
3017 /* Check the values that are returned in the reply message */
3018
3019 WriteCheckIdentity(file, rt);
3020
3021 /* If the reply message has no Out parameters or return values
3022 other than the return code, we can type-check it and
3023 return it directly. */
3024
3025 if (rt->rtNoReplyArgs && !rt->rtUserImpl) {
3026 if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbReply) && rt->rtRetCode)
3027 WriteReplyNDRConvertIntRepOneArgUse(file, rt->rtRetCode);
3028 WriteReturn(file, rt, "\t", stRetCode, "\n");
3029 }
3030 else {
3031 if (UseEventLogger)
3032 WriteLogMsg(file, rt, LOG_USER, LOG_REPLY);
3033
3034 WriteRetCodeCheck(file, rt);
3035
3036 /* Type Checking for the Out parameters which are typed */
3037 WriteList(file, rt->rtArgs, WriteTypeCheck, akbReturnKPD, "\n", "\n");
3038
3039 {
3040 register argument_t *arg, *lastVarArg;
3041
3042 lastVarArg = argNULL;
3043 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
3044 /*
3045 * Advance message pointer if the last reply argument was
3046 * variable-length and the reply position will change.
3047 */
3048 if (lastVarArg != argNULL &&
3049 lastVarArg->argReplyPos < arg->argReplyPos) {
3050 WriteAdjustReplyMsgPtr(file, lastVarArg);
3051 lastVarArg = argNULL;
3052 }
3053
3054 if (akCheckAll(arg->argKind, akbReturnRcv|akbReturnBody)) {
3055 if (akCheck(arg->argKind, akbVariable)) {
3056 WriteCheckMsgSize(file, arg);
3057 lastVarArg = arg;
3058 }
3059 }
3060 }
3061 }
3062
3063 if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbReply)) {
3064 fprintf(file, "#if\t");
3065 WriteList(file, rt->rtArgs, WriteReplyNDRConvertIntRepArgCond, akbReturnNdr, " || \\\n\t", "\n");
3066 fprintf(file, "\tif (Out0P->NDR.int_rep != NDR_record.int_rep) {\n");
3067 WriteList(file, rt->rtArgs, WriteReplyNDRConvertIntRepArgUse, akbReturnNdr, "", "");
3068 fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__int_rep...) */\n\n");
3069
3070 fprintf(file, "#if\t");
3071 WriteList(file, rt->rtArgs, WriteReplyNDRConvertCharRepArgCond, akbReturnNdr, " || \\\n\t", "\n");
3072 fprintf(file, "\tif (Out0P->NDR.char_rep != NDR_record.char_rep) {\n");
3073 WriteList(file, rt->rtArgs, WriteReplyNDRConvertCharRepArgUse, akbReturnNdr, "", "");
3074 fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__char_rep...) */\n\n");
3075
3076 fprintf(file, "#if\t");
3077 WriteList(file, rt->rtArgs, WriteReplyNDRConvertFloatRepArgCond, akbReturnNdr, " || \\\n\t", "\n");
3078 fprintf(file, "\tif (Out0P->NDR.float_rep != NDR_record.float_rep) {\n");
3079 WriteList(file, rt->rtArgs, WriteReplyNDRConvertFloatRepArgUse, akbReturnNdr, "", "");
3080 fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__float_rep...) */\n\n");
3081 }
3082 fprintf(file, "\treturn MACH_MSG_SUCCESS;\n");
3083 }
3084 fprintf(file, "}\n");
3085 fprintf(file, "#endif /* !defined(__MIG_check__Reply__%s_t__defined) */\n", rt->rtName);
3086 fprintf(file, "#endif /* __MIG_check__Reply__%s_subsystem__ */\n", SubsystemName);
3087 fprintf(file, "#endif /* ( __MigTypeCheck ");
3088 if (CheckNDR)
3089 fprintf(file, "|| __NDR_convert__ ");
3090 fprintf(file, ") */\n\n");
3091 }
3092
3093 static void
WriteCheckReplyCall(FILE * file,routine_t * rt)3094 WriteCheckReplyCall(FILE *file, routine_t *rt)
3095 {
3096 u_int i;
3097
3098 fprintf(file, "\n");
3099 fprintf(file, "#if\tdefined(__MIG_check__Reply__%s_t__defined)\n", rt->rtName);
3100 fprintf(file, "\tcheck_result = __MIG_check__Reply__%s_t((__Reply__%s_t *)Out0P", rt->rtName, rt->rtName);
3101 for (i = 1; i <= rt->rtMaxReplyPos; i++)
3102 fprintf(file, ", (__Reply__%s_t **)&Out%dP", rt->rtName, i);
3103 fprintf(file, ");\n");
3104 fprintf(file, "\tif (check_result != MACH_MSG_SUCCESS)\n");
3105 WriteReturnMsgError(file, rt, TRUE, argNULL, "check_result");
3106 fprintf(file, "#endif\t/* defined(__MIG_check__Reply__%s_t__defined) */\n", rt->rtName);
3107 fprintf(file, "\n");
3108 }
3109
3110 void
WriteCheckReplies(FILE * file,statement_t * stats)3111 WriteCheckReplies(FILE *file, statement_t *stats)
3112 {
3113 statement_t *stat;
3114
3115 for (stat = stats; stat != stNULL; stat = stat->stNext)
3116 if (stat->stKind == skRoutine)
3117 WriteCheckReply(file, stat->stRoutine);
3118 }
3119
3120 static void
WriteCheckReplyTrailerArgs(FILE * file,routine_t * rt)3121 WriteCheckReplyTrailerArgs(FILE *file, routine_t *rt)
3122 {
3123 register argument_t *arg;
3124
3125 if (rt->rtUserImpl)
3126 WriteCheckTrailerHead(file, rt, TRUE);
3127
3128 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
3129 if (akCheck(arg->argKind, akbUserImplicit))
3130 WriteCheckTrailerSize(file, TRUE, arg);
3131 }
3132 if (rt->rtUserImpl)
3133 fprintf(file, "\n");
3134 }
3135
3136
3137 /*************************************************************
3138 * Writes all the code comprising a routine body. Called by
3139 * WriteUser for each routine.
3140 *************************************************************/
3141 static void
WriteRoutine(FILE * file,register routine_t * rt)3142 WriteRoutine(FILE *file, register routine_t *rt)
3143 {
3144 /* write the stub's declaration */
3145 WriteStubDecl(file, rt);
3146
3147 /* Use the RPC trap for user-user and user-kernel RPC */
3148 if (UseRPCTrap)
3149 WriteRPCRoutine(file, rt);
3150
3151 /* write the code for doing a short-circuited RPC: */
3152 if (ShortCircuit)
3153 WriteShortCircRPC(file, rt);
3154
3155 /* typedef of structure for Request and Reply messages */
3156 WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest,
3157 "Request", rt->rtSimpleRequest, FALSE, FALSE, FALSE);
3158 if (!rt->rtOneWay) {
3159 WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply,
3160 "Reply", rt->rtSimpleReply, TRUE, rt->rtUserImpl, FALSE);
3161 WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply,
3162 "__Reply", rt->rtSimpleReply, FALSE, FALSE, FALSE);
3163 }
3164 if (rt->rtOverwrite)
3165 WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbReply|akbOverwrite,
3166 "OverwriteTemplate", FALSE, TRUE, FALSE, TRUE);
3167 /*
3168 * Define a Minimal Reply structure to be used in case of errors
3169 */
3170 fprintf(file, "\t/*\n");
3171 fprintf(file, "\t * typedef struct {\n");
3172 fprintf(file, "\t * \tmach_msg_header_t Head;\n");
3173 fprintf(file, "\t * \tNDR_record_t NDR;\n");
3174 fprintf(file, "\t * \tkern_return_t RetCode;\n");
3175 fprintf(file, "\t * } mig_reply_error_t;\n");
3176 fprintf(file, "\t */\n");
3177 fprintf(file, "\n");
3178
3179
3180 /* declarations for local vars: Union of Request and Reply messages,
3181 InP, OutP and return value */
3182
3183 WriteVarDecls(file, rt);
3184
3185 /* declarations and initializations of the mach_msg_type_descriptor_t variables
3186 for each argument that is a Kernel Processed Data */
3187
3188 WriteList(file, rt->rtArgs, WriteTemplateDeclIn, akbRequest | akbSendKPD, "\n", "\n");
3189
3190 WriteLimitCheck(file, rt);
3191 WriteRetCodeArg(file, rt);
3192
3193 /* fill in the fields that are non related to parameters */
3194
3195 if (!rt->rtSimpleRequest)
3196 fprintf(file, "\tInP->msgh_body.msgh_descriptor_count = %d;\n",
3197 rt->rtRequestKPDs);
3198
3199 /* fill in all the request message types and then arguments */
3200
3201 WriteRequestArgs(file, rt);
3202
3203 /* fill in request message head */
3204
3205 WriteRequestHead(file, rt);
3206 fprintf(file, "\n");
3207
3208 /* give the application a chance to do some stuff. */
3209 WriteApplMacro(file, "Send", "Before", rt);
3210
3211 /* Write the send/receive or rpc call */
3212
3213 if (UseEventLogger)
3214 WriteLogMsg(file, rt, LOG_USER, LOG_REQUEST);
3215
3216 if (rt->rtOneWay) {
3217 WriteMsgSend(file, rt);
3218 }
3219 else {
3220 if (UseMsgRPC
3221 #if USE_IMMEDIATE_SEND_TIMEOUT
3222 && (rt->rtWaitTime == argNULL)
3223 #endif
3224 ) {
3225 /* overwrite mode meaningful only when UseMsgRPC is enabled */
3226 if (rt->rtOverwrite)
3227 WriteOverwriteTemplate(file, rt);
3228 WriteMsgRPC(file, rt);
3229 } else
3230 WriteMsgSendReceive(file, rt);
3231
3232 WriteCheckReplyCall(file, rt);
3233 WriteCheckReplyTrailerArgs(file, rt);
3234
3235 if (UseEventLogger)
3236 WriteLogMsg(file, rt, LOG_USER, LOG_REPLY);
3237
3238 WriteReplyArgs(file, rt);
3239 }
3240 /* return the return value, if any */
3241 if (!rt->rtOneWay) // WriteMsgSend() already wrote the 'return'
3242 WriteReturnValue(file, rt);
3243 fprintf(file, "}\n");
3244 }
3245
3246 static void
WriteRPCClientFunctions(FILE * file,statement_t * stats)3247 WriteRPCClientFunctions(FILE *file, statement_t *stats)
3248 {
3249 register statement_t *stat;
3250 const char *fname;
3251 const char *argfmt = "(mach_port_t, char *, mach_msg_type_number_t)";
3252
3253 fprintf(file, "#ifdef AUTOTEST\n");
3254 for (stat = stats; stat != stNULL; stat = stat->stNext)
3255 if (stat->stKind == skRoutine) {
3256 fname = stat->stRoutine->rtName;
3257 fprintf(file, "extern void client_%s%s;\n", fname, argfmt);
3258 }
3259 fprintf(file, "function_table_entry %s_client_functions[] =\n", SubsystemName);
3260 fprintf(file, "{\n");
3261 for (stat = stats; stat != stNULL; stat = stat->stNext)
3262 if (stat->stKind == skRoutine)
3263 {
3264 fname = stat->stRoutine->rtName;
3265 fprintf(file, " { \"%s\", client_%s },\n", fname, fname);
3266 }
3267 fprintf(file, " { (char *) 0, (function_ptr_t) 0 }\n");
3268 fprintf(file, "};\n");
3269 fprintf(file, "#endif /* AUTOTEST */\n");
3270 }
3271
3272 /*************************************************************
3273 * Writes out the xxxUser.c file. Called by mig.c
3274 *************************************************************/
3275 void
WriteUser(FILE * file,statement_t * stats)3276 WriteUser(FILE *file, statement_t *stats)
3277 {
3278 register statement_t *stat;
3279
3280 WriteProlog(file, stats);
3281 if (TestRPCTrap)
3282 WriteRPCClientFunctions(file, stats);
3283 for (stat = stats; stat != stNULL; stat = stat->stNext)
3284 switch (stat->stKind)
3285 {
3286 case skRoutine:
3287 WriteCheckReply(file, stat->stRoutine);
3288 WriteRoutine(file, stat->stRoutine);
3289 break;
3290 case skImport:
3291 case skUImport:
3292 case skSImport:
3293 case skDImport:
3294 case skIImport:
3295 break;
3296 default:
3297 fatal("WriteUser(): bad statement_kind_t (%d)",
3298 (int) stat->stKind);
3299 }
3300 WriteEpilog(file);
3301 }
3302
3303 /*************************************************************
3304 * Writes out individual .c user files for each routine. Called by mig.c
3305 *************************************************************/
3306 void
WriteUserIndividual(statement_t * stats)3307 WriteUserIndividual(statement_t *stats)
3308 {
3309 register statement_t *stat;
3310
3311 for (stat = stats; stat != stNULL; stat = stat->stNext)
3312 switch (stat->stKind)
3313 {
3314 case skRoutine:
3315 {
3316 FILE *file;
3317 char *filename;
3318
3319 filename = (char *)(uintptr_t)strconcat(UserFilePrefix,
3320 strconcat(stat->stRoutine->rtName, ".c"));
3321 file = fopen(filename, "w");
3322 if (file == NULL)
3323 fatal("fopen(%s): %s", filename,
3324 strerror(errno));
3325 WriteProlog(file, stats);
3326 WriteRoutine(file, stat->stRoutine);
3327 WriteEpilog(file);
3328 fclose(file);
3329 strfree(filename);
3330 }
3331 case skUImport:
3332 case skSImport:
3333 case skDImport:
3334 case skIImport:
3335 break;
3336 default:
3337 fatal("WriteUserIndividual(): bad statement_kind_t (%d)",
3338 (int) stat->stKind);
3339 }
3340 }
3341