1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1997-2001 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * 31*7c478bd9Sstevel@tonic-gate * trace.c -- a simple translator from spec source to c source for 32*7c478bd9Sstevel@tonic-gate * a apptrace interposer library. This file implements the 33*7c478bd9Sstevel@tonic-gate * (interface to) the front end. Other files implement the middle 34*7c478bd9Sstevel@tonic-gate * and databases, and generate.c implements the back end. 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate */ 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate #include <stdio.h> 39*7c478bd9Sstevel@tonic-gate #include <errno.h> 40*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 42*7c478bd9Sstevel@tonic-gate #include <time.h> 43*7c478bd9Sstevel@tonic-gate #include <string.h> 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate #include "parser.h" 46*7c478bd9Sstevel@tonic-gate #include "trace.h" 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate #include "util.h" 49*7c478bd9Sstevel@tonic-gate #include "db.h" 50*7c478bd9Sstevel@tonic-gate #include "symtab.h" 51*7c478bd9Sstevel@tonic-gate #include "io.h" 52*7c478bd9Sstevel@tonic-gate #include "printfuncs.h" 53*7c478bd9Sstevel@tonic-gate #include "errlog.h" 54*7c478bd9Sstevel@tonic-gate #include "parseproto.h" 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate static int Verbose; 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* File globals. This would be better as a class. */ 59*7c478bd9Sstevel@tonic-gate /* The first four (commented out) of these enums are defined in parser.h */ 60*7c478bd9Sstevel@tonic-gate enum { 61*7c478bd9Sstevel@tonic-gate /* XLATOR_KW_NOTFOUND = 0, */ 62*7c478bd9Sstevel@tonic-gate /* XLATOR_KW_FUNC, */ 63*7c478bd9Sstevel@tonic-gate /* XLATOR_KW_DATA */ 64*7c478bd9Sstevel@tonic-gate /* XLATOR_KW_END */ 65*7c478bd9Sstevel@tonic-gate XLATOR_KW_EXCP = 4, 66*7c478bd9Sstevel@tonic-gate XLATOR_KW_DECL, 67*7c478bd9Sstevel@tonic-gate XLATOR_KW_INCL, 68*7c478bd9Sstevel@tonic-gate XLATOR_KW_ERRNO, 69*7c478bd9Sstevel@tonic-gate XLATOR_KW_ERRVAL, 70*7c478bd9Sstevel@tonic-gate XLATOR_KW_ARCH, 71*7c478bd9Sstevel@tonic-gate XLATOR_KW_WEAK 72*7c478bd9Sstevel@tonic-gate }; 73*7c478bd9Sstevel@tonic-gate #define FIRST_TOKEN 4 /* Must match the first token in the above enum */ 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate static xlator_keyword_t Keywords[] = { 76*7c478bd9Sstevel@tonic-gate { "exception", XLATOR_KW_EXCP }, 77*7c478bd9Sstevel@tonic-gate { "declaration", XLATOR_KW_DECL }, 78*7c478bd9Sstevel@tonic-gate { "include", XLATOR_KW_INCL }, 79*7c478bd9Sstevel@tonic-gate { "errno", XLATOR_KW_ERRNO }, 80*7c478bd9Sstevel@tonic-gate { "errval", XLATOR_KW_ERRVAL}, 81*7c478bd9Sstevel@tonic-gate { "arch", XLATOR_KW_ARCH}, 82*7c478bd9Sstevel@tonic-gate { "weak", XLATOR_KW_WEAK}, 83*7c478bd9Sstevel@tonic-gate { "weakfor", XLATOR_KW_WEAK}, 84*7c478bd9Sstevel@tonic-gate { "alias", XLATOR_KW_WEAK}, 85*7c478bd9Sstevel@tonic-gate { NULL, XLATOR_KW_NOTFOUND } 86*7c478bd9Sstevel@tonic-gate }; 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate static struct stats_t { 89*7c478bd9Sstevel@tonic-gate int libraries, 90*7c478bd9Sstevel@tonic-gate files, 91*7c478bd9Sstevel@tonic-gate interfaces, 92*7c478bd9Sstevel@tonic-gate lines; 93*7c478bd9Sstevel@tonic-gate int errors, 94*7c478bd9Sstevel@tonic-gate warnings, 95*7c478bd9Sstevel@tonic-gate skips; 96*7c478bd9Sstevel@tonic-gate time_t start, 97*7c478bd9Sstevel@tonic-gate end; 98*7c478bd9Sstevel@tonic-gate } Statistics; 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate #define LINE (m.mi_line_number-(m.mi_nlines-1)) 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate static void stats_init(void); 103*7c478bd9Sstevel@tonic-gate static void stats_report(void); 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate static int collect_binding(int const, char *, int); 106*7c478bd9Sstevel@tonic-gate static int collect_prototype(char *, int, int); 107*7c478bd9Sstevel@tonic-gate static int collect_include(char *, int); 108*7c478bd9Sstevel@tonic-gate static int collect_errval(char *, int); 109*7c478bd9Sstevel@tonic-gate static int collect_arch(char *); 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate static void generate_includes(void); 112*7c478bd9Sstevel@tonic-gate static void generate_init(void); 113*7c478bd9Sstevel@tonic-gate static void generate_interface(void); 114*7c478bd9Sstevel@tonic-gate static void generate_closedown(void); 115*7c478bd9Sstevel@tonic-gate static int generate_aux_file(); 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate /* Local (static) parsing functions. */ 118*7c478bd9Sstevel@tonic-gate static char *to_actual(); 119*7c478bd9Sstevel@tonic-gate static int to_basetype(char *); 120*7c478bd9Sstevel@tonic-gate static char *de_const(char *); 121*7c478bd9Sstevel@tonic-gate static char *strpqcpy(char *, char *, char *); 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate /* 124*7c478bd9Sstevel@tonic-gate * xlator_init -- initialize translator, called at startup-time 125*7c478bd9Sstevel@tonic-gate * with a struct translator_info of information the translator 126*7c478bd9Sstevel@tonic-gate * might need, returning a list of ``interesting'' spec keywords 127*7c478bd9Sstevel@tonic-gate * for the front end to select and pass to the back end translator. 128*7c478bd9Sstevel@tonic-gate * 129*7c478bd9Sstevel@tonic-gate */ 130*7c478bd9Sstevel@tonic-gate xlator_keyword_t * 131*7c478bd9Sstevel@tonic-gate xlator_init(const Translator_info *t_info) 132*7c478bd9Sstevel@tonic-gate { 133*7c478bd9Sstevel@tonic-gate int i; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "xlator_init() {"); 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate /* Save interesting parameters. */ 138*7c478bd9Sstevel@tonic-gate stats_init(); 139*7c478bd9Sstevel@tonic-gate db_set_source_directory("."); 140*7c478bd9Sstevel@tonic-gate db_set_target_directory("."); 141*7c478bd9Sstevel@tonic-gate Verbose = t_info->ti_verbosity; 142*7c478bd9Sstevel@tonic-gate seterrseverity(Verbose); /* Ditto. */ 143*7c478bd9Sstevel@tonic-gate db_set_output_file(t_info->ti_output_file); 144*7c478bd9Sstevel@tonic-gate db_set_arch(t_info->ti_arch); 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate /* Display passed argument and return value. */ 147*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, "Keywords[] = {"); 148*7c478bd9Sstevel@tonic-gate for (i = 0; Keywords[i].key != NULL; i++) { 149*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, " \"%s\", ", Keywords[i].key); 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, " (char *) NULL"); 152*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, "};"); 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 155*7c478bd9Sstevel@tonic-gate return (Keywords); 156*7c478bd9Sstevel@tonic-gate } 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate /* 159*7c478bd9Sstevel@tonic-gate * xlator_startlib -- called on starting a new library, so back end 160*7c478bd9Sstevel@tonic-gate * translator can decide to change output file/directory if desired. 161*7c478bd9Sstevel@tonic-gate */ 162*7c478bd9Sstevel@tonic-gate int 163*7c478bd9Sstevel@tonic-gate xlator_startlib(char const *libname) 164*7c478bd9Sstevel@tonic-gate { 165*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "xlator_startlib() "); 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate Statistics.libraries++; 168*7c478bd9Sstevel@tonic-gate db_set_current_library(libname); 169*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, "now in library \"%s\"", libname); 170*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 171*7c478bd9Sstevel@tonic-gate return (SUCCESS_RC); 172*7c478bd9Sstevel@tonic-gate } 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate /* 175*7c478bd9Sstevel@tonic-gate * xlator_startfile -- ditto, called on starting each new spec file in the 176*7c478bd9Sstevel@tonic-gate * specified library. 177*7c478bd9Sstevel@tonic-gate */ 178*7c478bd9Sstevel@tonic-gate int 179*7c478bd9Sstevel@tonic-gate xlator_startfile(char const *filename) 180*7c478bd9Sstevel@tonic-gate { 181*7c478bd9Sstevel@tonic-gate int rc = SUCCESS_RC; 182*7c478bd9Sstevel@tonic-gate char infile[MAXLINE], 183*7c478bd9Sstevel@tonic-gate outfile[MAXLINE], 184*7c478bd9Sstevel@tonic-gate *lib = db_get_current_library(); 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate seterrline(0, filename, "", ""); 187*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "xlator_startfile() {"); 188*7c478bd9Sstevel@tonic-gate Statistics.files++; 189*7c478bd9Sstevel@tonic-gate db_set_current_file(filename); 190*7c478bd9Sstevel@tonic-gate errlog(TRACING, "now in file \"%s\" in lib \"%s\"", 191*7c478bd9Sstevel@tonic-gate filename, lib); 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate /* Generate filenames. */ 194*7c478bd9Sstevel@tonic-gate (void) snprintf(infile, sizeof (infile), "%s", filename); 195*7c478bd9Sstevel@tonic-gate (void) snprintf(outfile, sizeof (outfile), "%s.c", 196*7c478bd9Sstevel@tonic-gate db_get_output_file()); 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate /* Open .c file. */ 199*7c478bd9Sstevel@tonic-gate if (open_code_file() == NO) { 200*7c478bd9Sstevel@tonic-gate rc = ERROR_RC; 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate generate_init(); /* Write stuff to the c file. */ 204*7c478bd9Sstevel@tonic-gate symtab_clear_includes(); /* Clear out the per-file data. */ 205*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 206*7c478bd9Sstevel@tonic-gate return (rc); 207*7c478bd9Sstevel@tonic-gate } 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate /* 210*7c478bd9Sstevel@tonic-gate * xlator_start_if -- tritto, called on starting each new 211*7c478bd9Sstevel@tonic-gate * interface in the spec file. 212*7c478bd9Sstevel@tonic-gate */ 213*7c478bd9Sstevel@tonic-gate int 214*7c478bd9Sstevel@tonic-gate xlator_start_if(const Meta_info m, int const token, char *value) 215*7c478bd9Sstevel@tonic-gate { 216*7c478bd9Sstevel@tonic-gate char ifname[BUFSIZ]; 217*7c478bd9Sstevel@tonic-gate char *kw; 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate switch (token) { 220*7c478bd9Sstevel@tonic-gate case XLATOR_KW_FUNC: 221*7c478bd9Sstevel@tonic-gate kw = "Function"; 222*7c478bd9Sstevel@tonic-gate break; 223*7c478bd9Sstevel@tonic-gate case XLATOR_KW_DATA: 224*7c478bd9Sstevel@tonic-gate kw = "Data"; 225*7c478bd9Sstevel@tonic-gate break; 226*7c478bd9Sstevel@tonic-gate default: 227*7c478bd9Sstevel@tonic-gate /* This should never happen */ 228*7c478bd9Sstevel@tonic-gate errlog(ERROR, 229*7c478bd9Sstevel@tonic-gate "\"%s\", line %d: Implementation error! " 230*7c478bd9Sstevel@tonic-gate "Please file a bug\n", __FILE__, __LINE__); 231*7c478bd9Sstevel@tonic-gate return (XLATOR_FATAL); 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate seterrline(LINE, m.mi_filename, kw, value); 235*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "xlator_start_if() {"); 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate /* 238*7c478bd9Sstevel@tonic-gate * XXX Note whether interface is function or data in some state data item. 239*7c478bd9Sstevel@tonic-gate * We'll need it later when writing interceptors. 240*7c478bd9Sstevel@tonic-gate */ 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate Statistics.interfaces++; 243*7c478bd9Sstevel@tonic-gate (void) strpqcpy(ifname, value, nextsep2(value)); 244*7c478bd9Sstevel@tonic-gate if (*ifname == '\0') { 245*7c478bd9Sstevel@tonic-gate errlog(INPUT|ERROR|FATAL, 246*7c478bd9Sstevel@tonic-gate "missing argument in \"%s\" line", kw); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate db_set_current_interface(ifname); 249*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, "interface='%s'", value); 250*7c478bd9Sstevel@tonic-gate if (token == XLATOR_KW_DATA) { 251*7c478bd9Sstevel@tonic-gate Statistics.skips++; 252*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, "telling front end to skip '%s'", value); 253*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 254*7c478bd9Sstevel@tonic-gate return (SKIP_RC); /* Tell front end to skip it for us. */ 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate errlog(TRACING, "now in interface \"%s\"", value); 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate symtab_new_function(m.mi_line_number, m.mi_filename); 260*7c478bd9Sstevel@tonic-gate /* Also cleans junk out of symbol table. */ 261*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 262*7c478bd9Sstevel@tonic-gate return (SUCCESS_RC); 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate /* 266*7c478bd9Sstevel@tonic-gate * xlator_take_kvpair -- the primary call: collect a datum provide by the 267*7c478bd9Sstevel@tonic-gate * front-end wrapper. 268*7c478bd9Sstevel@tonic-gate */ 269*7c478bd9Sstevel@tonic-gate int 270*7c478bd9Sstevel@tonic-gate xlator_take_kvpair(Meta_info m, int const token, char *value) 271*7c478bd9Sstevel@tonic-gate { 272*7c478bd9Sstevel@tonic-gate int retval; 273*7c478bd9Sstevel@tonic-gate char *key = Keywords[token-FIRST_TOKEN].key; 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate int line = LINE; /* TBD */ 276*7c478bd9Sstevel@tonic-gate symtab_set_filename(m.mi_filename); 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate value = strnormalize(value); 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate seterrline(line, m.mi_filename, key, value); 281*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "xlator_take_kvpair() {"); 282*7c478bd9Sstevel@tonic-gate Statistics.lines++; 283*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, "key='%s', value='%s'", 284*7c478bd9Sstevel@tonic-gate (key) ? key : "<nil>", 285*7c478bd9Sstevel@tonic-gate (value) ? value : "<nil>"); 286*7c478bd9Sstevel@tonic-gate switch (token) { 287*7c478bd9Sstevel@tonic-gate case XLATOR_KW_DECL: 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * XXX Check state item to see that it is a function, 291*7c478bd9Sstevel@tonic-gate * else do not emit interceptor 292*7c478bd9Sstevel@tonic-gate */ 293*7c478bd9Sstevel@tonic-gate symtab_clear_function(); /* Always use last one. */ 294*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 295*7c478bd9Sstevel@tonic-gate retval = collect_prototype(value, line, m.mi_ext_cnt); 296*7c478bd9Sstevel@tonic-gate break; 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate case XLATOR_KW_INCL: 299*7c478bd9Sstevel@tonic-gate errlog(END, "}"); /* Use union of all includes. */ 300*7c478bd9Sstevel@tonic-gate retval = collect_include(value, line); 301*7c478bd9Sstevel@tonic-gate if (retval == ERROR_RC) { 302*7c478bd9Sstevel@tonic-gate errlog(FATAL|INPUT, "Bad include line in spec file"); 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate break; 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate case XLATOR_KW_EXCP: 307*7c478bd9Sstevel@tonic-gate symtab_clear_exception(); /* Always use last. */ 308*7c478bd9Sstevel@tonic-gate retval = collect_binding(token, value, line); 309*7c478bd9Sstevel@tonic-gate break; 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate case XLATOR_KW_ERRNO: 312*7c478bd9Sstevel@tonic-gate symtab_clear_errval(); /* Always use last. */ 313*7c478bd9Sstevel@tonic-gate retval = collect_errval("errno", line); 314*7c478bd9Sstevel@tonic-gate break; 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate case XLATOR_KW_ERRVAL: 317*7c478bd9Sstevel@tonic-gate symtab_clear_errval(); /* Always use last. */ 318*7c478bd9Sstevel@tonic-gate retval = collect_errval(value, line); 319*7c478bd9Sstevel@tonic-gate break; 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate case XLATOR_KW_ARCH: 322*7c478bd9Sstevel@tonic-gate retval = collect_arch(value); 323*7c478bd9Sstevel@tonic-gate break; 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate case XLATOR_KW_WEAK: 326*7c478bd9Sstevel@tonic-gate if (m.mi_extended == 1) { 327*7c478bd9Sstevel@tonic-gate errlog(ERROR, "\"%s\", line %d: " 328*7c478bd9Sstevel@tonic-gate "Warning: Cannot use extends with a weak " 329*7c478bd9Sstevel@tonic-gate "interface", 330*7c478bd9Sstevel@tonic-gate m.mi_filename, 331*7c478bd9Sstevel@tonic-gate m.mi_line_number); 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate retval = SUCCESS_RC; 334*7c478bd9Sstevel@tonic-gate break; 335*7c478bd9Sstevel@tonic-gate default: 336*7c478bd9Sstevel@tonic-gate retval = ERROR_RC; 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate return (retval); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate /* 345*7c478bd9Sstevel@tonic-gate * xlator_end_if -- called at the end of the interface, to trigger 346*7c478bd9Sstevel@tonic-gate * per-interface processing now entire thing has been seen. 347*7c478bd9Sstevel@tonic-gate */ 348*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 349*7c478bd9Sstevel@tonic-gate int 350*7c478bd9Sstevel@tonic-gate xlator_end_if(const Meta_info m, char const *value) 351*7c478bd9Sstevel@tonic-gate { 352*7c478bd9Sstevel@tonic-gate seterrline(LINE, m.mi_filename, "end", value); 353*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "xlator_end_if() {"); 354*7c478bd9Sstevel@tonic-gate if (symtab_get_skip() == YES) { 355*7c478bd9Sstevel@tonic-gate symtab_set_skip(NO); 356*7c478bd9Sstevel@tonic-gate Statistics.skips++; 357*7c478bd9Sstevel@tonic-gate } else { 358*7c478bd9Sstevel@tonic-gate generate_interface(); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 361*7c478bd9Sstevel@tonic-gate return (SUCCESS_RC); 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate /* 365*7c478bd9Sstevel@tonic-gate * xlator_endfile -- called at the end of the file, to trigger per-file 366*7c478bd9Sstevel@tonic-gate * processing. 367*7c478bd9Sstevel@tonic-gate */ 368*7c478bd9Sstevel@tonic-gate int 369*7c478bd9Sstevel@tonic-gate xlator_endfile(void) 370*7c478bd9Sstevel@tonic-gate { 371*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "xlator_endfile() {"); 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate generate_closedown(); 374*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 375*7c478bd9Sstevel@tonic-gate return ((commit_code_file() == YES)? SUCCESS_RC: ERROR_RC); 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate /* 379*7c478bd9Sstevel@tonic-gate * xlator_endlib -- ditto, at the end of the library. 380*7c478bd9Sstevel@tonic-gate */ 381*7c478bd9Sstevel@tonic-gate int 382*7c478bd9Sstevel@tonic-gate xlator_endlib(void) 383*7c478bd9Sstevel@tonic-gate { 384*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "xlator_endlib() {"); 385*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 386*7c478bd9Sstevel@tonic-gate return (SUCCESS_RC); 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate /* 390*7c478bd9Sstevel@tonic-gate * xlator_end -- the end of the processing, called so translator 391*7c478bd9Sstevel@tonic-gate * can do cleanup, write makefiles, etc. 392*7c478bd9Sstevel@tonic-gate */ 393*7c478bd9Sstevel@tonic-gate int 394*7c478bd9Sstevel@tonic-gate xlator_end(void) 395*7c478bd9Sstevel@tonic-gate { 396*7c478bd9Sstevel@tonic-gate int rc = SUCCESS_RC; 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "xlator_end() {"); 399*7c478bd9Sstevel@tonic-gate rc += !generate_aux_file(); 400*7c478bd9Sstevel@tonic-gate stats_report(); 401*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 402*7c478bd9Sstevel@tonic-gate return (rc); 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate /* 407*7c478bd9Sstevel@tonic-gate ** utilities for this layer/phase only. 408*7c478bd9Sstevel@tonic-gate */ 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate /* 411*7c478bd9Sstevel@tonic-gate * stats_init -- note what time it is... 412*7c478bd9Sstevel@tonic-gate */ 413*7c478bd9Sstevel@tonic-gate static void 414*7c478bd9Sstevel@tonic-gate stats_init(void) 415*7c478bd9Sstevel@tonic-gate { 416*7c478bd9Sstevel@tonic-gate Statistics.start = time(NULL); 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /* 420*7c478bd9Sstevel@tonic-gate * stats_report -- say how much we just did 421*7c478bd9Sstevel@tonic-gate */ 422*7c478bd9Sstevel@tonic-gate #define max(a, b) (a > b)? a: b 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate static void 425*7c478bd9Sstevel@tonic-gate stats_report(void) 426*7c478bd9Sstevel@tonic-gate { 427*7c478bd9Sstevel@tonic-gate double seconds; 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate Statistics.end = time(NULL); 430*7c478bd9Sstevel@tonic-gate seconds = difftime(Statistics.end, Statistics.start); 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate switch (Verbose) { 433*7c478bd9Sstevel@tonic-gate default: 434*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 435*7c478bd9Sstevel@tonic-gate case 1: 436*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Statistics:\n" 437*7c478bd9Sstevel@tonic-gate " %d libraries\n %d files\n" 438*7c478bd9Sstevel@tonic-gate " %d interfaces\n %d lines\n" 439*7c478bd9Sstevel@tonic-gate " %d errors\n %d warnings\n" 440*7c478bd9Sstevel@tonic-gate " %d skips\n" 441*7c478bd9Sstevel@tonic-gate "in %.0f seconds, at %.1f lines/minute.\n", 442*7c478bd9Sstevel@tonic-gate Statistics.libraries, Statistics.files, 443*7c478bd9Sstevel@tonic-gate Statistics.interfaces, Statistics.lines, 444*7c478bd9Sstevel@tonic-gate Statistics.errors, Statistics.warnings, 445*7c478bd9Sstevel@tonic-gate Statistics.skips, 446*7c478bd9Sstevel@tonic-gate seconds, Statistics.lines*60.0/seconds); 447*7c478bd9Sstevel@tonic-gate break; 448*7c478bd9Sstevel@tonic-gate case 0: 449*7c478bd9Sstevel@tonic-gate if (Statistics.errors != 0 || Statistics.warnings != 0) { 450*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 451*7c478bd9Sstevel@tonic-gate "spec2trace: %d errors %d warnings.\n", 452*7c478bd9Sstevel@tonic-gate Statistics.errors, Statistics.warnings); 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate break; 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate /* 460*7c478bd9Sstevel@tonic-gate * Tiny stats class... 461*7c478bd9Sstevel@tonic-gate */ 462*7c478bd9Sstevel@tonic-gate void 463*7c478bd9Sstevel@tonic-gate stats_add_warning(void) 464*7c478bd9Sstevel@tonic-gate { 465*7c478bd9Sstevel@tonic-gate Statistics.warnings++; 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate void 469*7c478bd9Sstevel@tonic-gate stats_add_error(void) 470*7c478bd9Sstevel@tonic-gate { 471*7c478bd9Sstevel@tonic-gate Statistics.errors++; 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate /* 475*7c478bd9Sstevel@tonic-gate * collect_includes -- collect a global list of include files, 476*7c478bd9Sstevel@tonic-gate * converting the comma- or space-separated input list into a 477*7c478bd9Sstevel@tonic-gate * structure for the database to store. 478*7c478bd9Sstevel@tonic-gate * As this can cause problems will ill-structured 479*7c478bd9Sstevel@tonic-gate * files, there is a mechanism to allow exclusion of 480*7c478bd9Sstevel@tonic-gate * certain files, (or certain combinations). At 481*7c478bd9Sstevel@tonic-gate * the moment, the mechanism is TBD, as is the second arg. 482*7c478bd9Sstevel@tonic-gate */ 483*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 484*7c478bd9Sstevel@tonic-gate int 485*7c478bd9Sstevel@tonic-gate collect_include(char *p, int line) 486*7c478bd9Sstevel@tonic-gate { 487*7c478bd9Sstevel@tonic-gate char *include; 488*7c478bd9Sstevel@tonic-gate int len; 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "collect_include() {"); 491*7c478bd9Sstevel@tonic-gate if ((include = strtok(p, ", ")) != NULL) { 492*7c478bd9Sstevel@tonic-gate for (; include != NULL; include = strtok(NULL, ", ")) { 493*7c478bd9Sstevel@tonic-gate include = skipb(include); 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate /* 496*7c478bd9Sstevel@tonic-gate * Make sure the include file's name 497*7c478bd9Sstevel@tonic-gate * has legitimate C syntax - i.e. it's in double 498*7c478bd9Sstevel@tonic-gate * quotes or angle brackets. 499*7c478bd9Sstevel@tonic-gate */ 500*7c478bd9Sstevel@tonic-gate if (*include != '"' && *include != '<') 501*7c478bd9Sstevel@tonic-gate return (ERROR_RC); 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate len = strlen(include); 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate if (include[len-1] != '"' && include[len-1] != '>') 506*7c478bd9Sstevel@tonic-gate return (ERROR_RC); 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate /* 509*7c478bd9Sstevel@tonic-gate * If include filename syntax is OK, add it to 510*7c478bd9Sstevel@tonic-gate * the list 511*7c478bd9Sstevel@tonic-gate */ 512*7c478bd9Sstevel@tonic-gate symtab_add_includes(include); 513*7c478bd9Sstevel@tonic-gate } 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 516*7c478bd9Sstevel@tonic-gate return (SUCCESS_RC); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate /* 520*7c478bd9Sstevel@tonic-gate * collect_binding -- take a binding and stuff it into the database 521*7c478bd9Sstevel@tonic-gate * in canonical form (with the word return in it). 522*7c478bd9Sstevel@tonic-gate */ 523*7c478bd9Sstevel@tonic-gate int 524*7c478bd9Sstevel@tonic-gate collect_binding(int const token, char *value, int line) 525*7c478bd9Sstevel@tonic-gate { 526*7c478bd9Sstevel@tonic-gate char *file = db_get_current_file(); 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "collect_binding() {"); 529*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, "name=\"%s\", value=\"%s\", line=%d\n", 530*7c478bd9Sstevel@tonic-gate Keywords[token-FIRST_TOKEN].key, value, line); 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate if (token == XLATOR_KW_EXCP) { 533*7c478bd9Sstevel@tonic-gate symtab_set_exception(value, line, file); 534*7c478bd9Sstevel@tonic-gate } else { 535*7c478bd9Sstevel@tonic-gate errlog(FATAL|INPUT, "programmer error: impossible binding."); 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 538*7c478bd9Sstevel@tonic-gate return (SUCCESS_RC); 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate /* 542*7c478bd9Sstevel@tonic-gate * collect_errval -- collect the error variable name (only) 543*7c478bd9Sstevel@tonic-gate * from the line. This is expected to be the first 544*7c478bd9Sstevel@tonic-gate * or only thing in a space- or comma-separated list. 545*7c478bd9Sstevel@tonic-gate * Collecting errno/errval possible value is left TBD. 546*7c478bd9Sstevel@tonic-gate */ 547*7c478bd9Sstevel@tonic-gate int 548*7c478bd9Sstevel@tonic-gate collect_errval(char *p, int line) 549*7c478bd9Sstevel@tonic-gate { 550*7c478bd9Sstevel@tonic-gate char *name; 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "collect_errval() {"); 553*7c478bd9Sstevel@tonic-gate name = strtok(p, " \t\n\r"); 554*7c478bd9Sstevel@tonic-gate symtab_set_errval(name, line, db_get_current_file(), "int", "int", 0); 555*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 556*7c478bd9Sstevel@tonic-gate return (SUCCESS_RC); 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate /* 560*7c478bd9Sstevel@tonic-gate * collect_arch -- collect architecture. 561*7c478bd9Sstevel@tonic-gate */ 562*7c478bd9Sstevel@tonic-gate int 563*7c478bd9Sstevel@tonic-gate collect_arch(char *value) 564*7c478bd9Sstevel@tonic-gate { 565*7c478bd9Sstevel@tonic-gate char const *arch = db_get_arch(); 566*7c478bd9Sstevel@tonic-gate char *buf, *p; 567*7c478bd9Sstevel@tonic-gate char *t; 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "collect_arch() {"); 570*7c478bd9Sstevel@tonic-gate if (value == 0 || *value == '\0') 571*7c478bd9Sstevel@tonic-gate errlog(FATAL|INPUT, "No architectures defined in ARCH line"); 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate if ((buf = strdup(value)) == NULL) 574*7c478bd9Sstevel@tonic-gate errlog(FATAL, "Could not allocate memory in ARCH directive"); 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate t = buf; 577*7c478bd9Sstevel@tonic-gate while ((p = strtok(t, " \r\t\n")) != NULL) { 578*7c478bd9Sstevel@tonic-gate if (strcmp(p, arch) == 0 || strcmp(p, "all") == 0) 579*7c478bd9Sstevel@tonic-gate goto cleanup; 580*7c478bd9Sstevel@tonic-gate t = NULL; 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate symtab_set_skip(YES); 583*7c478bd9Sstevel@tonic-gate 584*7c478bd9Sstevel@tonic-gate cleanup: 585*7c478bd9Sstevel@tonic-gate free(buf); 586*7c478bd9Sstevel@tonic-gate return (SUCCESS_RC); 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate /* 590*7c478bd9Sstevel@tonic-gate * de_const -- get rid of const meta-types. This is actually a 591*7c478bd9Sstevel@tonic-gate * dodge to avoid writing a base-type function early in the 592*7c478bd9Sstevel@tonic-gate * process. This may turn into to_basetype() or to_primitivetype(). 593*7c478bd9Sstevel@tonic-gate */ 594*7c478bd9Sstevel@tonic-gate static char * 595*7c478bd9Sstevel@tonic-gate de_const(char *type) 596*7c478bd9Sstevel@tonic-gate { 597*7c478bd9Sstevel@tonic-gate char *p, *q; 598*7c478bd9Sstevel@tonic-gate int i; 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate p = skipb(type); 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate q = strstr(type, "const"); 603*7c478bd9Sstevel@tonic-gate if (q > p) { 604*7c478bd9Sstevel@tonic-gate for (i = 0; i < 5; i++) { 605*7c478bd9Sstevel@tonic-gate *q++ = '\0'; 606*7c478bd9Sstevel@tonic-gate } 607*7c478bd9Sstevel@tonic-gate (void) sprintf(type, "%s%s", strnormalize(p), q); 608*7c478bd9Sstevel@tonic-gate return (type); 609*7c478bd9Sstevel@tonic-gate } else if (p == q) { 610*7c478bd9Sstevel@tonic-gate return (skipb(nextsep(p))); 611*7c478bd9Sstevel@tonic-gate } else { 612*7c478bd9Sstevel@tonic-gate return (type); 613*7c478bd9Sstevel@tonic-gate } 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate /* 618*7c478bd9Sstevel@tonic-gate * to_basetype -- convert a C type declaration into its base type and return 619*7c478bd9Sstevel@tonic-gate * the number of levels of indirection. 620*7c478bd9Sstevel@tonic-gate * Destructive and eats ``const''. 621*7c478bd9Sstevel@tonic-gate */ 622*7c478bd9Sstevel@tonic-gate static int 623*7c478bd9Sstevel@tonic-gate to_basetype(char *str) 624*7c478bd9Sstevel@tonic-gate { 625*7c478bd9Sstevel@tonic-gate char *p = str, 626*7c478bd9Sstevel@tonic-gate buffer[MAXLINE+1], 627*7c478bd9Sstevel@tonic-gate *q = &buffer[0]; 628*7c478bd9Sstevel@tonic-gate int levels = 0; 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate assert(strlen(str) < MAXLINE, "string exceeded MAXLINE"); 631*7c478bd9Sstevel@tonic-gate buffer[0] = NULL; 632*7c478bd9Sstevel@tonic-gate for (; *p != NULL; p++) { 633*7c478bd9Sstevel@tonic-gate switch (*p) { 634*7c478bd9Sstevel@tonic-gate case ' ': /* Convert spaces to single ' '. */ 635*7c478bd9Sstevel@tonic-gate if (*(q-1) != ' ') 636*7c478bd9Sstevel@tonic-gate *q++ = ' '; 637*7c478bd9Sstevel@tonic-gate break; 638*7c478bd9Sstevel@tonic-gate case '*': /* Convert * to _P. */ 639*7c478bd9Sstevel@tonic-gate if (*(q-1) != ' ') 640*7c478bd9Sstevel@tonic-gate *q++ = ' '; 641*7c478bd9Sstevel@tonic-gate levels++; 642*7c478bd9Sstevel@tonic-gate break; 643*7c478bd9Sstevel@tonic-gate case 'c': /* This might be a const */ 644*7c478bd9Sstevel@tonic-gate if (strncmp(p, "const", 5) == 0) { 645*7c478bd9Sstevel@tonic-gate p += 4; 646*7c478bd9Sstevel@tonic-gate } else { 647*7c478bd9Sstevel@tonic-gate *q++ = *p; 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate break; 650*7c478bd9Sstevel@tonic-gate default: 651*7c478bd9Sstevel@tonic-gate /* Otherwise just copy. */ 652*7c478bd9Sstevel@tonic-gate *q++ = *p; 653*7c478bd9Sstevel@tonic-gate break; 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate *q = NULL; 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate assert(q < &buffer[MAXLINE], "q fell off end of buffer"); 658*7c478bd9Sstevel@tonic-gate q--; 659*7c478bd9Sstevel@tonic-gate while (*q == ' ') { 660*7c478bd9Sstevel@tonic-gate *q-- = NULL; 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate assert(strlen(buffer) < MAXLINE, "buffer length exceeded MAXLINE"); 663*7c478bd9Sstevel@tonic-gate (void) strcpy(str, buffer); 664*7c478bd9Sstevel@tonic-gate return (levels); 665*7c478bd9Sstevel@tonic-gate } 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate /* 668*7c478bd9Sstevel@tonic-gate * to_actual -- create an actual-argument list for use 669*7c478bd9Sstevel@tonic-gate * when calling the function. 670*7c478bd9Sstevel@tonic-gate */ 671*7c478bd9Sstevel@tonic-gate static char * 672*7c478bd9Sstevel@tonic-gate to_actual(void) 673*7c478bd9Sstevel@tonic-gate { 674*7c478bd9Sstevel@tonic-gate ENTRY *p; 675*7c478bd9Sstevel@tonic-gate static char buffer[MAXLINE+1]; 676*7c478bd9Sstevel@tonic-gate int n; 677*7c478bd9Sstevel@tonic-gate 678*7c478bd9Sstevel@tonic-gate *buffer = NULL; 679*7c478bd9Sstevel@tonic-gate if ((p = symtab_get_first_arg()) != NULL) { 680*7c478bd9Sstevel@tonic-gate n = MAXLINE - snprintf(buffer, MAXLINE, "%s", name_of(p)); 681*7c478bd9Sstevel@tonic-gate for (p = symtab_get_next_arg(); p != NULL; 682*7c478bd9Sstevel@tonic-gate p = symtab_get_next_arg()) { 683*7c478bd9Sstevel@tonic-gate if (*name_of(p) != NULL) 684*7c478bd9Sstevel@tonic-gate n -= snprintf(strend(buffer), n, 685*7c478bd9Sstevel@tonic-gate ", %s", name_of(p)); 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate } 688*7c478bd9Sstevel@tonic-gate return (buffer); 689*7c478bd9Sstevel@tonic-gate } 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate /* 692*7c478bd9Sstevel@tonic-gate * strpqcpy -- string copy that takes whatever begins with p and ends 693*7c478bd9Sstevel@tonic-gate * just before q. 694*7c478bd9Sstevel@tonic-gate */ 695*7c478bd9Sstevel@tonic-gate static char * 696*7c478bd9Sstevel@tonic-gate strpqcpy(char *target, char *p, char *q) 697*7c478bd9Sstevel@tonic-gate { 698*7c478bd9Sstevel@tonic-gate char saved; 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate saved = *q; 701*7c478bd9Sstevel@tonic-gate *q = NULL; 702*7c478bd9Sstevel@tonic-gate (void) strcpy(target, p); 703*7c478bd9Sstevel@tonic-gate *q = saved; 704*7c478bd9Sstevel@tonic-gate return (target); 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate 707*7c478bd9Sstevel@tonic-gate #ifndef lint 708*7c478bd9Sstevel@tonic-gate int 709*7c478bd9Sstevel@tonic-gate breakpoint(void) 710*7c478bd9Sstevel@tonic-gate { 711*7c478bd9Sstevel@tonic-gate return (0); 712*7c478bd9Sstevel@tonic-gate } 713*7c478bd9Sstevel@tonic-gate #endif 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate int 717*7c478bd9Sstevel@tonic-gate collect_prototype(char *p, int line, int extcnt) 718*7c478bd9Sstevel@tonic-gate { 719*7c478bd9Sstevel@tonic-gate char f_type[BUFSIZ]; /* The function. */ 720*7c478bd9Sstevel@tonic-gate char f_basetype[BUFSIZ]; 721*7c478bd9Sstevel@tonic-gate char f_name[BUFSIZ]; 722*7c478bd9Sstevel@tonic-gate char a_name[BUFSIZ]; /* The arguments. */ 723*7c478bd9Sstevel@tonic-gate char a_basetype[BUFSIZ]; 724*7c478bd9Sstevel@tonic-gate char a_type[BUFSIZ]; 725*7c478bd9Sstevel@tonic-gate char *file = db_get_current_file(); 726*7c478bd9Sstevel@tonic-gate char *interface = db_get_current_interface(); 727*7c478bd9Sstevel@tonic-gate char *q; 728*7c478bd9Sstevel@tonic-gate char const *parse_err; 729*7c478bd9Sstevel@tonic-gate char tmp_proto[BUFSIZ], buf[BUFSIZ]; 730*7c478bd9Sstevel@tonic-gate decl_t *pp, *funargs; 731*7c478bd9Sstevel@tonic-gate type_t *tp; 732*7c478bd9Sstevel@tonic-gate int levels, a_levels; 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate tmp_proto[BUFSIZ-1] = 0; 735*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "collect_prototype() {"); 736*7c478bd9Sstevel@tonic-gate if (p[strlen(p)-1] != ';') 737*7c478bd9Sstevel@tonic-gate (void) snprintf(tmp_proto, BUFSIZ, "%s;", p); 738*7c478bd9Sstevel@tonic-gate else 739*7c478bd9Sstevel@tonic-gate (void) snprintf(tmp_proto, BUFSIZ, "%s", p); 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate /* save prototype in symbol table */ 742*7c478bd9Sstevel@tonic-gate symtab_set_prototype(p); 743*7c478bd9Sstevel@tonic-gate 744*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, "parsing prototype: %s\n", tmp_proto); 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate /* Parse Prototype */ 747*7c478bd9Sstevel@tonic-gate if ((parse_err = decl_Parse(tmp_proto, &pp)) != NULL) { 748*7c478bd9Sstevel@tonic-gate errlog(FATAL|INPUT, "bad prototype: %s\n\t%s\n", parse_err, p); 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate if (extcnt == 0) { 752*7c478bd9Sstevel@tonic-gate char *dname = decl_GetName(pp); 753*7c478bd9Sstevel@tonic-gate if (strcmp(interface, dname) != 0) 754*7c478bd9Sstevel@tonic-gate errlog(FATAL|INPUT, "function and declaration" 755*7c478bd9Sstevel@tonic-gate " name mismatch\nfunction name = %s," 756*7c478bd9Sstevel@tonic-gate " declaration name = %s\n", interface, 757*7c478bd9Sstevel@tonic-gate dname); 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate tp = decl_GetType(pp); 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate if (type_IsPtrFun(tp)) { 763*7c478bd9Sstevel@tonic-gate errlog(FATAL|INPUT, "function %s is declared as a data item" 764*7c478bd9Sstevel@tonic-gate " (pointer to function)\n", interface); 765*7c478bd9Sstevel@tonic-gate } else if (!type_IsFunction(tp)) { 766*7c478bd9Sstevel@tonic-gate errlog(FATAL|INPUT, "function %s is declared as a data item", 767*7c478bd9Sstevel@tonic-gate interface); 768*7c478bd9Sstevel@tonic-gate } 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate if (type_IsVarargs(tp)) { 771*7c478bd9Sstevel@tonic-gate symtab_set_skip(YES); 772*7c478bd9Sstevel@tonic-gate decl_Destroy(pp); 773*7c478bd9Sstevel@tonic-gate return (SUCCESS_RC); 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate decl_GetTraceInfo(pp, f_type, f_basetype, &funargs); 777*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%s", strnormalize(f_type)); 778*7c478bd9Sstevel@tonic-gate (void) strcpy(f_type, buf); 779*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%s", strnormalize(f_basetype)); 780*7c478bd9Sstevel@tonic-gate (void) strcpy(f_basetype, buf); 781*7c478bd9Sstevel@tonic-gate levels = to_basetype(f_basetype); 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate /* get interface name from 'Begin' line */ 784*7c478bd9Sstevel@tonic-gate (void) strpqcpy(f_name, interface, nextsep(interface)); 785*7c478bd9Sstevel@tonic-gate (void) decl_SetName(pp, f_name); 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, "f_name=%s, f_basetype=%s, f_type=%s\n", 788*7c478bd9Sstevel@tonic-gate f_name, f_basetype, f_type); 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate symtab_set_function(f_name, line, file, f_type, f_basetype, levels); 791*7c478bd9Sstevel@tonic-gate 792*7c478bd9Sstevel@tonic-gate db_add_print_types(f_basetype, 793*7c478bd9Sstevel@tonic-gate (q = de_const(type_of(symtab_get_function())))); 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate symtab_add_print_types(f_basetype, q); 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate /* args list */ 798*7c478bd9Sstevel@tonic-gate while (funargs) { 799*7c478bd9Sstevel@tonic-gate (void) snprintf(a_type, BUFSIZ, "%s ", 800*7c478bd9Sstevel@tonic-gate strnormalize(declspec_ToString(buf, funargs->d_ds))); 801*7c478bd9Sstevel@tonic-gate (void) snprintf(a_basetype, BUFSIZ, "%s", 802*7c478bd9Sstevel@tonic-gate strnormalize(de_const(declspec_ToString(buf, 803*7c478bd9Sstevel@tonic-gate funargs->d_ds)))); 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate tp = funargs->d_type; 806*7c478bd9Sstevel@tonic-gate 807*7c478bd9Sstevel@tonic-gate for (a_levels = 0; tp; ) { 808*7c478bd9Sstevel@tonic-gate if (tp->t_dt == DD_PTR || tp->t_dt == DD_ARY) { 809*7c478bd9Sstevel@tonic-gate (void) strcat(a_type, "*"); 810*7c478bd9Sstevel@tonic-gate a_levels++; 811*7c478bd9Sstevel@tonic-gate } 812*7c478bd9Sstevel@tonic-gate tp = tp->t_next; 813*7c478bd9Sstevel@tonic-gate } 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate /* 816*7c478bd9Sstevel@tonic-gate * XXX: This is a hack to work around bug in yacc parser 817*7c478bd9Sstevel@tonic-gate * "int foo(void)" prototypes get interpreted as having 1 818*7c478bd9Sstevel@tonic-gate * argument with the d_name of the argument being NULL. 819*7c478bd9Sstevel@tonic-gate */ 820*7c478bd9Sstevel@tonic-gate if (funargs->d_name) { 821*7c478bd9Sstevel@tonic-gate (void) snprintf(a_name, 20, "%s", funargs->d_name); 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, 824*7c478bd9Sstevel@tonic-gate "a_name = %s, a_basetype = %s, a_type = %s\n", 825*7c478bd9Sstevel@tonic-gate a_name, a_basetype, a_type); 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate symtab_add_args(a_name, line, file, 828*7c478bd9Sstevel@tonic-gate a_type, a_basetype, a_levels); 829*7c478bd9Sstevel@tonic-gate db_add_print_types(a_basetype, 830*7c478bd9Sstevel@tonic-gate q = de_const(type_of(symtab_get_last_arg()))); 831*7c478bd9Sstevel@tonic-gate symtab_add_print_types(a_basetype, q); 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate funargs = funargs->d_next; 835*7c478bd9Sstevel@tonic-gate } 836*7c478bd9Sstevel@tonic-gate symtab_set_formals(decl_ToFormal(pp)); 837*7c478bd9Sstevel@tonic-gate symtab_set_actuals(to_actual()); 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate symtab_set_cast(decl_ToString(buf, DTS_CAST, pp, NULL)); 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate decl_Destroy(pp); 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 844*7c478bd9Sstevel@tonic-gate return (SUCCESS_RC); 845*7c478bd9Sstevel@tonic-gate } 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate 848*7c478bd9Sstevel@tonic-gate /* 849*7c478bd9Sstevel@tonic-gate * generators 850*7c478bd9Sstevel@tonic-gate */ 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate /* 853*7c478bd9Sstevel@tonic-gate * generate_init -- prime the code generator as required. 854*7c478bd9Sstevel@tonic-gate */ 855*7c478bd9Sstevel@tonic-gate static void 856*7c478bd9Sstevel@tonic-gate generate_init(void) 857*7c478bd9Sstevel@tonic-gate { 858*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "generate_init() {"); 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate (void) fprintf(Headfp, 861*7c478bd9Sstevel@tonic-gate "/*\n" 862*7c478bd9Sstevel@tonic-gate " * Generated by spec2trace %s: do not edit this file.\n */\n\n", 863*7c478bd9Sstevel@tonic-gate TRACE_VERSION); 864*7c478bd9Sstevel@tonic-gate 865*7c478bd9Sstevel@tonic-gate (void) fprintf(Headfp, 866*7c478bd9Sstevel@tonic-gate "#ifndef true\n" 867*7c478bd9Sstevel@tonic-gate "#define\ttrue 1\n" 868*7c478bd9Sstevel@tonic-gate "#define\tfalse 0\n" 869*7c478bd9Sstevel@tonic-gate "#endif\n\n" 870*7c478bd9Sstevel@tonic-gate "static char const *oparen = \"(\";\n" 871*7c478bd9Sstevel@tonic-gate "static char const *retstr = \" return = \";\n" 872*7c478bd9Sstevel@tonic-gate "static char const *errnostr = \" errno = \";\n" 873*7c478bd9Sstevel@tonic-gate "static char const *nilstr = \"<nil>\";\n" 874*7c478bd9Sstevel@tonic-gate "\n"); 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 877*7c478bd9Sstevel@tonic-gate } 878*7c478bd9Sstevel@tonic-gate 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate /* 881*7c478bd9Sstevel@tonic-gate * generate_interface -- call the two main parts of the per-interface 882*7c478bd9Sstevel@tonic-gate * code generation. 883*7c478bd9Sstevel@tonic-gate */ 884*7c478bd9Sstevel@tonic-gate static void 885*7c478bd9Sstevel@tonic-gate generate_interface(void) 886*7c478bd9Sstevel@tonic-gate { 887*7c478bd9Sstevel@tonic-gate ENTRY *function = symtab_get_function(); 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "generate_interface() {"); 890*7c478bd9Sstevel@tonic-gate /* Check for required information. */ 891*7c478bd9Sstevel@tonic-gate if (validity_of(function) == NO) { 892*7c478bd9Sstevel@tonic-gate symtab_set_skip(YES); 893*7c478bd9Sstevel@tonic-gate errlog(WARNING|INPUT, "no prototype for interface " 894*7c478bd9Sstevel@tonic-gate "it will be skipped"); 895*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 896*7c478bd9Sstevel@tonic-gate return; 897*7c478bd9Sstevel@tonic-gate } 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate /* Generate the current interface 's print-functions declarations. */ 900*7c478bd9Sstevel@tonic-gate generate_print_declarations(Bodyfp); 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate /* Generate the linkage part (a function and a struct */ 903*7c478bd9Sstevel@tonic-gate generate_linkage(function); 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate /* Generate the actual interceptor. */ 906*7c478bd9Sstevel@tonic-gate generate_interceptor(function); 907*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate /* 912*7c478bd9Sstevel@tonic-gate * generate_closedown -- produce includes. 913*7c478bd9Sstevel@tonic-gate */ 914*7c478bd9Sstevel@tonic-gate static void 915*7c478bd9Sstevel@tonic-gate generate_closedown(void) 916*7c478bd9Sstevel@tonic-gate { 917*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "generate_closedown() {"); 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate /* Print includes to primary file. */ 920*7c478bd9Sstevel@tonic-gate generate_includes(); 921*7c478bd9Sstevel@tonic-gate (void) putc('\n', Headfp); 922*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate /* 926*7c478bd9Sstevel@tonic-gate * generate_aux_file -- generate one additional .pf file with 927*7c478bd9Sstevel@tonic-gate * print-function pointers. 928*7c478bd9Sstevel@tonic-gate */ 929*7c478bd9Sstevel@tonic-gate static int 930*7c478bd9Sstevel@tonic-gate generate_aux_file(void) 931*7c478bd9Sstevel@tonic-gate { 932*7c478bd9Sstevel@tonic-gate FILE *fp; 933*7c478bd9Sstevel@tonic-gate char pathname[MAXLINE]; 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "generate_aux_file() {"); 936*7c478bd9Sstevel@tonic-gate /* Open file */ 937*7c478bd9Sstevel@tonic-gate (void) snprintf(pathname, sizeof (pathname), "%s.pf", 938*7c478bd9Sstevel@tonic-gate db_get_output_file()); 939*7c478bd9Sstevel@tonic-gate errlog(TRACING, "output file = '%s'", pathname); 940*7c478bd9Sstevel@tonic-gate if ((fp = fopen(pathname, "w")) == NULL) { 941*7c478bd9Sstevel@tonic-gate errlog(FATAL, "%s: %s", pathname, strerror(errno)); 942*7c478bd9Sstevel@tonic-gate } 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate /* 945*7c478bd9Sstevel@tonic-gate * Declare and initialize all print function pointers to null. 946*7c478bd9Sstevel@tonic-gate * Some spec files result in nothing being put into the .pf 947*7c478bd9Sstevel@tonic-gate * file. We must create the file since make(1) does not cope 948*7c478bd9Sstevel@tonic-gate * well with absent files that it expects to have built. So 949*7c478bd9Sstevel@tonic-gate * now the build gets empty compilation unit warnings... So 950*7c478bd9Sstevel@tonic-gate * we unconditionally create a static pointer. 951*7c478bd9Sstevel@tonic-gate */ 952*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, 953*7c478bd9Sstevel@tonic-gate "/* Do not edit this file: it is a generated one. */\n\n" 954*7c478bd9Sstevel@tonic-gate "static char const *__abi_place_holder;\n\n"); 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate generate_print_definitions(fp); 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate /* Close file */ 959*7c478bd9Sstevel@tonic-gate if (fclose(fp) != 0) { 960*7c478bd9Sstevel@tonic-gate errlog(FATAL, "fclose %s: %s", pathname, strerror(errno)); 961*7c478bd9Sstevel@tonic-gate } 962*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 963*7c478bd9Sstevel@tonic-gate return (YES); 964*7c478bd9Sstevel@tonic-gate } 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate /* 969*7c478bd9Sstevel@tonic-gate * generate_includes -- generate #includes to Headfp 970*7c478bd9Sstevel@tonic-gate */ 971*7c478bd9Sstevel@tonic-gate static void 972*7c478bd9Sstevel@tonic-gate generate_includes(void) 973*7c478bd9Sstevel@tonic-gate { 974*7c478bd9Sstevel@tonic-gate char *include; 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "generate_includes() {"); 977*7c478bd9Sstevel@tonic-gate errlog(TRACING, "includes="); 978*7c478bd9Sstevel@tonic-gate for (include = symtab_get_first_include(); include != NULL; 979*7c478bd9Sstevel@tonic-gate include = symtab_get_next_include()) 980*7c478bd9Sstevel@tonic-gate (void) fprintf(Headfp, "#include %s\n", include); 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate (void) fprintf(Headfp, "\n#include <stdio.h>\n" 983*7c478bd9Sstevel@tonic-gate "#include <dlfcn.h>\n" 984*7c478bd9Sstevel@tonic-gate "#include <apptrace.h>\n\n"); 985*7c478bd9Sstevel@tonic-gate 986*7c478bd9Sstevel@tonic-gate errlog(TRACING, "\n"); 987*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 988*7c478bd9Sstevel@tonic-gate } 989