1 /*=========================================================================== 2 * Filename : scmint.h 3 * About : Integer types for Scheme implementation 4 * 5 * Copyright (C) 2005-2006 YAMAMOTO Kengo <yamaken AT bp.iij4u.or.jp> 6 * Copyright (c) 2007-2008 SigScheme Project <uim-en AT googlegroups.com> 7 * 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of authors nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 24 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR 27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 30 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 ===========================================================================*/ 35 36 /* 37 * This file is independent of SigScheme and can be used to implement Scheme 38 * implementation-neutral generic subordinate parts, such as ports and 39 * character encoding handlers. In our short-term development, this separation 40 * aims that making the underlying port implementations and encoding handlers 41 * directly usable from libuim without SigScheme. It is needed to make libuim 42 * Scheme-implementation independent without problems caused by differences of 43 * implementation-specific character encoding handling behaviors. 44 * 45 * The copyright will be succeeded to the uim Project once the subordinate 46 * parts are completely separated from SigScheme. 47 * 48 * -- YamaKen 2006-03-30 49 */ 50 51 #ifndef __SCM_SCMINT_H 52 #define __SCM_SCMINT_H 53 54 #include <sigscheme/config.h> 55 56 #if HAVE_STDINT_H 57 #include <stdint.h> 58 #endif 59 #if HAVE_INTTYPES_H 60 #include <inttypes.h> 61 #endif 62 #if HAVE_SYS_INTTYPES_H 63 #include <sys/inttypes.h> 64 #endif 65 #if HAVE_SYS_TYPES_H 66 #include <sys/types.h> 67 #endif 68 #include <limits.h> 69 70 #ifdef __cplusplus 71 extern "C" { 72 #endif 73 74 /*======================================= 75 Macro Definitions 76 =======================================*/ 77 #ifndef SCM_EMPTY_EXPR 78 #define SCM_EMPTY_EXPR ((void)0) 79 #endif 80 81 /*======================================= 82 Type Definitions: stdint.h subtitutes 83 =======================================*/ 84 #define SCM_STDINT_MIN(t) ((t)(~(u##t)0)) 85 #define SCM_STDINT_MAX(t) ((t)((~(u##t)0) >> 1)) 86 87 /* Note: Since these macros are not pure constant such as (-1LL), testing in 88 * preprocessor directives (such as #if INT32_MAX < LONG_MAX) does not work. */ 89 #ifndef INT8_MIN 90 #define INT8_MIN SCM_STDINT_MIN(int8_t) 91 #endif 92 #ifndef INT16_MIN 93 #define INT16_MIN SCM_STDINT_MIN(int16_t) 94 #endif 95 #ifndef INT32_MIN 96 #define INT32_MIN SCM_STDINT_MIN(int32_t) 97 #endif 98 #ifndef INT64_MIN 99 #define INT64_MIN SCM_STDINT_MIN(int64_t) 100 #endif 101 #ifndef INTMAX_MIN 102 #define INTMAX_MIN SCM_STDINT_MIN(intmax_t) 103 #endif 104 #ifndef INTPTR_MIN 105 #define INTPTR_MIN SCM_STDINT_MIN(intptr_t) 106 #endif 107 108 #ifndef INT8_MAX 109 #define INT8_MAX SCM_STDINT_MAX(int8_t) 110 #endif 111 #ifndef INT16_MAX 112 #define INT16_MAX SCM_STDINT_MAX(int16_t) 113 #endif 114 #ifndef INT32_MAX 115 #define INT32_MAX SCM_STDINT_MAX(int32_t) 116 #endif 117 #ifndef INT64_MAX 118 #define INT64_MAX SCM_STDINT_MAX(int64_t) 119 #endif 120 #ifndef INTMAX_MAX 121 #define INTMAX_MAX SCM_STDINT_MAX(intmax_t) 122 #endif 123 #ifndef INTPTR_MAX 124 #define INTPTR_MAX SCM_STDINT_MAX(intptr_t) 125 #endif 126 127 #ifndef UINT8_MAX 128 #define UINT8_MAX (~(uint8_t)0) 129 #endif 130 #ifndef UINT16_MAX 131 #define UINT16_MAX (~(uint16_t)0) 132 #endif 133 #ifndef UINT32_MAX 134 #define UINT32_MAX (~(uint32_t)0) 135 #endif 136 #ifndef UINT64_MAX 137 #define UINT64_MAX (~(uint64_t)0) 138 #endif 139 #ifndef UINTMAX_MAX 140 #define UINTMAX_MAX (~(uintmax_t)0) 141 #endif 142 #ifndef UINTPTR_MAX 143 #define UINTPTR_MAX (~(uintptr_t)0) 144 #endif 145 146 /*======================================= 147 Type Definitions 148 =======================================*/ 149 /* 150 * Our own Boolean type 151 * 152 * libsscm does not use C99 stdbool, its autoconf equivalent or popular 153 * combination of {int, TRUE, FALSE}, to avoid system-dependent ABI 154 * incompatibility (such as size difference) and client-dependent problems 155 * (such as an unexpected assumption about TRUE value). 156 * 157 * The definition use plain typedef and macro definition to avoid 158 * misrecognition about the usage of the type, such as enum-related ones. 159 * 160 * *** IMPORTANT *** 161 * 162 * Do not test a value with (val == scm_true). The scm_true is only A TYPICAL 163 * VALUE FOR TRUE. Use (val) or (val != scm_false) instead. 164 * 165 */ 166 typedef int scm_bool; 167 #define scm_false 0 168 #define scm_true 1 169 170 /* 171 * Fixed bit width numbers 172 * 173 * This types define internal representation corresponding to each number 174 * objects of Scheme. 175 * 176 * The configuration alters both ABI and storage implementation of 177 * libsscm. Although it specifies the bit width, actual width varies for each 178 * underlying storage implementation. Refer SCM_INT_BITS, SCM_INT_MAX and so 179 * on to know such values. 180 * 181 * The integer type defaults to 64-bit on LP64 platforms. 182 */ 183 #if SCM_USE_64BIT_FIXNUM 184 typedef int64_t scm_int_t; 185 typedef uint64_t scm_uint_t; 186 #define ALIGNOF_SCM_INT_T ALIGNOF_INT64_T 187 #define ALIGNOF_SCM_UINT_T ALIGNOF_INT64_T 188 #define SIZEOF_SCM_INT_T SIZEOF_INT64_T 189 #define SIZEOF_SCM_UINT_T SIZEOF_INT64_T 190 #define SCM_INT_T_MAX INT64_MAX 191 #define SCM_INT_T_MIN INT64_MIN 192 #define SCM_UINT_T_MAX UINT64_MAX 193 #elif SCM_USE_32BIT_FIXNUM 194 typedef int32_t scm_int_t; 195 typedef uint32_t scm_uint_t; 196 #define ALIGNOF_SCM_INT_T ALIGNOF_INT32_T 197 #define ALIGNOF_SCM_UINT_T ALIGNOF_INT32_T 198 #define SIZEOF_SCM_INT_T SIZEOF_INT32_T 199 #define SIZEOF_SCM_UINT_T SIZEOF_INT32_T 200 #define SCM_INT_T_MAX INT32_MAX 201 #define SCM_INT_T_MIN INT32_MIN 202 #define SCM_UINT_T_MAX UINT32_MAX 203 #elif SCM_USE_INT_FIXNUM 204 typedef int scm_int_t; 205 typedef unsigned int scm_uint_t; 206 #define ALIGNOF_SCM_INT_T ALIGNOF_INT 207 #define ALIGNOF_SCM_UINT_T ALIGNOF_INT 208 #define SIZEOF_SCM_INT_T SIZEOF_INT 209 #define SIZEOF_SCM_UINT_T SIZEOF_INT 210 #define SCM_INT_T_MAX INT_MAX 211 #define SCM_INT_T_MIN INT_MIN 212 #define SCM_UINT_T_MAX UINT_MAX 213 #else 214 #undef SCM_USE_LONG_FIXNUM 215 #define SCM_USE_LONG_FIXNUM 1 216 typedef long scm_int_t; 217 typedef unsigned long scm_uint_t; 218 #define ALIGNOF_SCM_INT_T ALIGNOF_LONG 219 #define ALIGNOF_SCM_UINT_T ALIGNOF_LONG 220 #define SIZEOF_SCM_INT_T SIZEOF_LONG 221 #define SIZEOF_SCM_UINT_T SIZEOF_LONG 222 #define SCM_INT_T_MAX LONG_MAX 223 #define SCM_INT_T_MIN LONG_MIN 224 #define SCM_UINT_T_MAX ULONG_MAX 225 #endif 226 227 /* 228 * Integer representation of abstract reference to ScmObj 229 * 230 * This types define sufficient width integer which is capable of holding any 231 * ScmRef that is used in currently selected storage implementation. 232 * 233 * A ScmRef is abstract reference to a ScmObj. It is usually a pointer, but do 234 * not assume it since another representation may be used. For instance, a pair 235 * of heap index and object index in the heap can be a ScmRef. In such case, 236 * scm_uintref_t can address any object in a heap scattered in full 64-bit 237 * address space even if the bit width of the reference is smaller than a 238 * 64-bit pointer. So any size assumption between pointer and the reference 239 * must not be coded. 240 * 241 * The integer representation is intended for low-level bitwise processing. Use 242 * ScmRef instead for higher-level code. 243 * 244 * Since actual representation is entirely controlled in each storage 245 * implementation, this configuration only specifies the ABI about maximum size 246 * of reference objects. Deal with particular storage implementation if fine 247 * tuning is required. Otherwise simply keep untouched. 248 * 249 * The type defaults to direct pointer represenation, so *LP64 gets 64-bit. 250 */ 251 #if SCM_USE_64BIT_SCMREF 252 typedef int64_t scm_intref_t; 253 typedef uint64_t scm_uintref_t; 254 #define ALIGNOF_SCM_INTREF_T ALIGNOF_INT64_T 255 #define ALIGNOF_SCM_UINTREF_T ALIGNOF_INT64_T 256 #define SIZEOF_SCM_INTREF_T SIZEOF_INT64_T 257 #define SIZEOF_SCM_UINTREF_T SIZEOF_INT64_T 258 #elif SCM_USE_32BIT_SCMREF 259 typedef int32_t scm_intref_t; 260 typedef uint32_t scm_uintref_t; 261 #define ALIGNOF_SCM_INTREF_T ALIGNOF_INT32_T 262 #define ALIGNOF_SCM_UINTREF_T ALIGNOF_INT32_T 263 #define SIZEOF_SCM_INTREF_T SIZEOF_INT32_T 264 #define SIZEOF_SCM_UINTREF_T SIZEOF_INT32_T 265 #else 266 #undef SCM_USE_INTPTR_SCMREF 267 #define SCM_USE_INTPTR_SCMREF 1 268 typedef intptr_t scm_intref_t; 269 typedef uintptr_t scm_uintref_t; 270 #define ALIGNOF_SCM_INTREF_T ALIGNOF_INTPTR_T 271 #define ALIGNOF_SCM_UINTREF_T ALIGNOF_INTPTR_T 272 #define SIZEOF_SCM_INTREF_T SIZEOF_INTPTR_T 273 #define SIZEOF_SCM_UINTREF_T SIZEOF_INTPTR_T 274 #endif 275 276 /* 277 * Integer representation of ScmObj 278 * 279 * This types define sufficient width integer which is capable of holding the 280 * ScmObj that is used in currently selected storage implementation. 281 * 282 * A ScmObj is abstract Scheme object. Its represenation and size vary for each 283 * storage implementations. But the size is surely defined as larger one of 284 * scm_uint_t and scm_uintref_t. It can be assumed on coding. 285 * 286 * The integer representation is intended for low-level bitwise processing. Use 287 * ScmObj instead for higher-level code. 288 * 289 * This configuration is passively chosen in accordance with the fixnum size 290 * and reference size. And of course alters the ABI. 291 */ 292 #if (SIZEOF_SCM_INT_T < SIZEOF_SCM_INTREF_T) 293 typedef scm_intref_t scm_intobj_t; 294 typedef scm_uintref_t scm_uintobj_t; 295 #define ALIGNOF_SCM_INTOBJ_T ALIGNOF_SCM_INTREF_T 296 #define ALIGNOF_SCM_UINTOBJ_T ALIGNOF_SCM_UINTREF_T 297 #define SIZEOF_SCM_INTOBJ_T SIZEOF_SCM_INTREF_T 298 #define SIZEOF_SCM_UINTOBJ_T SIZEOF_SCM_UINTREF_T 299 #else 300 typedef scm_int_t scm_intobj_t; 301 typedef scm_uint_t scm_uintobj_t; 302 #define ALIGNOF_SCM_INTOBJ_T ALIGNOF_SCM_INT_T 303 #define ALIGNOF_SCM_UINTOBJ_T ALIGNOF_SCM_UINT_T 304 #define SIZEOF_SCM_INTOBJ_T SIZEOF_SCM_INT_T 305 #define SIZEOF_SCM_UINTOBJ_T SIZEOF_SCM_UINT_T 306 #endif 307 308 /* 309 * Internal integer representation of Scheme character object 310 * 311 * The type is used to pass a Scheme-level character object in C codes. 312 * 313 * It is distinguished from the element of fixed-width character string 314 * (scm_wchar_t). This integer type is defined as wide as capable of any 315 * multibyte char, and not configurable, to keep ABI stable regardless of 316 * configuration about scm_wchar_t. 317 * 318 * Actual bit width varies for each storage implementation. Refer 319 * SCM_CHAR_BITS, SCM_CHAR_MAX and SCM_CHAR_MIN if needed. 320 */ 321 typedef int32_t scm_ichar_t; 322 #define ALIGNOF_SCM_ICHAR_T ALIGNOF_INT32_T 323 #define SIZEOF_SCM_ICHAR_T SIZEOF_INT32_T 324 #define SCM_ICHAR_T_MAX INT32_MAX 325 #define SCM_ICHAR_T_MIN INT32_MIN 326 #define SCM_ICHAR_EOF (-1) 327 328 /* 329 * Definitive byte type 330 * 331 * To avoid the sign-extension problem, platform-dependent signedness variation 332 * (for example, ARM compilers treat 'char' as 'unsigned char'), use this type 333 * for raw strings and so on. 334 */ 335 typedef unsigned char scm_byte_t; 336 #define ALIGNOF_SCM_BYTE_T ALIGNOF_CHAR 337 #define SIZEOF_SCM_BYTE_T SIZEOF_CHAR 338 #define SCM_BYTE_T_MAX UCHAR_MAX 339 #define SCM_BYTE_T_MIN 0 340 341 /* 342 * Constant-width character for strings (not used yet) 343 */ 344 #if SCM_HAS_4OCT_WCHAR 345 typedef uint32_t scm_wchar_t; 346 #define ALIGNOF_SCM_WCHAR_T ALIGNOF_INT32_T 347 #define SIZEOF_SCM_WCHAR_T SIZEOF_INT32_T 348 #elif SCM_HAS_2OCT_WCHAR 349 typedef uint16_t scm_wchar_t; 350 #define ALIGNOF_SCM_WCHAR_T ALIGNOF_INT16_T 351 #define SIZEOF_SCM_WCHAR_T SIZEOF_INT16_T 352 #else 353 typedef scm_byte_t scm_wchar_t; 354 #define ALIGNOF_SCM_WCHAR_T ALIGNOF_SCM_BYTE_T 355 #define SIZEOF_SCM_WCHAR_T SIZEOF_SCM_BYTE_T 356 #endif 357 358 /* size constraints */ 359 #if !( SIZEOF_SCM_INT_T == SIZEOF_SCM_UINT_T \ 360 && SIZEOF_SCM_INTREF_T == SIZEOF_SCM_UINTREF_T \ 361 && SIZEOF_SCM_INTOBJ_T == SIZEOF_SCM_UINTOBJ_T \ 362 && SIZEOF_SCM_INTREF_T <= SIZEOF_SCM_INTOBJ_T \ 363 && SIZEOF_SCM_INT_T <= SIZEOF_SCM_INTOBJ_T \ 364 && ((SIZEOF_SCM_UINTREF_T <= SIZEOF_SCM_UINT_T \ 365 && SIZEOF_SCM_UINTOBJ_T == SIZEOF_SCM_UINT_T) \ 366 || (SIZEOF_SCM_UINTREF_T > SIZEOF_SCM_UINT_T \ 367 && SIZEOF_SCM_UINTOBJ_T == SIZEOF_SCM_UINTREF_T)) \ 368 && SIZEOF_SCM_WCHAR_T <= SIZEOF_SCM_ICHAR_T \ 369 && SIZEOF_SCM_ICHAR_T <= SIZEOF_SCM_INT_T) 370 #error "size constraints of primitive types are broken" 371 #endif 372 373 #define SCM_MAX(a, b) (((a) < (b)) ? (b) : (a)) 374 #define SCM_MIN(a, b) (((a) > (b)) ? (b) : (a)) 375 376 /*======================================= 377 Variable Declarations 378 =======================================*/ 379 380 /*======================================= 381 Function Declarations 382 =======================================*/ 383 384 #ifdef __cplusplus 385 } 386 #endif 387 388 #endif /* __SCM_SCMINT_H */ 389