/* (-lgl * Coherent 386 release 4.2 * Copyright (c) 1982, 1993 by Mark Williams Company. * All rights reserved. May not be copied without permission. * For copying permission and licensing info, write licensing@mwc.com -lgl) */ #ifndef __COMMON__LIMITS_H__ #define __COMMON__LIMITS_H__ /* * This header file is the internal equivalent of the ISO C Standard header * file <limits.h>. It defines many similar constants that are useful in * system headers for parameterizing definitions based on such things as * the representation ranges of various types, but the names of the constants * are prefixed with underscores to stay in the implementation namespace. * * Rather than just stating the constants, we calculate then from a small * set of fundamental parameters. Doing it this way will give the right * results as long as your preprocessor and compiler understand that ISO C * type rules. If they don't, well, this will tell you that. * * Note that the "fundamental" constants can be determined at run-time in * a portable fashion, but because we need them for the preprocessor we must * depend on someone running such a program and supplying them. * * The fundamental parameters: * __CHAR_BIT The number of bits in a character. Although most systems built in the 1990s have 8, others are possible. * __SHORT_DIV The factor by which to divide the number of bits in * an integer by to give the number of bits in a short. * __TWOSCOMP This contains 1 if the representation is twos- * complement for negative integers, 0 if we have a * sign-magnitude or ones-complement machine. * __CHAR_SIGNED 1 if characters are signed, undefined if they are * unsigned. * * Parameters that can be inferred from the type system: * __INT_BIT The number of bits in an integer. * __LONG_BIT The number of bits in a long. */ #include <common/feature.h> #if __COHERENT__ || __BORLANDC__ || defined (GNUDOS) # define __CHAR_BIT 8U # define __TWOSCOMP 1 #if '\x80' < 0 # define __CHAR_SIGNED 1 #endif # if __BORLANDC__ # define __SHORT_DIV 1 # else # define __SHORT_DIV 2 # endif #else # error The fundamental parameters of this system are not known. #endif #define __TOP_BIT_INT(bytes) (1U << (__CHAR_BIT * (bytes) - 1)) #define __TOP_BIT_LONG(bytes) (1UL << (__CHAR_BIT * (bytes) - 1)) #if (~ 0U ^ (~ 0U / 2)) == __TOP_BIT_INT(1) # define __INT_BIT (1 * __CHAR_BIT) #elif (~ 0U ^ (~ 0U / 2)) == __TOP_BIT_INT(2) # define __INT_BIT (2 * __CHAR_BIT) #elif (~ 0U ^ (~ 0U / 2)) == __TOP_BIT_INT(4) # define __INT_BIT (4 * __CHAR_BIT) #elif (~ 0U ^ (~ 0U / 2)) == __TOP_BIT_INT(8) # define __INT_BIT (8 * __CHAR_BIT) #else # error Cannot determine number of bits per int. #endif #if (~ 0UL ^ (~ 0UL / 2)) == __TOP_BIT_LONG(1) # define __LONG_BIT (1 * __CHAR_BIT) #elif (~ 0UL ^ (~ 0UL / 2)) == __TOP_BIT_LONG(2) # define __LONG_BIT (2 * __CHAR_BIT) #elif (~ 0UL ^ (~ 0UL / 2)) == __TOP_BIT_LONG(4) # define __LONG_BIT (4 * __CHAR_BIT) #elif (~ 0UL ^ (~ 0UL / 2)) == __TOP_BIT_LONG(8) # define __LONG_BIT (8 * __CHAR_BIT) #else # error Cannot determine number of bits per long. #endif #define __SHRT_BIT (__INT_BIT / __SHORT_DIV) #define __UCHAR_MAX ((1U << (__CHAR_BIT - 1)) + \ ((1U << (__CHAR_BIT - 1)) - 1)) #define __SCHAR_MAX ((1 << (__CHAR_BIT - 2)) + \ ((1 << (__CHAR_BIT - 2)) - 1)) #define __SCHAR_MIN (- __SCHAR_MAX - __TWOSCOMP) #if __CHAR_SIGNED # define __CHAR_MAX __SCHAR_MAX # define __CHAR_MIN __SCHAR_MIN #else # define __CHAR_MAX __UCHAR_MAX # define __CHAR_MIN 0 #endif #define __USHRT_MAX ((1U << (__SHRT_BIT - 1)) + \ ((1U << (__SHRT_BIT - 1)) - 1)) #define __SHRT_MAX ((1 << (__SHRT_BIT - 2)) + \ ((1 << (__SHRT_BIT - 2)) - 1)) #define __SHRT_MIN (- __SHRT_MAX - __TWOSCOMP) #define __UINT_MAX ((1U << (__INT_BIT - 1)) + \ ((1U << (__INT_BIT - 1)) - 1)) #define __INT_MAX ((1 << (__INT_BIT - 2)) + \ ((1 << (__INT_BIT - 2)) - 1)) #define __INT_MIN (- __INT_MAX - __TWOSCOMP) #define __ULONG_MAX ((1U << (__LONG_BIT - 1)) + \ ((1U << (__LONG_BIT - 1)) - 1)) #define __LONG_MAX ((1 << (__LONG_BIT - 2)) + \ ((1 << (__LONG_BIT - 2)) - 1)) #define __LONG_MIN (- __LONG_MAX - __TWOSCOMP) /* * A frequent use of all the above is to figure out a mapping from the C data * types to machine 8/16/32-bit specific idioms, where the actual assignment * of data types to machine widths is highly variable (perhaps even controlled * by a compiler switch). * * Here we create standard aliases for the 8-bit-multiple cases, which careful * programs can use token-pasting with to further parameterize things. If * other macros use the __CONCAT... () facility from <sys/ccompat.h> to create * type-encoded macro names, the extra level of indirection in the * preprocessor that comes from using a concatenation macro will cause the * following substitutions to be made before the final token is created, thus * automagically mapping from types into word sizes. * * Because the following information is mainly used in token-pasting, please * leave the decimal constants alone! */ #if __CHAR_BIT == 8 # define __CHAR 8 #endif #if __SHRT_BIT == 16 # define __SHORT 16 #elif __SHRT_BIT == 32 # define __SHORT 32 #endif #if __INT_BIT == 16 # define __INT 16 #elif __INT_BIT == 32 # define __INT 32 #elif __INT_BIT == 64 # define __INT 64 #endif #if __LONG_BIT == 32 # define __LONG 32 #elif __LONG_BIT == 64 # define __LONG 64 #endif /* * Of course, the reverse of the above is also highly useful; being able to * select the data type that is the best match for a particular width is very * useful for setting up data types that must match some external protocol * specification (although one much be very careful of alignment issues, which * are beyond our scope here). * * Here we define some reverse mappings from the above. Although the tests * below are clearly biased towards the current state of affairs, at least we * have taken steps to parameterize this whole thing. */ #if __CHAR_BIT == 8 # define __8 _UCHAR #endif #if _SHRT_BIT == 16 # define __16 _USHRT #endif #if _INT_BIT == 32 # define __32 _UINT #elif _LONG_BIT == 32 # define __32 _ULONG #endif #endif /* ! defined (__COMMON__LIMITS_H__) */