This commit is contained in:
Kelvin Sherlock 2013-02-07 19:47:49 -05:00
parent 271bc85c37
commit 0d594d9e31
5 changed files with 1483 additions and 1 deletions

View File

@ -8,4 +8,5 @@ cmake_minimum_required(VERSION 2.6)
add_subdirectory(bin)
add_subdirectory(cpu)
add_subdirectory(toolbox)
add_subdirectory(toolbox)
add_subdirectory(mplite)

5
mplite/CMakeLists.txt Normal file
View File

@ -0,0 +1,5 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(MPLITE_SRC mplite.c)
add_library(MPLITE_LIB ${MPLITE_SRC})

455
mplite/mplite.c Normal file
View File

@ -0,0 +1,455 @@
#include "mplite.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
/*
** A minimum allocation is an instance of the following structure.
** Larger allocations are an array of these structures where the
** size of the array is a power of 2.
**
** The size of this object must be a power of two. That fact is
** verified in mplite_init().
*/
typedef struct mplite_link mplite_link_t;
struct mplite_link {
int next; /* Index of next free chunk */
int prev; /* Index of previous free chunk */
};
/*
** Masks used for mplite_t.aCtrl[] elements.
*/
#define MPLITE_CTRL_LOGSIZE 0x1f /* Log2 Size of this block */
#define MPLITE_CTRL_FREE 0x20 /* True if not checked out */
#ifdef _WIN32
#define snprintf(buf, buf_size, format, ...) \
_snprintf(buf, buf_size, format, ## __VA_ARGS__)
#endif /* #ifdef _WIN32 */
/*
** Assuming mplite_t.zPool is divided up into an array of mplite_link_t
** structures, return a pointer to the idx-th such lik.
*/
#define mplite_getlink(handle, idx) ((mplite_link_t *) \
(&handle->zPool[(idx) * handle->szAtom]))
#define mplite_enter(handle) if((handle != NULL) && \
((handle)->lock.acquire != NULL)) \
{ (handle)->lock.acquire((handle)->lock.arg); }
#define mplite_leave(handle) if((handle != NULL) && \
((handle)->lock.release != NULL)) \
{ (handle)->lock.release((handle)->lock.arg); }
static int mplite_logarithm(const int iValue);
static int mplite_size(const mplite_t *handle, const void *p);
static void mplite_link(mplite_t *handle, const int i, const int iLogsize);
static void mplite_unlink(mplite_t *handle, const int i, const int iLogsize);
static int mplite_unlink_first(mplite_t *handle, const int iLogsize);
static void *mplite_malloc_unsafe(mplite_t *handle, const int nByte);
static void mplite_free_unsafe(mplite_t *handle, const void *pOld);
MPLITE_API int mplite_init(mplite_t *handle, const void *buf,
const int buf_size, const int min_alloc,
const mplite_lock_t *lock)
{
int ii; /* Loop counter */
int nByte; /* Number of bytes of memory available to this allocator */
uint8_t *zByte; /* Memory usable by this allocator */
int nMinLog; /* Log base 2 of minimum allocation size in bytes */
int iOffset; /* An offset into handle->aCtrl[] */
/* Check the parameters */
if ((NULL == handle) || (NULL == buf) || (buf_size <= 0) ||
(min_alloc <= 0)) {
return MPLITE_ERR_INVPAR;
}
/* Initialize the mplite_t object */
memset(handle, 0, sizeof (*handle));
/* Copy the lock if it is not NULL */
if (lock != NULL) {
memcpy(&handle->lock, lock, sizeof (handle->lock));
}
/* The size of a mplite_link_t object must be a power of two. Verify that
** this is case.
*/
assert((sizeof (mplite_link_t)&(sizeof (mplite_link_t) - 1)) == 0);
nByte = buf_size;
zByte = (uint8_t*) buf;
nMinLog = mplite_logarithm(min_alloc);
handle->szAtom = (1 << nMinLog);
while ((int) sizeof (mplite_link_t) > handle->szAtom) {
handle->szAtom = handle->szAtom << 1;
}
handle->nBlock = (nByte / (handle->szAtom + sizeof (uint8_t)));
handle->zPool = zByte;
handle->aCtrl = (uint8_t *) & handle->zPool[handle->nBlock * handle->szAtom];
for (ii = 0; ii <= MPLITE_LOGMAX; ii++) {
handle->aiFreelist[ii] = -1;
}
iOffset = 0;
for (ii = MPLITE_LOGMAX; ii >= 0; ii--) {
int nAlloc = (1 << ii);
if ((iOffset + nAlloc) <= handle->nBlock) {
handle->aCtrl[iOffset] = (uint8_t) (ii | MPLITE_CTRL_FREE);
mplite_link(handle, iOffset, ii);
iOffset += nAlloc;
}
assert((iOffset + nAlloc) > handle->nBlock);
}
return MPLITE_OK;
}
MPLITE_API void *mplite_malloc(mplite_t *handle, const int nBytes)
{
int64_t *p = 0;
/* Check the parameters */
if ((NULL == handle) || (nBytes <= 0)) {
return NULL;
}
mplite_enter(handle);
p = mplite_malloc_unsafe(handle, nBytes);
mplite_leave(handle);
return (void*) p;
}
MPLITE_API void mplite_free(mplite_t *handle, const void *pPrior)
{
/* Check the parameters */
if ((NULL == handle) || (NULL == pPrior)) {
return;
}
mplite_enter(handle);
mplite_free_unsafe(handle, pPrior);
mplite_leave(handle);
}
MPLITE_API void *mplite_realloc(mplite_t *handle, const void *pPrior,
const int nBytes)
{
int nOld;
void *p;
/* Check the parameters */
if ((NULL == handle) || (NULL == pPrior) || (nBytes <= 0) ||
(nBytes & (nBytes - 1))) {
return NULL;
}
nOld = mplite_size(handle, pPrior);
if (nBytes <= nOld) {
return (void *) pPrior;
}
mplite_enter(handle);
p = mplite_malloc_unsafe(handle, nBytes);
if (p) {
memcpy(p, pPrior, nOld);
mplite_free_unsafe(handle, pPrior);
}
mplite_leave(handle);
return p;
}
MPLITE_API int mplite_roundup(mplite_t *handle, const int n)
{
int iFullSz;
/* Check the parameters */
if ((NULL == handle) || (n > MPLITE_MAX_ALLOC_SIZE)) {
return 0;
}
for (iFullSz = handle->szAtom; iFullSz < n; iFullSz *= 2);
return iFullSz;
}
MPLITE_API void mplite_print_stats(const mplite_t * const handle,
const mplite_putsfunc_t putsfunc)
{
if ((handle != NULL) && (putsfunc != NULL)) {
char zStats[256];
snprintf(zStats, sizeof (zStats), "Total number of calls to malloc: %u",
(unsigned) handle->nAlloc);
putsfunc(zStats);
snprintf(zStats, sizeof (zStats), "Total of all malloc calls - includes "
"internal fragmentation: %u", (unsigned) handle->totalAlloc);
putsfunc(zStats);
snprintf(zStats, sizeof (zStats), "Total internal fragmentation: %u",
(unsigned) handle->totalExcess);
putsfunc(zStats);
snprintf(zStats, sizeof (zStats), "Current checkout, including internal "
"fragmentation: %u", handle->currentOut);
putsfunc(zStats);
snprintf(zStats, sizeof (zStats), "Current number of distinct checkouts: %u",
handle->currentCount);
putsfunc(zStats);
snprintf(zStats, sizeof (zStats), "Maximum instantaneous currentOut: %u",
handle->maxOut);
putsfunc(zStats);
snprintf(zStats, sizeof (zStats), "Maximum instantaneous currentCount: %u",
handle->maxCount);
putsfunc(zStats);
snprintf(zStats, sizeof (zStats), "Largest allocation (exclusive of "
"internal frag): %u", handle->maxRequest);
putsfunc(zStats);
}
}
/*
** Return the ceiling of the logarithm base 2 of iValue.
**
** Examples: mplite_logarithm(1) -> 0
** mplite_logarithm(2) -> 1
** mplite_logarithm(4) -> 2
** mplite_logarithm(5) -> 3
** mplite_logarithm(8) -> 3
** mplite_logarithm(9) -> 4
*/
static int mplite_logarithm(const int iValue)
{
int iLog;
for (iLog = 0; (1 << iLog) < iValue; iLog++);
return iLog;
}
/*
** Return the size of an outstanding allocation, in bytes. The
** size returned omits the 8-byte header overhead. This only
** works for chunks that are currently checked out.
*/
static int mplite_size(const mplite_t *handle, const void *p)
{
int iSize = 0;
if (p) {
int i = ((uint8_t *) p - handle->zPool) / handle->szAtom;
assert(i >= 0 && i < handle->nBlock);
iSize = handle->szAtom *
(1 << (handle->aCtrl[i] & MPLITE_CTRL_LOGSIZE));
}
return iSize;
}
/*
** Link the chunk at handle->aPool[i] so that is on the iLogsize
** free list.
*/
static void mplite_link(mplite_t *handle, const int i, const int iLogsize)
{
int x;
assert(i >= 0 && i < handle->nBlock);
assert(iLogsize >= 0 && iLogsize <= MPLITE_LOGMAX);
assert((handle->aCtrl[i] & MPLITE_CTRL_LOGSIZE) == iLogsize);
x = mplite_getlink(handle, i)->next = handle->aiFreelist[iLogsize];
mplite_getlink(handle, i)->prev = -1;
if (x >= 0) {
assert(x < handle->nBlock);
mplite_getlink(handle, x)->prev = i;
}
handle->aiFreelist[iLogsize] = i;
}
/*
** Unlink the chunk at handle->aPool[i] from list it is currently
** on. It should be found on handle->aiFreelist[iLogsize].
*/
static void mplite_unlink(mplite_t *handle, const int i, const int iLogsize)
{
int next, prev;
assert(i >= 0 && i < handle->nBlock);
assert(iLogsize >= 0 && iLogsize <= MPLITE_LOGMAX);
assert((handle->aCtrl[i] & MPLITE_CTRL_LOGSIZE) == iLogsize);
next = mplite_getlink(handle, i)->next;
prev = mplite_getlink(handle, i)->prev;
if (prev < 0) {
handle->aiFreelist[iLogsize] = next;
}
else {
mplite_getlink(handle, prev)->next = next;
}
if (next >= 0) {
mplite_getlink(handle, next)->prev = prev;
}
}
/*
** Find the first entry on the freelist iLogsize. Unlink that
** entry and return its index.
*/
static int mplite_unlink_first(mplite_t *handle, const int iLogsize)
{
int i;
int iFirst;
assert(iLogsize >= 0 && iLogsize <= MPLITE_LOGMAX);
i = iFirst = handle->aiFreelist[iLogsize];
assert(iFirst >= 0);
while (i > 0) {
if (i < iFirst) iFirst = i;
i = mplite_getlink(handle, i)->next;
}
mplite_unlink(handle, iFirst, iLogsize);
return iFirst;
}
/*
** Return a block of memory of at least nBytes in size.
** Return NULL if unable. Return NULL if nBytes==0.
**
** The caller guarantees that nByte positive.
**
** The caller has obtained a lock prior to invoking this
** routine so there is never any chance that two or more
** threads can be in this routine at the same time.
*/
static void *mplite_malloc_unsafe(mplite_t *handle, const int nByte)
{
int i; /* Index of a handle->aPool[] slot */
int iBin; /* Index into handle->aiFreelist[] */
int iFullSz; /* Size of allocation rounded up to power of 2 */
int iLogsize; /* Log2 of iFullSz/POW2_MIN */
/* nByte must be a positive */
assert(nByte > 0);
/* Keep track of the maximum allocation request. Even unfulfilled
** requests are counted */
if ((uint32_t) nByte > handle->maxRequest) {
handle->maxRequest = nByte;
}
/* Abort if the requested allocation size is larger than the largest
** power of two that we can represent using 32-bit signed integers.
*/
if (nByte > MPLITE_MAX_ALLOC_SIZE) {
return NULL;
}
/* Round nByte up to the next valid power of two */
for (iFullSz = handle->szAtom, iLogsize = 0; iFullSz < nByte; iFullSz *= 2,
iLogsize++) {
}
/* Make sure handle->aiFreelist[iLogsize] contains at least one free
** block. If not, then split a block of the next larger power of
** two in order to create a new free block of size iLogsize.
*/
for (iBin = iLogsize; handle->aiFreelist[iBin] < 0 && iBin <= MPLITE_LOGMAX;
iBin++) {
}
if (iBin > MPLITE_LOGMAX) {
return NULL;
}
i = mplite_unlink_first(handle, iBin);
while (iBin > iLogsize) {
int newSize;
iBin--;
newSize = 1 << iBin;
handle->aCtrl[i + newSize] = (uint8_t) (MPLITE_CTRL_FREE | iBin);
mplite_link(handle, i + newSize, iBin);
}
handle->aCtrl[i] = (uint8_t) iLogsize;
/* Update allocator performance statistics. */
handle->nAlloc++;
handle->totalAlloc += iFullSz;
handle->totalExcess += iFullSz - nByte;
handle->currentCount++;
handle->currentOut += iFullSz;
if (handle->maxCount < handle->currentCount) {
handle->maxCount = handle->currentCount;
}
if (handle->maxOut < handle->currentOut) {
handle->maxOut = handle->currentOut;
}
/* Return a pointer to the allocated memory. */
return (void*) &handle->zPool[i * handle->szAtom];
}
/*
** Free an outstanding memory allocation.
*/
static void mplite_free_unsafe(mplite_t *handle, const void *pOld)
{
uint32_t size, iLogsize;
int iBlock;
/* Set iBlock to the index of the block pointed to by pOld in
** the array of handle->szAtom byte blocks pointed to by handle->zPool.
*/
iBlock = ((uint8_t *) pOld - handle->zPool) / handle->szAtom;
/* Check that the pointer pOld points to a valid, non-free block. */
assert(iBlock >= 0 && iBlock < handle->nBlock);
assert(((uint8_t *) pOld - handle->zPool) % handle->szAtom == 0);
assert((handle->aCtrl[iBlock] & MPLITE_CTRL_FREE) == 0);
iLogsize = handle->aCtrl[iBlock] & MPLITE_CTRL_LOGSIZE;
size = 1 << iLogsize;
assert(iBlock + size - 1 < (uint32_t) handle->nBlock);
handle->aCtrl[iBlock] |= MPLITE_CTRL_FREE;
handle->aCtrl[iBlock + size - 1] |= MPLITE_CTRL_FREE;
assert(handle->currentCount > 0);
assert(handle->currentOut >= (size * handle->szAtom));
handle->currentCount--;
handle->currentOut -= size * handle->szAtom;
assert(handle->currentOut > 0 || handle->currentCount == 0);
assert(handle->currentCount > 0 || handle->currentOut == 0);
handle->aCtrl[iBlock] = (uint8_t) (MPLITE_CTRL_FREE | iLogsize);
while (iLogsize < MPLITE_LOGMAX) {
int iBuddy;
if ((iBlock >> iLogsize) & 1) {
iBuddy = iBlock - size;
}
else {
iBuddy = iBlock + size;
}
assert(iBuddy >= 0);
if ((iBuddy + (1 << iLogsize)) > handle->nBlock) break;
if (handle->aCtrl[iBuddy] != (MPLITE_CTRL_FREE | iLogsize)) break;
mplite_unlink(handle, iBuddy, iLogsize);
iLogsize++;
if (iBuddy < iBlock) {
handle->aCtrl[iBuddy] = (uint8_t) (MPLITE_CTRL_FREE | iLogsize);
handle->aCtrl[iBlock] = 0;
iBlock = iBuddy;
}
else {
handle->aCtrl[iBlock] = (uint8_t) (MPLITE_CTRL_FREE | iLogsize);
handle->aCtrl[iBuddy] = 0;
}
size *= 2;
}
mplite_link(handle, iBlock, iLogsize);
}

222
mplite/mplite.h Normal file
View File

@ -0,0 +1,222 @@
/**
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*
* This file contains the APIs that implement a memory allocation subsystem
* based on SQLite's memsys5 memory subsystem. Refer to
* http://www.sqlite.org/malloc.html for more info.
*
* This version of the memory allocation subsystem omits all
* use of malloc(). The application gives a block of memory
* from which allocations are made and returned by the mplite_malloc()
* and mplite_realloc() implementations.
*
* This memory allocator uses the following algorithm:
*
* 1. All memory allocations sizes are rounded up to a power of 2.
*
* 2. If two adjacent free blocks are the halves of a larger block,
* then the two blocks are coalesed into the single larger block.
*
* 3. New memory is allocated from the first available free block.
*
* This algorithm is described in: J. M. Robson. "Bounds for Some Functions
* Concerning Dynamic Storage Allocation". Journal of the Association for
* Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499.
*
* Let n be the size of the largest allocation divided by the minimum
* allocation size (after rounding all sizes up to a power of 2.) Let M
* be the maximum amount of memory ever outstanding at one time. Let
* N be the total amount of memory available for allocation. Robson
* proved that this memory allocator will never breakdown due to
* fragmentation as long as the following constraint holds:
*
* N >= M*(1 + log2(n)/2) - n + 1
*/
#ifndef MPLITE_H
#define MPLITE_H
#ifdef _WIN32
#include "pstdint.h"
#else
#include <stdint.h>
#endif /* #ifdef _WIN32 */
/**
* @brief The function call returns success
*/
#define MPLITE_OK 0
/**
* @brief Invalid parameters are passed to a function
*/
#define MPLITE_ERR_INVPAR -1
/**
* @brief Macro to fix unused parameter compiler warning
*/
#define MPLITE_UNUSED_PARAM(param) (void)(param)
/**
* @brief Maximum size of any allocation is ((1 << @ref MPLITE_LOGMAX) *
* mplite_t.szAtom). Since mplite_t.szAtom is always at least 8 and
* 32-bit integers are used, it is not actually possible to reach this
* limit.
*/
#define MPLITE_LOGMAX 30
/**
* @brief Maximum allocation size of this memory pool library. All allocations
* must be a power of two and must be expressed by a 32-bit signed
* integer. Hence the largest allocation is 0x40000000 or 1073741824.
*/
#define MPLITE_MAX_ALLOC_SIZE 0x40000000
/**
* @brief An indicator that a function is a public API
*/
#define MPLITE_API
/**
* @brief Lock object to be used in a threadsafe memory pool
*/
typedef struct mplite_lock {
void *arg; /**< Argument to be passed to acquire and release function
pointers */
int (*acquire)(void *arg); /**< Function pointer to acquire a lock */
int (*release)(void *arg); /**< Function pointer to release a lock */
} mplite_lock_t;
/**
* @brief Memory pool object
*/
typedef struct mplite {
/*-------------------------------
Memory available for allocation
-------------------------------*/
int szAtom; /**< Smallest possible allocation in bytes */
int nBlock; /**< Number of szAtom sized blocks in zPool */
uint8_t *zPool; /**< Memory available to be allocated */
mplite_lock_t lock; /**< Lock to control access to the memory allocation
subsystem. */
/*----------------------
Performance statistics
----------------------*/
uint64_t nAlloc; /**< Total number of calls to malloc */
uint64_t totalAlloc; /**< Total of all malloc calls - includes internal
fragmentation */
uint64_t totalExcess; /**< Total internal fragmentation */
uint32_t currentOut; /**< Current checkout, including internal
fragmentation */
uint32_t currentCount; /**< Current number of distinct checkouts */
uint32_t maxOut; /**< Maximum instantaneous currentOut */
uint32_t maxCount; /**< Maximum instantaneous currentCount */
uint32_t maxRequest; /**< Largest allocation (exclusive of internal frag) */
int aiFreelist[MPLITE_LOGMAX + 1]; /**< List of free blocks. aiFreelist[0]
is a list of free blocks of size mplite_t.szAtom. aiFreelist[1] holds
blocks of size szAtom * 2 and so forth.*/
uint8_t *aCtrl; /**< Space for tracking which blocks are checked out and the
size of each block. One byte per block. */
} mplite_t;
/**
* @brief Print string function pointer to be passed to @ref mplite_print_stats
* function. This must be same as stdio's puts function mechanism which
* automatically appends a new line character in every call.
*/
typedef int (*mplite_putsfunc_t)(const char* stats);
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize the memory pool object.
* @param[in,out] handle Pointer to a @ref mplite_t object which is allocated
* by the caller either from stack, heap, or application's
* memory space.
* @param[in] buf Pointer to a large, contiguous chunk of memory space that
* @ref mplite_t will use to satisfy all of its memory
* allocation needs. This might point to a static array or it
* might be memory obtained from some other application-specific
* mechanism.
* @param[in] buf_size The number of bytes of memory space pointed to by @ref
* buf
* @param[in] min_alloc Minimum size of an allocation. Any call to @ref
* mplite_malloc where nBytes is less than min_alloc will
* be rounded up to min_alloc. min_alloc must be a power of
* two.
* @param[in] lock Pointer to a lock object to control access to the memory
* allocation subsystem of @ref mplite_t object. If this is
* @ref NULL, @ref mplite_t will be non-threadsafe and can only
* be safely used by a single thread. It is safe to allocate
* this in stack because it will be copied to @ref mplite_t
* object.
* @return @ref MPLITE_OK on success and @ref MPLITE_ERR_INVPAR on invalid
* parameters error.
*/
MPLITE_API int mplite_init(mplite_t *handle, const void *buf,
const int buf_size, const int min_alloc,
const mplite_lock_t *lock);
/**
* @brief Allocate bytes of memory
* @param[in,out] handle Pointer to an initialized @ref mplite_t object
* @param[in] nBytes Number of bytes to allocate
* @return Non-NULL on success, NULL otherwise
*/
MPLITE_API void *mplite_malloc(mplite_t *handle, const int nBytes);
/**
* @brief Free memory
* @param[in,out] handle Pointer to an initialized @ref mplite_t object
* @param[in] pPrior Allocated buffer
*/
MPLITE_API void mplite_free(mplite_t *handle, const void *pPrior);
/**
* @brief Change the size of an existing memory allocation.
* @param[in,out] handle Pointer to an initialized @ref mplite_t object
* @param[in] pPrior Existing allocated memory
* @param[in] nBytes Size of the new memory allocation. This is always a value
* obtained from a prior call to mplite_roundup(). Hence,
* this is always a non-negative power of two. If nBytes == 0
* that means that an oversize allocation (an allocation
* larger than @ref MPLITE_MAX_ALLOC_SIZE) was requested and
* this routine should return NULL without freeing pPrior.
* @return Non-NULL on success, NULL otherwise
*/
MPLITE_API void *mplite_realloc(mplite_t *handle, const void *pPrior,
const int nBytes);
/**
* @brief Round up a request size to the next valid allocation size.
* @param[in,out] handle Pointer to an initialized @ref mplite_t object
* @param[in] n Request size
* @return Positive non-zero value if the size can be allocated or zero if the
* allocation is too large to be handled.
*/
MPLITE_API int mplite_roundup(mplite_t *handle, const int n);
/**
* @brief Print the statistics of the memory pool object
* @param[in,out] handle Pointer to an initialized @ref mplite_t object
* @param[in] logfunc Non-NULL log function of the caller. Refer to
* @ref mplite_logfunc_t for the prototype of this function.
*/
MPLITE_API void mplite_print_stats(const mplite_t * const handle,
const mplite_putsfunc_t logfunc);
/**
* @brief Macro to return the number of times mplite_malloc() has been called.
*/
#define mplite_alloc_count(handle) (((handle) != NULL)? (handle)->nAlloc : 0)
#ifdef __cplusplus
}
#endif
#endif /* #ifndef MPLITE_H */

799
mplite/pstdint.h Normal file
View File

@ -0,0 +1,799 @@
/* A portable stdint.h
****************************************************************************
* BSD License:
****************************************************************************
*
* Copyright (c) 2005-2007 Paul Hsieh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************
*
* Version 0.1.11
*
* The ANSI C standard committee, for the C99 standard, specified the
* inclusion of a new standard include file called stdint.h. This is
* a very useful and long desired include file which contains several
* very precise definitions for integer scalar types that is
* critically important for making portable several classes of
* applications including cryptography, hashing, variable length
* integer libraries and so on. But for most developers its likely
* useful just for programming sanity.
*
* The problem is that most compiler vendors have decided not to
* implement the C99 standard, and the next C++ language standard
* (which has a lot more mindshare these days) will be a long time in
* coming and its unknown whether or not it will include stdint.h or
* how much adoption it will have. Either way, it will be a long time
* before all compilers come with a stdint.h and it also does nothing
* for the extremely large number of compilers available today which
* do not include this file, or anything comparable to it.
*
* So that's what this file is all about. Its an attempt to build a
* single universal include file that works on as many platforms as
* possible to deliver what stdint.h is supposed to. A few things
* that should be noted about this file:
*
* 1) It is not guaranteed to be portable and/or present an identical
* interface on all platforms. The extreme variability of the
* ANSI C standard makes this an impossibility right from the
* very get go. Its really only meant to be useful for the vast
* majority of platforms that possess the capability of
* implementing usefully and precisely defined, standard sized
* integer scalars. Systems which are not intrinsically 2s
* complement may produce invalid constants.
*
* 2) There is an unavoidable use of non-reserved symbols.
*
* 3) Other standard include files are invoked.
*
* 4) This file may come in conflict with future platforms that do
* include stdint.h. The hope is that one or the other can be
* used with no real difference.
*
* 5) In the current verison, if your platform can't represent
* int32_t, int16_t and int8_t, it just dumps out with a compiler
* error.
*
* 6) 64 bit integers may or may not be defined. Test for their
* presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX.
* Note that this is different from the C99 specification which
* requires the existence of 64 bit support in the compiler. If
* this is not defined for your platform, yet it is capable of
* dealing with 64 bits then it is because this file has not yet
* been extended to cover all of your system's capabilities.
*
* 7) (u)intptr_t may or may not be defined. Test for its presence
* with the test: #ifdef PTRDIFF_MAX. If this is not defined
* for your platform, then it is because this file has not yet
* been extended to cover all of your system's capabilities, not
* because its optional.
*
* 8) The following might not been defined even if your platform is
* capable of defining it:
*
* WCHAR_MIN
* WCHAR_MAX
* (u)int64_t
* PTRDIFF_MIN
* PTRDIFF_MAX
* (u)intptr_t
*
* 9) The following have not been defined:
*
* WINT_MIN
* WINT_MAX
*
* 10) The criteria for defining (u)int_least(*)_t isn't clear,
* except for systems which don't have a type that precisely
* defined 8, 16, or 32 bit types (which this include file does
* not support anyways). Default definitions have been given.
*
* 11) The criteria for defining (u)int_fast(*)_t isn't something I
* would trust to any particular compiler vendor or the ANSI C
* committee. It is well known that "compatible systems" are
* commonly created that have very different performance
* characteristics from the systems they are compatible with,
* especially those whose vendors make both the compiler and the
* system. Default definitions have been given, but its strongly
* recommended that users never use these definitions for any
* reason (they do *NOT* deliver any serious guarantee of
* improved performance -- not in this file, nor any vendor's
* stdint.h).
*
* 12) The following macros:
*
* PRINTF_INTMAX_MODIFIER
* PRINTF_INT64_MODIFIER
* PRINTF_INT32_MODIFIER
* PRINTF_INT16_MODIFIER
* PRINTF_LEAST64_MODIFIER
* PRINTF_LEAST32_MODIFIER
* PRINTF_LEAST16_MODIFIER
* PRINTF_INTPTR_MODIFIER
*
* are strings which have been defined as the modifiers required
* for the "d", "u" and "x" printf formats to correctly output
* (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t,
* (u)least32_t, (u)least16_t and (u)intptr_t types respectively.
* PRINTF_INTPTR_MODIFIER is not defined for some systems which
* provide their own stdint.h. PRINTF_INT64_MODIFIER is not
* defined if INT64_MAX is not defined. These are an extension
* beyond what C99 specifies must be in stdint.h.
*
* In addition, the following macros are defined:
*
* PRINTF_INTMAX_HEX_WIDTH
* PRINTF_INT64_HEX_WIDTH
* PRINTF_INT32_HEX_WIDTH
* PRINTF_INT16_HEX_WIDTH
* PRINTF_INT8_HEX_WIDTH
* PRINTF_INTMAX_DEC_WIDTH
* PRINTF_INT64_DEC_WIDTH
* PRINTF_INT32_DEC_WIDTH
* PRINTF_INT16_DEC_WIDTH
* PRINTF_INT8_DEC_WIDTH
*
* Which specifies the maximum number of characters required to
* print the number of that type in either hexadecimal or decimal.
* These are an extension beyond what C99 specifies must be in
* stdint.h.
*
* Compilers tested (all with 0 warnings at their highest respective
* settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32
* bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio
* .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3
*
* This file should be considered a work in progress. Suggestions for
* improvements, especially those which increase coverage are strongly
* encouraged.
*
* Acknowledgements
*
* The following people have made significant contributions to the
* development and testing of this file:
*
* Chris Howie
* John Steele Scott
* Dave Thorup
*
*/
#include <stddef.h>
#include <limits.h>
#include <signal.h>
/*
* For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and
* do nothing else. On the Mac OS X version of gcc this is _STDINT_H_.
*/
#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) )) && !defined (_PSTDINT_H_INCLUDED)
#include <stdint.h>
#define _PSTDINT_H_INCLUDED
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "ll"
# endif
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER "l"
# endif
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER "h"
# endif
# ifndef PRINTF_INTMAX_MODIFIER
# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
# endif
# ifndef PRINTF_INT64_HEX_WIDTH
# define PRINTF_INT64_HEX_WIDTH "16"
# endif
# ifndef PRINTF_INT32_HEX_WIDTH
# define PRINTF_INT32_HEX_WIDTH "8"
# endif
# ifndef PRINTF_INT16_HEX_WIDTH
# define PRINTF_INT16_HEX_WIDTH "4"
# endif
# ifndef PRINTF_INT8_HEX_WIDTH
# define PRINTF_INT8_HEX_WIDTH "2"
# endif
# ifndef PRINTF_INT64_DEC_WIDTH
# define PRINTF_INT64_DEC_WIDTH "20"
# endif
# ifndef PRINTF_INT32_DEC_WIDTH
# define PRINTF_INT32_DEC_WIDTH "10"
# endif
# ifndef PRINTF_INT16_DEC_WIDTH
# define PRINTF_INT16_DEC_WIDTH "5"
# endif
# ifndef PRINTF_INT8_DEC_WIDTH
# define PRINTF_INT8_DEC_WIDTH "3"
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
# endif
/*
* Something really weird is going on with Open Watcom. Just pull some of
* these duplicated definitions from Open Watcom's stdint.h file for now.
*/
# if defined (__WATCOMC__) && __WATCOMC__ >= 1250
# if !defined (INT64_C)
# define INT64_C(x) (x + (INT64_MAX - INT64_MAX))
# endif
# if !defined (UINT64_C)
# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
# endif
# if !defined (INT32_C)
# define INT32_C(x) (x + (INT32_MAX - INT32_MAX))
# endif
# if !defined (UINT32_C)
# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX))
# endif
# if !defined (INT16_C)
# define INT16_C(x) (x)
# endif
# if !defined (UINT16_C)
# define UINT16_C(x) (x)
# endif
# if !defined (INT8_C)
# define INT8_C(x) (x)
# endif
# if !defined (UINT8_C)
# define UINT8_C(x) (x)
# endif
# if !defined (UINT64_MAX)
# define UINT64_MAX 18446744073709551615ULL
# endif
# if !defined (INT64_MAX)
# define INT64_MAX 9223372036854775807LL
# endif
# if !defined (UINT32_MAX)
# define UINT32_MAX 4294967295UL
# endif
# if !defined (INT32_MAX)
# define INT32_MAX 2147483647L
# endif
# if !defined (INTMAX_MAX)
# define INTMAX_MAX INT64_MAX
# endif
# if !defined (INTMAX_MIN)
# define INTMAX_MIN INT64_MIN
# endif
# endif
#endif
#ifndef _PSTDINT_H_INCLUDED
#define _PSTDINT_H_INCLUDED
#ifndef SIZE_MAX
# define SIZE_MAX (~(size_t)0)
#endif
/*
* Deduce the type assignments from limits.h under the assumption that
* integer sizes in bits are powers of 2, and follow the ANSI
* definitions.
*/
#ifndef UINT8_MAX
# define UINT8_MAX 0xff
#endif
#ifndef uint8_t
# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
typedef unsigned char uint8_t;
# define UINT8_C(v) ((uint8_t) v)
# else
# error "Platform not supported"
# endif
#endif
#ifndef INT8_MAX
# define INT8_MAX 0x7f
#endif
#ifndef INT8_MIN
# define INT8_MIN INT8_C(0x80)
#endif
#ifndef int8_t
# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
typedef signed char int8_t;
# define INT8_C(v) ((int8_t) v)
# else
# error "Platform not supported"
# endif
#endif
#ifndef UINT16_MAX
# define UINT16_MAX 0xffff
#endif
#ifndef uint16_t
#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
typedef unsigned int uint16_t;
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER ""
# endif
# define UINT16_C(v) ((uint16_t) (v))
#elif (USHRT_MAX == UINT16_MAX)
typedef unsigned short uint16_t;
# define UINT16_C(v) ((uint16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER "h"
# endif
#else
#error "Platform not supported"
#endif
#endif
#ifndef INT16_MAX
# define INT16_MAX 0x7fff
#endif
#ifndef INT16_MIN
# define INT16_MIN INT16_C(0x8000)
#endif
#ifndef int16_t
#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
typedef signed int int16_t;
# define INT16_C(v) ((int16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER ""
# endif
#elif (SHRT_MAX == INT16_MAX)
typedef signed short int16_t;
# define INT16_C(v) ((int16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER "h"
# endif
#else
#error "Platform not supported"
#endif
#endif
#ifndef UINT32_MAX
# define UINT32_MAX (0xffffffffUL)
#endif
#ifndef uint32_t
#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
typedef unsigned long uint32_t;
# define UINT32_C(v) v ## UL
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER "l"
# endif
#elif (UINT_MAX == UINT32_MAX)
typedef unsigned int uint32_t;
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER ""
# endif
# define UINT32_C(v) v ## U
#elif (USHRT_MAX == UINT32_MAX)
typedef unsigned short uint32_t;
# define UINT32_C(v) ((unsigned short) (v))
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER ""
# endif
#else
#error "Platform not supported"
#endif
#endif
#ifndef INT32_MAX
# define INT32_MAX (0x7fffffffL)
#endif
#ifndef INT32_MIN
# define INT32_MIN INT32_C(0x80000000)
#endif
#ifndef int32_t
#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
typedef signed long int32_t;
# define INT32_C(v) v ## L
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER "l"
# endif
#elif (INT_MAX == INT32_MAX)
typedef signed int int32_t;
# define INT32_C(v) v
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER ""
# endif
#elif (SHRT_MAX == INT32_MAX)
typedef signed short int32_t;
# define INT32_C(v) ((short) (v))
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER ""
# endif
#else
#error "Platform not supported"
#endif
#endif
/*
* The macro stdint_int64_defined is temporarily used to record
* whether or not 64 integer support is available. It must be
* defined for any 64 integer extensions for new platforms that are
* added.
*/
#undef stdint_int64_defined
#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
# if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S)
# define stdint_int64_defined
typedef long long int64_t;
typedef unsigned long long uint64_t;
# define UINT64_C(v) v ## ULL
# define INT64_C(v) v ## LL
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "ll"
# endif
# endif
#endif
#if !defined (stdint_int64_defined)
# if defined(__GNUC__)
# define stdint_int64_defined
__extension__ typedef long long int64_t;
__extension__ typedef unsigned long long uint64_t;
# define UINT64_C(v) v ## ULL
# define INT64_C(v) v ## LL
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "ll"
# endif
# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S)
# define stdint_int64_defined
typedef long long int64_t;
typedef unsigned long long uint64_t;
# define UINT64_C(v) v ## ULL
# define INT64_C(v) v ## LL
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "ll"
# endif
# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC)
# define stdint_int64_defined
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
# define UINT64_C(v) v ## UI64
# define INT64_C(v) v ## I64
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "I64"
# endif
# endif
#endif
#if !defined (LONG_LONG_MAX) && defined (INT64_C)
# define LONG_LONG_MAX INT64_C (9223372036854775807)
#endif
#ifndef ULONG_LONG_MAX
# define ULONG_LONG_MAX UINT64_C (18446744073709551615)
#endif
#if !defined (INT64_MAX) && defined (INT64_C)
# define INT64_MAX INT64_C (9223372036854775807)
#endif
#if !defined (INT64_MIN) && defined (INT64_C)
# define INT64_MIN INT64_C (-9223372036854775808)
#endif
#if !defined (UINT64_MAX) && defined (INT64_C)
# define UINT64_MAX UINT64_C (18446744073709551615)
#endif
/*
* Width of hexadecimal for number field.
*/
#ifndef PRINTF_INT64_HEX_WIDTH
# define PRINTF_INT64_HEX_WIDTH "16"
#endif
#ifndef PRINTF_INT32_HEX_WIDTH
# define PRINTF_INT32_HEX_WIDTH "8"
#endif
#ifndef PRINTF_INT16_HEX_WIDTH
# define PRINTF_INT16_HEX_WIDTH "4"
#endif
#ifndef PRINTF_INT8_HEX_WIDTH
# define PRINTF_INT8_HEX_WIDTH "2"
#endif
#ifndef PRINTF_INT64_DEC_WIDTH
# define PRINTF_INT64_DEC_WIDTH "20"
#endif
#ifndef PRINTF_INT32_DEC_WIDTH
# define PRINTF_INT32_DEC_WIDTH "10"
#endif
#ifndef PRINTF_INT16_DEC_WIDTH
# define PRINTF_INT16_DEC_WIDTH "5"
#endif
#ifndef PRINTF_INT8_DEC_WIDTH
# define PRINTF_INT8_DEC_WIDTH "3"
#endif
/*
* Ok, lets not worry about 128 bit integers for now. Moore's law says
* we don't need to worry about that until about 2040 at which point
* we'll have bigger things to worry about.
*/
#ifdef stdint_int64_defined
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
# define INTMAX_MAX INT64_MAX
# define INTMAX_MIN INT64_MIN
# define UINTMAX_MAX UINT64_MAX
# define UINTMAX_C(v) UINT64_C(v)
# define INTMAX_C(v) INT64_C(v)
# ifndef PRINTF_INTMAX_MODIFIER
# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
# endif
#else
typedef int32_t intmax_t;
typedef uint32_t uintmax_t;
# define INTMAX_MAX INT32_MAX
# define UINTMAX_MAX UINT32_MAX
# define UINTMAX_C(v) UINT32_C(v)
# define INTMAX_C(v) INT32_C(v)
# ifndef PRINTF_INTMAX_MODIFIER
# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH
# endif
#endif
/*
* Because this file currently only supports platforms which have
* precise powers of 2 as bit sizes for the default integers, the
* least definitions are all trivial. Its possible that a future
* version of this file could have different definitions.
*/
#ifndef stdint_least_defined
typedef int8_t int_least8_t;
typedef uint8_t uint_least8_t;
typedef int16_t int_least16_t;
typedef uint16_t uint_least16_t;
typedef int32_t int_least32_t;
typedef uint32_t uint_least32_t;
# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER
# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER
# define UINT_LEAST8_MAX UINT8_MAX
# define INT_LEAST8_MAX INT8_MAX
# define UINT_LEAST16_MAX UINT16_MAX
# define INT_LEAST16_MAX INT16_MAX
# define UINT_LEAST32_MAX UINT32_MAX
# define INT_LEAST32_MAX INT32_MAX
# define INT_LEAST8_MIN INT8_MIN
# define INT_LEAST16_MIN INT16_MIN
# define INT_LEAST32_MIN INT32_MIN
# ifdef stdint_int64_defined
typedef int64_t int_least64_t;
typedef uint64_t uint_least64_t;
# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER
# define UINT_LEAST64_MAX UINT64_MAX
# define INT_LEAST64_MAX INT64_MAX
# define INT_LEAST64_MIN INT64_MIN
# endif
#endif
#undef stdint_least_defined
/*
* The ANSI C committee pretending to know or specify anything about
* performance is the epitome of misguided arrogance. The mandate of
* this file is to *ONLY* ever support that absolute minimum
* definition of the fast integer types, for compatibility purposes.
* No extensions, and no attempt to suggest what may or may not be a
* faster integer type will ever be made in this file. Developers are
* warned to stay away from these types when using this or any other
* stdint.h.
*/
typedef int_least8_t int_fast8_t;
typedef uint_least8_t uint_fast8_t;
typedef int_least16_t int_fast16_t;
typedef uint_least16_t uint_fast16_t;
typedef int_least32_t int_fast32_t;
typedef uint_least32_t uint_fast32_t;
#define UINT_FAST8_MAX UINT_LEAST8_MAX
#define INT_FAST8_MAX INT_LEAST8_MAX
#define UINT_FAST16_MAX UINT_LEAST16_MAX
#define INT_FAST16_MAX INT_LEAST16_MAX
#define UINT_FAST32_MAX UINT_LEAST32_MAX
#define INT_FAST32_MAX INT_LEAST32_MAX
#define INT_FAST8_MIN INT_LEAST8_MIN
#define INT_FAST16_MIN INT_LEAST16_MIN
#define INT_FAST32_MIN INT_LEAST32_MIN
#ifdef stdint_int64_defined
typedef int_least64_t int_fast64_t;
typedef uint_least64_t uint_fast64_t;
# define UINT_FAST64_MAX UINT_LEAST64_MAX
# define INT_FAST64_MAX INT_LEAST64_MAX
# define INT_FAST64_MIN INT_LEAST64_MIN
#endif
#undef stdint_int64_defined
/*
* Whatever piecemeal, per compiler thing we can do about the wchar_t
* type limits.
*/
#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__)
# include <wchar.h>
# ifndef WCHAR_MIN
# define WCHAR_MIN 0
# endif
# ifndef WCHAR_MAX
# define WCHAR_MAX ((wchar_t)-1)
# endif
#endif
/*
* Whatever piecemeal, per compiler/platform thing we can do about the
* (u)intptr_t types and limits.
*/
#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)
# define STDINT_H_UINTPTR_T_DEFINED
#endif
#ifndef STDINT_H_UINTPTR_T_DEFINED
# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64)
# define stdint_intptr_bits 64
# elif defined (__WATCOMC__) || defined (__TURBOC__)
# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
# define stdint_intptr_bits 16
# else
# define stdint_intptr_bits 32
# endif
# elif defined (__i386__) || defined (_WIN32) || defined (WIN32)
# define stdint_intptr_bits 32
# elif defined (__INTEL_COMPILER)
/* TODO -- what will Intel do about x86-64? */
# endif
# ifdef stdint_intptr_bits
# define stdint_intptr_glue3_i(a,b,c) a##b##c
# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c)
# ifndef PRINTF_INTPTR_MODIFIER
# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER)
# endif
# ifndef PTRDIFF_MAX
# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
# endif
# ifndef PTRDIFF_MIN
# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
# endif
# ifndef UINTPTR_MAX
# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX)
# endif
# ifndef INTPTR_MAX
# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
# endif
# ifndef INTPTR_MIN
# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
# endif
# ifndef INTPTR_C
# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x)
# endif
# ifndef UINTPTR_C
# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x)
# endif
typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t;
typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t;
# else
/* TODO -- This following is likely wrong for some platforms, and does
nothing for the definition of uintptr_t. */
typedef ptrdiff_t intptr_t;
# endif
# define STDINT_H_UINTPTR_T_DEFINED
#endif
/*
* Assumes sig_atomic_t is signed and we have a 2s complement machine.
*/
#ifndef SIG_ATOMIC_MAX
# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1)
#endif
#endif
#if defined (__TEST_PSTDINT_FOR_CORRECTNESS)
/*
* Please compile with the maximum warning settings to make sure macros are not
* defined more than once.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define glue3_aux(x,y,z) x ## y ## z
#define glue3(x,y,z) glue3_aux(x,y,z)
#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0);
#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0);
#define DECL(us,bits) glue3(DECL,us,) (bits)
#define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits)
int main () {
DECL(I,8)
DECL(U,8)
DECL(I,16)
DECL(U,16)
DECL(I,32)
DECL(U,32)
#ifdef INT64_MAX
DECL(I,64)
DECL(U,64)
#endif
intmax_t imax = INTMAX_C(0);
uintmax_t umax = UINTMAX_C(0);
char str0[256], str1[256];
sprintf (str0, "%d %x\n", 0, ~0);
sprintf (str1, "%d %x\n", i8, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1);
sprintf (str1, "%u %x\n", u8, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1);
sprintf (str1, "%d %x\n", i16, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1);
sprintf (str1, "%u %x\n", u16, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1);
sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1);
sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1);
#ifdef INT64_MAX
sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1);
#endif
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1);
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1);
TESTUMAX(8);
TESTUMAX(16);
TESTUMAX(32);
#ifdef INT64_MAX
TESTUMAX(64);
#endif
return EXIT_SUCCESS;
}
#endif