Conversion to Apache 2.0 license
[platform/core/uifw/dali-core.git] / dali / public-api / common / dali-common.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/public-api/common/dali-common.h>
20
21 // EXTERNAL INCLUDES
22 #include <stdlib.h>
23 #include <string>
24 #include <cstdio>
25 #include <execinfo.h>
26
27 #ifndef EMSCRIPTEN // cxxabi not supported
28 # include <cxxabi.h>
29 #endif
30
31 #include <cstring>
32
33 // INTERNAL INCLUDES
34 #include <dali/integration-api/debug.h>
35
36 namespace
37 {
38 const int MAX_NUM_STACK_FRAMES = 25;
39 const size_t C_SYMBOL_LENGTH = 4096;
40 }
41
42 namespace Dali
43 {
44
45 #ifndef EMSCRIPTEN
46
47 std::string Demangle(const char* symbol)
48 {
49   std::string result;
50
51   // backtrace ::=  <filename>'('['_'<mangled-symbol>'_']['+'<offset>]')'
52   // Only want <mangled-symbol>:
53   const char* openParen = strchr(symbol, '(');
54   if(openParen != NULL)
55   {
56     const char* startOfToken = openParen + 1;
57     const char* plus = strchr(startOfToken, '+');
58     const char* closeParen = strchr(startOfToken, ')');
59     const char* endOfToken = NULL;
60     if(plus != NULL)
61     {
62       endOfToken = plus;
63     }
64     else if(closeParen != NULL)
65     {
66       endOfToken = closeParen;
67     }
68     if(endOfToken != NULL)
69     {
70       size_t tokenLength = endOfToken - startOfToken;
71
72       // Allocate space for symbol
73       char *mangledSymbol = (char*)malloc(tokenLength+1u);
74       strncpy(mangledSymbol, startOfToken, tokenLength);
75       mangledSymbol[tokenLength] = '\0';
76
77       size_t size;
78       int    status;
79       char*  demangled=NULL;
80       demangled = abi::__cxa_demangle( mangledSymbol, NULL, &size, &status );
81       if( demangled != NULL )
82       {
83         result = demangled;
84         free(demangled); // demangle() allocates returned string, so free it
85       }
86       else
87       {
88         result = symbol;
89       }
90       free(mangledSymbol);
91     }
92   }
93
94   return result;
95 }
96
97 #endif // EMSCRIPTEN
98
99 #ifndef EMSCRIPTEN
100
101 DALI_EXPORT_API DaliException::DaliException(const char *location, const char* condition)
102 : mLocation(location), mCondition(condition)
103 {
104   // Note, if a memory error has occured, then the backtrace won't work - backtrace_symbols relies on
105   // allocating memory.
106
107   // Initial dlog error message is output in DALI_ASSERT_ALWAYS macro
108   // Also output on stderr
109   fprintf(stderr, "Exception: \n%s\n thrown at %s\nSee dlog for backtrace\n", mCondition.c_str(), mLocation.c_str());
110
111   DALI_LOG_ERROR_NOFN("Backtrace:\n");
112
113   void* frameArray[MAX_NUM_STACK_FRAMES];
114   int nSize = backtrace(frameArray, MAX_NUM_STACK_FRAMES);
115   char** symbols = backtrace_symbols(frameArray, nSize);
116   for(int i=1; i< nSize; i++)
117   {
118     std::string demangled_symbol = Demangle(symbols[i]);
119     DALI_LOG_ERROR_NOFN("[%02d]   %s\n", i, demangled_symbol.c_str() );
120   }
121   free(symbols);
122 }
123
124 #else
125
126 DALI_EXPORT_API DaliException::DaliException(const char *location, const char* condition)
127 : mLocation(location), mCondition(condition)
128 {
129   printf("Exception: \n%s\n thrown at %s\nSee dlog for backtrace\n", mCondition.c_str(), mLocation.c_str());
130 }
131
132 #endif // EMSCRIPTEN
133
134 DALI_EXPORT_API void DaliAssertMessage(const char* condition, const char* file, int line)
135 {
136   DALI_LOG_ERROR_NOFN( "Assertion (%s) failed in: %s:%d\n", condition, file, line );
137 }
138
139 } // Dali