mupdf
Loading...
Searching...
No Matches
system.h
Go to the documentation of this file.
1// Copyright (C) 2004-2025 Artifex Software, Inc.
2//
3// This file is part of MuPDF.
4//
5// MuPDF is free software: you can redistribute it and/or modify it under the
6// terms of the GNU Affero General Public License as published by the Free
7// Software Foundation, either version 3 of the License, or (at your option)
8// any later version.
9//
10// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13// details.
14//
15// You should have received a copy of the GNU Affero General Public License
16// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17//
18// Alternative licensing terms are available from the licensor.
19// For commercial licensing, see <https://www.artifex.com/> or contact
20// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21// CA 94129, USA, for further information.
22
23#ifndef MUPDF_FITZ_SYSTEM_H
24#define MUPDF_FITZ_SYSTEM_H
25
26/* Turn on valgrind pacification in debug builds. */
27#ifndef NDEBUG
28#ifndef PACIFY_VALGRIND
29#define PACIFY_VALGRIND
30#endif
31#endif
32
36
37#include <stddef.h> /* needed for size_t */
38#include <stdarg.h> /* needed for va_list vararg functions */
39#include <setjmp.h> /* needed for the try/catch macros */
40#include <stdio.h> /* useful for debug printfs */
41
42#ifdef __cplusplus
43/* C++ doesn't support flexible array members... */
44#define FZ_FLEXIBLE_ARRAY 1
45#else
46#define FZ_FLEXIBLE_ARRAY
47#endif
48
49#include "export.h"
50
51#if defined(_MSC_VER) && (_MSC_VER < 1700) /* MSVC older than VS2012 */
52typedef signed char int8_t;
53typedef short int int16_t;
54typedef int int32_t;
55typedef __int64 int64_t;
56typedef unsigned char uint8_t;
57typedef unsigned short int uint16_t;
58typedef unsigned int uint32_t;
59typedef unsigned __int64 uint64_t;
60#ifndef INT64_MAX
61#define INT64_MAX 9223372036854775807i64
62#endif
63#else
64#include <stdint.h> /* needed for int64_t */
65#endif
66
67/* Detect if we can use stdckdint.h */
68#ifdef __has_include
69#if __has_include(<stdckdint.h>)
70#define HAVE_STDCKDINT_H 1
71#endif
72#endif
73
74#include "mupdf/memento.h"
76
77#define nelem(x) (sizeof(x)/sizeof((x)[0]))
78
79#ifndef PATH_MAX
80#define PATH_MAX 4096
81#endif
82
83#define FZ_PI 3.14159265f
84#define FZ_RADIAN 57.2957795f
85#define FZ_DEGREE 0.017453292f
86#define FZ_SQRT2 1.41421356f
87#define FZ_LN2 0.69314718f
88
92
93/* ARCH_ARM is only used for 32bit ARM stuff. */
94#if defined(__arm__) || defined(__thumb__)
95#ifndef ARCH_ARM
96#define ARCH_ARM
97#endif
98#endif
99
100/* Detect NEON */
101#ifndef ARCH_HAS_NEON
102#if defined(__ARM_NEON) || defined(__ARM_NEON__)
103#define ARCH_HAS_NEON 1
104#endif
105#endif
106
107#ifndef ARCH_HAS_NEON
108#define ARCH_HAS_NEON 0
109#endif
110
111
112/* We assume that pretty much any X86 or X64 machine has SSE these days. */
113#ifndef ARCH_HAS_SSE
114#if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64)
115#define ARCH_HAS_SSE 1
116#endif
117#endif
118
119#ifndef ARCH_HAS_SSE
120#define ARCH_HAS_SSE 0
121#endif
122
123
127
128#ifndef __STRICT_ANSI__
129#if defined(__APPLE__)
130#ifndef HAVE_SIGSETJMP
131#define HAVE_SIGSETJMP 1
132#endif
133#elif defined(__unix)
134#ifndef __EMSCRIPTEN__
135#ifndef HAVE_SIGSETJMP
136#define HAVE_SIGSETJMP 1
137#endif
138#endif
139#endif
140#endif
141#ifndef HAVE_SIGSETJMP
142#define HAVE_SIGSETJMP 0
143#endif
144
153#if HAVE_SIGSETJMP
154#define fz_setjmp(BUF) sigsetjmp(BUF, 0)
155#define fz_longjmp(BUF,VAL) siglongjmp(BUF, VAL)
156typedef sigjmp_buf fz_jmp_buf;
157#else
158#define fz_setjmp(BUF) setjmp(BUF)
159#define fz_longjmp(BUF,VAL) longjmp(BUF,VAL)
160typedef jmp_buf fz_jmp_buf;
161#endif
162
163/* these constants mirror the corresponding macros in stdio.h */
164#ifndef EOF
165#define EOF (-1)
166#endif
167#ifndef SEEK_SET
168#define SEEK_SET 0
169#endif
170#ifndef SEEK_CUR
171#define SEEK_CUR 1
172#endif
173#ifndef SEEK_END
174#define SEEK_END 2
175#endif
176
177#ifdef _MSC_VER /* Microsoft Visual C */
178
179/* MSVC up to VS2012 */
180#if _MSC_VER < 1800
181static __inline int signbit(double x)
182{
183 union
184 {
185 double d;
186 __int64 i;
187 } u;
188 u.d = x;
189 return (int)(u.i>>63);
190}
191#endif
192
193#pragma warning( disable: 4244 ) /* conversion from X to Y, possible loss of data */
194#pragma warning( disable: 4701 ) /* Potentially uninitialized local variable 'name' used */
195#pragma warning( disable: 4996 ) /* 'function': was declared deprecated */
196
197#if _MSC_VER <= 1700 /* MSVC 2012 */
198#define isnan(x) _isnan(x)
199#define isinf(x) (!_finite(x))
200#endif
201
202#if _MSC_VER <= 1920 /* MSVC 2019 */
203#define hypotf _hypotf
204#endif
205#define atoll _atoi64
206
207#endif
208
209#ifdef _WIN32
210
211/* really a FILE* but we don't want to include stdio.h here */
212void *fz_fopen_utf8(const char *name, const char *mode);
213int fz_remove_utf8(const char *name);
214
215char **fz_argv_from_wargv(int argc, wchar_t **wargv);
216void fz_free_argv(int argc, char **argv);
217
218#endif
219
220/* Cope with systems (such as Windows) with no S_ISDIR */
221#ifndef S_ISDIR
222#define S_ISDIR(mode) ((mode) & S_IFDIR)
223#endif
224
225int64_t fz_stat_ctime(const char *path);
226int64_t fz_stat_mtime(const char *path);
227int fz_mkdir(char *path);
228
229
230/* inline is standard in C++. For some compilers we can enable it within
231 * C too. Some compilers think they know better than we do about when
232 * to actually honour inline (particularly for large functions); use
233 * fz_forceinline to kick them into really inlining. */
234
235#ifndef __cplusplus
236#if defined (__STDC_VERSION_) && (__STDC_VERSION__ >= 199901L) /* C99 */
237#elif defined(_MSC_VER) && (_MSC_VER >= 1500) /* MSVC 9 or newer */
238#define inline __inline
239#define fz_forceinline __forceinline
240#elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC 3 or newer */
241#define inline __inline
242#else /* Unknown or ancient */
243#define inline
244#endif
245#endif
246
247#ifndef fz_forceinline
248#define fz_forceinline inline
249#endif
250
251/* restrict is standard in C99, but not in all C++ compilers. */
252#if defined (__STDC_VERSION_) && (__STDC_VERSION__ >= 199901L) /* C99 */
253#define FZ_RESTRICT restrict
254#elif defined(_MSC_VER) && (_MSC_VER >= 1600) /* MSVC 10 or newer */
255#define FZ_RESTRICT __restrict
256#elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC 3 or newer */
257#define FZ_RESTRICT __restrict
258#else /* Unknown or ancient */
259#define FZ_RESTRICT
260#endif
261
262/* noreturn is a GCC extension */
263#ifdef __GNUC__
264#define FZ_NORETURN __attribute__((noreturn))
265#else
266#ifdef _MSC_VER
267#define FZ_NORETURN __declspec(noreturn)
268#else
269#define FZ_NORETURN
270#endif
271#endif
272
273/* Flag unused parameters, for use with 'static inline' functions in
274 * headers. */
275#if defined(__GNUC__) && (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7)
276#define FZ_UNUSED __attribute__((__unused__))
277#else
278#define FZ_UNUSED
279#endif
280
281/* GCC can do type checking of printf strings */
282#ifdef __printflike
283#define FZ_PRINTFLIKE(F,V) __printflike(F,V)
284#else
285#if defined(__GNUC__) && (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7)
286#define FZ_PRINTFLIKE(F,V) __attribute__((__format__ (__printf__, F, V)))
287#else
288#define FZ_PRINTFLIKE(F,V)
289#endif
290#endif
291
292/* ARM assembly specific defines */
293
294#ifdef ARCH_ARM
295
296/* If we're compiling as thumb code, then we need to tell the compiler
297 * to enter and exit ARM mode around our assembly sections. If we move
298 * the ARM functions to a separate file and arrange for it to be
299 * compiled without thumb mode, we can save some time on entry.
300 */
301/* This is slightly suboptimal; __thumb__ and __thumb2__ become defined
302 * and undefined by #pragma arm/#pragma thumb - but we can't define a
303 * macro to track that. */
304#if defined(__thumb__) || defined(__thumb2__)
305#define ENTER_ARM ".balign 4\nmov r12,pc\nbx r12\n0:.arm\n"
306#define ENTER_THUMB "9:.thumb\n"
307#else
308#define ENTER_ARM
309#define ENTER_THUMB
310#endif
311
312#endif
313
314/* Memory block alignment */
315
316/* Most architectures are happy with blocks being aligned to the size
317 * of void *'s. Some (notably sparc) are not.
318 *
319 * Some architectures (notably amd64) are happy for pointers to be 32bit
320 * aligned even on 64bit systems. By making use of this we can save lots
321 * of memory in data structures (notably the display list).
322 *
323 * We attempt to cope with these vagaries via the following definitions.
324 */
325
326/* All blocks allocated by mupdf's allocators are expected to be
327 * returned aligned to FZ_MEMORY_BLOCK_ALIGN_MOD. This is sizeof(void *)
328 * unless overwritten by a predefinition, or by a specific architecture
329 * being detected. */
330#ifndef FZ_MEMORY_BLOCK_ALIGN_MOD
331#if defined(sparc) || defined(__sparc) || defined(__sparc__)
332#define FZ_MEMORY_BLOCK_ALIGN_MOD 8
333#else
334#define FZ_MEMORY_BLOCK_ALIGN_MOD sizeof(void *)
335#endif
336#endif
337
338/* MuPDF will ensure that its use of pointers in packed structures
339 * (such as the display list) will be aligned to FZ_POINTER_ALIGN_MOD.
340 * This is the same as FZ_MEMORY_BLOCK_ALIGN_MOD unless overridden by
341 * a predefinition, or by a specific architecture being detected. */
342#ifndef FZ_POINTER_ALIGN_MOD
343#if defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__)
344#define FZ_POINTER_ALIGN_MOD 4
345#else
346#define FZ_POINTER_ALIGN_MOD FZ_MEMORY_BLOCK_ALIGN_MOD
347#endif
348#endif
349
350/*
351 * The undefined behavior sanitizer complains about unaligned loads even on
352 * platforms where unaligned loads are allowed.
353 *
354 * Older compilers don't set __SANITIZE_UNDEFINED__, but we can also
355 * check for __SANITIZE_ADDRESS__ since our sanitize build target enables
356 * both ASAN and UBSAN.
357 */
358#if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_UNDEFINED__)
359#undef FZ_POINTER_ALIGN_MOD
360#define FZ_POINTER_ALIGN_MOD FZ_MEMORY_BLOCK_ALIGN_MOD
361#endif
362
363#ifdef CLUSTER
364/* Include this first so our defines don't clash with the system
365 * definitions */
366#include <math.h>
370static float
371my_atan_table[258] =
372{
3730.0000000000f, 0.00390623013f,0.00781234106f,0.0117182136f,
3740.0156237286f, 0.0195287670f, 0.0234332099f, 0.0273369383f,
3750.0312398334f, 0.0351417768f, 0.0390426500f, 0.0429423347f,
3760.0468407129f, 0.0507376669f, 0.0546330792f, 0.0585268326f,
3770.0624188100f, 0.0663088949f, 0.0701969711f, 0.0740829225f,
3780.0779666338f, 0.0818479898f, 0.0857268758f, 0.0896031775f,
3790.0934767812f, 0.0973475735f, 0.1012154420f, 0.1050802730f,
3800.1089419570f, 0.1128003810f, 0.1166554350f, 0.1205070100f,
3810.1243549950f, 0.1281992810f, 0.1320397620f, 0.1358763280f,
3820.1397088740f, 0.1435372940f, 0.1473614810f, 0.1511813320f,
3830.1549967420f, 0.1588076080f, 0.1626138290f, 0.1664153010f,
3840.1702119250f, 0.1740036010f, 0.1777902290f, 0.1815717110f,
3850.1853479500f, 0.1891188490f, 0.1928843120f, 0.1966442450f,
3860.2003985540f, 0.2041471450f, 0.2078899270f, 0.2116268090f,
3870.2153577000f, 0.2190825110f, 0.2228011540f, 0.2265135410f,
3880.2302195870f, 0.2339192060f, 0.2376123140f, 0.2412988270f,
3890.2449786630f, 0.2486517410f, 0.2523179810f, 0.2559773030f,
3900.2596296290f, 0.2632748830f, 0.2669129880f, 0.2705438680f,
3910.2741674510f, 0.2777836630f, 0.2813924330f, 0.2849936890f,
3920.2885873620f, 0.2921733830f, 0.2957516860f, 0.2993222020f,
3930.3028848680f, 0.3064396190f, 0.3099863910f, 0.3135251230f,
3940.3170557530f, 0.3205782220f, 0.3240924700f, 0.3275984410f,
3950.3310960770f, 0.3345853220f, 0.3380661230f, 0.3415384250f,
3960.3450021770f, 0.3484573270f, 0.3519038250f, 0.3553416220f,
3970.3587706700f, 0.3621909220f, 0.3656023320f, 0.3690048540f,
3980.3723984470f, 0.3757830650f, 0.3791586690f, 0.3825252170f,
3990.3858826690f, 0.3892309880f, 0.3925701350f, 0.3959000740f,
4000.3992207700f, 0.4025321870f, 0.4058342930f, 0.4091270550f,
4010.4124104420f, 0.4156844220f, 0.4189489670f, 0.4222040480f,
4020.4254496370f, 0.4286857080f, 0.4319122350f, 0.4351291940f,
4030.4383365600f, 0.4415343100f, 0.4447224240f, 0.4479008790f,
4040.4510696560f, 0.4542287350f, 0.4573780990f, 0.4605177290f,
4050.4636476090f, 0.4667677240f, 0.4698780580f, 0.4729785980f,
4060.4760693300f, 0.4791502430f, 0.4822213240f, 0.4852825630f,
4070.4883339510f, 0.4913754780f, 0.4944071350f, 0.4974289160f,
4080.5004408130f, 0.5034428210f, 0.5064349340f, 0.5094171490f,
4090.5123894600f, 0.5153518660f, 0.5183043630f, 0.5212469510f,
4100.5241796290f, 0.5271023950f, 0.5300152510f, 0.5329181980f,
4110.5358112380f, 0.5386943730f, 0.5415676050f, 0.5444309400f,
4120.5472843810f, 0.5501279330f, 0.5529616020f, 0.5557853940f,
4130.5585993150f, 0.5614033740f, 0.5641975770f, 0.5669819340f,
4140.5697564530f, 0.5725211450f, 0.5752760180f, 0.5780210840f,
4150.5807563530f, 0.5834818390f, 0.5861975510f, 0.5889035040f,
4160.5915997100f, 0.5942861830f, 0.5969629370f, 0.5996299860f,
4170.6022873460f, 0.6049350310f, 0.6075730580f, 0.6102014430f,
4180.6128202020f, 0.6154293530f, 0.6180289120f, 0.6206188990f,
4190.6231993300f, 0.6257702250f, 0.6283316020f, 0.6308834820f,
4200.6334258830f, 0.6359588250f, 0.6384823300f, 0.6409964180f,
4210.6435011090f, 0.6459964250f, 0.6484823880f, 0.6509590190f,
4220.6534263410f, 0.6558843770f, 0.6583331480f, 0.6607726790f,
4230.6632029930f, 0.6656241120f, 0.6680360620f, 0.6704388650f,
4240.6728325470f, 0.6752171330f, 0.6775926450f, 0.6799591110f,
4250.6823165550f, 0.6846650020f, 0.6870044780f, 0.6893350100f,
4260.6916566220f, 0.6939693410f, 0.6962731940f, 0.6985682070f,
4270.7008544080f, 0.7031318220f, 0.7054004770f, 0.7076604000f,
4280.7099116190f, 0.7121541600f, 0.7143880520f, 0.7166133230f,
4290.7188300000f, 0.7210381110f, 0.7232376840f, 0.7254287490f,
4300.7276113330f, 0.7297854640f, 0.7319511710f, 0.7341084830f,
4310.7362574290f, 0.7383980370f, 0.7405303370f, 0.7426543560f,
4320.7447701260f, 0.7468776740f, 0.7489770290f, 0.7510682220f,
4330.7531512810f, 0.7552262360f, 0.7572931160f, 0.7593519510f,
4340.7614027700f, 0.7634456020f, 0.7654804790f, 0.7675074280f,
4350.7695264800f, 0.7715376650f, 0.7735410110f, 0.7755365500f,
4360.7775243100f, 0.7795043220f, 0.7814766150f, 0.7834412190f,
4370.7853981630f, 0.7853981630f /* Extended by 1 for interpolation */
438};
439
440static inline float my_sinf(float x)
441{
442 float x2, xn;
443 int i;
444 /* Map x into the -PI to PI range. We could do this using:
445 * x = fmodf(x, 2.0f * FZ_PI);
446 * but that's C99, and seems to misbehave with negative numbers
447 * on some platforms. */
448 x -= FZ_PI;
449 i = x / (2.0f * FZ_PI);
450 x -= i * 2.0f * FZ_PI;
451 if (x < 0.0f)
452 x += 2.0f * FZ_PI;
453 x -= FZ_PI;
454 if (x <= -FZ_PI / 2.0f)
455 x = -FZ_PI - x;
456 else if (x >= FZ_PI / 2.0f)
457 x = FZ_PI-x;
458 x2 = x * x;
459 xn = x * x2 / 6.0f;
460 x -= xn;
461 xn *= x2 / 20.0f;
462 x += xn;
463 xn *= x2 / 42.0f;
464 x -= xn;
465 xn *= x2 / 72.0f;
466 x += xn;
467 if (x > 1)
468 x = 1;
469 else if (x < -1)
470 x = -1;
471 return x;
472}
473
474static inline float my_atan2f(float o, float a)
475{
476 int negate = 0, flip = 0, i;
477 float r, s;
478 if (o == 0.0f)
479 {
480 if (a > 0)
481 return 0.0f;
482 else
483 return FZ_PI;
484 }
485 if (o < 0)
486 o = -o, negate = 1;
487 if (a < 0)
488 a = -a, flip = 1;
489 if (o < a)
490 i = 65536.0f * o / a + 0.5f;
491 else
492 i = 65536.0f * a / o + 0.5f;
493 r = my_atan_table[i >> 8];
494 s = my_atan_table[(i >> 8) + 1];
495 r += (s - r) * (i & 255) / 256.0f;
496 if (o >= a)
497 r = FZ_PI / 2.0f - r;
498 if (flip)
499 r = FZ_PI - r;
500 if (negate)
501 r = -r;
502 return r;
503}
504
505#define sinf(x) my_sinf(x)
506#define cosf(x) my_sinf(FZ_PI / 2.0f + (x))
507#define atan2f(x,y) my_atan2f((x),(y))
508#endif
509
510static inline int fz_is_pow2(int a)
511{
512 return (a != 0) && (a & (a-1)) == 0;
513}
514
515#endif
int fz_mkdir(char *path)
int64_t fz_stat_mtime(const char *path)
int64_t fz_stat_ctime(const char *path)
jmp_buf fz_jmp_buf
Definition system.h:160
#define FZ_PI
Definition system.h:83