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