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