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