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