diff options
Diffstat (limited to 'nuttx/libc/stdio/lib_libvsprintf.c')
-rw-r--r-- | nuttx/libc/stdio/lib_libvsprintf.c | 1625 |
1 files changed, 0 insertions, 1625 deletions
diff --git a/nuttx/libc/stdio/lib_libvsprintf.c b/nuttx/libc/stdio/lib_libvsprintf.c deleted file mode 100644 index 2cc7950f7..000000000 --- a/nuttx/libc/stdio/lib_libvsprintf.c +++ /dev/null @@ -1,1625 +0,0 @@ -/**************************************************************************** - * libc/stdio/lib_libvsprintf.c - * - * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <gnutt@nuttx.org> - * - * 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 <nuttx/compiler.h> - -#include <stdint.h> -#include <stdbool.h> -#include <stdio.h> -#include <string.h> - -#include <nuttx/arch.h> - -#include "lib_internal.h" - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ -/* If you have floating point but no fieldwidth, then use a fixed (but - * configurable) floating point precision. - */ - -#if defined(CONFIG_LIBC_FLOATINGPOINT) && \ - defined(CONFIG_NOPRINTF_FIELDWIDTH) && \ - !defined(CONFIG_LIBC_FIXEDPRECISION) -# define CONFIG_LIBC_FIXEDPRECISION 3 -#endif - -#define FLAG_SHOWPLUS 0x01 -#define FLAG_ALTFORM 0x02 -#define FLAG_HASDOT 0x04 -#define FLAG_HASASTERISKWIDTH 0x08 -#define FLAG_HASASTERISKTRUNC 0x10 -#define FLAG_LONGPRECISION 0x20 -#define FLAG_LONGLONGPRECISION 0x40 -#define FLAG_NEGATE 0x80 - -#define SET_SHOWPLUS(f) do (f) |= FLAG_SHOWPLUS; while (0) -#define SET_ALTFORM(f) do (f) |= FLAG_ALTFORM; while (0) -#define SET_HASDOT(f) do (f) |= FLAG_HASDOT; while (0) -#define SET_HASASTERISKWIDTH(f) do (f) |= FLAG_HASASTERISKWIDTH; while (0) -#define SET_HASASTERISKTRUNC(f) do (f) |= FLAG_HASASTERISKTRUNC; while (0) -#define SET_LONGPRECISION(f) do (f) |= FLAG_LONGPRECISION; while (0) -#define SET_LONGLONGPRECISION(f) do (f) |= FLAG_LONGLONGPRECISION; while (0) -#define SET_NEGATE(f) do (f) |= FLAG_NEGATE; while (0) - -#define CLR_SHOWPLUS(f) do (f) &= ~FLAG_SHOWPLUS; while (0) -#define CLR_ALTFORM(f) do (f) &= ~FLAG_ALTFORM; while (0) -#define CLR_HASDOT(f) do (f) &= ~FLAG_HASDOT; while (0) -#define CLR_HASASTERISKWIDTH(f) do (f) &= ~FLAG_HASASTERISKWIDTH; while (0) -#define CLR_HASASTERISKTRUNC(f) do (f) &= ~FLAG_HASASTERISKTRUNC; while (0) -#define CLR_LONGPRECISION(f) do (f) &= ~FLAG_LONGPRECISION; while (0) -#define CLR_LONGLONGPRECISION(f) do (f) &= ~FLAG_LONGLONGPRECISION; while (0) -#define CLR_NEGATE(f) do (f) &= ~FLAG_NEGATE; while (0) -#define CLR_SIGNED(f) do (f) &= ~(FLAG_SHOWPLUS|FLAG_NEGATE); while (0) - -#define IS_SHOWPLUS(f) (((f) & FLAG_SHOWPLUS) != 0) -#define IS_ALTFORM(f) (((f) & FLAG_ALTFORM) != 0) -#define IS_HASDOT(f) (((f) & FLAG_HASDOT) != 0) -#define IS_HASASTERISKWIDTH(f) (((f) & FLAG_HASASTERISKWIDTH) != 0) -#define IS_HASASTERISKTRUNC(f) (((f) & FLAG_HASASTERISKTRUNC) != 0) -#define IS_LONGPRECISION(f) (((f) & FLAG_LONGPRECISION) != 0) -#define IS_LONGLONGPRECISION(f) (((f) & FLAG_LONGLONGPRECISION) != 0) -#define IS_NEGATE(f) (((f) & FLAG_NEGATE) != 0) -#define IS_SIGNED(f) (((f) & (FLAG_SHOWPLUS|FLAG_NEGATE)) != 0) - -/* If CONFIG_ARCH_ROMGETC is defined, then it is assumed that the format - * string data cannot be accessed by simply de-referencing the format string - * pointer. This might be in the case in Harvard architectures where string - * data might be stored in instruction space or if string data were stored - * on some media like EEPROM or external serial FLASH. In all of these cases, - * string data has to be accessed indirectly using the architecture-supplied - * up_romgetc(). The following mechanisms attempt to make these different - * access methods indistinguishable in the following code. - * - * NOTE: It is assumed that string arguments for %s still reside in memory - * that can be directly accessed by de-referencing the string pointer. - */ - -#ifdef CONFIG_ARCH_ROMGETC -# define FMT_TOP ch = up_romgetc(src) /* Loop initialization */ -# define FMT_BOTTOM src++, ch = up_romgetc(src) /* Bottom of a loop */ -# define FMT_CHAR ch /* Access a character */ -# define FMT_NEXT src++; ch = up_romgetc(src) /* Advance to the next character */ -# define FMT_PREV src--; ch = up_romgetc(src) /* Backup to the previous character */ -#else -# define FMT_TOP /* Loop initialization */ -# define FMT_BOTTOM src++ /* Bottom of a loop */ -# define FMT_CHAR *src /* Access a character */ -# define FMT_NEXT src++ /* Advance to the next character */ -# define FMT_PREV src-- /* Backup to the previous character */ -#endif - -/**************************************************************************** - * Private Type Declarations - ****************************************************************************/ - -enum -{ - FMT_RJUST = 0, /* Default */ - FMT_LJUST, - FMT_RJUST0, - FMT_CENTER -}; - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -/* Pointer to ASCII conversion */ - -#ifdef CONFIG_PTR_IS_NOT_INT -static void ptohex(FAR struct lib_outstream_s *obj, uint8_t flags, FAR void *p); -#ifndef CONFIG_NOPRINTF_FIELDWIDTH -static int getsizesize(uint8_t fmt, uint8_t flags, FAR void *p) -#endif /* CONFIG_NOPRINTF_FIELDWIDTH */ -#endif /* CONFIG_PTR_IS_NOT_INT */ - -/* Unsigned int to ASCII conversion */ - -static void utodec(FAR struct lib_outstream_s *obj, unsigned int n); -static void utohex(FAR struct lib_outstream_s *obj, unsigned int n, uint8_t a); -static void utooct(FAR struct lib_outstream_s *obj, unsigned int n); -static void utobin(FAR struct lib_outstream_s *obj, unsigned int n); -static void utoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, - uint8_t flags, unsigned int lln); - -#ifndef CONFIG_NOPRINTF_FIELDWIDTH -static void fixup(uint8_t fmt, FAR uint8_t *flags, int *n); -static int getusize(uint8_t fmt, uint8_t flags, unsigned int lln); -#endif - -/* Unsigned long int to ASCII conversion */ - -#ifdef CONFIG_LONG_IS_NOT_INT -static void lutodec(FAR struct lib_outstream_s *obj, unsigned long ln); -static void lutohex(FAR struct lib_outstream_s *obj, unsigned long ln, uint8_t a); -static void lutooct(FAR struct lib_outstream_s *obj, unsigned long ln); -static void lutobin(FAR struct lib_outstream_s *obj, unsigned long ln); -static void lutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, - uint8_t flags, unsigned long ln); -#ifndef CONFIG_NOPRINTF_FIELDWIDTH -static void lfixup(uint8_t fmt, FAR uint8_t *flags, long *ln); -static int getlusize(uint8_t fmt, FAR uint8_t flags, unsigned long ln); -#endif -#endif - -/* Unsigned long long int to ASCII conversions */ - -#ifdef CONFIG_HAVE_LONG_LONG -static void llutodec(FAR struct lib_outstream_s *obj, unsigned long long lln); -static void llutohex(FAR struct lib_outstream_s *obj, unsigned long long lln, uint8_t a); -static void llutooct(FAR struct lib_outstream_s *obj, unsigned long long lln); -static void llutobin(FAR struct lib_outstream_s *obj, unsigned long long lln); -static void llutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, - uint8_t flags, unsigned long long lln); -#ifndef CONFIG_NOPRINTF_FIELDWIDTH -static void llfixup(uint8_t fmt, FAR uint8_t *flags, FAR long long *lln); -static int getllusize(uint8_t fmt, FAR uint8_t flags, FAR unsigned long long lln); -#endif -#endif - -#ifndef CONFIG_NOPRINTF_FIELDWIDTH -static void prejustify(FAR struct lib_outstream_s *obj, uint8_t fmt, - uint8_t flags, int fieldwidth, int valwidth); -static void postjustify(FAR struct lib_outstream_s *obj, uint8_t fmt, - uint8_t flags, int fieldwidth, int valwidth); -#endif - -/**************************************************************************** - * Global Constant Data - ****************************************************************************/ - -/**************************************************************************** - * Global Variables - ****************************************************************************/ - -/**************************************************************************** - * Private Constant Data - ****************************************************************************/ - -static const char g_nullstring[] = "(null)"; - -/**************************************************************************** - * Private Variables - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/* Include floating point functions */ - -#ifdef CONFIG_LIBC_FLOATINGPOINT -# include "stdio/lib_libdtoa.c" -#endif - -/**************************************************************************** - * Name: ptohex - ****************************************************************************/ - -#ifdef CONFIG_PTR_IS_NOT_INT -static void ptohex(FAR struct lib_outstream_s *obj, uint8_t flags, FAR void *p) -{ - union - { - uint32_t dw; - FAR void *p; - } u; - uint8_t bits; - - /* Check for alternate form */ - - if (IS_ALTFORM(flags)) - { - /* Prefix the number with "0x" */ - - obj->put(obj, '0'); - obj->put(obj, 'x'); - } - - u.dw = 0; - u.p = p; - - for (bits = 8*sizeof(void *); bits > 0; bits -= 4) - { - uint8_t nibble = (uint8_t)((u.dw >> (bits - 4)) & 0xf); - if (nibble < 10) - { - obj->put(obj, nibble + '0'); - } - else - { - obj->put(obj, nibble + 'a' - 10); - } - } -} - -/**************************************************************************** - * Name: getpsize - ****************************************************************************/ - -#ifndef CONFIG_NOPRINTF_FIELDWIDTH -static int getpsize(uint8_t flags, FAR void *p) -{ - struct lib_outstream_s nulloutstream; - lib_nulloutstream(&nulloutstream); - - ptohex(&nulloutstream, flags, p); - return nulloutstream.nput; -} - -#endif /* CONFIG_NOPRINTF_FIELDWIDTH */ -#endif /* CONFIG_PTR_IS_NOT_INT */ - -/**************************************************************************** - * Name: utodec - ****************************************************************************/ - -static void utodec(FAR struct lib_outstream_s *obj, unsigned int n) -{ - unsigned int remainder = n % 10; - unsigned int dividend = n / 10; - - if (dividend) - { - utodec(obj, dividend); - } - - obj->put(obj, (remainder + (unsigned int)'0')); -} - -/**************************************************************************** - * Name: utohex - ****************************************************************************/ - -static void utohex(FAR struct lib_outstream_s *obj, unsigned int n, uint8_t a) -{ - bool nonzero = false; - uint8_t bits; - - for (bits = 8*sizeof(unsigned int); bits > 0; bits -= 4) - { - uint8_t nibble = (uint8_t)((n >> (bits - 4)) & 0xf); - if (nibble || nonzero) - { - nonzero = true; - - if (nibble < 10) - { - obj->put(obj, nibble + '0'); - } - else - { - obj->put(obj, nibble + a - 10); - } - } - } - - if (!nonzero) - { - obj->put(obj, '0'); - } -} - -/**************************************************************************** - * Name: utooct - ****************************************************************************/ - -static void utooct(FAR struct lib_outstream_s *obj, unsigned int n) -{ - unsigned int remainder = n & 0x7; - unsigned int dividend = n >> 3; - - if (dividend) - { - utooct(obj, dividend); - } - - obj->put(obj, (remainder + (unsigned int)'0')); -} - -/**************************************************************************** - * Name: utobin - ****************************************************************************/ - -static void utobin(FAR struct lib_outstream_s *obj, unsigned int n) -{ - unsigned int remainder = n & 1; - unsigned int dividend = n >> 1; - - if (dividend) - { - utobin(obj, dividend); - } - - obj->put(obj, (remainder + (unsigned int)'0')); -} - -/**************************************************************************** - * Name: utoascii - ****************************************************************************/ - -static void utoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, uint8_t flags, unsigned int n) -{ - /* Perform the integer conversion according to the format specifier */ - - switch (fmt) - { - case 'd': - case 'i': - /* Signed base 10 */ - { -#ifdef CONFIG_NOPRINTF_FIELDWIDTH - if ((int)n < 0) - { - obj->put(obj, '-'); - n = (unsigned int)(-(int)n); - } - else if (IS_SHOWPLUS(flags)) - { - obj->put(obj, '+'); - } -#endif - /* Convert the unsigned value to a string. */ - - utodec(obj, n); - } - break; - - case 'u': - /* Unigned base 10 */ - { -#ifdef CONFIG_NOPRINTF_FIELDWIDTH - if (IS_SHOWPLUS(flags)) - { - obj->put(obj, '+'); - } -#endif - /* Convert the unsigned value to a string. */ - - utodec(obj, n); - } - break; - -#ifndef CONFIG_PTR_IS_NOT_INT - case 'p': -#endif - case 'x': - case 'X': - /* Hexadecimal */ - { - /* Check for alternate form */ - - if (IS_ALTFORM(flags)) - { - /* Prefix the number with "0x" */ - - obj->put(obj, '0'); - obj->put(obj, 'x'); - } - - /* Convert the unsigned value to a string. */ - - if (fmt == 'X') - { - utohex(obj, n, 'A'); - } - else - { - utohex(obj, n, 'a'); - } - } - break; - - case 'o': - /* Octal */ - { - /* Check for alternate form */ - - if (IS_ALTFORM(flags)) - { - /* Prefix the number with '0' */ - - obj->put(obj, '0'); - } - - /* Convert the unsigned value to a string. */ - - utooct(obj, n); - } - break; - - case 'b': - /* Binary */ - { - /* Convert the unsigned value to a string. */ - - utobin(obj, n); - } - break; - -#ifdef CONFIG_PTR_IS_NOT_INT - case 'p': -#endif - default: - break; - } -} - -/**************************************************************************** - * Name: fixup - ****************************************************************************/ - -#ifndef CONFIG_NOPRINTF_FIELDWIDTH -static void fixup(uint8_t fmt, FAR uint8_t *flags, FAR int *n) -{ - /* Perform the integer conversion according to the format specifier */ - - switch (fmt) - { - case 'd': - case 'i': - /* Signed base 10 */ - - if (*n < 0) - { - SET_NEGATE(*flags); - CLR_SHOWPLUS(*flags); - *n = -*n; - } - break; - - case 'u': - /* Unsigned base 10 */ - break; - - case 'p': - case 'x': - case 'X': - /* Hexadecimal */ - case 'o': - /* Octal */ - case 'b': - /* Binary */ - CLR_SIGNED(*flags); - break; - - default: - break; - } -} - -/**************************************************************************** - * Name: getusize - ****************************************************************************/ - -static int getusize(uint8_t fmt, uint8_t flags, unsigned int n) -{ - struct lib_outstream_s nulloutstream; - lib_nulloutstream(&nulloutstream); - - utoascii(&nulloutstream, fmt, flags, n); - return nulloutstream.nput; -} - -/**************************************************************************** - * Name: getdblsize - ****************************************************************************/ - -#ifdef CONFIG_LIBC_FLOATINGPOINT -static int getdblsize(uint8_t fmt, int trunc, uint8_t flags, double n) -{ - struct lib_outstream_s nulloutstream; - lib_nulloutstream(&nulloutstream); - - lib_dtoa(&nulloutstream, fmt, trunc, flags, n); - return nulloutstream.nput; -} -#endif -#endif /* CONFIG_NOPRINTF_FIELDWIDTH */ - -#ifdef CONFIG_LONG_IS_NOT_INT -/**************************************************************************** - * Name: lutodec - ****************************************************************************/ - -static void lutodec(FAR struct lib_outstream_s *obj, unsigned long n) -{ - unsigned int remainder = n % 10; - unsigned long dividend = n / 10; - - if (dividend) - { - lutodec(obj, dividend); - } - - obj->put(obj, (remainder + (unsigned int)'0')); -} - -/**************************************************************************** - * Name: lutohex - ****************************************************************************/ - -static void lutohex(FAR struct lib_outstream_s *obj, unsigned long n, uint8_t a) -{ - bool nonzero = false; - uint8_t bits; - - for (bits = 8*sizeof(unsigned long); bits > 0; bits -= 4) - { - uint8_t nibble = (uint8_t)((n >> (bits - 4)) & 0xf); - if (nibble || nonzero) - { - nonzero = true; - - if (nibble < 10) - { - obj->put(obj, nibble + '0'); - } - else - { - obj->put(obj, nibble + a - 10); - } - } - } - - if (!nonzero) - { - obj->put(obj, '0'); - } -} - -/**************************************************************************** - * Name: lutooct - ****************************************************************************/ - -static void lutooct(FAR struct lib_outstream_s *obj, unsigned long n) -{ - unsigned int remainder = n & 0x7; - unsigned long dividend = n >> 3; - - if (dividend) - { - lutooct(obj, dividend); - } - - obj->put(obj, (remainder + (unsigned int)'0')); -} - -/**************************************************************************** - * Name: lutobin - ****************************************************************************/ - -static void lutobin(FAR struct lib_outstream_s *obj, unsigned long n) -{ - unsigned int remainder = n & 1; - unsigned long dividend = n >> 1; - - if (dividend) - { - lutobin(obj, dividend); - } - - obj->put(obj, (remainder + (unsigned int)'0')); -} - -/**************************************************************************** - * Name: lutoascii - ****************************************************************************/ - -static void lutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, uint8_t flags, unsigned long ln) -{ - /* Perform the integer conversion according to the format specifier */ - - switch (fmt) - { - case 'd': - case 'i': - /* Signed base 10 */ - { -#ifdef CONFIG_NOPRINTF_FIELDWIDTH - if ((long)ln < 0) - { - obj->put(obj, '-'); - ln = (unsigned long)(-(long)ln); - } - else if (IS_SHOWPLUS(flags)) - { - obj->put(obj, '+'); - } -#endif - /* Convert the unsigned value to a string. */ - - lutodec(obj, ln); - } - break; - - case 'u': - /* Unigned base 10 */ - { -#ifdef CONFIG_NOPRINTF_FIELDWIDTH - if (IS_SHOWPLUS(flags)) - { - obj->put(obj, '+'); - } -#endif - /* Convert the unsigned value to a string. */ - - lutodec(obj, ln); - } - break; - - case 'x': - case 'X': - /* Hexadecimal */ - { - /* Check for alternate form */ - - if (IS_ALTFORM(flags)) - { - /* Prefix the number with "0x" */ - - obj->put(obj, '0'); - obj->put(obj, 'x'); - } - - /* Convert the unsigned value to a string. */ - - if (fmt == 'X') - { - lutohex(obj, ln, 'A'); - } - else - { - lutohex(obj, ln, 'a'); - } - } - break; - - case 'o': - /* Octal */ - { - /* Check for alternate form */ - - if (IS_ALTFORM(flags)) - { - /* Prefix the number with '0' */ - - obj->put(obj, '0'); - } - - /* Convert the unsigned value to a string. */ - - lutooct(obj, ln); - } - break; - - case 'b': - /* Binary */ - { - /* Convert the unsigned value to a string. */ - - lutobin(obj, ln); - } - break; - - case 'p': - default: - break; - } -} - -/**************************************************************************** - * Name: lfixup - ****************************************************************************/ - -#ifndef CONFIG_NOPRINTF_FIELDWIDTH -static void lfixup(uint8_t fmt, FAR uint8_t *flags, FAR long *ln) -{ - /* Perform the integer conversion according to the format specifier */ - - switch (fmt) - { - case 'd': - case 'i': - /* Signed base 10 */ - - if (*ln < 0) - { - SET_NEGATE(*flags); - CLR_SHOWPLUS(*flags); - *ln = -*ln; - } - break; - - case 'u': - /* Unsigned base 10 */ - break; - - case 'p': - case 'x': - case 'X': - /* Hexadecimal */ - case 'o': - /* Octal */ - case 'b': - /* Binary */ - CLR_SIGNED(*flags); - break; - - default: - break; - } -} - -/**************************************************************************** - * Name: getlusize - ****************************************************************************/ - -static int getlusize(uint8_t fmt, uint8_t flags, unsigned long ln) -{ - struct lib_outstream_s nulloutstream; - lib_nulloutstream(&nulloutstream); - - lutoascii(&nulloutstream, fmt, flags, ln); - return nulloutstream.nput; -} - -#endif /* CONFIG_NOPRINTF_FIELDWIDTH */ -#endif /* CONFIG_LONG_IS_NOT_INT */ - -#ifdef CONFIG_HAVE_LONG_LONG -/**************************************************************************** - * Name: llutodec - ****************************************************************************/ - -static void llutodec(FAR struct lib_outstream_s *obj, unsigned long long n) -{ - unsigned int remainder = n % 10; - unsigned long long dividend = n / 10; - - if (dividend) - { - llutodec(obj, dividend); - } - - obj->put(obj, (remainder + (unsigned int)'0')); -} - -/**************************************************************************** - * Name: llutohex - ****************************************************************************/ - -static void llutohex(FAR struct lib_outstream_s *obj, unsigned long long n, uint8_t a) -{ - bool nonzero = false; - uint8_t bits; - - for (bits = 8*sizeof(unsigned long long); bits > 0; bits -= 4) - { - uint8_t nibble = (uint8_t)((n >> (bits - 4)) & 0xf); - if (nibble || nonzero) - { - nonzero = true; - - if (nibble < 10) - { - obj->put(obj, (nibble + '0')); - } - else - { - obj->put(obj, (nibble + a - 10)); - } - } - } - - if (!nonzero) - { - obj->put(obj, '0'); - } -} - -/**************************************************************************** - * Name: llutooct - ****************************************************************************/ - -static void llutooct(FAR struct lib_outstream_s *obj, unsigned long long n) -{ - unsigned int remainder = n & 0x7; - unsigned long long dividend = n >> 3; - - if (dividend) - { - llutooct(obj, dividend); - } - - obj->put(obj, (remainder + (unsigned int)'0')); -} - -/**************************************************************************** - * Name: llutobin - ****************************************************************************/ - -static void llutobin(FAR struct lib_outstream_s *obj, unsigned long long n) -{ - unsigned int remainder = n & 1; - unsigned long long dividend = n >> 1; - - if (dividend) - { - llutobin(obj, dividend); - } - - obj->put(obj, (remainder + (unsigned int)'0')); -} - -/**************************************************************************** - * Name: llutoascii - ****************************************************************************/ - -static void llutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, uint8_t flags, unsigned long long lln) -{ - /* Perform the integer conversion according to the format specifier */ - - switch (fmt) - { - case 'd': - case 'i': - /* Signed base 10 */ - { -#ifdef CONFIG_NOPRINTF_FIELDWIDTH - if ((long long)lln < 0) - { - obj->put(obj, '-'); - lln = (unsigned long long)(-(long long)lln); - } - else if (IS_SHOWPLUS(flags)) - { - obj->put(obj, '+'); - } -#endif - /* Convert the unsigned value to a string. */ - - llutodec(obj, (unsigned long long)lln); - } - break; - - case 'u': - /* Unigned base 10 */ - { -#ifdef CONFIG_NOPRINTF_FIELDWIDTH - if (IS_SHOWPLUS(flags)) - { - obj->put(obj, '+'); - } -#endif - /* Convert the unsigned value to a string. */ - - llutodec(obj, (unsigned long long)lln); - } - break; - - case 'x': - case 'X': - /* Hexadecimal */ - { - /* Check for alternate form */ - - if (IS_ALTFORM(flags)) - { - /* Prefix the number with "0x" */ - - obj->put(obj, '0'); - obj->put(obj, 'x'); - } - - /* Convert the unsigned value to a string. */ - - if (fmt == 'X') - { - llutohex(obj, (unsigned long long)lln, 'A'); - } - else - { - llutohex(obj, (unsigned long long)lln, 'a'); - } - } - break; - - case 'o': - /* Octal */ - { - /* Check for alternate form */ - - if (IS_ALTFORM(flags)) - { - /* Prefix the number with '0' */ - - obj->put(obj, '0'); - } - - /* Convert the unsigned value to a string. */ - - llutooct(obj, (unsigned long long)lln); - } - break; - - case 'b': - /* Binary */ - { - /* Convert the unsigned value to a string. */ - - llutobin(obj, (unsigned long long)lln); - } - break; - - case 'p': - default: - break; - } -} - -/**************************************************************************** - * Name: llfixup - ****************************************************************************/ - -#ifndef CONFIG_NOPRINTF_FIELDWIDTH -static void llfixup(uint8_t fmt, FAR uint8_t *flags, FAR long long *lln) -{ - /* Perform the integer conversion according to the format specifier */ - - switch (fmt) - { - case 'd': - case 'i': - /* Signed base 10 */ - - if (*lln < 0) - { - SET_NEGATE(*flags); - CLR_SHOWPLUS(*flags); - *lln = -*lln; - } - break; - - case 'u': - /* Unsigned base 10 */ - break; - - case 'p': - case 'x': - case 'X': - /* Hexadecimal */ - case 'o': - /* Octal */ - case 'b': - /* Binary */ - CLR_SIGNED(*flags); - break; - - default: - break; - } -} - -/**************************************************************************** - * Name: getllusize - ****************************************************************************/ - -static int getllusize(uint8_t fmt, uint8_t flags, unsigned long long lln) -{ - struct lib_outstream_s nulloutstream; - lib_nulloutstream(&nulloutstream); - - - llutoascii(&nulloutstream, fmt, flags, lln); - return nulloutstream.nput; -} - -#endif /* CONFIG_NOPRINTF_FIELDWIDTH */ -#endif /* CONFIG_HAVE_LONG_LONG */ - -/**************************************************************************** - * Name: prejustify - ****************************************************************************/ - -#ifndef CONFIG_NOPRINTF_FIELDWIDTH -static void prejustify(FAR struct lib_outstream_s *obj, uint8_t fmt, - uint8_t flags, int fieldwidth, int valwidth) -{ - int i; - - switch (fmt) - { - default: - case FMT_RJUST: - if (IS_SIGNED(flags)) - { - valwidth++; - } - - for (i = fieldwidth - valwidth; i > 0; i--) - { - obj->put(obj, ' '); - } - - if (IS_NEGATE(flags)) - { - obj->put(obj, '-'); - } - else if (IS_SHOWPLUS(flags)) - { - obj->put(obj, '+'); - } - break; - - case FMT_RJUST0: - if (IS_NEGATE(flags)) - { - obj->put(obj, '-'); - valwidth++; - } - else if (IS_SHOWPLUS(flags)) - { - obj->put(obj, '+'); - valwidth++; - } - - for (i = fieldwidth - valwidth; i > 0; i--) - { - obj->put(obj, '0'); - } - break; - - case FMT_LJUST: - if (IS_NEGATE(flags)) - { - obj->put(obj, '-'); - } - else if (IS_SHOWPLUS(flags)) - { - obj->put(obj, '+'); - } - break; - } -} -#endif - -/**************************************************************************** - * Name: postjustify - ****************************************************************************/ - -#ifndef CONFIG_NOPRINTF_FIELDWIDTH -static void postjustify(FAR struct lib_outstream_s *obj, uint8_t fmt, - uint8_t flags, int fieldwidth, int valwidth) -{ - int i; - - /* Apply field justification to the integer value. */ - - switch (fmt) - { - default: - case FMT_RJUST: - case FMT_RJUST0: - break; - - case FMT_LJUST: - if (IS_SIGNED(flags)) - { - valwidth++; - } - - for (i = fieldwidth - valwidth; i > 0; i--) - { - obj->put(obj, ' '); - } - break; - } -} -#endif - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * libc/stdio/lib_vsprintf - ****************************************************************************/ - -int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list ap) -{ - FAR char *ptmp; -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - int width; -#ifdef CONFIG_LIBC_FLOATINGPOINT - int trunc; -#endif - uint8_t fmt; -#endif - uint8_t flags; -#ifdef CONFIG_ARCH_ROMGETC - char ch; -#endif - - for (FMT_TOP; FMT_CHAR; FMT_BOTTOM) - { - /* Just copy regular characters */ - - if (FMT_CHAR != '%') - { - /* Output the character */ - - obj->put(obj, FMT_CHAR); - - /* Flush the buffer if a newline is encountered */ - -#ifdef CONFIG_STDIO_LINEBUFFER - if (FMT_CHAR == '\n') - { - /* Should return an error on a failure to flush */ - - (void)obj->flush(obj); - } -#endif - /* Process the next character in the format */ - - continue; - } - - /* We have found a format specifier. Move past it. */ - - FMT_NEXT; - - /* Assume defaults */ - - flags = 0; -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - fmt = FMT_RJUST; - width = 0; -#ifdef CONFIG_LIBC_FLOATINGPOINT - trunc = 6; -#endif -#endif - - /* Process each format qualifier. */ - - for (; FMT_CHAR; FMT_BOTTOM) - { - /* Break out of the loop when the format is known. */ - - if (strchr("diuxXpobeEfgGlLsc%", FMT_CHAR)) - { - break; - } - - /* Check for left justification. */ - - else if (FMT_CHAR == '-') - { -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - fmt = FMT_LJUST; -#endif - } - - /* Check for leading zero fill right justification. */ - - else if (FMT_CHAR == '0') - { -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - fmt = FMT_RJUST0; -#ifdef CONFIG_LIBC_FLOATINGPOINT - if (IS_HASDOT(flags)) { - trunc = 0; - } -#endif -#endif - } -#if 0 - /* Center justification. */ - - else if (FMT_CHAR == '~') - { -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - fmt = FMT_CENTER; -#endif - } -#endif - - else if (FMT_CHAR == '*') - { -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - int value = va_arg(ap, int); - if (IS_HASDOT(flags)) - { -#ifdef CONFIG_LIBC_FLOATINGPOINT - trunc = value; - SET_HASASTERISKTRUNC(flags); -#endif - } - else - { - width = value; - SET_HASASTERISKWIDTH(flags); - } -#endif - } - - /* Check for field width */ - - else if (FMT_CHAR >= '1' && FMT_CHAR <= '9') - { -#ifdef CONFIG_NOPRINTF_FIELDWIDTH - do - { - FMT_NEXT; - } - while (FMT_CHAR >= '0' && FMT_CHAR <= '9'); -#else - /* Accumulate the field width integer. */ - - int n = ((int)(FMT_CHAR)) - (int)'0'; - for (;;) - { - FMT_NEXT; - if (FMT_CHAR >= '0' && FMT_CHAR <= '9') - { - n = 10*n + (((int)(FMT_CHAR)) - (int)'0'); - } - else - { - break; - } - } - - if (IS_HASDOT(flags)) - { -#ifdef CONFIG_LIBC_FLOATINGPOINT - trunc = n; -#endif - } - else - { - width = n; - } -#endif - /* Back up to the last digit. */ - - FMT_PREV; - } - - /* Check for a decimal point. */ - - else if (FMT_CHAR == '.') - { -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - SET_HASDOT(flags); -#endif - } - - /* Check for leading plus sign. */ - - else if (FMT_CHAR == '+') - { - SET_SHOWPLUS(flags); - } - - /* Check for alternate form. */ - - else if (FMT_CHAR == '#') - { - SET_ALTFORM(flags); - } - } - - /* "%%" means that a literal '%' was intended (instead of a format - * specification). - */ - - if (FMT_CHAR == '%') - { - obj->put(obj, '%'); - continue; - } - - /* Check for the string format. */ - - if (FMT_CHAR == 's') - { -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - int swidth; -#endif - /* Get the string to output */ - - ptmp = va_arg(ap, char *); - if (!ptmp) - { - ptmp = (char*)g_nullstring; - } - - /* Get the widith of the string and perform right-justification - * operations. - */ - -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - swidth = strlen(ptmp); - prejustify(obj, fmt, 0, width, swidth); -#endif - /* Concatenate the string into the output */ - - while (*ptmp) - { - obj->put(obj, *ptmp); - ptmp++; - } - - /* Perform left-justification operations. */ - -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - postjustify(obj, fmt, 0, width, swidth); -#endif - continue; - } - - /* Check for the character output */ - - else if (FMT_CHAR == 'c') - { - /* Just copy the character into the output. */ - - int n = va_arg(ap, int); - obj->put(obj, n); - continue; - } - - /* Check for the long long prefix. */ - - if (FMT_CHAR == 'L') - { - SET_LONGLONGPRECISION(flags); - FMT_NEXT; - } - else if (FMT_CHAR == 'l') - { - SET_LONGPRECISION(flags); - FMT_NEXT; - if (FMT_CHAR == 'l') - { - SET_LONGLONGPRECISION(flags); - FMT_NEXT; - } - } - - /* Handle integer conversions */ - - if (strchr("diuxXpob", FMT_CHAR)) - { -#ifdef CONFIG_HAVE_LONG_LONG - if (IS_LONGLONGPRECISION(flags) && FMT_CHAR != 'p') - { - long long lln; -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - int lluwidth; -#endif - /* Extract the long long value. */ - - lln = va_arg(ap, long long); - -#ifdef CONFIG_NOPRINTF_FIELDWIDTH - /* Output the number */ - - llutoascii(obj, FMT_CHAR, flags, (unsigned long long)lln); -#else - /* Resolve sign-ness and format issues */ - - llfixup(FMT_CHAR, &flags, &lln); - - /* Get the width of the output */ - - lluwidth = getllusize(FMT_CHAR, flags, lln); - - /* Perform left field justification actions */ - - prejustify(obj, fmt, flags, width, lluwidth); - - /* Output the number */ - - llutoascii(obj, FMT_CHAR, flags, (unsigned long long)lln); - - /* Perform right field justification actions */ - - postjustify(obj, fmt, flags, width, lluwidth); -#endif - } - else -#endif /* CONFIG_HAVE_LONG_LONG */ -#ifdef CONFIG_LONG_IS_NOT_INT - if (IS_LONGPRECISION(flags) && FMT_CHAR != 'p') - { - long ln; -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - int luwidth; -#endif - /* Extract the long value. */ - - ln = va_arg(ap, long); - -#ifdef CONFIG_NOPRINTF_FIELDWIDTH - /* Output the number */ - - lutoascii(obj, FMT_CHAR, flags, (unsigned long)ln); -#else - /* Resolve sign-ness and format issues */ - - lfixup(FMT_CHAR, &flags, &ln); - - /* Get the width of the output */ - - luwidth = getlusize(FMT_CHAR, flags, ln); - - /* Perform left field justification actions */ - - prejustify(obj, fmt, flags, width, luwidth); - - /* Output the number */ - - lutoascii(obj, FMT_CHAR, flags, (unsigned long)ln); - - /* Perform right field justification actions */ - - postjustify(obj, fmt, flags, width, luwidth); -#endif - } - else -#endif /* CONFIG_LONG_IS_NOT_INT */ -#ifdef CONFIG_PTR_IS_NOT_INT - if (FMT_CHAR == 'p') - { - void *p; -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - int pwidth; -#endif - /* Extract the integer value. */ - - p = va_arg(ap, void *); - -#ifdef CONFIG_NOPRINTF_FIELDWIDTH - /* Output the pointer value */ - - ptohex(obj, flags, p); -#else - /* Resolve sign-ness and format issues */ - - lfixup(FMT_CHAR, &flags, &ln); - - /* Get the width of the output */ - - luwidth = getpsize(FMT_CHAR, flags, p); - - /* Perform left field justification actions */ - - prejustify(obj, fmt, flags, width, pwidth); - - /* Output the pointer value */ - - ptohex(obj, flags, p); - - /* Perform right field justification actions */ - - postjustify(obj, fmt, flags, width, pwidth); -#endif - } - else -#endif - { - int n; -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - int uwidth; -#endif - /* Extract the long long value. */ - - n = va_arg(ap, int); - -#ifdef CONFIG_NOPRINTF_FIELDWIDTH - /* Output the number */ - - utoascii(obj, FMT_CHAR, flags, (unsigned int)n); -#else - /* Resolve sign-ness and format issues */ - - fixup(FMT_CHAR, &flags, &n); - - /* Get the width of the output */ - - uwidth = getusize(FMT_CHAR, flags, n); - - /* Perform left field justification actions */ - - prejustify(obj, fmt, flags, width, uwidth); - - /* Output the number */ - - utoascii(obj, FMT_CHAR, flags, (unsigned int)n); - - /* Perform right field justification actions */ - - postjustify(obj, fmt, flags, width, uwidth); -#endif - } - } - - /* Handle floating point conversions */ - -#ifdef CONFIG_LIBC_FLOATINGPOINT - else if (strchr("eEfgG", FMT_CHAR)) - { -#ifndef CONFIG_NOPRINTF_FIELDWIDTH - double dblval = va_arg(ap, double); - int dblsize; - - /* Get the width of the output */ - - dblsize = getdblsize(FMT_CHAR, trunc, flags, dblval); - - /* Perform left field justification actions */ - - prejustify(obj, fmt, 0, width, dblsize); - - /* Output the number */ - - lib_dtoa(obj, FMT_CHAR, trunc, flags, dblval); - - /* Perform right field justification actions */ - - postjustify(obj, fmt, 0, width, dblsize); -#else - /* Output the number with a fixed precision */ - - double dblval = va_arg(ap, double); - lib_dtoa(obj, FMT_CHAR, CONFIG_LIBC_FIXEDPRECISION, flags, dblval); -#endif - } -#endif /* CONFIG_LIBC_FLOATINGPOINT */ - } - - return obj->nput; -} - - |