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