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
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 the
73 * rights to redistribute these changes.
74 */
75 /*
76 * 91/08/28 11:17:04 jsb
77 * Removed TrapRoutine support.
78 * [91/08/12 rpd]
79 *
80 * 91/06/25 10:31:32 rpd
81 * Added ServerHeaderFileName and -sheader.
82 * [91/05/22 rpd]
83 *
84 * 91/02/05 17:55:02 mrt
85 * Changed to new Mach copyright
86 * [91/02/01 17:54:42 mrt]
87 *
88 * 90/06/19 23:01:01 rpd
89 * Added prefix argument to -i option.
90 * Replaced GenIndividualUser with UserFilePrefix.
91 * [90/06/03 rpd]
92 *
93 * 90/06/02 15:04:59 rpd
94 * Created for new IPC.
95 * [90/03/26 21:11:47 rpd]
96 *
97 * 07-Apr-89 Richard Draves (rpd) at Carnegie-Mellon University
98 * Extensive revamping. Added polymorphic arguments.
99 * Allow multiple variable-sized inline arguments in messages.
100 *
101 * 8-Feb-89 David Golub (dbg) at Carnegie-Mellon University
102 * Added -user, -server, and -header switches to name output files.
103 * Added -i switch to write individual files for user routines.
104 *
105 * 17-Aug-87 Bennet Yee (bsy) at Carnegie-Mellon University
106 * Added -s,-S switches for generating a SymTab
107 *
108 * 3-Aug-87 Mary Thompson (mrt) at Carnegie-Mellon University
109 * Removed -t,-T switch as code is now the same for
110 * multi and single threaded use.
111 *
112 * 28-May-87 Richard Draves (rpd) at Carnegie-Mellon University
113 * Created.
114 */
115
116 /*
117 * Switches are;
118 * -[v,Q] verbose or not quiet: prints out type
119 * and routine information as mig runs.
120 * -[V,q] not verbose or quiet : don't print
121 * information during compilation
122 * (this is the default)
123 * -[r,R] do or don't use rpc calls instead of
124 * send/receive pairs. Default is -r.
125 * -[s,S] generate symbol table or not: generate a
126 * table of rpc-name, number, routine triplets
127 * as an external data structure -- main use is
128 * for protection system's specification of rights
129 * and for protection dispatch code. Default is -s.
130 * -[l,L] -L generate code that insert code for logging
131 * the most important events that happen at the
132 * stub level (message conception, target routine
133 * calls). Default is -l.
134 * -[k,K] -K enforces MIG to generate K&R C language, with the
135 * addition of ANSI C syntax under #ifdef __STDC__.
136 * Default is -k.
137 * -[n,N] -n enforces NDR checking and conversion logic generation.
138 * Default is -N (no checking).
139 * -i <prefix>
140 * Put each user routine in its own file. The
141 * file is named <prefix><routine-name>.c.
142 * -user <name>
143 * Name the user-side file <name>
144 * -server <name>
145 * Name the server-side file <name>
146 * -header <name>
147 * Name the user-side header file <name>
148 * -iheader <name>
149 * Name the user-side internal header file <name>
150 * -sheader <name>
151 * Name the server-side header file <name>
152 * -dheader <name>
153 * Name the defines (msgh_ids) header file <name>
154 *
155 * DESIGN:
156 * Mig uses a lexxer module created by lex from lexxer.l and
157 * a parser module created by yacc from parser.y to parse an
158 * interface definitions module for a mach server.
159 * The parser module calls routines in statement.c
160 * and routines.c to build a list of statement structures.
161 * The most interesting statements are the routine definitions
162 * which contain information about the name, type, characteristics
163 * of the routine, an argument list containing information for
164 * each argument type, and a list of special arguments. The
165 * argument type structures are build by routines in type.c
166 * Once parsing is completed, the three code generation modules:
167 * header.c user.c and server.c are called sequentially. These
168 * do some code generation directly and also call the routines
169 * in utils.c for common (parameterized) code generation.
170 *
171 */
172
173 #include <stdio.h>
174 #include <stdlib.h>
175 #include "error.h"
176 #include "lexxer.h"
177 #include "global.h"
178 #include "write.h"
179
180 extern int yyparse();
181 static FILE *myfopen();
182
183 static void
parseArgs(int argc,char * argv[])184 parseArgs(int argc,char *argv[])
185 {
186 while (--argc > 0)
187 if ((++argv)[0][0] == '-')
188 {
189 switch (argv[0][1])
190 {
191 case 'q':
192 BeQuiet = TRUE;
193 break;
194 case 'Q':
195 BeQuiet = FALSE;
196 break;
197 case 'v':
198 BeVerbose = TRUE;
199 break;
200 case 'V':
201 BeVerbose = FALSE;
202 break;
203 case 'r':
204 UseMsgRPC = TRUE;
205 break;
206 case 'R':
207 UseMsgRPC = FALSE;
208 break;
209 case 'l':
210 UseEventLogger = FALSE;
211 break;
212 case 'L':
213 UseEventLogger = TRUE;
214 break;
215 case 'k':
216 BeAnsiC = TRUE;
217 break;
218 case 'K':
219 BeAnsiC = FALSE;
220 break;
221
222 case 'n':
223 if (streql(argv[0], "-novouchers")) {
224 IsVoucherCodeAllowed = FALSE;
225 } else {
226 CheckNDR = TRUE;
227 }
228 break;
229
230 case 'N':
231 CheckNDR = FALSE;
232 break;
233
234 case 's':
235 if (streql(argv[0], "-server"))
236 {
237 --argc; ++argv;
238 if (argc == 0)
239 fatal("missing name for -server option");
240 ServerFileName = strmake(argv[0]);
241 }
242 else if (streql(argv[0], "-sheader"))
243 {
244 --argc; ++argv;
245 if (argc == 0)
246 fatal ("missing name for -sheader option");
247 ServerHeaderFileName = strmake(argv[0]);
248 }
249 else if (streql(argv[0], "-split"))
250 UseSplitHeaders = TRUE;
251 else
252 GenSymTab = TRUE;
253 break;
254 case 'S':
255 GenSymTab = FALSE;
256 break;
257 case 't':
258 TestRPCTrap = TRUE;
259 UseRPCTrap = TRUE;
260 break;
261 case 'T':
262 UseRPCTrap = FALSE;
263 break;
264 case 'i':
265 if (streql(argv[0], "-iheader"))
266 {
267 --argc; ++argv;
268 if (argc == 0)
269 fatal("missing name for -iheader option");
270 InternalHeaderFileName = strmake(argv[0]);
271 }
272 else
273 {
274 --argc; ++argv;
275 if (argc == 0)
276 fatal("missing prefix for -i option");
277 UserFilePrefix = strmake(argv[0]);
278 }
279 break;
280 case 'u':
281 if (streql(argv[0], "-user"))
282 {
283 --argc; ++argv;
284 if (argc == 0)
285 fatal("missing name for -user option");
286 UserFileName = strmake(argv[0]);
287 }
288 else
289 fatal("unknown flag: '%s'", argv[0]);
290 break;
291 case 'h':
292 if (streql(argv[0], "-header"))
293 {
294 --argc; ++argv;
295 if (argc == 0)
296 fatal("missing name for -header option");
297 UserHeaderFileName = strmake(argv[0]);
298 }
299 else
300 fatal("unknown flag: '%s'", argv[0]);
301 break;
302 case 'd':
303 if (streql(argv[0], "-dheader"))
304 {
305 --argc; ++argv;
306 if (argc == 0)
307 fatal("missing name for -dheader option");
308 DefinesHeaderFileName = strmake(argv[0]);
309 }
310 else
311 fatal("unknown flag: '%s'", argv[0]);
312 break;
313 case 'm':
314 if (streql(argv[0], "-maxonstack"))
315 {
316 --argc; ++argv;
317 if (argc == 0)
318 fatal("missing size for -maxonstack option");
319 MaxMessSizeOnStack = atoi(argv[0]);
320 }
321 else
322 fatal("unknown flag: '%s'", argv[0]);
323 break;
324 case 'x':
325 ShortCircuit = TRUE;
326 break;
327 case 'X':
328 ShortCircuit = FALSE;
329 break;
330 default:
331 fatal("unknown flag: '%s'", argv[0]);
332 /*NOTREACHED*/
333 }
334 }
335 else
336 fatal("bad argument: '%s'", *argv);
337 }
338
339 static FILE *uheader, *server, *user;
340
341 int
main(int argc,char * argv[])342 main(int argc, char *argv[])
343 {
344 FILE *iheader, *sheader, *dheader;
345 time_t loc;
346 extern time_t time();
347 extern string_t ctime();
348 extern string_t GenerationDate;
349
350 set_program_name("mig");
351 parseArgs(argc, argv);
352 init_global();
353 init_type();
354 loc = time((time_t *)0);
355
356 GenerationDate = ctime(&loc);
357
358 LookNormal();
359 (void) yyparse();
360
361 if (errors > 0)
362 fatal("%d errors found. Abort.\n", errors);
363
364 more_global();
365
366 uheader = myfopen(UserHeaderFileName, "w");
367 if (!UserFilePrefix)
368 user = myfopen(UserFileName, "w");
369 server = myfopen(ServerFileName, "w");
370 if (ServerHeaderFileName)
371 sheader = myfopen(ServerHeaderFileName, "w");
372 if (IsKernelServer)
373 {
374 iheader = myfopen(InternalHeaderFileName, "w");
375 }
376 if (DefinesHeaderFileName)
377 dheader = myfopen(DefinesHeaderFileName, "w");
378 if (BeVerbose)
379 {
380 printf("Writing %s ... ", UserHeaderFileName);
381 fflush(stdout);
382 }
383 WriteUserHeader(uheader, defs_stats);
384 fclose(uheader);
385 if (ServerHeaderFileName)
386 {
387 if (BeVerbose)
388 {
389 printf ("done.\nWriting %s ...", ServerHeaderFileName);
390 fflush (stdout);
391 }
392 WriteServerHeader(sheader, defs_stats);
393 fclose(sheader);
394 }
395 if (IsKernelServer)
396 {
397 if (BeVerbose)
398 {
399 printf("done.\nWriting %s ... ", InternalHeaderFileName);
400 fflush(stdout);
401 }
402 WriteInternalHeader(iheader, defs_stats);
403 fclose(iheader);
404 }
405 if (DefinesHeaderFileName)
406 {
407 if (BeVerbose)
408 {
409 printf ("done.\nWriting %s ...", DefinesHeaderFileName);
410 fflush (stdout);
411 }
412 WriteDefinesHeader(dheader, defs_stats);
413 fclose(dheader);
414 }
415 if (UserFilePrefix)
416 {
417 if (BeVerbose)
418 {
419 printf("done.\nWriting individual user files ... ");
420 fflush(stdout);
421 }
422 WriteUserIndividual(defs_stats);
423 }
424 else
425 {
426 if (BeVerbose)
427 {
428 printf("done.\nWriting %s ... ", UserFileName);
429 fflush(stdout);
430 }
431 WriteUser(user, defs_stats);
432 fclose(user);
433 }
434 if (BeVerbose)
435 {
436 printf("done.\nWriting %s ... ", ServerFileName);
437 fflush(stdout);
438 }
439 WriteServer(server, defs_stats);
440 fclose(server);
441 if (BeVerbose)
442 printf("done.\n");
443
444 return (0);
445 }
446
447 static FILE *
myfopen(char * name,char * mode)448 myfopen(char *name, char *mode)
449 {
450 const char *realname;
451 FILE *file;
452
453 if (name == strNULL)
454 realname = "/dev/null";
455 else
456 realname = name;
457
458 file = fopen(realname, mode);
459 if (file == NULL)
460 fatal("fopen(%s): %s", realname, strerror(errno));
461 return file;
462 }
463