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 <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