tor-browser

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

ftdebug.c (14105B)


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