17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright (c) 1997-2001 by Sun Microsystems, Inc.
247c478bd9Sstevel@tonic-gate  * All rights reserved.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  *
297c478bd9Sstevel@tonic-gate  * trace.c -- a  simple translator from spec source to c source for
307c478bd9Sstevel@tonic-gate  *	a apptrace interposer library.  This file implements the
317c478bd9Sstevel@tonic-gate  *	(interface to) the front end. Other files implement the middle
327c478bd9Sstevel@tonic-gate  *	and databases, and generate.c implements the back end.
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <errno.h>
387c478bd9Sstevel@tonic-gate #include <stdlib.h>
397c478bd9Sstevel@tonic-gate #include <sys/types.h>
407c478bd9Sstevel@tonic-gate #include <time.h>
417c478bd9Sstevel@tonic-gate #include <string.h>
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #include "parser.h"
447c478bd9Sstevel@tonic-gate #include "trace.h"
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate #include "util.h"
477c478bd9Sstevel@tonic-gate #include "db.h"
487c478bd9Sstevel@tonic-gate #include "symtab.h"
497c478bd9Sstevel@tonic-gate #include "io.h"
507c478bd9Sstevel@tonic-gate #include "printfuncs.h"
517c478bd9Sstevel@tonic-gate #include "errlog.h"
527c478bd9Sstevel@tonic-gate #include "parseproto.h"
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate static int  Verbose;
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate /* File globals. This would be better as a class. */
577c478bd9Sstevel@tonic-gate /* The first four (commented out) of these enums are defined in parser.h */
587c478bd9Sstevel@tonic-gate enum {
597c478bd9Sstevel@tonic-gate 	/* XLATOR_KW_NOTFOUND = 0, */
607c478bd9Sstevel@tonic-gate 	/* XLATOR_KW_FUNC, */
617c478bd9Sstevel@tonic-gate 	/* XLATOR_KW_DATA */
627c478bd9Sstevel@tonic-gate 	/* XLATOR_KW_END */
637c478bd9Sstevel@tonic-gate 	XLATOR_KW_EXCP = 4,
647c478bd9Sstevel@tonic-gate 	XLATOR_KW_DECL,
657c478bd9Sstevel@tonic-gate 	XLATOR_KW_INCL,
667c478bd9Sstevel@tonic-gate 	XLATOR_KW_ERRNO,
677c478bd9Sstevel@tonic-gate 	XLATOR_KW_ERRVAL,
687c478bd9Sstevel@tonic-gate 	XLATOR_KW_ARCH,
697c478bd9Sstevel@tonic-gate 	XLATOR_KW_WEAK
707c478bd9Sstevel@tonic-gate };
717c478bd9Sstevel@tonic-gate #define	FIRST_TOKEN 4	/* Must match the first token in the above enum */
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate static xlator_keyword_t Keywords[] = {
747c478bd9Sstevel@tonic-gate 	{ "exception", XLATOR_KW_EXCP },
757c478bd9Sstevel@tonic-gate 	{ "declaration", XLATOR_KW_DECL },
767c478bd9Sstevel@tonic-gate 	{ "include", XLATOR_KW_INCL },
777c478bd9Sstevel@tonic-gate 	{ "errno", XLATOR_KW_ERRNO },
787c478bd9Sstevel@tonic-gate 	{ "errval", XLATOR_KW_ERRVAL},
797c478bd9Sstevel@tonic-gate 	{ "arch", XLATOR_KW_ARCH},
807c478bd9Sstevel@tonic-gate 	{ "weak", XLATOR_KW_WEAK},
817c478bd9Sstevel@tonic-gate 	{ "weakfor", XLATOR_KW_WEAK},
827c478bd9Sstevel@tonic-gate 	{ "alias", XLATOR_KW_WEAK},
837c478bd9Sstevel@tonic-gate 	{ NULL, XLATOR_KW_NOTFOUND }
847c478bd9Sstevel@tonic-gate };
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate static struct stats_t {
877c478bd9Sstevel@tonic-gate 	int	libraries,
887c478bd9Sstevel@tonic-gate 		files,
897c478bd9Sstevel@tonic-gate 		interfaces,
907c478bd9Sstevel@tonic-gate 		lines;
917c478bd9Sstevel@tonic-gate 	int	errors,
927c478bd9Sstevel@tonic-gate 		warnings,
937c478bd9Sstevel@tonic-gate 		skips;
947c478bd9Sstevel@tonic-gate 	time_t	start,
957c478bd9Sstevel@tonic-gate 		end;
967c478bd9Sstevel@tonic-gate } Statistics;
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate #define	LINE	(m.mi_line_number-(m.mi_nlines-1))
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate static void stats_init(void);
1017c478bd9Sstevel@tonic-gate static void stats_report(void);
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate static int collect_binding(int const, char *, int);
1047c478bd9Sstevel@tonic-gate static int collect_prototype(char *, int, int);
1057c478bd9Sstevel@tonic-gate static int collect_include(char *, int);
1067c478bd9Sstevel@tonic-gate static int collect_errval(char *, int);
1077c478bd9Sstevel@tonic-gate static int collect_arch(char *);
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate static void generate_includes(void);
1107c478bd9Sstevel@tonic-gate static void generate_init(void);
1117c478bd9Sstevel@tonic-gate static void generate_interface(void);
1127c478bd9Sstevel@tonic-gate static void generate_closedown(void);
1137c478bd9Sstevel@tonic-gate static int generate_aux_file();
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate /* Local (static) parsing functions. */
1167c478bd9Sstevel@tonic-gate static char *to_actual();
1177c478bd9Sstevel@tonic-gate static int to_basetype(char *);
1187c478bd9Sstevel@tonic-gate static char *de_const(char *);
1197c478bd9Sstevel@tonic-gate static char *strpqcpy(char *, char *, char *);
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate /*
1227c478bd9Sstevel@tonic-gate  * xlator_init -- initialize translator, called at startup-time
1237c478bd9Sstevel@tonic-gate  *	with a struct translator_info of information the translator
1247c478bd9Sstevel@tonic-gate  *	might need, returning a list of ``interesting'' spec keywords
1257c478bd9Sstevel@tonic-gate  *	for the front end to select and pass to the back end translator.
1267c478bd9Sstevel@tonic-gate  *
1277c478bd9Sstevel@tonic-gate  */
1287c478bd9Sstevel@tonic-gate xlator_keyword_t *
xlator_init(const Translator_info * t_info)1297c478bd9Sstevel@tonic-gate xlator_init(const Translator_info *t_info)
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate 	int	i;
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "xlator_init() {");
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	/* Save interesting parameters. */
1367c478bd9Sstevel@tonic-gate 	stats_init();
1377c478bd9Sstevel@tonic-gate 	db_set_source_directory(".");
1387c478bd9Sstevel@tonic-gate 	db_set_target_directory(".");
1397c478bd9Sstevel@tonic-gate 	Verbose = t_info->ti_verbosity;
1407c478bd9Sstevel@tonic-gate 	seterrseverity(Verbose); /* Ditto. */
1417c478bd9Sstevel@tonic-gate 	db_set_output_file(t_info->ti_output_file);
1427c478bd9Sstevel@tonic-gate 	db_set_arch(t_info->ti_arch);
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	/* Display passed argument and return value. */
1457c478bd9Sstevel@tonic-gate 	errlog(VERBOSE, "Keywords[] = {");
1467c478bd9Sstevel@tonic-gate 	for (i = 0; Keywords[i].key != NULL; i++) {
1477c478bd9Sstevel@tonic-gate 		errlog(VERBOSE, "    \"%s\", ", Keywords[i].key);
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate 	errlog(VERBOSE, "    (char *) NULL");
1507c478bd9Sstevel@tonic-gate 	errlog(VERBOSE, "};");
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	errlog(END, "}");
1537c478bd9Sstevel@tonic-gate 	return (Keywords);
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate /*
1577c478bd9Sstevel@tonic-gate  * xlator_startlib -- called on starting a new library, so back end
1587c478bd9Sstevel@tonic-gate  *	translator can decide to change output file/directory if desired.
1597c478bd9Sstevel@tonic-gate  */
1607c478bd9Sstevel@tonic-gate int
xlator_startlib(char const * libname)1617c478bd9Sstevel@tonic-gate xlator_startlib(char const *libname)
1627c478bd9Sstevel@tonic-gate {
1637c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "xlator_startlib() ");
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	Statistics.libraries++;
1667c478bd9Sstevel@tonic-gate 	db_set_current_library(libname);
1677c478bd9Sstevel@tonic-gate 	errlog(VERBOSE, "now in library \"%s\"", libname);
1687c478bd9Sstevel@tonic-gate 	errlog(END, "}");
1697c478bd9Sstevel@tonic-gate 	return (SUCCESS_RC);
1707c478bd9Sstevel@tonic-gate }
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate /*
1737c478bd9Sstevel@tonic-gate  * xlator_startfile -- ditto, called on starting each new spec file in the
1747c478bd9Sstevel@tonic-gate  *	specified library.
1757c478bd9Sstevel@tonic-gate  */
1767c478bd9Sstevel@tonic-gate int
xlator_startfile(char const * filename)1777c478bd9Sstevel@tonic-gate xlator_startfile(char const *filename)
1787c478bd9Sstevel@tonic-gate {
1797c478bd9Sstevel@tonic-gate 	int	rc = SUCCESS_RC;
1807c478bd9Sstevel@tonic-gate 	char	infile[MAXLINE],
1817c478bd9Sstevel@tonic-gate 		outfile[MAXLINE],
1827c478bd9Sstevel@tonic-gate 		*lib = db_get_current_library();
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	seterrline(0, filename, "", "");
1857c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "xlator_startfile() {");
1867c478bd9Sstevel@tonic-gate 	Statistics.files++;
1877c478bd9Sstevel@tonic-gate 	db_set_current_file(filename);
1887c478bd9Sstevel@tonic-gate 	errlog(TRACING, "now in file \"%s\" in lib \"%s\"",
1897c478bd9Sstevel@tonic-gate 		filename, lib);
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	/* Generate filenames. */
1927c478bd9Sstevel@tonic-gate 	(void) snprintf(infile, sizeof (infile), "%s", filename);
1937c478bd9Sstevel@tonic-gate 	(void) snprintf(outfile, sizeof (outfile), "%s.c",
1947c478bd9Sstevel@tonic-gate 		db_get_output_file());
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	/* Open .c file. */
1977c478bd9Sstevel@tonic-gate 	if (open_code_file() == NO) {
1987c478bd9Sstevel@tonic-gate 		rc = ERROR_RC;
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	generate_init(); /* Write stuff to the c file. */
2027c478bd9Sstevel@tonic-gate 	symtab_clear_includes(); /* Clear out the per-file data. */
2037c478bd9Sstevel@tonic-gate 	errlog(END, "}");
2047c478bd9Sstevel@tonic-gate 	return (rc);
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate  * xlator_start_if -- tritto, called on starting each new
2097c478bd9Sstevel@tonic-gate  *	interface in the spec file.
2107c478bd9Sstevel@tonic-gate  */
2117c478bd9Sstevel@tonic-gate int
xlator_start_if(const Meta_info m,int const token,char * value)2127c478bd9Sstevel@tonic-gate xlator_start_if(const Meta_info m, int const token, char *value)
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate 	char ifname[BUFSIZ];
2157c478bd9Sstevel@tonic-gate 	char *kw;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	switch (token) {
2187c478bd9Sstevel@tonic-gate 	case XLATOR_KW_FUNC:
2197c478bd9Sstevel@tonic-gate 		kw = "Function";
2207c478bd9Sstevel@tonic-gate 		break;
2217c478bd9Sstevel@tonic-gate 	case XLATOR_KW_DATA:
2227c478bd9Sstevel@tonic-gate 		kw = "Data";
2237c478bd9Sstevel@tonic-gate 		break;
2247c478bd9Sstevel@tonic-gate 	default:
2257c478bd9Sstevel@tonic-gate 		/* This should never happen */
2267c478bd9Sstevel@tonic-gate 		errlog(ERROR,
2277c478bd9Sstevel@tonic-gate 		    "\"%s\", line %d: Implementation error! "
2287c478bd9Sstevel@tonic-gate 		    "Please file a bug\n", __FILE__, __LINE__);
2297c478bd9Sstevel@tonic-gate 		return (XLATOR_FATAL);
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	seterrline(LINE, m.mi_filename, kw, value);
2337c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "xlator_start_if() {");
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate /*
2367c478bd9Sstevel@tonic-gate  * XXX Note whether interface is function or data in some state data item.
2377c478bd9Sstevel@tonic-gate  * We'll need it later when writing interceptors.
2387c478bd9Sstevel@tonic-gate  */
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	Statistics.interfaces++;
2417c478bd9Sstevel@tonic-gate 	(void) strpqcpy(ifname, value, nextsep2(value));
2427c478bd9Sstevel@tonic-gate 	if (*ifname == '\0') {
2437c478bd9Sstevel@tonic-gate 		errlog(INPUT|ERROR|FATAL,
2447c478bd9Sstevel@tonic-gate 		    "missing argument in \"%s\" line", kw);
2457c478bd9Sstevel@tonic-gate 	}
2467c478bd9Sstevel@tonic-gate 	db_set_current_interface(ifname);
2477c478bd9Sstevel@tonic-gate 	errlog(VERBOSE, "interface='%s'", value);
2487c478bd9Sstevel@tonic-gate 	if (token == XLATOR_KW_DATA) {
2497c478bd9Sstevel@tonic-gate 		Statistics.skips++;
2507c478bd9Sstevel@tonic-gate 		errlog(VERBOSE, "telling front end to skip '%s'", value);
2517c478bd9Sstevel@tonic-gate 		errlog(END, "}");
2527c478bd9Sstevel@tonic-gate 		return (SKIP_RC); /* Tell front end to skip it for us. */
2537c478bd9Sstevel@tonic-gate 	}
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	errlog(TRACING, "now in interface \"%s\"", value);
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	symtab_new_function(m.mi_line_number, m.mi_filename);
2587c478bd9Sstevel@tonic-gate 		/* Also cleans junk out of symbol table. */
2597c478bd9Sstevel@tonic-gate 	errlog(END, "}");
2607c478bd9Sstevel@tonic-gate 	return (SUCCESS_RC);
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate /*
2647c478bd9Sstevel@tonic-gate  * xlator_take_kvpair -- the primary call: collect a datum provide by the
2657c478bd9Sstevel@tonic-gate  *	front-end wrapper.
2667c478bd9Sstevel@tonic-gate  */
2677c478bd9Sstevel@tonic-gate int
xlator_take_kvpair(Meta_info m,int const token,char * value)2687c478bd9Sstevel@tonic-gate xlator_take_kvpair(Meta_info m, int const token, char *value)
2697c478bd9Sstevel@tonic-gate {
2707c478bd9Sstevel@tonic-gate 	int retval;
2717c478bd9Sstevel@tonic-gate 	char *key = Keywords[token-FIRST_TOKEN].key;
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	int line = LINE; /* TBD */
2747c478bd9Sstevel@tonic-gate 	symtab_set_filename(m.mi_filename);
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	value = strnormalize(value);
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	seterrline(line, m.mi_filename, key, value);
2797c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "xlator_take_kvpair() {");
2807c478bd9Sstevel@tonic-gate 	Statistics.lines++;
2817c478bd9Sstevel@tonic-gate 	errlog(VERBOSE, "key='%s', value='%s'",
2827c478bd9Sstevel@tonic-gate 	    (key) ? key : "<nil>",
2837c478bd9Sstevel@tonic-gate 	    (value) ? value : "<nil>");
2847c478bd9Sstevel@tonic-gate 	switch (token) {
2857c478bd9Sstevel@tonic-gate 	case XLATOR_KW_DECL:
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	/*
2887c478bd9Sstevel@tonic-gate 	 * XXX Check state item to see that it is a function,
2897c478bd9Sstevel@tonic-gate 	 * else do not emit interceptor
2907c478bd9Sstevel@tonic-gate 	 */
2917c478bd9Sstevel@tonic-gate 		symtab_clear_function(); /* Always use last one. */
2927c478bd9Sstevel@tonic-gate 		errlog(END, "}");
2937c478bd9Sstevel@tonic-gate 		retval = collect_prototype(value, line, m.mi_ext_cnt);
2947c478bd9Sstevel@tonic-gate 		break;
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	case XLATOR_KW_INCL:
2977c478bd9Sstevel@tonic-gate 		errlog(END, "}"); /* Use union of all includes. */
2987c478bd9Sstevel@tonic-gate 		retval = collect_include(value, line);
2997c478bd9Sstevel@tonic-gate 		if (retval == ERROR_RC) {
3007c478bd9Sstevel@tonic-gate 			errlog(FATAL|INPUT, "Bad include line in spec file");
3017c478bd9Sstevel@tonic-gate 		}
3027c478bd9Sstevel@tonic-gate 		break;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	case XLATOR_KW_EXCP:
3057c478bd9Sstevel@tonic-gate 		symtab_clear_exception(); /* Always use last. */
3067c478bd9Sstevel@tonic-gate 		retval = collect_binding(token, value, line);
3077c478bd9Sstevel@tonic-gate 		break;
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	case XLATOR_KW_ERRNO:
3107c478bd9Sstevel@tonic-gate 		symtab_clear_errval(); /* Always use last. */
3117c478bd9Sstevel@tonic-gate 		retval = collect_errval("errno", line);
3127c478bd9Sstevel@tonic-gate 		break;
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	case XLATOR_KW_ERRVAL:
3157c478bd9Sstevel@tonic-gate 		symtab_clear_errval(); /* Always use last. */
3167c478bd9Sstevel@tonic-gate 		retval =  collect_errval(value, line);
3177c478bd9Sstevel@tonic-gate 		break;
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	case XLATOR_KW_ARCH:
3207c478bd9Sstevel@tonic-gate 		retval = collect_arch(value);
3217c478bd9Sstevel@tonic-gate 		break;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	case XLATOR_KW_WEAK:
3247c478bd9Sstevel@tonic-gate 		if (m.mi_extended == 1) {
3257c478bd9Sstevel@tonic-gate 			errlog(ERROR, "\"%s\", line %d: "
3267c478bd9Sstevel@tonic-gate 			    "Warning: Cannot use extends with a weak "
3277c478bd9Sstevel@tonic-gate 			    "interface",
3287c478bd9Sstevel@tonic-gate 			    m.mi_filename,
3297c478bd9Sstevel@tonic-gate 			    m.mi_line_number);
3307c478bd9Sstevel@tonic-gate 		}
3317c478bd9Sstevel@tonic-gate 		retval = SUCCESS_RC;
3327c478bd9Sstevel@tonic-gate 		break;
3337c478bd9Sstevel@tonic-gate 	default:
3347c478bd9Sstevel@tonic-gate 		retval = ERROR_RC;
3357c478bd9Sstevel@tonic-gate 	}
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	errlog(END, "}");
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	return (retval);
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate /*
3437c478bd9Sstevel@tonic-gate  * xlator_end_if -- called at the end of the interface, to trigger
3447c478bd9Sstevel@tonic-gate  *	per-interface processing now entire thing has been seen.
3457c478bd9Sstevel@tonic-gate  */
3467c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3477c478bd9Sstevel@tonic-gate int
xlator_end_if(const Meta_info m,char const * value)3487c478bd9Sstevel@tonic-gate xlator_end_if(const Meta_info m, char const *value)
3497c478bd9Sstevel@tonic-gate {
3507c478bd9Sstevel@tonic-gate 	seterrline(LINE, m.mi_filename, "end", value);
3517c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "xlator_end_if() {");
3527c478bd9Sstevel@tonic-gate 	if (symtab_get_skip() == YES) {
3537c478bd9Sstevel@tonic-gate 		symtab_set_skip(NO);
3547c478bd9Sstevel@tonic-gate 		Statistics.skips++;
3557c478bd9Sstevel@tonic-gate 	} else {
3567c478bd9Sstevel@tonic-gate 		generate_interface();
3577c478bd9Sstevel@tonic-gate 	}
3587c478bd9Sstevel@tonic-gate 	errlog(END, "}");
3597c478bd9Sstevel@tonic-gate 	return (SUCCESS_RC);
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate /*
3637c478bd9Sstevel@tonic-gate  * xlator_endfile -- called at the end of the file, to trigger per-file
3647c478bd9Sstevel@tonic-gate  * processing.
3657c478bd9Sstevel@tonic-gate  */
3667c478bd9Sstevel@tonic-gate int
xlator_endfile(void)3677c478bd9Sstevel@tonic-gate xlator_endfile(void)
3687c478bd9Sstevel@tonic-gate {
3697c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "xlator_endfile() {");
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	generate_closedown();
3727c478bd9Sstevel@tonic-gate 	errlog(END, "}");
3737c478bd9Sstevel@tonic-gate 	return ((commit_code_file() == YES)? SUCCESS_RC: ERROR_RC);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate /*
3777c478bd9Sstevel@tonic-gate  * xlator_endlib -- ditto, at the end of the library.
3787c478bd9Sstevel@tonic-gate  */
3797c478bd9Sstevel@tonic-gate int
xlator_endlib(void)3807c478bd9Sstevel@tonic-gate xlator_endlib(void)
3817c478bd9Sstevel@tonic-gate {
3827c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "xlator_endlib() {");
3837c478bd9Sstevel@tonic-gate 	errlog(END, "}");
3847c478bd9Sstevel@tonic-gate 	return (SUCCESS_RC);
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate /*
3887c478bd9Sstevel@tonic-gate  * xlator_end -- the end of the processing, called so translator
3897c478bd9Sstevel@tonic-gate  *	can do cleanup, write makefiles, etc.
3907c478bd9Sstevel@tonic-gate  */
3917c478bd9Sstevel@tonic-gate int
xlator_end(void)3927c478bd9Sstevel@tonic-gate xlator_end(void)
3937c478bd9Sstevel@tonic-gate {
3947c478bd9Sstevel@tonic-gate 	int	rc = SUCCESS_RC;
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "xlator_end() {");
3977c478bd9Sstevel@tonic-gate 	rc += !generate_aux_file();
3987c478bd9Sstevel@tonic-gate 	stats_report();
3997c478bd9Sstevel@tonic-gate 	errlog(END, "}");
4007c478bd9Sstevel@tonic-gate 	return (rc);
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate /*
4057c478bd9Sstevel@tonic-gate ** utilities for this layer/phase only.
4067c478bd9Sstevel@tonic-gate */
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate /*
4097c478bd9Sstevel@tonic-gate  * stats_init -- note what time it is...
4107c478bd9Sstevel@tonic-gate  */
4117c478bd9Sstevel@tonic-gate static void
stats_init(void)4127c478bd9Sstevel@tonic-gate stats_init(void)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate 	Statistics.start = time(NULL);
4157c478bd9Sstevel@tonic-gate }
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate /*
4187c478bd9Sstevel@tonic-gate  * stats_report -- say how much we just did
4197c478bd9Sstevel@tonic-gate  */
4207c478bd9Sstevel@tonic-gate #define	max(a, b) (a > b)? a: b
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate static void
stats_report(void)4237c478bd9Sstevel@tonic-gate stats_report(void)
4247c478bd9Sstevel@tonic-gate {
4257c478bd9Sstevel@tonic-gate 	double	seconds;
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	Statistics.end = time(NULL);
4287c478bd9Sstevel@tonic-gate 	seconds = difftime(Statistics.end, Statistics.start);
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	switch (Verbose) {
4317c478bd9Sstevel@tonic-gate 	default:
4327c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
4337c478bd9Sstevel@tonic-gate 	case 1:
4347c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Statistics:\n"
4357c478bd9Sstevel@tonic-gate 		    "    %d libraries\n    %d files\n"
4367c478bd9Sstevel@tonic-gate 		    "    %d interfaces\n    %d lines\n"
4377c478bd9Sstevel@tonic-gate 		    "    %d errors\n    %d warnings\n"
4387c478bd9Sstevel@tonic-gate 		    "    %d skips\n"
4397c478bd9Sstevel@tonic-gate 		    "in %.0f seconds, at %.1f lines/minute.\n",
4407c478bd9Sstevel@tonic-gate 		    Statistics.libraries, Statistics.files,
4417c478bd9Sstevel@tonic-gate 		    Statistics.interfaces, Statistics.lines,
4427c478bd9Sstevel@tonic-gate 		    Statistics.errors, Statistics.warnings,
4437c478bd9Sstevel@tonic-gate 		    Statistics.skips,
4447c478bd9Sstevel@tonic-gate 		    seconds, Statistics.lines*60.0/seconds);
4457c478bd9Sstevel@tonic-gate 		break;
4467c478bd9Sstevel@tonic-gate 	case 0:
4477c478bd9Sstevel@tonic-gate 		if (Statistics.errors != 0 || Statistics.warnings != 0) {
4487c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
4497c478bd9Sstevel@tonic-gate 			    "spec2trace: %d errors %d warnings.\n",
4507c478bd9Sstevel@tonic-gate 			    Statistics.errors, Statistics.warnings);
4517c478bd9Sstevel@tonic-gate 		}
4527c478bd9Sstevel@tonic-gate 		break;
4537c478bd9Sstevel@tonic-gate 	}
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate /*
4587c478bd9Sstevel@tonic-gate  * Tiny stats class...
4597c478bd9Sstevel@tonic-gate  */
4607c478bd9Sstevel@tonic-gate void
stats_add_warning(void)4617c478bd9Sstevel@tonic-gate stats_add_warning(void)
4627c478bd9Sstevel@tonic-gate {
4637c478bd9Sstevel@tonic-gate 	Statistics.warnings++;
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate void
stats_add_error(void)4677c478bd9Sstevel@tonic-gate stats_add_error(void)
4687c478bd9Sstevel@tonic-gate {
4697c478bd9Sstevel@tonic-gate 	Statistics.errors++;
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate /*
4737c478bd9Sstevel@tonic-gate  * collect_includes -- collect a global list of include files,
4747c478bd9Sstevel@tonic-gate  *	converting the comma- or space-separated input list into a
4757c478bd9Sstevel@tonic-gate  *	structure for the database to store.
4767c478bd9Sstevel@tonic-gate  *	As this can cause problems will ill-structured
4777c478bd9Sstevel@tonic-gate  *	files, there is a mechanism to allow exclusion of
4787c478bd9Sstevel@tonic-gate  *	certain files, (or certain combinations).  At
4797c478bd9Sstevel@tonic-gate  *	the moment, the mechanism is TBD, as is the second arg.
4807c478bd9Sstevel@tonic-gate  */
4817c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
4827c478bd9Sstevel@tonic-gate int
collect_include(char * p,int line)4837c478bd9Sstevel@tonic-gate collect_include(char *p, int line)
4847c478bd9Sstevel@tonic-gate {
4857c478bd9Sstevel@tonic-gate 	char	*include;
4867c478bd9Sstevel@tonic-gate 	int	len;
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "collect_include() {");
4897c478bd9Sstevel@tonic-gate 	if ((include = strtok(p, ", ")) != NULL) {
4907c478bd9Sstevel@tonic-gate 		for (; include != NULL; include = strtok(NULL, ", ")) {
4917c478bd9Sstevel@tonic-gate 			include  = skipb(include);
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 			/*
4947c478bd9Sstevel@tonic-gate 			 * Make sure the include file's name
4957c478bd9Sstevel@tonic-gate 			 * has legitimate C syntax - i.e. it's in double
4967c478bd9Sstevel@tonic-gate 			 * quotes or angle brackets.
4977c478bd9Sstevel@tonic-gate 			 */
4987c478bd9Sstevel@tonic-gate 			if (*include != '"' && *include != '<')
4997c478bd9Sstevel@tonic-gate 				return (ERROR_RC);
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 			len = strlen(include);
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 			if (include[len-1] != '"' && include[len-1] != '>')
5047c478bd9Sstevel@tonic-gate 				return (ERROR_RC);
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 			/*
5077c478bd9Sstevel@tonic-gate 			 * If include filename syntax is OK, add it to
5087c478bd9Sstevel@tonic-gate 			 * the list
5097c478bd9Sstevel@tonic-gate 			 */
5107c478bd9Sstevel@tonic-gate 			symtab_add_includes(include);
5117c478bd9Sstevel@tonic-gate 		}
5127c478bd9Sstevel@tonic-gate 	}
5137c478bd9Sstevel@tonic-gate 	errlog(END, "}");
5147c478bd9Sstevel@tonic-gate 	return (SUCCESS_RC);
5157c478bd9Sstevel@tonic-gate }
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate /*
5187c478bd9Sstevel@tonic-gate  * collect_binding -- take a binding and stuff it into the database
5197c478bd9Sstevel@tonic-gate  *	in canonical form (with the word return in it).
5207c478bd9Sstevel@tonic-gate  */
5217c478bd9Sstevel@tonic-gate int
collect_binding(int const token,char * value,int line)5227c478bd9Sstevel@tonic-gate collect_binding(int const token, char *value, int line)
5237c478bd9Sstevel@tonic-gate {
5247c478bd9Sstevel@tonic-gate 	char	*file = db_get_current_file();
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "collect_binding() {");
5277c478bd9Sstevel@tonic-gate 	errlog(VERBOSE, "name=\"%s\", value=\"%s\", line=%d\n",
5287c478bd9Sstevel@tonic-gate 	    Keywords[token-FIRST_TOKEN].key, value, line);
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	if (token == XLATOR_KW_EXCP) {
5317c478bd9Sstevel@tonic-gate 		symtab_set_exception(value, line, file);
5327c478bd9Sstevel@tonic-gate 	} else {
5337c478bd9Sstevel@tonic-gate 		errlog(FATAL|INPUT, "programmer error: impossible binding.");
5347c478bd9Sstevel@tonic-gate 	}
5357c478bd9Sstevel@tonic-gate 	errlog(END, "}");
5367c478bd9Sstevel@tonic-gate 	return (SUCCESS_RC);
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate /*
5407c478bd9Sstevel@tonic-gate  * collect_errval -- collect the error variable name (only)
5417c478bd9Sstevel@tonic-gate  *	from the line.  This is expected to be the first
5427c478bd9Sstevel@tonic-gate  *	or only thing in a space- or comma-separated list.
5437c478bd9Sstevel@tonic-gate  *	Collecting errno/errval possible value is left TBD.
5447c478bd9Sstevel@tonic-gate  */
5457c478bd9Sstevel@tonic-gate int
collect_errval(char * p,int line)5467c478bd9Sstevel@tonic-gate collect_errval(char *p, int line)
5477c478bd9Sstevel@tonic-gate {
5487c478bd9Sstevel@tonic-gate 	char	*name;
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "collect_errval() {");
5517c478bd9Sstevel@tonic-gate 	name = strtok(p, " \t\n\r");
5527c478bd9Sstevel@tonic-gate 	symtab_set_errval(name, line, db_get_current_file(), "int", "int", 0);
5537c478bd9Sstevel@tonic-gate 	errlog(END, "}");
5547c478bd9Sstevel@tonic-gate 	return (SUCCESS_RC);
5557c478bd9Sstevel@tonic-gate }
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate /*
5587c478bd9Sstevel@tonic-gate  * collect_arch -- collect architecture.
5597c478bd9Sstevel@tonic-gate  */
5607c478bd9Sstevel@tonic-gate int
collect_arch(char * value)5617c478bd9Sstevel@tonic-gate collect_arch(char *value)
5627c478bd9Sstevel@tonic-gate {
5637c478bd9Sstevel@tonic-gate 	char const	*arch = db_get_arch();
5647c478bd9Sstevel@tonic-gate 	char	*buf, *p;
5657c478bd9Sstevel@tonic-gate 	char	*t;
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "collect_arch() {");
5687c478bd9Sstevel@tonic-gate 	if (value == 0 || *value == '\0')
5697c478bd9Sstevel@tonic-gate 		errlog(FATAL|INPUT, "No architectures defined in ARCH line");
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	if ((buf = strdup(value)) == NULL)
5727c478bd9Sstevel@tonic-gate 		errlog(FATAL, "Could not allocate memory in ARCH directive");
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 	t = buf;
5757c478bd9Sstevel@tonic-gate 	while ((p = strtok(t, " \r\t\n")) != NULL) {
5767c478bd9Sstevel@tonic-gate 		if (strcmp(p, arch) == 0 || strcmp(p, "all") == 0)
5777c478bd9Sstevel@tonic-gate 			goto cleanup;
5787c478bd9Sstevel@tonic-gate 		t = NULL;
5797c478bd9Sstevel@tonic-gate 	}
5807c478bd9Sstevel@tonic-gate 	symtab_set_skip(YES);
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate cleanup:
5837c478bd9Sstevel@tonic-gate 	free(buf);
5847c478bd9Sstevel@tonic-gate 	return (SUCCESS_RC);
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate /*
5887c478bd9Sstevel@tonic-gate  * de_const -- get rid of const meta-types. This is actually a
5897c478bd9Sstevel@tonic-gate  *	dodge to avoid writing a base-type function early in the
5907c478bd9Sstevel@tonic-gate  *	process. This may turn into to_basetype() or to_primitivetype().
5917c478bd9Sstevel@tonic-gate  */
5927c478bd9Sstevel@tonic-gate static char *
de_const(char * type)5937c478bd9Sstevel@tonic-gate de_const(char *type)
5947c478bd9Sstevel@tonic-gate {
5957c478bd9Sstevel@tonic-gate 	char *p, *q;
5967c478bd9Sstevel@tonic-gate 	int i;
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	p = skipb(type);
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	q = strstr(type, "const");
6017c478bd9Sstevel@tonic-gate 	if (q > p) {
6027c478bd9Sstevel@tonic-gate 		for (i = 0; i < 5; i++) {
6037c478bd9Sstevel@tonic-gate 			*q++ = '\0';
6047c478bd9Sstevel@tonic-gate 		}
6057c478bd9Sstevel@tonic-gate 		(void) sprintf(type, "%s%s", strnormalize(p), q);
6067c478bd9Sstevel@tonic-gate 		return (type);
6077c478bd9Sstevel@tonic-gate 	} else if (p == q) {
6087c478bd9Sstevel@tonic-gate 		return (skipb(nextsep(p)));
6097c478bd9Sstevel@tonic-gate 	} else {
6107c478bd9Sstevel@tonic-gate 		return (type);
6117c478bd9Sstevel@tonic-gate 	}
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate /*
6167c478bd9Sstevel@tonic-gate  * to_basetype -- convert a C type declaration into its base type and return
6177c478bd9Sstevel@tonic-gate  * 	the number of levels of indirection.
6187c478bd9Sstevel@tonic-gate  *	Destructive and eats ``const''.
6197c478bd9Sstevel@tonic-gate  */
6207c478bd9Sstevel@tonic-gate static int
to_basetype(char * str)6217c478bd9Sstevel@tonic-gate to_basetype(char *str)
6227c478bd9Sstevel@tonic-gate {
6237c478bd9Sstevel@tonic-gate 	char	*p = str,
6247c478bd9Sstevel@tonic-gate 		buffer[MAXLINE+1],
6257c478bd9Sstevel@tonic-gate 		*q = &buffer[0];
6267c478bd9Sstevel@tonic-gate 	int	levels = 0;
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate 	assert(strlen(str) < MAXLINE, "string exceeded MAXLINE");
629*07c94cbfSToomas Soome 	buffer[0] = '\0';
630*07c94cbfSToomas Soome 	for (; *p != '\0'; p++) {
6317c478bd9Sstevel@tonic-gate 		switch (*p) {
6327c478bd9Sstevel@tonic-gate 		case ' ': /* Convert spaces to single ' '. */
6337c478bd9Sstevel@tonic-gate 			if (*(q-1) != ' ')
6347c478bd9Sstevel@tonic-gate 				*q++ = ' ';
6357c478bd9Sstevel@tonic-gate 			break;
6367c478bd9Sstevel@tonic-gate 		case '*': /* Convert * to _P. */
6377c478bd9Sstevel@tonic-gate 			if (*(q-1) != ' ')
6387c478bd9Sstevel@tonic-gate 				*q++ = ' ';
6397c478bd9Sstevel@tonic-gate 			levels++;
6407c478bd9Sstevel@tonic-gate 			break;
6417c478bd9Sstevel@tonic-gate 		case 'c': /* This might be a const */
6427c478bd9Sstevel@tonic-gate 			if (strncmp(p, "const", 5) == 0) {
6437c478bd9Sstevel@tonic-gate 				p += 4;
6447c478bd9Sstevel@tonic-gate 			} else {
6457c478bd9Sstevel@tonic-gate 				*q++ = *p;
6467c478bd9Sstevel@tonic-gate 			}
6477c478bd9Sstevel@tonic-gate 			break;
6487c478bd9Sstevel@tonic-gate 		default:
6497c478bd9Sstevel@tonic-gate 			/* Otherwise just copy. */
6507c478bd9Sstevel@tonic-gate 			*q++ = *p;
6517c478bd9Sstevel@tonic-gate 			break;
6527c478bd9Sstevel@tonic-gate 		}
653*07c94cbfSToomas Soome 		*q = '\0';
6547c478bd9Sstevel@tonic-gate 	}
6557c478bd9Sstevel@tonic-gate 	assert(q < &buffer[MAXLINE], "q fell off end of buffer");
6567c478bd9Sstevel@tonic-gate 	q--;
6577c478bd9Sstevel@tonic-gate 	while (*q == ' ') {
658*07c94cbfSToomas Soome 		*q-- = '\0';
6597c478bd9Sstevel@tonic-gate 	}
6607c478bd9Sstevel@tonic-gate 	assert(strlen(buffer) < MAXLINE, "buffer length exceeded MAXLINE");
6617c478bd9Sstevel@tonic-gate 	(void) strcpy(str, buffer);
6627c478bd9Sstevel@tonic-gate 	return (levels);
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate /*
6667c478bd9Sstevel@tonic-gate  * to_actual -- create an actual-argument list for use
6677c478bd9Sstevel@tonic-gate  *	when calling the function.
6687c478bd9Sstevel@tonic-gate  */
6697c478bd9Sstevel@tonic-gate static char *
to_actual(void)6707c478bd9Sstevel@tonic-gate to_actual(void)
6717c478bd9Sstevel@tonic-gate {
6727c478bd9Sstevel@tonic-gate 	ENTRY	*p;
6737c478bd9Sstevel@tonic-gate 	static char buffer[MAXLINE+1];
6747c478bd9Sstevel@tonic-gate 	int	n;
6757c478bd9Sstevel@tonic-gate 
676*07c94cbfSToomas Soome 	*buffer = '\0';
6777c478bd9Sstevel@tonic-gate 	if ((p = symtab_get_first_arg()) != NULL) {
6787c478bd9Sstevel@tonic-gate 		n = MAXLINE - snprintf(buffer, MAXLINE, "%s", name_of(p));
6797c478bd9Sstevel@tonic-gate 		for (p = symtab_get_next_arg(); p != NULL;
6807c478bd9Sstevel@tonic-gate 						p = symtab_get_next_arg()) {
681*07c94cbfSToomas Soome 			if (*name_of(p) != '\0')
6827c478bd9Sstevel@tonic-gate 				n -= snprintf(strend(buffer), n,
6837c478bd9Sstevel@tonic-gate 					", %s", name_of(p));
6847c478bd9Sstevel@tonic-gate 		}
6857c478bd9Sstevel@tonic-gate 	}
6867c478bd9Sstevel@tonic-gate 	return (buffer);
6877c478bd9Sstevel@tonic-gate }
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate /*
6907c478bd9Sstevel@tonic-gate  * strpqcpy -- string copy that takes whatever begins with p and ends
6917c478bd9Sstevel@tonic-gate  *	just before q.
6927c478bd9Sstevel@tonic-gate  */
6937c478bd9Sstevel@tonic-gate static char *
strpqcpy(char * target,char * p,char * q)6947c478bd9Sstevel@tonic-gate strpqcpy(char *target, char *p, char *q)
6957c478bd9Sstevel@tonic-gate {
6967c478bd9Sstevel@tonic-gate 	char	saved;
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 	saved = *q;
699*07c94cbfSToomas Soome 	*q = '\0';
7007c478bd9Sstevel@tonic-gate 	(void) strcpy(target, p);
7017c478bd9Sstevel@tonic-gate 	*q = saved;
7027c478bd9Sstevel@tonic-gate 	return (target);
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate #ifndef lint
7067c478bd9Sstevel@tonic-gate int
breakpoint(void)7077c478bd9Sstevel@tonic-gate breakpoint(void)
7087c478bd9Sstevel@tonic-gate {
7097c478bd9Sstevel@tonic-gate 	return (0);
7107c478bd9Sstevel@tonic-gate }
7117c478bd9Sstevel@tonic-gate #endif
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate int
collect_prototype(char * p,int line,int extcnt)7157c478bd9Sstevel@tonic-gate collect_prototype(char *p, int line, int extcnt)
7167c478bd9Sstevel@tonic-gate {
7177c478bd9Sstevel@tonic-gate 	char	f_type[BUFSIZ];	/* The function. */
7187c478bd9Sstevel@tonic-gate 	char	f_basetype[BUFSIZ];
7197c478bd9Sstevel@tonic-gate 	char	f_name[BUFSIZ];
7207c478bd9Sstevel@tonic-gate 	char	a_name[BUFSIZ];	/* The arguments. */
7217c478bd9Sstevel@tonic-gate 	char	a_basetype[BUFSIZ];
7227c478bd9Sstevel@tonic-gate 	char	a_type[BUFSIZ];
7237c478bd9Sstevel@tonic-gate 	char	*file = db_get_current_file();
7247c478bd9Sstevel@tonic-gate 	char	*interface = db_get_current_interface();
7257c478bd9Sstevel@tonic-gate 	char	*q;
7267c478bd9Sstevel@tonic-gate 	char const *parse_err;
7277c478bd9Sstevel@tonic-gate 	char	tmp_proto[BUFSIZ], buf[BUFSIZ];
7287c478bd9Sstevel@tonic-gate 	decl_t	*pp, *funargs;
7297c478bd9Sstevel@tonic-gate 	type_t	*tp;
7307c478bd9Sstevel@tonic-gate 	int	levels, a_levels;
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 	tmp_proto[BUFSIZ-1] = 0;
7337c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "collect_prototype() {");
7347c478bd9Sstevel@tonic-gate 	if (p[strlen(p)-1] != ';')
7357c478bd9Sstevel@tonic-gate 		(void) snprintf(tmp_proto, BUFSIZ, "%s;", p);
7367c478bd9Sstevel@tonic-gate 	else
7377c478bd9Sstevel@tonic-gate 		(void) snprintf(tmp_proto, BUFSIZ, "%s", p);
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate 	/* save prototype in symbol table */
7407c478bd9Sstevel@tonic-gate 	symtab_set_prototype(p);
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 	errlog(VERBOSE, "parsing prototype: %s\n", tmp_proto);
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	/* Parse Prototype */
7457c478bd9Sstevel@tonic-gate 	if ((parse_err = decl_Parse(tmp_proto, &pp)) != NULL) {
7467c478bd9Sstevel@tonic-gate 		errlog(FATAL|INPUT, "bad prototype: %s\n\t%s\n", parse_err, p);
7477c478bd9Sstevel@tonic-gate 	}
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	if (extcnt == 0) {
7507c478bd9Sstevel@tonic-gate 		char *dname = decl_GetName(pp);
7517c478bd9Sstevel@tonic-gate 		if (strcmp(interface, dname) != 0)
7527c478bd9Sstevel@tonic-gate 			errlog(FATAL|INPUT, "function and declaration"
7537c478bd9Sstevel@tonic-gate 			    " name mismatch\nfunction name = %s,"
7547c478bd9Sstevel@tonic-gate 			    " declaration name = %s\n", interface,
7557c478bd9Sstevel@tonic-gate 			    dname);
7567c478bd9Sstevel@tonic-gate 	}
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 	tp = decl_GetType(pp);
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 	if (type_IsPtrFun(tp)) {
7617c478bd9Sstevel@tonic-gate 		errlog(FATAL|INPUT, "function %s is declared as a data item"
7627c478bd9Sstevel@tonic-gate 		    " (pointer to function)\n", interface);
7637c478bd9Sstevel@tonic-gate 	} else if (!type_IsFunction(tp)) {
7647c478bd9Sstevel@tonic-gate 		errlog(FATAL|INPUT, "function %s is declared as a data item",
7657c478bd9Sstevel@tonic-gate 		    interface);
7667c478bd9Sstevel@tonic-gate 	}
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 	if (type_IsVarargs(tp)) {
7697c478bd9Sstevel@tonic-gate 		symtab_set_skip(YES);
7707c478bd9Sstevel@tonic-gate 		decl_Destroy(pp);
7717c478bd9Sstevel@tonic-gate 		return (SUCCESS_RC);
7727c478bd9Sstevel@tonic-gate 	}
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 	decl_GetTraceInfo(pp, f_type, f_basetype, &funargs);
7757c478bd9Sstevel@tonic-gate 	(void) sprintf(buf, "%s", strnormalize(f_type));
7767c478bd9Sstevel@tonic-gate 	(void) strcpy(f_type, buf);
7777c478bd9Sstevel@tonic-gate 	(void) sprintf(buf, "%s", strnormalize(f_basetype));
7787c478bd9Sstevel@tonic-gate 	(void) strcpy(f_basetype, buf);
7797c478bd9Sstevel@tonic-gate 	levels = to_basetype(f_basetype);
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	/* get interface name from 'Begin' line */
7827c478bd9Sstevel@tonic-gate 	(void) strpqcpy(f_name, interface, nextsep(interface));
7837c478bd9Sstevel@tonic-gate 	(void) decl_SetName(pp, f_name);
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 	errlog(VERBOSE, "f_name=%s, f_basetype=%s, f_type=%s\n",
7867c478bd9Sstevel@tonic-gate 		f_name, f_basetype, f_type);
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 	symtab_set_function(f_name, line, file, f_type, f_basetype, levels);
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 	db_add_print_types(f_basetype,
7917c478bd9Sstevel@tonic-gate 	    (q = de_const(type_of(symtab_get_function()))));
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 	symtab_add_print_types(f_basetype, q);
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 	/* args list */
7967c478bd9Sstevel@tonic-gate 	while (funargs) {
7977c478bd9Sstevel@tonic-gate 		(void) snprintf(a_type, BUFSIZ, "%s ",
7987c478bd9Sstevel@tonic-gate 			strnormalize(declspec_ToString(buf, funargs->d_ds)));
7997c478bd9Sstevel@tonic-gate 		(void) snprintf(a_basetype, BUFSIZ, "%s",
8007c478bd9Sstevel@tonic-gate 			strnormalize(de_const(declspec_ToString(buf,
8017c478bd9Sstevel@tonic-gate 			funargs->d_ds))));
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 		tp = funargs->d_type;
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate 		for (a_levels = 0; tp; ) {
8067c478bd9Sstevel@tonic-gate 			if (tp->t_dt == DD_PTR || tp->t_dt == DD_ARY) {
8077c478bd9Sstevel@tonic-gate 				(void) strcat(a_type, "*");
8087c478bd9Sstevel@tonic-gate 				a_levels++;
8097c478bd9Sstevel@tonic-gate 			}
8107c478bd9Sstevel@tonic-gate 			tp = tp->t_next;
8117c478bd9Sstevel@tonic-gate 		}
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 		/*
8147c478bd9Sstevel@tonic-gate 		 * XXX: This is a hack to work around bug in yacc parser
8157c478bd9Sstevel@tonic-gate 		 *  "int foo(void)" prototypes get interpreted as having 1
8167c478bd9Sstevel@tonic-gate 		 *  argument with the d_name of the argument being NULL.
8177c478bd9Sstevel@tonic-gate 		 */
8187c478bd9Sstevel@tonic-gate 		if (funargs->d_name) {
8197c478bd9Sstevel@tonic-gate 			(void) snprintf(a_name, 20, "%s", funargs->d_name);
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate 			errlog(VERBOSE,
8227c478bd9Sstevel@tonic-gate 			    "a_name = %s, a_basetype = %s, a_type = %s\n",
8237c478bd9Sstevel@tonic-gate 			    a_name, a_basetype, a_type);
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate 			symtab_add_args(a_name, line, file,
8267c478bd9Sstevel@tonic-gate 			    a_type, a_basetype, a_levels);
8277c478bd9Sstevel@tonic-gate 			db_add_print_types(a_basetype,
8287c478bd9Sstevel@tonic-gate 			    q = de_const(type_of(symtab_get_last_arg())));
8297c478bd9Sstevel@tonic-gate 			symtab_add_print_types(a_basetype, q);
8307c478bd9Sstevel@tonic-gate 		}
8317c478bd9Sstevel@tonic-gate 
8327c478bd9Sstevel@tonic-gate 		funargs = funargs->d_next;
8337c478bd9Sstevel@tonic-gate 	}
8347c478bd9Sstevel@tonic-gate 	symtab_set_formals(decl_ToFormal(pp));
8357c478bd9Sstevel@tonic-gate 	symtab_set_actuals(to_actual());
8367c478bd9Sstevel@tonic-gate 
8377c478bd9Sstevel@tonic-gate 	symtab_set_cast(decl_ToString(buf, DTS_CAST, pp, NULL));
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate 	decl_Destroy(pp);
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 	errlog(END, "}");
8427c478bd9Sstevel@tonic-gate 	return (SUCCESS_RC);
8437c478bd9Sstevel@tonic-gate }
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate /*
8477c478bd9Sstevel@tonic-gate  * generators
8487c478bd9Sstevel@tonic-gate  */
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate /*
8517c478bd9Sstevel@tonic-gate  * generate_init -- prime the code generator as required.
8527c478bd9Sstevel@tonic-gate  */
8537c478bd9Sstevel@tonic-gate static void
generate_init(void)8547c478bd9Sstevel@tonic-gate generate_init(void)
8557c478bd9Sstevel@tonic-gate {
8567c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_init() {");
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 	(void) fprintf(Headfp,
8597c478bd9Sstevel@tonic-gate 	    "/*\n"
8607c478bd9Sstevel@tonic-gate 	    " * Generated by spec2trace %s: do not edit this file.\n */\n\n",
8617c478bd9Sstevel@tonic-gate 	    TRACE_VERSION);
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 	(void) fprintf(Headfp,
8647c478bd9Sstevel@tonic-gate 	    "#ifndef true\n"
8657c478bd9Sstevel@tonic-gate 	    "#define\ttrue 1\n"
8667c478bd9Sstevel@tonic-gate 	    "#define\tfalse 0\n"
8677c478bd9Sstevel@tonic-gate 	    "#endif\n\n"
8687c478bd9Sstevel@tonic-gate 	    "static char const *oparen = \"(\";\n"
8697c478bd9Sstevel@tonic-gate 	    "static char const *retstr = \"  return = \";\n"
8707c478bd9Sstevel@tonic-gate 	    "static char const *errnostr = \" errno = \";\n"
8717c478bd9Sstevel@tonic-gate 	    "static char const *nilstr = \"<nil>\";\n"
8727c478bd9Sstevel@tonic-gate 	    "\n");
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 	errlog(END, "}");
8757c478bd9Sstevel@tonic-gate }
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate /*
8797c478bd9Sstevel@tonic-gate  * generate_interface -- call the two main parts of the per-interface
8807c478bd9Sstevel@tonic-gate  *	code generation.
8817c478bd9Sstevel@tonic-gate  */
8827c478bd9Sstevel@tonic-gate static void
generate_interface(void)8837c478bd9Sstevel@tonic-gate generate_interface(void)
8847c478bd9Sstevel@tonic-gate {
8857c478bd9Sstevel@tonic-gate 	ENTRY	*function = symtab_get_function();
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_interface() {");
8887c478bd9Sstevel@tonic-gate 	/* Check for required information. */
8897c478bd9Sstevel@tonic-gate 	if (validity_of(function) == NO) {
8907c478bd9Sstevel@tonic-gate 		symtab_set_skip(YES);
8917c478bd9Sstevel@tonic-gate 		errlog(WARNING|INPUT, "no prototype for interface "
8927c478bd9Sstevel@tonic-gate 			"it will be skipped");
8937c478bd9Sstevel@tonic-gate 		errlog(END, "}");
8947c478bd9Sstevel@tonic-gate 		return;
8957c478bd9Sstevel@tonic-gate 	}
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 	/* Generate the current interface 's print-functions declarations. */
8987c478bd9Sstevel@tonic-gate 	generate_print_declarations(Bodyfp);
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 	/* Generate the linkage part (a function and a struct */
9017c478bd9Sstevel@tonic-gate 	generate_linkage(function);
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 	/* Generate the actual interceptor. */
9047c478bd9Sstevel@tonic-gate 	generate_interceptor(function);
9057c478bd9Sstevel@tonic-gate 	errlog(END, "}");
9067c478bd9Sstevel@tonic-gate }
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate /*
9107c478bd9Sstevel@tonic-gate  * generate_closedown -- produce includes.
9117c478bd9Sstevel@tonic-gate  */
9127c478bd9Sstevel@tonic-gate static void
generate_closedown(void)9137c478bd9Sstevel@tonic-gate generate_closedown(void)
9147c478bd9Sstevel@tonic-gate {
9157c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_closedown() {");
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate 	/* Print includes to primary file. */
9187c478bd9Sstevel@tonic-gate 	generate_includes();
9197c478bd9Sstevel@tonic-gate 	(void) putc('\n', Headfp);
9207c478bd9Sstevel@tonic-gate 	errlog(END, "}");
9217c478bd9Sstevel@tonic-gate }
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate /*
9247c478bd9Sstevel@tonic-gate  * generate_aux_file -- generate one additional .pf file with
9257c478bd9Sstevel@tonic-gate  *	print-function pointers.
9267c478bd9Sstevel@tonic-gate  */
9277c478bd9Sstevel@tonic-gate static int
generate_aux_file(void)9287c478bd9Sstevel@tonic-gate generate_aux_file(void)
9297c478bd9Sstevel@tonic-gate {
9307c478bd9Sstevel@tonic-gate 	FILE	*fp;
9317c478bd9Sstevel@tonic-gate 	char	pathname[MAXLINE];
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_aux_file() {");
9347c478bd9Sstevel@tonic-gate 	/* Open file */
9357c478bd9Sstevel@tonic-gate 	(void) snprintf(pathname, sizeof (pathname), "%s.pf",
9367c478bd9Sstevel@tonic-gate 		db_get_output_file());
9377c478bd9Sstevel@tonic-gate 	errlog(TRACING,  "output file = '%s'", pathname);
9387c478bd9Sstevel@tonic-gate 	if ((fp = fopen(pathname, "w")) == NULL) {
9397c478bd9Sstevel@tonic-gate 		errlog(FATAL, "%s: %s", pathname, strerror(errno));
9407c478bd9Sstevel@tonic-gate 	}
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate 	/*
9437c478bd9Sstevel@tonic-gate 	 * Declare and initialize all print function pointers to null.
9447c478bd9Sstevel@tonic-gate 	 * Some spec files result in nothing being put into the .pf
9457c478bd9Sstevel@tonic-gate 	 * file.  We must create the file since make(1) does not cope
9467c478bd9Sstevel@tonic-gate 	 * well with absent files that it expects to have built.  So
9477c478bd9Sstevel@tonic-gate 	 * now the build gets empty compilation unit warnings...  So
9487c478bd9Sstevel@tonic-gate 	 * we unconditionally create a static pointer.
9497c478bd9Sstevel@tonic-gate 	 */
9507c478bd9Sstevel@tonic-gate 	(void) fprintf(fp,
9517c478bd9Sstevel@tonic-gate 	    "/* Do not edit this file: it is a generated one. */\n\n"
9527c478bd9Sstevel@tonic-gate 	    "static char const *__abi_place_holder;\n\n");
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate 	generate_print_definitions(fp);
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 	/* Close file */
9577c478bd9Sstevel@tonic-gate 	if (fclose(fp) != 0) {
9587c478bd9Sstevel@tonic-gate 		errlog(FATAL, "fclose %s: %s", pathname, strerror(errno));
9597c478bd9Sstevel@tonic-gate 	}
9607c478bd9Sstevel@tonic-gate 	errlog(END, "}");
9617c478bd9Sstevel@tonic-gate 	return (YES);
9627c478bd9Sstevel@tonic-gate }
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate /*
9677c478bd9Sstevel@tonic-gate  * generate_includes -- generate #includes to Headfp
9687c478bd9Sstevel@tonic-gate  */
9697c478bd9Sstevel@tonic-gate static void
generate_includes(void)9707c478bd9Sstevel@tonic-gate generate_includes(void)
9717c478bd9Sstevel@tonic-gate {
9727c478bd9Sstevel@tonic-gate 	char	*include;
9737c478bd9Sstevel@tonic-gate 
9747c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_includes() {");
9757c478bd9Sstevel@tonic-gate 	errlog(TRACING,  "includes=");
9767c478bd9Sstevel@tonic-gate 	for (include = symtab_get_first_include(); include != NULL;
9777c478bd9Sstevel@tonic-gate 	    include = symtab_get_next_include())
9787c478bd9Sstevel@tonic-gate 		(void) fprintf(Headfp, "#include %s\n", include);
9797c478bd9Sstevel@tonic-gate 
9807c478bd9Sstevel@tonic-gate 	(void) fprintf(Headfp, "\n#include <stdio.h>\n"
9817c478bd9Sstevel@tonic-gate 	    "#include <dlfcn.h>\n"
9827c478bd9Sstevel@tonic-gate 	    "#include <apptrace.h>\n\n");
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 	errlog(TRACING,  "\n");
9857c478bd9Sstevel@tonic-gate 	errlog(END, "}");
9867c478bd9Sstevel@tonic-gate }
987