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