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