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