Exemplo n.º 1
0
static bool notify_openr_await(const char *path)
{
    bool needs_await = false;
    DEFINE_MSG(msg, openr);
    PATH_COPY(needs_await, msg.args.path, path);
    return SEND_MSG_AWAIT(needs_await, msg);
}
Exemplo n.º 2
0
static bool notify_openw(const char *path, bool is_also_read, bool is_create, mode_t mode)
{
    bool needs_await = false;
    DEFINE_MSG(msg, openw);
    PATH_COPY(needs_await, msg.args.path, path);
    if(is_also_read) msg.args.flags |= FLAG_ALSO_READ;
    if(is_create)    msg.args.flags |= FLAG_CREATE;
    msg.args.mode = mode;
    return SEND_MSG_AWAIT(needs_await, msg);
}
Exemplo n.º 3
0
namespace sc_core
{

// not documented, but available
const std::string sc_report_compose_message(const sc_report& rep)
{
    static const char * severity_names[] =
    {
        "Info", "Warning", "Error", "Fatal"
    };
    std::string str;

    str += severity_names[rep.get_severity()];
    str += ": ";

    if ( rep.get_id() >= 0 ) // backward compatibility with 2.0+
    {
        char idstr[64];
        std::sprintf(idstr, "(%c%d) ",
                     "IWEF"[rep.get_severity()], rep.get_id());
        str += idstr;
    }
    str += rep.get_msg_type();

    if ( *rep.get_msg() )
    {
        str += ": ";
        str += rep.get_msg();
    }
    if ( rep.get_severity() > SC_INFO )
    {
        char line_number_str[16];
        str += "\nIn file: ";
        str += rep.get_file_name();
        str += ":";
        std::sprintf(line_number_str, "%d", rep.get_line_number());
        str += line_number_str;
        sc_simcontext* simc = sc_get_curr_simcontext();

        if ( simc && sc_is_running() )
        {
            const char* proc_name = rep.get_process_name();

            if ( proc_name )
            {
                str += "\nIn process: ";
                str += proc_name;
                str += " @ ";
                str += rep.get_time().to_string();
            }
        }
    }

    return str;
}
bool sc_report_close_default_log();

static ::std::ofstream* log_stream = 0;
static
struct auto_close_log
{
    ~auto_close_log()
    {
        sc_report_close_default_log();
    }
} auto_close;

const char* sc_report::get_process_name() const
{
    return process ? process->name() : 0;
}


//
// The official handler of the exception reporting
//

void sc_report_handler::default_handler(const sc_report& rep,
                                        const sc_actions& actions)
{
    if ( actions & SC_DISPLAY )
        ::std::cout << ::std::endl << sc_report_compose_message(rep) <<
                    ::std::endl;

    if ( (actions & SC_LOG) && get_log_file_name() )
    {
        if ( !log_stream )
            log_stream = new ::std::ofstream(get_log_file_name()); // ios::trunc

        *log_stream << rep.get_time() << ": "
                    << sc_report_compose_message(rep) << ::std::endl;
    }
    if ( actions & SC_STOP )
    {
        sc_stop_here(rep.get_msg_type(), rep.get_severity());
        sc_stop();
    }
    if ( actions & SC_INTERRUPT )
        sc_interrupt_here(rep.get_msg_type(), rep.get_severity());

    if ( actions & SC_ABORT )
        abort();

    if ( actions & SC_THROW )
        throw rep;
}

// not documented, but available
bool sc_report_close_default_log()
{
    delete log_stream;
    sc_report_handler::set_log_file_name(NULL);

    if ( !log_stream )
        return false;

    log_stream = 0;
    return true;
}

int sc_report_handler::get_count(sc_severity severity_)
{
    return sev_call_count[severity_];
}

int sc_report_handler::get_count(const char* msg_type_)
{
    sc_msg_def * md = mdlookup(msg_type_);

    if ( !md )
        md = add_msg_type(msg_type_);

    return md->call_count;
}

int sc_report_handler::get_count(const char* msg_type_, sc_severity severity_)
{
    sc_msg_def * md = mdlookup(msg_type_);

    if ( !md )
        md = add_msg_type(msg_type_);

    return md->sev_call_count[severity_];
}


//
// CLASS: sc_report_handler
// implementation
//

sc_msg_def * sc_report_handler::mdlookup(const char * msg_type_)
{
    for ( msg_def_items * item = messages; item; item = item->next )
    {
        for ( int i = 0; i < item->count; ++i )
            if ( !strcmp(msg_type_, item->md[i].msg_type) )
                return item->md + i;
    }
    return 0;
}

// The calculation of actions to be executed
sc_actions sc_report_handler::execute(sc_msg_def* md, sc_severity severity_)
{
    sc_actions actions = md->sev_actions[severity_]; // high prio

    if ( SC_UNSPECIFIED == actions ) // middle prio
        actions = md->actions;

    if ( SC_UNSPECIFIED == actions ) // the lowest prio
        actions = sev_actions[severity_];

    actions &= ~suppress_mask; // higher than the high prio
    actions |= force_mask; // higher than above, and the limit is the highest

    unsigned * limit = 0;
    unsigned * call_count = 0;

    // just increment counters and check for overflow
    if ( md->sev_call_count[severity_] < UINT_MAX )
        md->sev_call_count[severity_]++;
    if ( md->call_count < UINT_MAX )
        md->call_count++;
    if ( sev_call_count[severity_] < UINT_MAX )
        sev_call_count[severity_]++;

    if ( md->limit_mask & (1 << (severity_ + 1)) )
    {
        limit = md->sev_limit + severity_;
        call_count = md->sev_call_count + severity_;
    }
    if ( !limit && (md->limit_mask & 1) )
    {
        limit = &md->limit;
        call_count = &md->call_count;
    }
    if ( !limit )
    {
        limit = sev_limit + severity_;
        call_count = sev_call_count + severity_;
    }
    if ( *limit == 0 )
    {
        // stop limit disabled
    }
    else if ( *limit != UINT_MAX )
    {
        if ( *call_count >= *limit )
            actions |= SC_STOP; // force sc_stop()
    }
    return actions;
}

void sc_report_handler::report(sc_severity severity_,
                               const char * msg_type_,
                               const char * msg_,
                               const char * file_,
                               int line_)
{
    sc_msg_def * md = mdlookup(msg_type_);

    if ( !md )
        md = add_msg_type(msg_type_);

    sc_actions actions = execute(md, severity_);
    sc_report rep(severity_, md, msg_, file_, line_);

    if ( actions & SC_CACHE_REPORT )
        cache_report(rep);

    handler(rep, actions);
}

// The following method is never called by the simulator.

void sc_report_handler::initialize()
{
#if 0 // actually, i do not know whether we have to reset these.
    suppress();
    force();
    set_actions(SC_INFO,    SC_DEFAULT_INFO_ACTIONS);
    set_actions(SC_WARNING, SC_DEFAULT_WARNING_ACTIONS);
    set_actions(SC_ERROR,   SC_DEFAULT_ERROR_ACTIONS);
    set_actions(SC_FATAL,   SC_DEFAULT_FATAL_ACTIONS);
#endif

    sev_call_count[SC_INFO]    = 0;
    sev_call_count[SC_WARNING] = 0;
    sev_call_count[SC_ERROR]   = 0;
    sev_call_count[SC_FATAL]   = 0;

    msg_def_items * items = messages;

    while ( items != &msg_terminator )
    {
        for ( int i = 0; i < items->count; ++i )
        {
            items->md[i].call_count = 0;
            items->md[i].sev_call_count[SC_INFO]    = 0;
            items->md[i].sev_call_count[SC_WARNING] = 0;
            items->md[i].sev_call_count[SC_ERROR]   = 0;
            items->md[i].sev_call_count[SC_FATAL]   = 0;
        }
        items = items->next;
    }

    // PROCESS ANY ENVIRONMENTAL OVERRIDES:

    const char* deprecation_warn = std::getenv("SC_DEPRECATION_WARNINGS");
    if ( (deprecation_warn!=0) && !strcmp(deprecation_warn,"DISABLE") )
    {
        set_actions("/IEEE_Std_1666/deprecated", SC_DO_NOTHING);
    }
}

// free the sc_msg_def's allocated by add_msg_type
// (or implicit msg_type registration: set_actions, abort_after)
// clear last_global_report.
void sc_report_handler::release()
{
    if ( last_global_report )
        delete last_global_report;
    last_global_report = 0;
    sc_report_close_default_log();

    msg_def_items * items = messages, * newitems = &msg_terminator;
    messages = &msg_terminator;

    while ( items != &msg_terminator )
    {
        for ( int i = 0; i < items->count; ++i )
            if ( items->md[i].msg_type == items->md[i].msg_type_data )
                free(items->md[i].msg_type_data);

        msg_def_items * prev = items;
        items = items->next;

        if ( prev->allocated )
        {
            delete [] prev->md;
            delete prev;
        }
        else
        {
            prev->next = newitems;
            newitems = prev;
        }
    }
    messages = newitems;
}

sc_msg_def * sc_report_handler::add_msg_type(const char * msg_type_)
{
    sc_msg_def * md = mdlookup(msg_type_);

    if ( md )
        return md;

    msg_def_items * items = new msg_def_items;

    if ( !items )
        return 0;

    items->count = 1;
    items->md = new sc_msg_def[items->count];

    if ( !items->md )
    {
        delete items;
        return 0;
    }
    memset(items->md, 0, sizeof(sc_msg_def) * items->count);
    items->md->msg_type_data = strdup(msg_type_);
    items->md->id = -1; // backward compatibility with 2.0+

    if ( !items->md->msg_type_data )
    {
        delete items->md;
        delete items;
        return 0;
    }
    items->md->msg_type = items->md->msg_type_data;
    add_static_msg_types(items);
    items->allocated = true;

    return items->md;
}

void sc_report_handler::add_static_msg_types(msg_def_items * items)
{
    items->allocated = false;
    items->next = messages;
    messages = items;
}

sc_actions sc_report_handler::set_actions(sc_severity severity_,
        sc_actions actions_)
{
    sc_actions old = sev_actions[severity_];
    sev_actions[severity_] = actions_;
    return old;
}

sc_actions sc_report_handler::set_actions(const char * msg_type_,
        sc_actions actions_)
{
    sc_msg_def * md = mdlookup(msg_type_);

    if ( !md )
        md = add_msg_type(msg_type_);

    sc_actions old = md->actions;
    md->actions = actions_;

    return old;
}

sc_actions sc_report_handler::set_actions(const char * msg_type_,
        sc_severity severity_,
        sc_actions actions_)
{
    sc_msg_def * md = mdlookup(msg_type_);

    if ( !md )
        md = add_msg_type(msg_type_);

    sc_actions old = md->sev_actions[severity_];
    md->sev_actions[severity_] = actions_;

    return old;
}

int sc_report_handler::stop_after(sc_severity severity_, int limit)
{
    int old = sev_limit[severity_];

    sev_limit[severity_] = limit < 0 ? UINT_MAX: limit;

    return old;
}

int sc_report_handler::stop_after(const char * msg_type_, int limit)
{
    sc_msg_def * md = mdlookup(msg_type_);

    if ( !md )
        md = add_msg_type(msg_type_);

    int old = md->limit_mask & 1 ? md->limit: UINT_MAX;

    if ( limit < 0 )
        md->limit_mask &= ~1;
    else
    {
        md->limit_mask |= 1;
        md->limit = limit;
    }
    return old;
}

int sc_report_handler::stop_after(const char * msg_type_,
                                  sc_severity severity_,
                                  int limit)
{
    sc_msg_def * md = mdlookup(msg_type_);

    if ( !md )
        md = add_msg_type(msg_type_);

    int mask = 1 << (severity_ + 1);
    int old = md->limit_mask & mask ?  md->sev_limit[severity_]: UINT_MAX;

    if ( limit < 0 )
        md->limit_mask &= ~mask;
    else
    {
        md->limit_mask |= mask;
        md->sev_limit[severity_] = limit;
    }
    return old;
}

sc_actions sc_report_handler::suppress(sc_actions mask)
{
    sc_actions old = suppress_mask;
    suppress_mask = mask;
    return old;
}

sc_actions sc_report_handler::suppress()
{
    return suppress(0);
}

sc_actions sc_report_handler::force(sc_actions mask)
{
    sc_actions old = force_mask;
    force_mask = mask;
    return old;
}

sc_actions sc_report_handler::force()
{
    return force(0);
}

void sc_report_handler::set_handler(sc_report_handler_proc handler_)
{
    handler = handler_ ? handler_: &sc_report_handler::default_handler;
}

sc_report* sc_report_handler::get_cached_report()
{
    sc_process_b * proc = sc_get_current_process_b();

    if ( proc )
        return proc->get_last_report();

    return last_global_report;
}

void sc_report_handler::clear_cached_report()
{
    sc_process_b * proc = sc_get_current_process_b();

    if ( proc )
        proc->set_last_report(0);
    else
    {
        if ( last_global_report )
            delete last_global_report;
        last_global_report = 0;
    }
}

sc_actions sc_report_handler::get_new_action_id()
{
    for ( sc_actions p = 1; p; p <<= 1 )
    {
        if ( !(p & available_actions) ) // free
        {
            available_actions |= p;
            return p;
        }
    }
    return SC_UNSPECIFIED;
}

bool sc_report_handler::set_log_file_name(const char* name_)
{
    if ( !name_ )
    {
        free(log_file_name);
        log_file_name = 0;
        return false;
    }
    if ( log_file_name )
        return false;

    log_file_name = strdup(name_);
    return true;
}

const char * sc_report_handler::get_log_file_name()
{
    return log_file_name;
}

void sc_report_handler::cache_report(const sc_report& rep)
{
    sc_process_b * proc = sc_get_current_process_b();
    if ( proc )
        proc->set_last_report(new sc_report(rep));
    else
    {
        if ( last_global_report )
            delete last_global_report;
        last_global_report = new sc_report(rep);
    }
}

//
// backward compatibility with 2.0+
//

sc_msg_def * sc_report_handler::mdlookup(int id)
{
    for ( msg_def_items * item = messages; item; item = item->next )
    {
        for ( int i = 0; i < item->count; ++i )
            if ( id == item->md[i].id )
                return item->md + i;
    }
    return 0;
}

//
// CLASS: sc_report_handler
// static variables
//

sc_actions sc_report_handler::suppress_mask = 0;
sc_actions sc_report_handler::force_mask = 0;

sc_actions sc_report_handler::sev_actions[SC_MAX_SEVERITY] =
{
    /* info  */ SC_DEFAULT_INFO_ACTIONS,
    /* warn  */ SC_DEFAULT_WARNING_ACTIONS,
    /* error */ SC_DEFAULT_ERROR_ACTIONS,
    /* fatal */ SC_DEFAULT_FATAL_ACTIONS
};

// Note that SC_FATAL has a limit of 1 by default

sc_actions sc_report_handler::sev_limit[SC_MAX_SEVERITY] =
{
    UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX
};
sc_actions sc_report_handler::sev_call_count[SC_MAX_SEVERITY] = { 0, 0, 0, 0 };

sc_report* sc_report_handler::last_global_report = NULL;
sc_actions sc_report_handler::available_actions =
    SC_DO_NOTHING |
    SC_THROW |
    SC_LOG |
    SC_DISPLAY |
    SC_CACHE_REPORT |
    SC_INTERRUPT |
    SC_STOP |
    SC_ABORT;

sc_report_handler_proc sc_report_handler::handler =
    &sc_report_handler::default_handler;

char * sc_report_handler::log_file_name = 0;

sc_report_handler::msg_def_items * sc_report_handler::messages =
    &sc_report_handler::msg_terminator;


//
// predefined messages
//

const char SC_ID_REGISTER_ID_FAILED_[] = "register_id failed";
const char SC_ID_UNKNOWN_ERROR_[]      = "unknown error";
const char SC_ID_WITHOUT_MESSAGE_[]    = "";
const char SC_ID_NOT_IMPLEMENTED_[]    = "not implemented";
const char SC_ID_INTERNAL_ERROR_[]     = "internal error";
const char SC_ID_ASSERTION_FAILED_[]   = "assertion failed";
const char SC_ID_OUT_OF_BOUNDS_[]      = "out of bounds";

#define DEFINE_MSG(id,n)                                                     \
    {                                                                        \
	(id),                                                                \
	0u, {0u}, /* actions */                                              \
	0u, {0u}, 0u, /* limits */                                           \
	0u, {0u}, NULL, /* call counters */                                  \
	n                                                                    \
    }

static sc_msg_def default_msgs[] =
{
    DEFINE_MSG(SC_ID_REGISTER_ID_FAILED_, 800),
    DEFINE_MSG(SC_ID_UNKNOWN_ERROR_, 0),
    DEFINE_MSG(SC_ID_WITHOUT_MESSAGE_, 1),
    DEFINE_MSG(SC_ID_NOT_IMPLEMENTED_, 2),
    DEFINE_MSG(SC_ID_INTERNAL_ERROR_, 3),
    DEFINE_MSG(SC_ID_ASSERTION_FAILED_, 4),
    DEFINE_MSG(SC_ID_OUT_OF_BOUNDS_, 5)
};

sc_report_handler::msg_def_items sc_report_handler::msg_terminator =
{
    default_msgs,
    sizeof(default_msgs)/sizeof(*default_msgs),
    false,
    NULL
};

} // namespace sc_core