1 /*------------------------------------------------------------------------
2  *  Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
3  *
4  *  This file is part of the ZBar Bar Code Reader.
5  *
6  *  The ZBar Bar Code Reader is free software; you can redistribute it
7  *  and/or modify it under the terms of the GNU Lesser Public License as
8  *  published by the Free Software Foundation; either version 2.1 of
9  *  the License, or (at your option) any later version.
10  *
11  *  The ZBar Bar Code Reader is distributed in the hope that it will be
12  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13  *  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU Lesser Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser Public License
17  *  along with the ZBar Bar Code Reader; if not, write to the Free
18  *  Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  *  Boston, MA  02110-1301  USA
20  *
21  *  http://sourceforge.net/projects/zbar
22  *------------------------------------------------------------------------*/
23 #ifndef _ERROR_H_
24 #define _ERROR_H_
25 
26 #ifdef HAVE_INTTYPES_H
27 # include <inttypes.h>
28 #endif
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <assert.h>
34 
35 #include <zbar.h>
36 
37 #ifdef _WIN32
38 # include <windows.h>
39 #endif
40 
41 #if __STDC_VERSION__ < 199901L
42 # if __GNUC__ >= 2
43 #  define __func__ __FUNCTION__
44 # else
45 #  define __func__ "<unknown>"
46 # endif
47 #endif
48 
49 #define ERRINFO_MAGIC (0x5252457a) /* "zERR" (LE) */
50 
51 typedef enum errsev_e {
52     SEV_FATAL   = -2,           /* application must terminate */
53     SEV_ERROR   = -1,           /* might be able to recover and continue */
54     SEV_OK      =  0,
55     SEV_WARNING =  1,           /* unexpected condition */
56     SEV_NOTE    =  2,           /* fyi */
57 } errsev_t;
58 
59 typedef enum errmodule_e {
60     ZBAR_MOD_PROCESSOR,
61     ZBAR_MOD_VIDEO,
62     ZBAR_MOD_WINDOW,
63     ZBAR_MOD_IMAGE_SCANNER,
64     ZBAR_MOD_UNKNOWN,
65 } errmodule_t;
66 
67 typedef struct errinfo_s {
68     uint32_t magic;             /* just in case */
69     errmodule_t module;         /* reporting module */
70     char *buf;                  /* formatted and passed to application */
71     int errnum;                 /* errno for system errors */
72 
73     errsev_t sev;
74     zbar_error_t type;
75     const char *func;           /* reporting function */
76     const char *detail;         /* description */
77     char *arg_str;              /* single string argument */
78     int arg_int;                /* single integer argument */
79 } errinfo_t;
80 
81 extern int _zbar_verbosity;
82 
83 /* FIXME don't we need varargs hacks here? */
84 
85 #ifdef _WIN32
86 # define ZFLUSH fflush(stderr);
87 #else
88 # define ZFLUSH
89 #endif
90 
91 #ifdef ZNO_MESSAGES
92 
93 # ifdef __GNUC__
94     /* older versions of gcc (< 2.95) require a named varargs parameter */
95 #  define zprintf(args...)
96 # else
97     /* unfortunately named vararg parameter is a gcc-specific extension */
98 #  define zprintf(...)
99 # endif
100 
101 #else
102 
103 # ifdef __GNUC__
104 #  define zprintf(level, format, args...) do {                          \
105         if(_zbar_verbosity >= level) {                                  \
106             fprintf(stderr, "%s: " format, __func__ , ##args);          \
107             ZFLUSH                                                      \
108         }                                                               \
109     } while(0)
110 # else
111 #  define zprintf(level, format, ...) do {                              \
112         if(_zbar_verbosity >= level) {                                  \
113             fprintf(stderr, "%s: " format, __func__ , ##__VA_ARGS__);   \
114             ZFLUSH                                                      \
115         }                                                               \
116     } while(0)
117 # endif
118 
119 #endif
120 
err_copy(void * dst_c,void * src_c)121 static inline int err_copy (void *dst_c,
122                             void *src_c)
123 {
124     errinfo_t *dst = dst_c;
125     errinfo_t *src = src_c;
126     assert(dst->magic == ERRINFO_MAGIC);
127     assert(src->magic == ERRINFO_MAGIC);
128 
129     dst->errnum = src->errnum;
130     dst->sev = src->sev;
131     dst->type = src->type;
132     dst->func = src->func;
133     dst->detail = src->detail;
134     dst->arg_str = src->arg_str;
135     src->arg_str = NULL; /* unused at src, avoid double free */
136     dst->arg_int = src->arg_int;
137     return(-1);
138 }
139 
err_capture(const void * container,errsev_t sev,zbar_error_t type,const char * func,const char * detail)140 static inline int err_capture (const void *container,
141                                errsev_t sev,
142                                zbar_error_t type,
143                                const char *func,
144                                const char *detail)
145 {
146     errinfo_t *err = (errinfo_t*)container;
147     assert(err->magic == ERRINFO_MAGIC);
148     if(type == ZBAR_ERR_SYSTEM)
149         err->errnum = errno;
150 #ifdef _WIN32
151     else if(type == ZBAR_ERR_WINAPI)
152         err->errnum = GetLastError();
153 #endif
154     err->sev = sev;
155     err->type = type;
156     err->func = func;
157     err->detail = detail;
158     if(_zbar_verbosity >= 1)
159         _zbar_error_spew(err, 0);
160     return(-1);
161 }
162 
err_capture_str(const void * container,errsev_t sev,zbar_error_t type,const char * func,const char * detail,const char * arg)163 static inline int err_capture_str (const void *container,
164                                    errsev_t sev,
165                                    zbar_error_t type,
166                                    const char *func,
167                                    const char *detail,
168                                    const char *arg)
169 {
170     errinfo_t *err = (errinfo_t*)container;
171     assert(err->magic == ERRINFO_MAGIC);
172     if(err->arg_str)
173         free(err->arg_str);
174     err->arg_str = strdup(arg);
175     return(err_capture(container, sev, type, func, detail));
176 }
177 
err_capture_int(const void * container,errsev_t sev,zbar_error_t type,const char * func,const char * detail,int arg)178 static inline int err_capture_int (const void *container,
179                                    errsev_t sev,
180                                    zbar_error_t type,
181                                    const char *func,
182                                    const char *detail,
183                                    int arg)
184 {
185     errinfo_t *err = (errinfo_t*)container;
186     assert(err->magic == ERRINFO_MAGIC);
187     err->arg_int = arg;
188     return(err_capture(container, sev, type, func, detail));
189 }
190 
err_capture_num(const void * container,errsev_t sev,zbar_error_t type,const char * func,const char * detail,int num)191 static inline int err_capture_num (const void *container,
192                                    errsev_t sev,
193                                    zbar_error_t type,
194                                    const char *func,
195                                    const char *detail,
196                                    int num)
197 {
198     errinfo_t *err = (errinfo_t*)container;
199     assert(err->magic == ERRINFO_MAGIC);
200     err->errnum = num;
201     return(err_capture(container, sev, type, func, detail));
202 }
203 
err_init(errinfo_t * err,errmodule_t module)204 static inline void err_init (errinfo_t *err,
205                              errmodule_t module)
206 {
207     err->magic = ERRINFO_MAGIC;
208     err->module = module;
209 }
210 
err_cleanup(errinfo_t * err)211 static inline void err_cleanup (errinfo_t *err)
212 {
213     assert(err->magic == ERRINFO_MAGIC);
214     if(err->buf) {
215         free(err->buf);
216         err->buf = NULL;
217     }
218     if(err->arg_str) {
219         free(err->arg_str);
220         err->arg_str = NULL;
221     }
222 }
223 
224 #endif
225