1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1997-2000 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * interceptor.c -- a functional decomposition of generate.c,
31*7c478bd9Sstevel@tonic-gate  *	the code generator for apptrace
32*7c478bd9Sstevel@tonic-gate  */
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include <stdio.h>
35*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
36*7c478bd9Sstevel@tonic-gate #include <string.h>
37*7c478bd9Sstevel@tonic-gate #include <unistd.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
39*7c478bd9Sstevel@tonic-gate #include "parser.h"
40*7c478bd9Sstevel@tonic-gate #include "trace.h"
41*7c478bd9Sstevel@tonic-gate #include "util.h"
42*7c478bd9Sstevel@tonic-gate #include "db.h"
43*7c478bd9Sstevel@tonic-gate #include "symtab.h"
44*7c478bd9Sstevel@tonic-gate #include "io.h"
45*7c478bd9Sstevel@tonic-gate #include "bindings.h"
46*7c478bd9Sstevel@tonic-gate #include "printfuncs.h"
47*7c478bd9Sstevel@tonic-gate #include "errlog.h"
48*7c478bd9Sstevel@tonic-gate #include "parseproto.h"
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate static void generate_i_declarations(char *, int, char *);
51*7c478bd9Sstevel@tonic-gate static void generate_i_preamble(ENTRY *);
52*7c478bd9Sstevel@tonic-gate static void generate_i_call();
53*7c478bd9Sstevel@tonic-gate static int  generate_i_bindings(int);
54*7c478bd9Sstevel@tonic-gate static void generate_i_postamble(ENTRY *, int, char *, char *);
55*7c478bd9Sstevel@tonic-gate static void generate_i_evaluations(ENTRY *);
56*7c478bd9Sstevel@tonic-gate static void generate_i_prints(ENTRY *, char *, char *);
57*7c478bd9Sstevel@tonic-gate static void generate_i_closedown(char *, int);
58*7c478bd9Sstevel@tonic-gate static void generate_i_live_vars(ENTRY *);
59*7c478bd9Sstevel@tonic-gate static void generate_return_printf(int);
60*7c478bd9Sstevel@tonic-gate static char *variables_get_errorname(void);
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate /*
63*7c478bd9Sstevel@tonic-gate  * generate_interceptor -- make code for an individual interceptor, written
64*7c478bd9Sstevel@tonic-gate  *	as an output grammar
65*7c478bd9Sstevel@tonic-gate  */
66*7c478bd9Sstevel@tonic-gate void
67*7c478bd9Sstevel@tonic-gate generate_interceptor(ENTRY *function)
68*7c478bd9Sstevel@tonic-gate {
69*7c478bd9Sstevel@tonic-gate 	char	*prototype = symtab_get_prototype(),
70*7c478bd9Sstevel@tonic-gate 		*library_name = db_get_current_library(),
71*7c478bd9Sstevel@tonic-gate 		*function_name,
72*7c478bd9Sstevel@tonic-gate 		*error_name;
73*7c478bd9Sstevel@tonic-gate 	int	void_func;
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_interceptor() {");
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate 	/* Check for required information. */
78*7c478bd9Sstevel@tonic-gate 	if (validity_of(function) == NO) {
79*7c478bd9Sstevel@tonic-gate 		symtab_set_skip(YES);
80*7c478bd9Sstevel@tonic-gate 		errlog(WARNING|INPUT, "No prototype for interface, "
81*7c478bd9Sstevel@tonic-gate 			"it will be skipped");
82*7c478bd9Sstevel@tonic-gate 		errlog(END, "}");
83*7c478bd9Sstevel@tonic-gate 		return;
84*7c478bd9Sstevel@tonic-gate 	}
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate 	/* Collect things we'll use more than once. */
87*7c478bd9Sstevel@tonic-gate 	function_name = name_of(function);
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate 	error_name = variables_get_errorname();
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate 	void_func = is_void(function);
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 	/*
94*7c478bd9Sstevel@tonic-gate 	 * Emit "artificial" prototype here so that if there's a
95*7c478bd9Sstevel@tonic-gate 	 * disagreement between it and the prototype contained in the
96*7c478bd9Sstevel@tonic-gate 	 * declaring header, the compiler will flag it.
97*7c478bd9Sstevel@tonic-gate 	 * First #undef the function to make sure the prototype in the header
98*7c478bd9Sstevel@tonic-gate 	 * is exposed and to avoid breaking the artificial prototype if it's
99*7c478bd9Sstevel@tonic-gate 	 * not.
100*7c478bd9Sstevel@tonic-gate 	 */
101*7c478bd9Sstevel@tonic-gate 	{
102*7c478bd9Sstevel@tonic-gate 		decl_t *dp;
103*7c478bd9Sstevel@tonic-gate 		char *buf;
104*7c478bd9Sstevel@tonic-gate 		char const *err;
105*7c478bd9Sstevel@tonic-gate 		size_t s;
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 		s = strlen(prototype) + 2;
108*7c478bd9Sstevel@tonic-gate 		buf = malloc(s);
109*7c478bd9Sstevel@tonic-gate 		if (buf == NULL)
110*7c478bd9Sstevel@tonic-gate 			abort();
111*7c478bd9Sstevel@tonic-gate 		(void) strcpy(buf, prototype);
112*7c478bd9Sstevel@tonic-gate 		buf[s - 2] = ';';
113*7c478bd9Sstevel@tonic-gate 		buf[s - 1] = '\0';
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 		err = decl_Parse(buf, &dp);
116*7c478bd9Sstevel@tonic-gate 		if (err != NULL)
117*7c478bd9Sstevel@tonic-gate 			errlog(FATAL, "\"%s\", line %d: %s: %s",
118*7c478bd9Sstevel@tonic-gate 			    symtab_get_filename(), line_of(function),
119*7c478bd9Sstevel@tonic-gate 			    err, prototype);
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 		/* generate the mapfile entry */
122*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Mapfp, "\t__abi_%s;\n", decl_GetName(dp));
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 		(void) decl_ToString(buf, DTS_DECL, dp, function_name);
125*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp, "#line %d \"%s\"\n",
126*7c478bd9Sstevel@tonic-gate 		    line_of(function), symtab_get_filename());
127*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp, "#undef %s\n", function_name);
128*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp, "extern %s;\n", buf);
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp, "static %s\n{\n", prototype);
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 		(void) decl_ToString(buf, DTS_RET, dp, "_return");
133*7c478bd9Sstevel@tonic-gate 		generate_i_declarations(error_name, void_func, buf);
134*7c478bd9Sstevel@tonic-gate 		decl_Destroy(dp);
135*7c478bd9Sstevel@tonic-gate 		free(buf);
136*7c478bd9Sstevel@tonic-gate 	}
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate 	generate_i_preamble(function);
139*7c478bd9Sstevel@tonic-gate 	generate_i_call(function, void_func, library_name, error_name);
140*7c478bd9Sstevel@tonic-gate 	generate_i_postamble(function, void_func, error_name, library_name);
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate 	errlog(END, "}");
143*7c478bd9Sstevel@tonic-gate }
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate /*
146*7c478bd9Sstevel@tonic-gate  * print_function_signature -- print the line defining the function, without
147*7c478bd9Sstevel@tonic-gate  *      an ``extern'' prefix or either a ``;'' or ''{'' suffix.
148*7c478bd9Sstevel@tonic-gate  */
149*7c478bd9Sstevel@tonic-gate void
150*7c478bd9Sstevel@tonic-gate print_function_signature(char *xtype, char *name, char *formals)
151*7c478bd9Sstevel@tonic-gate {
152*7c478bd9Sstevel@tonic-gate 	char	buffer[MAXLINE];
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	(void) snprintf(buffer, sizeof (buffer), "%s", name);
155*7c478bd9Sstevel@tonic-gate 	(void) fprintf(Bodyfp,  xtype, buffer);
156*7c478bd9Sstevel@tonic-gate 	if (strstr(xtype, "(*") == NULL) {
157*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,  "(%s)", formals);
158*7c478bd9Sstevel@tonic-gate 	}
159*7c478bd9Sstevel@tonic-gate }
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate /*
163*7c478bd9Sstevel@tonic-gate  * generate_i_declarations -- generate the declarations which
164*7c478bd9Sstevel@tonic-gate  *      are local to the interceptor function itself.
165*7c478bd9Sstevel@tonic-gate  */
166*7c478bd9Sstevel@tonic-gate static void
167*7c478bd9Sstevel@tonic-gate generate_i_declarations(char *errname, int voidfunc, char *ret_str)
168*7c478bd9Sstevel@tonic-gate {
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_i_declarations() {");
171*7c478bd9Sstevel@tonic-gate 	if (*errname != NULL) {
172*7c478bd9Sstevel@tonic-gate 		/* Create locals for errno-type variable, */
173*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,
174*7c478bd9Sstevel@tonic-gate 		    "    int saved_errvar = %s;\n", errname);
175*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,  "    int functions_errvar;\n");
176*7c478bd9Sstevel@tonic-gate 	}
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate 	if (need_exception_binding()) {
179*7c478bd9Sstevel@tonic-gate 		/* Create a local for that. */
180*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,  "    int exception = 0;\n");
181*7c478bd9Sstevel@tonic-gate 	}
182*7c478bd9Sstevel@tonic-gate 	if (! voidfunc) {
183*7c478bd9Sstevel@tonic-gate 		/* Create a return value. */
184*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,  "    %s;\n", ret_str);
185*7c478bd9Sstevel@tonic-gate 	}
186*7c478bd9Sstevel@tonic-gate 	(void) fprintf(Bodyfp, "    sigset_t omask;\n");
187*7c478bd9Sstevel@tonic-gate 	(void) putc('\n', Bodyfp);
188*7c478bd9Sstevel@tonic-gate 	errlog(END, "}");
189*7c478bd9Sstevel@tonic-gate }
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate /*
193*7c478bd9Sstevel@tonic-gate  * generate_i_preamble -- do the actions which must occur
194*7c478bd9Sstevel@tonic-gate  *      before the call.
195*7c478bd9Sstevel@tonic-gate  */
196*7c478bd9Sstevel@tonic-gate static void
197*7c478bd9Sstevel@tonic-gate generate_i_preamble(ENTRY *function)
198*7c478bd9Sstevel@tonic-gate {
199*7c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_i_preamble() {");
200*7c478bd9Sstevel@tonic-gate 	generate_i_live_vars(function); /* Deferred. */
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	if (symtab_get_nonreturn() == YES) {
203*7c478bd9Sstevel@tonic-gate 		/* Make things safe for printing */
204*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,
205*7c478bd9Sstevel@tonic-gate 		    "    abilock(&omask);\n");
206*7c478bd9Sstevel@tonic-gate 		/* Print all the args in terse format. */
207*7c478bd9Sstevel@tonic-gate 		generate_printf(function);
208*7c478bd9Sstevel@tonic-gate 		(void) fputs("    putc('\\n', ABISTREAM);\n\n", Bodyfp);
209*7c478bd9Sstevel@tonic-gate 		/* unlock stdio */
210*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,
211*7c478bd9Sstevel@tonic-gate 		    "    abiunlock(&omask);\n");
212*7c478bd9Sstevel@tonic-gate 	}
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 	errlog(END, "}");
215*7c478bd9Sstevel@tonic-gate }
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate /*
218*7c478bd9Sstevel@tonic-gate  * generate_i_call -- implement the save/call/restore cycle
219*7c478bd9Sstevel@tonic-gate  */
220*7c478bd9Sstevel@tonic-gate static void
221*7c478bd9Sstevel@tonic-gate generate_i_call(
222*7c478bd9Sstevel@tonic-gate 	ENTRY	*function,
223*7c478bd9Sstevel@tonic-gate 	int	void_func,
224*7c478bd9Sstevel@tonic-gate 	char	*library_name,
225*7c478bd9Sstevel@tonic-gate 	char	*error_name)
226*7c478bd9Sstevel@tonic-gate {
227*7c478bd9Sstevel@tonic-gate 	char	*function_name = name_of(function),
228*7c478bd9Sstevel@tonic-gate 		*function_cast = symtab_get_cast(),
229*7c478bd9Sstevel@tonic-gate 		*actual_args = symtab_get_actuals();
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_i_call() {");
232*7c478bd9Sstevel@tonic-gate 	/* Zero the error variable. */
233*7c478bd9Sstevel@tonic-gate 	if (*error_name != NULL) {
234*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,  "    %s = 0;\n", error_name);
235*7c478bd9Sstevel@tonic-gate 	}
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 	/* Then print the call itself. */
238*7c478bd9Sstevel@tonic-gate 	if (void_func) {
239*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,
240*7c478bd9Sstevel@tonic-gate 		    "    (void) ABI_CALL_REAL(%s, %s, %s)(%s);\n",
241*7c478bd9Sstevel@tonic-gate 		    library_name, function_name, function_cast, actual_args);
242*7c478bd9Sstevel@tonic-gate 	} else {
243*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,
244*7c478bd9Sstevel@tonic-gate 		    "    _return = ABI_CALL_REAL(%s, %s, %s)(%s);\n",
245*7c478bd9Sstevel@tonic-gate 		    library_name, function_name, function_cast, actual_args);
246*7c478bd9Sstevel@tonic-gate 	}
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 	/* Then set the local copy of the error variable. */
249*7c478bd9Sstevel@tonic-gate 	if (*error_name != NULL) {
250*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,
251*7c478bd9Sstevel@tonic-gate 		    "    functions_errvar = %s;\n", error_name);
252*7c478bd9Sstevel@tonic-gate 	}
253*7c478bd9Sstevel@tonic-gate 	(void) putc('\n', Bodyfp);
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate 	/* Make things safe for printing */
256*7c478bd9Sstevel@tonic-gate 	(void) fprintf(Bodyfp,
257*7c478bd9Sstevel@tonic-gate 	    "    abilock(&omask);\n");
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate 	errlog(END, "}");
260*7c478bd9Sstevel@tonic-gate }
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate /*
263*7c478bd9Sstevel@tonic-gate  * generate_i_postamble -- do all the things which come
264*7c478bd9Sstevel@tonic-gate  *      after the call.  In the case of apptrace, this is most of the work.
265*7c478bd9Sstevel@tonic-gate  */
266*7c478bd9Sstevel@tonic-gate static void
267*7c478bd9Sstevel@tonic-gate generate_i_postamble(ENTRY *function, int void_func,
268*7c478bd9Sstevel@tonic-gate     char *error_name, char *library_name)
269*7c478bd9Sstevel@tonic-gate {
270*7c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_i_postamble() {");
271*7c478bd9Sstevel@tonic-gate 	if (symtab_get_nonreturn() == NO) {
272*7c478bd9Sstevel@tonic-gate 		/* Print all the args in terse format. */
273*7c478bd9Sstevel@tonic-gate 		generate_printf(function);
274*7c478bd9Sstevel@tonic-gate 	}
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate 	/* If it isn't supposed to return, and actually ends up here, */
277*7c478bd9Sstevel@tonic-gate 	/* we'd better be prepared to print all sorts of diagnostic stuff */
278*7c478bd9Sstevel@tonic-gate 	(void) putc('\n', Bodyfp);
279*7c478bd9Sstevel@tonic-gate 	if (generate_i_bindings(void_func) == YES) {
280*7c478bd9Sstevel@tonic-gate 		generate_return_printf(void_func);
281*7c478bd9Sstevel@tonic-gate 	}
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 	generate_i_prints(function, library_name, name_of(function));
284*7c478bd9Sstevel@tonic-gate 	generate_i_evaluations(function); /* Deferred */
285*7c478bd9Sstevel@tonic-gate 	generate_i_closedown(error_name, void_func);
286*7c478bd9Sstevel@tonic-gate 	errlog(END, "}");
287*7c478bd9Sstevel@tonic-gate }
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate /*
290*7c478bd9Sstevel@tonic-gate  * generate_i_bindings -- see about success and failure, so we can decide
291*7c478bd9Sstevel@tonic-gate  *      what to do next.
292*7c478bd9Sstevel@tonic-gate  */
293*7c478bd9Sstevel@tonic-gate static int
294*7c478bd9Sstevel@tonic-gate generate_i_bindings(int void_func)
295*7c478bd9Sstevel@tonic-gate {
296*7c478bd9Sstevel@tonic-gate 	ENTRY   *e;
297*7c478bd9Sstevel@tonic-gate 	char *exception;
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 	exception  = ((e = symtab_get_exception()) != NULL)?
300*7c478bd9Sstevel@tonic-gate 	    (name_of(e)? name_of(e): ""): "";
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_i_bindings() {");
303*7c478bd9Sstevel@tonic-gate 	if (void_func && bindings_exist()) {
304*7c478bd9Sstevel@tonic-gate 		/* To become a warning, as there are spec errors! TBD */
305*7c478bd9Sstevel@tonic-gate 		errlog(FATAL, "exception bindings found in a "
306*7c478bd9Sstevel@tonic-gate 			"void function");
307*7c478bd9Sstevel@tonic-gate 	} else if (void_func || need_bindings(exception) == NO) {
308*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,
309*7c478bd9Sstevel@tonic-gate 		    "    (void) putc('\\n', ABISTREAM);\n");
310*7c478bd9Sstevel@tonic-gate 		(void) putc('\n', Bodyfp);
311*7c478bd9Sstevel@tonic-gate 		errlog(END, "}");
312*7c478bd9Sstevel@tonic-gate 		return (NO);
313*7c478bd9Sstevel@tonic-gate 	} else {
314*7c478bd9Sstevel@tonic-gate 		/*
315*7c478bd9Sstevel@tonic-gate 		 * Then there is a return value, so we try to
316*7c478bd9Sstevel@tonic-gate 		 * generate exception bindings
317*7c478bd9Sstevel@tonic-gate 		 * and code to print errno on exception.
318*7c478bd9Sstevel@tonic-gate 		 */
319*7c478bd9Sstevel@tonic-gate 		if ((generate_bindings(exception)) != ANTONYMS) {
320*7c478bd9Sstevel@tonic-gate 			/* Generate code to cross-evaluate them. */
321*7c478bd9Sstevel@tonic-gate 			(void) fprintf(Bodyfp,
322*7c478bd9Sstevel@tonic-gate 			    "    if (!exception) {\n");
323*7c478bd9Sstevel@tonic-gate 			errlog(END, "}");
324*7c478bd9Sstevel@tonic-gate 			return (YES);
325*7c478bd9Sstevel@tonic-gate 		}
326*7c478bd9Sstevel@tonic-gate 	}
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate 	/* should not get here */
329*7c478bd9Sstevel@tonic-gate 	errlog(END, "}");
330*7c478bd9Sstevel@tonic-gate 	return (NO);
331*7c478bd9Sstevel@tonic-gate }
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate /*
334*7c478bd9Sstevel@tonic-gate  * generate_return_printf -- print the return value and end the line
335*7c478bd9Sstevel@tonic-gate  */
336*7c478bd9Sstevel@tonic-gate static void
337*7c478bd9Sstevel@tonic-gate generate_return_printf(int void_func)
338*7c478bd9Sstevel@tonic-gate {
339*7c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_return_printf() {");
340*7c478bd9Sstevel@tonic-gate 	if (void_func) {
341*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,  "    putc('\\n', ABISTREAM);\n");
342*7c478bd9Sstevel@tonic-gate 		errlog(END, "}");
343*7c478bd9Sstevel@tonic-gate 		return;
344*7c478bd9Sstevel@tonic-gate 	}
345*7c478bd9Sstevel@tonic-gate 	/* If its a non-void function there are bindings. */
346*7c478bd9Sstevel@tonic-gate 	(void) fprintf(Bodyfp,
347*7c478bd9Sstevel@tonic-gate 	    "\t/* Just end the line */\n"
348*7c478bd9Sstevel@tonic-gate 	    "\tputc('\\n', ABISTREAM);\n"
349*7c478bd9Sstevel@tonic-gate 	    "    }\n"
350*7c478bd9Sstevel@tonic-gate 	    "    else {\n"
351*7c478bd9Sstevel@tonic-gate 	    "        fprintf(ABISTREAM, \"%%s%%d (%%s)\\n\", errnostr, "
352*7c478bd9Sstevel@tonic-gate 	    "functions_errvar, strerror((int)functions_errvar));\n"
353*7c478bd9Sstevel@tonic-gate 	    "    }\n\n");
354*7c478bd9Sstevel@tonic-gate 	errlog(END, "}");
355*7c478bd9Sstevel@tonic-gate }
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate /*
358*7c478bd9Sstevel@tonic-gate  * generate_i_prints -- if we're doing the verbose stuff,
359*7c478bd9Sstevel@tonic-gate  *      generate verbose printouts of the variables.
360*7c478bd9Sstevel@tonic-gate  */
361*7c478bd9Sstevel@tonic-gate static void
362*7c478bd9Sstevel@tonic-gate generate_i_prints(ENTRY *function, char *lib, char *func)
363*7c478bd9Sstevel@tonic-gate {
364*7c478bd9Sstevel@tonic-gate 	ENTRY   *e;
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_i_prints() {");
367*7c478bd9Sstevel@tonic-gate 	if ((e = symtab_get_first_arg()) != NULL || !is_void(e)) {
368*7c478bd9Sstevel@tonic-gate 		/* Then we have to generate code for verbose reports. */
369*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,  "    if (ABI_VFLAG(%s, %s) != 0) {\n",
370*7c478bd9Sstevel@tonic-gate 			lib, func);
371*7c478bd9Sstevel@tonic-gate 		generate_printfunc_calls(function);
372*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,  "    }\n");
373*7c478bd9Sstevel@tonic-gate 	}
374*7c478bd9Sstevel@tonic-gate 	(void) putc('\n', Bodyfp);
375*7c478bd9Sstevel@tonic-gate 	errlog(END, "}");
376*7c478bd9Sstevel@tonic-gate }
377*7c478bd9Sstevel@tonic-gate 
378*7c478bd9Sstevel@tonic-gate /*
379*7c478bd9Sstevel@tonic-gate  * generate_i_closedown -- restore error variables and return.
380*7c478bd9Sstevel@tonic-gate  */
381*7c478bd9Sstevel@tonic-gate static void
382*7c478bd9Sstevel@tonic-gate generate_i_closedown(char *error_name, int void_func)
383*7c478bd9Sstevel@tonic-gate {
384*7c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_i_closedown() {");
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 	/* unlock stdio */
387*7c478bd9Sstevel@tonic-gate 	(void) fprintf(Bodyfp,
388*7c478bd9Sstevel@tonic-gate 	    "    abiunlock(&omask);\n");
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	if (*error_name != NULL) {
391*7c478bd9Sstevel@tonic-gate 		/* Restore error variables. */
392*7c478bd9Sstevel@tonic-gate 		(void) fprintf(Bodyfp,
393*7c478bd9Sstevel@tonic-gate 		    "    %s = (functions_errvar == 0)? "
394*7c478bd9Sstevel@tonic-gate 		    "            saved_errvar: functions_errvar;\n",
395*7c478bd9Sstevel@tonic-gate 		    error_name);
396*7c478bd9Sstevel@tonic-gate 	}
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 	/* And return. */
399*7c478bd9Sstevel@tonic-gate 	(void) fprintf(Bodyfp,
400*7c478bd9Sstevel@tonic-gate 	    "    return%s;\n",
401*7c478bd9Sstevel@tonic-gate 	    (void_func)? "": " _return");
402*7c478bd9Sstevel@tonic-gate 	(void) fprintf(Bodyfp,  "}\n");
403*7c478bd9Sstevel@tonic-gate 	(void) putc('\n', Bodyfp);
404*7c478bd9Sstevel@tonic-gate 	errlog(END, "}");
405*7c478bd9Sstevel@tonic-gate }
406*7c478bd9Sstevel@tonic-gate 
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate /*
409*7c478bd9Sstevel@tonic-gate  * generate_i_live_vars -- generate temps for any ``out''
410*7c478bd9Sstevel@tonic-gate  *	or ``inout'' variables in the function.  Deferred.
411*7c478bd9Sstevel@tonic-gate  */
412*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
413*7c478bd9Sstevel@tonic-gate static void
414*7c478bd9Sstevel@tonic-gate generate_i_live_vars(ENTRY *function)
415*7c478bd9Sstevel@tonic-gate {
416*7c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_i_live_vars() {");
417*7c478bd9Sstevel@tonic-gate 	errlog(END, "}");
418*7c478bd9Sstevel@tonic-gate }
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate /*
421*7c478bd9Sstevel@tonic-gate  * generate_i_evaluations -- generate evaluations for
422*7c478bd9Sstevel@tonic-gate  *	all the expressions. Deferred.
423*7c478bd9Sstevel@tonic-gate  */
424*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
425*7c478bd9Sstevel@tonic-gate static void
426*7c478bd9Sstevel@tonic-gate generate_i_evaluations(ENTRY *function)
427*7c478bd9Sstevel@tonic-gate {
428*7c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_i_evaluations() {");
429*7c478bd9Sstevel@tonic-gate 	errlog(END, "}");
430*7c478bd9Sstevel@tonic-gate }
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate static char *
434*7c478bd9Sstevel@tonic-gate variables_get_errorname(void)
435*7c478bd9Sstevel@tonic-gate {
436*7c478bd9Sstevel@tonic-gate 	return ("ABI_ERRNO");
437*7c478bd9Sstevel@tonic-gate }
438