FORM v5.0.1-23-g7a8f756
form3.h
Go to the documentation of this file.
1
8/* #[ License : */
9/*
10 * Copyright (C) 1984-2026 J.A.M. Vermaseren
11 * When using this file you are requested to refer to the publication
12 * J.A.M.Vermaseren "New features of FORM" math-ph/0010025
13 * This is considered a matter of courtesy as the development was paid
14 * for by FOM the Dutch physics granting agency and we would like to
15 * be able to track its scientific use to convince FOM of its value
16 * for the community.
17 *
18 * This file is part of FORM.
19 *
20 * FORM is free software: you can redistribute it and/or modify it under the
21 * terms of the GNU General Public License as published by the Free Software
22 * Foundation, either version 3 of the License, or (at your option) any later
23 * version.
24 *
25 * FORM is distributed in the hope that it will be useful, but WITHOUT ANY
26 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
27 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
28 * details.
29 *
30 * You should have received a copy of the GNU General Public License along
31 * with FORM. If not, see <http://www.gnu.org/licenses/>.
32 */
33/* #] License : */
34
35#ifndef __FORM3H__
36#define __FORM3H__
37
38#ifdef HAVE_CONFIG_H
39
40#ifndef CONFIG_H_INCLUDED
41#define CONFIG_H_INCLUDED
42#include <config.h>
43#endif
44
45#else /* HAVE_CONFIG_H */
46
47// This information is now only determined by scripts/git-version-gen.sh
48#define MAJORVERSION X
49#define MINORVERSION Y
50#define PATCHVERSION Z
51
52#ifdef __DATE__
53#define PRODUCTIONDATE __DATE__
54#else
55#define PRODUCTIONDATE "DD-MM-YYYY"
56#endif
57
58#undef BETAVERSION
59/*#define BETAVERSION*/
60
61#ifdef LINUX32
62#define UNIX
63#define LINUX
64#define _FILE_OFFSET_BITS 64
65#define WITHZLIB
66#define WITHGMP
67#define WITHPOSIXCLOCK
68#endif
69
70#ifdef LINUX64
71#define UNIX
72#define LINUX
73#define WITHZLIB
74#define WITHGMP
75#define WITHPOSIXCLOCK
76#define WITHFLOAT
77#endif
78
79#ifdef APPLE32
80#define UNIX
81#define _FILE_OFFSET_BITS 64
82#define WITHZLIB
83#endif
84
85#ifdef APPLE64
86#define UNIX
87#define WITHZLIB
88#define WITHGMP
89#define WITHPOSIXCLOCK
90#define WITHFLOAT
91#define HAVE_UNORDERED_MAP
92#define HAVE_UNORDERED_SET
93#endif
94
95#ifdef CYGWIN32
96#define UNIX
97#endif
98
99#ifdef _MSC_VER
100#define WINDOWS
101#define _CRT_SECURE_NO_WARNINGS
102#endif
103
104/*
105 * We must not define WITHPOSIXCLOCK in compiling the sequential FORM or ParFORM.
106 */
107#if !defined(WITHPTHREADS) && defined(WITHPOSIXCLOCK)
108#undef WITHPOSIXCLOCK
109#endif
110
111#if !defined(__cplusplus) && !defined(inline)
112#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
113/* "inline" is available. */
114#elif defined(__GNUC__)
115/* GNU C compiler has "__inline__". */
116#define inline __inline__
117#elif defined(_MSC_VER)
118/* Microsoft C compiler has "__inline". */
119#define inline __inline
120#else
121/* Inline functions may be not supported. Define "inline" to be empty. */
122#define inline
123#endif
124#endif
125
126#endif /* HAVE_CONFIG_H */
127
128/* Workaround for MSVC. */
129#if defined(_MSC_VER)
130/*
131 * Old versions of MSVC didn't support C99 function `snprintf`, which is used
132 * in poly.cc. On the other hand, macroizing `snprintf` gives a fatal error
133 * with MSVC >= 2015.
134 */
135#if _MSC_VER < 1900
136#define snprintf _snprintf
137#endif
138#endif
139
140/*
141 * Translate our dialect "DEBUGGING" to the standard "NDEBUG".
142 */
143#ifdef DEBUGGING
144#ifdef NDEBUG
145#undef NDEBUG
146#endif
147#else
148#ifndef NDEBUG
149#define NDEBUG
150#endif
151#endif
152
153/*
154 * STATIC_ASSERT(condition) will fail to be compiled if the given
155 * condition is false.
156 */
157/*
158#define STATIC_ASSERT(condition)
159*/
160#define STATIC_ASSERT(condition) STATIC_ASSERT__1(condition,__LINE__)
161#define STATIC_ASSERT__1(X,L) STATIC_ASSERT__2(X,L)
162#define STATIC_ASSERT__2(X,L) STATIC_ASSERT__3(X,L)
163#define STATIC_ASSERT__3(X,L) \
164 typedef char static_assertion_failed_##L[(!!(X))*2-1]
165
166/*
167 * UNIX or WINDOWS must be defined.
168 */
169#if defined(UNIX)
170#define mBSD
171#define ANSI
172#elif defined(WINDOWS)
173#define ANSI
174#define WIN32_LEAN_AND_MEAN
175#include <windows.h>
176#include <io.h>
177#include <fcntl.h>
178/* Undefine/rename conflicted symbols. */
179#undef MAXLONG /* WinNT.h */
180#define WORD FORM_WORD /* WinDef.h */
181#define LONG FORM_LONG /* WinNT.h */
182#define ULONG FORM_ULONG /* WinDef.h */
183#define BOOL FORM_BOOL /* WinDef.h */
184#undef CreateFile /* WinBase.h */
185#undef CopyFile /* WinBase.h */
186#define OpenFile FORM_OpenFile /* WinBase.h */
187#define ReOpenFile FORM_ReOpenFile /* WinBase.h */
188#define ReadFile FORM_ReadFile /* WinBase.h */
189#define WriteFile FORM_WriteFile /* WinBase.h */
190#define DeleteObject FORM_DeleteObject /* WinGDI.h */
191#else
192#error UNIX or WINDOWS must be defined!
193#endif
194
195#include <stdint.h>
196
197#if UINTPTR_MAX == UINT64_MAX
198 typedef int32_t WORD;
199 typedef int64_t LONG;
200 typedef uint32_t UWORD;
201 typedef uint64_t ULONG;
202 #define BITSINWORD 32
203 #define BITSINLONG 64
204 #define WORD_MIN_VALUE INT32_MIN
205 #define WORD_MAX_VALUE INT32_MAX
206 #define LONG_MIN_VALUE INT64_MIN
207 #define LONG_MAX_VALUE INT64_MAX
208#elif UINTPTR_MAX == UINT32_MAX
209 typedef int16_t WORD;
210 typedef int32_t LONG;
211 typedef uint16_t UWORD;
212 typedef uint32_t ULONG;
213 #define BITSINWORD 16
214 #define BITSINLONG 32
215 #define WORD_MIN_VALUE INT16_MIN
216 #define WORD_MAX_VALUE INT16_MAX
217 #define LONG_MIN_VALUE INT32_MIN
218 #define LONG_MAX_VALUE INT32_MAX
219#else
220 #error Can not detect if this is a 32-bit or 64-bit platform.
221#endif
222
223STATIC_ASSERT(sizeof(WORD) * 8 == BITSINWORD);
224STATIC_ASSERT(sizeof(LONG) * 8 == BITSINLONG);
225STATIC_ASSERT(sizeof(WORD) * 2 == sizeof(LONG));
226STATIC_ASSERT(sizeof(LONG) >= sizeof(int *));
227STATIC_ASSERT(sizeof(LONG) >= sizeof(int *));
228STATIC_ASSERT(sizeof(int *) >= sizeof(int));
229STATIC_ASSERT(sizeof(int) >= sizeof(WORD));
230STATIC_ASSERT(sizeof(WORD) >= sizeof(char));
231STATIC_ASSERT(sizeof(char) == 1);
232
233typedef signed char SBYTE;
234typedef unsigned char UBYTE;
235typedef unsigned int UINT;
236typedef ULONG RLONG; /* Used in reken.c. */
237typedef int64_t MLONG; /* See commentary in minos.h. */
238/*
239 * NOTE: we don't use the standard _Bool (or C++ bool) because its size is
240 * implementation-dependent.
241 */
242typedef char BOOL;
243 /* E.g. in 32-bits */
244#define TOPBITONLY ((ULONG)1 << (BITSINWORD - 1)) /* 0x00008000UL */
245#define TOPLONGBITONLY ((ULONG)1 << (BITSINLONG - 1)) /* 0x80000000UL */
246#define SPECMASK ((UWORD)1 << (BITSINWORD - 1)) /* 0x8000U */
247#define WILDMASK ((UWORD)1 << (BITSINWORD - 2)) /* 0x4000U */
248#define WORDMASK ((ULONG)FULLMAX - 1) /* 0x0000FFFFUL */
249#define AWORDMASK (WORDMASK << BITSINWORD) /* 0xFFFF0000UL */
250#define FULLMAX ((LONG)1 << BITSINWORD) /* 0x00010000L */
251#define MAXPOSITIVE ((LONG)(TOPBITONLY - 1)) /* 0x00007FFFL */
252#define MAXLONG ((LONG)(TOPLONGBITONLY - 1)) /* 0x7FFFFFFFL */
253#define MAXPOSITIVE2 (MAXPOSITIVE / 2) /* 0x00003FFFL */
254#define MAXPOSITIVE4 (MAXPOSITIVE / 4) /* 0x00001FFFL */
255
256/*
257 * form_alignof(type) returns the number of bytes used in the alignment of
258 * the type.
259 */
260#if !defined(form_alignof)
261#if defined(__GNUC__)
262/* GNU C compiler has "__alignof__". */
263#define form_alignof(type) __alignof__(type)
264#elif defined(_MSC_VER)
265/* Microsoft C compiler has "__alignof". */
266#define form_alignof(type) __alignof(type)
267#elif !defined(__cplusplus)
268/* Generic case in C. */
269#include <stddef.h>
270#define form_alignof(type) offsetof(struct { char c_; type x_; }, x_)
271#else
272/* Generic case in C++, at least works with a POD struct. */
273#include <cstddef>
274namespace alignof_impl_ {
275template<typename T> struct calc {
276 struct X { char c_; T x_; };
277 enum { value = offsetof(X, x_) };
278};
279}
280#define form_alignof(type) alignof_impl_::calc<type>::value
281#endif
282#endif
283
284
285/*
286#define WITHPCOUNTER
287#define DEBUGGINGLOCKS
288#define WITHSTATS
289*/
290#define WITHSORTBOTS
291
292#include <stdio.h>
293#include <stdlib.h>
294#include <string.h>
295#include <ctype.h>
296#include <limits.h>
297#include <stdarg.h>
298#include <time.h>
299#ifdef WINDOWS
300#include "fwin.h"
301#endif
302#ifdef UNIX
303#include <unistd.h>
304#include <fcntl.h>
305#include <sys/file.h>
306#include "unix.h"
307#endif
308#ifdef WITHZLIB
309#ifdef WITHZSTD
310#include <zstd_zlibwrapper.h>
311#else
312#include <zlib.h>
313#endif
314#endif
315#ifdef WITHPTHREADS
316#include <pthread.h>
317#endif
318
319/*
320 PARALLELCODE indicates code that is common for TFORM and ParFORM but
321 should not be there for sequential FORM.
322*/
323#if defined(WITHMPI) || defined(WITHPTHREADS)
324#define PARALLELCODE
325#endif
326
327#include "ftypes.h"
328#include "fsizes.h"
329#include "minos.h"
330#include "structs.h"
331#include "declare.h"
332#include "variable.h"
333
334STATIC_ASSERT(sizeof(off_t) >= sizeof(LONG));
335
336/*
337 * The interface to file routines for UNIX or non-UNIX (Windows).
338 */
339#ifdef UNIX
340
341#define UFILES
342typedef struct FiLeS {
343 int descriptor;
344} FILES;
345extern FILES *Uopen(char *,char *);
346extern int Uclose(FILES *);
347extern size_t Uread(char *,size_t,size_t,FILES *);
348extern size_t Uwrite(char *,size_t,size_t,FILES *);
349extern int Useek(FILES *,off_t,int);
350extern off_t Utell(FILES *);
351extern void Uflush(FILES *);
352extern int Ugetpos(FILES *,fpos_t *);
353extern int Usetpos(FILES *,fpos_t *);
354extern void Usetbuf(FILES *,char *);
355#define Usync(f) fsync(f->descriptor)
356#define Utruncate(f) { \
357 if ( ftruncate(f->descriptor, 0) ) { \
358 MLOCK(ErrorMessageLock); \
359 MesPrint("Utruncate failed"); \
360 MUNLOCK(ErrorMessageLock); \
361 /* Calling Terminate() here may cause an infinite loop due to CleanUpSort(). */ \
362 /* Terminate(-1); */ \
363 } \
364}
365extern FILES *Ustdout;
366#define MAX_OPEN_FILES getdtablesize()
367#define GetPID() ((LONG)getpid())
368
369#else /* UNIX */
370
371#define FILES FILE
372#define Uopen(x,y) fopen(x,y)
373#define Uflush(x) fflush(x)
374#define Uclose(x) fclose(x)
375#define Uread(x,y,z,u) fread(x,y,z,u)
376#define Uwrite(x,y,z,u) fwrite(x,y,z,u)
377#define Usetbuf(x,y) setbuf(x,y)
378#define Useek(x,y,z) fseek(x,y,z)
379#define Utell(x) ftell(x)
380#define Ugetpos(x,y) fgetpos(x,y)
381#define Usetpos(x,y) fsetpos(x,y)
382#define Usync(x) fflush(x)
383#define Utruncate(x) _chsize(_fileno(x),0)
384#define Ustdout stdout
385#define MAX_OPEN_FILES FOPEN_MAX
386#define bzero(b,len) (memset((b), 0, (len)), (void)0)
387#define GetPID() ((LONG)GetCurrentProcessId())
388
389#endif /* UNIX */
390
391/*
392 * Some system may implement the POSIX "environ" variable as a macro, e.g.,
393 * https://github.com/mingw-w64/mingw-w64/blob/v10.0.0/mingw-w64-headers/crt/stdlib.h#L704
394 * which breaks the definition of DoShattering() in diagrams.c that uses
395 * "environ" as a formal parameter. Because FORM doesn't use the POSIX "environ"
396 * or its variant anyway, we can just undefine it.
397 */
398#ifdef environ
399#undef environ
400#endif
401
402#ifdef WITHMPI
403#include "parallel.h"
404#endif
405
406#endif /* __FORM3H__ */