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