/*
 * Copyright (c) 2004, 2005 by
 * Ralf Corsepius, Ulm/Germany. All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * is freely granted, provided that this notice is preserved.
 */

/**
 *  @file  inttypes.h
 */

#ifndef _INTTYPES_H
#define _INTTYPES_H

#include <sys/cdefs.h>
#include <stdint.h>
#include <sys/_intsup.h>

_BEGIN_STD_C

#if __BSD_VISIBLE
#include <sys/_locale.h>
#endif

typedef struct {
    intmax_t quot;
    intmax_t rem;
} imaxdiv_t;

/*
 * Try to avoid defining wchar_t by using __WCHAR_TYPE__ when
 * available.
 */

#ifdef __WCHAR_TYPE__
typedef __WCHAR_TYPE__ _wchar_t;
#else
#define __need_wchar_t
#include <stddef.h>
typdef wchar_t _wchar_t;
#endif

#define __STRINGIFY(a) #a

/* 8-bit types */
#define __PRI8(x)      __INT8 __STRINGIFY(x)
#define __PRI8LEAST(x) __LEAST8 __STRINGIFY(x)
#define __PRI8FAST(x)  __FAST8 __STRINGIFY(x)

/* NOTICE: scanning 8-bit types requires use of the hh specifier
 * which is only supported on picolibc platforms that
 * are built with C99 I/O format support enabled.  If the flag in
 * picolibc.h hasn't been set during configuration to indicate this, the 8-bit
 * scanning format macros are disabled here as they result in undefined
 * behaviour which can include memory overwrite.  Overriding the flag after the
 * library has been built is not recommended as it will expose the underlying
 * undefined behaviour.
 */

#if defined(__IO_C99_FORMATS)
#define __SCN8(x)      __INT8 __STRINGIFY(x)
#define __SCN8LEAST(x) __LEAST8 __STRINGIFY(x)
#define __SCN8FAST(x)  __FAST8 __STRINGIFY(x)
#endif /* __IO_C99_FORMATS */

#define PRId8 __PRI8(d)
#define PRIi8 __PRI8(i)
#define PRIo8 __PRI8(o)
#define PRIu8 __PRI8(u)
#define PRIx8 __PRI8(x)
#define PRIX8 __PRI8(X)

/* Macros below are only enabled for a newlib built with C99 I/O format support. */
#if defined(__IO_C99_FORMATS)

#define SCNd8 __SCN8(d)
#define SCNi8 __SCN8(i)
#define SCNo8 __SCN8(o)
#define SCNu8 __SCN8(u)
#define SCNx8 __SCN8(x)

#endif /* __IO_C99_FORMATS */

#define PRIdLEAST8 __PRI8LEAST(d)
#define PRIiLEAST8 __PRI8LEAST(i)
#define PRIoLEAST8 __PRI8LEAST(o)
#define PRIuLEAST8 __PRI8LEAST(u)
#define PRIxLEAST8 __PRI8LEAST(x)
#define PRIXLEAST8 __PRI8LEAST(X)

/* Macros below are only enabled for a newlib built with C99 I/O format support. */
#if defined(__IO_C99_FORMATS)

#define SCNdLEAST8 __SCN8LEAST(d)
#define SCNiLEAST8 __SCN8LEAST(i)
#define SCNoLEAST8 __SCN8LEAST(o)
#define SCNuLEAST8 __SCN8LEAST(u)
#define SCNxLEAST8 __SCN8LEAST(x)

#endif /* __IO_C99_FORMATS */

#define PRIdFAST8 __PRI8FAST(d)
#define PRIiFAST8 __PRI8FAST(i)
#define PRIoFAST8 __PRI8FAST(o)
#define PRIuFAST8 __PRI8FAST(u)
#define PRIxFAST8 __PRI8FAST(x)
#define PRIXFAST8 __PRI8FAST(X)

/* Macros below are only enabled for a newlib built with C99 I/O format support. */
#if defined(__IO_C99_FORMATS)

#define SCNdFAST8 __SCN8FAST(d)
#define SCNiFAST8 __SCN8FAST(i)
#define SCNoFAST8 __SCN8FAST(o)
#define SCNuFAST8 __SCN8FAST(u)
#define SCNxFAST8 __SCN8FAST(x)

#endif /* __IO_C99_FORMATS */

/* 16-bit types */
#define __PRI16(x)      __INT16 __STRINGIFY(x)
#define __PRI16LEAST(x) __LEAST16 __STRINGIFY(x)
#define __PRI16FAST(x)  __FAST16 __STRINGIFY(x)
#define __SCN16(x)      __INT16 __STRINGIFY(x)
#define __SCN16LEAST(x) __LEAST16 __STRINGIFY(x)
#define __SCN16FAST(x)  __FAST16 __STRINGIFY(x)

#define PRId16          __PRI16(d)
#define PRIi16          __PRI16(i)
#define PRIo16          __PRI16(o)
#define PRIu16          __PRI16(u)
#define PRIx16          __PRI16(x)
#define PRIX16          __PRI16(X)

#define SCNd16          __SCN16(d)
#define SCNi16          __SCN16(i)
#define SCNo16          __SCN16(o)
#define SCNu16          __SCN16(u)
#define SCNx16          __SCN16(x)

#define PRIdLEAST16     __PRI16LEAST(d)
#define PRIiLEAST16     __PRI16LEAST(i)
#define PRIoLEAST16     __PRI16LEAST(o)
#define PRIuLEAST16     __PRI16LEAST(u)
#define PRIxLEAST16     __PRI16LEAST(x)
#define PRIXLEAST16     __PRI16LEAST(X)

#define SCNdLEAST16     __SCN16LEAST(d)
#define SCNiLEAST16     __SCN16LEAST(i)
#define SCNoLEAST16     __SCN16LEAST(o)
#define SCNuLEAST16     __SCN16LEAST(u)
#define SCNxLEAST16     __SCN16LEAST(x)

#define PRIdFAST16      __PRI16FAST(d)
#define PRIiFAST16      __PRI16FAST(i)
#define PRIoFAST16      __PRI16FAST(o)
#define PRIuFAST16      __PRI16FAST(u)
#define PRIxFAST16      __PRI16FAST(x)
#define PRIXFAST16      __PRI16FAST(X)

#define SCNdFAST16      __SCN16FAST(d)
#define SCNiFAST16      __SCN16FAST(i)
#define SCNoFAST16      __SCN16FAST(o)
#define SCNuFAST16      __SCN16FAST(u)
#define SCNxFAST16      __SCN16FAST(x)

/* 32-bit types */
#define __PRI32(x)      __INT32 __STRINGIFY(x)
#define __SCN32(x)      __INT32 __STRINGIFY(x)
#define __PRI32LEAST(x) __LEAST32 __STRINGIFY(x)
#define __SCN32LEAST(x) __LEAST32 __STRINGIFY(x)
#define __PRI32FAST(x)  __FAST32 __STRINGIFY(x)
#define __SCN32FAST(x)  __FAST32 __STRINGIFY(x)

#define PRId32          __PRI32(d)
#define PRIi32          __PRI32(i)
#define PRIo32          __PRI32(o)
#define PRIu32          __PRI32(u)
#define PRIx32          __PRI32(x)
#define PRIX32          __PRI32(X)

#define SCNd32          __SCN32(d)
#define SCNi32          __SCN32(i)
#define SCNo32          __SCN32(o)
#define SCNu32          __SCN32(u)
#define SCNx32          __SCN32(x)

#define PRIdLEAST32     __PRI32LEAST(d)
#define PRIiLEAST32     __PRI32LEAST(i)
#define PRIoLEAST32     __PRI32LEAST(o)
#define PRIuLEAST32     __PRI32LEAST(u)
#define PRIxLEAST32     __PRI32LEAST(x)
#define PRIXLEAST32     __PRI32LEAST(X)

#define SCNdLEAST32     __SCN32LEAST(d)
#define SCNiLEAST32     __SCN32LEAST(i)
#define SCNoLEAST32     __SCN32LEAST(o)
#define SCNuLEAST32     __SCN32LEAST(u)
#define SCNxLEAST32     __SCN32LEAST(x)

#define PRIdFAST32      __PRI32FAST(d)
#define PRIiFAST32      __PRI32FAST(i)
#define PRIoFAST32      __PRI32FAST(o)
#define PRIuFAST32      __PRI32FAST(u)
#define PRIxFAST32      __PRI32FAST(x)
#define PRIXFAST32      __PRI32FAST(X)

#define SCNdFAST32      __SCN32FAST(d)
#define SCNiFAST32      __SCN32FAST(i)
#define SCNoFAST32      __SCN32FAST(o)
#define SCNuFAST32      __SCN32FAST(u)
#define SCNxFAST32      __SCN32FAST(x)

/* 64-bit types */
#define __PRI64(x)      __INT64 __STRINGIFY(x)
#define __SCN64(x)      __INT64 __STRINGIFY(x)

#define __PRI64LEAST(x) __LEAST64 __STRINGIFY(x)
#define __SCN64LEAST(x) __LEAST64 __STRINGIFY(x)
#define __PRI64FAST(x)  __FAST64 __STRINGIFY(x)
#define __SCN64FAST(x)  __FAST64 __STRINGIFY(x)

#if __int64_t_defined
#define PRId64 __PRI64(d)
#define PRIi64 __PRI64(i)
#define PRIo64 __PRI64(o)
#define PRIu64 __PRI64(u)
#define PRIx64 __PRI64(x)
#define PRIX64 __PRI64(X)

#define SCNd64 __SCN64(d)
#define SCNi64 __SCN64(i)
#define SCNo64 __SCN64(o)
#define SCNu64 __SCN64(u)
#define SCNx64 __SCN64(x)
#endif

#if __int_least64_t_defined
#define PRIdLEAST64 __PRI64LEAST(d)
#define PRIiLEAST64 __PRI64LEAST(i)
#define PRIoLEAST64 __PRI64LEAST(o)
#define PRIuLEAST64 __PRI64LEAST(u)
#define PRIxLEAST64 __PRI64LEAST(x)
#define PRIXLEAST64 __PRI64LEAST(X)

#define SCNdLEAST64 __SCN64LEAST(d)
#define SCNiLEAST64 __SCN64LEAST(i)
#define SCNoLEAST64 __SCN64LEAST(o)
#define SCNuLEAST64 __SCN64LEAST(u)
#define SCNxLEAST64 __SCN64LEAST(x)
#endif

#if __int_fast64_t_defined
#define PRIdFAST64 __PRI64FAST(d)
#define PRIiFAST64 __PRI64FAST(i)
#define PRIoFAST64 __PRI64FAST(o)
#define PRIuFAST64 __PRI64FAST(u)
#define PRIxFAST64 __PRI64FAST(x)
#define PRIXFAST64 __PRI64FAST(X)

#define SCNdFAST64 __SCN64FAST(d)
#define SCNiFAST64 __SCN64FAST(i)
#define SCNoFAST64 __SCN64FAST(o)
#define SCNuFAST64 __SCN64FAST(u)
#define SCNxFAST64 __SCN64FAST(x)
#endif

/* max-bit types */
#if __have_long64
#define __PRIMAX(x) __STRINGIFY(l##x)
#define __SCNMAX(x) __STRINGIFY(l##x)
#elif __have_longlong64
#define __PRIMAX(x) __STRINGIFY(ll##x)
#define __SCNMAX(x) __STRINGIFY(ll##x)
#else
#define __PRIMAX(x) __STRINGIFY(x)
#define __SCNMAX(x) __STRINGIFY(x)
#endif

#define PRIdMAX __PRIMAX(d)
#define PRIiMAX __PRIMAX(i)
#define PRIoMAX __PRIMAX(o)
#define PRIuMAX __PRIMAX(u)
#define PRIxMAX __PRIMAX(x)
#define PRIXMAX __PRIMAX(X)

#define SCNdMAX __SCNMAX(d)
#define SCNiMAX __SCNMAX(i)
#define SCNoMAX __SCNMAX(o)
#define SCNuMAX __SCNMAX(u)
#define SCNxMAX __SCNMAX(x)

/* ptr types */
#if defined(_INTPTR_EQ_LONGLONG)
#define __PRIPTR(x) __STRINGIFY(ll##x)
#define __SCNPTR(x) __STRINGIFY(ll##x)
#elif defined(_INTPTR_EQ_LONG)
#define __PRIPTR(x) __STRINGIFY(l##x)
#define __SCNPTR(x) __STRINGIFY(l##x)
#else
#define __PRIPTR(x) __STRINGIFY(x)
#define __SCNPTR(x) __STRINGIFY(x)
#endif

#define PRIdPTR __PRIPTR(d)
#define PRIiPTR __PRIPTR(i)
#define PRIoPTR __PRIPTR(o)
#define PRIuPTR __PRIPTR(u)
#define PRIxPTR __PRIPTR(x)
#define PRIXPTR __PRIPTR(X)

#define SCNdPTR __SCNPTR(d)
#define SCNiPTR __SCNPTR(i)
#define SCNoPTR __SCNPTR(o)
#define SCNuPTR __SCNPTR(u)
#define SCNxPTR __SCNPTR(x)

intmax_t  imaxabs(intmax_t);
imaxdiv_t imaxdiv(intmax_t __numer, intmax_t __denomer);
intmax_t  strtoimax(const char  *__restrict, char  **__restrict, int);
uintmax_t strtoumax(const char * __restrict, char ** __restrict, int);
intmax_t  wcstoimax(const _wchar_t  *__restrict, _wchar_t  **__restrict, int);
uintmax_t wcstoumax(const _wchar_t * __restrict, _wchar_t ** __restrict, int);

#if __BSD_VISIBLE
intmax_t  strtoimax_l(const char  *__restrict, char **_restrict, int, locale_t);
uintmax_t strtoumax_l(const char * __restrict, char **_restrict, int, locale_t);
intmax_t  wcstoimax_l(const _wchar_t  *__restrict, _wchar_t **_restrict, int, locale_t);
uintmax_t wcstoumax_l(const _wchar_t * __restrict, _wchar_t **_restrict, int, locale_t);
#endif

_END_STD_C

#endif
