diff --git a/libs/libc/stdio/Kconfig b/libs/libc/stdio/Kconfig index ae5ab4efb6..893a8c0317 100644 --- a/libs/libc/stdio/Kconfig +++ b/libs/libc/stdio/Kconfig @@ -108,4 +108,26 @@ config MEMCPY_VIK Select this option for improved performance at the expense of increased size. See licensing information in the top-level COPYING file. +config NANO_PRINTF + bool "Use nano printf code" + default n + ---help--- + Replace printf code with version from newlib-nano. This version + provides improved floating point output support, including 'g' mode + as well as making the default 'f' format include digits past the + decimal point. However, it does not include 'long long' support. + +config NANO_PRINTLEVEL + int "Nano printf support level" + default 2 + range 1 2 if !LIBC_FLOATINGPOINT + range 1 3 if LIBC_FLOATINGPOINT + depends on NANO_PRINTF + ---help--- + Nano printf can be built into more than one support level. The + default is to offer the usual modifiers and integer formatting + support (level 2). Level 1 maintains a minimal version that just + offers integer formatting, but no modifier support whatsoever. + Level 3 is intented for floating point support. + endmenu #Standard C I/O diff --git a/libs/libc/stdio/Make.defs b/libs/libc/stdio/Make.defs index 6db6433cb6..c7804402d7 100644 --- a/libs/libc/stdio/Make.defs +++ b/libs/libc/stdio/Make.defs @@ -39,12 +39,28 @@ CSRCS += lib_fileno.c lib_printf.c lib_sprintf.c lib_asprintf.c CSRCS += lib_snprintf.c lib_libsprintf.c lib_vsprintf.c lib_vasprintf.c -CSRCS += lib_vsnprintf.c lib_libvsprintf.c lib_dprintf.c lib_vdprintf.c +CSRCS += lib_vsnprintf.c lib_dprintf.c lib_vdprintf.c CSRCS += lib_meminstream.c lib_memoutstream.c lib_memsistream.c CSRCS += lib_memsostream.c lib_lowoutstream.c CSRCS += lib_zeroinstream.c lib_nullinstream.c lib_nulloutstream.c CSRCS += lib_sscanf.c lib_libnoflush.c lib_libsnoflush.c +ifeq ($(CONFIG_NANO_PRINTF),y) + +CSRCS += nano_libvsprintf.c nano_ultoa_invert.c + +ifeq ($(CONFIG_NANO_PRINTLEVEL),3) + +CSRCS += nano_dtoa_engine.c nano_dtoa_data.c + +endif + +else + +CSRCS += lib_libvsprintf.c + +endif + # The remaining sources files depend upon file descriptors ifneq ($(CONFIG_NFILE_DESCRIPTORS),0) diff --git a/libs/libc/stdio/nano_dtoa_data.c b/libs/libc/stdio/nano_dtoa_data.c new file mode 100644 index 0000000000..cb8d5ec3a9 --- /dev/null +++ b/libs/libc/stdio/nano_dtoa_data.c @@ -0,0 +1,276 @@ +/**************************************************************************** + * libs/libc/stdio/nano_dtoa_data.c + * + * Copyright © 2018, Keith Packard + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "nano_dtoa_engine.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef DBL_MAX_10_EXP +# error DBL_MAX_10_EXP +#endif + +#ifndef DBL_MIN_10_EXP +# error DBL_MIN_10_EXP +#endif + +#ifndef DBL_DIG +# error DBL_DIG +#endif + +/* Make sure the computed sizes of the arrays match the actual sizes + * by declaring an array which is legal if the sizes match and illegal + * if they do not + */ + +#define count_of(n) (sizeof (n) / sizeof (n[0])) +#define match(array,size) (count_of(array) == size) +#define check_match(array,size) (match(array, size) ? 1 : -1) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const double __dtoa_scale_up[] = +{ +#if DBL_MAX_10_EXP >= 1 + 1e1, +#endif +#if DBL_MAX_10_EXP >= 2 + 1e2, +#endif +#if DBL_MAX_10_EXP >= 4 + 1e4, +#endif +#if DBL_MAX_10_EXP >= 8 + 1e8, +#endif +#if DBL_MAX_10_EXP >= 16 + 1e16, +#endif +#if DBL_MAX_10_EXP >= 32 + 1e32, +#endif +#if DBL_MAX_10_EXP >= 64 + 1e64, +#endif +#if DBL_MAX_10_EXP >= 128 + 1e128, +#endif +#if DBL_MAX_10_EXP >= 256 + 1e256, +#endif +#if DBL_MAX_10_EXP >= 512 + 1e512, +#endif +#if DBL_MAX_10_EXP >= 1024 + 1e1024, +#endif +#if DBL_MAX_10_EXP >= 2048 + 1e2048, +#endif +#if DBL_MAX_10_EXP >= 4096 + 1e4096, +#endif +#if DBL_MAX_10_EXP >= 8192 + 1e8192, +#endif +#if DBL_MAX_10_EXP >= 16384 + 1e16384, +#endif +#if DBL_MAX_10_EXP >= 32768 + 1e32768, +#endif +#if DBL_MAX_10_EXP >= 65536 + 1e65536, +#endif +}; + +const double __dtoa_scale_down[] = +{ +#if DBL_MIN_10_EXP <= -1 + 1e-1, +#endif +#if DBL_MIN_10_EXP <= -2 + 1e-2, +#endif +#if DBL_MIN_10_EXP <= -4 + 1e-4, +#endif +#if DBL_MIN_10_EXP <= -8 + 1e-8, +#endif +#if DBL_MIN_10_EXP <= -16 + 1e-16, +#endif +#if DBL_MIN_10_EXP <= -32 + 1e-32, +#endif +#if DBL_MIN_10_EXP <= -64 + 1e-64, +#endif +#if DBL_MIN_10_EXP <= -128 + 1e-128, +#endif +#if DBL_MIN_10_EXP <= -256 + 1e-256, +#endif +#if DBL_MIN_10_EXP <= -512 + 1e-512, +#endif +#if DBL_MIN_10_EXP <= -1024 + 1e-1024, +#endif +#if DBL_MIN_10_EXP <= -2048 + 1e-2048, +#endif +#if DBL_MIN_10_EXP <= -4096 + 1e-4096, +#endif +#if DBL_MIN_10_EXP <= -8192 + 1e-8192, +#endif +#if DBL_MIN_10_EXP <= -16384 + 1e-16384, +#endif +#if DBL_MIN_10_EXP <= -32768 + 1e-32768, +#endif +#if DBL_MIN_10_EXP <= -65536 + 1e-65536, +#endif +}; + +const double __dtoa_round[] = +{ +#if DBL_DIG >= 30 + 5e30, +#endif +#if DBL_DIG >= 29 + 5e29, +#endif +#if DBL_DIG >= 28 + 5e28, +#endif +#if DBL_DIG >= 27 + 5e27, +#endif +#if DBL_DIG >= 26 + 5e26, +#endif +#if DBL_DIG >= 25 + 5e25, +#endif +#if DBL_DIG >= 24 + 5e24, +#endif +#if DBL_DIG >= 23 + 5e23, +#endif +#if DBL_DIG >= 22 + 5e22, +#endif +#if DBL_DIG >= 21 + 5e21, +#endif +#if DBL_DIG >= 20 + 5e20, +#endif +#if DBL_DIG >= 19 + 5e19, +#endif +#if DBL_DIG >= 18 + 5e18, +#endif +#if DBL_DIG >= 17 + 5e17, +#endif +#if DBL_DIG >= 16 + 5e16, +#endif +#if DBL_DIG >= 15 + 5e15, +#endif +#if DBL_DIG >= 14 + 5e14, +#endif +#if DBL_DIG >= 13 + 5e13, +#endif +#if DBL_DIG >= 12 + 5e12, +#endif +#if DBL_DIG >= 11 + 5e11, +#endif +#if DBL_DIG >= 10 + 5e10, +#endif +#if DBL_DIG >= 9 + 5e9, +#endif +#if DBL_DIG >= 8 + 5e8, +#endif +#if DBL_DIG >= 7 + 5e7, +#endif +#if DBL_DIG >= 6 + 5e6, +#endif +#if DBL_DIG >= 5 + 5e5, +#endif +#if DBL_DIG >= 4 + 5e4, +#endif +#if DBL_DIG >= 3 + 5e3, +#endif +#if DBL_DIG >= 2 + 5e2, +#endif +#if DBL_DIG >= 1 + 5e1, +#endif +#if DBL_DIG >= 0 + 5e0, +#endif +}; diff --git a/libs/libc/stdio/nano_dtoa_engine.c b/libs/libc/stdio/nano_dtoa_engine.c new file mode 100644 index 0000000000..dc4d3578d5 --- /dev/null +++ b/libs/libc/stdio/nano_dtoa_engine.c @@ -0,0 +1,169 @@ +/**************************************************************************** + * libs/libc/stdio/nanoo_dtoa_engine.c + * + * Copyright © 2018, Keith Packard + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "nano_dtoa_engine.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* A bit of CPP trickery -- construct the floating-point value 10 ** DBL_DIG + * by pasting the value of DBL_DIG onto '1e' to + */ + +#define PASTE(a) 1e##a +#define SUBSTITUTE(a) PASTE(a) +#define MIN_MANT (SUBSTITUTE(DBL_DIG)) +#define MAX_MANT (10.0 * MIN_MANT) +#define MIN_MANT_INT ((uint64_t)MIN_MANT) +#define MIN_MANT_EXP DBL_DIG + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int __dtoa_engine(double x, FAR struct dtoa *dtoa, int max_digits, + int max_decimals) +{ + int32_t exp = 0; + uint8_t flags = 0; + int i; + + if (__builtin_signbit(x)) + { + flags |= DTOA_MINUS; + x = -x; + } + + if (x == 0) + { + flags |= DTOA_ZERO; + for (i = 0; i < max_digits; i++) + dtoa->digits[i] = '0'; + } + else if (isnan(x)) + { + flags |= DTOA_NAN; + } + else if (isinf(x)) + { + flags |= DTOA_INF; + } + else + { + double y; + + exp = MIN_MANT_EXP; + + /* Bring x within range MIN_MANT <= x < MAX_MANT while computing + * exponent value + */ + + if (x < MIN_MANT) + { + for (i = DTOA_SCALE_UP_NUM - 1; i >= 0; i--) + { + y = x * __dtoa_scale_up[i]; + if (y < MAX_MANT) + { + x = y; + exp -= (1 << i); + } + } + } + else + { + for (i = DTOA_SCALE_DOWN_NUM - 1; i >= 0; i--) + { + y = x * __dtoa_scale_down[i]; + if (y >= MIN_MANT) + { + x = y; + exp += (1 << i); + } + } + } + + /* If limiting decimals, then limit the max digits to no more than the + * number of digits left of the decimal plus the number of digits right + * of the decimal + */ + + if (max_decimals != 0) + { + max_digits = MIN(max_digits, max_decimals + MAX(exp + 1, 1)); + } + + /* Round nearest by adding 1/2 of the last digit before converting to + * int. Check for overflow and adjust mantissa and exponent values + */ + + x = x + __dtoa_round[max_digits]; + + if (x >= MAX_MANT) + { + x /= 10.0; + exp++; + } + + /* Now convert mantissa to decimal. */ + + uint64_t mant = (uint64_t) x; + uint64_t decimal = MIN_MANT_INT; + + /* Compute digits */ + + for (i = 0; i < max_digits; i++) + { + dtoa->digits[i] = mant / decimal + '0'; + mant %= decimal; + decimal /= 10; + } + } + + dtoa->digits[max_digits] = '\0'; + dtoa->flags = flags; + dtoa->exp = exp; + return max_digits; +} diff --git a/libs/libc/stdio/nano_dtoa_engine.h b/libs/libc/stdio/nano_dtoa_engine.h new file mode 100644 index 0000000000..9f2b54a468 --- /dev/null +++ b/libs/libc/stdio/nano_dtoa_engine.h @@ -0,0 +1,189 @@ +/**************************************************************************** + * libs/libc/stdio/nano_dtoa_engine.h + * + * Copyright © 2018, Keith Packard + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +#ifndef __LIBS_LIBC_STDIO_NANO_DTOA_ENGINE_H +#define __LIBS_LIBC_STDIO_NANO_DTOA_ENGINE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define DTOA_MAX_DIG DBL_DIG + +#define DTOA_MINUS 1 +#define DTOA_ZERO 2 +#define DTOA_INF 4 +#define DTOA_NAN 8 +#define DTOA_CARRY 16 /* Carry was to master position. */ + +#if DBL_MAX_10_EXP >= 1 && DBL_MAX_10_EXP < 2 +# define DTOA_SCALE_UP_NUM 1 +#endif +#if DBL_MAX_10_EXP >= 2 && DBL_MAX_10_EXP < 4 +# define DTOA_SCALE_UP_NUM 2 +#endif +#if DBL_MAX_10_EXP >= 4 && DBL_MAX_10_EXP < 8 +# define DTOA_SCALE_UP_NUM 3 +#endif +#if DBL_MAX_10_EXP >= 8 && DBL_MAX_10_EXP < 16 +# define DTOA_SCALE_UP_NUM 4 +#endif +#if DBL_MAX_10_EXP >= 16 && DBL_MAX_10_EXP < 32 +# define DTOA_SCALE_UP_NUM 5 +#endif +#if DBL_MAX_10_EXP >= 32 && DBL_MAX_10_EXP < 64 +# define DTOA_SCALE_UP_NUM 6 +#endif +#if DBL_MAX_10_EXP >= 64 && DBL_MAX_10_EXP < 128 +# define DTOA_SCALE_UP_NUM 7 +#endif +#if DBL_MAX_10_EXP >= 128 && DBL_MAX_10_EXP < 256 +# define DTOA_SCALE_UP_NUM 8 +#endif +#if DBL_MAX_10_EXP >= 256 && DBL_MAX_10_EXP < 512 +# define DTOA_SCALE_UP_NUM 9 +#endif +#if DBL_MAX_10_EXP >= 512 && DBL_MAX_10_EXP < 1024 +# define DTOA_SCALE_UP_NUM 10 +#endif +#if DBL_MAX_10_EXP >= 1024 && DBL_MAX_10_EXP < 2048 +# define DTOA_SCALE_UP_NUM 11 +#endif +#if DBL_MAX_10_EXP >= 2048 && DBL_MAX_10_EXP < 4096 +# define DTOA_SCALE_UP_NUM 12 +#endif +#if DBL_MAX_10_EXP >= 4096 && DBL_MAX_10_EXP < 8192 +# define DTOA_SCALE_UP_NUM 13 +#endif +#if DBL_MAX_10_EXP >= 8192 && DBL_MAX_10_EXP < 16384 +# define DTOA_SCALE_UP_NUM 14 +#endif +#if DBL_MAX_10_EXP >= 16384 && DBL_MAX_10_EXP < 32768 +# define DTOA_SCALE_UP_NUM 15 +#endif +#if DBL_MAX_10_EXP >= 32768 && DBL_MAX_10_EXP < 65536 +# define DTOA_SCALE_UP_NUM 16 +#endif +#if DBL_MAX_10_EXP >= 65536 && DBL_MAX_10_EXP < 131072 +# define DTOA_SCALE_UP_NUM 17 +#endif +#if DBL_MIN_10_EXP <= -1 && DBL_MIN_10_EXP > -2 +# define DTOA_SCALE_DOWN_NUM 1 +#endif +#if DBL_MIN_10_EXP <= -2 && DBL_MIN_10_EXP > -4 +# define DTOA_SCALE_DOWN_NUM 2 +#endif +#if DBL_MIN_10_EXP <= -4 && DBL_MIN_10_EXP > -8 +# define DTOA_SCALE_DOWN_NUM 3 +#endif +#if DBL_MIN_10_EXP <= -8 && DBL_MIN_10_EXP > -16 +# define DTOA_SCALE_DOWN_NUM 4 +#endif +#if DBL_MIN_10_EXP <= -16 && DBL_MIN_10_EXP > -32 +# define DTOA_SCALE_DOWN_NUM 5 +#endif +#if DBL_MIN_10_EXP <= -32 && DBL_MIN_10_EXP > -64 +# define DTOA_SCALE_DOWN_NUM 6 +#endif +#if DBL_MIN_10_EXP <= -64 && DBL_MIN_10_EXP > -128 +# define DTOA_SCALE_DOWN_NUM 7 +#endif +#if DBL_MIN_10_EXP <= -128 && DBL_MIN_10_EXP > -256 +# define DTOA_SCALE_DOWN_NUM 8 +#endif +#if DBL_MIN_10_EXP <= -256 && DBL_MIN_10_EXP > -512 +# define DTOA_SCALE_DOWN_NUM 9 +#endif +#if DBL_MIN_10_EXP <= -512 && DBL_MIN_10_EXP > -1024 +# define DTOA_SCALE_DOWN_NUM 10 +#endif +#if DBL_MIN_10_EXP <= -1024 && DBL_MIN_10_EXP > -2048 +# define DTOA_SCALE_DOWN_NUM 11 +#endif +#if DBL_MIN_10_EXP <= -2048 && DBL_MIN_10_EXP > -4096 +# define DTOA_SCALE_DOWN_NUM 12 +#endif +#if DBL_MIN_10_EXP <= -4096 && DBL_MIN_10_EXP > -8192 +# define DTOA_SCALE_DOWN_NUM 13 +#endif +#if DBL_MIN_10_EXP <= -8192 && DBL_MIN_10_EXP > -16384 +# define DTOA_SCALE_DOWN_NUM 14 +#endif +#if DBL_MIN_10_EXP <= -16384 && DBL_MIN_10_EXP > -32768 +# define DTOA_SCALE_DOWN_NUM 15 +#endif +#if DBL_MIN_10_EXP <= -32768 && DBL_MIN_10_EXP > -65536 +# define DTOA_SCALE_DOWN_NUM 16 +#endif +#if DBL_MIN_10_EXP <= -65536 && DBL_MIN_10_EXP > -131072 +# define DTOA_SCALE_DOWN_NUM 17 +#endif + +#define DTOA_ROUND_NUM (DBL_DIG + 1) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct dtoa +{ + int32_t exp; + uint8_t flags; + char digits[DTOA_MAX_DIG + 1]; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern const double __dtoa_scale_up[]; +extern const double __dtoa_scale_down[]; +extern const double __dtoa_round[]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int __dtoa_engine(double x, FAR struct dtoa *dtoa, int max_digits, + int max_decimals); + +#endif /* __LIBS_LIBC_STDIO_NANO_DTOA_ENGINE_H */ diff --git a/libs/libc/stdio/nano_libvsprintf.c b/libs/libc/stdio/nano_libvsprintf.c new file mode 100644 index 0000000000..f934b7b22d --- /dev/null +++ b/libs/libc/stdio/nano_libvsprintf.c @@ -0,0 +1,1037 @@ +/**************************************************************************** + * libs/libc/stdio/nano_libvsprintf.c + * + * Copyright (c) 2002, Alexander Popov (sasho@vip.bg) + * Copyright (c) 2002,2004,2005 Joerg Wunsch + * Copyright (c) 2005, Helmut Wallner + * Copyright (c) 2007, Dmitry Xmelkov + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "nano_dtoa_engine.h" +#include "nano_ultoa_invert.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration options for nano-printf PRINTF_LEVEL */ + +#define PRINTF_MIN 1 +#define PRINTF_STD 2 +#define PRINTF_FLT 3 + +/* This file can be compiled into more than one flavour. The default + * is to offer the usual modifiers and integer formatting support + * (level 2). Level 1 maintains a minimal version that just offers + * integer formatting, but no modifier support whatsoever. Level 3 is + * intented for floating point support. + */ + +#if defined(CONFIG_NANO_PRINTLEVEL) +# define PRINTF_LEVEL CONFIG_NANO_PRINTLEVEL +#elif defined(CONFIG_LIBC_FLOATINGPOINT) +# define PRINTF_LEVEL PRINTF_FLT +#else +# define PRINTF_LEVEL PRINTF_STD +#endif + +#if PRINTF_LEVEL == PRINTF_MIN || PRINTF_LEVEL == PRINTF_STD || \ + PRINTF_LEVEL == PRINTF_FLT + +/* OK */ + +#else +# error "Not a known printf level." +#endif + +#ifdef putc +# undef putc +#endif + +#define putc(c,stream) (total_len++, (stream)->put(stream, c)) + +#if PRINTF_LEVEL <= PRINTF_MIN + +# define FL_ALTHEX 0x04 +# define FL_ALT 0x10 +# define FL_ALTLWR 0x20 +# define FL_NEGATIVE 0x40 +# define FL_LONG 0x80 + +#else /* i.e. PRINTF_LEVEL > PRINTF_MIN */ + +/* Order is relevant here and matches order in format string */ + +# define FL_ZFILL 0x0001 +# define FL_PLUS 0x0002 +# define FL_SPACE 0x0004 +# define FL_LPAD 0x0008 +# define FL_ALT 0x0010 + +# define FL_WIDTH 0x0020 +# define FL_PREC 0x0040 + +# define FL_LONG 0x0080 +# define FL_LONGLONG 0x0100 +# define FL_SHORT 0x0200 + +# define FL_NEGATIVE 0x0400 + +# define FL_ALTUPP 0x0800 +# define FL_ALTHEX 0x1000 + +# define FL_FLTUPP 0x2000 +# define FL_FLTEXP 0x4000 +# define FL_FLTFIX 0x8000 + +#endif + +/* Support special access to CODE-space strings for Harvard architectures */ + +#ifdef CONFIG_ARCH_ROMGETC +# define fmt_char(fmt) up_romgetc((fmt)++) +#else +# define fmt_char(fmt) (*(fmt)++) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#if PRINTF_LEVEL <= PRINTF_MIN +int lib_vsprintf(FAR struct lib_outstream_s *stream, + FAR const IPTR char *fmt, va_list ap) +{ + unsigned char c; /* Holds a char from the format string */ + unsigned char flags; + unsigned char buf[11]; /* Size for -1 in octal, without '\0' */ + int total_len = 0; + + for (; ; ) + { + for (; ; ) + { + c = fmt_char(fmt); + if (!c) + { + goto ret; + } + + if (c == '%') + { + c = fmt_char(fmt); + if (c != '%') + { + break; + } + } + + putc(c, stream); + } + + for (flags = 0; !(flags & FL_LONG); /* 'll' will detect as error */ + c = fmt_char(fmt)) + { + if (c && strchr(" +-.0123456789h", c)) + { + continue; + } + + if (c == '#') + { + flags |= FL_ALT; + continue; + } + + if (c == 'l') + { + flags |= FL_LONG; + continue; + } + + break; + } + + /* Only a format character is valid. */ + + if (c && strchr("EFGefg", c)) + { + (void)va_arg(ap, double); + putc('?', stream); + continue; + } + + { + const char *pnt; + + switch (c) + { + case 'c': + putc(va_arg(ap, int), stream); + continue; + + case 'S': + + /* FALLTHROUGH */ + + case 's': + pnt = va_arg(ap, char *); + while ((c = *pnt++) != 0) + { + putc(c, stream); + } + + continue; + } + } + + if (c == 'd' || c == 'i') + { + long x = (flags & FL_LONG) ? va_arg(ap, long) : va_arg(ap, int); + flags &= ~FL_ALT; + if (x < 0) + { + x = -x; + + /* `putc ('-', stream)' will considarably inlarge stack size. So + * flag is used. + */ + + flags |= FL_NEGATIVE; + } + + c = __ultoa_invert(x, (char *)buf, 10) - (char *)buf; + } + else + { + int base; + + switch (c) + { + case 'u': + flags &= ~FL_ALT; + base = 10; + sign = 0; + goto ultoa; + + case 'o': + base = 8; + goto ultoa; + + case 'p': + flags |= FL_ALT; + + /* no break */ + + case 'x': + flags |= (FL_ALTHEX | FL_ALTLWR); + base = 16; + goto ultoa; + + case 'X': + flags |= FL_ALTHEX; + base = 16 | XTOA_UPPER; + + ultoa: + c = __ultoa_invert((flags & FL_LONG) + ? va_arg(ap, unsigned long) + : va_arg(ap, unsigned int), + (char *)buf, base) - (char *)buf; + break; + + default: + goto ret; + } + } + + /* Integer number output. */ + + if (flags & FL_NEGATIVE) + { + putc('-', stream); + } + + if ((flags & FL_ALT) && (buf[c - 1] != '0')) + { + putc('0', stream); + if (flags & FL_ALTHEX) + { +# if FL_ALTLWR != 'x' - 'X' +# error +# endif + putc('X' + (flags & FL_ALTLWR), stream); + } + } + + do + { + putc(buf[--c], stream); + } + while (c); + } + +ret: + return total_len; +} + +#else /* i.e. PRINTF_LEVEL > PRINTF_MIN */ + +int lib_vsprintf(FAR struct lib_outstream_s *stream, + FAR const IPTR char *fmt, va_list ap) +{ + unsigned char c; /* Holds a char from the format string */ + uint16_t flags; + int width; + int prec; + union + { + unsigned char __buf[11]; /* Size for -1 in octal, without '\0' */ +# if PRINTF_LEVEL >= PRINTF_FLT + struct dtoa __dtoa; +# endif + } u; + const char *pnt; + size_t size; + unsigned char len; + int total_len = 0; + +# define buf (u.__buf) +# define _dtoa (u.__dtoa) + + for (; ; ) + { + for (; ; ) + { + c = fmt_char(fmt); + if (!c) + { + goto ret; + } + + if (c == '%') + { + c = fmt_char(fmt); + if (c != '%') + { + break; + } + } + + putc(c, stream); + } + + flags = 0; + width = 0; + prec = 0; + + do + { + if (flags < FL_WIDTH) + { + switch (c) + { + case '0': + flags |= FL_ZFILL; + continue; + + case '+': + flags |= FL_PLUS; + + /* FALLTHROUGH */ + + case ' ': + flags |= FL_SPACE; + continue; + + case '-': + flags |= FL_LPAD; + continue; + + case '#': + flags |= FL_ALT; + continue; + } + } + + if (flags < FL_LONG) + { + if (c >= '0' && c <= '9') + { + c -= '0'; + if (flags & FL_PREC) + { + prec = 10 * prec + c; + continue; + } + + width = 10 * width + c; + flags |= FL_WIDTH; + continue; + } + + if (c == '*') + { + if (flags & FL_PREC) + { + prec = va_arg(ap, int); + if (prec < 0) + { + prec = 0; + } + } + else + { + width = va_arg(ap, int); + flags |= FL_WIDTH; + if (width < 0) + { + width = -width; + flags |= FL_LPAD; + } + } + + continue; + } + + if (c == '.') + { + if (flags & FL_PREC) + { + goto ret; + } + + flags |= FL_PREC; + continue; + } + } + + if (c == 'l') + { + if (flags & FL_LONG) + { + flags |= FL_LONGLONG; + } + + flags |= FL_LONG; + flags &= ~FL_SHORT; + continue; + } + + if (c == 'h') + { + flags |= FL_SHORT; + flags &= ~FL_LONG; + continue; + } + + break; + } + while ((c = fmt_char(fmt)) != 0); + + /* Only a format character is valid. */ + +# if 'F' != 'E'+1 || 'G' != 'F'+1 || 'f' != 'e'+1 || 'g' != 'f'+1 +# error +# endif + +# if PRINTF_LEVEL >= PRINTF_FLT + if (c >= 'E' && c <= 'G') + { + flags |= FL_FLTUPP; + c += 'e' - 'E'; + goto flt_oper; + } + else if (c >= 'e' && c <= 'g') + { + int exp; /* Exponent of master decimal digit */ + int n; + uint8_t sign; /* Sign character (or 0) */ + uint8_t ndigs; /* Number of digits to convert */ + uint8_t ndecimal; /* Digits after decimal (for 'f' format), 0 if + * no limit */ + + flags &= ~FL_FLTUPP; + + flt_oper: + ndigs = 0; + if (!(flags & FL_PREC)) + { + prec = 6; + } + + flags &= ~(FL_FLTEXP | FL_FLTFIX); + + if (c == 'e') + { + ndigs = prec + 1; + ndecimal = 0; + flags |= FL_FLTEXP; + } + else if (c == 'f') + { + ndigs = DTOA_MAX_DIG; + ndecimal = prec; + flags |= FL_FLTFIX; + } + else + { + ndigs = prec; + ndecimal = 0; + } + + if (ndigs > DTOA_MAX_DIG) + { + ndigs = DTOA_MAX_DIG; + } + + ndigs = __dtoa_engine(va_arg(ap, double), &_dtoa, ndigs, ndecimal); + exp = _dtoa.exp; + + sign = 0; + if ((_dtoa.flags & DTOA_MINUS) && !(_dtoa.flags & DTOA_NAN)) + { + sign = '-'; + } + else if (flags & FL_PLUS) + { + sign = '+'; + } + else if (flags & FL_SPACE) + { + sign = ' '; + } + + if (_dtoa.flags & (DTOA_NAN | DTOA_INF)) + { + const char *p; + + ndigs = sign ? 4 : 3; + if (width > ndigs) + { + width -= ndigs; + if (!(flags & FL_LPAD)) + { + do + { + putc(' ', stream); + } + while (--width); + } + } + else + { + width = 0; + } + + if (sign) + { + putc(sign, stream); + } + + p = "inf"; + if (_dtoa.flags & DTOA_NAN) + { + p = "nan"; + } + +# if ('I'-'i' != 'N'-'n') || ('I'-'i' != 'F'-'f') || ('I'-'i' != 'A'-'a') +# error +# endif + while ((ndigs = *p) != 0) + { + if (flags & FL_FLTUPP) + { + ndigs += 'I' - 'i'; + } + + putc(ndigs, stream); + p++; + } + + goto tail; + } + + if (!(flags & (FL_FLTEXP | FL_FLTFIX))) + { + /* 'g(G)' format */ + + prec = ndigs; + + /* Remove trailing zeros */ + + while (ndigs > 0 && _dtoa.digits[ndigs - 1] == '0') + { + ndigs--; + } + + if (-4 <= exp && exp < prec) + { + flags |= FL_FLTFIX; + + if (exp < 0 || ndigs > exp) + { + prec = ndigs - (exp + 1); + } + else + { + prec = 0; + } + } + else + { + /* Limit displayed precision to available precision */ + + prec = ndigs - 1; + } + } + + /* Conversion result length, width := free space length */ + + if (flags & FL_FLTFIX) + { + n = (exp > 0 ? exp + 1 : 1); + } + else + { + n = 5; /* 1e+00 */ + } + + if (sign) + { + n += 1; + } + + if (prec) + { + n += prec + 1; + } + else if (flags & FL_ALT) + { + n += 1; + } + + width = width > n ? width - n : 0; + + /* Output before first digit */ + + if (!(flags & (FL_LPAD | FL_ZFILL))) + { + while (width) + { + putc(' ', stream); + width--; + } + } + + if (sign) + { + putc(sign, stream); + } + + if (!(flags & FL_LPAD)) + { + while (width) + { + putc('0', stream); + width--; + } + } + + if (flags & FL_FLTFIX) + { + /* 'f' format */ + + char out; + + /* At this point, we should have exp exponent of leftmost digit + * in _dtoa.digits ndigs number of buffer digits to print prec + * number of digits after decimal In the loop, 'n' walks over + * the exponent value + */ + + n = exp > 0 ? exp : 0; /* Exponent of left digit */ + do + { + + /* Insert decimal point at correct place */ + + if (n == -1) + { + putc('.', stream); + } + + /* Pull digits from buffer when in-range, otherwise use 0 */ + + if (0 <= exp - n && exp - n < ndigs) + { + out = _dtoa.digits[exp - n]; + } + else + { + out = '0'; + } + + if (--n < -prec) + { + if ((flags & FL_ALT) && n == -1) + { + putc('.', stream); + } + + break; + } + + putc(out, stream); + } + while (1); + + if (n == exp && (_dtoa.digits[0] > '5' || + (_dtoa.digits[0] == '5' && !(_dtoa.flags & DTOA_CARRY)))) + { + out = '1'; + } + + putc(out, stream); + } + else + { + /* 'e(E)' format + * + * Mantissa + */ + + if (_dtoa.digits[0] != '1') + { + _dtoa.flags &= ~DTOA_CARRY; + } + + putc(_dtoa.digits[0], stream); + if (prec > 0) + { + putc('.', stream); + uint8_t pos = 1; + for (pos = 1; pos < 1 + prec; pos++) + putc(pos < ndigs ? _dtoa.digits[pos] : '0', stream); + } + else if (flags & FL_ALT) + { + putc('.', stream); + } + + /* Exponent */ + + putc(flags & FL_FLTUPP ? 'E' : 'e', stream); + ndigs = '+'; + if (exp < 0 || (exp == 0 && (_dtoa.flags & DTOA_CARRY) != 0)) + { + exp = -exp; + ndigs = '-'; + } + + putc(ndigs, stream); + for (ndigs = '0'; exp >= 10; exp -= 10) + { + ndigs += 1; + } + + putc(ndigs, stream); + putc('0' + exp, stream); + } + + goto tail; + } + +# else /* to: PRINTF_LEVEL >= PRINTF_FLT */ + if ((c >= 'E' && c <= 'G') || (c >= 'e' && c <= 'g')) + { + (void)va_arg(ap, double); + pnt = "*float*"; + size = sizeof("*float*") - 1; + goto str_lpad; + } +# endif + + switch (c) + { + + case 'c': + buf[0] = va_arg(ap, int); + pnt = (char *)buf; + size = 1; + goto str_lpad; + + case 's': + case 'S': + pnt = va_arg(ap, char *); + size = strnlen(pnt, (flags & FL_PREC) ? prec : ~0); + + str_lpad: + if (!(flags & FL_LPAD)) + { + while (size < width) + { + putc(' ', stream); + width--; + } + } + + while (size) + { + putc(*pnt++, stream); + if (width) + { + width -= 1; + } + + size -= 1; + } + + goto tail; + } + + if (c == 'd' || c == 'i') + { + long x; + + if (flags & FL_LONG) + { + x = va_arg(ap, long); + } + else + { + x = va_arg(ap, int); + if (flags & FL_SHORT) + { + x = (short)x; + } + } + + flags &= ~(FL_NEGATIVE | FL_ALT); + if (x < 0) + { + x = -x; + flags |= FL_NEGATIVE; + } + + if ((flags & FL_PREC) && prec == 0 && x == 0) + { + c = 0; + } + else + { + c = __ultoa_invert(x, (char *)buf, 10) - (char *)buf; + } + } + else + { + int base; + unsigned long x; + + if (flags & FL_LONG) + { + x = va_arg(ap, unsigned long); + } + else + { + x = va_arg(ap, unsigned int); + if (flags & FL_SHORT) + x = (unsigned short)x; + } + + flags &= ~(FL_PLUS | FL_SPACE); + + switch (c) + { + case 'u': + flags &= ~FL_ALT; + base = 10; + break; + + case 'o': + base = 8; + break; + + case 'p': + flags |= FL_ALT; + + /* no break */ + + case 'x': + if (flags & FL_ALT) + flags |= FL_ALTHEX; + base = 16; + break; + + case 'X': + if (flags & FL_ALT) + flags |= (FL_ALTHEX | FL_ALTUPP); + base = 16 | XTOA_UPPER; + break; + + default: + putc('%', stream); + putc(c, stream); + continue; + } + + if ((flags & FL_PREC) && prec == 0 && x == 0) + { + c = 0; + } + else + { + c = __ultoa_invert(x, (char *)buf, base) - (char *)buf; + } + + flags &= ~FL_NEGATIVE; + } + + len = c; + + if (flags & FL_PREC) + { + flags &= ~FL_ZFILL; + if (len < prec) + { + len = prec; + if ((flags & FL_ALT) && !(flags & FL_ALTHEX)) + { + flags &= ~FL_ALT; + } + } + } + + if (flags & FL_ALT) + { + if (buf[c - 1] == '0') + { + flags &= ~(FL_ALT | FL_ALTHEX | FL_ALTUPP); + } + else + { + len += 1; + if (flags & FL_ALTHEX) + { + len += 1; + } + } + } + else if (flags & (FL_NEGATIVE | FL_PLUS | FL_SPACE)) + { + len += 1; + } + + if (!(flags & FL_LPAD)) + { + if (flags & FL_ZFILL) + { + prec = c; + if (len < width) + { + prec += width - len; + len = width; + } + } + + while (len < width) + { + putc(' ', stream); + len++; + } + } + + width = (len < width) ? width - len : 0; + + if (flags & FL_ALT) + { + putc('0', stream); + if (flags & FL_ALTHEX) + { + putc(flags & FL_ALTUPP ? 'X' : 'x', stream); + } + } + else if (flags & (FL_NEGATIVE | FL_PLUS | FL_SPACE)) + { + unsigned char z = ' '; + if (flags & FL_PLUS) + { + z = '+'; + } + + if (flags & FL_NEGATIVE) + { + z = '-'; + } + + putc(z, stream); + } + + while (prec > c) + { + putc('0', stream); + prec--; + } + + while (c) + { + putc(buf[--c], stream); + } + + tail: + + /* Tail is possible. */ + + while (width) + { + putc(' ', stream); + width--; + } + } + +ret: + return total_len; +} + +#endif /* PRINTF_LEVEL > PRINTF_MIN */ diff --git a/libs/libc/stdio/nano_ultoa_invert.c b/libs/libc/stdio/nano_ultoa_invert.c new file mode 100644 index 0000000000..6bd28e9067 --- /dev/null +++ b/libs/libc/stdio/nano_ultoa_invert.c @@ -0,0 +1,79 @@ +/**************************************************************************** + * libs/libc/stdio/nano_ultoa_invert.c + * + * Copyright © 2017, Keith Packard + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "nano_ultoa_invert.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +FAR char *__ultoa_invert(unsigned long val, FAR char *str, int base) +{ + int upper = 0; + + if (base & XTOA_UPPER) + { + upper = 1; + base &= ~XTOA_UPPER; + } + do + { + int v; + + v = val % base; + val = val / base; + + if (v <= 9) + { + v += '0'; + } + else + { + if (upper) + v += 'A' - 10; + else + v += 'a' - 10; + } + + *str++ = v; + } + while (val); + + return str; +} diff --git a/libs/libc/stdio/nano_ultoa_invert.h b/libs/libc/stdio/nano_ultoa_invert.h new file mode 100644 index 0000000000..0c07cb96c1 --- /dev/null +++ b/libs/libc/stdio/nano_ultoa_invert.h @@ -0,0 +1,62 @@ +/**************************************************************************** + * libs/libc/stdio/nano_ultoa_invert.h + * + * Copyright (c) 2005, Dmitry Xmelkov + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +#ifndef __LIBS_LIBC_STDIO_NANO_ULTOA_INVERT_H +#define __LIBS_LIBC_STDIO_NANO_ULTOA_INVERT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Next flags are to use with `base'. Unused fields are reserved. */ + +#define XTOA_PREFIX 0x0100 /* Put prefix for octal or hex */ +#define XTOA_UPPER 0x0200 /* Use upper case letters */ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Internal function for use from `printf'. */ + +FAR char *__ultoa_invert(unsigned long val, FAR char *s, int base); + +#endif /* __LIBS_LIBC_STDIO_NANO_ULTOA_INVERT_H */