xref: /NextBSD/usr.bin/migcom/mig.c (revision 33da5adc555b3bc29986eeadca03829e4ad06b1e)
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