Overview

The RoseErrorContext class is used for error handling and holds thresholds for controlling the display of messages, and can also hold a table of RoseError messages for lookup by numeric code.

The ROSE library defines two contexts. The rose_ec() context controls general library messages and provides the system-wide defaults for the reporting thresholds. The rose_io_ec() context is used for file parsing messages so that they can be shown even if normal library messages are hidden.

RoseErrorContext Constructor

RoseErrorContext();
RoseErrorContext(
	RoseError * msgs,  /* message array */
	unsigned msgcnt    /* message array size */
	);

The RoseErrorContext constructor can create an empty context with default threshold values, or one containing an array of predefined RoseError messages. The numeric RoseErrorCode values within the predefined messages can be used to report issues.

The following code creates a context with some predefined error messages. The context object is created the first time the function is called.

#define BAD_KEYWORD  ROSE_USER_ERROR_CODE + 100
#define NO_FILE      ROSE_USER_ERROR_CODE + 200

RoseError application_errors[] = {
{ BAD_KEYWORD, ROSE_STATUS_WARNING, Unknown keyword %s },
{ NO_FILE,     ROSE_STATUS_WARNING, Could not find %s }
};

RoseErrorContext * application_ec() {
    static RoseErrorContext * ec = 0;

    /* Create the context on the first call.  Do this rather than
     * have a global with a static ctor so that we can report
     * errors during static ctor calls if necessary.
     */
    if (!ec) {
	    ec = new RoseErrorContext 
		    (application_errors, 
		     ROSE_COUNT (application_errors));
    }
    return ec;
}

Later in your application, you can use the context to report an error by passing in the numeric code. Having all of the predefined messages in the context simplifies localization if you application has an alternative set of message strings.

application_ec()-> report (BAD_KEYWORD, "foobar");

// This will print 
// warning: Unknown keyword foobar

disable()

void disable (RoseErrorCode ec)

The enable() function finds the error information for a predefined code and stops all reporting of the message. This is equivalent to finding the RoseError structure and calling rose_error_disable()

Use the enable() function to begin reporting of a message.

// turn the warning about extra fields off and on
rose_io_ec()->disable(ROSE_IO_FIELD_COUNT);
rose_io_ec()->enable(ROSE_IO_FIELD_COUNT);

// same thing, but not using the shortcuts
rose_error_disable(rose_io_ec()->find_error(ROSE_IO_FIELD_COUNT));
rose_error_enable(rose_io_ec()->find_error(ROSE_IO_FIELD_COUNT));

enable()

void enable (RoseErrorCode ec)

The enable() function controls finds the error information for a predefined code and turns reporting back on if the message was previously being suppressed. This is equivalent to finding the RoseError structure and calling rose_error_enable()

See the disable() function for examples

exit_threshold()

void exit_threshold (RoseStatus s);
RoseStatus exit_threshold();

The exit_threshold() value is matched against the severity of a RoseError message. When this threshold is met or exceeded, the fatal_fn() hook is called to exit or otherwise try to recover. The threshold is initially ROSE_STATUS_DEFAULT, which tells the reporting code to use the threshold value found in the rose_ec() context. The rose_ec() value is normally ROSE_STATUS_FATAL.

find_error()

RoseError * find_error (RoseErrorCode code);

The find_error function searches the table of predefined RoseErrors in a context and returns the first one with the given numeric code. The function returns NULL if no error struct was found. The codes ROSE_GENERAL, ROSE_MEMORY and ROSE_BAD_ERROR_CODE have built-in RoseError structs and are always available.

get_error_by_index()

RoseError * get_error_by_index (unsigned idx);

The get_error_by_index function returns a RoseError element from the table of predefined errors held by the context. The order of elements within the table may be different than originally supplied by the constructor. The size() function returns the size of the table.

message() / warning() / error() / fatal()

void message (const char * fmat, ...);
void warning (const char * fmat, ...);
void error   (const char * fmat, ...);
void fatal   (const char * fmat, ...);

These functions report a general issue for conditions that do not have a RoseError struct or pre-defined code for the report() function. The functions take a format string an variable arguments with printf() conventions, but no trailing newline is required.

Internally, these build a temporary RoseError struct with the ROSE_GENERAL code and then use the normal reporting mechanism.

RoseErrorContext * ec;
RoseDesign * design;

ec-> message (Design %s is happy, design-> name());
ec-> warning (Design %s is not happy, design-> name());
ec-> error (Design %s is extremely unhappy, design-> name());
ec-> fatal (Design %s is so unhappy that we stop here, design-> name());

name()

const char * name();
void name(const char * n);

The name function can provide additional information for messages. If present, it will be added to the reported message after the trace string if any. For example, if the name of a context was set to "Oatmeal", messages reported using that context would appear like the following:

ROSE: Oatmeal: error: Normal summary message
ROSE: Oatmeal: warning: Normal summary message
ROSE: Oatmeal: Normal summary message

report()

void report (RoseErrorCode code, ...);
void report (const RoseError *, ...);

The report() function issues a message using a RoseError struct that is either passed as an explicit parameter or found by error code. The error struct, context, and variable arguments for the printf-style parameters within the detail message string will all be passed to the RoseErrorReporter, which will check the various thresholds held by the context to determine whether a detail message will be displayed and whether the application will quit or continue.

The following example uses the messages defined by the RoseErrorContext constructor example:

RoseErrorContext * ec;

ec-> report (BAD_KEYWORD, OPEN);
ec-> report (NO_FILE, /usr/local/widget);

report_maxcount()

void report_maxcount (unsigned i);
unsigned report_maxcount();

The report_maxcount() functions stop the error reporter from displaying a message after it has occurred a certain number of times. The limit is checked against the count in the current RoseErrorStats object held by the reporter. The limit has no effect if the reporter is not keeping statistics.

The limit is initially ROSE_MAXCOUNT_DEFAULT, which uses the value found in the rose_ec() context. The rose_ec() value is normally zero, indicating no limit.

report_threshold()

void report_threshold (RoseStatus s);
RoseStatus report_threshold();

The report_threshold() value is matched against the severity of a RoseError message. When this threshold is met or exceeded, the report_fn() hook is called to display the message. The threshold is initially ROSE_STATUS_DEFAULT, which uses the value in the rose_ec() context. The rose_ec() value is normally ROSE_OK which shows messages with any severity.

The following example sets the reporting threshold so that informational messages are not printed.

RoseErrorContext * ec;
ec-> report_threshold (ROSE_STATUS_WARNING);

size()

unsigned size();

The size function returns the number of RoseError elements in the table of predefined errors held by the context, primarily for examining all elements using get_error_by_index()