Book Contents | Book Index | Master Index | Previous Chapter | Next Chapter
Search STEP Tools Web Support

8.1 Messages, Warnings, and Errors

A ROSE application may generate Part 21 syntax error or warning messages when reading a file, as well as other useful status messages. By default, these are printed to the console via stdout or stderr , but Windows programs can easily send them to a window as described in ST-Developer Message Window.

Internally, ROSE handles all messages through a special reporter object. This object has many configuration options, and applications can replace it with a subclass of RoseErrorReporter for completely customized message handling.

Errors and warnings from ROSE are prefixed by a tag indicating the severity, and then followed by a brief explanation of the error, as shown below:

    ROSE: warning: $ROSE not set. System schemas may not be found.

Informational messages do not have any prefix, such as the banner, shown below, that prints out whenever ROSE is initialized:

    ST-DEVELOPER
    System Release v12
     
    Copyright (c) 1991-2007 by
    STEP Tools Inc., Troy, New York
    All Rights Reserved

It is possible to turn off the printing of informational messages. This might be desirable when preparing an application for production release. The RoseInterface::quiet() function turns off printing of all informational messages.

    ROSE.quiet (TRUE);     /* turn off informational messages */
    . . .
    ROSE.quiet (FALSE);    /* turn messages back on */

The RoseErrorReporter ranks messages by severity. The least severe is message, then warning, error, and fatal. The quiet() function works by setting the error reporter's print threshold so that informational messages are not reported. This threshold can be set to other levels so that, for example, only error and fatal severity messages are printed. The severity levels are given by the RoseSeverity as shown below:

    ROSE_SEV_FATAL      = 4 /* Fatal error, no recovery possible */
    ROSE_SEV_ERROR      = 3 /* Problem, unable to complete function */
    ROSE_SEV_WARNING    = 2 /* Problem, may still complete function */
    ROSE_SEV_MESSAGE    = 1 /* Application status messages */
    ROSE_SEV_NULL       = 0 /* severity unset */

The RoseErrorReporter::report_threshold() function sets the minimum severity at which messages will be printed. The default threshold is ROSE_SEV_MESSAGE . The following example has the same effect as the quiet() function. The RoseInterface::error_reporter() function returns the error reporter object from the RoseInterface object.

    ROSE.error_reporter()-> report_threshold (ROSE_SEV_WARNING);

A version of the report_threshold() function that takes no parameters returns the current threshold value, so it is possible to bump up the threshold temporarily and then reset it to the previous value:

    RoseSeverity sev;
     
    sev = ROSE.error_reporter()-> report_threshold();
    ROSE.error_reporter()-> report_threshold (ROSE_SEV_ERROR);
     
    /* some code that would generate unwanted warnings */
     
    ROSE.error_reporter()-> report_threshold (sev);

Similarly, there is a threshold that controls whether the reporter will continue or exit after receiving an error. The default exit threshold is ROSE_SEV_ERROR . The reporter continues execution after informational and warning messages, but will exit after error and fatal messages. The RoseErrorReporter::exit_threshold() function can be used to change this behavior. The following example shows how to set the exit threshold so that an application keeps executing after an error:

    /* not recommended*/
    ROSE.error_reporter()-> exit_threshold (ROSE_SEV_FATAL); 

Some functions may not be able to recover from conditions more severe than ROSE_SEV_WARNING and so the use of this function is not recommended. It may keep your application running, but you may see inconsistent or inexplicable results later on in execution.


8.2 Logging and Debugging

The ROSE error reporter can log error messages to a file. This is useful for debugging applications that has turned off message printing or on systems that do not have a proper stdout , such as Windows. Logging can be controlled from within the application or from the environment. Within an application, logging can be activated by using the RoseErrorReporter::log() and RoseErrorReporter::log_filename() functions:

    ROSE.error_reporter()-> log_filename ("logfile");
    ROSE.error_reporter()-> log();         /* turn it on */
     
    . . .
     
    ROSE.error_reporter()-> log (FALSE);   /* turn it off */

This fine-grained control may be useful in some situations, but the most common use of logging is to record an entire application run. The $ROSE_LOG environment variable controls logging from the command line. Set $ROSE_LOG to the name of a log file to turn on logging. The file will be opened in "append" mode and all messages will be added to it. If you have several ROSE applications running at the same time, they will all write to the file.

    % setenv ROSE_LOG  logfile     -- Turns on logging
    % unsetenv ROSE_LOG            -- Turns off logging

Any message that is reported will be logged. By default, this threshold is set to ROSE_SEV_MESSAGE , and this is the threshold used when logging with the $ROSE_LOG mechanism. Setting the report threshold is only possible from within the application, but setting the $ROSE_DEBUG environment variable will override any threshold settings and print all messages.

    % setenv ROSE_DEBUG  foo        -- Force reporting of all messages
    % unsetenv ROSE_DEBUG           -- Back to normal reporting

This feature is useful for tracking down problems in an execution that does not print many messages.


8.3 Error Reporting

The RoseErrorReporter can report predefined as well as ad-hoc errors. Predefined errors are RoseError objects associated with a RoseErrorContext object. These RoseError objects define a numeric code, severity, and printf-style message for each error. They may be reported by passing the numeric code to the RoseInterface::report() or the RoseErrorContext::report() functions. The error contexts group errors and provide additional control over reporting parameters. For example, the ROSE library defines contexts for general system errors and STEP Part 21 file errors, returned by the rose_ec() and rose_io_ec() functions, respectively. The context for the Part 21 files sets separate thresholds to make sure that file error messages are always seen.

The predefined system errors used by the ROSE library are listed in Section 8.4. In addition to the predefined errors, ad-hoc errors can be reported with the RoseInterface::error() , RoseInterface::warning() , and RoseInterface::message() functions, or the corresponding messages on the RoseErrorContext class. The report() , error() , warning() , and message() functions on RoseInterface are the same as the equivalent function on the rose_ec() error context. Note in the following examples that a trailing newline " \n " is omitted. The report routines add one automatically.

    ROSE.warning ("Could not open file %s.", filename);
    rose_ec()-> warning ("Could not open file %s.", filename);
     
    ROSE.error ("Out of memory!");
    rose_ec()-> error ("Out of memory!");
     
    ROSE.report (ROSE_EC_NO_DESIGN, designname);
    rose_ec()-> report (ROSE_EC_NO_DESIGN, designname);

When an error of ROSE_SEV_ERROR severity is reported, the code and matching context are saved and can be queried with RoseInterface::errcode() and RoseInterface::errcontext() . Warnings and messages do not set errcode() . These can be cleared with the RoseInterface::error_reset() function.

The errcode() method returns the numeric code for the last error seen, or zero ( ROSE_OK ) if there was no error. If the error was a general one reported through the error() member function, the code returned is ROSE_GENERAL . The errcontext() function returns the context object that defines the error. The error_reset() function can be used to clear the error status.


Trace Information

When an error message is printed, the RoseErrorReporter can prepend some trace information to the message. The reporter keeps a stack of special traceobjects that provide this information. When printing a message, the reporter will get a trace string from the top object. If the top object is null, no trace string is added.

The trace objects are derived from the RoseErrorTrace class. The location() virtual function provides trace information that is used as a prefix for error messages. Use these to indicate a location in a file, an application name, or whatever. There are subclasses for files and other named locations.

    class RoseErrorTrace        /* base class */
    class RoseErrorNamedTrace   /* prepends: name: */
    class RoseErrorFileTrace    /* prepends: "filename":<line>: */

To use the trace objects, create them and then push them on the reporter stack using the push_trace() function. Any message that is printed will use the location information from the top object. When done, pop it off using the pop_trace() function. The following example shows how to prepend the application name to every message using the RoseErrorNamedTrace class:

    RoseErrorNamedTrace trace;
    trace.name (argv[0]);
    ROSE.error_reporter()-> push_trace (&trace);
    [ . . .]
    ROSE.error_reporter()-> pop_trace();

The following example shows how to prepend a file name and line number to every message using the RoseErrorFileTrace class:

    RoseErrorFileTrace trace;
    trace.file ("filename");
    trace.line (0);
    ROSE.error_reporter()-> push_trace (&trace);
    [ . . .]
    trace-> increment_line();
    [ . . .]
    ROSE.error_reporter()-> pop_trace();

The following example shows how to temporarily remove all trace information from the messages by pushing a null trace object on the stack:

    ROSE.error_reporter()-> push_trace (0);
    [ . . .]
    ROSE.error_reporter()-> pop_trace();


8.4 ROSE Library Predefined Errors

These are the predefined errors, warnings and messages that may appear while processing any of the core system functions. The errors and warnings are prefixed with ROSE_EC while the messages are prefixed by ROSE_MSG . These errors are defined in rose_errors.h .

Error Code

Severity

Error Message

    ROSE_EC_BAD_ATT
    WARNING
    "Attribute %s.%s not found."
    ROSE_EC_BAD_BINCHAR
    WARNING
    "Bad hex character '%c' for binary value. Using '0'."
    ROSE_EC_BAD_BINSTART
    WARNING
    "Bad first character '%c' for binary value. Expecting 0, 1, 2, or 3."
    ROSE_EC_BAD_CLASS
    WARNING
    "Class %s not found."
    ROSE_EC_BAD_DOMAIN
    WARNING
    "Domain %s not found."
    ROSE_EC_BAD_HASH
    ERROR
    "Could not find hash insertion point."
    ROSE_EC_BAD_NODETYPE
    ERROR
    "Unknown RoseNodeType %d found."
    ROSE_EC_BAD_SCHEMA
    WARNING
    "Schema %s not found."
    ROSE_EC_EXTRA_OBJECTS
    WARNING
    "Design contains extra '%s' objects."
    ROSE_EC_FREAKY_ENUM
    ERROR
    "Found enum of size (%d).Expected: %d %d or %d"
    ROSE_EC_FREAKY_PRIM
    ERROR
    "Found primitive value of size (%d).Expected: %d %d or %d"
    ROSE_EC_GEN_DOMAIN
    WARNING
    "Generating domain%s - %s."
    ROSE_EC_GEN_DUP_SCHEMA
    WARNING
    "Generating schema - schema '%s' is in search path, generating from scratch."
    ROSE_EC_GEN_NULL_SCHEMA
    WARNING
    "Generating schema - schema name cannot be null."
    ROSE_EC_GEN_SCHEMA
    WARNING
    "Generating schema - creating schema '%s'."
    ROSE_EC_INVALID_CHANGE
    ERROR
    "Change value not allowed on '%s' object"
    ROSE_EC_INVALID_INSERT
    ERROR
    "Insert not allowed on '%s' object"
    ROSE_EC_INVALID_REMOVE
    ERROR
    "Remove not allowed on '%s' object"
    ROSE_EC_LOCKED_DESIGN
    WARNING
    "Attempt to modify read-only design '%s'."
    ROSE_EC_MUST_OVERRIDE
    ERROR
    "%s::%s: Method must be overridden."
    ROSE_EC_NESTED_TRAVERSAL
    ERROR
    "Traversal already in progress, nested traversals not allowed."
    ROSE_EC_NOT_IMPLEMENTED
    ERROR
    "%s::%s: Sorry, method not yet implemented."
    ROSE_EC_NO_ATT
    WARNING
    "No attribute specified."
    ROSE_EC_NO_COPY_CTOR
    WARNING
    "No copy ctors for 'best-fit' classes. '%s' copied as a '%s'."
    ROSE_EC_NO_CTOR
    ERROR
    "Class '%s' has no creator function."
    ROSE_EC_NO_DESIGN
    WARNING
    "Problems reading design '%s'"
    ROSE_EC_NO_FORMAT
    WARNING
    "Format '%s' not available, no such repository present."
    ROSE_EC_NO_KEYSTONE_OID
    WARNING
    "No OID for built-in type '%s'"
    ROSE_EC_NO_MEMORY
    FATAL
    "Out of memory, can not continue."
    ROSE_EC_NO_PROTO
    ERROR
    "Class '%s' has no prototype."
    ROSE_EC_NO_REPO
    WARNING
    "Repository '%s' not found."
    ROSE_EC_OID_BOOT
    ERROR
    "Problems creating ROSE oid index."
    ROSE_EC_OID_EXISTS
    ERROR
    "Object with the requested OID already exists in design '%s'."
    ROSE_EC_OID_FAILED
    ERROR
    "Could not generate unique OID."
    ROSE_EC_RTP_AFTER_BOOT
    ERROR
    "RoseTypePtrs cannot be created after ROSE is initialized."
    ROSE_EC_RTP_ON_HEAP
    FATAL
    "RoseTypePtrs must be statically created."
    ROSE_EC_UNREGISTERED_REPO
    WARNING
    "Repository of type '%s' was not registered."
    ROSE_MSG_READING_FORMAT
    MESSAGE
    "Reading in %s format"
    ROSE_MSG_WRITING_FORMAT
    MESSAGE
    "Writing in %s format"
     
| Book Contents | Book Index | Master Index | ST-Developer Home | Previous Chapter | Next Chapter |