FORM 4.3
form3.h
Go to the documentation of this file.
1
7
8/* #[ License : */
9/*
10 * Copyright (C) 1984-2022 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#define MAJORVERSION 4
48#define MINORVERSION 3
49
50#define PRODUCTIONDATE "08-nov-2022"
51
52#undef BETAVERSION
53
54#ifdef LINUX32
55#define UNIX
56#define LINUX
57#define ILP32
58#define SIZEOF_LONG_LONG 8
59#define _FILE_OFFSET_BITS 64
60#define WITHZLIB
61#define WITHGMP
62#define WITHPOSIXCLOCK
63#endif
64
65#ifdef LINUX64
66#define UNIX
67#define LINUX
68#define LP64
69#define WITHZLIB
70#define WITHGMP
71#define WITHPOSIXCLOCK
72#endif
73
74#ifdef APPLE32
75#define UNIX
76#define ILP32
77#define SIZEOF_LONG_LONG 8
78#define _FILE_OFFSET_BITS 64
79#define WITHZLIB
80#endif
81
82#ifdef APPLE64
83#define UNIX
84#define LP64
85#define WITHZLIB
86#define WITHGMP
87#define WITHPOSIXCLOCK
88#define HAVE_UNORDERED_MAP
89#define HAVE_UNORDERED_SET
90#endif
91
92#ifdef CYGWIN32
93#define UNIX
94#define ILP32
95#define SIZEOF_LONG_LONG 8
96#endif
97
98#ifdef _MSC_VER
99#define WINDOWS
100#define _CRT_SECURE_NO_WARNINGS
101#if defined(_WIN64)
102#define LLP64
103#elif defined(_WIN32)
104#define ILP32
105#define SIZEOF_LONG_LONG 8
106#endif
107#endif
108
109/*
110 * We must not define WITHPOSIXCLOCK in compiling the sequential FORM or ParFORM.
111 */
112#if !defined(WITHPTHREADS) && defined(WITHPOSIXCLOCK)
113#undef WITHPOSIXCLOCK
114#endif
115
116#if !defined(__cplusplus) && !defined(inline)
117#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
118/* "inline" is available. */
119#elif defined(__GNUC__)
120/* GNU C compiler has "__inline__". */
121#define inline __inline__
122#elif defined(_MSC_VER)
123/* Microsoft C compiler has "__inline". */
124#define inline __inline
125#else
126/* Inline functions may be not supported. Define "inline" to be empty. */
127#define inline
128#endif
129#endif
130
131#endif /* HAVE_CONFIG_H */
132
133/* Workaround for MSVC. */
134#if defined(_MSC_VER)
135/*
136 * Recent versions of MSVC++ (>= 2012) don't like reserved keywords being
137 * macroized even when they are not available. This is problematic for
138 * `alignof`, which is used in legacy `PADXXX` macros. We disable tests in
139 * xkeycheck.h.
140 */
141#if _MSC_VER >= 1700
142#define _ALLOW_KEYWORD_MACROS
143#endif
144/*
145 * Old versions of MSVC didn't support C99 function `snprintf`, which is used
146 * in poly.cc. On the other hand, macroizing `snprintf` gives a fatal error
147 * with MSVC >= 2015.
148 */
149#if _MSC_VER < 1900
150#define snprintf _snprintf
151#endif
152#endif
153
154/*
155 * Translate our dialect "DEBUGGING" to the standard "NDEBUG".
156 */
157#ifdef DEBUGGING
158#ifdef NDEBUG
159#undef NDEBUG
160#endif
161#else
162#ifndef NDEBUG
163#define NDEBUG
164#endif
165#endif
166
167/*
168 * STATIC_ASSERT(condition) will fail to be compiled if the given
169 * condition is false.
170 */
171#define STATIC_ASSERT(condition) STATIC_ASSERT__1(condition,__LINE__)
172#define STATIC_ASSERT__1(X,L) STATIC_ASSERT__2(X,L)
173#define STATIC_ASSERT__2(X,L) STATIC_ASSERT__3(X,L)
174#define STATIC_ASSERT__3(X,L) \
175 typedef char static_assertion_failed_##L[(!!(X))*2-1]
176
177/*
178 * UNIX or WINDOWS must be defined.
179 */
180#if defined(UNIX)
181#define mBSD
182#define ANSI
183#elif defined(WINDOWS)
184#define ANSI
185#define WIN32_LEAN_AND_MEAN
186#include <windows.h>
187#include <io.h>
188/* Undefine/rename conflicted symbols. */
189#undef VOID /* WinNT.h */
190#undef MAXLONG /* WinNT.h */
191#define WORD FORM_WORD /* WinDef.h */
192#define LONG FORM_LONG /* WinNT.h */
193#define ULONG FORM_ULONG /* WinDef.h */
194#define BOOL FORM_BOOL /* WinDef.h */
195#undef CreateFile /* WinBase.h */
196#undef CopyFile /* WinBase.h */
197#define OpenFile FORM_OpenFile /* WinBase.h */
198#define ReOpenFile FORM_ReOpenFile /* WinBase.h */
199#define ReadFile FORM_ReadFile /* WinBase.h */
200#define WriteFile FORM_WriteFile /* WinBase.h */
201#define DeleteObject FORM_DeleteObject /* WinGDI.h */
202#else
203#error UNIX or WINDOWS must be defined!
204#endif
205
206/*
207 * Data model. ILP32 or LLP64 or LP64 must be defined.
208 *
209 * Here we define basic types WORD, LONG and their unsigned versions
210 * UWORD and ULONG. LONG must be double size of WORD. Their actual types
211 * are system-dependent. BITSINWORD and BITSINLONG are also defined.
212 * INT16, INT32 (also INT64 and INT128 if available) are used for
213 * system independent saved expressions (store.c).
214 */
215#if defined(ILP32)
216
217typedef short WORD;
218typedef long LONG;
219typedef unsigned short UWORD;
220typedef unsigned long ULONG;
221#define BITSINWORD 16
222#define BITSINLONG 32
223#define INT16 short
224#define INT32 int
225#undef INT64
226#undef INT128
227
228#ifdef SIZEOF_LONG_LONG
229#if SIZEOF_LONG_LONG == 8
230#define INT64 long long
231#endif
232#endif
233
234#ifndef INT64
235#error INT64 is not available!
236#endif
237
238#define WORD_MIN_VALUE SHRT_MIN
239#define WORD_MAX_VALUE SHRT_MAX
240#define LONG_MIN_VALUE LONG_MIN
241#define LONG_MAX_VALUE LONG_MAX
242
243#elif defined(LLP64)
244
245typedef int WORD;
246typedef long long LONG;
247typedef unsigned int UWORD;
248typedef unsigned long long ULONG;
249#define BITSINWORD 32
250#define BITSINLONG 64
251#define INT16 short
252#define INT32 int
253#define INT64 long long
254#undef INT128
255
256#define WORD_MIN_VALUE INT_MIN
257#define WORD_MAX_VALUE INT_MAX
258#define LONG_MIN_VALUE LLONG_MIN
259#define LONG_MAX_VALUE LLONG_MAX
260
261#elif defined(LP64)
262
263typedef int WORD;
264typedef long LONG;
265typedef unsigned int UWORD;
266typedef unsigned long ULONG;
267#define BITSINWORD 32
268#define BITSINLONG 64
269#define INT16 short
270#define INT32 int
271#define INT64 long
272#undef INT128
273
274#define WORD_MIN_VALUE INT_MIN
275#define WORD_MAX_VALUE INT_MAX
276#define LONG_MIN_VALUE LONG_MIN
277#define LONG_MAX_VALUE LONG_MAX
278
279#else
280#error ILP32 or LLP64 or LP64 must be defined!
281#endif
282
283STATIC_ASSERT(sizeof(WORD) * 8 == BITSINWORD);
284STATIC_ASSERT(sizeof(LONG) * 8 == BITSINLONG);
285STATIC_ASSERT(sizeof(WORD) * 2 == sizeof(LONG));
286STATIC_ASSERT(sizeof(LONG) >= sizeof(int *));
287STATIC_ASSERT(sizeof(INT16) == 2);
288STATIC_ASSERT(sizeof(INT32) == 4);
289STATIC_ASSERT(sizeof(INT64) == 8);
290#ifdef INT128
291STATIC_ASSERT(sizeof(INT128) == 16);
292#endif
293
294#if BITSINWORD == 32
295#define WORDSIZE32 1
296#endif
297
298typedef void VOID;
299typedef signed char SBYTE;
300typedef unsigned char UBYTE;
301typedef unsigned int UINT;
302typedef ULONG RLONG; /* Used in reken.c. */
303typedef INT64 MLONG; /* See commentary in minos.h. */
304/*
305 * NOTE: we don't use the standard _Bool (or C++ bool) because its size is
306 * implementation-dependent and messes up the traditional PADXXX macros.
307 */
308typedef char BOOL;
309 /* E.g. in 32-bits */
310#define TOPBITONLY ((ULONG)1 << (BITSINWORD - 1)) /* 0x00008000UL */
311#define TOPLONGBITONLY ((ULONG)1 << (BITSINLONG - 1)) /* 0x80000000UL */
312#define SPECMASK ((UWORD)1 << (BITSINWORD - 1)) /* 0x8000U */
313#define WILDMASK ((UWORD)1 << (BITSINWORD - 2)) /* 0x4000U */
314#define WORDMASK ((ULONG)FULLMAX - 1) /* 0x0000FFFFUL */
315#define AWORDMASK (WORDMASK << BITSINWORD) /* 0xFFFF0000UL */
316#define FULLMAX ((LONG)1 << BITSINWORD) /* 0x00010000L */
317#define MAXPOSITIVE ((LONG)(TOPBITONLY - 1)) /* 0x00007FFFL */
318#define MAXLONG ((LONG)(TOPLONGBITONLY - 1)) /* 0x7FFFFFFFL */
319#define MAXPOSITIVE2 (MAXPOSITIVE / 2) /* 0x00003FFFL */
320#define MAXPOSITIVE4 (MAXPOSITIVE / 4) /* 0x00001FFFL */
321
322/*
323 * alignof(type) returns the number of bytes used in the alignment of
324 * the type.
325 */
326#if !defined(alignof)
327#if defined(__GNUC__)
328/* GNU C compiler has "__alignof__". */
329#define alignof(type) __alignof__(type)
330#elif defined(_MSC_VER)
331/* Microsoft C compiler has "__alignof". */
332#define alignof(type) __alignof(type)
333#elif !defined(__cplusplus)
334/* Generic case in C. */
335#include <stddef.h>
336#define alignof(type) offsetof(struct { char c_; type x_; }, x_)
337#else
338/* Generic case in C++, at least works with a POD struct. */
339#include <cstddef>
340namespace alignof_impl_ {
341template<typename T> struct calc {
342 struct X { char c_; T x_; };
343 enum { value = offsetof(X, x_) };
344};
345}
346#define alignof(type) alignof_impl_::calc<type>::value
347#endif
348#endif
349
350/*
351 * Macros to be inserted at the end of a structure to align the whole structure.
352 *
353 * In the currently available systems,
354 * sizeof(POSITION) >= sizeof(pointers) == sizeof(LONG) >= sizeof(int)
355 * >= sizeof(WORD) >= sizeof(UBYTE) = 1.
356 * (POSITION is defined in struct.h and contains only an off_t variable.)
357 * Thus, if we put members of a structure in this order and use those macros,
358 * then we can align the data without relying on extra paddings added by
359 * the compiler. For example,
360 * typedef struct {
361 * int *a;
362 * LONG b;
363 * WORD c[2];
364 * UBYTE d;
365 * PADPOINTER(1,0,2,1);
366 * } A;
367 * typedef struct {
368 * POSITION p;
369 * A a; // aligned same as pointers
370 * int *b;
371 * LONG c;
372 * UBYTE d;
373 * PADPOSITION(1,1,0,0,1+sizeof(A));
374 * } B;
375 * The cost for the use of those PADXXX macros is a padding (>= 1 byte) will
376 * be always inserted even in the case that no padding is actually needed.
377 *
378 * Numbers for the arguments have to be calculated manually and so very
379 * error-prone. Be careful!
380 *
381 * Note that there is a 32-bit system in which off_t is aligned on 8-byte
382 * boundary, (e.g., Cygwin with large file support), but still the above
383 * inequalities are satisfied.
384 *
385 * The legendary story of these macros--they fixed some problems in ancient
386 * times when compilers were unreliable and didn't know how to correctly compute
387 * structure paddings--has been handed down, though nowadays there are only
388 * disadvantages for them in practice (ancient compilers most likely can't
389 * compile C99 and C++98+TR1 sources anyway).
390 */
391#define PADDUMMY(type, size) \
392 UBYTE d_u_m_m_y[alignof(type) - ((size) & (alignof(type) - 1))]
393#define PADPOSITION(ptr_,long_,int_,word_,byte_) \
394 PADDUMMY(off_t, \
395 + sizeof(int *) * (ptr_) \
396 + sizeof(LONG) * (long_) \
397 + sizeof(int) * (int_) \
398 + sizeof(WORD) * (word_) \
399 + sizeof(UBYTE) * (byte_) \
400 )
401#define PADPOINTER(long_,int_,word_,byte_) \
402 PADDUMMY(int *, \
403 + sizeof(LONG) * (long_) \
404 + sizeof(int) * (int_) \
405 + sizeof(WORD) * (word_) \
406 + sizeof(UBYTE) * (byte_) \
407 )
408#define PADLONG(int_,word_,byte_) \
409 PADDUMMY(LONG, \
410 + sizeof(int) * (int_) \
411 + sizeof(WORD) * (word_) \
412 + sizeof(UBYTE) * (byte_) \
413 )
414#define PADINT(word_,byte_) \
415 PADDUMMY(int, \
416 + sizeof(WORD) * (word_) \
417 + sizeof(UBYTE) * (byte_) \
418 )
419#define PADWORD(byte_) \
420 PADDUMMY(WORD, \
421 + sizeof(UBYTE) * (byte_) \
422 )
423
424/*
425#define WITHPCOUNTER
426#define DEBUGGINGLOCKS
427#define WITHSTATS
428*/
429#define WITHSORTBOTS
430
431#include <stdio.h>
432#include <stdlib.h>
433#include <string.h>
434#include <ctype.h>
435#include <limits.h>
436#ifdef ANSI
437#include <stdarg.h>
438#include <time.h>
439#endif
440#ifdef WINDOWS
441#include "fwin.h"
442#endif
443#ifdef UNIX
444#include <unistd.h>
445#include <time.h>
446#include <fcntl.h>
447#include <sys/file.h>
448#include "unix.h"
449#endif
450#ifdef WITHZLIB
451#include <zlib.h>
452#endif
453#ifdef WITHPTHREADS
454#include <pthread.h>
455#endif
456
457/*
458 PARALLELCODE indicates code that is common for TFORM and ParFORM but
459 should not be there for sequential FORM.
460*/
461#if defined(WITHMPI) || defined(WITHPTHREADS)
462#define PARALLELCODE
463#endif
464
465#include "ftypes.h"
466#include "fsizes.h"
467#include "minos.h"
468#include "structs.h"
469#include "declare.h"
470#include "variable.h"
471
472/*
473 * The interface to file routines for UNIX or non-UNIX (Windows).
474 */
475#ifdef UNIX
476
477#define UFILES
478typedef struct FiLeS {
479 int descriptor;
480} FILES;
481extern FILES *Uopen(char *,char *);
482extern int Uclose(FILES *);
483extern size_t Uread(char *,size_t,size_t,FILES *);
484extern size_t Uwrite(char *,size_t,size_t,FILES *);
485extern int Useek(FILES *,off_t,int);
486extern off_t Utell(FILES *);
487extern void Uflush(FILES *);
488extern int Ugetpos(FILES *,fpos_t *);
489extern int Usetpos(FILES *,fpos_t *);
490extern void Usetbuf(FILES *,char *);
491#define Usync(f) fsync(f->descriptor)
492#define Utruncate(f) { \
493 if ( ftruncate(f->descriptor, 0) ) { \
494 MLOCK(ErrorMessageLock); \
495 MesPrint("Utruncate failed"); \
496 MUNLOCK(ErrorMessageLock); \
497 /* Calling Terminate() here may cause an infinite loop due to CleanUpSort(). */ \
498 /* Terminate(-1); */ \
499 } \
500}
501extern FILES *Ustdout;
502#define MAX_OPEN_FILES getdtablesize()
503#define GetPID() ((LONG)getpid())
504
505#else /* UNIX */
506
507#define FILES FILE
508#define Uopen(x,y) fopen(x,y)
509#define Uflush(x) fflush(x)
510#define Uclose(x) fclose(x)
511#define Uread(x,y,z,u) fread(x,y,z,u)
512#define Uwrite(x,y,z,u) fwrite(x,y,z,u)
513#define Usetbuf(x,y) setbuf(x,y)
514#define Useek(x,y,z) fseek(x,y,z)
515#define Utell(x) ftell(x)
516#define Ugetpos(x,y) fgetpos(x,y)
517#define Usetpos(x,y) fsetpos(x,y)
518#define Usync(x) fflush(x)
519#define Utruncate(x) _chsize(_fileno(x),0)
520#define Ustdout stdout
521#define MAX_OPEN_FILES FOPEN_MAX
522#define bzero(b,len) (memset((b), 0, (len)), (void)0)
523#define GetPID() ((LONG)GetCurrentProcessId())
524
525#endif /* UNIX */
526
527/*
528 * Some system may implement the POSIX "environ" variable as a macro, e.g.,
529 * https://github.com/mingw-w64/mingw-w64/blob/v10.0.0/mingw-w64-headers/crt/stdlib.h#L704
530 * which breaks the definition of DoShattering() in diagrams.c that uses
531 * "environ" as a formal parameter. Because FORM doesn't use the POSIX "environ"
532 * or its variant anyway, we can just undefine it.
533 */
534#ifdef environ
535#undef environ
536#endif
537
538#ifdef WITHMPI
539#include "parallel.h"
540#endif
541
542#endif /* __FORM3H__ */