bootstrap_cmds/migcom.tproj/mig.c

bootstrap_cmds source @ c71d2d7 2025-04-30 · 427 lines · view on GitHub
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 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 the 46 * rights to redistribute these changes. 47 */ 48 49/* 50 * Switches are; 51 * -[v,Q] verbose or not quiet: prints out type 52 * and routine information as mig runs. 53 * -[V,q] not verbose or quiet : don't print 54 * information during compilation 55 * (this is the default) 56 * -[r,R] do or don't use rpc calls instead of 57 * send/receive pairs. Default is -r. 58 * -[s,S] generate symbol table or not: generate a 59 * table of rpc-name, number, routine triplets 60 * as an external data structure -- main use is 61 * for protection system's specification of rights 62 * and for protection dispatch code. Default is -s. 63 * -[l,L] -L generate code that insert code for logging 64 * the most important events that happen at the 65 * stub level (message conception, target routine 66 * calls). Default is -l. 67 * -[k,K] -K enforces MIG to generate K&R C language, with the 68 * addition of ANSI C syntax under #ifdef __STDC__. 69 * Default is -k. 70 * -[n,N] -n enforces NDR checking and conversion logic generation. 71 * Default is -N (no checking). 72 * -i <prefix> 73 * Put each user routine in its own file. The 74 * file is named <prefix><routine-name>.c. 75 * -user <name> 76 * Name the user-side file <name> 77 * -server <name> 78 * Name the server-side file <name> 79 * -header <name> 80 * Name the user-side header file <name> 81 * -iheader <name> 82 * Name the user-side internal header file <name> 83 * -sheader <name> 84 * Name the server-side header file <name> 85 * -dheader <name> 86 * Name the defines (msgh_ids) header file <name> 87 * 88 * DESIGN: 89 * Mig uses a lexxer module created by lex from lexxer.l and 90 * a parser module created by yacc from parser.y to parse an 91 * interface definitions module for a mach server. 92 * The parser module calls routines in statement.c 93 * and routines.c to build a list of statement structures. 94 * The most interesting statements are the routine definitions 95 * which contain information about the name, type, characteristics 96 * of the routine, an argument list containing information for 97 * each argument type, and a list of special arguments. The 98 * argument type structures are build by routines in type.c 99 * Once parsing is completed, the three code generation modules: 100 * header.c user.c and server.c are called sequentially. These 101 * do some code generation directly and also call the routines 102 * in utils.c for common (parameterized) code generation. 103 * 104 */ 105 106#include <stdlib.h> 107#include <stdio.h> 108#include <time.h> 109#include "error.h" 110#include "lexxer.h" 111#include "global.h" 112#include "write.h" 113 114extern int yyparse(void); 115static FILE *myfopen(const char *name, const char *mode); 116 117static void 118parseArgs(int argc,char *argv[]) 119{ 120 if (argc == 2 && streql(argv[1], "-version")) { 121 PrintVersion = TRUE; 122 return; 123 } 124 125 while (--argc > 0) 126 if ((++argv)[0][0] == '-') { 127 switch (argv[0][1]) { 128 129 case 'q': 130 BeQuiet = TRUE; 131 break; 132 133 case 'Q': 134 BeQuiet = FALSE; 135 break; 136 137 case 'v': 138 BeVerbose = TRUE; 139 break; 140 141 case 'V': 142 BeVerbose = FALSE; 143 break; 144 145 case 'r': 146 UseMsgRPC = TRUE; 147 break; 148 149 case 'R': 150 UseMsgRPC = FALSE; 151 break; 152 153 case 'l': 154 UseEventLogger = FALSE; 155 break; 156 157 case 'L': 158 UseEventLogger = TRUE; 159 break; 160 161 case 'k': 162 BeAnsiC = TRUE; 163 break; 164 165 case 'K': 166 BeAnsiC = FALSE; 167 break; 168 169 case 'n': 170 if (streql(argv[0], "-novouchers")) { 171 IsVoucherCodeAllowed = FALSE; 172 } else { 173 CheckNDR = TRUE; 174 } 175 break; 176 177 case 'N': 178 CheckNDR = FALSE; 179 break; 180 181 case 'b': 182 EmitCountAnnotations = TRUE; 183 break; 184 185 case 'B': 186 EmitCountAnnotations = FALSE; 187 break; 188 189 case 's': 190 if (streql(argv[0], "-server")) { 191 --argc; ++argv; 192 if (argc == 0) 193 fatal("missing name for -server option"); 194 ServerFileName = strmake(argv[0]); 195 } 196 else if (streql(argv[0], "-sheader")) { 197 --argc; ++argv; 198 if (argc == 0) 199 fatal ("missing name for -sheader option"); 200 ServerHeaderFileName = strmake(argv[0]); 201 } 202 else if (streql(argv[0], "-split")) 203 UseSplitHeaders = TRUE; 204 else 205 GenSymTab = TRUE; 206 break; 207 208 case 'S': 209 GenSymTab = FALSE; 210 break; 211 212 case 't': 213 warn("Mach RPC traps not fully supported"); 214 TestRPCTrap = TRUE; 215 UseRPCTrap = TRUE; 216 break; 217 218 case 'T': 219 UseRPCTrap = FALSE; 220 break; 221 222 case 'i': 223 if (streql(argv[0], "-iheader")) { 224 --argc; ++argv; 225 if (argc == 0) 226 fatal("missing name for -iheader option"); 227 InternalHeaderFileName = strmake(argv[0]); 228 } 229 else { 230 --argc; ++argv; 231 if (argc == 0) 232 fatal("missing prefix for -i option"); 233 UserFilePrefix = strmake(argv[0]); 234 } 235 break; 236 237 case 'u': 238 if (streql(argv[0], "-user")) { 239 --argc; ++argv; 240 if (argc == 0) 241 fatal("missing name for -user option"); 242 UserFileName = strmake(argv[0]); 243 } 244 else 245 fatal("unknown flag: '%s'", argv[0]); 246 break; 247 248 case 'h': 249 if (streql(argv[0], "-header")) { 250 --argc; ++argv; 251 if (argc == 0) 252 fatal("missing name for -header option"); 253 UserHeaderFileName = strmake(argv[0]); 254 } 255 else 256 fatal("unknown flag: '%s'", argv[0]); 257 break; 258 259 case 'd': 260 if (streql(argv[0], "-dheader")) { 261 --argc; ++argv; 262 if (argc == 0) 263 fatal("missing name for -dheader option"); 264 DefinesHeaderFileName = strmake(argv[0]); 265 } 266 else 267 fatal("unknown flag: '%s'", argv[0]); 268 break; 269 270 case 'm': 271 if (streql(argv[0], "-maxonstack")) { 272 --argc; ++argv; 273 if (argc == 0) 274 fatal("missing size for -maxonstack option"); 275 MaxMessSizeOnStack = atoi(argv[0]); 276 } 277 else if (streql(argv[0], "-mach_msg2")) 278 UseMachMsg2 = TRUE; 279 else if (streql(argv[0], "-max_descrs")) { 280 --argc; ++argv; 281 if (argc == 0) 282 fatal("missing count for -max_descrs option"); 283 MaxServerDescrs = atoi(argv[0]); 284 } else if (streql(argv[0], "-max_reply_descrs")) { 285 --argc; ++argv; 286 if (argc == 0) 287 fatal("missing count for -max_reply_descrs option"); 288 MaxServerReplyDescrs = atoi(argv[0]); 289 } else 290 fatal("unknown flag: '%s'", argv[0]); 291 break; 292 293 case 'X': 294 ShortCircuit = FALSE; 295 break; 296 297 case 'x': 298 ShortCircuit = TRUE; 299 /* fall thru - no longer supported */ 300 301 default: 302 fatal("unknown/unsupported flag: '%s'", argv[0]); 303 /*NOTREACHED*/ 304 } 305 } 306 else 307 fatal("bad argument: '%s'", *argv); 308 309 if (UseMachMsg2) { 310 if (!BeAnsiC || UseRPCTrap || CheckNDR) { 311 fatal("KernelServer does not support the given uptions."); 312 } 313 } 314} 315 316FILE *uheader, *server, *user; 317 318int 319main(int argc, char *argv[]) 320{ 321 FILE *iheader = 0; 322 FILE *sheader = 0; 323 FILE *dheader = 0; 324 325 set_program_name("mig"); 326 parseArgs(argc, argv); 327 if (PrintVersion) { 328 printf("%s\n", MIG_VERSION); 329 fflush(stdout); 330 exit(0); 331 } 332 init_global(); 333 init_type(); 334 335 LookNormal(); 336 (void) yyparse(); 337 338 if (mig_errors > 0) 339 fatal("%d errors found. Abort.\n", mig_errors); 340 341 more_global(); 342 343 uheader = myfopen(UserHeaderFileName, "w"); 344 if (!UserFilePrefix) 345 user = myfopen(UserFileName, "w"); 346 server = myfopen(ServerFileName, "w"); 347 if (ServerHeaderFileName) 348 sheader = myfopen(ServerHeaderFileName, "w"); 349 if (IsKernelServer) { 350 iheader = myfopen(InternalHeaderFileName, "w"); 351 } 352 if (DefinesHeaderFileName) 353 dheader = myfopen(DefinesHeaderFileName, "w"); 354 if (BeVerbose) { 355 printf("Writing %s ... ", UserHeaderFileName); 356 fflush(stdout); 357 } 358 WriteUserHeader(uheader, stats); 359 fclose(uheader); 360 if (ServerHeaderFileName) { 361 if (BeVerbose) { 362 printf ("done.\nWriting %s ...", ServerHeaderFileName); 363 fflush (stdout); 364 } 365 WriteServerHeader(sheader, stats); 366 fclose(sheader); 367 } 368 if (IsKernelServer) { 369 if (BeVerbose) { 370 printf("done.\nWriting %s ... ", InternalHeaderFileName); 371 fflush(stdout); 372 } 373 WriteInternalHeader(iheader, stats); 374 fclose(iheader); 375 } 376 if (DefinesHeaderFileName) { 377 if (BeVerbose) { 378 printf ("done.\nWriting %s ...", DefinesHeaderFileName); 379 fflush (stdout); 380 } 381 WriteDefinesHeader(dheader, stats); 382 fclose(dheader); 383 } 384 if (UserFilePrefix) { 385 if (BeVerbose) { 386 printf("done.\nWriting individual user files ... "); 387 fflush(stdout); 388 } 389 WriteUserIndividual(stats); 390 } 391 else { 392 if (BeVerbose) { 393 printf("done.\nWriting %s ... ", UserFileName); 394 fflush(stdout); 395 } 396 WriteUser(user, stats); 397 fclose(user); 398 } 399 if (BeVerbose) { 400 printf("done.\nWriting %s ... ", ServerFileName); 401 fflush(stdout); 402 } 403 WriteServer(server, stats); 404 fclose(server); 405 if (BeVerbose) 406 printf("done.\n"); 407 408 exit(0); 409} 410 411static FILE * 412myfopen(const char *name, const char *mode) 413{ 414 const char *realname; 415 FILE *file; 416 417 if (name == strNULL) 418 realname = "/dev/null"; 419 else 420 realname = name; 421 422 file = fopen(realname, mode); 423 if (file == NULL) 424 fatal("fopen(%s): %s", realname, strerror(errno)); 425 426 return file; 427}