/* PDCLib printf logic <_PDCLIB_print.h> This file is part of the Public Domain C Library (PDCLib). Permission is granted to use, modify, and / or redistribute at will. */ #ifndef _PDCLIB_PRINT_H #define _PDCLIB_PRINT_H _PDCLIB_PRINT_H #include "pdclib/_PDCLIB_internal.h" #include #include #include /* This macro delivers a given character to either a memory buffer or a stream, depending on the contents of 'status' (struct _PDCLIB_status_t). x - the character to be delivered i - pointer to number of characters already delivered in this call n - pointer to maximum number of characters to be delivered in this call s - the buffer into which the character shall be delivered */ #define PUT( x ) \ do { \ int character = x; \ if ( status->i < status->n ) { \ if ( status->stream != NULL ) \ putc( character, status->stream ); \ else \ status->s[status->i] = character; \ } \ ++(status->i); \ } while ( 0 ) /* Using an integer's bits as flags for both the conversion flags and length modifiers. */ #define E_minus (INT32_C(1)<<0) #define E_plus (INT32_C(1)<<1) #define E_alt (INT32_C(1)<<2) #define E_space (INT32_C(1)<<3) #define E_zero (INT32_C(1)<<4) #define E_done (INT32_C(1)<<5) #define E_char (INT32_C(1)<<6) #define E_short (INT32_C(1)<<7) #define E_long (INT32_C(1)<<8) #define E_llong (INT32_C(1)<<9) #define E_intmax (INT32_C(1)<<10) #define E_size (INT32_C(1)<<11) #define E_ptrdiff (INT32_C(1)<<12) #define E_pointer (INT32_C(1)<<13) #define E_double (INT32_C(1)<<14) #define E_ldouble (INT32_C(1)<<15) #define E_lower (INT32_C(1)<<16) #define E_unsigned (INT32_C(1)<<17) #define E_decimal (INT32_C(1)<<18) #define E_exponent (INT32_C(1)<<19) #define E_generic (INT32_C(1)<<20) #define E_hexa (INT32_C(1)<<21) /* -------------------------------------------------------------------------- */ /* _PDCLIB_bigint_t support (required for floating point conversions) */ /* -------------------------------------------------------------------------- */ /* Must be divisible by 32. */ /* 1120 is enough for 64bit floats. A 128 float takes 16544 bits. */ #define _PDCLIB_BIGINT_BITS 1120 #if _PDCLIB_BIGINT_DIGIT_BITS == 32 #define _PDCLIB_BIGINT_DIGIT_MAX _PDCLIB_UINT_LEAST32_C( 0xFFFFFFFF ) typedef _PDCLIB_uint_least32_t _PDCLIB_bigint_digit_t; typedef _PDCLIB_int_least32_t _PDCLIB_bigint_sdigit_t; typedef _PDCLIB_uint_least64_t _PDCLIB_bigint_arith_t; #elif _PDCLIB_BIGINT_DIGIT_BITS == 16 #define _PDCLIB_BIGINT_DIGIT_MAX _PDCLIB_UINT_LEAST16_C( 0xFFFF ) typedef _PDCLIB_uint_least16_t _PDCLIB_bigint_digit_t; typedef _PDCLIB_int_least16_t _PDCLIB_bigint_sdigit_t; typedef _PDCLIB_uint_least32_t _PDCLIB_bigint_arith_t; #else #error _PDCLIB_BIGINT_DIGIT_BITS.needs to be 16 or 32. #endif /* How many "digits" a _PDCLIB_bigint_t holds. */ #define _PDCLIB_BIGINT_DIGITS _PDCLIB_BIGINT_BITS / _PDCLIB_BIGINT_DIGIT_BITS /* Maximum number of characters needed for _PDCLIB_bigint_tostring() */ #define _PDCLIB_BIGINT_CHARS ( _PDCLIB_BIGINT_BITS / 4 + _PDCLIB_BIGINT_DIGITS + 2 ) /* Type */ /* ---- */ typedef struct { /* Number of digits used; zero value == zero size */ _PDCLIB_size_t size; /* Least significant digit first */ _PDCLIB_bigint_digit_t data[ _PDCLIB_BIGINT_DIGITS ]; } _PDCLIB_bigint_t; typedef struct { _PDCLIB_bigint_t mantissa; _PDCLIB_int_least16_t exponent; _PDCLIB_int_least16_t scale; enum { _PDCLIB_FP_NORMAL, _PDCLIB_FP_SUBNORMAL, _PDCLIB_FP_INF, _PDCLIB_FP_NAN } state; char sign; } _PDCLIB_fp_t; void _PDCLIB_fp_from_dbl( _PDCLIB_fp_t * fp, double value ); void _PDCLIB_fp_from_ldbl( _PDCLIB_fp_t * fp, long double value ); void _PDCLIB_bigint_from_digit( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_digit_t digit ); void _PDCLIB_bigint_from_pow2( _PDCLIB_bigint_t * bigint, unsigned pow ); void _PDCLIB_bigint_from_pow10( _PDCLIB_bigint_t * bigint, unsigned pow ); void _PDCLIB_bigint_from_bigint( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other ); void _PDCLIB_bigint_add( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other ); void _PDCLIB_bigint_mul( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other ); void _PDCLIB_bigint_mul_pow10( _PDCLIB_bigint_t * bigint, int pow10 ); int _PDCLIB_bigint_cmp( _PDCLIB_bigint_t const * lhs, _PDCLIB_bigint_t const * rhs ); void _PDCLIB_bigint_shl( _PDCLIB_bigint_t * bigint, _PDCLIB_size_t bits ); void _PDCLIB_bigint_mul10( _PDCLIB_bigint_t * bigint ); int _PDCLIB_bigint_digit_log2( _PDCLIB_bigint_digit_t digit ); int _PDCLIB_bigint_log2( _PDCLIB_bigint_t const * bigint ); unsigned _PDCLIB_bigint_div( _PDCLIB_bigint_t * dividend, _PDCLIB_bigint_t const * divisor ); void _PDCLIB_print_integer( struct _PDCLIB_imaxdiv_t div, struct _PDCLIB_status_t * status ); void _PDCLIB_print_string( const char * s, struct _PDCLIB_status_t * status ); void _PDCLIB_print_fp( _PDCLIB_fp_t * fp, struct _PDCLIB_status_t * status ); int _PDCLIB_print_fp_deci( _PDCLIB_fp_t * fp, struct _PDCLIB_status_t * status, char * buffer ); void _PDCLIB_print_fp_hexa( _PDCLIB_fp_t * fp, struct _PDCLIB_status_t * status, char * buffer ); void _PDCLIB_print_fp_dragon4( _PDCLIB_bigint_t * fp, struct _PDCLIB_status_t * status ); #endif