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