FORM  4.3
form3.h
Go to the documentation of this file.
1 
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 
217 typedef short WORD;
218 typedef long LONG;
219 typedef unsigned short UWORD;
220 typedef 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 
245 typedef int WORD;
246 typedef long long LONG;
247 typedef unsigned int UWORD;
248 typedef 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 
263 typedef int WORD;
264 typedef long LONG;
265 typedef unsigned int UWORD;
266 typedef 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 
283 STATIC_ASSERT(sizeof(WORD) * 8 == BITSINWORD);
284 STATIC_ASSERT(sizeof(LONG) * 8 == BITSINLONG);
285 STATIC_ASSERT(sizeof(WORD) * 2 == sizeof(LONG));
286 STATIC_ASSERT(sizeof(LONG) >= sizeof(int *));
287 STATIC_ASSERT(sizeof(INT16) == 2);
288 STATIC_ASSERT(sizeof(INT32) == 4);
289 STATIC_ASSERT(sizeof(INT64) == 8);
290 #ifdef INT128
291 STATIC_ASSERT(sizeof(INT128) == 16);
292 #endif
293 
294 #if BITSINWORD == 32
295 #define WORDSIZE32 1
296 #endif
297 
298 typedef void VOID;
299 typedef signed char SBYTE;
300 typedef unsigned char UBYTE;
301 typedef unsigned int UINT;
302 typedef ULONG RLONG; /* Used in reken.c. */
303 typedef 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  */
308 typedef 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>
340 namespace alignof_impl_ {
341 template<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
478 typedef struct FiLeS {
479  int descriptor;
480 } FILES;
481 extern FILES *Uopen(char *,char *);
482 extern int Uclose(FILES *);
483 extern size_t Uread(char *,size_t,size_t,FILES *);
484 extern size_t Uwrite(char *,size_t,size_t,FILES *);
485 extern int Useek(FILES *,off_t,int);
486 extern off_t Utell(FILES *);
487 extern void Uflush(FILES *);
488 extern int Ugetpos(FILES *,fpos_t *);
489 extern int Usetpos(FILES *,fpos_t *);
490 extern 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 }
501 extern 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__ */