tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ftdebug.c (15423B)


      1 /****************************************************************************
      2 *
      3 * ftdebug.c
      4 *
      5 *   Debugging and logging component for Win32 (body).
      6 *
      7 * Copyright (C) 1996-2025 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/ftlogging.h>
     46 #include <freetype/internal/ftdebug.h>
     47 #include <freetype/internal/ftobjs.h>
     48 
     49 
     50 #ifdef FT_DEBUG_LOGGING
     51 
     52  /**************************************************************************
     53   *
     54   * Variables used to control logging.
     55   *
     56   * 1. `ft_default_trace_level` stores the value of trace levels, which are
     57   *    provided to FreeType using the `FT2_DEBUG` environment variable.
     58   *
     59   * 2. `ft_fileptr` stores the `FILE*` handle.
     60   *
     61   * 3. `ft_component` is a string that holds the name of `FT_COMPONENT`.
     62   *
     63   * 4. The flag `ft_component_flag` prints the name of `FT_COMPONENT` along
     64   *    with the actual log message if set to true.
     65   *
     66   * 5. The flag `ft_timestamp_flag` prints time along with the actual log
     67   *    message if set to true.
     68   *
     69   * 6. `ft_have_newline_char` is used to differentiate between a log
     70   *    message with and without a trailing newline character.
     71   *
     72   * 7. `ft_custom_trace_level` stores the custom trace level value, which
     73   *    is provided by the user at run-time.
     74   *
     75   * We use `static` to avoid 'unused variable' warnings.
     76   *
     77   */
     78  static const char*  ft_default_trace_level = NULL;
     79  static FILE*        ft_fileptr             = NULL;
     80  static const char*  ft_component           = NULL;
     81  static FT_Bool      ft_component_flag      = FALSE;
     82  static FT_Bool      ft_timestamp_flag      = FALSE;
     83  static FT_Bool      ft_have_newline_char   = TRUE;
     84  static const char*  ft_custom_trace_level  = NULL;
     85 
     86  /* declared in ftdebug.h */
     87 
     88  dlg_handler            ft_default_log_handler = NULL;
     89  FT_Custom_Log_Handler  custom_output_handler  = NULL;
     90 
     91 #endif /* FT_DEBUG_LOGGING */
     92 
     93 
     94 #ifdef FT_DEBUG_LEVEL_ERROR
     95 
     96 #define WIN32_LEAN_AND_MEAN
     97 #include <windows.h>
     98 
     99 
    100 #ifdef _WIN32_WCE
    101 
    102  FT_LOACAL_DEF( void )
    103  OutputDebugStringA( LPCSTR lpOutputString )
    104  {
    105    int            len;
    106    LPWSTR         lpOutputStringW;
    107 
    108 
    109    /* allocate memory space for converted string */
    110    len = MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
    111                               lpOutputString, -1, NULL, 0 );
    112 
    113    lpOutputStringW = (LPWSTR)_alloca( len * sizeof ( WCHAR ) );
    114 
    115    if ( !len || !lpOutputStringW )
    116      return;
    117 
    118    /* now it is safe to do the translation */
    119    MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
    120                         lpOutputString, -1, lpOutputStringW, len );
    121 
    122    OutputDebugStringW( lpOutputStringW );
    123  }
    124 
    125 #endif /* _WIN32_WCE */
    126 
    127 
    128  /* documentation is in ftdebug.h */
    129 
    130  FT_BASE_DEF( void )
    131  FT_Message( const char*  fmt,
    132              ... )
    133  {
    134    va_list  ap;
    135 
    136 
    137    va_start( ap, fmt );
    138    vfprintf( stderr, fmt, ap );
    139 #if ( defined( _WIN32_WINNT ) && _WIN32_WINNT >= 0x0400 ) || \
    140    ( defined( _WIN32_WCE )   && _WIN32_WCE   >= 0x0600 )
    141    if ( IsDebuggerPresent() )
    142    {
    143      static char  buf[1024];
    144 
    145 
    146      vsnprintf( buf, sizeof buf, fmt, ap );
    147      OutputDebugStringA( buf );
    148    }
    149 #endif
    150    va_end( ap );
    151  }
    152 
    153 
    154  /* documentation is in ftdebug.h */
    155 
    156  FT_BASE_DEF( void )
    157  FT_Panic( const char*  fmt,
    158            ... )
    159  {
    160    va_list  ap;
    161 
    162 
    163    va_start( ap, fmt );
    164    vfprintf( stderr, fmt, ap );
    165 #if ( defined( _WIN32_WINNT ) && _WIN32_WINNT >= 0x0400 ) || \
    166    ( defined( _WIN32_WCE )   && _WIN32_WCE   >= 0x0600 )
    167    if ( IsDebuggerPresent() )
    168    {
    169      static char  buf[1024];
    170 
    171 
    172      vsnprintf( buf, sizeof buf, fmt, ap );
    173      OutputDebugStringA( buf );
    174    }
    175 #endif
    176    va_end( ap );
    177 
    178    exit( EXIT_FAILURE );
    179  }
    180 
    181 
    182  /* documentation is in ftdebug.h */
    183 
    184  FT_BASE_DEF( int )
    185  FT_Throw( FT_Error     error,
    186            int          line,
    187            const char*  file )
    188  {
    189 #if 0
    190    /* activating the code in this block makes FreeType very chatty */
    191    fprintf( stderr,
    192             "%s:%d: error 0x%02x: %s\n",
    193             file,
    194             line,
    195             error,
    196             FT_Error_String( error ) );
    197 #else
    198    FT_UNUSED( error );
    199    FT_UNUSED( line );
    200    FT_UNUSED( file );
    201 #endif
    202 
    203    return 0;
    204  }
    205 
    206 #endif /* FT_DEBUG_LEVEL_ERROR */
    207 
    208 
    209 #ifdef FT_DEBUG_LEVEL_TRACE
    210 
    211  /* array of trace levels, initialized to 0; */
    212  /* this gets adjusted at run-time           */
    213  static int  ft_trace_levels_enabled[trace_count];
    214 
    215  /* array of trace levels, always initialized to 0 */
    216  static int  ft_trace_levels_disabled[trace_count];
    217 
    218  /* a pointer to either `ft_trace_levels_enabled' */
    219  /* or `ft_trace_levels_disabled'                 */
    220  int*  ft_trace_levels;
    221 
    222  /* define array of trace toggle names */
    223 #define FT_TRACE_DEF( x )  #x ,
    224 
    225  static const char*  ft_trace_toggles[trace_count + 1] =
    226  {
    227 #include <freetype/internal/fttrace.h>
    228    NULL
    229  };
    230 
    231 #undef FT_TRACE_DEF
    232 
    233 
    234  /* documentation is in ftdebug.h */
    235 
    236  FT_BASE_DEF( FT_Int )
    237  FT_Trace_Get_Count( void )
    238  {
    239    return trace_count;
    240  }
    241 
    242 
    243  /* documentation is in ftdebug.h */
    244 
    245  FT_BASE_DEF( const char * )
    246  FT_Trace_Get_Name( FT_Int  idx )
    247  {
    248    int  max = FT_Trace_Get_Count();
    249 
    250 
    251    if ( idx < max )
    252      return ft_trace_toggles[idx];
    253    else
    254      return NULL;
    255  }
    256 
    257 
    258  /* documentation is in ftdebug.h */
    259 
    260  FT_BASE_DEF( void )
    261  FT_Trace_Disable( void )
    262  {
    263    ft_trace_levels = ft_trace_levels_disabled;
    264  }
    265 
    266 
    267  /* documentation is in ftdebug.h */
    268 
    269  FT_BASE_DEF( void )
    270  FT_Trace_Enable( void )
    271  {
    272    ft_trace_levels = ft_trace_levels_enabled;
    273  }
    274 
    275 
    276  /**************************************************************************
    277   *
    278   * Initialize the tracing sub-system.  This is done by retrieving the
    279   * value of the `FT2_DEBUG' environment variable.  It must be a list of
    280   * toggles, separated by spaces, `;', or `,'.  Example:
    281   *
    282   *   export FT2_DEBUG="any:3 memory:7 stream:5"
    283   *
    284   * This requests that all levels be set to 3, except the trace level for
    285   * the memory and stream components which are set to 7 and 5,
    286   * respectively.
    287   *
    288   * See the file `include/freetype/internal/fttrace.h' for details of
    289   * the available toggle names.
    290   *
    291   * The level must be between 0 and 7; 0 means quiet (except for serious
    292   * runtime errors), and 7 means _very_ verbose.
    293   */
    294  FT_BASE_DEF( void )
    295  ft_debug_init( void )
    296  {
    297    const char*  ft2_debug = NULL;
    298 
    299 
    300 #ifdef FT_DEBUG_LOGGING
    301    if ( ft_custom_trace_level != NULL )
    302      ft2_debug = ft_custom_trace_level;
    303    else
    304      ft2_debug = ft_default_trace_level;
    305 #else
    306    ft2_debug = ft_getenv( "FT2_DEBUG" );
    307 #endif
    308 
    309    if ( ft2_debug )
    310    {
    311      const char*  p = ft2_debug;
    312      const char*  q;
    313 
    314 
    315      for ( ; *p; p++ )
    316      {
    317        /* skip leading whitespace and separators */
    318        if ( *p == ' ' || *p == '\t' || *p == ',' || *p == ';' || *p == '=' )
    319          continue;
    320 
    321 #ifdef FT_DEBUG_LOGGING
    322 
    323        /* check extra arguments for logging */
    324        if ( *p == '-' )
    325        {
    326          const char*  r = ++p;
    327 
    328 
    329          if ( *r == 'v' )
    330          {
    331            const char*  s = ++r;
    332 
    333 
    334            ft_component_flag = TRUE;
    335 
    336            if ( *s == 't' )
    337            {
    338              ft_timestamp_flag = TRUE;
    339              p++;
    340            }
    341 
    342            p++;
    343          }
    344 
    345          else if ( *r == 't' )
    346          {
    347            const char*  s = ++r;
    348 
    349 
    350            ft_timestamp_flag = TRUE;
    351 
    352            if ( *s == 'v' )
    353            {
    354              ft_component_flag = TRUE;
    355              p++;
    356            }
    357 
    358            p++;
    359          }
    360        }
    361 
    362 #endif /* FT_DEBUG_LOGGING */
    363 
    364        /* read toggle name, followed by ':' */
    365        q = p;
    366        while ( *p && *p != ':' )
    367          p++;
    368 
    369        if ( !*p )
    370          break;
    371 
    372        if ( *p == ':' && p > q )
    373        {
    374          FT_Int  n, i, len = (FT_Int)( p - q );
    375          FT_Int  level = -1, found = -1;
    376 
    377 
    378          for ( n = 0; n < trace_count; n++ )
    379          {
    380            const char*  toggle = ft_trace_toggles[n];
    381 
    382 
    383            for ( i = 0; i < len; i++ )
    384            {
    385              if ( toggle[i] != q[i] )
    386                break;
    387            }
    388 
    389            if ( i == len && toggle[i] == 0 )
    390            {
    391              found = n;
    392              break;
    393            }
    394          }
    395 
    396          /* read level */
    397          p++;
    398          if ( *p )
    399          {
    400            level = *p - '0';
    401            if ( level < 0 || level > 7 )
    402              level = -1;
    403          }
    404 
    405          if ( found >= 0 && level >= 0 )
    406          {
    407            if ( found == trace_any )
    408            {
    409              /* special case for `any' */
    410              for ( n = 0; n < trace_count; n++ )
    411                ft_trace_levels_enabled[n] = level;
    412            }
    413            else
    414              ft_trace_levels_enabled[found] = level;
    415          }
    416        }
    417      }
    418    }
    419 
    420    ft_trace_levels = ft_trace_levels_enabled;
    421  }
    422 
    423 
    424 #else  /* !FT_DEBUG_LEVEL_TRACE */
    425 
    426 
    427  FT_BASE_DEF( void )
    428  ft_debug_init( void )
    429  {
    430    /* nothing */
    431  }
    432 
    433 
    434  FT_BASE_DEF( FT_Int )
    435  FT_Trace_Get_Count( void )
    436  {
    437    return 0;
    438  }
    439 
    440 
    441  FT_BASE_DEF( const char * )
    442  FT_Trace_Get_Name( FT_Int  idx )
    443  {
    444    FT_UNUSED( idx );
    445 
    446    return NULL;
    447  }
    448 
    449 
    450  FT_BASE_DEF( void )
    451  FT_Trace_Disable( void )
    452  {
    453    /* nothing */
    454  }
    455 
    456 
    457  /* documentation is in ftdebug.h */
    458 
    459  FT_BASE_DEF( void )
    460  FT_Trace_Enable( void )
    461  {
    462    /* nothing */
    463  }
    464 
    465 #endif /* !FT_DEBUG_LEVEL_TRACE */
    466 
    467 
    468 #ifdef FT_DEBUG_LOGGING
    469 
    470  /**************************************************************************
    471   *
    472   * Initialize and de-initialize 'dlg' library.
    473   *
    474   */
    475 
    476  FT_BASE_DEF( void )
    477  ft_logging_init( void )
    478  {
    479    ft_default_log_handler = ft_log_handler;
    480    ft_default_trace_level = ft_getenv( "FT2_DEBUG" );
    481 
    482    if ( ft_getenv( "FT_LOGGING_FILE" ) )
    483      ft_fileptr = ft_fopen( ft_getenv( "FT_LOGGING_FILE" ), "w" );
    484    else
    485      ft_fileptr = stderr;
    486 
    487    ft_debug_init();
    488 
    489    /* Set the default output handler for 'dlg'. */
    490    dlg_set_handler( ft_default_log_handler, NULL );
    491  }
    492 
    493 
    494  FT_BASE_DEF( void )
    495  ft_logging_deinit( void )
    496  {
    497    if ( ft_fileptr != stderr )
    498      ft_fclose( ft_fileptr );
    499  }
    500 
    501 
    502  /**************************************************************************
    503   *
    504   * An output log handler for FreeType.
    505   *
    506   */
    507  FT_BASE_DEF( void )
    508  ft_log_handler( const struct dlg_origin*  origin,
    509                  const char*               string,
    510                  void*                     data )
    511  {
    512    char         features_buf[128];
    513    char*        bufp = features_buf;
    514 
    515    FT_UNUSED( data );
    516 
    517 
    518    if ( ft_have_newline_char )
    519    {
    520      const char*  features        = NULL;
    521      size_t       features_length = 0;
    522 
    523 
    524 #define FEATURES_TIMESTAMP            "[%h:%m] "
    525 #define FEATURES_COMPONENT            "[%t] "
    526 #define FEATURES_TIMESTAMP_COMPONENT  "[%h:%m %t] "
    527 
    528      if ( ft_timestamp_flag && ft_component_flag )
    529      {
    530        features        = FEATURES_TIMESTAMP_COMPONENT;
    531        features_length = sizeof ( FEATURES_TIMESTAMP_COMPONENT );
    532      }
    533      else if ( ft_timestamp_flag )
    534      {
    535        features        = FEATURES_TIMESTAMP;
    536        features_length = sizeof ( FEATURES_TIMESTAMP );
    537      }
    538      else if ( ft_component_flag )
    539      {
    540        features        = FEATURES_COMPONENT;
    541        features_length = sizeof ( FEATURES_COMPONENT );
    542      }
    543 
    544      if ( ft_component_flag || ft_timestamp_flag )
    545      {
    546        ft_strncpy( features_buf, features, features_length );
    547        bufp += features_length - 1;
    548      }
    549 
    550      if ( ft_component_flag )
    551      {
    552        size_t  tag_length = ft_strlen( *origin->tags );
    553        size_t  i;
    554 
    555 
    556        /* To vertically align tracing messages we compensate the */
    557        /* different FT_COMPONENT string lengths by inserting an  */
    558        /* appropriate amount of space characters.                */
    559        for ( i = 0;
    560              i < FT_MAX_TRACE_LEVEL_LENGTH - tag_length;
    561              i++ )
    562          *bufp++ = ' ';
    563      }
    564    }
    565 
    566    /* Finally add the format string for the tracing message. */
    567    *bufp++ = '%';
    568    *bufp++ = 'c';
    569    *bufp   = '\0';
    570 
    571    dlg_generic_outputf_stream( ft_fileptr,
    572                                (const char*)features_buf,
    573                                origin,
    574                                string,
    575                                dlg_default_output_styles,
    576                                true );
    577 
    578    if ( ft_strrchr( string, '\n' ) )
    579      ft_have_newline_char = TRUE;
    580    else
    581      ft_have_newline_char = FALSE;
    582  }
    583 
    584 
    585  /* documentation is in ftdebug.h */
    586  FT_BASE_DEF( void )
    587  ft_add_tag( const char*  tag )
    588  {
    589    ft_component = tag;
    590 
    591    dlg_add_tag( tag, NULL );
    592  }
    593 
    594 
    595  /* documentation is in ftdebug.h */
    596  FT_BASE_DEF( void )
    597  ft_remove_tag( const char*  tag )
    598  {
    599    dlg_remove_tag( tag, NULL );
    600  }
    601 
    602 
    603  /* documentation is in ftlogging.h */
    604 
    605  FT_EXPORT_DEF( void )
    606  FT_Trace_Set_Level( const char*  level )
    607  {
    608    ft_component_flag     = FALSE;
    609    ft_timestamp_flag     = FALSE;
    610    ft_custom_trace_level = level;
    611 
    612    ft_debug_init();
    613  }
    614 
    615 
    616  /* documentation is in ftlogging.h */
    617 
    618  FT_EXPORT_DEF( void )
    619  FT_Trace_Set_Default_Level( void )
    620  {
    621    ft_component_flag     = FALSE;
    622    ft_timestamp_flag     = FALSE;
    623    ft_custom_trace_level = NULL;
    624 
    625    ft_debug_init();
    626  }
    627 
    628 
    629  /**************************************************************************
    630   *
    631   * Functions to handle a custom log handler.
    632   *
    633   */
    634 
    635  /* documentation is in ftlogging.h */
    636 
    637  FT_EXPORT_DEF( void )
    638  FT_Set_Log_Handler( FT_Custom_Log_Handler  handler )
    639  {
    640    custom_output_handler = handler;
    641  }
    642 
    643 
    644  /* documentation is in ftlogging.h */
    645 
    646  FT_EXPORT_DEF( void )
    647  FT_Set_Default_Log_Handler( void )
    648  {
    649    custom_output_handler = NULL;
    650  }
    651 
    652 
    653  /* documentation is in ftdebug.h */
    654  FT_BASE_DEF( void )
    655  FT_Logging_Callback( const char*  fmt,
    656                       ... )
    657  {
    658    va_list  ap;
    659 
    660 
    661    va_start( ap, fmt );
    662    custom_output_handler( ft_component, fmt, ap );
    663    va_end( ap );
    664  }
    665 
    666 #else /* !FT_DEBUG_LOGGING */
    667 
    668  FT_EXPORT_DEF( void )
    669  FT_Trace_Set_Level( const char*  level )
    670  {
    671    FT_UNUSED( level );
    672  }
    673 
    674 
    675  FT_EXPORT_DEF( void )
    676  FT_Trace_Set_Default_Level( void )
    677  {
    678    /* nothing */
    679  }
    680 
    681 
    682  FT_EXPORT_DEF( void )
    683  FT_Set_Log_Handler( FT_Custom_Log_Handler  handler )
    684  {
    685    FT_UNUSED( handler );
    686  }
    687 
    688 
    689  FT_EXPORT_DEF( void )
    690  FT_Set_Default_Log_Handler( void )
    691  {
    692    /* nothing */
    693  }
    694 
    695 #endif /* !FT_DEBUG_LOGGING */
    696 
    697 
    698 /* END */