xref: /onnv-gate/usr/src/cmd/abi/spectrans/spec2trace/printfuncs.c (revision 2775:892d346f56a9)
1*2775Sraf /*
2*2775Sraf  * CDDL HEADER START
3*2775Sraf  *
4*2775Sraf  * The contents of this file are subject to the terms of the
5*2775Sraf  * Common Development and Distribution License, Version 1.0 only
6*2775Sraf  * (the "License").  You may not use this file except in compliance
7*2775Sraf  * with the License.
8*2775Sraf  *
9*2775Sraf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*2775Sraf  * or http://www.opensolaris.org/os/licensing.
11*2775Sraf  * See the License for the specific language governing permissions
12*2775Sraf  * and limitations under the License.
13*2775Sraf  *
14*2775Sraf  * When distributing Covered Code, include this CDDL HEADER in each
15*2775Sraf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*2775Sraf  * If applicable, add the following below this CDDL HEADER, with the
17*2775Sraf  * fields enclosed by brackets "[]" replaced with your own identifying
18*2775Sraf  * information: Portions Copyright [yyyy] [name of copyright owner]
19*2775Sraf  *
20*2775Sraf  * CDDL HEADER END
21*2775Sraf  */
22*2775Sraf /*
23*2775Sraf  * Copyright (c) 1997-1999 by Sun Microsystems, Inc.
24*2775Sraf  * All rights reserved.
25*2775Sraf  */
26*2775Sraf 
27*2775Sraf #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*2775Sraf 
29*2775Sraf #include <stdlib.h>
30*2775Sraf #include <stdio.h>
31*2775Sraf #include <string.h>
32*2775Sraf #include <limits.h>
33*2775Sraf #include "parser.h"
34*2775Sraf #include "trace.h"
35*2775Sraf #include "util.h"
36*2775Sraf #include "db.h"
37*2775Sraf #include "symtab.h"
38*2775Sraf #include "io.h"
39*2775Sraf #include "printfuncs.h"
40*2775Sraf #include "errlog.h"
41*2775Sraf 
42*2775Sraf static int	 prepare_printf_part(ENTRY *, char *, char *, int);
43*2775Sraf static char	 *space_to_uscore(char const *);
44*2775Sraf 
45*2775Sraf static char	arglist[_POSIX_ARG_MAX];
46*2775Sraf 
47*2775Sraf /*
48*2775Sraf  * generate_printf -- make the cleanest possible printf for the
49*2775Sraf  *	parameters, in a relatively terse apptrace/dbx-like format,
50*2775Sraf  *	ending in ") = ", or ) if its a void function we're doing.
51*2775Sraf  */
52*2775Sraf void
generate_printf(ENTRY * f)53*2775Sraf generate_printf(ENTRY *f)
54*2775Sraf {
55*2775Sraf 	ENTRY	*e;
56*2775Sraf 	char	*p, *name;
57*2775Sraf 	int	l, n;
58*2775Sraf 
59*2775Sraf 	errlog(BEGIN, "generate_printf");
60*2775Sraf 	(void) fprintf(Bodyfp, "    fprintf(ABISTREAM, \"");
61*2775Sraf 	p = &arglist[0];
62*2775Sraf 	l = (int)sizeof (arglist);
63*2775Sraf 	*p = NULL;
64*2775Sraf 	for (e = symtab_get_first_arg(); e != NULL; e = symtab_get_next_arg()) {
65*2775Sraf 		errlog(TRACING, "arglist = '%s'", arglist);
66*2775Sraf 
67*2775Sraf 		if (is_void(e)) {
68*2775Sraf 			/* This placeholder means there are no real args. */
69*2775Sraf 			break;
70*2775Sraf 		}
71*2775Sraf 		/* Insert punctuation. */
72*2775Sraf 		if (p != &arglist[0]) {
73*2775Sraf 			(void) fprintf(Bodyfp, ", ");
74*2775Sraf 		}
75*2775Sraf 		if (*(name =  name_of(e)) == NULL) {
76*2775Sraf 			/* It's a varargs indicator instead */
77*2775Sraf 			(void) fprintf(Bodyfp, "...");
78*2775Sraf 		} else {
79*2775Sraf 			(void) fprintf(Bodyfp, "%s = ", name);
80*2775Sraf 			n = prepare_printf_part(e, name, p, l);
81*2775Sraf 			l -= n;
82*2775Sraf 			p += n;
83*2775Sraf 			*(p+1) = NULL;
84*2775Sraf 		}
85*2775Sraf 	}
86*2775Sraf 
87*2775Sraf 	if (is_void(f) || symtab_get_nonreturn() == YES) {
88*2775Sraf 		/* It is a function returning void, or a function */
89*2775Sraf 		/* which doesn't return. Close off args. */
90*2775Sraf 		(void) fprintf(Bodyfp, ")\"");
91*2775Sraf 	} else {
92*2775Sraf 		/* Make some more printf for the return type. */
93*2775Sraf 		(void) fprintf(Bodyfp, ") = ");
94*2775Sraf 		(void) prepare_printf_part(f, "_return", p, l);
95*2775Sraf 		(void) fprintf(Bodyfp, "\"");
96*2775Sraf 
97*2775Sraf 	}
98*2775Sraf 	(void) fprintf(Bodyfp, "%s);\n", arglist);
99*2775Sraf 	errlog(END, "}");
100*2775Sraf }
101*2775Sraf 
102*2775Sraf 
103*2775Sraf /*
104*2775Sraf  * prepare_printf_part -- do one element of a printf/argument string,
105*2775Sraf  *	for printing non-verbose parameter lists
106*2775Sraf  */
107*2775Sraf static int
prepare_printf_part(ENTRY * e,char * name,char * place,int size)108*2775Sraf prepare_printf_part(ENTRY *e, char *name, char *place, int size)
109*2775Sraf {
110*2775Sraf 	char	*bt;
111*2775Sraf 	int	li;
112*2775Sraf 
113*2775Sraf 	errlog(BEGIN, "prepare_printf_part() {");
114*2775Sraf 	errlog(TRACING, "name = '%s'", name);
115*2775Sraf 
116*2775Sraf 	bt = basetype_of(e);
117*2775Sraf 	li = levels_of(e);
118*2775Sraf 
119*2775Sraf 	if (li == 1 && (strcmp(bt, "char") == 0)) {
120*2775Sraf 		/* It's a string, print the beginning of it. */
121*2775Sraf 		(void) fputs("\\\"%.*s\\\"", Bodyfp);
122*2775Sraf 		size = snprintf(place, size,
123*2775Sraf 		    /*CSTYLED*/
124*2775Sraf 		    ",\n\tabi_strpsz, (%s) ? %s : nilstr",
125*2775Sraf 		    name, name);
126*2775Sraf 	} else {
127*2775Sraf 		/* Just print a hex value */
128*2775Sraf 		(void) fprintf(Bodyfp, "%s", "0x%p");
129*2775Sraf 		size = snprintf(place, size, ", \n\t%s", name);
130*2775Sraf 	}
131*2775Sraf 
132*2775Sraf 	errlog(TRACING, "place='%s'\n", place);
133*2775Sraf 	errlog(END, "}");
134*2775Sraf 	return (size);
135*2775Sraf 
136*2775Sraf }
137*2775Sraf 
138*2775Sraf 
139*2775Sraf /*
140*2775Sraf  * generate_printfunc_calls -- generate print commands for primitive types
141*2775Sraf  *	and calls to print functions for composite types, cleanly.
142*2775Sraf  *	Needs to know about base types of primitives, difference
143*2775Sraf  *	between primitives and composite types: TBD.
144*2775Sraf  */
145*2775Sraf void
generate_printfunc_calls(ENTRY * f)146*2775Sraf generate_printfunc_calls(ENTRY *f)
147*2775Sraf {
148*2775Sraf 	ENTRY	*e;
149*2775Sraf 	char	*name;
150*2775Sraf 	char	*pf_str_name;
151*2775Sraf 	int	li;
152*2775Sraf 	char	*format;
153*2775Sraf 
154*2775Sraf 	errlog(BEGIN, "generate_printfunc_calls() {");
155*2775Sraf 	for (e = symtab_get_first_arg(); e != NULL; e = symtab_get_next_arg()) {
156*2775Sraf 		if (is_void(e)) {
157*2775Sraf 			break;
158*2775Sraf 		}
159*2775Sraf 		if (*(name = name_of(e)) == NULL) {
160*2775Sraf 			(void) fprintf(Bodyfp, "        fputs(\"  ...\\n\", "
161*2775Sraf 				"ABISTREAM);\n");
162*2775Sraf 		}
163*2775Sraf 		errlog(TRACING, "name = '%s'\n", name);
164*2775Sraf 		(void) fprintf(Bodyfp,
165*2775Sraf 		    "        fprintf(ABISTREAM, \"  %s = \");\n",
166*2775Sraf 		    name);
167*2775Sraf 
168*2775Sraf 		pf_str_name = space_to_uscore(basetype_of(e));
169*2775Sraf 
170*2775Sraf 		/*
171*2775Sraf 		 * If we're dealing with a scalar (non-pointer) then
172*2775Sraf 		 * we need to call the printer with a &
173*2775Sraf 		 */
174*2775Sraf 		li = levels_of(e);
175*2775Sraf 		if (li)
176*2775Sraf 			format = "\tspf_prtype(ABISTREAM, pf_%s_str, %d, "
177*2775Sraf 			    "(void const *)%s);\n";
178*2775Sraf 		else
179*2775Sraf 			format = "\tspf_prtype(ABISTREAM, pf_%s_str, %d, "
180*2775Sraf 			    "(void const *)&%s);\n";
181*2775Sraf 
182*2775Sraf 		(void) fprintf(Bodyfp, format, pf_str_name, li, name);
183*2775Sraf 
184*2775Sraf 		free(pf_str_name);
185*2775Sraf 	}
186*2775Sraf 
187*2775Sraf 	if (is_void(f)) {
188*2775Sraf 		/*EMPTY*/;
189*2775Sraf 	} else {
190*2775Sraf 		pf_str_name = space_to_uscore(basetype_of(f));
191*2775Sraf 
192*2775Sraf 		li = levels_of(f);
193*2775Sraf 		if (li)
194*2775Sraf 			format = "\tspf_prtype(ABISTREAM, pf_%s_str, %d, "
195*2775Sraf 			    "(void const *)_return);\n";
196*2775Sraf 		else
197*2775Sraf 			format = "\tspf_prtype(ABISTREAM, pf_%s_str, %d, "
198*2775Sraf 			    "(void const *)&_return);\n";
199*2775Sraf 
200*2775Sraf 		(void) fputs("        fputs(retstr, ABISTREAM);\n", Bodyfp);
201*2775Sraf 		(void) fprintf(Bodyfp, format, pf_str_name, li);
202*2775Sraf 
203*2775Sraf 		free(pf_str_name);
204*2775Sraf 	}
205*2775Sraf 
206*2775Sraf 	errlog(END, "}");
207*2775Sraf }
208*2775Sraf 
209*2775Sraf 
210*2775Sraf /*
211*2775Sraf  * Print Function Pointers -- definition, declaration and initialization.
212*2775Sraf  *	Use is above...
213*2775Sraf  */
214*2775Sraf 
215*2775Sraf /*
216*2775Sraf  * generate_print_definitions -- generate variable definitions and
217*2775Sraf  *	initialize them to NULL.
218*2775Sraf  *      These will be set non-null by a lazy evaluation in the
219*2775Sraf  *	main.c file if and only if the print function will be used.
220*2775Sraf  *	All print functions which can be called must be defined.
221*2775Sraf  */
222*2775Sraf void
generate_print_definitions(FILE * fp)223*2775Sraf generate_print_definitions(FILE *fp)
224*2775Sraf {
225*2775Sraf 	char	*print_type,
226*2775Sraf 		*c_type,
227*2775Sraf 		*pf_str_name;
228*2775Sraf 
229*2775Sraf 	errlog(BEGIN, "generate_print_definitions() {");
230*2775Sraf 	for (print_type = db_get_first_print_type();
231*2775Sraf 		print_type != NULL;
232*2775Sraf 			print_type = db_get_next_print_type()) {
233*2775Sraf 		c_type = strchr(print_type, ','); /* Safe by construction. */
234*2775Sraf 		*c_type++ = NULL;
235*2775Sraf 		errlog(TRACING,  "print_type=%s\n", print_type);
236*2775Sraf 
237*2775Sraf 		pf_str_name = space_to_uscore(print_type);
238*2775Sraf 
239*2775Sraf 		(void) fprintf(fp,
240*2775Sraf 		    "char const *pf_%s_str = \"%s\";\n",
241*2775Sraf 		    pf_str_name, print_type);
242*2775Sraf 
243*2775Sraf 		free(pf_str_name);
244*2775Sraf 
245*2775Sraf 		*--c_type = ',';
246*2775Sraf 	}
247*2775Sraf 
248*2775Sraf 	errlog(END, "}");
249*2775Sraf }
250*2775Sraf 
251*2775Sraf /*
252*2775Sraf  * generate_print_declarations -- generate variable declarations
253*2775Sraf  *	for the strings that'll be used as arguments to the type
254*2775Sraf  *	printing function.
255*2775Sraf  */
256*2775Sraf void
generate_print_declarations(FILE * fp)257*2775Sraf generate_print_declarations(FILE *fp)
258*2775Sraf {
259*2775Sraf 	char	*print_type,
260*2775Sraf 		*c_type,
261*2775Sraf 		*pf_str_name;
262*2775Sraf 
263*2775Sraf 	errlog(BEGIN, "generate_print_declarations() {");
264*2775Sraf 	for (print_type = symtab_get_first_print_type();
265*2775Sraf 	    print_type != NULL;
266*2775Sraf 	    print_type = symtab_get_next_print_type()) {
267*2775Sraf 
268*2775Sraf 		errlog(TRACING,  "print_type, c_type=%s\n", print_type);
269*2775Sraf 
270*2775Sraf 		c_type = strchr(print_type, ','); /* Safe by construction. */
271*2775Sraf 		*c_type++ = NULL;
272*2775Sraf 
273*2775Sraf 		pf_str_name = space_to_uscore(print_type);
274*2775Sraf 
275*2775Sraf 		(void) fprintf(fp, "extern char const *pf_%s_str;\n",
276*2775Sraf 		    pf_str_name);
277*2775Sraf 
278*2775Sraf 		free(pf_str_name);
279*2775Sraf 
280*2775Sraf 		*--c_type = ',';
281*2775Sraf 	}
282*2775Sraf 
283*2775Sraf 	errlog(END, "}");
284*2775Sraf }
285*2775Sraf 
286*2775Sraf /*
287*2775Sraf  * is_void -- see if a type is void.
288*2775Sraf  */
289*2775Sraf int
is_void(ENTRY * e)290*2775Sraf is_void(ENTRY *e)
291*2775Sraf {
292*2775Sraf 	if ((e != NULL) &&
293*2775Sraf 	    levels_of(e) == 0 && (strcmp(basetype_of(e), "void") == 0))
294*2775Sraf 		return (1);
295*2775Sraf 	else
296*2775Sraf 		return (0);
297*2775Sraf }
298*2775Sraf 
299*2775Sraf static char *
space_to_uscore(char const * str)300*2775Sraf space_to_uscore(char const *str)
301*2775Sraf {
302*2775Sraf 	char *strp, *p;
303*2775Sraf 
304*2775Sraf 	strp = strdup(str);
305*2775Sraf 
306*2775Sraf 	assert(strp != NULL, "strdup failed");
307*2775Sraf 
308*2775Sraf 	for (p = strp; *p != '\0'; p++)
309*2775Sraf 		if (*p == ' ')
310*2775Sraf 			*p = '_';
311*2775Sraf 
312*2775Sraf 	return (strp);
313*2775Sraf }
314