1 /*
2  * Copyright © 2007,2008,2009  Red Hat, Inc.
3  * Copyright © 2011,2012  Google, Inc.
4  *
5  *  This is part of HarfBuzz, a text shaping library.
6  *
7  * Permission is hereby granted, without written agreement and without
8  * license or royalty fees, to use, copy, modify, and distribute this
9  * software and its documentation for any purpose, provided that the
10  * above copyright notice and the following two paragraphs appear in
11  * all copies of this software.
12  *
13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17  * DAMAGE.
18  *
19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24  *
25  * Red Hat Author(s): Behdad Esfahbod
26  * Google Author(s): Behdad Esfahbod
27  */
28 
29 #ifndef HB_HH
30 #define HB_HH
31 
32 
33 #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC
34 #ifdef _MSC_VER
35 #pragma warning( disable: 4068 ) /* Unknown pragma */
36 #endif
37 #if defined(__GNUC__) || defined(__clang__)
38 /* Rules:
39  *
40  * - All pragmas are declared GCC even if they are clang ones.  Otherwise GCC
41  *   nags, even though we instruct it to ignore -Wunknown-pragmas. ¯\_(ツ)_/¯
42  *
43  * - Within each category, keep sorted.
44  *
45  * - Warnings whose scope can be expanded in future compiler versions shall
46  *   be declared as "warning".  Otherwise, either ignored or error.
47  */
48 
49 /* Setup.  Don't sort order within this category. */
50 #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
51 #pragma GCC diagnostic warning "-Wall"
52 #pragma GCC diagnostic warning "-Wextra"
53 #endif
54 #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
55 #pragma GCC diagnostic ignored "-Wpragmas"
56 #pragma GCC diagnostic ignored "-Wunknown-pragmas"
57 #pragma GCC diagnostic ignored "-Wunknown-warning-option"
58 #endif
59 #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
60 //#pragma GCC diagnostic warning "-Weverything"
61 #endif
62 
63 /* Error.  Should never happen. */
64 #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR
65 #pragma GCC diagnostic error   "-Wbitwise-instead-of-logical"
66 #pragma GCC diagnostic error   "-Wcast-align"
67 #pragma GCC diagnostic error   "-Wcast-function-type"
68 #pragma GCC diagnostic error   "-Wdelete-non-virtual-dtor"
69 #pragma GCC diagnostic error   "-Wembedded-directive"
70 #pragma GCC diagnostic error   "-Wextra-semi-stmt"
71 #pragma GCC diagnostic error   "-Wformat-security"
72 #pragma GCC diagnostic error   "-Wimplicit-function-declaration"
73 #pragma GCC diagnostic error   "-Winit-self"
74 #pragma GCC diagnostic error   "-Winjected-class-name"
75 #pragma GCC diagnostic error   "-Wmissing-braces"
76 #pragma GCC diagnostic error   "-Wmissing-declarations"
77 #pragma GCC diagnostic error   "-Wmissing-prototypes"
78 #pragma GCC diagnostic error   "-Wnarrowing"
79 #pragma GCC diagnostic error   "-Wnested-externs"
80 #pragma GCC diagnostic error   "-Wold-style-definition"
81 #pragma GCC diagnostic error   "-Wpointer-arith"
82 #pragma GCC diagnostic error   "-Wredundant-decls"
83 #pragma GCC diagnostic error   "-Wreorder"
84 #pragma GCC diagnostic error   "-Wsign-compare"
85 #pragma GCC diagnostic error   "-Wstrict-prototypes"
86 #pragma GCC diagnostic error   "-Wstring-conversion"
87 #pragma GCC diagnostic error   "-Wswitch-enum"
88 #pragma GCC diagnostic error   "-Wtautological-overlap-compare"
89 #pragma GCC diagnostic error   "-Wunneeded-internal-declaration"
90 #pragma GCC diagnostic error   "-Wunused"
91 #pragma GCC diagnostic error   "-Wunused-local-typedefs"
92 #pragma GCC diagnostic error   "-Wunused-value"
93 #pragma GCC diagnostic error   "-Wunused-variable"
94 #pragma GCC diagnostic error   "-Wvla"
95 #pragma GCC diagnostic error   "-Wwrite-strings"
96 #endif
97 
98 /* Warning.  To be investigated if happens. */
99 #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
100 #pragma GCC diagnostic warning "-Wbuiltin-macro-redefined"
101 #pragma GCC diagnostic warning "-Wdeprecated"
102 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
103 #pragma GCC diagnostic warning "-Wdisabled-optimization"
104 #pragma GCC diagnostic warning "-Wdouble-promotion"
105 #pragma GCC diagnostic warning "-Wformat=2"
106 #pragma GCC diagnostic warning "-Wignored-pragma-optimize"
107 #pragma GCC diagnostic warning "-Wlogical-op"
108 #pragma GCC diagnostic warning "-Wmaybe-uninitialized"
109 #pragma GCC diagnostic warning "-Wmissing-format-attribute"
110 #pragma GCC diagnostic warning "-Wundef"
111 #pragma GCC diagnostic warning "-Wunused-but-set-variable"
112 #endif
113 
114 /* Ignored currently, but should be fixed at some point. */
115 #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
116 #pragma GCC diagnostic ignored "-Wconversion"			// TODO fix
117 #pragma GCC diagnostic ignored "-Wformat-signedness"		// TODO fix
118 #pragma GCC diagnostic ignored "-Wshadow"			// TODO fix
119 #pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"	// TODO fix
120 #pragma GCC diagnostic ignored "-Wunused-parameter"		// TODO fix
121 #if defined(__GNUC__) && !defined(__clang__)
122 #pragma GCC diagnostic ignored "-Wunused-result"		// TODO fix
123 #endif
124 #endif
125 
126 /* Ignored intentionally. */
127 #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
128 #pragma GCC diagnostic ignored "-Wclass-memaccess"
129 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
130 #pragma GCC diagnostic ignored "-Wformat-zero-length"
131 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
132 #pragma GCC diagnostic ignored "-Wpacked" // Erratic impl in clang
133 #pragma GCC diagnostic ignored "-Wrange-loop-analysis" // https://github.com/harfbuzz/harfbuzz/issues/2834
134 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
135 #pragma GCC diagnostic ignored "-Wtype-limits"
136 #pragma GCC diagnostic ignored "-Wc++11-compat" // only gcc raises it
137 #endif
138 
139 #endif
140 #endif
141 
142 
143 #include "hb-config.hh"
144 
145 
146 /*
147  * Following added based on what AC_USE_SYSTEM_EXTENSIONS adds to
148  * config.h.in.  Copied here for the convenience of those embedding
149  * HarfBuzz and not using our build system.
150  */
151 /* Enable extensions on AIX 3, Interix.  */
152 #ifndef _ALL_SOURCE
153 # define _ALL_SOURCE 1
154 #endif
155 /* Enable GNU extensions on systems that have them.  */
156 #ifndef _GNU_SOURCE
157 # define _GNU_SOURCE 1
158 #endif
159 /* Enable threading extensions on Solaris.  */
160 #ifndef _POSIX_PTHREAD_SEMANTICS
161 # define _POSIX_PTHREAD_SEMANTICS 1
162 #endif
163 /* Enable extensions on HP NonStop.  */
164 #ifndef _TANDEM_SOURCE
165 # define _TANDEM_SOURCE 1
166 #endif
167 /* Enable general extensions on Solaris.  */
168 #ifndef __EXTENSIONS__
169 # define __EXTENSIONS__ 1
170 #endif
171 
172 #if defined (_MSC_VER) && defined (HB_DLL_EXPORT)
173 #define HB_EXTERN __declspec (dllexport) extern
174 #endif
175 
176 #include "hb.h"
177 #define HB_H_IN
178 #include "hb-ot.h"
179 #define HB_OT_H_IN
180 #include "hb-aat.h"
181 #define HB_AAT_H_IN
182 
183 #include <cassert>
184 #include <cfloat>
185 #include <climits>
186 #ifdef _MSC_VER
187 # define _USE_MATH_DEFINES
188 #endif
189 #include <cmath>
190 #include <cstdarg>
191 #include <cstddef>
192 #include <cstdio>
193 #include <cstdlib>
194 #include <cstring>
195 
196 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
197 #ifdef __MINGW32_VERSION
198 #ifndef WIN32_LEAN_AND_MEAN
199 #define WIN32_LEAN_AND_MEAN 1
200 #endif
201 #else
202 #include <intrin.h>
203 #endif
204 #endif
205 
206 #ifdef _WIN32
207 #include <windows.h>
208 #include <winapifamily.h>
209 #endif
210 
211 #define HB_PASTE1(a,b) a##b
212 #define HB_PASTE(a,b) HB_PASTE1(a,b)
213 
214 
215 /* Compile-time custom allocator support. */
216 
217 #if !defined(HB_CUSTOM_MALLOC) \
218   && defined(hb_malloc_impl) \
219   && defined(hb_calloc_impl) \
220   && defined(hb_realloc_impl) \
221   && defined(hb_free_impl)
222 #define HB_CUSTOM_MALLOC
223 #endif
224 
225 #ifdef HB_CUSTOM_MALLOC
226 extern "C" void* hb_malloc_impl(size_t size);
227 extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
228 extern "C" void* hb_realloc_impl(void *ptr, size_t size);
229 extern "C" void  hb_free_impl(void *ptr);
230 #define hb_malloc hb_malloc_impl
231 #define hb_calloc hb_calloc_impl
232 #define hb_realloc hb_realloc_impl
233 #define hb_free hb_free_impl
234 #else
235 #define hb_malloc malloc
236 #define hb_calloc calloc
237 #define hb_realloc realloc
238 #define hb_free free
239 #endif
240 
241 
242 /*
243  * Compiler attributes
244  */
245 
246 #if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
247 #define likely(expr) (__builtin_expect (!!(expr), 1))
248 #define unlikely(expr) (__builtin_expect (!!(expr), 0))
249 #else
250 #define likely(expr) (expr)
251 #define unlikely(expr) (expr)
252 #endif
253 
254 #if !defined(__GNUC__) && !defined(__clang__)
255 #undef __attribute__
256 #define __attribute__(x)
257 #endif
258 
259 #if defined(__GNUC__) && (__GNUC__ >= 3)
260 #define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
261 #else
262 #define HB_PRINTF_FUNC(format_idx, arg_idx)
263 #endif
264 #if defined(__GNUC__) && (__GNUC__ >= 4) || (__clang__)
265 #define HB_UNUSED	__attribute__((unused))
266 #elif defined(_MSC_VER) /* https://github.com/harfbuzz/harfbuzz/issues/635 */
267 #define HB_UNUSED __pragma(warning(suppress: 4100 4101))
268 #else
269 #define HB_UNUSED
270 #endif
271 
272 #ifndef HB_INTERNAL
273 # if !defined(HB_NO_VISIBILITY) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_MSC_VER) && !defined(__SUNPRO_CC)
274 #  define HB_INTERNAL __attribute__((__visibility__("hidden")))
275 # elif defined(__MINGW32__)
276    /* We use -export-symbols on mingw32, since it does not support visibility attributes. */
277 #  define HB_INTERNAL
278 # elif defined (_MSC_VER) && defined (HB_DLL_EXPORT)
279    /* We do not try to export internal symbols on Visual Studio */
280 #  define HB_INTERNAL
281 #else
282 #  define HB_INTERNAL
283 #  define HB_NO_VISIBILITY 1
284 # endif
285 #endif
286 
287 /* https://github.com/harfbuzz/harfbuzz/issues/1651 */
288 #if defined(__clang__) && __clang_major__ < 10
289 #define static_const static
290 #else
291 #define static_const static const
292 #endif
293 
294 #if defined(__GNUC__) && (__GNUC__ >= 3)
295 #define HB_FUNC __PRETTY_FUNCTION__
296 #elif defined(_MSC_VER)
297 #define HB_FUNC __FUNCSIG__
298 #else
299 #define HB_FUNC __func__
300 #endif
301 
302 #if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5140)
303 /* https://github.com/harfbuzz/harfbuzz/issues/630 */
304 #define __restrict
305 #endif
306 
307 /*
308  * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
309  * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
310  * cases that fall through without a break or return statement. HB_FALLTHROUGH
311  * is only needed on cases that have code:
312  *
313  * switch (foo) {
314  *   case 1: // These cases have no code. No fallthrough annotations are needed.
315  *   case 2:
316  *   case 3:
317  *     foo = 4; // This case has code, so a fallthrough annotation is needed:
318  *     HB_FALLTHROUGH;
319  *   default:
320  *     return foo;
321  * }
322  */
323 #if defined(__clang__) && __cplusplus >= 201103L
324    /* clang's fallthrough annotations are only available starting in C++11. */
325 #  define HB_FALLTHROUGH [[clang::fallthrough]]
326 #elif defined(__GNUC__) && (__GNUC__ >= 7)
327    /* GNU fallthrough attribute is available from GCC7 */
328 #  define HB_FALLTHROUGH __attribute__((fallthrough))
329 #elif defined(_MSC_VER)
330    /*
331     * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
332     * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
333     */
334 #  include <sal.h>
335 #  define HB_FALLTHROUGH __fallthrough
336 #else
337 #  define HB_FALLTHROUGH /* FALLTHROUGH */
338 #endif
339 
340 /* A tag to enforce use of return value for a function */
341 #if __cplusplus >= 201703L
342 #  define HB_NODISCARD [[nodiscard]]
343 #elif defined(__GNUC__) || defined(__clang__)
344 #  define HB_NODISCARD __attribute__((warn_unused_result))
345 #elif defined(_MSC_VER)
346 #  define HB_NODISCARD _Check_return_
347 #else
348 #  define HB_NODISCARD
349 #endif
350 
351 /* https://github.com/harfbuzz/harfbuzz/issues/1852 */
352 #if defined(__clang__) && !(defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__)))
353 /* Disable certain sanitizer errors. */
354 /* https://github.com/harfbuzz/harfbuzz/issues/1247 */
355 #define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW __attribute__((no_sanitize("signed-integer-overflow")))
356 #else
357 #define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW
358 #endif
359 
360 
361 #ifdef _WIN32
362    /* We need Windows Vista for both Uniscribe backend and for
363     * MemoryBarrier.  We don't support compiling on Windows XP,
364     * though we run on it fine. */
365 #  if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
366 #    undef _WIN32_WINNT
367 #  endif
368 #  ifndef _WIN32_WINNT
369 #    if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
370 #      define _WIN32_WINNT 0x0600
371 #    endif
372 #  endif
373 #  ifndef WIN32_LEAN_AND_MEAN
374 #    define WIN32_LEAN_AND_MEAN 1
375 #  endif
376 #  ifndef STRICT
377 #    define STRICT 1
378 #  endif
379 
380 #  if defined(_WIN32_WCE)
381      /* Some things not defined on Windows CE. */
382 #    define vsnprintf _vsnprintf
383 #    ifndef HB_NO_GETENV
384 #      define HB_NO_GETENV
385 #    endif
386 #    if _WIN32_WCE < 0x800
387 #      define HB_NO_SETLOCALE
388 #      define HB_NO_ERRNO
389 #    endif
390 #  elif !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
391 #    ifndef HB_NO_GETENV
392 #      define HB_NO_GETENV
393 #    endif
394 #  endif
395 #  if defined(_MSC_VER) && _MSC_VER < 1900
396 #    define snprintf _snprintf
397 #  endif
398 #endif
399 
400 #ifdef HB_NO_GETENV
401 #define getenv(Name) nullptr
402 #endif
403 
404 #ifndef HB_NO_ERRNO
405 #  include <cerrno>
406 #else
407 static int HB_UNUSED _hb_errno = 0;
408 #  undef errno
409 #  define errno _hb_errno
410 #endif
411 
412 #define HB_STMT_START do
413 #define HB_STMT_END   while (0)
414 
415 #if defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT)
416 /* atexit() is only safe to be called from shared libraries on certain
417  * platforms.  Whitelist.
418  * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
419 #  if defined(__linux) && defined(__GLIBC_PREREQ)
420 #    if __GLIBC_PREREQ(2,3)
421 /* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
422 #      define HB_USE_ATEXIT 1
423 #    endif
424 #  elif defined(_MSC_VER) || defined(__MINGW32__)
425 /* For MSVC:
426  * https://msdn.microsoft.com/en-us/library/tze57ck3.aspx
427  * https://msdn.microsoft.com/en-us/library/zk17ww08.aspx
428  * mingw32 headers say atexit is safe to use in shared libraries.
429  */
430 #    define HB_USE_ATEXIT 1
431 #  elif defined(__ANDROID__)
432 /* This is available since Android NKD r8 or r8b:
433  * https://issuetracker.google.com/code/p/android/issues/detail?id=6455
434  */
435 #    define HB_USE_ATEXIT 1
436 #  elif defined(__APPLE__)
437 /* For macOS and related platforms, the atexit man page indicates
438  * that it will be invoked when the library is unloaded, not only
439  * at application exit.
440  */
441 #    define HB_USE_ATEXIT 1
442 #  endif
443 #endif /* defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT) */
444 #ifdef HB_NO_ATEXIT
445 #  undef HB_USE_ATEXIT
446 #endif
447 #ifndef HB_USE_ATEXIT
448 #  define HB_USE_ATEXIT 0
449 #endif
450 #ifndef hb_atexit
451 #if !HB_USE_ATEXIT
452 #  define hb_atexit(_) HB_STMT_START { if (0) (_) (); } HB_STMT_END
453 #else /* HB_USE_ATEXIT */
454 #  ifdef HAVE_ATEXIT
455 #    define hb_atexit atexit
456 #  else
~hb_atexit_thb_atexit_t457      template <void (*function) (void)> struct hb_atexit_t { ~hb_atexit_t () { function (); } };
458 #    define hb_atexit(f) static hb_atexit_t<f> _hb_atexit_##__LINE__;
459 #  endif
460 #endif
461 #endif
462 
463 /* Lets assert int types.  Saves trouble down the road. */
464 static_assert ((sizeof (hb_codepoint_t) == 4), "");
465 static_assert ((sizeof (hb_position_t) == 4), "");
466 static_assert ((sizeof (hb_mask_t) == 4), "");
467 static_assert ((sizeof (hb_var_int_t) == 4), "");
468 
469 
470 /* Headers we include for everyone.  Keep topologically sorted by dependency.
471  * They express dependency amongst themselves, but no other file should include
472  * them directly.*/
473 #include "hb-meta.hh"
474 #include "hb-mutex.hh"
475 #include "hb-number.hh"
476 #include "hb-atomic.hh"	// Requires: hb-meta
477 #include "hb-null.hh"	// Requires: hb-meta
478 #include "hb-algs.hh"	// Requires: hb-meta hb-null hb-number
479 #include "hb-iter.hh"	// Requires: hb-algs hb-meta
480 #include "hb-debug.hh"	// Requires: hb-algs hb-atomic
481 #include "hb-array.hh"	// Requires: hb-algs hb-iter hb-null
482 #include "hb-vector.hh"	// Requires: hb-array hb-null
483 #include "hb-object.hh"	// Requires: hb-atomic hb-mutex hb-vector
484 
485 #endif /* HB_HH */
486