CoCoALib-0.9905 date: 23 May 2007

CoCoA::ErrorInfo Class Reference

#include <error.H>

Inheritance diagram for CoCoA::ErrorInfo:

Inheritance graph
List of all members.

Public Member Functions

 ErrorInfo (const std::string &mesg, const std::string &func)
 ErrorInfo (const std::string &mesg, const std::string &func, const char *file, unsigned long line)
 ErrorInfo (ERR::code id, const std::string &func)
 ErrorInfo (ERR::code id, const std::string &func, const char *file, unsigned long line)
 ~ErrorInfo () throw ()
const ERR::codecode () const
const char * what () const throw ()


void ANNOUNCE (const ErrorInfo &err)

Detailed Description

      Copyright (c)  2005 John Abbott
      Permission is granted to copy, distribute and/or modify this document
      under the terms of the GNU Free Documentation License, Version 1.2;
      with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
      A copy of the licence is included in the file COPYING in this directory.

User documentation for files error.H and error.C

Choosing the language for error messages

You may choose the language for CoCoALib error messages: the default is
English.  If an error message has not yet been translated into the
chosen language then it is replaced by the default english message.
Currently there are only two choices:

  int main()
    CoCoA::ErrorLanguage::italian(); // vogliamo messaggi d'errore in italiano

Recommended way of reporting errors

Usually if you have detected an error in your program, you want to
report it immediately.  We recommend that you use the macro CoCoA_ERROR
to do this.  Here's an example:

    value_t operator/(const value_t& num, const value_t& den)
      if (IsZero(den))
        CoCoA_ERROR(ERR::DivByZero, "operator/ for value_t");

The first argument should be an error code (i.e. ERR::something); you
can find a list of the codes in the file (CoCoA_ROOT)/include/CoCoA/error.H
If no code is suitable, you can just put a string constant instead.
The second argument should be an indication of the function in which the
error occurred.

Information about errors -- for the more advanced

The macro CoCoA_ERROR does two things:
 (1) it creates a CoCoA::ErrorInfo object with the parameters given to
     the macro, and also with the filename and line number;
 (2) it calls the function CoCoA::error on the ErrorInfo object just created.
Below we explain these two stages in more detail.

The class CoCoA::ErrorInfo is intended to be used for creating exception
objects -- indeed, it derives from std::exception.  There are two things
you are likely to want to do with exception objects:

 (1)  create and throw the exception object
 (2)  catch the exception object

Case (1) Rather than using "throw" directly, we recommend that you pass the
  error object to the function CoCoA::error as it makes debugging
  easier (in gdb: "break CoCoA::error", then "up" to the offending line).
  We also recommend that you use the constructor which takes a
  CoCoA::ERR::code and a string; the string should indicate where the
  error was detected, e.g. the name of the C++ function which found
  the error.  Look through the list of CoCoA::ERR::codes (in the file
  error.H) to find the one best suited to the type of error you wish
  to signal.

  If no error CoCoA::ERR::code is suitable then you may use the
  constructor which accepts two C string arguments: the first should be
  a description of the error (e.g. "Incompatible hypermatrix
  dimensions"), and the second should indicate where the error was
  detected.  If you are a CoCoALib contributor, see the notes below
  about how to add a new error code and message.

  NOTE: if you set the C++ preprocessor symbol CoCoA_DEBUG to a value
    greater than 1 then a log message is produced each time CoCoA::error
    is called; the log message is printed on CoCoA::GlobalLogput.

Case (2) After catching a CoCoA::ErrorInfo object in the variable [err]
  you can make the following queries:
    err.code()  -- returns the ERR::code object associated with the error
    err.what()  -- returns a C string being the error message;

  EXAMPLE (of handling a CoCoA Error):
     try { ... }
     catch (CoCoA::ErrorInfo& err)
       if (err.code() != ERR::DivByZero) throw; // rethrow unexpected error
       // code to handle the "expected" division by zero error

  If you have caught a CoCoA::ErrorInfo object and want to announce it as an
  error then call the procedure CoCoA::ANNOUNCE with the ErrorInfo as
  argument.  This will print an eye-catching error announcement on
  CoCoA::GlobalErrput (see file io.txt) and then return to the caller.
  Note that CoCoA::ANNOUNCE does not cause the program to exit/abort.

  To facilitate debugging, an ErrorInfo object may be printed in the usual
  way; this produces a modest message, clearly different from an error

As for any other "exception object", simply creating a CoCoA::ErrorInfo
object does not cause the error condition to be signalled.  To signal
the error pass the error object to the function CoCoA::error which will
then use C++'s throw mechanism -- using C++'s throw mechanism directly
may make debugging less simple (it is easy to tell the debugger to
intercept a call to CoCoA::error).

Adding a New Error Code and its Message

If you are a CoCoALib contributor and want to add a new error message
(or even a new language for error messages), please read the maintainer
documentation for what to do.

Maintainer documentation for files error.H and error.C

CoCoA::ErrorInfo is derived from std::exception for compatibility with the
rest of C++.  How this might be useful I cannot yet say, but it does not
measurably complicate the code.

The preferred constructors for ErrorInfo are those accepting an
ERR::code and a C string indicating context (with or without filename
and line numerb information); the other constructors should be used
only when no suitable ERR::code exists.

Note that the conversion from ERR::code to a string is slightly
convoluted: this is to allow the possibility of selecting at run-time a
language other than English for the error messages.

I chose not to offer a ErrorInfo constructor which accepts natively
"const char*" args because the potential extra copying of strings (to
construct a std::string) is hardly likely to be important, and
std::strings feel much cleaner.

The nature and context of the error are kept separate in an ErrorInfo
object since it is possible that we may wish to propagate the nature of the
error to top level in an interactive system where it would be unhelpful
or confusing to refer to some C++ function irrelevant to the user.

The definition of the function CoCoA::error is quite straightforward.
The function is deliberately not inline: efficiency is wholly
unimportant whereas the ability to set a breakpoint in the function is
[some debuggers may be unable to set a breakpoint in an inline function]

Each CoCoA error code is in reality a constant global variable
containing a pointer to a C string constant: the contents of the string
are the associated error message in English.  The identity of the error
code resides in the address of that specific string constant -- another
ERR::message object referring to another string which happens to have
the same contents would be regarded as a different error code.  Rather
than use a naked "const char* const" I chose to define a class
(ERR::message, also typedefed to ERR::code) for these "error variables"
to highlight the fact that they are not equivalent to any old string.
Of course, a C string can be converted explicitly into an ERR::message
by calling the constructor, but this is not to be encouraged (which is
why I made the constructor "explicit").  There are comparison operators
(equal, not-equal, and less than) for ERR::message; less-than is needed
for using C++ maps when implementing error messages in languages other
than english.  These comparison operators merely conduct the required
comparison on the values of the C string POINTERS: in particular the
contents of the strings pointed to are not taken into consideration!

To Add a New Error Code and Message

Invent a new name for the error code, and insert it in the list of names
of "error variables" (in the file error.H).  Make sure you insert it
in the right place respecting alphabetical order -- this way it is easy
to check whether a name is already present in the list.  Add a short
comment indicating what sort of error that code is to be used for.

Next you must add a message corresponding to that code.  In the file
error.C you will find a long list of "error variable" initializations.
Add an initialization for your new "error variable" -- the syntax is
quite obvious from the other initializations there.  You may wish to
add translations of your new error message into the other languages
present in error.C.

To Add a New Language for Error Messages

You must write a function analogous to the function italian() which
resides inside the namespace CoCoA::ErrorLanguage.  The new function
must have a name different from the other functions there: I suggest the
english name of the language.  Inside the function you will have to fill
a MsgTable_t object with the translated messages associated to each
possible error code.  At the end you should check to make sure that you
have a message for each possible code: it should suffice simply to count
them.  The code will still compile and run even if some translated
messages are missing: if an error occurs for which the current error
language has no translation then the english message is printed.

  Suppose we want to add german error messages.  We choose to use
  the name "german" for the function which activates german error
  messages.  Here is what we do:
  (1) edit error.H;
      immediately after the line containing "void italian();" insert
      "void german();"

  (2) edit error.C;
      make a copy of the function italian(){...} and change its name
      to "german" -- make sure you stay inside namespace ErrorLanguage;
      translate all the error messages in the strings.

Bugs, Shortcomings, and other ideas

The throw specifications on the destructor and "what" member function
are needed for compatibility with std::exception -- I regard this as
a nuisance.  I wonder if std::string::c_str can throw?

What about parameter values?  In some cases it would be handy to give
the bad value which caused the error: e.g. "Bad characteristic: 33".
A problem is that a parameter value could be very large.  We could
simply allow up to 1000 (say) characters of parameter information in
a suitable string.

Only very few error messages have been translated into italian so far.

NOTE: Several fairly simple tests have not revealed any significant run-time
overhead when using exceptions.  Should we use exceptions from the standard
library?  Any code which is not exception-safe should be clearly marked.
Note that writing exception-safe code requires thought!

Definition at line 152 of file error.H.

Constructor & Destructor Documentation

CoCoA::ErrorInfo::ErrorInfo const std::string &  mesg,
const std::string &  func

CoCoA::ErrorInfo::ErrorInfo const std::string &  mesg,
const std::string &  func,
const char *  file,
unsigned long  line

CoCoA::ErrorInfo::ErrorInfo ERR::code  id,
const std::string &  func

CoCoA::ErrorInfo::ErrorInfo ERR::code  id,
const std::string &  func,
const char *  file,
unsigned long  line

CoCoA::ErrorInfo::~ErrorInfo  )  throw () [inline]

Definition at line 159 of file error.H.

Member Function Documentation

const ERR::code& CoCoA::ErrorInfo::code  )  const [inline]

Definition at line 160 of file error.H.

const char* CoCoA::ErrorInfo::what  )  const throw () [inline]

Definition at line 161 of file error.H.

Friends And Related Function Documentation

void ANNOUNCE const ErrorInfo err  )  [friend]

The documentation for this class was generated from the following file:
Generated on Wed May 23 13:46:18 2007 for CoCoALib by  doxygen 1.4.6