1 /**************************************************************************** 2 * 3 * ftdebug.c 4 * 5 * Debugging and logging component for Win32 (body). 6 * 7 * Copyright (C) 1996-2019 by 8 * David Turner, Robert Wilhelm, and Werner Lemberg. 9 * 10 * This file is part of the FreeType project, and may only be used, 11 * modified, and distributed under the terms of the FreeType project 12 * license, LICENSE.TXT. By continuing to use, modify, or distribute 13 * this file you indicate that you have read the license and 14 * understand and accept it fully. 15 * 16 */ 17 18 19 /************************************************************************** 20 * 21 * This component contains various macros and functions used to ease the 22 * debugging of the FreeType engine. Its main purpose is in assertion 23 * checking, tracing, and error detection. 24 * 25 * There are now three debugging modes: 26 * 27 * - trace mode 28 * 29 * Error and trace messages are sent to the log file (which can be the 30 * standard error output). 31 * 32 * - error mode 33 * 34 * Only error messages are generated. 35 * 36 * - release mode: 37 * 38 * No error message is sent or generated. The code is free from any 39 * debugging parts. 40 * 41 */ 42 43 44 #include <ft2build.h> 45 #include FT_FREETYPE_H 46 #include FT_INTERNAL_DEBUG_H 47 48 49 #ifdef FT_DEBUG_LEVEL_ERROR 50 51 #include <stdarg.h> 52 #include <stdlib.h> 53 #include <string.h> 54 55 #include <windows.h> 56 57 58 /* documentation is in ftdebug.h */ 59 60 FT_BASE_DEF( void ) FT_Message(const char * fmt,...)61 FT_Message( const char* fmt, 62 ... ) 63 { 64 static char buf[8192]; 65 va_list ap; 66 67 68 va_start( ap, fmt ); 69 vfprintf( stderr, fmt, ap ); 70 /* send the string to the debugger as well */ 71 vsprintf( buf, fmt, ap ); 72 OutputDebugStringA( buf ); 73 va_end( ap ); 74 } 75 76 77 /* documentation is in ftdebug.h */ 78 79 FT_BASE_DEF( void ) FT_Panic(const char * fmt,...)80 FT_Panic( const char* fmt, 81 ... ) 82 { 83 static char buf[8192]; 84 va_list ap; 85 86 87 va_start( ap, fmt ); 88 vsprintf( buf, fmt, ap ); 89 OutputDebugStringA( buf ); 90 va_end( ap ); 91 92 exit( EXIT_FAILURE ); 93 } 94 95 96 /* documentation is in ftdebug.h */ 97 98 FT_BASE_DEF( int ) FT_Throw(FT_Error error,int line,const char * file)99 FT_Throw( FT_Error error, 100 int line, 101 const char* file ) 102 { 103 #if 0 104 /* activating the code in this block makes FreeType very chatty */ 105 fprintf( stderr, 106 "%s:%d: error 0x%02x: %s\n", 107 file, 108 line, 109 error, 110 FT_Error_String( error ) ); 111 #else 112 FT_UNUSED( error ); 113 FT_UNUSED( line ); 114 FT_UNUSED( file ); 115 #endif 116 117 return 0; 118 } 119 120 #endif /* FT_DEBUG_LEVEL_ERROR */ 121 122 123 #ifdef FT_DEBUG_LEVEL_TRACE 124 125 /* array of trace levels, initialized to 0; */ 126 /* this gets adjusted at run-time */ 127 static int ft_trace_levels_enabled[trace_count]; 128 129 /* array of trace levels, always initialized to 0 */ 130 static int ft_trace_levels_disabled[trace_count]; 131 132 /* a pointer to either `ft_trace_levels_enabled' */ 133 /* or `ft_trace_levels_disabled' */ 134 int* ft_trace_levels; 135 136 /* define array of trace toggle names */ 137 #define FT_TRACE_DEF( x ) #x , 138 139 static const char* ft_trace_toggles[trace_count + 1] = 140 { 141 #include FT_INTERNAL_TRACE_H 142 NULL 143 }; 144 145 #undef FT_TRACE_DEF 146 147 148 /* documentation is in ftdebug.h */ 149 150 FT_BASE_DEF( FT_Int ) FT_Trace_Get_Count(void)151 FT_Trace_Get_Count( void ) 152 { 153 return trace_count; 154 } 155 156 157 /* documentation is in ftdebug.h */ 158 159 FT_BASE_DEF( const char * ) FT_Trace_Get_Name(FT_Int idx)160 FT_Trace_Get_Name( FT_Int idx ) 161 { 162 int max = FT_Trace_Get_Count(); 163 164 165 if ( idx < max ) 166 return ft_trace_toggles[idx]; 167 else 168 return NULL; 169 } 170 171 172 /* documentation is in ftdebug.h */ 173 174 FT_BASE_DEF( void ) FT_Trace_Disable(void)175 FT_Trace_Disable( void ) 176 { 177 ft_trace_levels = ft_trace_levels_disabled; 178 } 179 180 181 /* documentation is in ftdebug.h */ 182 183 FT_BASE_DEF( void ) FT_Trace_Enable(void)184 FT_Trace_Enable( void ) 185 { 186 ft_trace_levels = ft_trace_levels_enabled; 187 } 188 189 190 /************************************************************************** 191 * 192 * Initialize the tracing sub-system. This is done by retrieving the 193 * value of the `FT2_DEBUG' environment variable. It must be a list of 194 * toggles, separated by spaces, `;', or `,'. Example: 195 * 196 * export FT2_DEBUG="any:3 memory:7 stream:5" 197 * 198 * This requests that all levels be set to 3, except the trace level for 199 * the memory and stream components which are set to 7 and 5, 200 * respectively. 201 * 202 * See the file `include/freetype/internal/fttrace.h' for details of 203 * the available toggle names. 204 * 205 * The level must be between 0 and 7; 0 means quiet (except for serious 206 * runtime errors), and 7 means _very_ verbose. 207 */ 208 FT_BASE_DEF( void ) ft_debug_init(void)209 ft_debug_init( void ) 210 { 211 const char* ft2_debug = getenv( "FT2_DEBUG" ); 212 213 214 if ( ft2_debug ) 215 { 216 const char* p = ft2_debug; 217 const char* q; 218 219 220 for ( ; *p; p++ ) 221 { 222 /* skip leading whitespace and separators */ 223 if ( *p == ' ' || *p == '\t' || *p == ',' || *p == ';' || *p == '=' ) 224 continue; 225 226 /* read toggle name, followed by ':' */ 227 q = p; 228 while ( *p && *p != ':' ) 229 p++; 230 231 if ( !*p ) 232 break; 233 234 if ( *p == ':' && p > q ) 235 { 236 FT_Int n, i, len = (FT_Int)( p - q ); 237 FT_Int level = -1, found = -1; 238 239 240 for ( n = 0; n < trace_count; n++ ) 241 { 242 const char* toggle = ft_trace_toggles[n]; 243 244 245 for ( i = 0; i < len; i++ ) 246 { 247 if ( toggle[i] != q[i] ) 248 break; 249 } 250 251 if ( i == len && toggle[i] == 0 ) 252 { 253 found = n; 254 break; 255 } 256 } 257 258 /* read level */ 259 p++; 260 if ( *p ) 261 { 262 level = *p - '0'; 263 if ( level < 0 || level > 7 ) 264 level = -1; 265 } 266 267 if ( found >= 0 && level >= 0 ) 268 { 269 if ( found == trace_any ) 270 { 271 /* special case for `any' */ 272 for ( n = 0; n < trace_count; n++ ) 273 ft_trace_levels_enabled[n] = level; 274 } 275 else 276 ft_trace_levels_enabled[found] = level; 277 } 278 } 279 } 280 } 281 282 ft_trace_levels = ft_trace_levels_enabled; 283 } 284 285 286 #else /* !FT_DEBUG_LEVEL_TRACE */ 287 288 289 FT_BASE_DEF( void ) ft_debug_init(void)290 ft_debug_init( void ) 291 { 292 /* nothing */ 293 } 294 295 296 FT_BASE_DEF( FT_Int ) FT_Trace_Get_Count(void)297 FT_Trace_Get_Count( void ) 298 { 299 return 0; 300 } 301 302 303 FT_BASE_DEF( const char * ) FT_Trace_Get_Name(FT_Int idx)304 FT_Trace_Get_Name( FT_Int idx ) 305 { 306 FT_UNUSED( idx ); 307 308 return NULL; 309 } 310 311 312 FT_BASE_DEF( void ) FT_Trace_Disable(void)313 FT_Trace_Disable( void ) 314 { 315 /* nothing */ 316 } 317 318 319 /* documentation is in ftdebug.h */ 320 321 FT_BASE_DEF( void ) FT_Trace_Enable(void)322 FT_Trace_Enable( void ) 323 { 324 /* nothing */ 325 } 326 327 328 #endif /* !FT_DEBUG_LEVEL_TRACE */ 329 330 331 /* END */ 332