1/* 2 * Copyright (c) 1999, 2008 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 "error.h" 109#include "lexxer.h" 110#include "global.h" 111#include "write.h" 112 113extern int yyparse(); 114static FILE *myfopen(); 115 116static void 117parseArgs(int argc,char *argv[]) 118{ 119 while (--argc > 0) 120 if ((++argv)[0][0] == '-') { 121 switch (argv[0][1]) { 122 123 case 'q': 124 BeQuiet = TRUE; 125 break; 126 127 case 'Q': 128 BeQuiet = FALSE; 129 break; 130 131 case 'v': 132 BeVerbose = TRUE; 133 break; 134 135 case 'V': 136 BeVerbose = FALSE; 137 break; 138 139 case 'r': 140 UseMsgRPC = TRUE; 141 break; 142 143 case 'R': 144 UseMsgRPC = FALSE; 145 break; 146 147 case 'l': 148 UseEventLogger = FALSE; 149 break; 150 151 case 'L': 152 UseEventLogger = TRUE; 153 break; 154 155 case 'k': 156 BeAnsiC = TRUE; 157 break; 158 159 case 'K': 160 BeAnsiC = FALSE; 161 break; 162 163 case 'n': 164 if (streql(argv[0], "-novouchers")) { 165 IsVoucherCodeAllowed = FALSE; 166 } else { 167 CheckNDR = TRUE; 168 } 169 break; 170 171 case 'N': 172 CheckNDR = FALSE; 173 break; 174 175 case 's': 176 if (streql(argv[0], "-server")) { 177 --argc; ++argv; 178 if (argc == 0) 179 fatal("missing name for -server option"); 180 ServerFileName = strmake(argv[0]); 181 } 182 else if (streql(argv[0], "-sheader")) { 183 --argc; ++argv; 184 if (argc == 0) 185 fatal ("missing name for -sheader option"); 186 ServerHeaderFileName = strmake(argv[0]); 187 } 188 else if (streql(argv[0], "-split")) 189 UseSplitHeaders = TRUE; 190 else 191 GenSymTab = TRUE; 192 break; 193 194 case 'S': 195 GenSymTab = FALSE; 196 break; 197 198 case 't': 199 warn("Mach RPC traps not fully supported"); 200 TestRPCTrap = TRUE; 201 UseRPCTrap = TRUE; 202 break; 203 204 case 'T': 205 UseRPCTrap = FALSE; 206 break; 207 208 case 'i': 209 if (streql(argv[0], "-iheader")) { 210 --argc; ++argv; 211 if (argc == 0) 212 fatal("missing name for -iheader option"); 213 InternalHeaderFileName = strmake(argv[0]); 214 } 215 else { 216 --argc; ++argv; 217 if (argc == 0) 218 fatal("missing prefix for -i option"); 219 UserFilePrefix = strmake(argv[0]); 220 } 221 break; 222 223 case 'u': 224 if (streql(argv[0], "-user")) { 225 --argc; ++argv; 226 if (argc == 0) 227 fatal("missing name for -user option"); 228 UserFileName = strmake(argv[0]); 229 } 230 else 231 fatal("unknown flag: '%s'", argv[0]); 232 break; 233 234 case 'h': 235 if (streql(argv[0], "-header")) { 236 --argc; ++argv; 237 if (argc == 0) 238 fatal("missing name for -header option"); 239 UserHeaderFileName = strmake(argv[0]); 240 } 241 else 242 fatal("unknown flag: '%s'", argv[0]); 243 break; 244 245 case 'd': 246 if (streql(argv[0], "-dheader")) { 247 --argc; ++argv; 248 if (argc == 0) 249 fatal("missing name for -dheader option"); 250 DefinesHeaderFileName = strmake(argv[0]); 251 } 252 else 253 fatal("unknown flag: '%s'", argv[0]); 254 break; 255 256 case 'm': 257 if (streql(argv[0], "-maxonstack")) { 258 --argc; ++argv; 259 if (argc == 0) 260 fatal("missing size for -maxonstack option"); 261 MaxMessSizeOnStack = atoi(argv[0]); 262 } 263 else 264 fatal("unknown flag: '%s'", argv[0]); 265 break; 266 267 case 'X': 268 ShortCircuit = FALSE; 269 break; 270 271 case 'x': 272 ShortCircuit = TRUE; 273 /* fall thru - no longer supported */ 274 275 default: 276 fatal("unknown/unsupported flag: '%s'", argv[0]); 277 /*NOTREACHED*/ 278 } 279 } 280 else 281 fatal("bad argument: '%s'", *argv); 282} 283 284FILE *uheader, *server, *user; 285 286int 287main(int argc, char *argv[]) 288{ 289 FILE *iheader = 0; 290 FILE *sheader = 0; 291 FILE *dheader = 0; 292 time_t loc; 293 extern time_t time(); 294 extern string_t ctime(); 295 extern string_t GenerationDate; 296 297 set_program_name("mig"); 298 parseArgs(argc, argv); 299 init_global(); 300 init_type(); 301 loc = time((time_t *)0); 302 GenerationDate = ctime(&loc); 303 304 LookNormal(); 305 (void) yyparse(); 306 307 if (mig_errors > 0) 308 fatal("%d errors found. Abort.\n", mig_errors); 309 310 more_global(); 311 312 uheader = myfopen(UserHeaderFileName, "w"); 313 if (!UserFilePrefix) 314 user = myfopen(UserFileName, "w"); 315 server = myfopen(ServerFileName, "w"); 316 if (ServerHeaderFileName) 317 sheader = myfopen(ServerHeaderFileName, "w"); 318 if (IsKernelServer) { 319 iheader = myfopen(InternalHeaderFileName, "w"); 320 } 321 if (DefinesHeaderFileName) 322 dheader = myfopen(DefinesHeaderFileName, "w"); 323 if (BeVerbose) { 324 printf("Writing %s ... ", UserHeaderFileName); 325 fflush(stdout); 326 } 327 WriteUserHeader(uheader, stats); 328 fclose(uheader); 329 if (ServerHeaderFileName) { 330 if (BeVerbose) { 331 printf ("done.\nWriting %s ...", ServerHeaderFileName); 332 fflush (stdout); 333 } 334 WriteServerHeader(sheader, stats); 335 fclose(sheader); 336 } 337 if (IsKernelServer) { 338 if (BeVerbose) { 339 printf("done.\nWriting %s ... ", InternalHeaderFileName); 340 fflush(stdout); 341 } 342 WriteInternalHeader(iheader, stats); 343 fclose(iheader); 344 } 345 if (DefinesHeaderFileName) { 346 if (BeVerbose) { 347 printf ("done.\nWriting %s ...", DefinesHeaderFileName); 348 fflush (stdout); 349 } 350 WriteDefinesHeader(dheader, stats); 351 fclose(dheader); 352 } 353 if (UserFilePrefix) { 354 if (BeVerbose) { 355 printf("done.\nWriting individual user files ... "); 356 fflush(stdout); 357 } 358 WriteUserIndividual(stats); 359 } 360 else { 361 if (BeVerbose) { 362 printf("done.\nWriting %s ... ", UserFileName); 363 fflush(stdout); 364 } 365 WriteUser(user, stats); 366 fclose(user); 367 } 368 if (BeVerbose) { 369 printf("done.\nWriting %s ... ", ServerFileName); 370 fflush(stdout); 371 } 372 WriteServer(server, stats); 373 fclose(server); 374 if (BeVerbose) 375 printf("done.\n"); 376 377 exit(0); 378} 379 380static FILE * 381myfopen(char *name, char *mode) 382{ 383 char *realname; 384 FILE *file; 385 386 if (name == strNULL) 387 realname = "/dev/null"; 388 else 389 realname = name; 390 391 file = fopen(realname, mode); 392 if (file == NULL) 393 fatal("fopen(%s): %s", realname, strerror(errno)); 394 395 return file; 396} 397