Coherent4.2.10/include/common/_limits.h

/* (-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__) */