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