QtBase  v6.3.1
hb-debug.hh
Go to the documentation of this file.
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  * Global runtime options.
42  */
43 
45 {
46  bool unused : 1; /* In-case sign bit is here. */
47  bool initialized : 1;
49 };
50 
52  int i;
54 };
55 static_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), "");
56 
57 HB_INTERNAL void
59 
61 
62 static inline hb_options_t
63 hb_options ()
64 {
65 #ifdef HB_NO_GETENV
66  return hb_options_t ();
67 #endif
68  /* Make a local copy, so we can access bitfield threadsafely. */
70  u.i = _hb_options.get_relaxed ();
71 
72  if (unlikely (!u.i))
73  {
75  u.i = _hb_options.get_relaxed ();
76  }
77 
78  return u.opts;
79 }
80 
81 
82 /*
83  * Debug output (needs enabling at compile time.)
84  */
85 
86 static inline bool
87 _hb_debug (unsigned int level,
88  unsigned int max_level)
89 {
90  return level < max_level;
91 }
92 
93 #define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
94 #define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
95 
96 static inline void
97 _hb_print_func (const char *func)
98 {
99  if (func)
100  {
101  unsigned int func_len = strlen (func);
102  /* Skip "static" */
103  if (0 == strncmp (func, "static ", 7))
104  func += 7;
105  /* Skip "typename" */
106  if (0 == strncmp (func, "typename ", 9))
107  func += 9;
108  /* Skip return type */
109  const char *space = strchr (func, ' ');
110  if (space)
111  func = space + 1;
112  /* Skip parameter list */
113  const char *paren = strchr (func, '(');
114  if (paren)
115  func_len = paren - func;
116  fprintf (stderr, "%.*s", func_len, func);
117  }
118 }
119 
120 template <int max_level> static inline void
121 _hb_debug_msg_va (const char *what,
122  const void *obj,
123  const char *func,
124  bool indented,
125  unsigned int level,
126  int level_dir,
127  const char *message,
128  va_list ap) HB_PRINTF_FUNC(7, 0);
129 template <int max_level> static inline void
130 _hb_debug_msg_va (const char *what,
131  const void *obj,
132  const char *func,
133  bool indented,
134  unsigned int level,
135  int level_dir,
136  const char *message,
137  va_list ap)
138 {
139  if (!_hb_debug (level, max_level))
140  return;
141 
142  fprintf (stderr, "%-10s", what ? what : "");
143 
144  if (obj)
145  fprintf (stderr, "(%*p) ", (unsigned int) (2 * sizeof (void *)), obj);
146  else
147  fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), "");
148 
149  if (indented) {
150 #define VBAR "\342\224\202" /* U+2502 BOX DRAWINGS LIGHT VERTICAL */
151 #define VRBAR "\342\224\234" /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
152 #define DLBAR "\342\225\256" /* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
153 #define ULBAR "\342\225\257" /* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
154 #define LBAR "\342\225\264" /* U+2574 BOX DRAWINGS LIGHT LEFT */
155  static const char bars[] =
161  fprintf (stderr, "%2u %s" VRBAR "%s",
162  level,
163  bars + sizeof (bars) - 1 - hb_min ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
164  level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
165  } else
166  fprintf (stderr, " " VRBAR LBAR);
167 
168  _hb_print_func (func);
169 
170  if (message)
171  {
172  fprintf (stderr, ": ");
173  vfprintf (stderr, message, ap);
174  }
175 
176  fprintf (stderr, "\n");
177 }
178 template <> inline void HB_PRINTF_FUNC(7, 0)
179 _hb_debug_msg_va<0> (const char *what HB_UNUSED,
181  const char *func HB_UNUSED,
182  bool indented HB_UNUSED,
183  unsigned int level HB_UNUSED,
184  int level_dir HB_UNUSED,
185  const char *message HB_UNUSED,
186  va_list ap HB_UNUSED) {}
187 
188 template <int max_level> static inline void
189 _hb_debug_msg (const char *what,
190  const void *obj,
191  const char *func,
192  bool indented,
193  unsigned int level,
194  int level_dir,
195  const char *message,
196  ...) HB_PRINTF_FUNC(7, 8);
197 template <int max_level> static inline void HB_PRINTF_FUNC(7, 8)
198 _hb_debug_msg (const char *what,
199  const void *obj,
200  const char *func,
201  bool indented,
202  unsigned int level,
204  const char *message,
205  ...)
206 {
207  va_list ap;
210  va_end (ap);
211 }
212 template <> inline void
213 _hb_debug_msg<0> (const char *what HB_UNUSED,
214  const void *obj HB_UNUSED,
215  const char *func HB_UNUSED,
216  bool indented HB_UNUSED,
217  unsigned int level HB_UNUSED,
218  int level_dir HB_UNUSED,
219  const char *message HB_UNUSED,
220  ...) HB_PRINTF_FUNC(7, 8);
221 template <> inline void HB_PRINTF_FUNC(7, 8)
222 _hb_debug_msg<0> (const char *what HB_UNUSED,
223  const void *obj HB_UNUSED,
224  const char *func HB_UNUSED,
225  bool indented HB_UNUSED,
226  unsigned int level HB_UNUSED,
227  int level_dir HB_UNUSED,
228  const char *message HB_UNUSED,
229  ...) {}
230 
231 #define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr, true, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
232 #define DEBUG_MSG(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr, false, 0, 0, __VA_ARGS__)
233 #define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
234 
235 
236 /*
237  * Printer
238  */
239 
240 template <typename T>
241 struct hb_printer_t {
242  const char *print (const T&) { return "something"; }
243 };
244 
245 template <>
246 struct hb_printer_t<bool> {
247  const char *print (bool v) { return v ? "true" : "false"; }
248 };
249 
250 template <>
251 struct hb_printer_t<hb_empty_t> {
252  const char *print (hb_empty_t) { return ""; }
253 };
254 
255 
256 /*
257  * Trace
258  */
259 
260 template <typename T>
261 static inline void _hb_warn_no_return (bool returned)
262 {
263  if (unlikely (!returned)) {
264  fprintf (stderr, "OUCH, returned with no call to return_trace(). This is a bug, please report.\n");
265  }
266 }
267 template <>
268 /*static*/ inline void _hb_warn_no_return<hb_empty_t> (bool returned HB_UNUSED)
269 {}
270 
271 template <int max_level, typename ret_t>
273 {
274  explicit inline hb_auto_trace_t (unsigned int *plevel_,
275  const char *what_,
276  const void *obj_,
277  const char *func,
278  const char *message,
279  ...) HB_PRINTF_FUNC(6, 7)
280  : plevel (plevel_), what (what_), obj (obj_), returned (false)
281  {
282  if (plevel) ++*plevel;
283 
284  va_list ap;
285  va_start (ap, message);
286  _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
287  va_end (ap);
288  }
290  {
291  _hb_warn_no_return<ret_t> (returned);
292  if (!returned) {
293  _hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1, " ");
294  }
295  if (plevel) --*plevel;
296  }
297 
298  template <typename T>
299  T ret (T&& v,
300  const char *func = "",
301  unsigned int line = 0)
302  {
303  if (unlikely (returned)) {
304  fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n");
305  return std::forward<T> (v);
306  }
307 
308  _hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
309  "return %s (line %d)",
310  hb_printer_t<hb_decay<decltype (v)>>().print (v), line);
311  if (plevel) --*plevel;
312  plevel = nullptr;
313  returned = true;
314  return std::forward<T> (v);
315  }
316 
317  private:
318  unsigned int *plevel;
319  const char *what;
320  const void *obj;
321  bool returned;
322 };
323 template <typename ret_t> /* Make sure we don't use hb_auto_trace_t when not tracing. */
324 struct hb_auto_trace_t<0, ret_t>
325 {
326  explicit inline hb_auto_trace_t (unsigned int *plevel_,
327  const char *what_,
328  const void *obj_,
329  const char *func,
330  const char *message,
331  ...) HB_PRINTF_FUNC(6, 7) {}
332 
333  template <typename T>
334  T ret (T&& v,
335  const char *func HB_UNUSED = nullptr,
336  unsigned int line HB_UNUSED = 0) { return std::forward<T> (v); }
337 };
338 
339 /* For disabled tracing; optimize out everything.
340  * https://github.com/harfbuzz/harfbuzz/pull/605 */
341 template <typename ret_t>
343  template <typename T>
344  T ret (T&& v,
345  const char *func HB_UNUSED = nullptr,
346  unsigned int line HB_UNUSED = 0) { return std::forward<T> (v); }
347 };
348 
349 #define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__)
350 
351 
352 /*
353  * Instances.
354  */
355 
356 #ifndef HB_DEBUG_ARABIC
357 #define HB_DEBUG_ARABIC (HB_DEBUG+0)
358 #endif
359 
360 #ifndef HB_DEBUG_BLOB
361 #define HB_DEBUG_BLOB (HB_DEBUG+0)
362 #endif
363 
364 #ifndef HB_DEBUG_CORETEXT
365 #define HB_DEBUG_CORETEXT (HB_DEBUG+0)
366 #endif
367 
368 #ifndef HB_DEBUG_DIRECTWRITE
369 #define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
370 #endif
371 
372 #ifndef HB_DEBUG_FT
373 #define HB_DEBUG_FT (HB_DEBUG+0)
374 #endif
375 
376 #ifndef HB_DEBUG_OBJECT
377 #define HB_DEBUG_OBJECT (HB_DEBUG+0)
378 #endif
379 
380 #ifndef HB_DEBUG_SHAPE_PLAN
381 #define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0)
382 #endif
383 
384 #ifndef HB_DEBUG_UNISCRIBE
385 #define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
386 #endif
387 
388 /*
389  * With tracing.
390  */
391 
392 #ifndef HB_DEBUG_APPLY
393 #define HB_DEBUG_APPLY (HB_DEBUG+0)
394 #endif
395 #if HB_DEBUG_APPLY
396 #define TRACE_APPLY(this) \
397  hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
398  (&c->debug_depth, c->get_name (), this, HB_FUNC, \
399  "idx %d gid %u lookup %d", \
400  c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index)
401 #else
402 #define TRACE_APPLY(this) hb_no_trace_t<bool> trace
403 #endif
404 
405 #ifndef HB_DEBUG_SANITIZE
406 #define HB_DEBUG_SANITIZE (HB_DEBUG+0)
407 #endif
408 #if HB_DEBUG_SANITIZE
409 #define TRACE_SANITIZE(this) \
410  hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
411  (&c->debug_depth, c->get_name (), this, HB_FUNC, \
412  " ")
413 #else
414 #define TRACE_SANITIZE(this) hb_no_trace_t<bool> trace
415 #endif
416 
417 #ifndef HB_DEBUG_SERIALIZE
418 #define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
419 #endif
420 #if HB_DEBUG_SERIALIZE
421 #define TRACE_SERIALIZE(this) \
422  hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
423  (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
424  " ")
425 #else
426 #define TRACE_SERIALIZE(this) hb_no_trace_t<bool> trace
427 #endif
428 
429 #ifndef HB_DEBUG_SUBSET
430 #define HB_DEBUG_SUBSET (HB_DEBUG+0)
431 #endif
432 #if HB_DEBUG_SUBSET
433 #define TRACE_SUBSET(this) \
434  hb_auto_trace_t<HB_DEBUG_SUBSET, bool> trace \
435  (&c->debug_depth, c->get_name (), this, HB_FUNC, \
436  " ")
437 #else
438 #define TRACE_SUBSET(this) hb_no_trace_t<bool> trace
439 #endif
440 
441 #ifndef HB_DEBUG_SUBSET_REPACK
442 #define HB_DEBUG_SUBSET_REPACK (HB_DEBUG+0)
443 #endif
444 
445 #ifndef HB_DEBUG_DISPATCH
446 #define HB_DEBUG_DISPATCH ( \
447  HB_DEBUG_APPLY + \
448  HB_DEBUG_SANITIZE + \
449  HB_DEBUG_SERIALIZE + \
450  HB_DEBUG_SUBSET + \
451  0)
452 #endif
453 #if HB_DEBUG_DISPATCH
454 #define TRACE_DISPATCH(this, format) \
455  hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
456  (&c->debug_depth, c->get_name (), this, HB_FUNC, \
457  "format %d", (int) format)
458 #else
459 #define TRACE_DISPATCH(this, format) hb_no_trace_t<typename context_t::return_t> trace
460 #endif
461 
462 
463 #endif /* HB_DEBUG_HH */
small capitals from c petite p scientific f u
Definition: afcover.h:88
HB_INTERNAL hb_atomic_int_t _hb_options
Definition: hb-common.cc:71
#define VRBAR
void HB_PRINTF_FUNC(7, 0) _hb_debug_msg_va< 0 >(const char *what HB_UNUSED
_hb_debug_msg_va< max_level >(what, obj, func, indented, level, level_dir, message, ap)
void _hb_warn_no_return< hb_empty_t >(bool returned HB_UNUSED)
Definition: hb-debug.hh:268
void _hb_debug_msg< 0 >(const char *what HB_UNUSED, const void *obj HB_UNUSED, const char *func HB_UNUSED, bool indented HB_UNUSED, unsigned int level HB_UNUSED, int level_dir HB_UNUSED, const char *message HB_UNUSED,...) HB_PRINTF_FUNC(7
va_end(ap)
#define DLBAR
static void const void const char bool unsigned int int level_dir
Definition: hb-debug.hh:203
static void const void const char bool indented
Definition: hb-debug.hh:201
HB_INTERNAL void _hb_options_init()
Definition: hb-common.cc:74
#define ULBAR
void const void *obj HB_UNUSED
Definition: hb-debug.hh:180
static void const void const char * func
Definition: hb-debug.hh:200
#define VBAR
static void const void const char bool unsigned int int const char va_start(ap, message)
#define LBAR
auto it unsigned count const
Definition: hb-iter.hh:848
hb_remove_const< hb_remove_reference< T > > hb_decay
Definition: hb-meta.hh:116
#define unlikely(expr)
Definition: hb.hh:251
#define HB_INTERNAL
Definition: hb.hh:274
#define inline
Definition: md4c.c:45
int PRIV() strncmp(PCRE2_SPTR str1, PCRE2_SPTR str2, size_t len)
PCRE2_SIZE PRIV() strlen(PCRE2_SPTR str)
GLenum GLuint GLenum GLsizei const GLchar * message
Definition: qopengl.h:270
GLsizei const GLfloat * v
[13]
GLenum GLuint GLint level
GLhandleARB obj
[2]
Definition: qopenglext.h:4164
GLenum func
Definition: qopenglext.h:663
Definition: main.cpp:38
int get_relaxed() const
Definition: hb-atomic.hh:151
hb_auto_trace_t(unsigned int *plevel_, const char *what_, const void *obj_, const char *func, const char *message,...) HB_PRINTF_FUNC(6
hb_auto_trace_t(unsigned int *plevel_, const char *what_, const void *obj_, const char *func, const char *message,...) HB_PRINTF_FUNC(6
T ret(T &&v, const char *func="", unsigned int line=0)
Definition: hb-debug.hh:299
T ret(T &&v, const char *func HB_UNUSED=nullptr, unsigned int line HB_UNUSED=0)
Definition: hb-debug.hh:344
bool uniscribe_bug_compatible
Definition: hb-debug.hh:48
bool initialized
Definition: hb-debug.hh:47
bool unused
Definition: hb-debug.hh:46
const char * print(bool v)
Definition: hb-debug.hh:247
const char * print(hb_empty_t)
Definition: hb-debug.hh:252
hb_options_t opts
Definition: hb-debug.hh:53