#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.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);
void
generate_interceptor(ENTRY *function)
{
char *prototype = symtab_get_prototype(),
*library_name = db_get_current_library(),
*function_name,
*error_name;
int void_func;
errlog(BEGIN, "generate_interceptor() {");
if (validity_of(function) == NO) {
symtab_set_skip(YES);
errlog(WARNING|INPUT, "No prototype for interface, "
"it will be skipped");
errlog(END, "}");
return;
}
function_name = name_of(function);
error_name = variables_get_errorname();
void_func = is_void(function);
{
decl_t *dp;
char *buf;
char const *err;
size_t s;
s = strlen(prototype) + 2;
buf = malloc(s);
if (buf == NULL)
abort();
(void) strcpy(buf, prototype);
buf[s - 2] = ';';
buf[s - 1] = '\0';
err = decl_Parse(buf, &dp);
if (err != NULL)
errlog(FATAL, "\"%s\", line %d: %s: %s",
symtab_get_filename(), line_of(function),
err, prototype);
(void) fprintf(Mapfp, "\t__abi_%s;\n", decl_GetName(dp));
(void) decl_ToString(buf, DTS_DECL, dp, function_name);
(void) fprintf(Bodyfp, "#line %d \"%s\"\n",
line_of(function), symtab_get_filename());
(void) fprintf(Bodyfp, "#undef %s\n", function_name);
(void) fprintf(Bodyfp, "extern %s;\n", buf);
(void) fprintf(Bodyfp, "static %s\n{\n", prototype);
(void) decl_ToString(buf, DTS_RET, dp, "_return");
generate_i_declarations(error_name, void_func, buf);
decl_Destroy(dp);
free(buf);
}
generate_i_preamble(function);
generate_i_call(function, void_func, library_name, error_name);
generate_i_postamble(function, void_func, error_name, library_name);
errlog(END, "}");
}
void
print_function_signature(char *xtype, char *name, char *formals)
{
char buffer[MAXLINE];
(void) snprintf(buffer, sizeof (buffer), "%s", name);
(void) fprintf(Bodyfp, xtype, buffer);
if (strstr(xtype, "(*") == NULL) {
(void) fprintf(Bodyfp, "(%s)", formals);
}
}
static void
generate_i_declarations(char *errname, int voidfunc, char *ret_str)
{
errlog(BEGIN, "generate_i_declarations() {");
if (*errname != '\0') {
(void) fprintf(Bodyfp,
" int saved_errvar = %s;\n", errname);
(void) fprintf(Bodyfp, " int functions_errvar;\n");
}
if (need_exception_binding()) {
(void) fprintf(Bodyfp, " int exception = 0;\n");
}
if (! voidfunc) {
(void) fprintf(Bodyfp, " %s;\n", ret_str);
}
(void) fprintf(Bodyfp, " sigset_t omask;\n");
(void) putc('\n', Bodyfp);
errlog(END, "}");
}
static void
generate_i_preamble(ENTRY *function)
{
errlog(BEGIN, "generate_i_preamble() {");
generate_i_live_vars(function);
if (symtab_get_nonreturn() == YES) {
(void) fprintf(Bodyfp,
" abilock(&omask);\n");
generate_printf(function);
(void) fputs(" putc('\\n', ABISTREAM);\n\n", Bodyfp);
(void) fprintf(Bodyfp,
" abiunlock(&omask);\n");
}
errlog(END, "}");
}
static void
generate_i_call(
ENTRY *function,
int void_func,
char *library_name,
char *error_name)
{
char *function_name = name_of(function),
*function_cast = symtab_get_cast(),
*actual_args = symtab_get_actuals();
errlog(BEGIN, "generate_i_call() {");
if (*error_name != '\0') {
(void) fprintf(Bodyfp, " %s = 0;\n", error_name);
}
if (void_func) {
(void) fprintf(Bodyfp,
" (void) ABI_CALL_REAL(%s, %s, %s)(%s);\n",
library_name, function_name, function_cast, actual_args);
} else {
(void) fprintf(Bodyfp,
" _return = ABI_CALL_REAL(%s, %s, %s)(%s);\n",
library_name, function_name, function_cast, actual_args);
}
if (*error_name != '\0') {
(void) fprintf(Bodyfp,
" functions_errvar = %s;\n", error_name);
}
(void) putc('\n', Bodyfp);
(void) fprintf(Bodyfp,
" abilock(&omask);\n");
errlog(END, "}");
}
static void
generate_i_postamble(ENTRY *function, int void_func,
char *error_name, char *library_name)
{
errlog(BEGIN, "generate_i_postamble() {");
if (symtab_get_nonreturn() == NO) {
generate_printf(function);
}
(void) putc('\n', Bodyfp);
if (generate_i_bindings(void_func) == YES) {
generate_return_printf(void_func);
}
generate_i_prints(function, library_name, name_of(function));
generate_i_evaluations(function);
generate_i_closedown(error_name, void_func);
errlog(END, "}");
}
static int
generate_i_bindings(int void_func)
{
ENTRY *e;
char *exception;
exception = ((e = symtab_get_exception()) != NULL)?
(name_of(e)? name_of(e): ""): "";
errlog(BEGIN, "generate_i_bindings() {");
if (void_func && bindings_exist()) {
errlog(FATAL, "exception bindings found in a "
"void function");
} else if (void_func || need_bindings(exception) == NO) {
(void) fprintf(Bodyfp,
" (void) putc('\\n', ABISTREAM);\n");
(void) putc('\n', Bodyfp);
errlog(END, "}");
return (NO);
} else {
if ((generate_bindings(exception)) != ANTONYMS) {
(void) fprintf(Bodyfp,
" if (!exception) {\n");
errlog(END, "}");
return (YES);
}
}
errlog(END, "}");
return (NO);
}
static void
generate_return_printf(int void_func)
{
errlog(BEGIN, "generate_return_printf() {");
if (void_func) {
(void) fprintf(Bodyfp, " putc('\\n', ABISTREAM);\n");
errlog(END, "}");
return;
}
(void) fprintf(Bodyfp,
"\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");
errlog(END, "}");
}
static void
generate_i_prints(ENTRY *function, char *lib, char *func)
{
ENTRY *e;
errlog(BEGIN, "generate_i_prints() {");
if ((e = symtab_get_first_arg()) != NULL || !is_void(e)) {
(void) fprintf(Bodyfp, " if (ABI_VFLAG(%s, %s) != 0) {\n",
lib, func);
generate_printfunc_calls(function);
(void) fprintf(Bodyfp, " }\n");
}
(void) putc('\n', Bodyfp);
errlog(END, "}");
}
static void
generate_i_closedown(char *error_name, int void_func)
{
errlog(BEGIN, "generate_i_closedown() {");
(void) fprintf(Bodyfp,
" abiunlock(&omask);\n");
if (*error_name != '\0') {
(void) fprintf(Bodyfp,
" %s = (functions_errvar == 0)? "
" saved_errvar: functions_errvar;\n",
error_name);
}
(void) fprintf(Bodyfp,
" return%s;\n",
(void_func)? "": " _return");
(void) fprintf(Bodyfp, "}\n");
(void) putc('\n', Bodyfp);
errlog(END, "}");
}
static void
generate_i_live_vars(ENTRY *function)
{
errlog(BEGIN, "generate_i_live_vars() {");
errlog(END, "}");
}
static void
generate_i_evaluations(ENTRY *function)
{
errlog(BEGIN, "generate_i_evaluations() {");
errlog(END, "}");
}
static char *
variables_get_errorname(void)
{
return ("ABI_ERRNO");
}