tor-browser

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

hb-debug.hh (12077B)


      1 /*
      2 * Copyright © 2017  Google, Inc.
      3 *
      4 *  This is part of HarfBuzz, a text shaping library.
      5 *
      6 * Permission is hereby granted, without written agreement and without
      7 * license or royalty fees, to use, copy, modify, and distribute this
      8 * software and its documentation for any purpose, provided that the
      9 * above copyright notice and the following two paragraphs appear in
     10 * all copies of this software.
     11 *
     12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     16 * DAMAGE.
     17 *
     18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     20 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     23 *
     24 * Google Author(s): Behdad Esfahbod
     25 */
     26 
     27 #ifndef HB_DEBUG_HH
     28 #define HB_DEBUG_HH
     29 
     30 #include "hb.hh"
     31 #include "hb-atomic.hh"
     32 #include "hb-algs.hh"
     33 
     34 
     35 #ifndef HB_DEBUG
     36 #define HB_DEBUG 0
     37 #endif
     38 
     39 
     40 /*
     41 * Debug output (needs enabling at compile time.)
     42 */
     43 
     44 static inline bool
     45 _hb_debug (unsigned int level,
     46    unsigned int max_level)
     47 {
     48  return level < max_level;
     49 }
     50 
     51 #define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
     52 #define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
     53 
     54 static inline void
     55 _hb_print_func (const char *func)
     56 {
     57  if (func)
     58  {
     59    unsigned int func_len = strlen (func);
     60    /* Skip "static" */
     61    if (0 == strncmp (func, "static ", 7))
     62      func += 7;
     63    /* Skip "typename" */
     64    if (0 == strncmp (func, "typename ", 9))
     65      func += 9;
     66    /* Skip return type */
     67    const char *space = strchr (func, ' ');
     68    if (space)
     69      func = space + 1;
     70    /* Skip parameter list */
     71    const char *paren = strchr (func, '(');
     72    if (paren)
     73      func_len = paren - func;
     74    fprintf (stderr, "%.*s", (int) func_len, func);
     75  }
     76 }
     77 
     78 template <int max_level> static inline void
     79 _hb_debug_msg_va (const char *what,
     80 	  const void *obj,
     81 	  const char *func,
     82 	  bool indented,
     83 	  unsigned int level,
     84 	  int level_dir,
     85 	  const char *message,
     86 	  va_list ap) HB_PRINTF_FUNC(7, 0);
     87 template <int max_level> static inline void
     88 _hb_debug_msg_va (const char *what,
     89 	  const void *obj,
     90 	  const char *func,
     91 	  bool indented,
     92 	  unsigned int level,
     93 	  int level_dir,
     94 	  const char *message,
     95 	  va_list ap)
     96 {
     97  if (!_hb_debug (level, max_level))
     98    return;
     99 
    100  fprintf (stderr, "%-10s", what ? what : "");
    101 
    102  if (obj)
    103    fprintf (stderr, "(%*p) ", (int) (2 * sizeof (void *)), obj);
    104  else
    105    fprintf (stderr, " %*s  ", (int) (2 * sizeof (void *)), "");
    106 
    107  if (indented) {
    108 #define VBAR	"\342\224\202"	/* U+2502 BOX DRAWINGS LIGHT VERTICAL */
    109 #define VRBAR	"\342\224\234"	/* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
    110 #define DLBAR	"\342\225\256"	/* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
    111 #define ULBAR	"\342\225\257"	/* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
    112 #define LBAR	"\342\225\264"	/* U+2574 BOX DRAWINGS LIGHT LEFT */
    113    static const char bars[] =
    114      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
    115      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
    116      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
    117      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
    118      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
    119    fprintf (stderr, "%2u %s" VRBAR "%s",
    120      level,
    121      bars + sizeof (bars) - 1 - hb_min ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
    122      level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
    123  } else
    124    fprintf (stderr, "   " VRBAR LBAR);
    125 
    126  _hb_print_func (func);
    127 
    128  if (message)
    129  {
    130    fprintf (stderr, ": ");
    131    vfprintf (stderr, message, ap);
    132  }
    133 
    134  fprintf (stderr, "\n");
    135 }
    136 template <> inline void HB_PRINTF_FUNC(7, 0)
    137 _hb_debug_msg_va<0> (const char *what HB_UNUSED,
    138 	     const void *obj HB_UNUSED,
    139 	     const char *func HB_UNUSED,
    140 	     bool indented HB_UNUSED,
    141 	     unsigned int level HB_UNUSED,
    142 	     int level_dir HB_UNUSED,
    143 	     const char *message HB_UNUSED,
    144 	     va_list ap HB_UNUSED) {}
    145 
    146 template <int max_level> static inline void
    147 _hb_debug_msg (const char *what,
    148        const void *obj,
    149        const char *func,
    150        bool indented,
    151        unsigned int level,
    152        int level_dir,
    153        const char *message,
    154        ...) HB_PRINTF_FUNC(7, 8);
    155 template <int max_level> static inline void HB_PRINTF_FUNC(7, 8)
    156 _hb_debug_msg (const char *what,
    157        const void *obj,
    158        const char *func,
    159        bool indented,
    160        unsigned int level,
    161        int level_dir,
    162        const char *message,
    163        ...)
    164 {
    165  va_list ap;
    166  va_start (ap, message);
    167  _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
    168  va_end (ap);
    169 }
    170 template <> inline void
    171 _hb_debug_msg<0> (const char *what HB_UNUSED,
    172 	  const void *obj HB_UNUSED,
    173 	  const char *func HB_UNUSED,
    174 	  bool indented HB_UNUSED,
    175 	  unsigned int level HB_UNUSED,
    176 	  int level_dir HB_UNUSED,
    177 	  const char *message HB_UNUSED,
    178 	  ...) HB_PRINTF_FUNC(7, 8);
    179 template <> inline void HB_PRINTF_FUNC(7, 8)
    180 _hb_debug_msg<0> (const char *what HB_UNUSED,
    181 	  const void *obj HB_UNUSED,
    182 	  const char *func HB_UNUSED,
    183 	  bool indented HB_UNUSED,
    184 	  unsigned int level HB_UNUSED,
    185 	  int level_dir HB_UNUSED,
    186 	  const char *message HB_UNUSED,
    187 	  ...) {}
    188 
    189 #define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...)	_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr,    true, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
    190 #define DEBUG_MSG(WHAT, OBJ, ...)				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr,    false, 0, 0, __VA_ARGS__)
    191 #define DEBUG_MSG_FUNC(WHAT, OBJ, ...)				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
    192 
    193 
    194 /*
    195 * Printer
    196 */
    197 
    198 template <typename T>
    199 struct hb_printer_t {
    200  const char *print (const T&) { return "something"; }
    201 };
    202 
    203 template <>
    204 struct hb_printer_t<bool> {
    205  const char *print (bool v) { return v ? "true" : "false"; }
    206 };
    207 
    208 template <>
    209 struct hb_printer_t<hb_empty_t> {
    210  const char *print (hb_empty_t) { return ""; }
    211 };
    212 
    213 
    214 /*
    215 * Trace
    216 */
    217 
    218 template <typename T>
    219 static inline void _hb_warn_no_return (bool returned)
    220 {
    221  if (unlikely (!returned)) {
    222    fprintf (stderr, "OUCH, returned with no call to return_trace().  This is a bug, please report.\n");
    223  }
    224 }
    225 template <>
    226 /*static*/ inline void _hb_warn_no_return<hb_empty_t> (bool returned HB_UNUSED) {}
    227 template <>
    228 /*static*/ inline void _hb_warn_no_return<void> (bool returned HB_UNUSED) {}
    229 
    230 template <int max_level, typename ret_t>
    231 struct hb_auto_trace_t
    232 {
    233  explicit inline hb_auto_trace_t (unsigned int *plevel_,
    234 			   const char *what_,
    235 			   const void *obj_,
    236 			   const char *func,
    237 			   const char *message,
    238 			   ...) HB_PRINTF_FUNC(6, 7)
    239 			   : plevel (plevel_), what (what_), obj (obj_), returned (false)
    240  {
    241    if (plevel) ++*plevel;
    242 
    243    va_list ap;
    244    va_start (ap, message);
    245    _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
    246    va_end (ap);
    247  }
    248  ~hb_auto_trace_t ()
    249  {
    250    _hb_warn_no_return<ret_t> (returned);
    251    if (!returned) {
    252      _hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1, " ");
    253    }
    254    if (plevel) --*plevel;
    255  }
    256 
    257  template <typename T>
    258  T ret (T&& v,
    259  const char *func = "",
    260  unsigned int line = 0)
    261  {
    262    if (unlikely (returned)) {
    263      fprintf (stderr, "OUCH, double calls to return_trace().  This is a bug, please report.\n");
    264      return std::forward<T> (v);
    265    }
    266 
    267    _hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
    268 		      "return %s (line %u)",
    269 		      hb_printer_t<hb_decay<decltype (v)>>().print (v), line);
    270    if (plevel) --*plevel;
    271    plevel = nullptr;
    272    returned = true;
    273    return std::forward<T> (v);
    274  }
    275 
    276  private:
    277  unsigned int *plevel;
    278  const char *what;
    279  const void *obj;
    280  bool returned;
    281 };
    282 template <typename ret_t> /* Make sure we don't use hb_auto_trace_t when not tracing. */
    283 struct hb_auto_trace_t<0, ret_t>
    284 {
    285  explicit inline hb_auto_trace_t (unsigned int *plevel_,
    286 			   const char *what_,
    287 			   const void *obj_,
    288 			   const char *func,
    289 			   const char *message,
    290 			   ...) HB_PRINTF_FUNC(6, 7) {}
    291 
    292  template <typename T>
    293  T ret (T&& v,
    294  const char *func HB_UNUSED = nullptr,
    295  unsigned int line HB_UNUSED = 0) { return std::forward<T> (v); }
    296 };
    297 
    298 /* For disabled tracing; optimize out everything.
    299 * https://github.com/harfbuzz/harfbuzz/pull/605 */
    300 template <typename ret_t>
    301 struct hb_no_trace_t {
    302  template <typename T>
    303  T ret (T&& v,
    304  const char *func HB_UNUSED = nullptr,
    305  unsigned int line HB_UNUSED = 0) { return std::forward<T> (v); }
    306 };
    307 
    308 #define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__)
    309 
    310 
    311 /*
    312 * Instances.
    313 */
    314 
    315 #ifndef HB_DEBUG_ARABIC
    316 #define HB_DEBUG_ARABIC (HB_DEBUG+0)
    317 #endif
    318 
    319 #ifndef HB_DEBUG_BLOB
    320 #define HB_DEBUG_BLOB (HB_DEBUG+0)
    321 #endif
    322 
    323 #ifndef HB_DEBUG_CORETEXT
    324 #define HB_DEBUG_CORETEXT (HB_DEBUG+0)
    325 #endif
    326 
    327 #ifndef HB_DEBUG_DIRECTWRITE
    328 #define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
    329 #endif
    330 
    331 #ifndef HB_DEBUG_FT
    332 #define HB_DEBUG_FT (HB_DEBUG+0)
    333 #endif
    334 
    335 #ifndef HB_DEBUG_JUSTIFY
    336 #define HB_DEBUG_JUSTIFY (HB_DEBUG+0)
    337 #endif
    338 
    339 #ifndef HB_DEBUG_OBJECT
    340 #define HB_DEBUG_OBJECT (HB_DEBUG+0)
    341 #endif
    342 
    343 #ifndef HB_DEBUG_SHAPE_PLAN
    344 #define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0)
    345 #endif
    346 
    347 #ifndef HB_DEBUG_UNISCRIBE
    348 #define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
    349 #endif
    350 
    351 #ifndef HB_DEBUG_WASM
    352 #define HB_DEBUG_WASM (HB_DEBUG+0)
    353 #endif
    354 
    355 #ifndef HB_DEBUG_KBTS
    356 #define HB_DEBUG_KBTS (HB_DEBUG+0)
    357 #endif
    358 
    359 /*
    360 * With tracing.
    361 */
    362 
    363 #ifndef HB_DEBUG_APPLY
    364 #define HB_DEBUG_APPLY (HB_DEBUG+0)
    365 #endif
    366 #if HB_DEBUG_APPLY
    367 #define TRACE_APPLY(this) \
    368 hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
    369 (&c->debug_depth, c->get_name (), this, HB_FUNC, \
    370  "idx %u gid %u lookup %d", \
    371  c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index)
    372 #else
    373 #define TRACE_APPLY(this) hb_no_trace_t<bool> trace
    374 #endif
    375 
    376 #ifndef HB_DEBUG_SANITIZE
    377 #define HB_DEBUG_SANITIZE (HB_DEBUG+0)
    378 #endif
    379 #if HB_DEBUG_SANITIZE
    380 #define TRACE_SANITIZE(this) \
    381 hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
    382 (&c->debug_depth, c->get_name (), this, HB_FUNC, \
    383  " ")
    384 #else
    385 #define TRACE_SANITIZE(this) hb_no_trace_t<bool> trace
    386 #endif
    387 
    388 #ifndef HB_DEBUG_SERIALIZE
    389 #define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
    390 #endif
    391 #if HB_DEBUG_SERIALIZE
    392 #define TRACE_SERIALIZE(this) \
    393 hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
    394 (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
    395  " ")
    396 #else
    397 #define TRACE_SERIALIZE(this) hb_no_trace_t<bool> trace
    398 #endif
    399 
    400 #ifndef HB_DEBUG_SUBSET
    401 #define HB_DEBUG_SUBSET (HB_DEBUG+0)
    402 #endif
    403 #if HB_DEBUG_SUBSET
    404 #define TRACE_SUBSET(this) \
    405  hb_auto_trace_t<HB_DEBUG_SUBSET, bool> trace \
    406  (&c->debug_depth, c->get_name (), this, HB_FUNC, \
    407   " ")
    408 #else
    409 #define TRACE_SUBSET(this) hb_no_trace_t<bool> trace
    410 #endif
    411 
    412 #ifndef HB_DEBUG_SUBSET_REPACK
    413 #define HB_DEBUG_SUBSET_REPACK (HB_DEBUG+0)
    414 #endif
    415 
    416 #ifndef HB_DEBUG_PAINT
    417 #define HB_DEBUG_PAINT (HB_DEBUG+0)
    418 #endif
    419 #if HB_DEBUG_PAINT
    420 #define TRACE_PAINT(this) \
    421  HB_UNUSED hb_auto_trace_t<HB_DEBUG_PAINT, void> trace \
    422  (&c->debug_depth, c->get_name (), this, HB_FUNC, \
    423   " ")
    424 #else
    425 #define TRACE_PAINT(this) HB_UNUSED hb_no_trace_t<void> trace
    426 #endif
    427 
    428 
    429 #ifndef HB_DEBUG_DISPATCH
    430 #define HB_DEBUG_DISPATCH ( \
    431 HB_DEBUG_APPLY + \
    432 HB_DEBUG_SANITIZE + \
    433 HB_DEBUG_SERIALIZE + \
    434 HB_DEBUG_SUBSET + \
    435 HB_DEBUG_PAINT + \
    436 0)
    437 #endif
    438 #if HB_DEBUG_DISPATCH
    439 #define TRACE_DISPATCH(this, format) \
    440 hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
    441 (&c->debug_depth, c->get_name (), this, HB_FUNC, \
    442  "format %u", (unsigned) format)
    443 #else
    444 #define TRACE_DISPATCH(this, format) hb_no_trace_t<typename context_t::return_t> trace
    445 #endif
    446 
    447 
    448 #ifndef HB_BUFFER_MESSAGE_MORE
    449 #define HB_BUFFER_MESSAGE_MORE (HB_DEBUG+0)
    450 #endif
    451 
    452 
    453 #endif /* HB_DEBUG_HH */