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 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 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 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 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 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 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 * 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