xref: /trueos/usr.bin/migcom/header.c (revision b6e6246829d5cb1b6c2f704d82f8267a0d3a3362)
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:16:58  jsb
77  * 	Removed TrapRoutine support.
78  * 	[91/08/12            rpd]
79  *
80  * 91/06/26  14:39:37  rpd
81  * 	Removed the user initialization function and InitRoutineName.
82  * 	Fixed to use different symbolic constants to protect
83  * 	the user and server header files against multiple inclusion.
84  * 	[91/06/26            rpd]
85  *
86  * 91/06/25  10:31:21  rpd
87  * 	Restored prototype generation.
88  * 	Changed WriteHeader to WriteUserHeader.
89  * 	Added WriteServerHeader.
90  * 	[91/05/23            rpd]
91  *
92  * 91/02/05  17:54:33  mrt
93  * 	Changed to new Mach copyright
94  * 	[91/02/01  17:54:19  mrt]
95  *
96  * 90/12/20  17:04:47  jeffreyh
97  * 	Commented out code for prototype generation. This is a temporary solution
98  * 	to the longer term problem of the need
99  * 	for the generation of both a client and a server header file
100  * 	that have correct prototypes for strict ansi c and c++. The
101  * 	prototypes generated before anly were for the client and broke kernel
102  * 	files that included them if compiled under standard gcc
103  * 	[90/12/07            jeffreyh]
104  *
105  * 90/06/02  15:04:46  rpd
106  * 	Created for new IPC.
107  * 	[90/03/26  21:11:06  rpd]
108  *
109  * 07-Apr-89  Richard Draves (rpd) at Carnegie-Mellon University
110  *	Extensive revamping.  Added polymorphic arguments.
111  *	Allow multiple variable-sized inline arguments in messages.
112  *
113  *  8-Jul-88  Mary Thompson (mrt) at Carnegie-Mellon University
114  *	Conditionally defined mig_external to be extern and then defined
115  *	all functions  with the storage class mig_external.
116  *	Mig_external can be changed
117  *	when the generated code is compiled.
118  *
119  * 18-Jan-88  David Detlefs (dld) at Carnegie-Mellon University
120  *	Modified to produce C++ compatible code via #ifdefs.
121  *	All changes have to do with argument declarations.
122  *
123  *  3-Aug-87  Mary Thompson (mrt) at Carnegie-Mellon University
124  *	Revision to make multi-threaded use work. Removed definitions for
125  * 	alloc_reply_port and init_msg_type as these routines are
126  * 	no longer generated.
127  *
128  * 30-Jul-87  Mary Thompson (mrt) at Carnegie-Mellon University
129  * 	Made changes to generate conditional code for C++ parameter lists
130  *
131  * 29-Jul-87  Mary Thompson (mrt) at Carnegie-Mellon University
132  *	Changed WriteRoutine to produce conditional argument
133  *	lists for C++
134  *
135  *  8-Jun-87  Mary Thompson (mrt) at Carnegie-Mellon University
136  *	Changed the KERNEL include from ../h to sys/
137  *	Removed extern from WriteHeader to make hi-c happy
138  *
139  * 28-May-87  Richard Draves (rpd) at Carnegie-Mellon University
140  *	Created.
141  */
142 
143 #include "write.h"
144 #include "utils.h"
145 #include "global.h"
146 #include "strdefs.h"
147 #include "error.h"
148 #include <stdlib.h>
149 
150 void
WriteIncludes(FILE * file,boolean_t isuser,boolean_t isdef)151 WriteIncludes(FILE *file, boolean_t isuser, boolean_t isdef)
152 {
153 	if (isdef) {
154 		fprintf(file, "#include <mach/port.h>\n");
155 		fprintf(file, "#include <machine/mach/kern_return.h>\n");
156 		if (!isuser)
157 			fprintf(file, "#include <mach/mig_errors.h>\n");
158 	}
159 	else {
160 		fprintf(file, "#include <sys/cdefs.h>\n");
161 		fprintf(file, "#include <sys/types.h>\n");
162 		fprintf(file, "#ifdef _KERNEL\n");
163 		fprintf(file, "#include <sys/mach/ndr.h>\n");
164 		fprintf(file, "#include <sys/mach/kern_return.h>\n");
165 		fprintf(file, "#include <sys/mach/notify.h>\n");
166 		fprintf(file, "#include <sys/mach/mach_types.h>\n");
167 		fprintf(file, "#include <sys/mach/message.h>\n");
168 		fprintf(file, "#include <sys/mach/mig_errors.h>\n");
169 		fprintf(file, "#else /* !_KERNEL */\n");
170 		fprintf(file, "#include <string.h>\n");
171 		fprintf(file, "#include <mach/ndr.h>\n");
172 		fprintf(file, "#include <mach/boolean.h>\n");
173 		fprintf(file, "#include <mach/kern_return.h>\n");
174 		fprintf(file, "#include <mach/notify.h>\n");
175 		fprintf(file, "#include <mach/mach_types.h>\n");
176 		fprintf(file, "#include <mach/message.h>\n");
177 		fprintf(file, "#include <mach/mig_errors.h>\n");
178 		fprintf(file, "#endif /*_KERNEL */\n");
179 		if (ShortCircuit)
180 			fprintf(file, "#include <mach/rpc.h>\n");
181 		if (isuser && IsKernelUser) {
182 			fprintf(file, "#if\t(__MigKernelSpecificCode) || (_MIG_KERNEL_SPECIFIC_CODE_)\n");
183 			fprintf(file, "#include <kern/ipc_mig.h>\n");
184 			fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
185 		}
186 	}
187 	fprintf(file, "\n");
188 }
189 
190 static void
WriteETAPDefines(FILE * file)191 WriteETAPDefines(FILE *file)
192 {
193 	register statement_t *stat;
194 	int fnum;
195     const char *fname;
196 	int first = TRUE;
197 
198 	fprintf(file, "\n#ifndef subsystem_to_name_map_%s\n", SubsystemName);
199 	fprintf(file, "#define subsystem_to_name_map_%s \\\n", SubsystemName);
200     for (stat = defs_stats; stat != stNULL; stat = stat->stNext)
201         if (stat->stKind == skRoutine)
202 		{
203 			fnum = SubsystemBase + stat->stRoutine->rtNumber;
204 			fname = stat->stRoutine->rtName;
205 			if (! first)
206 				fprintf(file, ",\\\n");
207 			fprintf(file, "    { \"%s\", %d }", fname, fnum);
208 			first = FALSE;
209 		}
210 	fprintf(file, "\n#endif\n");
211 }
212 
213 static void
WriteProlog(FILE * file,const char * protect,boolean_t more,boolean_t isuser)214 WriteProlog(FILE *file, const char *protect, boolean_t more, boolean_t isuser)
215 {
216 	if (protect != strNULL) {
217 		fprintf(file, "#ifndef\t_%s\n", protect);
218 		fprintf(file, "#define\t_%s\n", protect);
219 		fprintf(file, "\n");
220 	}
221 
222 	fprintf(file, "/* Module %s */\n", SubsystemName);
223 	fprintf(file, "\n");
224 
225 	if (more) {
226 		WriteIncludes(file, isuser, UseSplitHeaders);
227 	}
228 	fprintf(file, "#ifdef AUTOTEST\n");
229 	fprintf(file, "#ifndef FUNCTION_PTR_T\n");
230 	fprintf(file, "#define FUNCTION_PTR_T\n");
231 	fprintf(file, "typedef void (*function_ptr_t)");
232 	fprintf(file, "(mach_port_t, char *, mach_msg_type_number_t);\n");
233 	fprintf(file, "typedef struct {\n");
234 	fprintf(file, "        char            *name;\n");
235 	fprintf(file, "        function_ptr_t  function;\n");
236 	fprintf(file, "} function_table_entry;\n");
237 	fprintf(file, "typedef function_table_entry   *function_table_t;\n");
238 	fprintf(file, "#endif /* FUNCTION_PTR_T */\n");
239 	fprintf(file, "#endif /* AUTOTEST */\n");
240 	fprintf(file, "\n#ifndef\t%s_MSG_COUNT\n", SubsystemName);
241 	fprintf(file, "#define\t%s_MSG_COUNT\t%d\n", SubsystemName, rtNumber);
242 	fprintf(file, "#endif\t/* %s_MSG_COUNT */\n\n", SubsystemName);
243 }
244 
245 static void
WriteEpilog(FILE * file,const char * protect,boolean_t isuser)246 WriteEpilog(FILE *file, const char *protect, boolean_t isuser)
247 {
248     const char *defname =
249         isuser ? "__AfterMigUserHeader" : "__AfterMigServerHeader";
250 
251 	WriteETAPDefines(file);
252     fprintf(file, "\n#ifdef %s\n%s\n#endif /* %s */\n",
253 			defname, defname, defname);
254 	if (protect != strNULL) {
255 		fprintf(file, "\n");
256 		fprintf(file, "#endif\t /* _%s */\n", protect);
257 	}
258 }
259 
260 static void
WriteUserRoutine(FILE * file,routine_t * rt)261 WriteUserRoutine(FILE *file, routine_t *rt)
262 {
263 	fprintf(file, "\n");
264 	fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
265 	WriteMigExternal(file);
266 	fprintf(file, "%s %s\n", ReturnTypeStr(rt), rt->rtUserName);
267     fprintf(file, "#if\t%s\n", LintLib);
268     fprintf(file, "    (");
269     WriteList(file, rt->rtArgs, WriteNameDecl, akbUserArg, ", " , "");
270     fprintf(file, ")\n");
271     WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ";\n", ";\n");
272     fprintf(file, "{ ");
273     fprintf(file, "return ");
274     fprintf(file, "%s(", rt->rtUserName);
275     WriteList(file, rt->rtArgs, WriteNameDecl, akbUserArg, ", ", "");
276     fprintf(file, "); }\n");
277     fprintf(file, "#else\n");
278 	if (BeAnsiC) {
279 		fprintf(file, "(\n");
280 		WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n");
281 		fprintf(file, ");\n");
282     } else {
283 		fprintf(file, "#if\t%s\n", NewCDecl);
284 		fprintf(file, "(\n");
285 		WriteList(file, rt->rtArgs, WriteUserVarDecl, akbUserArg, ",\n", "\n");
286 		fprintf(file, ");\n");
287 		fprintf(file, "#else\n");
288 
289 		fprintf(file, "    ();\n");
290 		fprintf(file, "#endif\t/* %s */\n", NewCDecl);
291 	}
292 	fprintf(file, "#endif\t/* %s */\n",  LintLib);
293 }
294 
295 void
WriteUserRequestUnion(FILE * file,statement_t * stats)296 WriteUserRequestUnion(FILE *file, statement_t *stats)
297 {
298 	register statement_t *stat;
299 
300 	fprintf(file, "/* union of all requests */\n\n");
301 	fprintf(file, "#ifndef __RequestUnion__%s%s_subsystem__defined\n", UserPrefix, SubsystemName);
302 	fprintf(file, "#define __RequestUnion__%s%s_subsystem__defined\n", UserPrefix, SubsystemName);
303 	fprintf(file, "union __RequestUnion__%s%s_subsystem {\n", UserPrefix, SubsystemName);
304 	for (stat = stats; stat != stNULL; stat = stat->stNext) {
305 		if (stat->stKind == skRoutine) {
306 			register routine_t *rt;
307 
308 			rt = stat->stRoutine;
309 			fprintf(file, "\t__Request__%s_t Request_%s;\n", rt->rtName, rt->rtUserName);
310 		}
311 	}
312 	fprintf(file, "};\n");
313 	fprintf(file, "#endif /* !__RequestUnion__%s%s_subsystem__defined */\n", UserPrefix, SubsystemName);
314 }
315 
316 void
WriteUserReplyUnion(FILE * file,statement_t * stats)317 WriteUserReplyUnion(FILE *file, statement_t *stats)
318 {
319 	register statement_t *stat;
320 
321 	fprintf(file, "/* union of all replies */\n\n");
322 	fprintf(file, "#ifndef __ReplyUnion__%s%s_subsystem__defined\n", UserPrefix, SubsystemName);
323 	fprintf(file, "#define __ReplyUnion__%s%s_subsystem__defined\n", UserPrefix, SubsystemName);
324 	fprintf(file, "union __ReplyUnion__%s%s_subsystem {\n", UserPrefix, SubsystemName);
325 	for (stat = stats; stat != stNULL; stat = stat->stNext) {
326 		if (stat->stKind == skRoutine) {
327 			register routine_t *rt;
328 
329 			rt = stat->stRoutine;
330 			fprintf(file, "\t__Reply__%s_t Reply_%s;\n", rt->rtName, rt->rtUserName);
331 		}
332 	}
333 	fprintf(file, "};\n");
334 	fprintf(file, "#endif /* !__RequestUnion__%s%s_subsystem__defined */\n", UserPrefix, SubsystemName);
335 }
336 
337 void
WriteUserHeader(FILE * file,statement_t * stats)338 WriteUserHeader(FILE *file, statement_t *stats)
339 {
340 	register statement_t *stat;
341     const char *protect = strconcat(SubsystemName, "_user_");
342 
343 	WriteProlog(file, protect, TRUE, TRUE);
344 	for (stat = stats; stat != stNULL; stat = stat->stNext)
345 		switch (stat->stKind)
346 		{
347 		case skImport:
348 		case skUImport:
349 		case skDImport:
350 			WriteImport(file, stat->stFileName);
351 			break;
352 		case skRoutine:
353 		case skSImport:
354 		case skIImport:
355 			break;
356 		default:
357 			fatal("WriteHeader(): bad statement_kind_t (%d)",
358 				  (int) stat->stKind);
359 		}
360     fprintf(file, "\n#ifdef __BeforeMigUserHeader\n");
361 	fprintf(file, "__BeforeMigUserHeader\n");
362 	fprintf(file, "#endif /* __BeforeMigUserHeader */\n");
363 	fprintf(file, "\n");
364 	fprintf(file, "#include <sys/cdefs.h>\n");
365 	fprintf(file, "__BEGIN_DECLS\n");
366 	fprintf(file, "\n");
367 	for (stat = stats; stat != stNULL; stat = stat->stNext) {
368 		if (stat->stKind == skRoutine)
369 			WriteUserRoutine(file, stat->stRoutine);
370 	}
371 	fprintf(file, "\n");
372 	fprintf(file, "__END_DECLS\n");
373 
374 	fprintf(file, "\n");
375 	fprintf(file, "/********************** Caution **************************/\n");
376 	fprintf(file, "/* The following data types should be used to calculate  */\n");
377 	fprintf(file, "/* maximum message sizes only. The actual message may be */\n");
378 	fprintf(file, "/* smaller, and the position of the arguments within the */\n");
379 	fprintf(file, "/* message layout may vary from what is presented here.  */\n");
380 	fprintf(file, "/* For example, if any of the arguments are variable-    */\n");
381 	fprintf(file, "/* sized, and less than the maximum is sent, the data    */\n");
382 	fprintf(file, "/* will be packed tight in the actual message to reduce  */\n");
383 	fprintf(file, "/* the presence of holes.                                */\n");
384 	fprintf(file, "/********************** Caution **************************/\n");
385 	fprintf(file, "\n");
386 
387 	WriteRequestTypes(file, stats);
388 	WriteUserRequestUnion(file, stats);
389 
390 	WriteReplyTypes(file, stats);
391 	WriteUserReplyUnion(file, stats);
392 
393 	WriteEpilog(file, protect, TRUE);
394 }
395 
396 static void
WriteDefinesRoutine(FILE * file,routine_t * rt)397 WriteDefinesRoutine(FILE *file, routine_t *rt)
398 {
399     char *up = (char *)malloc(strlen(rt->rtName)+1);
400 
401     up = toupperstr(strcpy(up, rt->rtName));
402     fprintf(file, "#define\tMACH_ID_%s\t\t%d\t/* %s() */\n",
403 			up, rt->rtNumber + SubsystemBase, rt->rtName);
404 	if (rt->rtKind == rkRoutine)
405 		fprintf(file, "#define\tMACH_ID_%s_REPLY\t\t%d\t/* %s() */\n",
406 				up, rt->rtNumber + SubsystemBase + 100, rt->rtName);
407 	fprintf(file, "\n");
408 }
409 
410 void
WriteServerRoutine(FILE * file,routine_t * rt)411 WriteServerRoutine(FILE *file, routine_t *rt)
412 {
413 	fprintf(file, "\n");
414 	fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
415 	WriteMigExternal(file);
416 	fprintf(file, "%s %s\n", ReturnTypeStr(rt), rt->rtServerName);
417     fprintf(file, "#if\t%s\n", LintLib);
418     fprintf(file, "    (");
419     WriteList(file, rt->rtArgs, WriteNameDecl, akbServerArg, ", " , "");
420     fprintf(file, ")\n");
421     WriteList(file, rt->rtArgs, WriteServerVarDecl,
422 			  akbServerArg, ";\n", ";\n");
423     fprintf(file, "{ ");
424     fprintf(file, "return ");
425     fprintf(file, "%s(", rt->rtServerName);
426     WriteList(file, rt->rtArgs, WriteNameDecl, akbServerArg, ", ", "");
427     fprintf(file, "); }\n");
428     fprintf(file, "#else\n");
429 	if (BeAnsiC) {
430 		fprintf(file, "(\n");
431         WriteList(file, rt->rtArgs, WriteServerVarDecl,
432 				  akbServerArg, ",\n", "\n");
433 		fprintf(file, ");\n");
434     } else {
435 		fprintf(file, "#if\t%s\n", NewCDecl);
436 		fprintf(file, "(\n");
437         WriteList(file, rt->rtArgs, WriteServerVarDecl,
438 				  akbServerArg, ",\n", "\n");
439 		fprintf(file, ");\n");
440 		fprintf(file, "#else\n");
441 
442 		fprintf(file, "    ();\n");
443 		fprintf(file, "#endif\t/* %s */\n", NewCDecl);
444 	}
445     fprintf(file, "#endif\t/* %s */\n",  LintLib);
446 }
447 
448 static void
WriteDispatcher(FILE * file)449 WriteDispatcher(FILE *file)
450 {
451 	register statement_t *stat;
452 	int descr_count = 0;
453 
454     for (stat = defs_stats; stat != stNULL; stat = stat->stNext)
455 		if (stat->stKind == skRoutine)
456 		{
457 			register routine_t *rt = stat->stRoutine;
458 			descr_count += rtCountArgDescriptors(rt->rtArgs, (int *) 0);
459 		}
460 	fprintf(file, "\n");
461 
462 	WriteMigExternal(file);
463 	fprintf(file, "boolean_t %s(\n", ServerDemux);
464 	fprintf(file, "\t\tmach_msg_header_t *InHeadP,\n");
465 	fprintf(file, "\t\tmach_msg_header_t *OutHeadP);\n\n");
466 
467 	WriteMigExternal(file);
468 	fprintf(file, "mig_routine_t %s_routine(\n", ServerDemux);
469 	fprintf(file, "\t\tmach_msg_header_t *InHeadP);\n\n");
470 
471 	fprintf(file, "\n/* Description of this subsystem, for use in direct RPC */\n");
472 	fprintf(file, "extern const struct %s {\n", ServerSubsys);
473 	if (UseRPCTrap) {
474 		fprintf(file, "\tstruct subsystem *\tsubsystem;\t/* Reserved for system use */\n");
475 	}
476 	else {
477 		fprintf(file, "\tmig_server_routine_t\tserver;\t/* Server routine */\n");
478 	}
479 	fprintf(file, "\tmach_msg_id_t\tstart;\t/* Min routine number */\n");
480 	fprintf(file, "\tmach_msg_id_t\tend;\t/* Max routine number + 1 */\n");
481 	fprintf(file, "\tunsigned int\tmaxsize;\t/* Max msg size */\n");
482 	if (UseRPCTrap) {
483 		fprintf(file, "\tvm_address_t\tbase_addr;\t/* Base address */\n");
484 		fprintf(file, "\tstruct rpc_routine_descriptor\t/*Array of routine descriptors */\n");
485 	}
486 	else {
487 		fprintf(file, "\tvm_address_t\treserved;\t/* Reserved */\n");
488 		fprintf(file, "\tstruct routine_descriptor\t/*Array of routine descriptors */\n");
489 	}
490 	fprintf(file, "\t\troutine[%d];\n", rtNumber);
491 	if (UseRPCTrap) {
492 		fprintf(file, "\tstruct rpc_routine_arg_descriptor\t/*Array of arg descriptors */\n");
493 		fprintf(file, "\t\targ_descriptor[%d];\n", descr_count);
494 	}
495 	fprintf(file, "} %s;\n", ServerSubsys);
496 	fprintf(file, "\n");
497 }
498 
499 void
WriteServerHeader(FILE * file,statement_t * stats)500 WriteServerHeader(FILE *file, statement_t *stats)
501 {
502 	register statement_t *stat;
503     const char *protect = strconcat(SubsystemName, "_server_");
504 
505 	WriteProlog(file, protect, TRUE, FALSE);
506 	for (stat = stats; stat != stNULL; stat = stat->stNext)
507 		switch (stat->stKind)
508 		{
509 		case skImport:
510 		case skSImport:
511 		case skDImport:
512 			WriteImport(file, stat->stFileName);
513 			break;
514 		case skRoutine:
515 		case skUImport:
516 		case skIImport:
517 			break;
518 		default:
519 			fatal("WriteServerHeader(): bad statement_kind_t (%d)",
520 				  (int) stat->stKind);
521 		}
522 	fprintf(file, "\n#ifdef __BeforeMigServerHeader\n");
523 	fprintf(file, "__BeforeMigServerHeader\n");
524 	fprintf(file, "#endif /* __BeforeMigServerHeader */\n\n");
525 	for (stat = stats; stat != stNULL; stat = stat->stNext) {
526 		if (stat->stKind == skRoutine)
527 			WriteServerRoutine(file, stat->stRoutine);
528 	}
529 
530 	for (stat = stats; stat != stNULL; stat = stat->stNext) {
531 		if (stat->stKind == skRoutine)
532 			WriteServerRoutine(file, stat->stRoutine);
533 	}
534 	WriteDispatcher(file);
535 
536 	WriteRequestTypes(file, stats);
537 	WriteServerRequestUnion(file, stats);
538 
539 	WriteReplyTypes(file, stats);
540 	WriteServerReplyUnion(file, stats);
541 
542 	WriteEpilog(file, protect, FALSE);
543 }
544 
545 static void
WriteInternalRedefine(FILE * file,register routine_t * rt)546 WriteInternalRedefine(FILE *file, register routine_t *rt)
547 {
548     fprintf(file, "#define %s %s_external\n",
549 			rt->rtUserName, rt->rtUserName);
550 }
551 
552 void
WriteInternalHeader(FILE * file,statement_t * stats)553 WriteInternalHeader(FILE *file, statement_t *stats)
554 {
555 	register statement_t *stat;
556 
557 	for (stat = stats; stat != stNULL; stat = stat->stNext)
558 		switch (stat->stKind)
559 		{
560 		case skRoutine:
561 			WriteInternalRedefine(file, stat->stRoutine);
562 			break;
563 		case skImport:
564 		case skUImport:
565 		case skSImport:
566 		case skDImport:
567 		case skIImport:
568 			break;
569 		default:
570 			fatal("WriteInternalHeader(): bad statement_kind_t (%d)",
571 				  (int) stat->stKind);
572 		}
573 }
574 
575 void
WriteDefinesHeader(FILE * file,statement_t * stats)576 WriteDefinesHeader(FILE *file, statement_t *stats)
577 {
578 	register statement_t *stat;
579     const char *protect = strconcat(SubsystemName, "_defines");
580 
581 	WriteProlog(file, protect, FALSE, FALSE);
582 	fprintf(file, "\n/*\tDefines related to the Subsystem %s\t*/\n\n", SubsystemName);
583 	for (stat = stats; stat != stNULL; stat = stat->stNext) {
584 		switch (stat->stKind)
585 		{
586 		case skRoutine:
587 			WriteDefinesRoutine(file, stat->stRoutine);
588 			break;
589 		case skImport:
590 		case skSImport:
591 		case skUImport:
592 			break;
593 		default:
594 			fatal("WriteDefinesHeader(): bad statement_kind_t (%d)",
595 				  (int) stat->stKind);
596 		}
597 	}
598 	WriteEpilog(file, protect, FALSE);
599 }
600