File: igraph_error.h

package info (click to toggle)
igraph 0.7.1-4
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 19,500 kB
  • sloc: ansic: 188,142; sh: 26,731; cpp: 18,275; yacc: 1,164; makefile: 957; lex: 484; xml: 405
file content (721 lines) | stat: -rw-r--r-- 27,148 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
/* -*- mode: C -*-  */
/* 
   IGraph library.
   Copyright (C) 2003-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard street, Cambridge, MA 02139 USA
   
   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

#include <stdarg.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 errorhandlingbasics Error handling basics
 * 
 * <para>\a igraph functions can run into various problems preventing them 
 * from normal operation. The user might have supplied invalid arguments,
 * e.g. a non-square matrix when a square-matrix was expected, or the program 
 * has run out of memory while some more memory allocation is required, etc.
 * </para>
 * 
 * <para>By default \a igraph aborts the program when it runs into an 
 * error. While this behavior might be good enough for smaller programs, 
 * it is without doubt avoidable in larger projects. Please read further
 * if your project requires more sophisticated error handling. You can 
 * safely skip the rest of this chapter otherwise.
 * </para>
 */

/**
 * \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
 * (almost) every non-void \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_error_type_t enumeration.
 * </para>
 */

/**
 * \section writing_error_handlers Writing error handlers
 *
 * <para>
 * The contents of the rest of this chapter might be useful only
 * for those who want to create an interface to \a igraph from another
 * language. Most readers can safely skip to the next chapter.
 * </para>
 * 
 * <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 \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 an \a igraph 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 before returning. Third, use
 * \ref IGRAPH_CHECK on all \a igraph 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
 * \brief Type of error handler functions.
 * 
 * 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
 * \brief Abort program in case of error.
 *
 * 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
 * \brief Ignore errors.
 *
 * 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
 * \brief Print and ignore errors.
 * 
 * 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
 * \brief Set a new 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_error_type_t
 * \brief Error code type.
 * These are the possible values returned by \a igraph functions.
 * Note that these are interesting only if you defined an error handler
 * with \ref igraph_set_error_handler(). Otherwise the program is aborted 
 * and the function causing the error never returns.
 * 
 * \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
 *    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 has no rights to open it.
 * \enumval IGRAPH_UNIMPLEMENTED Attempted to call an unimplemented or
 *   disabled (at compile-time) function.
 * \enumval IGRAPH_DIVERGED A numeric algorithm failed to converge.
 * \enumval IGRAPH_ARPACK_PROD Matrix-vector product failed.
 * \enumval IGRAPH_ARPACK_NPOS N must be positive.
 * \enumval IGRAPH_ARPACK_NEVNPOS NEV must be positive.
 * \enumval IGRAPH_ARPACK_NCVSMALL NCV must be bigger.
 * \enumval IGRAPH_ARPACK_NONPOSI Maximum number of iterations should be positive.
 * \enumval IGRAPH_ARPACK_WHICHINV Invalid WHICH parameter.
 * \enumval IGRAPH_ARPACK_BMATINV Invalid BMAT parameter.
 * \enumval IGRAPH_ARPACK_WORKLSMALL WORKL is too small.
 * \enumval IGRAPH_ARPACK_TRIDERR LAPACK error in tridiagonal eigenvalue calculation.
 * \enumval IGRAPH_ARPACK_ZEROSTART Starting vector is zero.
 * \enumval IGRAPH_ARPACK_MODEINV MODE is invalid.
 * \enumval IGRAPH_ARPACK_MODEBMAT MODE and BMAT are not compatible.
 * \enumval IGRAPH_ARPACK_ISHIFT ISHIFT must be 0 or 1.
 * \enumval IGRAPH_ARPACK_NEVBE NEV and WHICH='BE' are incompatible.
 * \enumval IGRAPH_ARPACK_NOFACT Could not build an Arnoldi factorization.
 * \enumval IGRAPH_ARPACK_FAILED No eigenvalues to sufficient accuracy.
 * \enumval IGRAPH_ARPACK_HOWMNY HOWMNY is invalid.
 * \enumval IGRAPH_ARPACK_HOWMNYS HOWMNY='S' is not implemented.
 * \enumval IGRAPH_ARPACK_EVDIFF Different number of converged Ritz values.
 * \enumval IGRAPH_ARPACK_SHUR Error from calculation of a real Schur form.
 * \enumval IGRAPH_ARPACK_LAPACK LAPACK (dtrevc) error for calculating eigenvectors.
 * \enumval IGRAPH_ARPACK_UNKNOWN Unknown ARPACK error.
 * \enumval IGRAPH_ENEGLOOP Negative loop detected while calculating shortest paths.
 * \enumval IGRAPH_EINTERNAL Internal error, likely a bug in igraph.
 * \enumval IGRAPH_EDIVZERO Big integer division by zero.
 * \enumval IGARPH_GLP_EBOUND GLPK error (GLP_EBOUND).
 * \enumval IGARPH_GLP_EROOT GLPK error (GLP_EROOT).
 * \enumval IGARPH_GLP_ENOPFS GLPK error (GLP_ENOPFS).
 * \enumval IGARPH_GLP_ENODFS GLPK error (GLP_ENODFS).
 * \enumval IGARPH_GLP_EFAIL GLPK error (GLP_EFAIL).
 * \enumval IGARPH_GLP_EMIPGAP GLPK error (GLP_EMIPGAP).
 * \enumval IGARPH_GLP_ETMLIM GLPK error (GLP_ETMLIM).
 * \enumval IGARPH_GLP_ESTOP GLPK error (GLP_ESTOP).
 * \enumval IGRAPH_EATTRIBUTES Attribute handler error. The user is not 
 *   expected to find this; it is signalled if some igraph function is
 *   not using the attribute handler interface properly.
 * \enumval IGRAPH_EATTRCOMBINE Unimplemented attribute combination 
 *   method for the given attribute type.
 * \enumval IGRAPH_ELAPACK A LAPACK call resulted an error.
 * \enumval IGRAPH_EDRL Internal error in the DrL layout generator.
 * \enumval IGRAPH_EOVERFLOW Integer or double overflow.
 * \enumval IGRAPH_EGLP Internal GLPK error.
 * \enumval IGRAPH_CPUTIME CPU time exceeded.
 * \enumval IGRAPH_EUNDERFLOW Integer or double underflow.
 */

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_UNIMPLEMENTED = 12,
  IGRAPH_INTERRUPTED   = 13,
  IGRAPH_DIVERGED      = 14,
  IGRAPH_ARPACK_PROD      = 15,
  IGRAPH_ARPACK_NPOS      = 16,
  IGRAPH_ARPACK_NEVNPOS   = 17,
  IGRAPH_ARPACK_NCVSMALL  = 18,
  IGRAPH_ARPACK_NONPOSI   = 19,
  IGRAPH_ARPACK_WHICHINV  = 20,
  IGRAPH_ARPACK_BMATINV   = 21,
  IGRAPH_ARPACK_WORKLSMALL= 22,
  IGRAPH_ARPACK_TRIDERR   = 23,
  IGRAPH_ARPACK_ZEROSTART = 24,
  IGRAPH_ARPACK_MODEINV   = 25,
  IGRAPH_ARPACK_MODEBMAT  = 26,
  IGRAPH_ARPACK_ISHIFT    = 27,
  IGRAPH_ARPACK_NEVBE     = 28,
  IGRAPH_ARPACK_NOFACT    = 29,
  IGRAPH_ARPACK_FAILED    = 30,
  IGRAPH_ARPACK_HOWMNY    = 31,
  IGRAPH_ARPACK_HOWMNYS   = 32,
  IGRAPH_ARPACK_EVDIFF    = 33,
  IGRAPH_ARPACK_SHUR      = 34,
  IGRAPH_ARPACK_LAPACK    = 35,
  IGRAPH_ARPACK_UNKNOWN   = 36,
  IGRAPH_ENEGLOOP         = 37,
  IGRAPH_EINTERNAL        = 38,
  IGRAPH_ARPACK_MAXIT     = 39,
  IGRAPH_ARPACK_NOSHIFT   = 40,
  IGRAPH_ARPACK_REORDER   = 41,
  IGRAPH_EDIVZERO         = 42,
  IGRAPH_GLP_EBOUND       = 43,
  IGRAPH_GLP_EROOT        = 44,
  IGRAPH_GLP_ENOPFS       = 45,
  IGRAPH_GLP_ENODFS       = 46,
  IGRAPH_GLP_EFAIL        = 47, 
  IGRAPH_GLP_EMIPGAP      = 48,
  IGRAPH_GLP_ETMLIM       = 49,
  IGRAPH_GLP_ESTOP        = 50,
  IGRAPH_EATTRIBUTES      = 51,
  IGRAPH_EATTRCOMBINE     = 52,
  IGRAPH_ELAPACK          = 53,
  IGRAPH_EDRL             = 54,
  IGRAPH_EOVERFLOW        = 55,
  IGRAPH_EGLP             = 56,
  IGRAPH_CPUTIME          = 57,
  IGRAPH_EUNDERFLOW       = 58
} igraph_error_type_t;

/**
 * \define IGRAPH_ERROR
 * \brief Trigger an error.
 * 
 * \a igraph functions usually use this macro when they notice an error.
 * 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 descriptive than the text associated with the error
 *   code. Eg. if the error code is \c IGRAPH_EINVAL,
 *   its associated 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
 * \brief Trigger an error.
 *
 * \a igraph functions usually call this function (most often via the 
 * \ref IGRAPH_ERROR macro) if they notice an error.
 * It calls the currently installed error handler function with the
 * supplied arguments. 
 *
 * \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)
 * 
 * \sa igraph_errorf().
 */

int igraph_error(const char *reason, const char *file, int line,
		 int igraph_errno);

/**
 * \function igraph_errorf
 * \brief Trigger an error, printf-like version.
 * 
 * \param reason Textual description of the error, interpreted as 
 *               a printf format string.
 * \param file The source file in which the error was noticed.
 * \param line The line in the source file which triggered the error.
 * \param igraph_errno The \a igraph error code.
 * \param ... Additional parameters, the values to substitute into the
 *            format string.
 * 
 * \sa igraph_error().
 */

int igraph_errorf(const char *reason, const char *file, int line, 
		  int igraph_errno, ...);

int igraph_errorvf(const char *reason, const char *file, int line,
		   int igraph_errno, va_list ap);

/**
 * \function igraph_strerror
 * \brief Textual description of an error.
 * 
 * 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 convenient 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
 * \brief Signal clean deallocation of objects.
 * 
 * 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
 * \brief Deallocate all registered objects.
 *
 * 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);

/**
 * \function IGRAPH_FINALLY_STACK_SIZE
 * \brief Returns the number of registered objects.
 *
 * Returns the number of objects in the stack of temporarily allocated
 * objects. This function is handy if you write an own igraph routine and
 * you want to make sure it handles errors properly. A properly written
 * igraph routine should not leave pointers to temporarily allocated objects
 * in the finally stack, because otherwise an \ref IGRAPH_FINALLY_FREE call
 * in another igraph function would result in freeing these objects as well
 * (and this is really hard to debug, since the error will be not in that
 * function that shows erroneous behaviour). Therefore, it is advised to
 * write your own test cases and examine \ref IGRAPH_FINALLY_STACK_SIZE
 * before and after your test cases - the numbers should be equal.
 */
int IGRAPH_FINALLY_STACK_SIZE(void);

/**
 * \define IGRAPH_FINALLY_STACK_EMPTY
 * \brief Returns true if there are no registered objects, false otherwise.
 *
 * This is just a shorthand notation for checking that
 * \ref IGRAPH_FINALLY_STACK_SIZE is zero.
 */
#define IGRAPH_FINALLY_STACK_EMPTY (IGRAPH_FINALLY_STACK_SIZE() == 0)

/**
 * \define IGRAPH_FINALLY
 * \brief Register an object for deallocation.
 * \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))

#if (defined(__GNUC__) && GCC_VERSION_MAJOR >= 3)
#  define IGRAPH_UNLIKELY(a) __builtin_expect((a), 0)
#  define IGRAPH_LIKELY(a)   __builtin_expect((a), 1)
#else
#  define IGRAPH_UNLIKELY(a) a
#  define IGRAPH_LIKELY(a)   a
#endif

/**
 * \define IGRAPH_CHECK
 * \brief Check the return value of a function call.
 *
 * \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(&amp;v, 100)); \endverbatim
 * 
 * </para><para>There is only one reason to use this macro when writing 
 * \a igraph functions. If the user installs an error handler which
 * returns to the auxiliary calling code (like \ref
 * igraph_error_handler_ignore and \ref
 * igraph_error_handler_printignore), and the \a igraph function
 * signalling the error is called from another \a igraph function 
 * then we need to make sure that the error is propagated back to 
 * the auxiliary (ie. non-igraph) calling function. This is achieved
 * by using <function>IGRAPH_CHECK</function> on every \a igraph
 * call which can return an error code.
 */

#define IGRAPH_CHECK(a) do { \
                 int igraph_i_ret=(a); \
                 if (IGRAPH_UNLIKELY(igraph_i_ret != 0)) {\
                     IGRAPH_ERROR("", igraph_i_ret); \
                 } } while (0)


/**
 * \section about_igraph_warnings Warning messages
 * 
 * <para>
 * Igraph also supports warning messages in addition to error 
 * messages. Warning messages typically do not terminate the 
 * program, but they are usually crucial to the user.
 * </para>
 * 
 * <para>
 * Igraph warning are handled similarly to errors. There is a 
 * separate warning handler function that is called whenever
 * an igraph function triggers a warning. This handler can be 
 * set by the \ref igraph_set_warning_handler() function. There are 
 * two predefined simple warning handlers, 
 * \ref igraph_warning_handler_ignore() and 
 * \ref igraph_warning_handler_print(), the latter being the default.
 * </para>
 * 
 * <para>
 * To trigger a warning, igraph functions typically use the 
 * \ref IGRAPH_WARNING() macro, the \ref igraph_warning() function, 
 * or if more flexibility is needed, \ref igraph_warningf().
 * </para>
 */

/**
 * \typedef igraph_warning_handler_t
 * Type of igraph warning handler functions
 * 
 * Currently it is defined to have the same type as 
 * \ref igraph_error_handler_t, although the last (error code)
 * argument is not used.
 */

typedef igraph_error_handler_t igraph_warning_handler_t;

/**
 * \function igraph_set_warning_handler
 * Install a warning handler
 * 
 * Install the supplied warning handler function.
 * \param new_handler The new warning handler function to install.
 *        Supply a null pointer here to uninstall the current 
 *        warning handler, without installing a new one.
 * \return The current warning handler function.
 */

igraph_warning_handler_t*
igraph_set_warning_handler(igraph_warning_handler_t* new_handler);

extern igraph_warning_handler_t igraph_warning_handler_ignore;
extern igraph_warning_handler_t igraph_warning_handler_print;

/**
 * \function igraph_warning
 * Trigger a warning
 * 
 * Call this function if you want to trigger a warning from within 
 * a function that uses igraph.
 * \param reason Textual description of the warning.
 * \param file The source file in which the warning was noticed.
 * \param line The number of line in the source file which triggered the
 *         warning.
 * \param igraph_errno Warnings could have potentially error codes as well, 
 *        but this is currently not used in igraph.
 * \return The supplied error code.
 */

int igraph_warning(const char *reason, const char *file, int line,
		   int igraph_errno);

/**
 * \function igraph_warningf
 * Trigger a warning, more flexible printf-like syntax
 * 
 * This function is similar to \ref igraph_warning(), but
 * uses a printf-like syntax. It substitutes the additional arguments 
 * into the \p reason template string and calls \ref igraph_warning().
 * \param reason Textual description of the warning, a template string
 *        with the same syntax as the standard printf C library function.
 * \param file The source file in which the warning was noticed.
 * \param line The number of line in the source file which triggered the
 *         warning.
 * \param igraph_errno Warnings could have potentially error codes as well, 
 *        but this is currently not used in igraph.
 * \param ... The additional arguments to be substituted into the 
 *        template string.
 * \return The supplied error code.
 */

int igraph_warningf(const char *reason, const char *file, int line, 
		    int igraph_errno, ...);

/**
 * \define IGRAPH_WARNING
 * Trigger a warning.
 * 
 * This is the usual way of triggering a warning from an igraph
 * function. It calls \ref igraph_warning().
 * \param reason The warning message.
 */

#define IGRAPH_WARNING(reason) \
       do { \
         igraph_warning(reason, __FILE__, __LINE__, -1); \
       } while (0)

__END_DECLS

#endif