/* -*- mode: C -*- */
/*
IGraph library.
Copyright (C) 2003, 2004, 2005 Gabor Csardi <csardi@rmki.kfki.hu>
MTA RMKI, Konkoly-Thege Miklos st. 29-33, Budapest 1121, Hungary
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef IGRAPH_ERROR_H
#define IGRAPH_ERROR_H
#undef __BEGIN_DECLS
#undef __END_DECLS
#ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
#else
# define __BEGIN_DECLS /* empty */
# define __END_DECLS /* empty */
#endif
__BEGIN_DECLS
/* This file contains the igraph error handling.
* Most bits are taken literally from the GSL library (with the GSL_
* prefix renamed to IGRAPH_), as I couldn't find a better way to do
* them. */
/**
* \section errorhandlers Error handlers
*
* <para>
* If \a igraph runs into an error - an invalid argument was supplied
* to a function, or we've ran out of memory - the control is
* transferred to the \emb error handler \eme function.
* </para><para>
* The default error handler is \ref igraph_error_handler_abort which
* prints an error message and aborts the program.
* </para>
* <para>
* The \ref igraph_set_error_handler() function can be used to set a new
* error handler function of type \ref igraph_error_handler_t, see the
* documentation of this type for details.
* </para>
* <para>
* There are two other predefined error handler functions,
* \ref igraph_error_handler_ignore and \ref igraph_error_handler_printignore,
* these deallocate the temporarily allocated memory (more about this
* later) and return with the error code. The latter also prints an
* error message. If you use these error handlers you need to take
* care about possible errors yourself by checking the return value of
* every \a igraph function.
* </para><para>
* Independently of the error handler installed, all functions in the
* library do their best to leave their arguments
* \em semantically unchanged if an error
* happens. By semantically we mean that the implementation of an
* object supplied as an argument might change, but its
* \quote meaning \endquote in most cases does not. The rare occasions
* when this rule is violated are documented in this manual.
* </para>
*/
/**
* \section errorcodes Error codes
*
* <para>Every \a igraph function which can fail return a
* single integer error code. Some functions are very simple and
* cannot run into any error, these may return other types, or
* \type void as well. The error codes are defined by the
* \ref igraph_i_error_type_t enumeration.
* </para>
*/
/**
* \section writing_error_handlers Writing error handlers
*
* <para>
* You can write and install error handlers simply by defining a
* function of type \ref igraph_error_handler_t and calling
* \ref igraph_set_error_handler(). This feature is useful for interface
* writers, as the \a igraph will have the chance to
* signal errors the appropriate way, eg. the R interface defines an
* error handler which calls the <function>error()</function>
* function, as required by R, while the Python interface has an error
* handler which raises an exception according to the Python way.
* </para>
* <para>
* If you want to write an error handler, your error handler should
* call \ref IGRAPH_FINALLY_FREE() to deallocate all temporary memory to
* prevent memory leaks.
* </para>
*/
/**
* \section error_handling_internals Error handling internals
*
* <para>
* If an error happens, the functions in the library call the
* \ref IGRAPH_ERROR macro with a textual description of the error and an
* \a igraph error code. This macro calls (through the \ref
* igraph_error() function) the installed error handler. Another useful
* macro is \ref IGRAPH_CHECK(), this checks the return value of its
* argument which is normally a function call, and calls \ref
* IGRAPH_ERROR if it is not \c IGRAPH_SUCCESS.
* </para>
*/
/**
* \section deallocating_memory Deallocating memory
*
* <para>
* If a function runs into an error (and the program is not aborted)
* the error handler should deallocate all temporary memory. This is
* done by storing the address and the destroy function of all temporary
* objects in a stack. The \ref IGRAPH_FINALLY function declares an object as
* temporary by placing its address in the stack. If a function returns
* with success it calls \ref IGRAPH_FINALLY_CLEAN() with the
* number of objects to remove from the stack. If an error happens
* however, the error handler should call \ref IGRAPH_FINALLY_FREE() to
* deallocate each object added to the stack. This means that the
* temporary objects allocated in the calling function (and etc.) will
* be freed as well.
* </para>
*/
/**
* \section writing_functions_error_handling Writing \a igraph functions with
* proper error handling
*
* <para>
* There are some simple rules to keep in order to have functions
* behaving well in erroneous situations. First, check the arguments
* of the functions and call \ref IGRAPH_ERROR if they are invalid. Second,
* call \ref IGRAPH_FINALLY on each dynamically allocated object and call
* \ref IGRAPH_FINALLY_CLEAN() with the proper argument. Third, use
* IGRAPH_CHECK on all function calls which can generate errors.
* </para>
* <para>
* The size of the stack used for this bookkeeping is fixed, and
* small. If you want to allocate several objects, write a destroy
* function which can deallocate all of these. See the
* <filename>adjlist.c</filename> file in the
* \a igraph source for an example.
* </para>
* <para>
* For some functions these mechanisms are simply not flexible
* enough. These functions should define their own error handlers and
* restore the error handler before they return.
* </para>
*/
/**
* \section error_handling_threads Error handling and threads
*
* <para>
* It is likely that the \a igraph error handling
* method is \em not thread-safe, mainly because of
* the static global stack which is used to store the address of the
* temporarily allocated objects. This issue might be addressed in a
* later version of \a igraph.
* </para>
*/
/**
* \typedef igraph_error_handler_t
*
* This is the type of the error handler functions.
* \param reason Textual description of the error.
* \param file The source file in which the error is noticed.
* \param line The number of the line in the source file which triggered
* the error
* \param igraph_errno The \a igraph error code.
*/
typedef void igraph_error_handler_t (const char * reason, const char * file,
int line, int igraph_errno);
/**
* \var igraph_error_handler_abort
*
* The default error handler, prints an error message and aborts the
* program.
*/
extern igraph_error_handler_t igraph_error_handler_abort;
/**
* \var igraph_error_handler_ignore
*
* This error handler frees the temporarily allocated memory and returns
* with the error code.
*/
extern igraph_error_handler_t igraph_error_handler_ignore;
/**
* \var igraph_error_handler_printignore
*
* Frees temporarily allocated memory, prints an error message to the
* standard error and returns with the error code.
*/
extern igraph_error_handler_t igraph_error_handler_printignore;
/**
* \function igraph_set_error_handler
*
* Installs a new error handler. If called with 0, it installs the
* default error handler (which is currently
* \ref igraph_error_handler_abort).
* \param new_handler The error handler function to install.
* \return the old error handler function. This should be saved and
* restored if \p new_handler is not needed any
* more.
*/
igraph_error_handler_t*
igraph_set_error_handler(igraph_error_handler_t new_handler);
/**
* \typedef igraph_i_error_type_t
* \enumval IGRAPH_SUCCESS The function successfully completed its task.
* \enumval IGRAPH_FAILURE Something went wrong. You'll almost never
* meet this error as normally more specific error codes are used.
* \enumval IGRAPH_ENOMEM There wasn't enough memory to allocate memory
* on the heap.
* \enumval IGRAPH_PARSEERROR A parse error was found in a file.
* \enumval IGRAPH_EINVAL A parameter's value is invalid. Eg. negative
* number was specified as the number of vertices.
* \enumval IGRAPH_EXISTS A graph/vertex/edge attribute is already
* installed with the given name.
* \enumval IGRAPH_EINVEVECTOR Invalid vector of vertex ids. A vertex id
* is either negative or bigger than the number of vertices minus one.
* \enumval IGRAPH_EINVVID Invalid vertex id, negative or too big.
* \enumval IGRAPH_NONSQUARE A non-square matrix was received while a
* square matrix was expected.
* \enumval IGRAPH_EINVMODE Invalid mode parameter.
* \enumval IGRAPH_EFILE A file operation failed. Eg. a file doesn't exist,
* or the user ha no rights to open it.
* \enumval IGRAPH_EUNFOLDINF Attempted to unfold an infinite iterator.
* \enumval IGRAPH_UNIMPLEMENTED Attempted to call an unimplemented or
* disabled (at compile-time) function.
* \enumval IGRAPH_DIVERGED A numeric algorithm failed to converge.
*/
typedef enum {
IGRAPH_SUCCESS = 0,
IGRAPH_FAILURE = 1,
IGRAPH_ENOMEM = 2,
IGRAPH_PARSEERROR = 3,
IGRAPH_EINVAL = 4,
IGRAPH_EXISTS = 5,
IGRAPH_EINVEVECTOR = 6,
IGRAPH_EINVVID = 7,
IGRAPH_NONSQUARE = 8,
IGRAPH_EINVMODE = 9,
IGRAPH_EFILE = 10,
IGRAPH_EUNFOLDINF = 11,
IGRAPH_UNIMPLEMENTED = 12,
IGRAPH_INTERRUPTED = 13,
IGRAPH_DIVERGED = 14,
} igraph_i_error_type_t;
/**
* \define IGRAPH_ERROR
*
* This macro is called if an error is noticed. It calls
* \ref igraph_error() with the proper parameters and if that returns
* the macro returns the "calling" function as well, with the error
* code. If for some (suspicious) reason you want to call the error
* handler without returning from the current function, call
* \ref igraph_error() directly.
* \param reason Textual description of the error. This should be
* something more explaning than the text associated with the error
* code. Eg. if the error code is \c IGRAPH_EINVAL,
* its asssociated text (see \ref igraph_strerror()) is "Invalid
* value" and this string should explain which parameter was invalid
* and maybe why.
* \param igraph_errno The \a igraph error code.
*/
#define IGRAPH_ERROR(reason, igraph_errno) \
do { \
igraph_error (reason, __FILE__, __LINE__, igraph_errno) ; \
return igraph_errno ; \
} while (0)
/**
* \function igraph_error
*
* This is the function which is called (usually via the
* \ref IGRAPH_ERROR macro) if an error is noticed. See the discussion of
* this macro as well.
*
* \param reason Textual description of the error.
* \param file The source file in which the error was noticed.
* \param line The number of line in the source file which triggered the
* error.
* \param igraph_errno The \a igraph error code.
* \return the error code (if it returns)
*/
int igraph_error(const char *reason, const char *file, int line,
int igraph_errno);
/**
* \function igraph_strerror
*
* This is a simple utility function, it gives a short general textual
* description for an \a igraph error code.
*
* \param igraph_errno The \a igraph error code.
* \return pointer to the textual description of the error code.
*/
const char* igraph_strerror(const int igraph_errno);
#define IGRAPH_ERROR_SELECT_2(a,b) ((a) != IGRAPH_SUCCESS ? (a) : ((b) != IGRAPH_SUCCESS ? (b) : IGRAPH_SUCCESS))
#define IGRAPH_ERROR_SELECT_3(a,b,c) ((a) != IGRAPH_SUCCESS ? (a) : IGRAPH_ERROR_SELECT_2(b,c))
#define IGRAPH_ERROR_SELECT_4(a,b,c,d) ((a) != IGRAPH_SUCCESS ? (a) : IGRAPH_ERROR_SELECT_3(b,c,d))
#define IGRAPH_ERROR_SELECT_5(a,b,c,d,e) ((a) != IGRAPH_SUCCESS ? (a) : IGRAPH_ERROR_SELECT_4(b,c,d,e))
/* Now comes the more conveninent error handling macro arsenal.
* Ideas taken from exception.{h,c} by Laurent Deniau see
* http://cern.ch/Laurent.Deniau/html/oopc/oopc.html#Exceptions for more
* information. We don't use the exception handling code though. */
struct igraph_i_protectedPtr {
int all;
void *ptr;
void (*func)(void*);
};
typedef void igraph_finally_func_t (void*);
void IGRAPH_FINALLY_REAL(void (*func)(void*), void* ptr);
/**
* \function IGRAPH_FINALLY_CLEAN
*
* Removes the specified number of objects from the stack of
* temporarily allocated objects. Most often this is called just
* before returning from a function.
* \param num The number of objects to remove from the bookkeeping
* stack.
*/
void IGRAPH_FINALLY_CLEAN(int num);
/**
* \function IGRAPH_FINALLY_FREE
*
* Calls the destroy function for all objects in the stack of
* temporarily allocated objects. This is usually called only from an
* error handler. It is \em not appropriate to use it
* instead of destroying each unneeded object of a function, as it
* destroys the temporary objects of the caller function (and so on)
* as well.
*/
void IGRAPH_FINALLY_FREE(void);
/**
* \define IGRAPH_FINALLY
* \param func The address of the function which is normally called to
* destroy the object.
* \param ptr Pointer to the object itself.
*
* This macro places the address of an object, together with the
* address of its destructor in a stack. This stack is used if an
* error happens to deallocate temporarily allocated objects to
* prevent memory leaks.
*/
#define IGRAPH_FINALLY(func, ptr) \
IGRAPH_FINALLY_REAL((igraph_finally_func_t*)(func), (ptr))
/**
* \define IGRAPH_CHECK
*
* \param a An expression, usually a function call.
*
* Executes the expression and checks its value. If this is not
* \c IGRAPH_SUCCESS, it calls \ref IGRAPH_ERROR with
* the value as the error code. Here is an example usage:
* \verbatim IGRAPH_CHECK(vector_push_back(&v, 100)); \endverbatim
*/
#define IGRAPH_CHECK(a) do { \
int igraph_i_ret=(a); \
if (igraph_i_ret != 0) { \
IGRAPH_ERROR("", igraph_i_ret); \
} } while(0)
typedef igraph_error_handler_t igraph_warning_handler_t;
igraph_warning_handler_t*
igraph_set_warning_handler(igraph_warning_handler_t new_handler);
extern igraph_warning_handler_t igraph_warning_handler_print;
int igraph_warning(const char *reason, const char *file, int line,
int igraph_errno);
#define IGRAPH_WARNING(reason) \
do { \
igraph_warning(reason, __FILE__, __LINE__, -1); \
} while (0)
__END_DECLS
#endif
syntax highlighted by Code2HTML, v. 0.9.1