1 // CLN internal macros
2 
3 #ifndef _CL_MACROS_H
4 #define _CL_MACROS_H
5 
6 #include "cln/types.h"
7 #include "cln/exception.h"
8 
9 // Concatenation of macroexpanded tokens.
10 // Example:
11 //   #undef x
12 //   #define y 16
13 //   CONCAT(x,y)        ==>  'x16' (not 'xy' !)
14   #define CONCAT_(xxx,yyy)  xxx##yyy
15   #define CONCAT3_(aaa,bbb,ccc)  aaa##bbb##ccc
16   #define CONCAT4_(aaa,bbb,ccc,ddd)  aaa##bbb##ccc##ddd
17   #define CONCAT5_(aaa,bbb,ccc,ddd,eee)  aaa##bbb##ccc##ddd##eee
18   #define CONCAT6_(aaa,bbb,ccc,ddd,eee,fff)  aaa##bbb##ccc##ddd##eee##fff
19   #define CONCAT7_(aaa,bbb,ccc,ddd,eee,fff,ggg)  aaa##bbb##ccc##ddd##eee##fff##ggg
20   #define CONCAT(xxx,yyy)  CONCAT_(xxx,yyy)
21   #define CONCAT3(aaa,bbb,ccc)  CONCAT3_(aaa,bbb,ccc)
22   #define CONCAT4(aaa,bbb,ccc,ddd)  CONCAT4_(aaa,bbb,ccc,ddd)
23   #define CONCAT5(aaa,bbb,ccc,ddd,eee)  CONCAT5_(aaa,bbb,ccc,ddd,eee)
24   #define CONCAT6(aaa,bbb,ccc,ddd,eee,fff)  CONCAT6_(aaa,bbb,ccc,ddd,eee,fff)
25   #define CONCAT7(aaa,bbb,ccc,ddd,eee,fff,ggg)  CONCAT7_(aaa,bbb,ccc,ddd,eee,fff,ggg)
26 
27 // Convert tokens to strings.
28 // STRING(token)  ==>  "token"
29   #define STRING(token) #token
30   #define STRINGIFY(token) STRING(token)
31 
32 // Declare functions that don't return.
33 // nonreturning_function(extern,exit,(void)); == extern void exit (void);
34   #ifdef __GNUC__
35     #if (__GNUC__ >= 3) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9))
36       #define nonreturning_function(storclass,funname,arguments)  \
37         storclass void funname arguments __attribute__((__noreturn__))
38     #else
39       #define nonreturning_function(storclass,funname,arguments)  \
40         typedef void CONCAT3(funname,_function_,__LINE__) arguments; \
41         storclass __volatile__ CONCAT3(funname,_function_,__LINE__) funname
42     #endif
43   #else
44     #define nonreturning_function(storclass,funname,arguments)  \
45       storclass void funname arguments
46   #endif
47 
48 // Declaration of variables.
49   #define var
50 
51 // `if' with more than one clause:
52 // if (cond1) ... {elif (condi) ...} [else ...]
53   #define elif  else if
54 
55 // Endless loop, leave with  break;  or return...;
56   #define loop  while (1)
57 
58 // Reversed end condition.
59 // Allows   until (expression) statement
60 // and      do statement until (expression);
61   #define until(expression)  while(!(expression))
62 
63 // Boolean values.
64   #define FALSE  0
65   #define TRUE   1
66 
67 // Ignore a value (instead of assigning it to a variable).
68 // unused ...
69   #if defined(__GNUC__) || defined(__KCC) // avoid a gcc warning "statement with no effect"
70     #define unused  (void)
71   #else
72     #define unused
73   #endif
74 
75 // Denotes a point where control flow can never arrive.
76 // NOTREACHED
77   #define NOTREACHED  throw notreached_exception(__FILE__,__LINE__);
78 
79 // Check an arithmetic expression.
80 // ASSERT(expr)
81   #define ASSERT(expr)  { if (!(expr)) { NOTREACHED } }
82 
83 // alloca()
84   #if defined(__GNUC__) && !defined(__riscos) && !defined(__convex__)
85     #undef alloca
86     #define alloca  __builtin_alloca
87   #elif defined(_MSC_VER)
88     #include <malloc.h>
89     #define alloca  _alloca
90   #elif defined(HAVE_ALLOCA_H) || defined(__riscos)
91     #include <alloca.h>
92     #ifndef alloca // Sometimes `alloca' is defined as a macro...
93       #if defined(__osf__)
94         extern "C" char* alloca (int size);
95       #else
96         extern "C" void* alloca (size_t size);
97       #endif
98     #endif
99   #elif defined(_AIX)
100     #pragma alloca // AIX requires this to be the first thing in the file.
101   #elif defined(WATCOM)
102     #include <malloc.h> // defines `alloca' as a macro
103   #elif !defined(NO_ALLOCA)
104     extern "C" void* alloca (size_t size);
105   #endif
106 
107 // NULL pointer.
108   #undef NULL
109   #define NULL  0
110 
111 // Bit number n (0<=n<32 or 0<=n<64)
112   #ifdef HAVE_FAST_LONGLONG
113     #define bit(n)  (long long)(1ULL<<(n))
114   #else
115     #define bit(n)  (long)(1UL<<(n))
116   #endif
117 // Bit number n (0<n<=32) mod 2^32
118   #ifdef HAVE_FAST_LONGLONG
119     #define bitm(n)  (long long)(2ULL<<((n)-1))
120   #else
121     #define bitm(n)  (long)(2UL<<((n)-1))
122   #endif
123 // Test bit n in x, n constant, x a cl_uint:
124   #if !(defined(__sparc__) || defined(__sparc64__))
125     #define bit_test(x,n)  ((x) & bit(n))
126   #else
127     // On Sparcs long constants are slower than shifts.
128     #if !defined(__GNUC__)
129       #define bit_test(x,n)  \
130         ((n)<12 ? ((x) & bit(n)) : ((sint32)((uint32)(x) << (31-(n))) < 0))
131     #else // gcc optimizes boolean expressions better this way:
132       #define bit_test(x,n)  \
133         (   ( ((n)<12) && ((x) & bit(n)) )                           \
134          || ( ((n)>=12) && ((sint32)((uint32)(x) << (31-(n))) < 0) ) \
135         )
136     #endif
137   #endif
138 // minus bit number n (0<=n<32 or 0<=n<64)
139   #ifdef HAVE_FAST_LONGLONG
140     #define minus_bit(n)  (long long)(-1ULL<<(n))
141   #else
142     #define minus_bit(n)  (long)(-1UL<<(n))
143   #endif
144 // minus bit number n (0<n<=32) mod 2^32
145   #ifdef HAVE_FAST_LONGLONG
146     #define minus_bitm(n)  (long long)(-2ULL<<((n)-1))
147   #else
148     #define minus_bitm(n)  (long)(-2UL<<((n)-1))
149   #endif
150 
151 // Return 2^n, n a constant expression.
152 // Same as bit(n), but undefined if n<0 or n>={long_}long_bitsize.
153   #if defined(HAVE_FAST_LONGLONG) || defined(intQsize)
154     #define bitc(n)  (1ULL << (((n) >= 0 && (n) < long_long_bitsize) ? (n) : 0))
155   #else
156     #define bitc(n)  (1UL << (((n) >= 0 && (n) < long_bitsize) ? (n) : 0))
157   #endif
158 
159 // floor(a,b) for a>=0, b>0 returns floor(a/b).
160 // b should be a constant expression.
161   #define floor(a_from_floor,b_from_floor)  ((a_from_floor) / (b_from_floor))
162 // Save the macro in case we need to include <cmath>.
163   #define cln_floor(a_from_floor,b_from_floor)  ((a_from_floor) / (b_from_floor))
164 
165 // ceiling(a,b) for a>=0, b>0 returns ceiling(a/b) = floor((a+b-1)/b).
166 // b should be a constant expression.
167   #define ceiling(a_from_ceiling,b_from_ceiling)  \
168     (((a_from_ceiling) + (b_from_ceiling) - 1) / (b_from_ceiling))
169 
170 // round_down(a,b) decreases a>=0 such that it becomes divisible by b>0.
171 // b should be a constant expression.
172   #define round_down(a_from_round,b_from_round)  \
173     (floor(a_from_round,b_from_round)*(b_from_round))
174 
175 // round_up(a,b) increases a>=0 such that it becomes divisible by b>0.
176 // b should be a constant expression.
177   #define round_up(a_from_round,b_from_round)  \
178     (ceiling(a_from_round,b_from_round)*(b_from_round))
179 
180 // We never call malloc(0), so no need to handle it.
181   #define __MALLOC_0_RETURNS_NULL
182 
183 // Loop which executes a statement a given number of times.
184 // dotimesC(countvar,count,statement);
185 // countvar must be of type `uintC'. It is modified!
186   #define dotimesC(countvar_from_dotimesC,count_from_dotimesC,statement_from_dotimesC)  \
187     { countvar_from_dotimesC = (count_from_dotimesC);         \
188       until (countvar_from_dotimesC==0)                       \
189         {statement_from_dotimesC; countvar_from_dotimesC--; } \
190     }
191   #define dotimespC(countvar_from_dotimespC,count_from_dotimespC,statement_from_dotimespC)  \
192     { countvar_from_dotimespC = (count_from_dotimespC);                   \
193       do {statement_from_dotimespC} until (--countvar_from_dotimespC==0); \
194     }
195 
196 // doconsttimes(count,statement);
197 // führt statement count mal aus (count mal der Code!),
198 // wobei count eine constant-expression >=0, <=8 ist.
199   #define doconsttimes(count_from_doconsttimes,statement_from_doconsttimes)  \
200     { if (0 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \
201       if (1 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \
202       if (2 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \
203       if (3 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \
204       if (4 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \
205       if (5 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \
206       if (6 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \
207       if (7 < (count_from_doconsttimes)) { statement_from_doconsttimes; } \
208     }
209 
210 // DOCONSTTIMES(count,macroname);
211 // ruft count mal den Macro macroname auf (count mal der Code!),
212 // wobei count eine constant-expression >=0, <=8 ist.
213 // Dabei bekommt macroname der Reihe nach die Werte 0,...,count-1 übergeben.
214   #define DOCONSTTIMES(count_from_DOCONSTTIMES,macroname_from_DOCONSTTIMES)  \
215     { if (0 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((0 < (count_from_DOCONSTTIMES) ? 0 : 0)); } \
216       if (1 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((1 < (count_from_DOCONSTTIMES) ? 1 : 0)); } \
217       if (2 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((2 < (count_from_DOCONSTTIMES) ? 2 : 0)); } \
218       if (3 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((3 < (count_from_DOCONSTTIMES) ? 3 : 0)); } \
219       if (4 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((4 < (count_from_DOCONSTTIMES) ? 4 : 0)); } \
220       if (5 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((5 < (count_from_DOCONSTTIMES) ? 5 : 0)); } \
221       if (6 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((6 < (count_from_DOCONSTTIMES) ? 6 : 0)); } \
222       if (7 < (count_from_DOCONSTTIMES)) { macroname_from_DOCONSTTIMES((7 < (count_from_DOCONSTTIMES) ? 7 : 0)); } \
223     }
224 
225 // AT_INITIALIZATION(id) { ... }
226 // executes the given code at initialization time of the file.
227 // The id is something unique.
228   #define AT_INITIALIZATION(id)  \
229     class CONCAT3(INIT_CLASS_,id,__LINE__) {				\
230       public: CONCAT3(INIT_CLASS_,id,__LINE__) (void);			\
231     } CONCAT4(INIT_CLASS_,id,__LINE__,_DUMMY);				\
232     inline CONCAT3(INIT_CLASS_,id,__LINE__)::CONCAT3(INIT_CLASS_,id,__LINE__) (void)
233 
234 // AT_DESTRUCTION(id) { ... }
235 // executes the given code at destruction time of the file.
236 // The id is something unique.
237   #define AT_DESTRUCTION(id)  \
238     class CONCAT3(DESTR_CLASS_,id,__LINE__) {				\
239       public: ~CONCAT3(DESTR_CLASS_,id,__LINE__) (void);		\
240     } CONCAT4(DESTR_CLASS_,id,__LINE__,_DUMMY);				\
241     CONCAT3(DESTR_CLASS_,id,__LINE__)::~CONCAT3(DESTR_CLASS_,id,__LINE__) (void)
242 
243 // Inside a class definition:
244 // Overload `new' so that a class object can be allocated anywhere.
245 #define ALLOCATE_ANYWHERE(classname)  \
246     /* Ability to place an object at a given address. */		\
247 public:									\
248     void* operator new (size_t size) { return malloc_hook(size); }	\
249     void* operator new (size_t size, classname* ptr) { unused size; return ptr; } \
250     void operator delete (void* ptr) { free_hook(ptr); }
251 
252 // init1(type, object) (value);
253 // initializes `object' with `value', by calling `type''s constructor.
254 // (The identifiers `init' and `Init' are already in use by <streambuf.h>,
255 // it's a shame!)
256 #define init1(type,lvalue)  (void) new (&(lvalue)) type
257 
258 #include "base/cl_maybe_inline.h"
259 
260 #endif /* _CL_MACROS_H */
261