text: /****************************************************************************
   *
   * ftdebug.c
   *
   *   Debugging and logging component (body).
   *
   * Copyright 1996-2018 by
   * David Turner, Robert Wilhelm, and Werner Lemberg.
   *
   * This file is part of the FreeType project, and may only be used,
   * modified, and distributed under the terms of the FreeType project
   * license, LICENSE.TXT.  By continuing to use, modify, or distribute
   * this file you indicate that you have read the license and
   * understand and accept it fully.
   *
   */
  
  
    /**************************************************************************
     *
     * This component contains various macros and functions used to ease the
     * debugging of the FreeType engine.  Its main purpose is in assertion
     * checking, tracing, and error detection.
     *
     * There are now three debugging modes:
     *
     * - trace mode
     *
     *   Error and trace messages are sent to the log file (which can be the
     *   standard error output).
     *
     * - error mode
     *
     *   Only error messages are generated.
     *
     * - release mode:
     *
     *   No error message is sent or generated.  The code is free from any
     *   debugging parts.
     *
     */
  
  
  #include <ft2build.h>
  #include FT_FREETYPE_H
  #include FT_INTERNAL_DEBUG_H
  
  
  #ifdef FT_DEBUG_LEVEL_ERROR
  
    /* documentation is in ftdebug.h */
  
    FT_BASE_DEF( void )
    FT_Message( const char*  fmt,
                ... )
    {
      va_list  ap;
  
  
      va_start( ap, fmt );
      vfprintf( stderr, fmt, ap );
      va_end( ap );
    }
  
  
    /* documentation is in ftdebug.h */
  
    FT_BASE_DEF( void )
    FT_Panic( const char*  fmt,
              ... )
    {
      va_list  ap;
  
  
      va_start( ap, fmt );
      vfprintf( stderr, fmt, ap );
      va_end( ap );
  
      exit( EXIT_FAILURE );
    }
  
  
    /* documentation is in ftdebug.h */
  
    FT_BASE_DEF( int )
    FT_Throw( FT_Error     error,
              int          line,
              const char*  file )
    {
  #if 0
      /* activating the code in this block makes FreeType very chatty */
      fprintf( stderr,
               "%s:%d: error 0x%02x: %s\n",
               file,
               line,
               error,
               FT_Error_String( error ) );
  #else
      FT_UNUSED( error );
      FT_UNUSED( line );
      FT_UNUSED( file );
  #endif
  
      return 0;
    }
  
  #endif /* FT_DEBUG_LEVEL_ERROR */
  
  
  
  #ifdef FT_DEBUG_LEVEL_TRACE
  
    /* array of trace levels, initialized to 0; */
    /* this gets adjusted at run-time           */
    static int  ft_trace_levels_enabled[trace_count];
  
    /* array of trace levels, always initialized to 0 */
    static int  ft_trace_levels_disabled[trace_count];
  
    /* a pointer to either `ft_trace_levels_enabled' */
    /* or `ft_trace_levels_disabled'                 */
    int*  ft_trace_levels;
  
    /* define array of trace toggle names */
  #define FT_TRACE_DEF( x )  #x ,
  
    static const char*  ft_trace_toggles[trace_count + 1] =
    {
  #include FT_INTERNAL_TRACE_H
      NULL
    };
  
  #undef FT_TRACE_DEF
  
  
    /* documentation is in ftdebug.h */
  
    FT_BASE_DEF( FT_Int )
    FT_Trace_Get_Count( void )
    {
      return trace_count;
    }
  
  
    /* documentation is in ftdebug.h */
  
    FT_BASE_DEF( const char * )
    FT_Trace_Get_Name( FT_Int  idx )
    {
      int  max = FT_Trace_Get_Count();
  
  
      if ( idx < max )
        return ft_trace_toggles[idx];
      else
        return NULL;
    }
  
  
    /* documentation is in ftdebug.h */
  
    FT_BASE_DEF( void )
    FT_Trace_Disable( void )
    {
      ft_trace_levels = ft_trace_levels_disabled;
    }
  
  
    /* documentation is in ftdebug.h */
  
    FT_BASE_DEF( void )
    FT_Trace_Enable( void )
    {
      ft_trace_levels = ft_trace_levels_enabled;
    }
  
  
    /**************************************************************************
     *
     * Initialize the tracing sub-system.  This is done by retrieving the
     * value of the `FT2_DEBUG' environment variable.  It must be a list of
     * toggles, separated by spaces, `;', or `,'.  Example:
     *
     *   export FT2_DEBUG="any:3 memory:7 stream:5"
     *
     * This requests that all levels be set to 3, except the trace level for
     * the memory and stream components which are set to 7 and 5,
     * respectively.
     *
     * See the file `include/freetype/internal/fttrace.h' for details of
     * the available toggle names.
     *
     * The level must be between 0 and 7; 0 means quiet (except for serious
     * runtime errors), and 7 means _very_ verbose.
     */
    FT_BASE_DEF( void )
    ft_debug_init( void )
    {
      const char*  ft2_debug = ft_getenv( "FT2_DEBUG" );
  
  
      if ( ft2_debug )
      {
        const char*  p = ft2_debug;
        const char*  q;
  
  
        for ( ; *p; p++ )
        {
          /* skip leading whitespace and separators */
          if ( *p == ' ' || *p == '\t' || *p == ',' || *p == ';' || *p == '=' )
            continue;
  
          /* read toggle name, followed by ':' */
          q = p;
          while ( *p && *p != ':' )
            p++;
  
          if ( !*p )
            break;
  
          if ( *p == ':' && p > q )
          {
            FT_Int  n, i, len = (FT_Int)( p - q );
            FT_Int  level = -1, found = -1;
  
  
            for ( n = 0; n < trace_count; n++ )
            {
              const char*  toggle = ft_trace_toggles[n];
  
  
              for ( i = 0; i < len; i++ )
              {
                if ( toggle[i] != q[i] )
                  break;
              }
  
              if ( i == len && toggle[i] == 0 )
              {
                found = n;
                break;
              }
            }
  
            /* read level */
            p++;
            if ( *p )
            {
              level = *p - '0';
              if ( level < 0 || level > 7 )
                level = -1;
            }
  
            if ( found >= 0 && level >= 0 )
            {
              if ( found == trace_any )
              {
                /* special case for `any' */
                for ( n = 0; n < trace_count; n++ )
                  ft_trace_levels_enabled[n] = level;
              }
              else
                ft_trace_levels_enabled[found] = level;
            }
          }
        }
      }
  
      ft_trace_levels = ft_trace_levels_enabled;
    }
  
  
  #else  /* !FT_DEBUG_LEVEL_TRACE */
  
  
    FT_BASE_DEF( void )
    ft_debug_init( void )
    {
      /* nothing */
    }
  
  
    FT_BASE_DEF( FT_Int )
    FT_Trace_Get_Count( void )
    {
      return 0;
    }
  
  
    FT_BASE_DEF( const char * )
    FT_Trace_Get_Name( FT_Int  idx )
    {
      FT_UNUSED( idx );
  
      return NULL;
    }
  
  
    FT_BASE_DEF( void )
    FT_Trace_Disable( void )
    {
      /* nothing */
    }
  
  
    /* documentation is in ftdebug.h */
  
    FT_BASE_DEF( void )
    FT_Trace_Enable( void )
    {
      /* nothing */
    }
  
  
  #endif /* !FT_DEBUG_LEVEL_TRACE */
  
  
  /* END */
  