1 /* Public domain */
2
3 #ifndef _AGAR_CORE_ERROR_H_
4 #define _AGAR_CORE_ERROR_H_
5
6 #include <agar/config/_mk_have_stdlib_h.h>
7 #ifdef _MK_HAVE_STDLIB_H
8 #include <stdlib.h>
9 #endif
10
11 #include <agar/core/begin.h>
12
13 /* Standard error code */
14 typedef enum ag_error_code {
15 AG_EUNDEFINED, /* Undefined error */
16 AG_EPERM, /* Operation not permitted */
17 AG_ENOENT, /* No such file or directory */
18 AG_EINTR, /* Interrupted system call */
19 AG_EIO, /* Input/output error */
20 AG_E2BIG, /* Argument list too long */
21 AG_EACCESS, /* Permission denied */
22 AG_EBUSY, /* Device or resource busy */
23 AG_EEXIST, /* File exists */
24 AG_ENOTDIR, /* Not a directory */
25 AG_EISDIR, /* Is a directory */
26 AG_EMFILE, /* Too many open files */
27 AG_EFBIG, /* File too large */
28 AG_ENOSPC, /* No space left on device */
29 AG_EROFS, /* Read-only file system */
30 AG_EAGAIN /* Resource temporarily unavailable */
31 } AG_ErrorCode;
32
33 #if defined(_AGAR_INTERNAL) || defined(_USE_AGAR_STD)
34 # define Malloc(len) AG_Malloc(len)
35 # define TryMalloc(len) AG_TryMalloc(len)
36 # define Free(p) AG_Free(p)
37 # define Realloc(p,len) AG_Realloc((p),(len))
38 # define TryRealloc(p,len) AG_TryRealloc((p),(len))
39 # define Verbose AG_Verbose
40 # ifdef AG_DEBUG
41 # define Debug AG_Debug
42 # else
43 # ifdef __GNUC__
44 # define Debug(obj, arg...) ((void)0)
45 # else
46 # define Debug AG_Debug
47 # endif
48 # endif /* AG_DEBUG */
49 #endif /* _AGAR_INTERNAL or _USE_AGAR_STD */
50
51 __BEGIN_DECLS
52 extern int agDebugLvl;
53
54 int AG_InitErrorSubsystem(void);
55 void AG_DestroyErrorSubsystem(void);
56 AG_ErrorCode AG_GetErrorCode(void);
57 const char *AG_GetError(void);
58 void AG_SetErrorCode(AG_ErrorCode);
59 void AG_SetError(const char *, ...)
60 FORMAT_ATTRIBUTE(printf, 1, 2)
61 NONNULL_ATTRIBUTE(1);
62 void AG_FatalError(const char *, ...)
63 NORETURN_ATTRIBUTE;
64 void AG_SetFatalCallback(void (*callback)(const char *));
65 void AG_SetVerboseCallback(int (*callback)(const char *));
66 void AG_SetDebugCallback(int (*callback)(const char *));
67 void AG_Debug(void *, const char *, ...)
68 FORMAT_ATTRIBUTE(printf, 2, 3)
69 NONNULL_ATTRIBUTE(2);
70 void AG_Verbose(const char *, ...)
71 FORMAT_ATTRIBUTE(printf, 1, 2)
72 NONNULL_ATTRIBUTE(1);
73 void *AG_PtrMismatch(void);
74 void *AG_ObjectMismatch(const char *, const char *);
75 int AG_IntMismatch(void);
76 float AG_FloatMismatch(void);
77 const char *AG_Strerror(int);
78
79 /* Malloc wrapper (failure is fatal) */
80 static __inline__ void *
AG_Malloc(size_t len)81 AG_Malloc(size_t len)
82 {
83 void *p;
84 if ((p = malloc(len)) == NULL) { AG_FatalError("malloc"); }
85 return (p);
86 }
87
88 /* Malloc wrapper (return on failure) */
89 static __inline__ void *
AG_TryMalloc(size_t len)90 AG_TryMalloc(size_t len)
91 {
92 void *p;
93 if ((p = malloc(len)) == NULL) {
94 AG_SetError("Out of memory");
95 return (NULL);
96 }
97 return (p);
98 }
99
100 /* Realloc wrapper (failure is fatal) */
101 static __inline__ void *
AG_Realloc(void * pOld,size_t len)102 AG_Realloc(void *pOld, size_t len)
103 {
104 void *pNew;
105 /* XXX redundant on some systems */
106 if (pOld == NULL) {
107 if ((pNew = malloc(len)) == NULL)
108 AG_FatalError("malloc");
109 } else {
110 if ((pNew = realloc(pOld, len)) == NULL)
111 AG_FatalError("realloc");
112 }
113 return (pNew);
114 }
115
116 /* Realloc wrapper (return on failure) */
117 static __inline__ void *
AG_TryRealloc(void * pOld,size_t len)118 AG_TryRealloc(void *pOld, size_t len)
119 {
120 void *pNew;
121 /* XXX redundant on some systems */
122 if (pOld == NULL) {
123 if ((pNew = malloc(len)) == NULL)
124 goto outofmem;
125 } else {
126 if ((pNew = realloc(pOld, len)) == NULL)
127 goto outofmem;
128 }
129 return (pNew);
130 outofmem:
131 AG_SetError("Out of memory");
132 return (NULL);
133 }
134
135 /* Free wrapper for symmetry */
136 #define AG_Free(p) free(p)
137 __END_DECLS
138
139 #include <agar/core/close.h>
140 #endif /* _AGAR_CORE_ERROR_H_ */
141