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