1/*M///////////////////////////////////////////////////////////////////////////////////////
2//
3//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4//
5//  By downloading, copying, installing or using the software you agree to this license.
6//  If you do not agree to this license, do not download, install,
7//  copy or use the software.
8//
9//
10//            Intel License Agreement
11//        For Open Source Computer Vision Library
12//
13// Copyright (C) 2000, Intel Corporation, all rights reserved.
14// Third party copyrights are property of their respective owners.
15//
16// Redistribution and use in source and binary forms, with or without modification,
17// are permitted provided that the following conditions are met:
18//
19//   * Redistribution's of source code must retain the above copyright notice,
20//     this list of conditions and the following disclaimer.
21//
22//   * Redistribution's in binary form must reproduce the above copyright notice,
23//     this list of conditions and the following disclaimer in the documentation
24//     and/or other materials provided with the distribution.
25//
26//   * The name of Intel Corporation may not be used to endorse or promote products
27//     derived from this software without specific prior written permission.
28//
29// This software is provided by the copyright holders and contributors "as is" and
30// any express or implied warranties, including, but not limited to, the implied
31// warranties of merchantability and fitness for a particular purpose are disclaimed.
32// In no event shall the Intel Corporation or contributors be liable for any direct,
33// indirect, incidental, special, exemplary, or consequential damages
34// (including, but not limited to, procurement of substitute goods or services;
35// loss of use, data, or profits; or business interruption) however caused
36// and on any theory of liability, whether in contract, strict liability,
37// or tort (including negligence or otherwise) arising in any way out of
38// the use of this software, even if advised of the possibility of such damage.
39//
40//M*/
41
42#include "_cxcore.h"
43
44#if defined WIN32 || defined WIN64
45#include <windows.h>
46#else
47#include <pthread.h>
48#endif
49
50typedef struct
51{
52    const char* file;
53    int         line;
54}
55CvStackRecord;
56
57typedef struct CvContext
58{
59    int  err_code;
60    int  err_mode;
61    CvErrorCallback error_callback;
62    void*  userdata;
63    char  err_msg[4096];
64    CvStackRecord  err_ctx;
65} CvContext;
66
67#if defined WIN32 || defined WIN64
68#define CV_DEFAULT_ERROR_CALLBACK  cvGuiBoxReport
69#else
70#define CV_DEFAULT_ERROR_CALLBACK  cvStdErrReport
71#endif
72
73static CvContext*
74icvCreateContext(void)
75{
76    CvContext* context = (CvContext*)malloc( sizeof(*context) );
77
78    context->err_mode = CV_ErrModeLeaf;
79    context->err_code = CV_StsOk;
80
81    context->error_callback = CV_DEFAULT_ERROR_CALLBACK;
82    context->userdata = 0;
83
84    return context;
85}
86
87static void
88icvDestroyContext(CvContext* context)
89{
90    free(context);
91}
92
93#if defined WIN32 || defined WIN64
94    static DWORD g_TlsIndex = TLS_OUT_OF_INDEXES;
95#else
96    static pthread_key_t g_TlsIndex;
97#endif
98
99static CvContext*
100icvGetContext(void)
101{
102#ifdef CV_DLL
103#if defined WIN32 || defined WIN64
104    CvContext* context;
105
106    //assert(g_TlsIndex != TLS_OUT_OF_INDEXES);
107    if( g_TlsIndex == TLS_OUT_OF_INDEXES )
108    {
109        g_TlsIndex = TlsAlloc();
110        if( g_TlsIndex == TLS_OUT_OF_INDEXES )
111            FatalAppExit( 0, "Only set CV_DLL for DLL usage" );
112    }
113
114    context = (CvContext*)TlsGetValue( g_TlsIndex );
115    if( !context )
116    {
117        context = icvCreateContext();
118        if( !context )
119            FatalAppExit( 0, "OpenCV. Problem to allocate memory for TLS OpenCV context." );
120
121        TlsSetValue( g_TlsIndex, context );
122    }
123    return context;
124#else
125    CvContext* context = (CvContext*)pthread_getspecific( g_TlsIndex );
126    if( !context )
127    {
128    context = icvCreateContext();
129    if( !context )
130    {
131            fprintf(stderr,"OpenCV. Problem to allocate memory for OpenCV context.");
132        exit(1);
133    }
134    pthread_setspecific( g_TlsIndex, context );
135    }
136    return context;
137#endif
138#else /* static single-thread library case */
139    static CvContext* context = 0;
140
141    if( !context )
142        context = icvCreateContext();
143
144    return context;
145#endif
146}
147
148
149CV_IMPL int
150cvStdErrReport( int code, const char *func_name, const char *err_msg,
151                const char *file, int line, void* )
152{
153    if( code == CV_StsBackTrace || code == CV_StsAutoTrace )
154        fprintf( stderr, "\tcalled from " );
155    else
156        fprintf( stderr, "OpenCV ERROR: %s (%s)\n\tin function ",
157                 cvErrorStr(code), err_msg ? err_msg : "no description" );
158
159    fprintf( stderr, "%s, %s(%d)\n", func_name ? func_name : "<unknown>",
160             file != NULL ? file : "", line );
161
162    if( cvGetErrMode() == CV_ErrModeLeaf )
163    {
164        fprintf( stderr, "Terminating the application...\n" );
165        return 1;
166    }
167    else
168        return 0;
169}
170
171
172CV_IMPL int
173cvGuiBoxReport( int code, const char *func_name, const char *err_msg,
174                const char *file, int line, void* )
175{
176#if !defined WIN32 && !defined WIN64
177    return cvStdErrReport( code, func_name, err_msg, file, line, 0 );
178#else
179    if( code != CV_StsBackTrace && code != CV_StsAutoTrace )
180    {
181        size_t msg_len = strlen(err_msg ? err_msg : "") + 1024;
182        char* message = (char*)alloca(msg_len);
183        char title[100];
184
185        wsprintf( message, "%s (%s)\nin function %s, %s(%d)\n\n"
186                  "Press \"Abort\" to terminate application.\n"
187                  "Press \"Retry\" to debug (if the app is running under debugger).\n"
188                  "Press \"Ignore\" to continue (this is not safe).\n",
189                  cvErrorStr(code), err_msg ? err_msg : "no description",
190                  func_name, file, line );
191
192        wsprintf( title, "OpenCV GUI Error Handler" );
193
194        int answer = MessageBox( NULL, message, title, MB_ICONERROR|MB_ABORTRETRYIGNORE|MB_SYSTEMMODAL );
195
196        if( answer == IDRETRY )
197        {
198            CV_DBG_BREAK();
199        }
200        return answer != IDIGNORE;
201    }
202    return 0;
203#endif
204}
205
206
207CV_IMPL int cvNulDevReport( int /*code*/, const char* /*func_name*/,
208    const char* /*err_msg*/, const char* /*file*/, int /*line*/, void* )
209{
210    return cvGetErrMode() == CV_ErrModeLeaf;
211}
212
213
214CV_IMPL CvErrorCallback
215cvRedirectError( CvErrorCallback func, void* userdata, void** prev_userdata )
216{
217    CvContext* context = icvGetContext();
218
219    CvErrorCallback old = context->error_callback;
220    if( prev_userdata )
221        *prev_userdata = context->userdata;
222    if( func )
223    {
224        context->error_callback = func;
225        context->userdata = userdata;
226    }
227    else
228    {
229        context->error_callback = CV_DEFAULT_ERROR_CALLBACK;
230        context->userdata = 0;
231    }
232
233    return old;
234}
235
236
237CV_IMPL int cvGetErrInfo( const char** errorcode_desc, const char** description,
238                          const char** filename, int* line )
239{
240    int code = cvGetErrStatus();
241
242    if( errorcode_desc )
243        *errorcode_desc = cvErrorStr( code );
244
245    if( code >= 0 )
246    {
247        if( description )
248            *description = 0;
249        if( filename )
250            *filename = 0;
251        if( line )
252            *line = 0;
253    }
254    else
255    {
256        CvContext* ctx = icvGetContext();
257
258        if( description )
259            *description = ctx->err_msg;
260        if( filename )
261            *filename = ctx->err_ctx.file;
262        if( line )
263            *line = ctx->err_ctx.line;
264    }
265
266    return code;
267}
268
269
270CV_IMPL const char* cvErrorStr( int status )
271{
272    static char buf[256];
273
274    switch (status)
275    {
276    case CV_StsOk :        return "No Error";
277    case CV_StsBackTrace : return "Backtrace";
278    case CV_StsError :     return "Unspecified error";
279    case CV_StsInternal :  return "Internal error";
280    case CV_StsNoMem :     return "Insufficient memory";
281    case CV_StsBadArg :    return "Bad argument";
282    case CV_StsNoConv :    return "Iterations do not converge";
283    case CV_StsAutoTrace : return "Autotrace call";
284    case CV_StsBadSize :   return "Incorrect size of input array";
285    case CV_StsNullPtr :   return "Null pointer";
286    case CV_StsDivByZero : return "Divizion by zero occured";
287    case CV_BadStep :      return "Image step is wrong";
288    case CV_StsInplaceNotSupported : return "Inplace operation is not supported";
289    case CV_StsObjectNotFound :      return "Requested object was not found";
290    case CV_BadDepth :     return "Input image depth is not supported by function";
291    case CV_StsUnmatchedFormats : return "Formats of input arguments do not match";
292    case CV_StsUnmatchedSizes :  return "Sizes of input arguments do not match";
293    case CV_StsOutOfRange : return "One of arguments\' values is out of range";
294    case CV_StsUnsupportedFormat : return "Unsupported format or combination of formats";
295    case CV_BadCOI :      return "Input COI is not supported";
296    case CV_BadNumChannels : return "Bad number of channels";
297    case CV_StsBadFlag :   return "Bad flag (parameter or structure field)";
298    case CV_StsBadPoint :  return "Bad parameter of type CvPoint";
299    case CV_StsBadMask : return "Bad type of mask argument";
300    case CV_StsParseError : return "Parsing error";
301    case CV_StsNotImplemented : return "The function/feature is not implemented";
302    case CV_StsBadMemBlock :  return "Memory block has been corrupted";
303    };
304
305    sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status);
306    return buf;
307}
308
309CV_IMPL int cvGetErrMode(void)
310{
311    return icvGetContext()->err_mode;
312}
313
314CV_IMPL int cvSetErrMode( int mode )
315{
316    CvContext* context = icvGetContext();
317    int prev_mode = context->err_mode;
318    context->err_mode = mode;
319    return prev_mode;
320}
321
322CV_IMPL int cvGetErrStatus()
323{
324    return icvGetContext()->err_code;
325}
326
327CV_IMPL void cvSetErrStatus( int code )
328{
329    icvGetContext()->err_code = code;
330}
331
332
333CV_IMPL void cvError( int code, const char* func_name,
334                      const char* err_msg,
335                      const char* file_name, int line )
336{
337    if( code == CV_StsOk )
338        cvSetErrStatus( code );
339    else
340    {
341        CvContext* context = icvGetContext();
342
343        if( code != CV_StsBackTrace && code != CV_StsAutoTrace )
344        {
345            char* message = context->err_msg;
346            context->err_code = code;
347
348            strcpy( message, err_msg );
349            context->err_ctx.file = file_name;
350            context->err_ctx.line = line;
351        }
352
353        if( context->err_mode != CV_ErrModeSilent )
354        {
355            int terminate = context->error_callback( code, func_name, err_msg,
356                                                    file_name, line, context->userdata );
357            if( terminate )
358            {
359                CV_DBG_BREAK();
360                //exit(-abs(terminate));
361            }
362        }
363    }
364}
365
366
367/******************** End of implementation of profiling stuff *********************/
368
369
370/**********************DllMain********************************/
371
372#if defined WIN32 || defined WIN64
373BOOL WINAPI DllMain( HINSTANCE, DWORD  fdwReason, LPVOID )
374{
375    CvContext *pContext;
376
377    switch (fdwReason)
378    {
379    case DLL_PROCESS_ATTACH:
380        g_TlsIndex = TlsAlloc();
381        if( g_TlsIndex == TLS_OUT_OF_INDEXES ) return FALSE;
382        //break;
383
384    case DLL_THREAD_ATTACH:
385        pContext = icvCreateContext();
386        if( pContext == NULL)
387            return FALSE;
388        TlsSetValue( g_TlsIndex, (LPVOID)pContext );
389        break;
390
391    case DLL_THREAD_DETACH:
392        if( g_TlsIndex != TLS_OUT_OF_INDEXES )
393        {
394            pContext = (CvContext*)TlsGetValue( g_TlsIndex );
395            if( pContext != NULL )
396                icvDestroyContext( pContext );
397        }
398        break;
399
400    case DLL_PROCESS_DETACH:
401        if( g_TlsIndex != TLS_OUT_OF_INDEXES )
402        {
403            pContext = (CvContext*)TlsGetValue( g_TlsIndex );
404            if( pContext != NULL )
405                icvDestroyContext( pContext );
406        }
407        TlsFree( g_TlsIndex );
408        break;
409    default:
410        ;
411    }
412    return TRUE;
413}
414#else
415/* POSIX pthread */
416
417/* function - destructor of thread */
418void icvPthreadDestructor(void* key_val)
419{
420    CvContext* context = (CvContext*) key_val;
421    icvDestroyContext( context );
422}
423
424int pthrerr = pthread_key_create( &g_TlsIndex, icvPthreadDestructor );
425
426#endif
427
428/* function, which converts int to int */
429CV_IMPL int
430cvErrorFromIppStatus( int status )
431{
432    switch (status)
433    {
434    case CV_BADSIZE_ERR: return CV_StsBadSize;
435    case CV_BADMEMBLOCK_ERR: return CV_StsBadMemBlock;
436    case CV_NULLPTR_ERR: return CV_StsNullPtr;
437    case CV_DIV_BY_ZERO_ERR: return CV_StsDivByZero;
438    case CV_BADSTEP_ERR: return CV_BadStep ;
439    case CV_OUTOFMEM_ERR: return CV_StsNoMem;
440    case CV_BADARG_ERR: return CV_StsBadArg;
441    case CV_NOTDEFINED_ERR: return CV_StsError;
442    case CV_INPLACE_NOT_SUPPORTED_ERR: return CV_StsInplaceNotSupported;
443    case CV_NOTFOUND_ERR: return CV_StsObjectNotFound;
444    case CV_BADCONVERGENCE_ERR: return CV_StsNoConv;
445    case CV_BADDEPTH_ERR: return CV_BadDepth;
446    case CV_UNMATCHED_FORMATS_ERR: return CV_StsUnmatchedFormats;
447    case CV_UNSUPPORTED_COI_ERR: return CV_BadCOI;
448    case CV_UNSUPPORTED_CHANNELS_ERR: return CV_BadNumChannels;
449    case CV_BADFLAG_ERR: return CV_StsBadFlag;
450    case CV_BADRANGE_ERR: return CV_StsBadArg;
451    case CV_BADCOEF_ERR: return CV_StsBadArg;
452    case CV_BADFACTOR_ERR: return CV_StsBadArg;
453    case CV_BADPOINT_ERR: return CV_StsBadPoint;
454
455    default: return CV_StsError;
456    }
457}
458/* End of file */
459
460
461