1 /****************************************************************************
   2  *
   3  * ftdebug.c
   4  *
   5  *   Debugging and logging component (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   /* documentation is in ftdebug.h */
  52 
  53   FT_BASE_DEF( void )
  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 )
  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 )
  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 )
 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 * )
 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 )
 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 )
 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 )
 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 )
 278   ft_debug_init( void )
 279   {
 280     /* nothing */
 281   }
 282 
 283 
 284   FT_BASE_DEF( FT_Int )
 285   FT_Trace_Get_Count( void )
 286   {
 287     return 0;
 288   }
 289 
 290 
 291   FT_BASE_DEF( const char * )
 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 )
 301   FT_Trace_Disable( void )
 302   {
 303     /* nothing */
 304   }
 305 
 306 
 307   /* documentation is in ftdebug.h */
 308 
 309   FT_BASE_DEF( void )
 310   FT_Trace_Enable( void )
 311   {
 312     /* nothing */
 313   }
 314 
 315 
 316 #endif /* !FT_DEBUG_LEVEL_TRACE */
 317 
 318 
 319 /* END */