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