/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1997-2000 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* interceptor.c -- a functional decomposition of generate.c,
* the code generator for apptrace
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "parser.h"
#include "trace.h"
#include "util.h"
#include "db.h"
#include "symtab.h"
#include "io.h"
#include "bindings.h"
#include "printfuncs.h"
#include "errlog.h"
#include "parseproto.h"
static void generate_i_declarations(char *, int, char *);
static void generate_i_preamble(ENTRY *);
static void generate_i_call();
static int generate_i_bindings(int);
static void generate_i_postamble(ENTRY *, int, char *, char *);
static void generate_i_evaluations(ENTRY *);
static void generate_i_prints(ENTRY *, char *, char *);
static void generate_i_closedown(char *, int);
static void generate_i_live_vars(ENTRY *);
static void generate_return_printf(int);
static char *variables_get_errorname(void);
/*
* generate_interceptor -- make code for an individual interceptor, written
* as an output grammar
*/
void
{
int void_func;
/* Check for required information. */
"it will be skipped");
return;
}
/* Collect things we'll use more than once. */
/*
* Emit "artificial" prototype here so that if there's a
* disagreement between it and the prototype contained in the
* declaring header, the compiler will flag it.
* First #undef the function to make sure the prototype in the header
* is exposed and to avoid breaking the artificial prototype if it's
* not.
*/
{
char *buf;
char const *err;
size_t s;
abort();
/* generate the mapfile entry */
}
}
/*
* print_function_signature -- print the line defining the function, without
* an ``extern'' prefix or either a ``;'' or ''{'' suffix.
*/
void
{
}
}
/*
* generate_i_declarations -- generate the declarations which
* are local to the interceptor function itself.
*/
static void
{
/* Create locals for errno-type variable, */
" int saved_errvar = %s;\n", errname);
}
if (need_exception_binding()) {
/* Create a local for that. */
}
if (! voidfunc) {
/* Create a return value. */
}
}
/*
* generate_i_preamble -- do the actions which must occur
* before the call.
*/
static void
{
if (symtab_get_nonreturn() == YES) {
/* Make things safe for printing */
" abilock(&omask);\n");
/* Print all the args in terse format. */
/* unlock stdio */
" abiunlock(&omask);\n");
}
}
/*
*/
static void
int void_func,
char *library_name,
char *error_name)
{
/* Zero the error variable. */
if (*error_name != NULL) {
}
/* Then print the call itself. */
if (void_func) {
" (void) ABI_CALL_REAL(%s, %s, %s)(%s);\n",
} else {
" _return = ABI_CALL_REAL(%s, %s, %s)(%s);\n",
}
/* Then set the local copy of the error variable. */
if (*error_name != NULL) {
" functions_errvar = %s;\n", error_name);
}
/* Make things safe for printing */
" abilock(&omask);\n");
}
/*
* generate_i_postamble -- do all the things which come
* after the call. In the case of apptrace, this is most of the work.
*/
static void
char *error_name, char *library_name)
{
if (symtab_get_nonreturn() == NO) {
/* Print all the args in terse format. */
}
/* If it isn't supposed to return, and actually ends up here, */
/* we'd better be prepared to print all sorts of diagnostic stuff */
}
}
/*
* generate_i_bindings -- see about success and failure, so we can decide
* what to do next.
*/
static int
{
ENTRY *e;
char *exception;
if (void_func && bindings_exist()) {
/* To become a warning, as there are spec errors! TBD */
"void function");
" (void) putc('\\n', ABISTREAM);\n");
return (NO);
} else {
/*
* Then there is a return value, so we try to
* generate exception bindings
* and code to print errno on exception.
*/
/* Generate code to cross-evaluate them. */
" if (!exception) {\n");
return (YES);
}
}
/* should not get here */
return (NO);
}
/*
* generate_return_printf -- print the return value and end the line
*/
static void
{
if (void_func) {
return;
}
/* If its a non-void function there are bindings. */
"\t/* Just end the line */\n"
"\tputc('\\n', ABISTREAM);\n"
" }\n"
" else {\n"
" fprintf(ABISTREAM, \"%%s%%d (%%s)\\n\", errnostr, "
"functions_errvar, strerror((int)functions_errvar));\n"
" }\n\n");
}
/*
* generate_i_prints -- if we're doing the verbose stuff,
* generate verbose printouts of the variables.
*/
static void
{
ENTRY *e;
/* Then we have to generate code for verbose reports. */
}
}
/*
* generate_i_closedown -- restore error variables and return.
*/
static void
{
/* unlock stdio */
" abiunlock(&omask);\n");
if (*error_name != NULL) {
/* Restore error variables. */
" %s = (functions_errvar == 0)? "
" saved_errvar: functions_errvar;\n",
}
/* And return. */
" return%s;\n",
}
/*
* generate_i_live_vars -- generate temps for any ``out''
* or ``inout'' variables in the function. Deferred.
*/
/*ARGSUSED*/
static void
{
}
/*
* generate_i_evaluations -- generate evaluations for
* all the expressions. Deferred.
*/
/*ARGSUSED*/
static void
{
}
static char *
variables_get_errorname(void)
{
return ("ABI_ERRNO");
}