Thanks.
- Michael
Here are my personal versions, from the various notes in
(ftp://ftp.dmk.com/DMK/sc22wg14/c9x/).
These may be out of date a bit, or incomplete, and please note that
I'm not a compiler writer, I just play one on the net.
To simplify things I came up with my own header, machine.h, that
allows me to have one inttypes.h for several architectures.
Alternatives would just be to define the actual #define you want in
inttypes.h, or omit the code for other architectures.
If you have any comments or corrections, please let me know.
-- begin bool.h
/* bool.h: boolean type from c9x working directory */
/* References:
* Document Number: WG14 N609/X3J11 96-073
*/
#ifndef _BOOL_H
#define _BOOL_H
/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
#ifdef c_plusplus
#ifndef __cplusplus
#define __cplusplus
#endif
#endif
/* allow C++ to define this in its own way */
#ifndef __cplusplus
typedef enum {
false,
true
} bool;
#define false(expr) ((expr) == false)
#define true(expr) ((expr) != false)
#define __bool_true_false_are_defined
#endif /* ! _cplusplus */
#endif /* ! _BOOL_H */
-- end bool.h
-- begin inttypes.h
/* inttypes.h: extended integer types from c9x working directory */
/* References:
* Kwan, John W. "Extended Integers For C." jk...@cup.hp.com
*/
#ifndef _INTTYPES_H
#define _INTTYPES_H
#include <machine.h>
#undef _not
/*********************** Basic integer types *****************************
**
** The following defines the basic fixed-size integer types.
**
** Implementations are free to typedef them to Standard C integer types or
** extensions that they support. If an implementation does not support one
** of the particular integer data types below, then it should not define the
** typedefs and macros corresponding to that data type.
**
** intmax_t and uintmax_t are to be the longest (in number of bits) signed
** and unsigned integer types supported by the implementation.
**
** intptr_t and uintptr_t are signed and unsigned integer types large enough
** to hold any data pointer; that is, data pointers can be assigned into or
** from these integer types without losing precision.
**
** intfast_t and uintfast_t are the most efficient signed and unsigned
** integer types of the implementation. These shall be at least 16-bits
* long.
**
*/
#ifdef _CPU_SUN_SPARC
typedef char int8_t; /* 8-bit signed integer */
typedef short int16_t; /* 16-bit signed integer */
typedef int int32_t; /* 32-bit signed integer */
typedef long long int64_t; /* 64-bit signed integer */
typedef unsigned char uint8_t; /* 8-bit unsigned integer */
typedef unsigned short uint16_t; /* 16-bit unsigned integer */
typedef unsigned int uint32_t; /* 32-bit unsigned integer */
typedef unsigned long long uint64_t; /* 64-bit unsigned integer */
/* largest signed integer supported */
typedef long long intmax_t;
/* largest unsigned integer supported */
typedef unsigned long long uintmax_t;
/* signed integer type capable of holding a void * */
typedef int * intptr_t;
/* unsigned integer type capable of holding a void * */
typedef unsigned int * uintptr_t;
typedef int intfast_t; /* most efficient signed integer type */
typedef unsigned int uintfast_t; /* most efficient unsigned integer type */
#endif /* _CPU_SUN_SPARC */
/*********************** Extended integer types *************************
**
** The following define the smallest integer types that can hold the
** specified number of bits.
**
** Implementations are free to typedef them to Standard C integer types or
** any supported extensions.
*/
#ifdef _CPU_SUN_SPARC
/* smallest signed integer of at least 8 bits */
typedef short int_least8_t;
/* the most efficient signed integer of at least 8 bits */
typedef int int_fast8_t;
/* smallest signed integer of at least 16 bits */
typedef short int_least16_t;
/* the most efficient signed integer of at least 16 bits */
typedef int int_fast16_t;
/* smallest signed integer of at least 32 bits */
typedef int int_least32_t;
/* the most efficient signed integer of at least 32 bits */
typedef int int_fast32_t;
/* smallest signed integer of at least 64 bits */
typedef long long int_least64_t;
/* the most efficient signed integer of at least 64 bits */
typedef long long int_fast64_t;
/* smallest unsigned integer of at least 8 bits */
typedef unsigned short uint_least8_t;
/* the most efficient unsigned integer of at least 8 bits */
typedef unsigned int uint_fast8_t;
/* smallest unsigned integer of at least 16 bits */
typedef unsigned short uint_least16_t;
/* the most efficient unsigned integer of at least 16 bits */
typedef unsigned int uint_fast16_t;
/* smallest unsigned integer of at least 32 bits */
typedef unsigned int uint_least32_t;
/* the most efficient unsigned integer of at least 32 bits */
typedef unsigned int uint_fast32_t;
/* smallest unsigned integer of at least 64 bits */
typedef unsigned long long uint_least64_t;
/* the most efficient unsigned integer of at least 64 bits */
typedef unsigned long long uint_fast64_t;
#endif /* _mach_sparc */
/* ************************** limits ***********************************
**
** The following defines the limits for the above types.
**
** INTMAX_MIN (minimum value of the largest supported signed integer type),
** INTMAX_MAX (maximum value of the largest supported signed integer type),
** and UINTMAX_MAX (maximum value of the largest supported unsigned integer
** type) can be set to implementation defined limits.
**
** NOTE : A programmer can test to see whether an implementation supports
** a particular size of integer by testing if the macro that gives the
** maximum for that datatype is defined. For example, if #ifdef UINT64_MAX
** tests false, the implementation does not support unsigned 64 bit integers.
**
** The values used below are merely examples. Actual limits for
** an implementation may vary.
**
** The type of these macros is intentionally unspecified.
**
*/
#ifdef _CPU_SUN_SPARC
#define INT8_MIN (-128)
#define INT16_MIN (-32767-1)
#define INT32_MIN (-2147483647-1)
#define INT64_MIN (-9223372036854775807-1)
#ifdef _not
#define INT_LEAST8_MIN ? /* implementation defined */
#define INT_LEAST16_MIN ? /* implementation defined */
#define INT_LEAST32_MIN ? /* implementation defined */
#define INT_LEAST64_MIN ? /* implementation defined */
#define INT_FAST8_MIN ? /* implementation defined */
#define INT_FAST16_MIN ? /* implementation defined */
#define INT_FAST32_MIN ? /* implementation defined */
#define INT_FAST64_MIN ? /* implementation defined */
#endif /* _not */
#define INT8_MAX (127)
#define INT16_MAX (32767)
#define INT32_MAX (2147483647)
#define INT64_MAX (9223372036854775807)
#define UINT8_MAX (255U)
#define UINT16_MAX (65535U)
#define UINT32_MAX (4294967295U)
#define UINT64_MAX (18446744073709551615U)
#ifdef _not
#define INTMAX_MIN ? /* implementation defined */
#define INTMAX_MAX ? /* implementation defined */
#define UINTMAX_MAX ? /* implementation defined */
#define INTFAST_MIN ? /* implementation defined */
#define INTFAST_MAX ? /* implementation defined */
#define UINTFAST_MAX ? /* implementation defined */
#define INT_LEAST8_MAX ? /* implementation defined */
#define INT_LEAST16_MAX ? /* implementation defined */
#define INT_LEAST32_MAX ? /* implementation defined */
#define INT_LEAST64_MAX ? /* implementation defined */
#define INT_FAST8_MAX ? /* implementation defined */
#define INT_FAST16_MAX ? /* implementation defined */
#define INT_FAST32_MAX ? /* implementation defined */
#define INT_FAST64_MAX ? /* implementation defined */
#endif /* _not */
#endif /* _CPU_SUN_SPARC */
/* ************************ CONSTANTS ********************************
**
** The following macros create constants of the above types. The intent is
** that:
** Constants defined using these macros have a specific size and
** signedness. The suffix used for int64_t and uint64_t (ll and ull)
** are for examples only. Implementations are permitted to use other
** suffixes.
*/
#define __CONCAT__(A,B) A ## B
#ifdef _CPU_SUN_SPARC
#define INT8_C(c) (c)
#define INT16_C(c) (c)
#define INT32_C(c) (c)
#define INT64_C(c) __CONCAT__(c,ll)
#define UINT8_C(c) __CONCAT__(c,u)
#define UINT16_C(c) __CONCAT__(c,u)
#define UINT32_C(c) __CONCAT__(c,u)
#define UINT64_C(c) __CONCAT__(c,ull)
#define INTMAX_C(c) __CONCAT__(c,ll)
#define UINTMAX_C(c) __CONCAT__(c,ull)
#endif /* _CPU_SUN_SPARC */
/************************* FORMATTED I/O ********************************
**
** The following macros can be used even when an implementation has not
** extended the printf/scanf family of functions.
**
** The form of the names of the macros is either "PRI" for printf specifiers
** or "SCN" for scanf specifiers, followed by the conversion specifier letter
** followed by the datatype size. For example, PRId32 is the macro for
** the printf d conversion specifier with the flags for 32 bit datatype.
**
** Separate macros are given for printf and scanf because typically different
** size flags must prefix the conversion specifier letter.
**
*** An example using one of these macros:
**
** uint64_t u;
** printf("u = %016" PRIx64 "\n", u);
**
** For the purpose of example, the definitions of the printf/scanf macros
** below have the values appropriate for a machine with 16 bit shorts,
** 32 bit ints, and 64 bit longs.
**
*/
#ifdef _CPU_SUN_SPARC
/* printf macros for signed integers */
#define PRId8 "d"
#define PRId16 "d"
#define PRId32 "d"
#define PRId64 "ld"
#define PRIdLEAST8 "d"
#define PRIdLEAST16 "d"
#define PRIdLEAST32 "d"
#define PRIdLEAST64 "ld"
#define PRIdFAST8 "d"
#define PRIdFAST16 "d"
#define PRIdFAST32 "d"
#define PRIdFAST64 "ld"
#define PRIi8 "i"
#define PRIi16 "i"
#define PRIi32 "i"
#define PRIi64 "li"
#define PRIiLEAST8 "i"
#define PRIiLEAST16 "i"
#define PRIiLEAST32 "i"
#define PRIiLEAST64 "li"
#define PRIiFAST8 "i"
#define PRIiFAST16 "i"
#define PRIiFAST32 "i"
#define PRIiFAST64 "li"
#define PRIo8 "o"
#define PRIo16 "o"
#define PRIo32 "o"
#define PRIo64 "lo"
#define PRIoLEAST8 "o"
#define PRIoLEAST16 "o"
#define PRIoLEAST32 "o"
#define PRIoLEAST64 "lo"
#define PRIoFAST8 "o"
#define PRIoFAST16 "o"
#define PRIoFAST32 "o"
#define PRIoFAST64 "lo"
#define PRIx8 "x"
#define PRIx16 "x"
#define PRIx32 "x"
#define PRIx64 "lx"
#define PRIxLEAST8 "x"
#define PRIxLEAST16 "x"
#define PRIxLEAST32 "x"
#define PRIxLEAST64 "lx"
#define PRIxFAST8 "x"
#define PRIxFAST16 "x"
#define PRIxFAST32 "x"
#define PRIxFAST64 "lx"
#define PRIX8 "X"
#define PRIX16 "X"
#define PRIX32 "X"
#define PRIX64 "lX"
#define PRIXLEAST8 "X"
#define PRIXLEST16 "X"
#define PRIXLEST32 "X"
#define PRIXLEST64 "lX"
#define PRIXFAST8 "X"
#define PRIXFAST16 "X"
#define PRIXFAST32 "X"
#define PRIXFAST64 "lX"
/* printf macros for unsigned integers */
#define PRIu8 "u"
#define PRIu16 "u"
#define PRIu32 "u"
#define PRIu64 "lu"
#define PRIuLEAST8 "u"
#define PRIuLEAST16 "u"
#define PRIuLEAST32 "u"
#define PRIuLEAST64 "lu"
#define PRIuFAST8 "u"
#define PRIuFAST16 "u"
#define PRIuFAST32 "u"
#define PRIuFAST64 "lu"
/* scanf macros */
#define SCNd16 "hd"
#define SCNd32 "d"
#define SCNd64 "ld"
#define SCNi16 "hi"
#define SCNi32 "i"
#define SCNi64 "li"
#define SCNo16 "ho"
#define SCNo32 "o"
#define SCNo64 "lo"
#define SCNu16 "hu"
#define SCNu32 "u"
#define SCNu64 "lu"
#define SCNx16 "hx"
#define SCNx32 "x"
#define SCNx64 "lx"
#ifdef _not
/* The following macros define I/O formats for intmax_t and uintmax_t. */
#define PRIdMAX ? /* implementation defined */
#define PRIoMAX ? /* implementation defined */
#define PRIxMAX ? /* implementation defined */
#define PRIuMAX ? /* implementation defined */
#define SCNiMAX ? /* implementation defined */
#define SCNdMAX ? /* implementation defined */
#define SCNoMAX ? /* implementation defined */
#define SCNxMAX ? /* implementation defined */
/* The following macros define I/O formats for intfast_t and uintfast_t. */
#define PRIdFAST ? /* implementation defined */
#define PRIoFAST ? /* implementation defined */
#define PRIxFAST ? /* implementation defined */
#define PRIuFAST ? /* implementation defined */
#define SCNiFAST ? /* implementation defined */
#define SCNdFAST ? /* implementation defined */
#define SCNoFAST ? /* implementation defined */
#define SCNxFAST ? /* implementation defined */
#endif /* _not */
#endif /* _CPU_SUN_SPARC */
/*************** conversion functions ********************************
**
** The following routines convert from strings to the largest supported
** integer types. They parallel the strtol and strtoul functions in Standard
** C. Implementations are free to equate them to any existing functions
** they may have.
*/
extern intmax_t strtoimax (const char *, char**, int);
extern uintmax_t strtoumax (const char *, char**, int);
#endif /* ! _INTTYPES_H */
-- end inttypes.h
-- begin machine.h
/* machine.h: CPU and system architecture */
#ifndef _MACHINE_H
#define _MACHINE_H
/* Sun SPARC */
#if defined(__sparc) || defined(__sparc__) || defined(_sparc) || defined(_sparc_) || defined(sparc)
#define _CPU_SUN_SPARC 1
#endif
/* Motorola 68000 family */
#if defined(M68000) || defined(M68K) || defined(MC68000) || defined(_MCC68K)
#define _CPU_MOT_68000 1
#endif
/* Motorola MC68HC16 */
#if defined(MIRS_RADIO)
#define _CPU_MOT_HC16
#endif
#endif /* ! _MACHINE_H */
-- end machine.h
I imagine you'd want signed char, not plain char. Signedness of plain
char probably depends on compiler switches, etc., but signedness of
int8_t should not.
> /* signed integer type capable of holding a void * */
> typedef int * intptr_t;
That's not an integer type; it's a pointer type. int* (and hence,
your intptr_t) may very well be able to hold any void* on your
platform, but if your typedef is correct, your comment is not.
Likewise for uintptr_t.
> /* smallest signed integer of at least 8 bits */
> typedef short int_least8_t;
Isn't signed char both smaller than short, and at least 8 bits?
Similarly for unsigned...
> #define INT16_MIN (-32767-1)
Since this is contained within an #ifdef for your platform, and you
know that ints on your platform can hold 32768, why not use -32768, as
you used -128 for INT8_MIN?
> #ifdef _not
Earlier in this file, you unconditionally #undef'ed _not. Why is this
conditional here?
> #define INT_LEAST8_MIN ? /* implementation defined */
These are also contained in a suitable #ifdef for suns - so why not
define these macros for suns, especially since you already made the
typedefs?
Also, if you're not going to provide values, ? doesn't strike me as a
particularly useful macro definition.
paul
The <inttypes.h> spec was split into <stdint.h> and <inttypes.h>
in order to support freestanding implementations. You can find
a recent version of the spec at ftp://ftp.arl.mil/arch/n788.ps
(or ftp://ftp.arl.mil/arch/n788.txt); it served as input to the
latest C9x working draft (which is not available to the public
at this time), which incorporated it with a few editorial changes.
[very big snip]
Thanks, Jason. This is just what I'm looking for.
I do have one question in connection with 64-bit integers, though. The
compiler I'm using is an old 16-bit MS-DOS compiler and does not have any
64-bit integer type (not "long long", "_int64" or anything else).
Therefore, I know I'm not supposed to implement int64_t, uint64_t,
int_least64_t, uint_least64_t, int_fast64_t, or uint_fast64_t.
But what about intmax_t [and uintmax_t]? They are simply described as the
"A signed[unsigned] integral type having greatest precision." There always
is such a type on any given machine. Yet the "minimum maximum" values
INTMAX_MAX [UINTMAX_MAX] are clearly chosen with 64-bit integers in mind.
So I assume that I shouldn't implement these types, the maximum value macros
given above, INTMAX_C(value), INTMAX_C(value), the corresponding printf()
and scanf() macros, strtoimax(), and strtoumax().
Right?
Again, thanks.
- Michael
Jason may have done that, but the spec doesn't require the maximum size
of
any integer type to be 64 bits. You should just follow the
specifications.
In C9x, there will always be at least 64 bits in the maximum-sized
integer
type, as a result of a requirement elsewhere in the standard.
In an implementation conforming to C89, there are always at least 32
bits.
The main usage is expected to be: for an arbitrary integer type,
convert it to the maximum size, then (perhaps) print it with the
corresponding format. This indicates that it is important to always
have these "largest size" types defined in every implementation.
Wrong. C9X specifies the minimum maximums to be 64 bit because all
C9X implementations are required to have 64-bit types. That is, it
is the description that is most important, not the minimax values.
So, implement all of them following the descriptions and ignoring
the minimax values.
-Larry Jones
I keep forgetting that rules are only for little nice people. -- Calvin