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