From 5fd83771641d15c418f747bd343ba6738d3875f7 Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Sun, 9 May 2021 14:20:58 -0400 Subject: Import macOS userland adv_cmds-176 basic_cmds-55 bootstrap_cmds-116.100.1 developer_cmds-66 diskdev_cmds-667.40.1 doc_cmds-53.60.1 file_cmds-321.40.3 mail_cmds-35 misc_cmds-34 network_cmds-606.40.1 patch_cmds-17 remote_cmds-63 shell_cmds-216.60.1 system_cmds-880.60.2 text_cmds-106 --- bootstrap_cmds/migcom.tproj/utils.c | 1043 +++++++++++++++++++++++++++++++++++ 1 file changed, 1043 insertions(+) create mode 100644 bootstrap_cmds/migcom.tproj/utils.c (limited to 'bootstrap_cmds/migcom.tproj/utils.c') diff --git a/bootstrap_cmds/migcom.tproj/utils.c b/bootstrap_cmds/migcom.tproj/utils.c new file mode 100644 index 0000000..7a609a4 --- /dev/null +++ b/bootstrap_cmds/migcom.tproj/utils.c @@ -0,0 +1,1043 @@ +/* + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include +#include +#include "routine.h" +#include "write.h" +#include "global.h" +#include "utils.h" +#include "error.h" + +extern char *MessFreeRoutine; + +void +WriteIdentificationString(FILE *file) +{ + extern char * GenerationDate; + + fprintf(file, "/*\n"); + fprintf(file, " * IDENTIFICATION:\n"); + fprintf(file, " * stub generated %s", GenerationDate); + fprintf(file, " * with a MiG generated by " MIG_VERSION "\n"); + fprintf(file, " * OPTIONS: \n"); + if (IsKernelUser) + fprintf(file, " *\tKernelUser\n"); + if (IsKernelServer) + fprintf(file, " *\tKernelServer\n"); + if (!UseMsgRPC) + fprintf(file, " *\t-R (no RPC calls)\n"); + fprintf(file, " */\n"); +} + +void +WriteMigExternal(FILE *file) +{ + fprintf(file, "#ifdef\tmig_external\n"); + fprintf(file, "mig_external\n"); + fprintf(file, "#else\n"); + fprintf(file, "extern\n"); + fprintf(file, "#endif\t/* mig_external */\n"); +} + +void +WriteMigInternal(FILE *file) +{ + fprintf(file, "#ifdef\tmig_internal\n"); + fprintf(file, "mig_internal\n"); + fprintf(file, "#else\n"); + fprintf(file, "static\n"); + fprintf(file, "#endif\t/* mig_internal */\n"); +} + +void +WriteImport(FILE *file, string_t filename) +{ + fprintf(file, "#include %s\n", filename); +} + +void +WriteImplImports(FILE *file, statement_t *stats, boolean_t isuser) +{ + statement_t *stat; + + for (stat = stats; stat != stNULL; stat = stat->stNext) + switch (stat->stKind) { + + case skImport: + case skIImport: + WriteImport(file, stat->stFileName); + break; + + case skSImport: + if (!isuser) + WriteImport(file, stat->stFileName); + break; + + case skUImport: + if (isuser) + WriteImport(file, stat->stFileName); + break; + + case skRoutine: + case skDImport: + break; + + default: + fatal("WriteImplImport(): bad statement_kind_t (%d)", (int) stat->stKind); + } +} + +void +WriteRCSDecl(FILE *file, identifier_t name, string_t rcs) +{ + fprintf(file, "#ifndef\tlint\n"); + fprintf(file, "#if\tUseExternRCSId\n"); + fprintf(file, "%s char %s_rcsid[] = %s;\n", (BeAnsiC) ? "const" : "", name, rcs); + fprintf(file, "#else\t/* UseExternRCSId */\n"); + fprintf(file, "static %s char rcsid[] = %s;\n", (BeAnsiC) ? "const" : "", rcs); + fprintf(file, "#endif\t/* UseExternRCSId */\n"); + fprintf(file, "#endif\t/* lint */\n"); + fprintf(file, "\n"); +} + +static void +WriteOneApplDefault(FILE *file, char *word1, char *word2, char *word3) +{ + char buf[50]; + + sprintf(buf, "__%s%s%s", word1, word2, word3); + fprintf(file, "#ifndef\t%s\n", buf); + fprintf(file, "#define\t%s(_NUM_, _NAME_)\n", buf); + fprintf(file, "#endif\t/* %s */\n", buf); + fprintf(file, "\n"); +} + +void +WriteApplDefaults(FILE *file, char *dir) +{ + WriteOneApplDefault(file, "Declare", dir, "Rpc"); + WriteOneApplDefault(file, "Before", dir, "Rpc"); + WriteOneApplDefault(file, "After", dir, "Rpc"); + WriteOneApplDefault(file, "Declare", dir, "Simple"); + WriteOneApplDefault(file, "Before", dir, "Simple"); + WriteOneApplDefault(file, "After", dir, "Simple"); +} + +void +WriteApplMacro(FILE *file, char *dir, char *when, routine_t *rt) +{ + char *what = (rt->rtOneWay) ? "Simple" : "Rpc"; + + fprintf(file, "\t__%s%s%s(%d, \"%s\")\n", when, dir, what, SubsystemBase + rt->rtNumber, rt->rtName); +} + + +void +WriteBogusDefines(FILE *file) +{ + fprintf(file, "#ifndef\tmig_internal\n"); + fprintf(file, "#define\tmig_internal\tstatic __inline__\n"); + fprintf(file, "#endif\t/* mig_internal */\n"); + fprintf(file, "\n"); + + fprintf(file, "#ifndef\tmig_external\n"); + fprintf(file, "#define mig_external\n"); + fprintf(file, "#endif\t/* mig_external */\n"); + fprintf(file, "\n"); + + fprintf(file, "#if\t!defined(__MigTypeCheck) && defined(TypeCheck)\n"); + fprintf(file, "#define\t__MigTypeCheck\t\tTypeCheck\t/* Legacy setting */\n"); + fprintf(file, "#endif\t/* !defined(__MigTypeCheck) */\n"); + fprintf(file, "\n"); + + fprintf(file, "#if\t!defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)\n"); + fprintf(file, "#define\t__MigKernelSpecificCode\t_MIG_KERNEL_SPECIFIC_CODE_\t/* Legacy setting */\n"); + fprintf(file, "#endif\t/* !defined(__MigKernelSpecificCode) */\n"); + fprintf(file, "\n"); + + fprintf(file, "#ifndef\tLimitCheck\n"); + fprintf(file, "#define\tLimitCheck 0\n"); + fprintf(file, "#endif\t/* LimitCheck */\n"); + fprintf(file, "\n"); + + fprintf(file, "#ifndef\tmin\n"); + fprintf(file, "#define\tmin(a,b) ( ((a) < (b))? (a): (b) )\n"); + fprintf(file, "#endif\t/* min */\n"); + fprintf(file, "\n"); + + fprintf(file, "#if !defined(_WALIGN_)\n"); + fprintf(file, "#define _WALIGN_(x) (((x) + %d) & ~%d)\n", (int)(itWordAlign - 1), (int)(itWordAlign - 1)); + fprintf(file, "#endif /* !defined(_WALIGN_) */\n"); + fprintf(file, "\n"); + + fprintf(file, "#if !defined(_WALIGNSZ_)\n"); + fprintf(file, "#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))\n"); + fprintf(file, "#endif /* !defined(_WALIGNSZ_) */\n"); + fprintf(file, "\n"); + + fprintf(file, "#ifndef\tUseStaticTemplates\n"); + if (BeAnsiC) { + fprintf(file, "#define\tUseStaticTemplates\t0\n"); + } + else { + fprintf(file, "#if\t%s\n", NewCDecl); + fprintf(file, "#define\tUseStaticTemplates\t0\n"); + fprintf(file, "#endif\t/* %s */\n", NewCDecl); + } + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); + fprintf(file, "\n"); + + WriteBogusServerRoutineAnnotationDefine(file); +} + +void +WriteList(FILE *file, argument_t *args, void (*func)(FILE *, argument_t *), u_int mask, char *between, char *after) +{ + argument_t *arg; + boolean_t sawone = FALSE; + + for (arg = args; arg != argNULL; arg = arg->argNext) + if (akCheckAll(arg->argKind, mask)) { + if (sawone) + fprintf(file, "%s", between); + sawone = TRUE; + + (*func)(file, arg); + } + + if (sawone) + fprintf(file, "%s", after); +} + + +static boolean_t +WriteReverseListPrim(FILE *file, argument_t *arg, void (*func)(FILE *, argument_t *), u_int mask, char *between) +{ + boolean_t sawone = FALSE; + + if (arg != argNULL) { + sawone = WriteReverseListPrim(file, arg->argNext, func, mask, between); + + if (akCheckAll(arg->argKind, mask)) { + if (sawone) + fprintf(file, "%s", between); + sawone = TRUE; + + (*func)(file, arg); + } + } + + return sawone; +} + +void +WriteReverseList(FILE *file, argument_t *args, void (*func)(FILE *file, argument_t *args), u_int mask, char *between, char *after) +{ + boolean_t sawone; + + sawone = WriteReverseListPrim(file, args, func, mask, between); + + if (sawone) + fprintf(file, "%s", after); +} + +void +WriteNameDecl(FILE *file, argument_t *arg) +{ + fprintf(file, "%s", arg->argVarName); +} + +void +WriteUserVarDecl(FILE *file, argument_t *arg) +{ + boolean_t pointer = (arg->argByReferenceUser ||arg->argType->itNativePointer); + char *ref = (pointer) ? "*" : ""; + char *cnst = ((arg->argFlags & flConst) && + (IS_VARIABLE_SIZED_UNTYPED(arg->argType) || + arg->argType->itNoOptArray || arg->argType->itString)) ? "const " : ""; + + fprintf(file, "\t%s%s %s%s", cnst, arg->argType->itUserType, ref, arg->argVarName); +} + +void +WriteServerVarDecl(FILE *file, argument_t *arg) +{ + char *ref = (arg->argByReferenceServer || + arg->argType->itNativePointer) ? "*" : ""; + char *cnst = ((arg->argFlags & flConst) && + (IS_VARIABLE_SIZED_UNTYPED(arg->argType) || + arg->argType->itNoOptArray || arg->argType->itString)) ? "const " : ""; + + fprintf(file, "\t%s%s %s%s", cnst, arg->argType->itTransType, ref, arg->argVarName); +} + +char * +ReturnTypeStr(routine_t *rt) +{ + return rt->rtRetCode->argType->itUserType; +} + +char * +FetchUserType(ipc_type_t *it) +{ + return it->itUserType; +} + +char * +FetchServerType(ipc_type_t *it) +{ + return it->itServerType; +} + +char * +FetchKPDType(ipc_type_t *it) +{ + return it->itKPDType; +} + +void +WriteTrailerDecl(FILE *file, boolean_t trailer) +{ + if (trailer) + fprintf(file, "\t\tmach_msg_max_trailer_t trailer;\n"); + else + fprintf(file, "\t\tmach_msg_trailer_t trailer;\n"); +} + +void +WriteFieldDeclPrim(FILE *file, argument_t *arg, char *(*tfunc)(ipc_type_t *it)) +{ + ipc_type_t *it = arg->argType; + + if (IS_VARIABLE_SIZED_UNTYPED(it) || it->itNoOptArray) { + argument_t *count = arg->argCount; + ipc_type_t *btype = it->itElement; + + /* + * Build our own declaration for a varying array: + * use the element type and maximum size specified. + * Note arg->argCount->argMultiplier == btype->itNumber. + */ + /* + * NDR encoded VarStrings requires the offset field. + * Since it is not used, it wasn't worthwhile to create an extra + * parameter + */ + if (it->itString) + fprintf(file, "\t\t%s %sOffset; /* MiG doesn't use it */\n", (*tfunc)(count->argType), arg->argName); + + if (!(arg->argFlags & flSameCount) && !it->itNoOptArray) + /* in these cases we would have a count, which we don't want */ + fprintf(file, "\t\t%s %s;\n", (*tfunc)(count->argType), count->argMsgField); + fprintf(file, "\t\t%s %s[%d];", (*tfunc)(btype), arg->argMsgField, it->itNumber/btype->itNumber); + } + else if (IS_MULTIPLE_KPD(it)) + fprintf(file, "\t\t%s %s[%d];", (*tfunc)(it), arg->argMsgField, it->itKPD_Number); + else if (IS_OPTIONAL_NATIVE(it)) { + fprintf(file, "\t\tboolean_t __Present__%s;\n", arg->argMsgField); + fprintf(file, "\t\tunion {\n"); + fprintf(file, "\t\t %s __Real__%s;\n", (*tfunc)(it), arg->argMsgField); + fprintf(file, "\t\t char __Phony__%s[_WALIGNSZ_(%s)];\n", arg->argMsgField, (*tfunc)(it)); + fprintf(file, "\t\t} %s;", arg->argMsgField); + } + else { + /* either simple KPD or simple in-line */ + fprintf(file, "\t\t%s %s;", (*tfunc)(it), arg->argMsgField); + } + + /* Kernel Processed Data has always PadSize = 0 */ + if (it->itPadSize != 0) + fprintf(file, "\n\t\tchar %s[%d];", arg->argPadName, it->itPadSize); +} + +void +WriteKPDFieldDecl(FILE *file, argument_t *arg) +{ + if (akCheck(arg->argKind, akbSendKPD) || + akCheck(arg->argKind, akbReturnKPD)) + WriteFieldDeclPrim(file, arg, FetchKPDType); + else + WriteFieldDeclPrim(file, arg, FetchServerType); +} + +void +WriteStructDecl( + FILE *file, + argument_t *args, + void (*func)(FILE *, argument_t *), + u_int mask, + char *name, + boolean_t simple, + boolean_t trailer, + boolean_t trailer_t, + boolean_t template_only) +{ + fprintf(file, "\n#ifdef __MigPackStructs\n#pragma pack(push, %lu)\n#endif\n",sizeof(natural_t)); + fprintf(file, "\ttypedef struct {\n"); + fprintf(file, "\t\tmach_msg_header_t Head;\n"); + if (simple == FALSE) { + fprintf(file, "\t\t/* start of the kernel processed data */\n"); + fprintf(file, "\t\tmach_msg_body_t msgh_body;\n"); + if (mask == akbRequest) + WriteList(file, args, func, mask | akbSendKPD, "\n", "\n"); + else + WriteList(file, args, func, mask | akbReturnKPD, "\n", "\n"); + fprintf(file, "\t\t/* end of the kernel processed data */\n"); + } + if (!template_only) { + if (mask == akbRequest) + WriteList(file, args, func, mask | akbSendBody, "\n", "\n"); + + else + WriteList(file, args, func, mask | akbReturnBody, "\n", "\n"); + if (trailer) + WriteTrailerDecl(file, trailer_t); + } + fprintf(file, "\t} %s __attribute__((unused));\n", name); + fprintf(file, "#ifdef __MigPackStructs\n#pragma pack(pop)\n#endif\n"); +} + +void +WriteTemplateDeclIn(FILE *file, argument_t *arg) +{ + (*arg->argKPD_Template)(file, arg, TRUE); +} + +void +WriteTemplateDeclOut(FILE *file, argument_t *arg) +{ + (*arg->argKPD_Template)(file, arg, FALSE); +} + +void +WriteTemplateKPD_port(FILE *file, argument_t *arg, boolean_t in) +{ + ipc_type_t *it = arg->argType; + + fprintf(file, "#if\tUseStaticTemplates\n"); + fprintf(file, "\tconst static %s %s = {\n", it->itKPDType, arg->argTTName); + + fprintf(file, "\t\t/* name = */\t\tMACH_PORT_NULL,\n"); + fprintf(file, "\t\t/* pad1 = */\t\t0,\n"); + fprintf(file, "\t\t/* pad2 = */\t\t0,\n"); + fprintf(file, "\t\t/* disp = */\t\t%s,\n", in ? it->itInNameStr: it->itOutNameStr); + fprintf(file, "\t\t/* type = */\t\tMACH_MSG_PORT_DESCRIPTOR,\n"); + + fprintf(file, "\t};\n"); + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); +} + +void +WriteTemplateKPD_ool(FILE *file, argument_t *arg, boolean_t in) +{ + ipc_type_t *it = arg->argType; + + fprintf(file, "#if\tUseStaticTemplates\n"); + fprintf(file, "\tconst static %s %s = {\n", it->itKPDType, arg->argTTName); + + if (IS_MULTIPLE_KPD(it)) + it = it->itElement; + + fprintf(file, "\t\t/* addr = */\t\t(void *)0,\n"); + if (it->itVarArray) + fprintf(file, "\t\t/* size = */\t\t0,\n"); + else + fprintf(file, "\t\t/* size = */\t\t%d,\n", (it->itNumber * it->itSize + 7)/8); + fprintf(file, "\t\t/* deal = */\t\t%s,\n", (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE"); + /* the d_MAYBE case will be fixed runtime */ + fprintf(file, "\t\t/* copy = */\t\t%s,\n", (arg->argFlags & flPhysicalCopy) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY"); + /* the PHYSICAL COPY flag has not been established yet */ + fprintf(file, "\t\t/* pad2 = */\t\t0,\n"); + fprintf(file, "\t\t/* type = */\t\tMACH_MSG_OOL_DESCRIPTOR,\n"); + + fprintf(file, "\t};\n"); + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); +} + +void +WriteTemplateKPD_oolport(FILE *file, argument_t *arg, boolean_t in) +{ + ipc_type_t *it = arg->argType; + + fprintf(file, "#if\tUseStaticTemplates\n"); + fprintf(file, "\tconst static %s %s = {\n", it->itKPDType, arg->argTTName); + + if (IS_MULTIPLE_KPD(it)) + it = it->itElement; + + fprintf(file, "\t\t/* addr = */\t\t(void *)0,\n"); + if (!it->itVarArray) + fprintf(file, "\t\t/* coun = */\t\t%d,\n", it->itNumber); + else + fprintf(file, "\t\t/* coun = */\t\t0,\n"); + fprintf(file, "\t\t/* deal = */\t\t%s,\n", (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE"); + fprintf(file, "\t\t/* copy is meaningful only in overwrite mode */\n"); + fprintf(file, "\t\t/* copy = */\t\tMACH_MSG_PHYSICAL_COPY,\n"); + fprintf(file, "\t\t/* disp = */\t\t%s,\n", in ? it->itInNameStr: it->itOutNameStr); + fprintf(file, "\t\t/* type = */\t\tMACH_MSG_OOL_PORTS_DESCRIPTOR,\n"); + + fprintf(file, "\t};\n"); + fprintf(file, "#endif\t/* UseStaticTemplates */\n"); +} + +void +WriteReplyTypes(FILE *file, statement_t *stats) +{ + statement_t *stat; + + fprintf(file, "/* typedefs for all replies */\n\n"); + fprintf(file, "#ifndef __Reply__%s_subsystem__defined\n", SubsystemName); + fprintf(file, "#define __Reply__%s_subsystem__defined\n", SubsystemName); + for (stat = stats; stat != stNULL; stat = stat->stNext) { + if (stat->stKind == skRoutine) { + routine_t *rt; + char str[MAX_STR_LEN]; + + rt = stat->stRoutine; + sprintf(str, "__Reply__%s_t", rt->rtName); + WriteStructDecl(file, rt->rtArgs, WriteKPDFieldDecl, akbReply, str, rt->rtSimpleReply, FALSE, FALSE, FALSE); + } + } + fprintf(file, "#endif /* !__Reply__%s_subsystem__defined */\n", SubsystemName); + fprintf(file, "\n"); +} + +void +WriteRequestTypes(FILE *file, statement_t *stats) +{ + statement_t *stat; + + fprintf(file, "/* typedefs for all requests */\n\n"); + fprintf(file, "#ifndef __Request__%s_subsystem__defined\n", SubsystemName); + fprintf(file, "#define __Request__%s_subsystem__defined\n", SubsystemName); + for (stat = stats; stat != stNULL; stat = stat->stNext) { + if (stat->stKind == skRoutine) { + routine_t *rt; + char str[MAX_STR_LEN]; + + rt = stat->stRoutine; + sprintf(str, "__Request__%s_t", rt->rtName); + WriteStructDecl(file, rt->rtArgs, WriteKPDFieldDecl, akbRequest, str, rt->rtSimpleRequest, FALSE, FALSE, FALSE); + } + } + fprintf(file, "#endif /* !__Request__%s_subsystem__defined */\n", SubsystemName); + fprintf(file, "\n"); +} + +void +WriteNDRConvertArgDecl(FILE *file, argument_t *arg, char *convert, char *dir) +{ + argument_t *count = arg->argCount; + argument_t *parent = arg->argParent; + char *carg = (count) ? ", c" : ""; + routine_t *rt = arg->argRoutine; + ipc_type_t *ptype = arg->argType; + ipc_type_t *btype; + int multi, array; + char domain[MAX_STR_LEN]; + + fprintf(file, "#ifndef __NDR_convert__%s__%s__%s_t__%s__defined\n#", convert, dir, rt->rtName, arg->argMsgField); + + for (btype = ptype, multi = (!parent) ? arg->argMultiplier : 1, array = 0; + btype; + ptype = btype, array += ptype->itVarArray, btype = btype->itElement) { + char *bttype; + + if (btype->itNumber < ptype->itNumber && !ptype->itVarArray && !parent) { + multi *= ptype->itNumber / btype->itNumber; + if (!btype->itString) + continue; + } + else if (array && ptype->itVarArray) + continue; + if (btype != ptype) + fprintf(file, "#el"); + + bttype = (multi > 1 && btype->itString) ? "string" : FetchServerType(btype); + sprintf(domain, "__%s", SubsystemName); + do { + fprintf(file, "if\tdefined(__NDR_convert__%s%s__%s__defined)\n", convert, domain, bttype); + fprintf(file, "#define\t__NDR_convert__%s__%s__%s_t__%s__defined\n", convert, dir, rt->rtName, arg->argMsgField); + fprintf(file, "#define\t__NDR_convert__%s__%s__%s_t__%s(a, f%s) \\\n\t", convert, dir, rt->rtName, arg->argMsgField, carg); + if (multi > 1) { + if (array) { + if (btype->itString) + fprintf(file, "__NDR_convert__2DARRAY((%s *)(a), f, %d, c, ", bttype, multi); + else + fprintf(file, "__NDR_convert__ARRAY((%s *)(a), f, %d * (c), ", bttype, multi); + } + else if (!btype->itString) + fprintf(file, "__NDR_convert__ARRAY((%s *)(a), f, %d, ", bttype, multi); + } + else if (array) + fprintf(file, "__NDR_convert__ARRAY((%s *)(a), f, c, ", bttype); + fprintf(file, "__NDR_convert__%s%s__%s", convert, domain, bttype); + if (multi > 1) { + if (!array && btype->itString) + fprintf(file, "(a, f, %d", multi); + } + else if (!array) + fprintf(file, "((%s *)(a), f%s", bttype, carg); + fprintf(file, ")\n"); + } while (strcmp(domain, "") && ((void)(domain[0] = '\0'), fprintf(file, "#el"))); + } + fprintf(file, "#endif /* defined(__NDR_convert__*__defined) */\n"); + fprintf(file, "#endif /* __NDR_convert__%s__%s__%s_t__%s__defined */\n\n", convert, dir, rt->rtName, arg->argMsgField); +} + +/* + * Like vfprintf, but omits a leading comment in the format string + * and skips the items that would be printed by it. Only %s, %d, + * and %f are recognized. + */ +void +SkipVFPrintf(FILE *file, char *fmt, va_list pvar) +{ + if (*fmt == 0) + return; /* degenerate case */ + + if (fmt[0] == '/' && fmt[1] == '*') { + /* Format string begins with C comment. Scan format + string until end-comment delimiter, skipping the + items in pvar that the enclosed format items would + print. */ + + int c; + + fmt += 2; + for (;;) { + c = *fmt++; + if (c == 0) + return; /* nothing to format */ + if (c == '*') { + if (*fmt == '/') { + break; + } + } + else if (c == '%') { + /* Field to skip */ + c = *fmt++; + switch (c) { + + case 's': + (void) va_arg(pvar, char *); + break; + + case 'd': + (void) va_arg(pvar, int); + break; + + case 'f': + (void) va_arg(pvar, double); + break; + + case '\0': + return; /* error - fmt ends with '%' */ + + default: + break; + } + } + } + /* End of comment. To be pretty, skip + the space that follows. */ + fmt++; + if (*fmt == ' ') + fmt++; + } + + /* Now format the string. */ + (void) vfprintf(file, fmt, pvar); +} + +static void +vWriteCopyType(FILE *file, ipc_type_t *it, boolean_t mig_allocated_buf, char *left, char *right, va_list pvar) +{ + va_list pvar2; + va_copy(pvar2, pvar); + + if (it->itStruct) { + + fprintf(file, "\t"); + (void) SkipVFPrintf(file, left, pvar); + fprintf(file, " = "); + (void) SkipVFPrintf(file, right, pvar2); + fprintf(file, ";\n"); + } + else if (it->itString) { + va_list pvar3, pvar4; + va_copy(pvar3, pvar); + va_copy(pvar4, pvar); + + if (mig_allocated_buf) { + /* + * zero-fill MIG allocated buffers: we control the size so there's + * no risk of buffer overrun, and we avoid leaking process/kernel + * memory on the copy-out + */ + fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n"); + fprintf(file, "\tif (mig_strncpy_zerofill != NULL) {\n"); + fprintf(file, "\t\t(void) mig_strncpy_zerofill("); + (void) SkipVFPrintf(file, left, pvar); + fprintf(file, ", "); + (void) SkipVFPrintf(file, right, pvar2); + fprintf(file, ", %d);\n", it->itTypeSize); + fprintf(file, "\t} else {\n"); + fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n\t"); + } + fprintf(file, "\t(void) mig_strncpy("); + + (void) SkipVFPrintf(file, left, pvar3); + fprintf(file, ", "); + (void) SkipVFPrintf(file, right, pvar4); + fprintf(file, ", %d);\n", it->itTypeSize); + + if (mig_allocated_buf) { + fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n"); + fprintf(file, "\t}\n"); + fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n"); + } + + va_end(pvar3); + va_end(pvar4); + } + else { + fprintf(file, "\t{ typedef struct { char data[%d]; } *sp;\n", it->itTypeSize); + fprintf(file, "\t * (sp) "); + (void) SkipVFPrintf(file, left, pvar); + fprintf(file, " = * (sp) "); + (void) SkipVFPrintf(file, right, pvar2); + fprintf(file, ";\n\t}\n"); + } + + va_end(pvar2); +} + + +/*ARGSUSED*/ +/*VARARGS4*/ +void +WriteCopyType(FILE *file, ipc_type_t *it, boolean_t mig_allocated_buf, char *left, char *right, ...) +{ + va_list pvar; + va_start(pvar, right); + + vWriteCopyType(file, it, mig_allocated_buf, left, right, pvar); + + va_end(pvar); +} + + +/*ARGSUSED*/ +/*VARARGS4*/ +void +WriteCopyArg(FILE *file, argument_t *arg, boolean_t mig_allocated_buf, char *left, char *right, ...) +{ + va_list pvar; + va_start(pvar, right); + + { + ipc_type_t *it = arg->argType; + if (it->itVarArray && !it->itString) { + fprintf(file, "\t (void)memcpy("); + (void) SkipVFPrintf(file, left, pvar); + va_end(pvar); + fprintf(file, ", "); + va_start(pvar, right); + (void) SkipVFPrintf(file, right, pvar); + fprintf(file, ", %s);\n", arg->argCount->argVarName); + } + else + vWriteCopyType(file, it, mig_allocated_buf, left, right, pvar); + } + + va_end(pvar); +} + + +/* + * Global KPD disciplines + */ +void +KPD_error(FILE *file, argument_t *arg) +{ + printf("MiG internal error: argument is %s\n", arg->argVarName); + exit(1); +} + +void +KPD_noop(FILE *file, argument_t *arg) +{ + /* Nothing to see here, people. Move it along... */ +} + +static void +WriteStringDynArgs(argument_t *args, u_int mask, string_t InPOutP, string_t *str_oolports, string_t *str_ool) +{ + argument_t *arg; + char loc[100], sub[20]; + string_t tmp_str1 = ""; + string_t tmp_str2 = ""; + int cnt, multiplier = 1; + boolean_t test, complex = FALSE; + + for (arg = args; arg != argNULL; arg = arg->argNext) { + ipc_type_t *it = arg->argType; + + if (IS_MULTIPLE_KPD(it)) { + test = it->itVarArray || it->itElement->itVarArray; + if (test) { + multiplier = it->itKPD_Number; + it = it->itElement; + complex = TRUE; + } + } + else + test = it->itVarArray; + + cnt = multiplier; + while (cnt) { + if (complex) + sprintf(sub, "[%d]", multiplier - cnt); + if (akCheck(arg->argKind, mask) && + it->itPortType && !it->itInLine && test) { + sprintf(loc, " + %s->%s%s.count", InPOutP, arg->argMsgField, complex ? sub : ""); + tmp_str1 = strconcat(tmp_str1, loc); + } + if (akCheck(arg->argKind, mask) && + !it->itInLine && !it->itPortType && test) { + sprintf(loc, " + %s->%s%s.size", InPOutP, arg->argMsgField, complex ? sub : ""); + tmp_str2 = strconcat(tmp_str2, loc); + } + cnt--; + } + } + *str_oolports = tmp_str1; + *str_ool = tmp_str2; +} + +/* + * Utilities for Logging Events that happen at the stub level + */ +void +WriteLogMsg(FILE *file, routine_t *rt, int where, int what) +{ + string_t ptr_str; + string_t StringOolPorts = strNULL; + string_t StringOOL = strNULL; + u_int ports, oolports, ool; + string_t event; + + fprintf(file, "\n#if MIG_DEBUG\n"); + if (where == LOG_USER) + fprintf(file, "\tLOG_TRACE(MACH_MSG_LOG_USER,\n"); + else + fprintf(file, "\tLOG_TRACE(MACH_MSG_LOG_SERVER,\n"); + if (where == LOG_USER && what == LOG_REQUEST) { + ptr_str = "InP"; + event = "MACH_MSG_REQUEST_BEING_SENT"; + } + else if (where == LOG_USER && what == LOG_REPLY) { + ptr_str = "Out0P"; + event = "MACH_MSG_REPLY_BEING_RCVD"; + } + else if (where == LOG_SERVER && what == LOG_REQUEST) { + ptr_str = "In0P"; + event = "MACH_MSG_REQUEST_BEING_RCVD"; + } + else { + ptr_str = "OutP"; + event = "MACH_MSG_REPLY_BEING_SENT"; + } + WriteStringDynArgs(rt->rtArgs, (what == LOG_REQUEST) ? akbSendKPD : akbReturnKPD, ptr_str, &StringOolPorts, &StringOOL); + fprintf(file, "\t\t%s,\n", event); + fprintf(file, "\t\t%s->Head.msgh_id,\n", ptr_str); + if (where == LOG_USER && what == LOG_REQUEST) { + if (rt->rtNumRequestVar) + fprintf(file, "\t\tmsgh_size,\n"); + else + fprintf(file, "\t\t(mach_msg_size_t)sizeof(Request),\n"); + } + else + fprintf(file, "\t\t%s->Head.msgh_size,\n", ptr_str); + if ((what == LOG_REQUEST && rt->rtSimpleRequest == FALSE) || + (what == LOG_REPLY && rt->rtSimpleReply == FALSE)) + fprintf(file, "\t\t%s->msgh_body.msgh_descriptor_count,\n", ptr_str); + else + fprintf(file, "\t\t0, /* Kernel Proc. Data entries */\n"); + if (what == LOG_REQUEST) { + fprintf(file, "\t\t0, /* RetCode */\n"); + ports = rt->rtCountPortsIn; + oolports = rt->rtCountOolPortsIn; + ool = rt->rtCountOolIn; + } + else { + if (akCheck(rt->rtRetCode->argKind, akbReply)) + fprintf(file, "\t\t%s->RetCode,\n", ptr_str); + else + fprintf(file, "\t\t0, /* RetCode */\n"); + ports = rt->rtCountPortsOut; + oolports = rt->rtCountOolPortsOut; + ool = rt->rtCountOolOut; + } + fprintf(file, "\t\t/* Ports */\n"); + fprintf(file, "\t\t%d,\n", ports); + fprintf(file, "\t\t/* Out-of-Line Ports */\n"); + fprintf(file, "\t\t%d", oolports); + if (StringOolPorts != strNULL) + fprintf(file, "%s,\n", StringOolPorts); + else + fprintf(file, ",\n"); + fprintf(file, "\t\t/* Out-of-Line Bytes */\n"); + fprintf(file, "\t\t%d", ool); + if (StringOOL != strNULL) + fprintf(file, "%s,\n", StringOOL); + else + fprintf(file, ",\n"); + fprintf(file, "\t\t__FILE__, __LINE__);\n"); + fprintf(file, "#endif /* MIG_DEBUG */\n\n"); +} + +void +WriteLogDefines(FILE *file, string_t who) +{ + fprintf(file, "#if MIG_DEBUG\n"); + fprintf(file, "#define LOG_W_E(X)\tLOG_ERRORS(%s, \\\n", who); + fprintf(file, "\t\t\tMACH_MSG_ERROR_WHILE_PARSING, (void *)(X), __FILE__, __LINE__)\n"); + fprintf(file, "#else /* MIG_DEBUG */\n"); + fprintf(file, "#define LOG_W_E(X)\n"); + fprintf(file, "#endif /* MIG_DEBUG */\n"); + fprintf(file, "\n"); +} + +/* common utility to report errors */ +void +WriteReturnMsgError(FILE *file, routine_t *rt, boolean_t isuser, argument_t *arg, string_t error) +{ + char space[MAX_STR_LEN]; + string_t string = &space[0]; + + if (UseEventLogger && arg != argNULL) + sprintf(string, "LOG_W_E(\"%s\"); ", arg->argVarName); + else + string = ""; + + fprintf(file, "\t\t{ "); + + if (isuser) { + if (! rtMessOnStack(rt)) + fprintf(file, "%s((char *) Mess, (mach_msg_size_t)sizeof(*Mess)); ", MessFreeRoutine); + + fprintf(file, "%sreturn %s; }\n", string, error); + } + else + fprintf(file, "%sMIG_RETURN_ERROR(OutP, %s); }\n", string, error); +} + +/* executed iff elements are defined */ +void +WriteCheckTrailerHead(FILE *file, routine_t *rt, boolean_t isuser) +{ + string_t who = (isuser) ? "Out0P" : "In0P"; + + fprintf(file, "\tTrailerP = (mach_msg_max_trailer_t *)((vm_offset_t)%s +\n", who); + fprintf(file, "\t\tround_msg(%s->Head.msgh_size));\n", who); + fprintf(file, "\tif (TrailerP->msgh_trailer_type != MACH_MSG_TRAILER_FORMAT_0)\n"); + if (isuser) + fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); + else + fprintf(file, "\t\t{ MIG_RETURN_ERROR(%s, MIG_TRAILER_ERROR); }\n", who); + + fprintf(file, "#if\t__MigTypeCheck\n"); + fprintf(file, "\ttrailer_size = TrailerP->msgh_trailer_size -\n"); + fprintf(file, "\t\t(mach_msg_size_t)(sizeof(mach_msg_trailer_type_t) - sizeof(mach_msg_trailer_size_t));\n"); + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); +} + +/* executed iff elements are defined */ +void +WriteCheckTrailerSize(FILE *file, boolean_t isuser, argument_t *arg) +{ + fprintf(file, "#if\t__MigTypeCheck\n"); + if (akIdent(arg->argKind) == akeMsgSeqno) { + fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(mach_port_seqno_t))\n"); + if (isuser) + fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); + else + fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n"); + fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(mach_port_seqno_t);\n"); + } + else if (akIdent(arg->argKind) == akeSecToken) { + fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(security_token_t))\n"); + if (isuser) + fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); + else + fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n"); + fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(security_token_t);\n"); + } + else if (akIdent(arg->argKind) == akeAuditToken) { + fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(audit_token_t))\n"); + if (isuser) + fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); + else + fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n"); + fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(audit_token_t);\n"); + } + else if (akIdent(arg->argKind) == akeContextToken) { + fprintf(file, "\tif (trailer_size < (mach_msg_size_t)sizeof(mach_vm_address_t))\n"); + if (isuser) + fprintf(file, "\t\t{ return MIG_TRAILER_ERROR ; }\n"); + else + fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, MIG_TRAILER_ERROR); }\n"); + fprintf(file, "\ttrailer_size -= (mach_msg_size_t)sizeof(mach_vm_address_t);\n"); + } + fprintf(file, "#endif\t/* __MigTypeCheck */\n"); +} + -- cgit v1.2.3-56-ge451