summaryrefslogtreecommitdiff
path: root/platform/utilities
diff options
context:
space:
mode:
authorStefan Agner <stefan.agner@toradex.com>2016-01-12 14:06:54 -0800
committerStefan Agner <stefan.agner@toradex.com>2016-01-12 14:06:54 -0800
commita57cc2c988482010061b9e68344fdf1969889763 (patch)
tree5c050337492ce27c09b47421b123980b5a79f8d9 /platform/utilities
initial commit, FreeRTOS_BSP_1.0.0_iMX7D
Diffstat (limited to 'platform/utilities')
-rw-r--r--platform/utilities/inc/debug_console_imx.h152
-rw-r--r--platform/utilities/src/debug_console_imx.c384
-rw-r--r--platform/utilities/src/print_scan.c1307
-rw-r--r--platform/utilities/src/print_scan.h91
4 files changed, 1934 insertions, 0 deletions
diff --git a/platform/utilities/inc/debug_console_imx.h b/platform/utilities/inc/debug_console_imx.h
new file mode 100644
index 0000000..bb14a67
--- /dev/null
+++ b/platform/utilities/inc/debug_console_imx.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o 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.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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 __DEBUG_CONSOLE_IMX_H__
+#define __DEBUG_CONSOLE_IMX_H__
+
+#include <stdint.h>
+#include "device_imx.h"
+
+/*!
+ * @addtogroup debug_console
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+#define IO_MAXLINE 20
+
+/*! @brief Configuration for toolchain's printf/scanf or Freescale version printf/scanf */
+#define PRINTF debug_printf
+//#define PRINTF printf
+#define SCANF debug_scanf
+//#define SCANF scanf
+#define PUTCHAR debug_putchar
+//#define PUTCHAR putchar
+#define GETCHAR debug_getchar
+//#define GETCHAR getchar
+
+/*! @brief Error code for the debug console driver. */
+typedef enum _debug_console_status {
+ status_DEBUGCONSOLE_Success = 0U,
+ status_DEBUGCONSOLE_InvalidDevice,
+ status_DEBUGCONSOLE_AllocateMemoryFailed,
+ status_DEBUGCONSOLE_Failed
+} debug_console_status_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * @name Initialization
+ * @{
+ */
+
+/*!
+ * @brief Init the UART_IMX used for debug messages.
+ *
+ * Call this function to enable debug log messages to be output via the specified UART_IMX
+ * base address and at the specified baud rate. Just initializes the UART_IMX to the given baud
+ * rate and 8N1. After this function has returned, stdout and stdin will be connected to the
+ * selected UART_IMX. The debug_printf() function also uses this UART_IMX.
+ *
+ * @param base Which UART_IMX instance is used to send debug messages.
+ * @param clockRate The input clock of UART_IMX module.
+ * @param baudRate The desired baud rate in bits per second.
+ * @return Whether initialization was successful or not.
+ */
+debug_console_status_t DbgConsole_Init(UART_Type* base,
+ uint32_t clockRate,
+ uint32_t baudRate);
+
+/*!
+ * @brief Deinit the UART/LPUART used for debug messages.
+ *
+ * Call this function to disable debug log messages to be output via the specified UART/LPUART
+ * base address and at the specified baud rate.
+ * @return Whether de-initialization was successful or not.
+ */
+debug_console_status_t DbgConsole_DeInit(void);
+
+/*!
+ * @brief Prints formatted output to the standard output stream.
+ *
+ * Call this function to print formatted output to the standard output stream.
+ *
+ * @param fmt_s Format control string.
+ * @return Returns the number of characters printed, or a negative value if an error occurs.
+ */
+int debug_printf(const char *fmt_s, ...);
+
+/*!
+ * @brief Writes a character to stdout.
+ *
+ * Call this function to write a character to stdout.
+ *
+ * @param ch Character to be written.
+ * @return Returns the character written.
+ */
+int debug_putchar(int ch);
+
+/*!
+ * @brief Reads formatted data from the standard input stream.
+ *
+ * Call this function to read formatted data from the standard input stream.
+ *
+ * @param fmt_ptr Format control string.
+ * @return Returns the number of fields successfully converted and assigned.
+ */
+int debug_scanf(const char *fmt_ptr, ...);
+
+/*!
+ * @brief Reads a character from standard input.
+ *
+ * Call this function to read a character from standard input.
+ *
+ * @return Returns the character read.
+ */
+int debug_getchar(void);
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*! @}*/
+
+#endif /* __DEBUG_CONSOLE_IMX_H__ */
+/*******************************************************************************
+ * EOF
+ ******************************************************************************/
diff --git a/platform/utilities/src/debug_console_imx.c b/platform/utilities/src/debug_console_imx.c
new file mode 100644
index 0000000..edc35ae
--- /dev/null
+++ b/platform/utilities/src/debug_console_imx.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o 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.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
+ */
+
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "device_imx.h"
+#include "debug_console_imx.h"
+#include "uart_imx.h"
+#include "print_scan.h"
+
+#if __ICCARM__
+#include <yfuns.h>
+#endif
+
+static int debug_putc(int ch, void* stream);
+static void UART_SendDataPolling(void *base, const uint8_t *txBuff, uint32_t txSize);
+static void UART_ReceiveDataPolling(void *base, uint8_t *rxBuff, uint32_t rxSize);
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief Operation functions definitions for debug console. */
+typedef struct DebugConsoleOperationFunctions {
+ void (* Send)(void *base, const uint8_t *buf, uint32_t count);
+ void (* Receive)(void *base, uint8_t *buf, uint32_t count);
+} debug_console_ops_t;
+
+/*! @brief State structure storing debug console. */
+typedef struct DebugConsoleState {
+ bool inited; /*<! Identify debug console inited or not. */
+ void* base; /*<! Base of the IP register. */
+ debug_console_ops_t ops; /*<! Operation function pointers for debug uart operations. */
+} debug_console_state_t;
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+/*! @brief Debug UART state information.*/
+static debug_console_state_t s_debugConsole;
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+/* See fsl_debug_console_imx.h for documentation of this function.*/
+debug_console_status_t DbgConsole_Init(UART_Type* base,
+ uint32_t clockRate,
+ uint32_t baudRate)
+{
+ if (s_debugConsole.inited)
+ {
+ return status_DEBUGCONSOLE_Failed;
+ }
+
+ s_debugConsole.base = base;
+ /* Setup UART init structure. */
+ uart_init_config_t uart_init_str = {.clockRate = clockRate,
+ .baudRate = baudRate,
+ .wordLength = uartWordLength8Bits,
+ .stopBitNum = uartStopBitNumOne,
+ .parity = uartParityDisable,
+ .direction = uartDirectionTxRx};
+ /* UART Init operation */
+ UART_Init(s_debugConsole.base, &uart_init_str);
+ UART_Enable(s_debugConsole.base);
+ /* Set the function pointer for send and receive for this kind of device. */
+ s_debugConsole.ops.Send = UART_SendDataPolling;
+ s_debugConsole.ops.Receive = UART_ReceiveDataPolling;
+
+ s_debugConsole.inited = true;
+ return status_DEBUGCONSOLE_Success;
+}
+
+/* See fsl_debug_console.h for documentation of this function.*/
+debug_console_status_t DbgConsole_DeInit(void)
+{
+ if (!s_debugConsole.inited)
+ {
+ return status_DEBUGCONSOLE_Success;
+ }
+
+ /* UART Deinit operation */
+ UART_Disable(s_debugConsole.base);
+ UART_Deinit(s_debugConsole.base);
+
+ s_debugConsole.inited = false;
+
+ return status_DEBUGCONSOLE_Success;
+}
+
+#if __ICCARM__
+#pragma weak __write
+size_t __write(int handle, const unsigned char * buffer, size_t size)
+{
+ if (buffer == 0)
+ {
+ /* This means that we should flush internal buffers. Since we*/
+ /* don't we just return. (Remember, "handle" == -1 means that all*/
+ /* handles should be flushed.)*/
+ return 0;
+ }
+
+ /* This function only writes to "standard out" and "standard err",*/
+ /* for all other file handles it returns failure.*/
+ if ((handle != _LLIO_STDOUT) && (handle != _LLIO_STDERR))
+ {
+ return _LLIO_ERROR;
+ }
+
+ /* Do nothing if the debug uart is not initialized.*/
+ if (!s_debugConsole.inited)
+ {
+ return _LLIO_ERROR;
+ }
+
+ /* Send data.*/
+ s_debugConsole.ops.Send(s_debugConsole.base, (uint8_t const *)buffer, size);
+ return size;
+}
+
+#pragma weak __read
+size_t __read(int handle, unsigned char * buffer, size_t size)
+{
+ /* This function only reads from "standard in", for all other file*/
+ /* handles it returns failure.*/
+ if (handle != _LLIO_STDIN)
+ {
+ return _LLIO_ERROR;
+ }
+
+ /* Do nothing if the debug uart is not initialized.*/
+ if (!s_debugConsole.inited)
+ {
+ return _LLIO_ERROR;
+ }
+
+ /* Receive data.*/
+ s_debugConsole.ops.Receive(s_debugConsole.base, buffer, size);
+
+ return size;
+}
+
+#elif (defined(__GNUC__))
+#pragma weak _write
+int _write (int handle, char *buffer, int size)
+{
+ if (buffer == 0)
+ {
+ /* return -1 if error */
+ return -1;
+ }
+
+ /* This function only writes to "standard out" and "standard err",*/
+ /* for all other file handles it returns failure.*/
+ if ((handle != 1) && (handle != 2))
+ {
+ return -1;
+ }
+
+ /* Do nothing if the debug uart is not initialized.*/
+ if (!s_debugConsole.inited)
+ {
+ return -1;
+ }
+
+ /* Send data.*/
+ s_debugConsole.ops.Send(s_debugConsole.base, (uint8_t *)buffer, size);
+ return size;
+}
+
+#pragma weak _read
+int _read(int handle, char *buffer, int size)
+{
+ /* This function only reads from "standard in", for all other file*/
+ /* handles it returns failure.*/
+ if (handle != 0)
+ {
+ return -1;
+ }
+
+ /* Do nothing if the debug uart is not initialized.*/
+ if (!s_debugConsole.inited)
+ {
+ return -1;
+ }
+
+ /* Receive data.*/
+ s_debugConsole.ops.Receive(s_debugConsole.base, (uint8_t *)buffer, size);
+ return size;
+}
+#elif defined(__CC_ARM)
+struct __FILE
+{
+ int handle;
+ /* Whatever you require here. If the only file you are using is */
+ /* standard output using printf() for debugging, no file handling */
+ /* is required. */
+};
+
+/* FILE is typedef in stdio.h. */
+#pragma weak __stdout
+FILE __stdout;
+FILE __stdin;
+
+#pragma weak fputc
+int fputc(int ch, FILE *f)
+{
+ /* Do nothing if the debug uart is not initialized.*/
+ if (!s_debugConsole.inited)
+ {
+ return -1;
+ }
+
+ /* Send data.*/
+ s_debugConsole.ops.Send(s_debugConsole.base, (const uint8_t*)&ch, 1);
+ return 1;
+}
+
+#pragma weak fgetc
+int fgetc(FILE *f)
+{
+ uint8_t temp;
+ /* Do nothing if the debug uart is not initialized.*/
+ if (!s_debugConsole.inited)
+ {
+ return -1;
+ }
+
+ /* Receive data.*/
+ s_debugConsole.ops.Receive(s_debugConsole.base, &temp, 1);
+ return temp;
+}
+#endif
+
+/*************Code for debug_printf/scanf/assert*******************************/
+int debug_printf(const char *fmt_s, ...)
+{
+ va_list ap;
+ int result;
+ /* Do nothing if the debug uart is not initialized.*/
+ if (!s_debugConsole.inited)
+ {
+ return -1;
+ }
+
+ va_start(ap, fmt_s);
+ result = _doprint(NULL, debug_putc, -1, (char *)fmt_s, ap);
+ va_end(ap);
+
+ return result;
+}
+
+static int debug_putc(int ch, void* stream)
+{
+ const unsigned char c = (unsigned char) ch;
+ /* Do nothing if the debug uart is not initialized.*/
+ if (!s_debugConsole.inited)
+ {
+ return -1;
+ }
+ s_debugConsole.ops.Send(s_debugConsole.base, &c, 1);
+
+ return 0;
+}
+
+int debug_putchar(int ch)
+{
+ /* Do nothing if the debug uart is not initialized.*/
+ if (!s_debugConsole.inited)
+ {
+ return -1;
+ }
+ debug_putc(ch, NULL);
+
+ return 1;
+}
+
+int debug_scanf(const char *fmt_ptr, ...)
+{
+ char temp_buf[IO_MAXLINE];
+ va_list ap;
+ uint32_t i;
+ char result;
+
+ /* Do nothing if the debug uart is not initialized.*/
+ if (!s_debugConsole.inited)
+ {
+ return -1;
+ }
+ va_start(ap, fmt_ptr);
+ temp_buf[0] = '\0';
+
+ for (i = 0; i < IO_MAXLINE; i++)
+ {
+ temp_buf[i] = result = debug_getchar();
+
+ if ((result == '\r') || (result == '\n'))
+ {
+ /* End of Line */
+ if (i == 0)
+ {
+ i = (uint32_t)-1;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ temp_buf[i + 1] = '\0';
+ }
+
+ result = scan_prv(temp_buf, (char *)fmt_ptr, ap);
+ va_end(ap);
+
+ return result;
+}
+
+int debug_getchar(void)
+{
+ unsigned char c;
+
+ /* Do nothing if the debug uart is not initialized.*/
+ if (!s_debugConsole.inited)
+ {
+ return -1;
+ }
+ s_debugConsole.ops.Receive(s_debugConsole.base, &c, 1);
+
+ return c;
+}
+
+void UART_SendDataPolling(void *base, const uint8_t *txBuff, uint32_t txSize)
+{
+ while (txSize--)
+ {
+ UART_Putchar((UART_Type*)base, *txBuff++);
+ while (!UART_GetStatusFlag((UART_Type*)base, uartStatusTxComplete));
+ }
+}
+
+void UART_ReceiveDataPolling(void *base, uint8_t *rxBuff, uint32_t rxSize)
+{
+ while (rxSize--)
+ {
+ while (!UART_GetStatusFlag((UART_Type*)base, uartStatusRxDataReady));
+
+ *rxBuff = UART_Getchar((UART_Type*)base);
+ rxBuff++;
+ }
+}
+
+/*******************************************************************************
+ * EOF
+ ******************************************************************************/
diff --git a/platform/utilities/src/print_scan.c b/platform/utilities/src/print_scan.c
new file mode 100644
index 0000000..01667af
--- /dev/null
+++ b/platform/utilities/src/print_scan.c
@@ -0,0 +1,1307 @@
+ /*********************************************************************
+ * File: print_scan.c
+ * Purpose: Implementation of debug_printf(), debug_scanf() functions.
+ *
+ * This is a modified version of the file printf.c, which was distributed
+ * by Motorola as part of the M5407C3BOOT.zip package used to initialize
+ * the M5407C3 evaluation board.
+ *
+ * Copyright:
+ * 1999-2000 MOTOROLA, INC. All Rights Reserved.
+ * You are hereby granted a copyright license to use, modify, and
+ * distribute the SOFTWARE so long as this entire notice is
+ * retained without alteration in any modified and/or redistributed
+ * versions, and that such modified versions are clearly identified
+ * as such. No licenses are granted by implication, estoppel or
+ * otherwise under any patents or trademarks of Motorola, Inc. This
+ * software is provided on an "AS IS" basis and without warranty.
+ *
+ * To the maximum extent permitted by applicable law, MOTOROLA
+ * DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+ * PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH REGARD TO THE
+ * SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) AND ANY
+ * ACCOMPANYING WRITTEN MATERIALS.
+ *
+ * To the maximum extent permitted by applicable law, IN NO EVENT
+ * SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING
+ * WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS
+ * INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY
+ * LOSS) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
+ *
+ * Motorola assumes no responsibility for the maintenance and support
+ * of this software
+ ********************************************************************/
+
+#include "print_scan.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <stdbool.h>
+// Keil: suppress ellipsis warning in va_arg usage below
+#if defined(__CC_ARM)
+#pragma diag_suppress 1256
+#endif
+
+#define FLAGS_MINUS (0x01)
+#define FLAGS_PLUS (0x02)
+#define FLAGS_SPACE (0x04)
+#define FLAGS_ZERO (0x08)
+#define FLAGS_POUND (0x10)
+
+#define IS_FLAG_MINUS(a) (a & FLAGS_MINUS)
+#define IS_FLAG_PLUS(a) (a & FLAGS_PLUS)
+#define IS_FLAG_SPACE(a) (a & FLAGS_SPACE)
+#define IS_FLAG_ZERO(a) (a & FLAGS_ZERO)
+#define IS_FLAG_POUND(a) (a & FLAGS_POUND)
+
+#define LENMOD_h (0x01)
+#define LENMOD_l (0x02)
+#define LENMOD_L (0x04)
+#define LENMOD_hh (0x08)
+#define LENMOD_ll (0x10)
+
+#define IS_LENMOD_h(a) (a & LENMOD_h)
+#define IS_LENMOD_hh(a) (a & LENMOD_hh)
+#define IS_LENMOD_l(a) (a & LENMOD_l)
+#define IS_LENMOD_ll(a) (a & LENMOD_ll)
+#define IS_LENMOD_L(a) (a & LENMOD_L)
+
+#define SCAN_SUPPRESS 0x2
+
+#define SCAN_DEST_MASK 0x7c
+#define SCAN_DEST_CHAR 0x4
+#define SCAN_DEST_STRING 0x8
+#define SCAN_DEST_SET 0x10
+#define SCAN_DEST_INT 0x20
+#define SCAN_DEST_FLOAT 0x30
+
+#define SCAN_LENGTH_MASK 0x1f00
+#define SCAN_LENGTH_CHAR 0x100
+#define SCAN_LENGTH_SHORT_INT 0x200
+#define SCAN_LENGTH_LONG_INT 0x400
+#define SCAN_LENGTH_LONG_LONG_INT 0x800
+#define SCAN_LENGTH_LONG_DOUBLE 0x1000
+
+#define SCAN_TYPE_SIGNED 0x2000
+
+/*!
+ * @brief Scanline function which ignores white spaces.
+ *
+ * @param[in] s The address of the string pointer to update.
+ *
+ * @return String without white spaces.
+ */
+static uint32_t scan_ignore_white_space(const char **s);
+
+#if defined(SCANF_FLOAT_ENABLE)
+static double fnum = 0.0;
+#endif
+
+/*!
+ * @brief Converts a radix number to a string and return its length.
+ *
+ * @param[in] numstr Converted string of the number.
+ * @param[in] nump Pointer to the number.
+ * @param[in] neg Polarity of the number.
+ * @param[in] radix The radix to be converted to.
+ * @param[in] use_caps Used to identify %x/X output format.
+
+ * @return Length of the converted string.
+ */
+static int32_t mknumstr (char *numstr, void *nump, int32_t neg, int32_t radix, bool use_caps);
+
+#if defined(PRINTF_FLOAT_ENABLE)
+/*!
+ * @brief Converts a floating radix number to a string and return its length.
+ *
+ * @param[in] numstr Converted string of the number.
+ * @param[in] nump Pointer to the number.
+ * @param[in] radix The radix to be converted to.
+ * @param[in] precision_width Specify the precision width.
+
+ * @return Length of the converted string.
+ */
+static int32_t mkfloatnumstr (char *numstr, void *nump, int32_t radix, uint32_t precision_width);
+#endif
+
+
+static void fput_pad(int32_t c, int32_t curlen, int32_t field_width, int32_t *count, PUTCHAR_FUNC func_ptr, void *farg, int *max_count);
+
+double modf(double input_dbl, double *intpart_ptr);
+
+#if !defined(PRINT_MAX_COUNT)
+#define n_putchar(func, chacter, p, count) func(chacter, p)
+#else
+static int n_putchar(PUTCHAR_FUNC func_ptr, int chacter, void *p, int *max_count)
+{
+ int result = 0;
+ if (*max_count)
+ {
+ result = func_ptr(chacter, p);
+ (*max_count)--;
+ }
+ return result;
+}
+#endif
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : _doprint
+ * Description : This function outputs its parameters according to a
+ * formatted string. I/O is performed by calling given function pointer
+ * using following (*func_ptr)(c,farg);
+ *
+ *END**************************************************************************/
+int _doprint(void *farg, PUTCHAR_FUNC func_ptr, int max_count, char *fmt, va_list ap)
+{
+ /* va_list ap; */
+ char *p;
+ int32_t c;
+
+ char vstr[33];
+ char *vstrp;
+ int32_t vlen;
+
+ int32_t done;
+ int32_t count = 0;
+ int temp_count = max_count;
+
+
+ uint32_t flags_used;
+ uint32_t field_width;
+
+ int32_t ival;
+ int32_t schar, dschar;
+ int32_t *ivalp;
+ char *sval;
+ int32_t cval;
+ uint32_t uval;
+ bool use_caps;
+ uint32_t precision_width;
+ //uint32_t length_modifier = 0;
+#if defined(PRINTF_FLOAT_ENABLE)
+ double fval;
+#endif
+
+ if (max_count == -1)
+ {
+ max_count = INT32_MAX - 1;
+ }
+
+ /*
+ * Start parsing apart the format string and display appropriate
+ * formats and data.
+ */
+ for (p = (char *)fmt; (c = *p) != 0; p++)
+ {
+ /*
+ * All formats begin with a '%' marker. Special chars like
+ * '\n' or '\t' are normally converted to the appropriate
+ * character by the __compiler__. Thus, no need for this
+ * routine to account for the '\' character.
+ */
+ if (c != '%')
+ {
+ n_putchar(func_ptr, c, farg, &max_count);
+
+ count++;
+
+ /*
+ * By using 'continue', the next iteration of the loop
+ * is used, skipping the code that follows.
+ */
+ continue;
+ }
+
+ /*
+ * First check for specification modifier flags.
+ */
+ use_caps = true;
+ flags_used = 0;
+ done = false;
+ while (!done)
+ {
+ switch (/* c = */ *++p)
+ {
+ case '-':
+ flags_used |= FLAGS_MINUS;
+ break;
+ case '+':
+ flags_used |= FLAGS_PLUS;
+ break;
+ case ' ':
+ flags_used |= FLAGS_SPACE;
+ break;
+ case '0':
+ flags_used |= FLAGS_ZERO;
+ break;
+ case '#':
+ flags_used |= FLAGS_POUND;
+ break;
+ default:
+ /* we've gone one char too far */
+ --p;
+ done = true;
+ break;
+ }
+ }
+
+ /*
+ * Next check for minimum field width.
+ */
+ field_width = 0;
+ done = false;
+ while (!done)
+ {
+ switch (c = *++p)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ field_width = (field_width * 10) + (c - '0');
+ break;
+ default:
+ /* we've gone one char too far */
+ --p;
+ done = true;
+ break;
+ }
+ }
+
+ /*
+ * Next check for the width and precision field separator.
+ */
+ precision_width = 6;
+ if (/* (c = *++p) */ *++p == '.')
+ {
+ /* precision_used = true; */
+
+ /*
+ * Must get precision field width, if present.
+ */
+ precision_width = 0;
+ done = false;
+ while (!done)
+ {
+ switch (c = *++p)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ precision_width = (precision_width * 10) + (c - '0');
+ break;
+ default:
+ /* we've gone one char too far */
+ --p;
+ done = true;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* we've gone one char too far */
+ --p;
+ }
+
+ /*
+ * Check for the length modifier.
+ */
+ /* length_modifier = 0; */
+ switch (/* c = */ *++p)
+ {
+ case 'h':
+ if (*++p != 'h')
+ {
+ --p;
+ }
+ /* length_modifier |= LENMOD_h; */
+ break;
+ case 'l':
+ if (*++p != 'l')
+ {
+ --p;
+ }
+ /* length_modifier |= LENMOD_l; */
+ break;
+ case 'L':
+ /* length_modifier |= LENMOD_L; */
+ break;
+ default:
+ /* we've gone one char too far */
+ --p;
+ break;
+ }
+
+ /*
+ * Now we're ready to examine the format.
+ */
+ switch (c = *++p)
+ {
+ case 'd':
+ case 'i':
+ ival = (int32_t)va_arg(ap, int32_t);
+ vlen = mknumstr(vstr,&ival,true,10,use_caps);
+ vstrp = &vstr[vlen];
+
+ if (ival < 0)
+ {
+ schar = '-';
+ ++vlen;
+ }
+ else
+ {
+ if (IS_FLAG_PLUS(flags_used))
+ {
+ schar = '+';
+ ++vlen;
+ }
+ else
+ {
+ if (IS_FLAG_SPACE(flags_used))
+ {
+ schar = ' ';
+ ++vlen;
+ }
+ else
+ {
+ schar = 0;
+ }
+ }
+ }
+ dschar = false;
+
+ /*
+ * do the ZERO pad.
+ */
+ if (IS_FLAG_ZERO(flags_used))
+ {
+ if (schar)
+ {
+ n_putchar(func_ptr, schar, farg, &max_count);
+ count++;
+ }
+ dschar = true;
+
+ fput_pad('0', vlen, field_width, &count, func_ptr, farg, &max_count);
+ vlen = field_width;
+ }
+ else
+ {
+ if (!IS_FLAG_MINUS(flags_used))
+ {
+ fput_pad(' ', vlen, field_width, &count, func_ptr, farg, &max_count);
+ if (schar)
+ {
+ n_putchar(func_ptr, schar, farg, &max_count);
+ count++;
+ }
+ dschar = true;
+ }
+ }
+
+ /* the string was built in reverse order, now display in */
+ /* correct order */
+ if ((!dschar) && schar)
+ {
+ n_putchar(func_ptr, schar, farg, &max_count);
+ count++;
+ }
+ goto cont_xd;
+#if defined(PRINTF_FLOAT_ENABLE)
+ case 'f':
+ case 'F':
+ fval = (double)va_arg(ap, double);
+ vlen = mkfloatnumstr(vstr,&fval,10, precision_width);
+ vstrp = &vstr[vlen];
+
+ if (fval < 0)
+ {
+ schar = '-';
+ ++vlen;
+ }
+ else
+ {
+ if (IS_FLAG_PLUS(flags_used))
+ {
+ schar = '+';
+ ++vlen;
+ }
+ else
+ {
+ if (IS_FLAG_SPACE(flags_used))
+ {
+ schar = ' ';
+ ++vlen;
+ }
+ else
+ {
+ schar = 0;
+ }
+ }
+ }
+ dschar = false;
+ if (IS_FLAG_ZERO(flags_used))
+ {
+ if (schar)
+ {
+ n_putchar(func_ptr, schar, farg, &max_count);
+ count++;
+ }
+ dschar = true;
+ fput_pad('0', vlen, field_width, &count, func_ptr, farg, &max_count);
+ vlen = field_width;
+ }
+ else
+ {
+ if (!IS_FLAG_MINUS(flags_used))
+ {
+ fput_pad(' ', vlen, field_width, &count, func_ptr, farg, &max_count);
+ if (schar)
+ {
+ n_putchar(func_ptr, schar, farg, &max_count);
+ count++;
+ }
+ dschar = true;
+ }
+ }
+ if (!dschar && schar)
+ {
+ n_putchar(func_ptr, schar, farg, &max_count);
+ count++;
+ }
+ goto cont_xd;
+#endif
+ case 'x':
+ use_caps = false;
+ case 'X':
+ uval = (uint32_t)va_arg(ap, uint32_t);
+ vlen = mknumstr(vstr,&uval,false,16,use_caps);
+ vstrp = &vstr[vlen];
+
+ dschar = false;
+ if (IS_FLAG_ZERO(flags_used))
+ {
+ if (IS_FLAG_POUND(flags_used))
+ {
+ n_putchar(func_ptr, '0', farg, &max_count);
+ n_putchar(func_ptr, (use_caps ? 'X' : 'x'), farg, &max_count);
+ count += 2;
+ /*vlen += 2;*/
+ dschar = true;
+ }
+ fput_pad('0', vlen, field_width, &count, func_ptr, farg, &max_count);
+ vlen = field_width;
+ }
+ else
+ {
+ if (!IS_FLAG_MINUS(flags_used))
+ {
+ if (IS_FLAG_POUND(flags_used))
+ {
+ vlen += 2;
+ }
+ fput_pad(' ', vlen, field_width, &count, func_ptr, farg, &max_count);
+ if (IS_FLAG_POUND(flags_used))
+ {
+ n_putchar(func_ptr, '0', farg, &max_count);
+ n_putchar(func_ptr, (use_caps ? 'X' : 'x'), farg, &max_count);
+ count += 2;
+
+ dschar = true;
+ }
+ }
+ }
+
+ if ((IS_FLAG_POUND(flags_used)) && (!dschar))
+ {
+ n_putchar(func_ptr, '0', farg, &max_count);
+ n_putchar(func_ptr, (use_caps ? 'X' : 'x'), farg, &max_count);
+ count += 2;
+ vlen += 2;
+ }
+ goto cont_xd;
+
+ case 'o':
+ uval = (uint32_t)va_arg(ap, uint32_t);
+ vlen = mknumstr(vstr,&uval,false,8,use_caps);
+ goto cont_u;
+ case 'b':
+ uval = (uint32_t)va_arg(ap, uint32_t);
+ vlen = mknumstr(vstr,&uval,false,2,use_caps);
+ goto cont_u;
+ case 'p':
+ uval = (uint32_t)va_arg(ap, uint32_t);
+ uval = (uint32_t)va_arg(ap, void *);
+ vlen = mknumstr(vstr,&uval,false,16,use_caps);
+ goto cont_u;
+ case 'u':
+ uval = (uint32_t)va_arg(ap, uint32_t);
+ vlen = mknumstr(vstr,&uval,false,10,use_caps);
+
+ cont_u:
+ vstrp = &vstr[vlen];
+
+ if (IS_FLAG_ZERO(flags_used))
+ {
+ fput_pad('0', vlen, field_width, &count, func_ptr, farg, &max_count);
+ vlen = field_width;
+ }
+ else
+ {
+ if (!IS_FLAG_MINUS(flags_used))
+ {
+ fput_pad(' ', vlen, field_width, &count, func_ptr, farg, &max_count);
+ }
+ }
+
+ cont_xd:
+ while (*vstrp)
+ {
+ n_putchar(func_ptr, *vstrp--, farg, &max_count);
+ count++;
+ }
+
+ if (IS_FLAG_MINUS(flags_used))
+ {
+ fput_pad(' ', vlen, field_width, &count, func_ptr, farg, &max_count);
+ }
+ break;
+
+ case 'c':
+ cval = (char)va_arg(ap, uint32_t);
+ n_putchar(func_ptr, cval, farg, &max_count);
+ count++;
+ break;
+ case 's':
+ sval = (char *)va_arg(ap, char *);
+ if (sval)
+ {
+ vlen = strlen(sval);
+ if (!IS_FLAG_MINUS(flags_used))
+ {
+ fput_pad(' ', vlen, field_width, &count, func_ptr, farg, &max_count);
+ }
+ while (*sval)
+ {
+ n_putchar(func_ptr, *sval++, farg, &max_count);
+ count++;
+ }
+ if (IS_FLAG_MINUS(flags_used))
+ {
+ fput_pad(' ', vlen, field_width, &count, func_ptr, farg, &max_count);
+ }
+ }
+ break;
+ case 'n':
+ ivalp = (int32_t *)va_arg(ap, int32_t *);
+ *ivalp = count;
+ break;
+ default:
+ n_putchar(func_ptr, c, farg, &max_count);
+ count++;
+ break;
+ }
+ }
+
+ if (max_count)
+ {
+ return count;
+ }
+ else
+ {
+ return temp_count;
+ }
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : _sputc
+ * Description : Writes the character into the string located by the string
+ * pointer and updates the string pointer.
+ *
+ *END**************************************************************************/
+int _sputc(int c, void * input_string)
+{
+ char **string_ptr = (char **)input_string;
+
+ *(*string_ptr)++ = (char)c;
+ return c;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : mknumstr
+ * Description : Converts a radix number to a string and return its length.
+ *
+ *END**************************************************************************/
+static int32_t mknumstr (char *numstr, void *nump, int32_t neg, int32_t radix, bool use_caps)
+{
+ int32_t a,b,c;
+ uint32_t ua,ub,uc;
+
+ int32_t nlen;
+ char *nstrp;
+
+ nlen = 0;
+ nstrp = numstr;
+ *nstrp++ = '\0';
+
+ if (neg)
+ {
+ a = *(int32_t *)nump;
+ if (a == 0)
+ {
+ *nstrp = '0';
+ ++nlen;
+ goto done;
+ }
+ while (a != 0)
+ {
+ b = (int32_t)a / (int32_t)radix;
+ c = (int32_t)a - ((int32_t)b * (int32_t)radix);
+ if (c < 0)
+ {
+ c = ~c + 1 + '0';
+ }
+ else
+ {
+ c = c + '0';
+ }
+ a = b;
+ *nstrp++ = (char)c;
+ ++nlen;
+ }
+ }
+ else
+ {
+ ua = *(uint32_t *)nump;
+ if (ua == 0)
+ {
+ *nstrp = '0';
+ ++nlen;
+ goto done;
+ }
+ while (ua != 0)
+ {
+ ub = (uint32_t)ua / (uint32_t)radix;
+ uc = (uint32_t)ua - ((uint32_t)ub * (uint32_t)radix);
+ if (uc < 10)
+ {
+ uc = uc + '0';
+ }
+ else
+ {
+ uc = uc - 10 + (use_caps ? 'A' : 'a');
+ }
+ ua = ub;
+ *nstrp++ = (char)uc;
+ ++nlen;
+ }
+ }
+ done:
+ return nlen;
+}
+
+#if defined(PRINTF_FLOAT_ENABLE)
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : mkfloatnumstr
+ * Description : Converts a floating radix number to a string and return
+ * its length, user can specify output precision width.
+ *
+ *END**************************************************************************/
+static int32_t mkfloatnumstr (char *numstr, void *nump, int32_t radix, uint32_t precision_width)
+{
+ int32_t a,b,c,i;
+ double fa,fb;
+ double r, fractpart, intpart;
+
+ int32_t nlen;
+ char *nstrp;
+ nlen = 0;
+ nstrp = numstr;
+ *nstrp++ = '\0';
+ r = *(double *)nump;
+ if (r == 0)
+ {
+ *nstrp = '0';
+ ++nlen;
+ goto done;
+ }
+ fractpart = modf((double)r , (double *)&intpart);
+ /* Process fractional part */
+ for (i = 0; i < precision_width; i++)
+ {
+ fractpart *= radix;
+ }
+ //a = (int32_t)floor(fractpart + (double)0.5);
+ fa = fractpart + (double)0.5;
+ for (i = 0; i < precision_width; i++)
+ {
+ fb = fa / (int32_t)radix;
+ c = (int32_t)(fa - (uint64_t)fb * (int32_t)radix);
+ if (c < 0)
+ {
+ c = ~c + 1 + '0';
+ }else
+ {
+ c = c + '0';
+ }
+ fa = fb;
+ *nstrp++ = (char)c;
+ ++nlen;
+ }
+ *nstrp++ = (char)'.';
+ ++nlen;
+ a = (int32_t)intpart;
+ while (a != 0)
+ {
+ b = (int32_t)a / (int32_t)radix;
+ c = (int32_t)a - ((int32_t)b * (int32_t)radix);
+ if (c < 0)
+ {
+ c = ~c + 1 + '0';
+ }else
+ {
+ c = c + '0';
+ }
+ a = b;
+ *nstrp++ = (char)c;
+ ++nlen;
+ }
+ done:
+ return nlen;
+}
+#endif
+
+static void fput_pad(int32_t c, int32_t curlen, int32_t field_width, int32_t *count, PUTCHAR_FUNC func_ptr, void *farg, int *max_count)
+{
+ int32_t i;
+
+ for (i = curlen; i < field_width; i++)
+ {
+ func_ptr((char)c, farg);
+ (*count)++;
+ }
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : scan_prv
+ * Description : Converts an input line of ASCII characters based upon a
+ * provided string format.
+ *
+ *END**************************************************************************/
+int scan_prv(const char *line_ptr, char *format, va_list args_ptr)
+{
+ uint8_t base;
+ /* Identifier for the format string */
+ char *c = format;
+ const char *s;
+ char temp;
+ /* Identifier for the input string */
+ const char *p = line_ptr;
+ /* flag telling the conversion specification */
+ uint32_t flag = 0 ;
+ /* filed width for the matching input streams */
+ uint32_t field_width;
+ /* how many arguments are assigned except the suppress */
+ uint32_t nassigned = 0;
+ /* how many characters are read from the input streams */
+ uint32_t n_decode = 0;
+
+ int32_t val;
+ char *buf;
+ int8_t neg;
+
+ /* return EOF error before any convernsion */
+ if (*p == '\0')
+ {
+ return EOF;
+ }
+
+ /* decode directives */
+ while ((*c) && (*p))
+ {
+ /* ignore all white-spaces in the format strings */
+ if (scan_ignore_white_space((const char **)&c))
+ {
+ n_decode += scan_ignore_white_space(&p);
+ }
+ else if (*c != '%')
+ {
+ /* Ordinary characters */
+ c++;
+ordinary: if (*p == *c)
+ {
+ n_decode++;
+ p++;
+ c++;
+ }
+ else
+ {
+ /* Match failure. Misalignment with C99, the unmatched
+ * characters need to be pushed back to stream. HOwever
+ * , it is deserted now. */
+ break;
+ }
+ }
+ else
+ {
+ /* convernsion specification */
+ c++;
+ if (*c == '%')
+ {
+ goto ordinary;
+ }
+
+ /* Reset */
+ flag = 0;
+ field_width = 0;
+ base = 0;
+
+ /* Loop to get full conversion specification */
+ while ((*c) && (!(flag & SCAN_DEST_MASK)))
+ {
+ switch (*c)
+ {
+ case '*':
+ if (flag & SCAN_SUPPRESS)
+ {
+ /* Match failure*/
+ return nassigned;
+ }
+ flag |= SCAN_SUPPRESS;
+ c++;
+ break;
+ case 'h':
+ if (flag & SCAN_LENGTH_MASK)
+ {
+ /* Match failure*/
+ return nassigned;
+ }
+ flag |= SCAN_LENGTH_SHORT_INT;
+
+ if (c[1] == 'h')
+ {
+ flag |= SCAN_LENGTH_CHAR;
+ c++;
+ }
+ c++;
+ break;
+ case 'l':
+ if (flag & SCAN_LENGTH_MASK)
+ {
+ /* Match failure*/
+ return nassigned;
+ }
+ flag |= SCAN_LENGTH_LONG_INT;
+
+ if (c[1] == 'l')
+ {
+ flag |= SCAN_LENGTH_LONG_LONG_INT;
+ c++;
+ }
+ c++;
+ break;
+#if defined(ADVANCE)
+ case 'j':
+ if (flag & SCAN_LENGTH_MASK)
+ {
+ /* Match failure*/
+ return nassigned;
+ }
+ flag |= SCAN_LENGTH_INTMAX;
+ c++
+ case 'z'
+ if (flag & SCAN_LENGTH_MASK)
+ {
+ /* Match failure*/
+ return nassigned;
+ }
+ flag |= SCAN_LENGTH_SIZE_T;
+ c++;
+ break;
+ case 't':
+ if (flag & SCAN_LENGTH_MASK)
+ {
+ /* Match failure*/
+ return nassigned;
+ }
+ flag |= SCAN_LENGTH_PTRDIFF_T;
+ c++;
+ break;
+#endif
+#if defined(SCANF_FLOAT_ENABLE)
+ case 'L':
+ if (flag & SCAN_LENGTH_MASK)
+ {
+ /* Match failure*/
+ return nassigned;
+ }
+ flag |= SCAN_LENGTH_LONG_DOUBLE;
+ c++;
+ break;
+#endif
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (field_width)
+ {
+ /* Match failure*/
+ return nassigned;
+ }
+ do {
+ field_width = field_width * 10 + *c - '0';
+ c++;
+ } while ((*c >= '0') && (*c <= '9'));
+ break;
+ case 'd':
+ flag |= SCAN_TYPE_SIGNED;
+ case 'u':
+ base = 10;
+ flag |= SCAN_DEST_INT;
+ c++;
+ break;
+ case 'o':
+ base = 8;
+ flag |= SCAN_DEST_INT;
+ c++;
+ break;
+ case 'x':
+ case 'X':
+ base = 16;
+ flag |= SCAN_DEST_INT;
+ c++;
+ break;
+ case 'i':
+ base = 0;
+ flag |= SCAN_DEST_INT;
+ c++;
+ break;
+#if defined(SCANF_FLOAT_ENABLE)
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ flag |= SCAN_DEST_FLOAT;
+ c++;
+ break;
+#endif
+ case 'c':
+ flag |= SCAN_DEST_CHAR;
+ if (!field_width)
+ {
+ field_width = 1;
+ }
+ c++;
+ break;
+ case 's':
+ flag |= SCAN_DEST_STRING;
+ c++;
+ break;
+#if defined(ADVANCE) /* [x]*/
+ case '[':
+ flag |= SCAN_DEST_SET;
+ /*Add Set functionality */
+ break;
+#endif
+ default:
+#if defined(SCAN_DEBUG)
+ printf("Unrecognized expression specifier: %c format: %s, number is: %d\r\n", c, format, nassigned);
+#endif
+ return nassigned;
+ }
+ }
+
+ if (!(flag & SCAN_DEST_MASK))
+ {
+ /* Format strings are exausted */
+ return nassigned;
+ }
+
+ if (!field_width)
+ {
+ /* Larget then length of a line */
+ field_width = 99;
+ }
+
+ /* Matching strings in input streams and assign to argument */
+ switch (flag & SCAN_DEST_MASK)
+ {
+ case SCAN_DEST_CHAR:
+ s = (const char *)p;
+ buf = va_arg(args_ptr, char *);
+ while ((field_width--) && (*p))
+ {
+ if (!(flag & SCAN_SUPPRESS))
+ {
+ *buf++ = *p++;
+ }
+ else
+ {
+ p++;
+ }
+ n_decode++;
+ }
+
+ if (((!(flag)) & SCAN_SUPPRESS) && (s != p))
+ {
+ nassigned++;
+ }
+ break;
+ case SCAN_DEST_STRING:
+ n_decode += scan_ignore_white_space(&p);
+ s = p;
+ buf = va_arg(args_ptr, char *);
+ while ((field_width--) && (*p != '\0') && (*p != ' ') &&
+ (*p != '\t') && (*p != '\n') && (*p != '\r') && (*p != '\v') && (*p != '\f'))
+ {
+ if (flag & SCAN_SUPPRESS)
+ {
+ p++;
+ }
+ else
+ {
+ *buf++ = *p++;
+ }
+ n_decode++;
+ }
+
+ if ((!(flag & SCAN_SUPPRESS)) && (s != p))
+ {
+ /* Add NULL to end of string */
+ *buf = '\0';
+ nassigned++;
+ }
+ break;
+ case SCAN_DEST_INT:
+ n_decode += scan_ignore_white_space(&p);
+ s = p;
+ val = 0;
+ /*TODO: scope is not testsed */
+ if ((base == 0) || (base == 16))
+ {
+ if ((s[0] == '0') && ((s[1] == 'x') || (s[1] == 'X')))
+ {
+ base = 16;
+ if (field_width >= 1)
+ {
+ p += 2;
+ n_decode += 2;
+ field_width -= 2;
+ }
+ }
+ }
+
+ if (base == 0)
+ {
+ if (s[0] == '0')
+ {
+ base = 8;
+ }
+ else
+ {
+ base = 10;
+ }
+ }
+
+ neg = 1;
+ switch (*p)
+ {
+ case '-':
+ neg = -1;
+ n_decode++;
+ p++;
+ field_width--;
+ break;
+ case '+':
+ neg = 1;
+ n_decode++;
+ p++;
+ field_width--;
+ break;
+ default:
+ break;
+ }
+
+ while ((*p) && (field_width--))
+ {
+ if ((*p <= '9') && (*p >= '0'))
+ {
+ temp = *p - '0';
+ }
+ else if((*p <= 'f') && (*p >= 'a'))
+ {
+ temp = *p - 'a' + 10;
+ }
+ else if((*p <= 'F') && (*p >= 'A'))
+ {
+ temp = *p - 'A' + 10;
+ }
+ else
+ {
+ break;
+ }
+
+ if (temp >= base)
+ {
+ break;
+ }
+ else
+ {
+ val = base * val + temp;
+ }
+ p++;
+ n_decode++;
+ }
+
+ val *= neg;
+ if (!(flag & SCAN_SUPPRESS))
+ {
+ switch (flag & SCAN_LENGTH_MASK)
+ {
+ case SCAN_LENGTH_CHAR:
+ if (flag & SCAN_TYPE_SIGNED)
+ {
+ *va_arg(args_ptr, signed char *) = (signed char)val;
+ }
+ else
+ {
+ *va_arg(args_ptr, unsigned char *) = (unsigned char)val;
+ }
+ break;
+ case SCAN_LENGTH_SHORT_INT:
+ if (flag & SCAN_TYPE_SIGNED)
+ {
+ *va_arg(args_ptr, signed short *) = (signed short)val;
+ }
+ else
+ {
+ *va_arg(args_ptr, unsigned short *) = (unsigned short)val;
+ }
+ break;
+ case SCAN_LENGTH_LONG_INT:
+ if (flag & SCAN_TYPE_SIGNED)
+ {
+ *va_arg(args_ptr, signed long int *) = (signed long int)val;
+ }
+ else
+ {
+ *va_arg(args_ptr, unsigned long int *) = (unsigned long int)val;
+ }
+ break;
+ case SCAN_LENGTH_LONG_LONG_INT:
+ if (flag & SCAN_TYPE_SIGNED)
+ {
+ *va_arg(args_ptr, signed long long int *) = (signed long long int)val;
+ }
+ else
+ {
+ *va_arg(args_ptr, unsigned long long int *) = (unsigned long long int)val;
+ }
+ break;
+ default:
+ /* The default type is the type int */
+ if (flag & SCAN_TYPE_SIGNED)
+ {
+ *va_arg(args_ptr, signed int *) = (signed int)val;
+ }
+ else
+ {
+ *va_arg(args_ptr, unsigned int *) = (unsigned int)val;
+ }
+ break;
+ }
+ nassigned++;
+ }
+ break;
+#if defined(SCANF_FLOAT_ENABLE)
+ case SCAN_DEST_FLOAT:
+ n_decode += scan_ignore_white_space(&p);
+ fnum = strtod(p, (char **)&s);
+
+ if ((fnum == HUGE_VAL) || (fnum == -HUGE_VAL))
+ {
+ break;
+ }
+
+ n_decode += (int)(s) - (int)(p);
+ p = s;
+ if (!(flag & SCAN_SUPPRESS))
+ {
+ if (flag & SCAN_LENGTH_LONG_DOUBLE)
+ {
+ *va_arg(args_ptr, double *) = fnum;
+ }
+ else
+ {
+ *va_arg(args_ptr, float *) = (float)fnum;
+ }
+ nassigned++;
+ }
+ break;
+#endif
+#if defined(ADVANCE)
+ case SCAN_DEST_SET:
+ break;
+#endif
+ default:
+#if defined(SCAN_DEBUG)
+ printf("ERROR: File %s line: %d\r\n", __FILE__, __LINE__);
+#endif
+ return nassigned;
+ }
+ }
+ }
+ return nassigned;
+}
+
+/*FUNCTION**********************************************************************
+ *
+ * Function Name : scan_ignore_white_space
+ * Description : Scanline function which ignores white spaces.
+ *
+ *END**************************************************************************/
+static uint32_t scan_ignore_white_space(const char **s)
+{
+ uint8_t count = 0;
+ uint8_t c;
+
+ c = **s;
+ while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r') || (c == '\v') || (c == '\f'))
+ {
+ count++;
+ (*s)++;
+ c = **s;
+ }
+ return count;
+}
diff --git a/platform/utilities/src/print_scan.h b/platform/utilities/src/print_scan.h
new file mode 100644
index 0000000..59c27e9
--- /dev/null
+++ b/platform/utilities/src/print_scan.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o 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.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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 __print_scan_h__
+#define __print_scan_h__
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+//#define PRINTF_FLOAT_ENABLE 1
+//#define PRINT_MAX_COUNT 1
+//#define SCANF_FLOAT_ENABLE 1
+
+#ifndef HUGE_VAL
+#define HUGE_VAL (99.e99)///wrong value
+#endif
+
+typedef int (*PUTCHAR_FUNC)(int a, void *b);
+
+/*!
+ * @brief This function outputs its parameters according to a formatted string.
+ *
+ * @note I/O is performed by calling given function pointer using following
+ * (*func_ptr)(c,farg);
+ *
+ * @param[in] farg Argument to func_ptr.
+ * @param[in] func_ptr Function to put character out.
+ * @param[in] max_count Maximum character count for snprintf and vsnprintf.
+ * Default value is 0 (unlimited size).
+ * @param[in] fmt_ptr Format string for printf.
+ * @param[in] args_ptr Arguments to printf.
+ *
+ * @return Number of characters
+ * @return EOF (End Of File found.)
+ */
+int _doprint(void *farg, PUTCHAR_FUNC func_ptr, int max_count, char *fmt, va_list ap);
+
+/*!
+ * @brief Writes the character into the string located by the string pointer and
+ * updates the string pointer.
+ *
+ * @param[in] c The character to put into the string.
+ * @param[in, out] input_string This is an updated pointer to a string pointer.
+ *
+ * @return Character written into string.
+ */
+int _sputc(int c, void * input_string);
+
+/*!
+ * @brief Converts an input line of ASCII characters based upon a provided
+ * string format.
+ *
+ * @param[in] line_ptr The input line of ASCII data.
+ * @param[in] format Format first points to the format string.
+ * @param[in] args_ptr The list of parameters.
+ *
+ * @return Number of input items converted and assigned.
+ * @return IO_EOF - When line_ptr is empty string "".
+ */
+int scan_prv(const char *line_ptr, char *format, va_list args_ptr);
+
+#endif