1753d2d2eSraf /*
2753d2d2eSraf  * CDDL HEADER START
3753d2d2eSraf  *
4753d2d2eSraf  * The contents of this file are subject to the terms of the
5753d2d2eSraf  * Common Development and Distribution License, Version 1.0 only
6753d2d2eSraf  * (the "License").  You may not use this file except in compliance
7753d2d2eSraf  * with the License.
8753d2d2eSraf  *
9753d2d2eSraf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10753d2d2eSraf  * or http://www.opensolaris.org/os/licensing.
11753d2d2eSraf  * See the License for the specific language governing permissions
12753d2d2eSraf  * and limitations under the License.
13753d2d2eSraf  *
14753d2d2eSraf  * When distributing Covered Code, include this CDDL HEADER in each
15753d2d2eSraf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16753d2d2eSraf  * If applicable, add the following below this CDDL HEADER, with the
17753d2d2eSraf  * fields enclosed by brackets "[]" replaced with your own identifying
18753d2d2eSraf  * information: Portions Copyright [yyyy] [name of copyright owner]
19753d2d2eSraf  *
20753d2d2eSraf  * CDDL HEADER END
21753d2d2eSraf  */
22753d2d2eSraf /*
23753d2d2eSraf  * Copyright (c) 1997-1999 by Sun Microsystems, Inc.
24753d2d2eSraf  * All rights reserved.
25753d2d2eSraf  */
26753d2d2eSraf 
27753d2d2eSraf #include <stdlib.h>
28753d2d2eSraf #include <stdio.h>
29753d2d2eSraf #include <string.h>
30753d2d2eSraf #include <limits.h>
31753d2d2eSraf #include "parser.h"
32753d2d2eSraf #include "trace.h"
33753d2d2eSraf #include "util.h"
34753d2d2eSraf #include "db.h"
35753d2d2eSraf #include "symtab.h"
36753d2d2eSraf #include "io.h"
37753d2d2eSraf #include "printfuncs.h"
38753d2d2eSraf #include "errlog.h"
39753d2d2eSraf 
40753d2d2eSraf static int	 prepare_printf_part(ENTRY *, char *, char *, int);
41753d2d2eSraf static char	 *space_to_uscore(char const *);
42753d2d2eSraf 
43753d2d2eSraf static char	arglist[_POSIX_ARG_MAX];
44753d2d2eSraf 
45753d2d2eSraf /*
46753d2d2eSraf  * generate_printf -- make the cleanest possible printf for the
47753d2d2eSraf  *	parameters, in a relatively terse apptrace/dbx-like format,
48753d2d2eSraf  *	ending in ") = ", or ) if its a void function we're doing.
49753d2d2eSraf  */
50753d2d2eSraf void
generate_printf(ENTRY * f)51753d2d2eSraf generate_printf(ENTRY *f)
52753d2d2eSraf {
53753d2d2eSraf 	ENTRY	*e;
54753d2d2eSraf 	char	*p, *name;
55753d2d2eSraf 	int	l, n;
56753d2d2eSraf 
57753d2d2eSraf 	errlog(BEGIN, "generate_printf");
58753d2d2eSraf 	(void) fprintf(Bodyfp, "    fprintf(ABISTREAM, \"");
59753d2d2eSraf 	p = &arglist[0];
60753d2d2eSraf 	l = (int)sizeof (arglist);
61*07c94cbfSToomas Soome 	*p = '\0';
62753d2d2eSraf 	for (e = symtab_get_first_arg(); e != NULL; e = symtab_get_next_arg()) {
63753d2d2eSraf 		errlog(TRACING, "arglist = '%s'", arglist);
64753d2d2eSraf 
65753d2d2eSraf 		if (is_void(e)) {
66753d2d2eSraf 			/* This placeholder means there are no real args. */
67753d2d2eSraf 			break;
68753d2d2eSraf 		}
69753d2d2eSraf 		/* Insert punctuation. */
70753d2d2eSraf 		if (p != &arglist[0]) {
71753d2d2eSraf 			(void) fprintf(Bodyfp, ", ");
72753d2d2eSraf 		}
73*07c94cbfSToomas Soome 		if (*(name =  name_of(e)) == '\0') {
74753d2d2eSraf 			/* It's a varargs indicator instead */
75753d2d2eSraf 			(void) fprintf(Bodyfp, "...");
76753d2d2eSraf 		} else {
77753d2d2eSraf 			(void) fprintf(Bodyfp, "%s = ", name);
78753d2d2eSraf 			n = prepare_printf_part(e, name, p, l);
79753d2d2eSraf 			l -= n;
80753d2d2eSraf 			p += n;
81*07c94cbfSToomas Soome 			*(p+1) = '\0';
82753d2d2eSraf 		}
83753d2d2eSraf 	}
84753d2d2eSraf 
85753d2d2eSraf 	if (is_void(f) || symtab_get_nonreturn() == YES) {
86753d2d2eSraf 		/* It is a function returning void, or a function */
87753d2d2eSraf 		/* which doesn't return. Close off args. */
88753d2d2eSraf 		(void) fprintf(Bodyfp, ")\"");
89753d2d2eSraf 	} else {
90753d2d2eSraf 		/* Make some more printf for the return type. */
91753d2d2eSraf 		(void) fprintf(Bodyfp, ") = ");
92753d2d2eSraf 		(void) prepare_printf_part(f, "_return", p, l);
93753d2d2eSraf 		(void) fprintf(Bodyfp, "\"");
94753d2d2eSraf 
95753d2d2eSraf 	}
96753d2d2eSraf 	(void) fprintf(Bodyfp, "%s);\n", arglist);
97753d2d2eSraf 	errlog(END, "}");
98753d2d2eSraf }
99753d2d2eSraf 
100753d2d2eSraf 
101753d2d2eSraf /*
102753d2d2eSraf  * prepare_printf_part -- do one element of a printf/argument string,
103753d2d2eSraf  *	for printing non-verbose parameter lists
104753d2d2eSraf  */
105753d2d2eSraf static int
prepare_printf_part(ENTRY * e,char * name,char * place,int size)106753d2d2eSraf prepare_printf_part(ENTRY *e, char *name, char *place, int size)
107753d2d2eSraf {
108753d2d2eSraf 	char	*bt;
109753d2d2eSraf 	int	li;
110753d2d2eSraf 
111753d2d2eSraf 	errlog(BEGIN, "prepare_printf_part() {");
112753d2d2eSraf 	errlog(TRACING, "name = '%s'", name);
113753d2d2eSraf 
114753d2d2eSraf 	bt = basetype_of(e);
115753d2d2eSraf 	li = levels_of(e);
116753d2d2eSraf 
117753d2d2eSraf 	if (li == 1 && (strcmp(bt, "char") == 0)) {
118753d2d2eSraf 		/* It's a string, print the beginning of it. */
119753d2d2eSraf 		(void) fputs("\\\"%.*s\\\"", Bodyfp);
120753d2d2eSraf 		size = snprintf(place, size,
121753d2d2eSraf 		    /*CSTYLED*/
122753d2d2eSraf 		    ",\n\tabi_strpsz, (%s) ? %s : nilstr",
123753d2d2eSraf 		    name, name);
124753d2d2eSraf 	} else {
125753d2d2eSraf 		/* Just print a hex value */
126753d2d2eSraf 		(void) fprintf(Bodyfp, "%s", "0x%p");
127753d2d2eSraf 		size = snprintf(place, size, ", \n\t%s", name);
128753d2d2eSraf 	}
129753d2d2eSraf 
130753d2d2eSraf 	errlog(TRACING, "place='%s'\n", place);
131753d2d2eSraf 	errlog(END, "}");
132753d2d2eSraf 	return (size);
133753d2d2eSraf 
134753d2d2eSraf }
135753d2d2eSraf 
136753d2d2eSraf 
137753d2d2eSraf /*
138753d2d2eSraf  * generate_printfunc_calls -- generate print commands for primitive types
139753d2d2eSraf  *	and calls to print functions for composite types, cleanly.
140753d2d2eSraf  *	Needs to know about base types of primitives, difference
141753d2d2eSraf  *	between primitives and composite types: TBD.
142753d2d2eSraf  */
143753d2d2eSraf void
generate_printfunc_calls(ENTRY * f)144753d2d2eSraf generate_printfunc_calls(ENTRY *f)
145753d2d2eSraf {
146753d2d2eSraf 	ENTRY	*e;
147753d2d2eSraf 	char	*name;
148753d2d2eSraf 	char	*pf_str_name;
149753d2d2eSraf 	int	li;
150753d2d2eSraf 	char	*format;
151753d2d2eSraf 
152753d2d2eSraf 	errlog(BEGIN, "generate_printfunc_calls() {");
153753d2d2eSraf 	for (e = symtab_get_first_arg(); e != NULL; e = symtab_get_next_arg()) {
154753d2d2eSraf 		if (is_void(e)) {
155753d2d2eSraf 			break;
156753d2d2eSraf 		}
157*07c94cbfSToomas Soome 		if (*(name = name_of(e)) == '\0') {
158753d2d2eSraf 			(void) fprintf(Bodyfp, "        fputs(\"  ...\\n\", "
159753d2d2eSraf 				"ABISTREAM);\n");
160753d2d2eSraf 		}
161753d2d2eSraf 		errlog(TRACING, "name = '%s'\n", name);
162753d2d2eSraf 		(void) fprintf(Bodyfp,
163753d2d2eSraf 		    "        fprintf(ABISTREAM, \"  %s = \");\n",
164753d2d2eSraf 		    name);
165753d2d2eSraf 
166753d2d2eSraf 		pf_str_name = space_to_uscore(basetype_of(e));
167753d2d2eSraf 
168753d2d2eSraf 		/*
169753d2d2eSraf 		 * If we're dealing with a scalar (non-pointer) then
170753d2d2eSraf 		 * we need to call the printer with a &
171753d2d2eSraf 		 */
172753d2d2eSraf 		li = levels_of(e);
173753d2d2eSraf 		if (li)
174753d2d2eSraf 			format = "\tspf_prtype(ABISTREAM, pf_%s_str, %d, "
175753d2d2eSraf 			    "(void const *)%s);\n";
176753d2d2eSraf 		else
177753d2d2eSraf 			format = "\tspf_prtype(ABISTREAM, pf_%s_str, %d, "
178753d2d2eSraf 			    "(void const *)&%s);\n";
179753d2d2eSraf 
180753d2d2eSraf 		(void) fprintf(Bodyfp, format, pf_str_name, li, name);
181753d2d2eSraf 
182753d2d2eSraf 		free(pf_str_name);
183753d2d2eSraf 	}
184753d2d2eSraf 
185753d2d2eSraf 	if (is_void(f)) {
186753d2d2eSraf 		/*EMPTY*/;
187753d2d2eSraf 	} else {
188753d2d2eSraf 		pf_str_name = space_to_uscore(basetype_of(f));
189753d2d2eSraf 
190753d2d2eSraf 		li = levels_of(f);
191753d2d2eSraf 		if (li)
192753d2d2eSraf 			format = "\tspf_prtype(ABISTREAM, pf_%s_str, %d, "
193753d2d2eSraf 			    "(void const *)_return);\n";
194753d2d2eSraf 		else
195753d2d2eSraf 			format = "\tspf_prtype(ABISTREAM, pf_%s_str, %d, "
196753d2d2eSraf 			    "(void const *)&_return);\n";
197753d2d2eSraf 
198753d2d2eSraf 		(void) fputs("        fputs(retstr, ABISTREAM);\n", Bodyfp);
199753d2d2eSraf 		(void) fprintf(Bodyfp, format, pf_str_name, li);
200753d2d2eSraf 
201753d2d2eSraf 		free(pf_str_name);
202753d2d2eSraf 	}
203753d2d2eSraf 
204753d2d2eSraf 	errlog(END, "}");
205753d2d2eSraf }
206753d2d2eSraf 
207753d2d2eSraf 
208753d2d2eSraf /*
209753d2d2eSraf  * Print Function Pointers -- definition, declaration and initialization.
210753d2d2eSraf  *	Use is above...
211753d2d2eSraf  */
212753d2d2eSraf 
213753d2d2eSraf /*
214753d2d2eSraf  * generate_print_definitions -- generate variable definitions and
215753d2d2eSraf  *	initialize them to NULL.
216753d2d2eSraf  *      These will be set non-null by a lazy evaluation in the
217753d2d2eSraf  *	main.c file if and only if the print function will be used.
218753d2d2eSraf  *	All print functions which can be called must be defined.
219753d2d2eSraf  */
220753d2d2eSraf void
generate_print_definitions(FILE * fp)221753d2d2eSraf generate_print_definitions(FILE *fp)
222753d2d2eSraf {
223753d2d2eSraf 	char	*print_type,
224753d2d2eSraf 		*c_type,
225753d2d2eSraf 		*pf_str_name;
226753d2d2eSraf 
227753d2d2eSraf 	errlog(BEGIN, "generate_print_definitions() {");
228753d2d2eSraf 	for (print_type = db_get_first_print_type();
229753d2d2eSraf 		print_type != NULL;
230753d2d2eSraf 			print_type = db_get_next_print_type()) {
231753d2d2eSraf 		c_type = strchr(print_type, ','); /* Safe by construction. */
232*07c94cbfSToomas Soome 		*c_type++ = '\0';
233753d2d2eSraf 		errlog(TRACING,  "print_type=%s\n", print_type);
234753d2d2eSraf 
235753d2d2eSraf 		pf_str_name = space_to_uscore(print_type);
236753d2d2eSraf 
237753d2d2eSraf 		(void) fprintf(fp,
238753d2d2eSraf 		    "char const *pf_%s_str = \"%s\";\n",
239753d2d2eSraf 		    pf_str_name, print_type);
240753d2d2eSraf 
241753d2d2eSraf 		free(pf_str_name);
242753d2d2eSraf 
243753d2d2eSraf 		*--c_type = ',';
244753d2d2eSraf 	}
245753d2d2eSraf 
246753d2d2eSraf 	errlog(END, "}");
247753d2d2eSraf }
248753d2d2eSraf 
249753d2d2eSraf /*
250753d2d2eSraf  * generate_print_declarations -- generate variable declarations
251753d2d2eSraf  *	for the strings that'll be used as arguments to the type
252753d2d2eSraf  *	printing function.
253753d2d2eSraf  */
254753d2d2eSraf void
generate_print_declarations(FILE * fp)255753d2d2eSraf generate_print_declarations(FILE *fp)
256753d2d2eSraf {
257753d2d2eSraf 	char	*print_type,
258753d2d2eSraf 		*c_type,
259753d2d2eSraf 		*pf_str_name;
260753d2d2eSraf 
261753d2d2eSraf 	errlog(BEGIN, "generate_print_declarations() {");
262753d2d2eSraf 	for (print_type = symtab_get_first_print_type();
263753d2d2eSraf 	    print_type != NULL;
264753d2d2eSraf 	    print_type = symtab_get_next_print_type()) {
265753d2d2eSraf 
266753d2d2eSraf 		errlog(TRACING,  "print_type, c_type=%s\n", print_type);
267753d2d2eSraf 
268753d2d2eSraf 		c_type = strchr(print_type, ','); /* Safe by construction. */
269*07c94cbfSToomas Soome 		*c_type++ = '\0';
270753d2d2eSraf 
271753d2d2eSraf 		pf_str_name = space_to_uscore(print_type);
272753d2d2eSraf 
273753d2d2eSraf 		(void) fprintf(fp, "extern char const *pf_%s_str;\n",
274753d2d2eSraf 		    pf_str_name);
275753d2d2eSraf 
276753d2d2eSraf 		free(pf_str_name);
277753d2d2eSraf 
278753d2d2eSraf 		*--c_type = ',';
279753d2d2eSraf 	}
280753d2d2eSraf 
281753d2d2eSraf 	errlog(END, "}");
282753d2d2eSraf }
283753d2d2eSraf 
284753d2d2eSraf /*
285753d2d2eSraf  * is_void -- see if a type is void.
286753d2d2eSraf  */
287753d2d2eSraf int
is_void(ENTRY * e)288753d2d2eSraf is_void(ENTRY *e)
289753d2d2eSraf {
290753d2d2eSraf 	if ((e != NULL) &&
291753d2d2eSraf 	    levels_of(e) == 0 && (strcmp(basetype_of(e), "void") == 0))
292753d2d2eSraf 		return (1);
293753d2d2eSraf 	else
294753d2d2eSraf 		return (0);
295753d2d2eSraf }
296753d2d2eSraf 
297753d2d2eSraf static char *
space_to_uscore(char const * str)298753d2d2eSraf space_to_uscore(char const *str)
299753d2d2eSraf {
300753d2d2eSraf 	char *strp, *p;
301753d2d2eSraf 
302753d2d2eSraf 	strp = strdup(str);
303753d2d2eSraf 
304753d2d2eSraf 	assert(strp != NULL, "strdup failed");
305753d2d2eSraf 
306753d2d2eSraf 	for (p = strp; *p != '\0'; p++)
307753d2d2eSraf 		if (*p == ' ')
308753d2d2eSraf 			*p = '_';
309753d2d2eSraf 
310753d2d2eSraf 	return (strp);
311753d2d2eSraf }
312