diff options
Diffstat (limited to 'FreeRTOS/Demo/Safer_Interrupts_M33F_NXP_LPC55S69_MCUXpresso/NXP_Code/utilities/fsl_str.c')
-rw-r--r-- | FreeRTOS/Demo/Safer_Interrupts_M33F_NXP_LPC55S69_MCUXpresso/NXP_Code/utilities/fsl_str.c | 1554 |
1 files changed, 1554 insertions, 0 deletions
diff --git a/FreeRTOS/Demo/Safer_Interrupts_M33F_NXP_LPC55S69_MCUXpresso/NXP_Code/utilities/fsl_str.c b/FreeRTOS/Demo/Safer_Interrupts_M33F_NXP_LPC55S69_MCUXpresso/NXP_Code/utilities/fsl_str.c new file mode 100644 index 000000000..c03ef8309 --- /dev/null +++ b/FreeRTOS/Demo/Safer_Interrupts_M33F_NXP_LPC55S69_MCUXpresso/NXP_Code/utilities/fsl_str.c @@ -0,0 +1,1554 @@ +/* + * Copyright 2017, 2020 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#include <math.h> +#include <stdarg.h> +#include <stdlib.h> +#include <errno.h> /* MISRA C-2012 Rule 22.9 */ +#include "fsl_str.h" +#include "fsl_debug_console_conf.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @brief The overflow value.*/ +#ifndef HUGE_VAL +#define HUGE_VAL (99.e99) +#endif /* HUGE_VAL */ + +#ifndef MAX_FIELD_WIDTH +#define MAX_FIELD_WIDTH 99U +#endif + +#if PRINTF_ADVANCED_ENABLE +/*! @brief Specification modifier flags for printf. */ +enum _debugconsole_printf_flag +{ + kPRINTF_Minus = 0x01U, /*!< Minus FLag. */ + kPRINTF_Plus = 0x02U, /*!< Plus Flag. */ + kPRINTF_Space = 0x04U, /*!< Space Flag. */ + kPRINTF_Zero = 0x08U, /*!< Zero Flag. */ + kPRINTF_Pound = 0x10U, /*!< Pound Flag. */ + kPRINTF_LengthChar = 0x20U, /*!< Length: Char Flag. */ + kPRINTF_LengthShortInt = 0x40U, /*!< Length: Short Int Flag. */ + kPRINTF_LengthLongInt = 0x80U, /*!< Length: Long Int Flag. */ + kPRINTF_LengthLongLongInt = 0x100U, /*!< Length: Long Long Int Flag. */ +}; +#endif /* PRINTF_ADVANCED_ENABLE */ + +/*! @brief Specification modifier flags for scanf. */ +enum _debugconsole_scanf_flag +{ + kSCANF_Suppress = 0x2U, /*!< Suppress Flag. */ + kSCANF_DestMask = 0x7cU, /*!< Destination Mask. */ + kSCANF_DestChar = 0x4U, /*!< Destination Char Flag. */ + kSCANF_DestString = 0x8U, /*!< Destination String FLag. */ + kSCANF_DestSet = 0x10U, /*!< Destination Set Flag. */ + kSCANF_DestInt = 0x20U, /*!< Destination Int Flag. */ + kSCANF_DestFloat = 0x30U, /*!< Destination Float Flag. */ + kSCANF_LengthMask = 0x1f00U, /*!< Length Mask Flag. */ +#if SCANF_ADVANCED_ENABLE + kSCANF_LengthChar = 0x100U, /*!< Length Char Flag. */ + kSCANF_LengthShortInt = 0x200U, /*!< Length ShortInt Flag. */ + kSCANF_LengthLongInt = 0x400U, /*!< Length LongInt Flag. */ + kSCANF_LengthLongLongInt = 0x800U, /*!< Length LongLongInt Flag. */ +#endif /* SCANF_ADVANCED_ENABLE */ +#if SCANF_FLOAT_ENABLE + kSCANF_LengthLongLongDouble = 0x1000U, /*!< Length LongLongDuoble Flag. */ +#endif /*PRINTF_FLOAT_ENABLE */ + kSCANF_TypeSinged = 0x2000U, /*!< TypeSinged Flag. */ +}; + +/*! @brief Keil: suppress ellipsis warning in va_arg usage below. */ +#if defined(__CC_ARM) +#pragma diag_suppress 1256 +#endif /* __CC_ARM */ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +/*! + * @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 ScanIgnoreWhiteSpace(const char **s); + +/*! + * @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 ConvertRadixNumToString(char *numstr, void *nump, int32_t neg, int32_t radix, bool use_caps); + +#if 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 ConvertFloatRadixNumToString(char *numstr, void *nump, int32_t radix, uint32_t precision_width); + +#endif /* PRINTF_FLOAT_ENABLE */ + +/*************Code for process formatted data*******************************/ +#if PRINTF_ADVANCED_ENABLE +static uint8_t PrintGetSignChar(int64_t ival, uint32_t flags_used, char *schar) +{ + uint8_t len = 1U; + if (ival < 0) + { + *schar = '-'; + } + else + { + if (0U != (flags_used & (uint32_t)kPRINTF_Plus)) + { + *schar = '+'; + } + else if (0U != (flags_used & (uint32_t)kPRINTF_Space)) + { + *schar = ' '; + } + else + { + *schar = '\0'; + len = 0U; + } + } + return len; +} +#endif + +static uint32_t PrintGetWidth(const char **p, va_list *ap) +{ + uint32_t field_width = 0; + uint8_t done = 0U; + char c; + + while (0U == done) + { + c = *(++(*p)); + if ((c >= '0') && (c <= '9')) + { + (field_width) = ((field_width)*10U) + ((uint32_t)c - (uint32_t)'0'); + } +#if PRINTF_ADVANCED_ENABLE + else if (c == '*') + { + (field_width) = (uint32_t)va_arg(*ap, uint32_t); + } +#endif /* PRINTF_ADVANCED_ENABLE */ + else + { + /* We've gone one char too far. */ + --(*p); + done = 1U; + } + } + return field_width; +} + +static uint32_t PrintGetPrecision(const char **s, va_list *ap, bool *valid_precision_width) +{ + const char *p = *s; + uint32_t precision_width = 6U; + uint8_t done = 0U; + +#if PRINTF_ADVANCED_ENABLE + if (NULL != valid_precision_width) + { + *valid_precision_width = false; + } +#endif /* PRINTF_ADVANCED_ENABLE */ + if (*++p == '.') + { + /* Must get precision field width, if present. */ + precision_width = 0U; + done = 0U; + while (0U == done) + { + char c = *++p; + if ((c >= '0') && (c <= '9')) + { + precision_width = (precision_width * 10U) + ((uint32_t)c - (uint32_t)'0'); +#if PRINTF_ADVANCED_ENABLE + if (NULL != valid_precision_width) + { + *valid_precision_width = true; + } +#endif /* PRINTF_ADVANCED_ENABLE */ + } +#if PRINTF_ADVANCED_ENABLE + else if (c == '*') + { + precision_width = (uint32_t)va_arg(*ap, uint32_t); + if (NULL != valid_precision_width) + { + *valid_precision_width = true; + } + } +#endif /* PRINTF_ADVANCED_ENABLE */ + else + { + /* We've gone one char too far. */ + --p; + done = 1U; + } + } + } + else + { + /* We've gone one char too far. */ + --p; + } + *s = p; + return precision_width; +} + +static uint32_t PrintIsobpu(const char c) +{ + uint32_t ret = 0U; + if ((c == 'o') || (c == 'b') || (c == 'p') || (c == 'u')) + { + ret = 1U; + } + return ret; +} + +static uint32_t PrintIsdi(const char c) +{ + uint32_t ret = 0U; + if ((c == 'd') || (c == 'i')) + { + ret = 1U; + } + return ret; +} + +static void PrintOutputdifFobpu(uint32_t flags_used, + uint32_t field_width, + uint32_t vlen, + char schar, + char *vstrp, + printfCb cb, + char *buf, + int32_t *count) +{ +#if PRINTF_ADVANCED_ENABLE + /* Do the ZERO pad. */ + if (0U != (flags_used & (uint32_t)kPRINTF_Zero)) + { + if ('\0' != schar) + { + cb(buf, count, schar, 1); + schar = '\0'; + } + cb(buf, count, '0', (int)field_width - (int)vlen); + vlen = field_width; + } + else + { + if (0U == (flags_used & (uint32_t)kPRINTF_Minus)) + { + cb(buf, count, ' ', (int)field_width - (int)vlen); + if ('\0' != schar) + { + cb(buf, count, schar, 1); + schar = '\0'; + } + } + } + /* The string was built in reverse order, now display in correct order. */ + if ('\0' != schar) + { + cb(buf, count, schar, 1); + } +#else + cb(buf, count, ' ', (int)field_width - (int)vlen); +#endif /* PRINTF_ADVANCED_ENABLE */ + while ('\0' != (*vstrp)) + { + cb(buf, count, *vstrp--, 1); + } +#if PRINTF_ADVANCED_ENABLE + if (0U != (flags_used & (uint32_t)kPRINTF_Minus)) + { + cb(buf, count, ' ', (int)field_width - (int)vlen); + } +#endif /* PRINTF_ADVANCED_ENABLE */ +} + +static void PrintOutputxX(uint32_t flags_used, + uint32_t field_width, + uint32_t vlen, + bool use_caps, + char *vstrp, + printfCb cb, + char *buf, + int32_t *count) +{ +#if PRINTF_ADVANCED_ENABLE + uint8_t dschar = 0; + if (0U != (flags_used & (uint32_t)kPRINTF_Zero)) + { + if (0U != (flags_used & (uint32_t)kPRINTF_Pound)) + { + cb(buf, count, '0', 1); + cb(buf, count, (use_caps ? 'X' : 'x'), 1); + dschar = 1U; + } + cb(buf, count, '0', (int)field_width - (int)vlen); + vlen = field_width; + } + else + { + if (0U == (flags_used & (uint32_t)kPRINTF_Minus)) + { + if (0U != (flags_used & (uint32_t)kPRINTF_Pound)) + { + vlen += 2U; + } + cb(buf, count, ' ', (int)field_width - (int)vlen); + if (0U != (flags_used & (uint32_t)kPRINTF_Pound)) + { + cb(buf, count, '0', 1); + cb(buf, count, (use_caps ? 'X' : 'x'), 1); + dschar = 1U; + } + } + } + + if ((0U != (flags_used & (uint32_t)kPRINTF_Pound)) && (0U == dschar)) + { + cb(buf, count, '0', 1); + cb(buf, count, (use_caps ? 'X' : 'x'), 1); + vlen += 2U; + } +#else + cb(buf, count, ' ', (int)field_width - (int)vlen); +#endif /* PRINTF_ADVANCED_ENABLE */ + while ('\0' != (*vstrp)) + { + cb(buf, count, *vstrp--, 1); + } +#if PRINTF_ADVANCED_ENABLE + if (0U != (flags_used & (uint32_t)kPRINTF_Minus)) + { + cb(buf, count, ' ', (int)field_width - (int)vlen); + } +#endif /* PRINTF_ADVANCED_ENABLE */ +} + +static uint32_t PrintIsfF(const char c) +{ + uint32_t ret = 0U; + if ((c == 'f') || (c == 'F')) + { + ret = 1U; + } + return ret; +} + +static uint32_t PrintIsxX(const char c) +{ + uint32_t ret = 0U; + if ((c == 'x') || (c == 'X')) + { + ret = 1U; + } + return ret; +} + +#if PRINTF_ADVANCED_ENABLE +static uint32_t PrintCheckFlags(const char **s) +{ + const char *p = *s; + /* First check for specification modifier flags. */ + uint32_t flags_used = 0U; + bool done = false; + while (false == done) + { + switch (*++p) + { + case '-': + flags_used |= (uint32_t)kPRINTF_Minus; + break; + case '+': + flags_used |= (uint32_t)kPRINTF_Plus; + break; + case ' ': + flags_used |= (uint32_t)kPRINTF_Space; + break; + case '0': + flags_used |= (uint32_t)kPRINTF_Zero; + break; + case '#': + flags_used |= (uint32_t)kPRINTF_Pound; + break; + default: + /* We've gone one char too far. */ + --p; + done = true; + break; + } + } + *s = p; + return flags_used; +} +#endif /* PRINTF_ADVANCED_ENABLE */ + +#if PRINTF_ADVANCED_ENABLE +/* + * Check for the length modifier. + */ +static uint32_t PrintGetLengthFlag(const char **s) +{ + const char *p = *s; + /* First check for specification modifier flags. */ + uint32_t flags_used = 0U; + + switch (/* c = */ *++p) + { + case 'h': + if (*++p != 'h') + { + flags_used |= (uint32_t)kPRINTF_LengthShortInt; + --p; + } + else + { + flags_used |= (uint32_t)kPRINTF_LengthChar; + } + break; + case 'l': + if (*++p != 'l') + { + flags_used |= (uint32_t)kPRINTF_LengthLongInt; + --p; + } + else + { + flags_used |= (uint32_t)kPRINTF_LengthLongLongInt; + } + break; + default: + /* we've gone one char too far */ + --p; + break; + } + *s = p; + return flags_used; +} +#else +static void PrintFilterLengthFlag(const char **s) +{ + const char *p = *s; + char ch; + + do + { + ch = *++p; + } while ((ch == 'h') || (ch == 'l')); + + *s = --p; +} +#endif /* PRINTF_ADVANCED_ENABLE */ + +static uint8_t PrintGetRadixFromobpu(const char c) +{ + uint8_t radix; + + if (c == 'o') + { + radix = 8U; + } + else if (c == 'b') + { + radix = 2U; + } + else if (c == 'p') + { + radix = 16U; + } + else + { + radix = 10U; + } + return radix; +} + +static uint32_t ScanIsWhiteSpace(const char c) +{ + uint32_t ret = 0U; + if ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r') || (c == '\v') || (c == '\f')) + { + ret = 1U; + } + return ret; +} + +static uint32_t ScanIgnoreWhiteSpace(const char **s) +{ + uint32_t count = 0U; + char c; + + c = **s; + while (1U == ScanIsWhiteSpace(c)) + { + count++; + (*s)++; + c = **s; + } + return count; +} + +static int32_t ConvertRadixNumToString(char *numstr, void *nump, int32_t neg, int32_t radix, bool use_caps) +{ +#if PRINTF_ADVANCED_ENABLE + int64_t a; + int64_t b; + int64_t c; + + uint64_t ua; + uint64_t ub; + uint64_t uc; +#else + int32_t a; + int32_t b; + int32_t c; + + uint32_t ua; + uint32_t ub; + uint32_t uc; +#endif /* PRINTF_ADVANCED_ENABLE */ + + int32_t nlen; + char *nstrp; + + nlen = 0; + nstrp = numstr; + *nstrp++ = '\0'; + +#if !(PRINTF_ADVANCED_ENABLE > 0) + neg = 0; +#endif + + if (0 != neg) + { +#if PRINTF_ADVANCED_ENABLE + a = *(int64_t *)nump; +#else + a = *(int32_t *)nump; +#endif /* PRINTF_ADVANCED_ENABLE */ + if (a == 0) + { + *nstrp = '0'; + ++nlen; + return nlen; + } + while (a != 0) + { +#if PRINTF_ADVANCED_ENABLE + b = (int64_t)a / (int64_t)radix; + c = (int64_t)a - ((int64_t)b * (int64_t)radix); + if (c < 0) + { + c = (int64_t)'0' - c; + } +#else + b = a / radix; + c = a - (b * radix); + if (c < 0) + { + c = (int32_t)'0' - c; + } +#endif /* PRINTF_ADVANCED_ENABLE */ + else + { + c = c + (int32_t)'0'; + } + a = b; + *nstrp++ = (char)c; + ++nlen; + } + } + else + { +#if PRINTF_ADVANCED_ENABLE + ua = *(uint64_t *)nump; +#else + ua = *(uint32_t *)nump; +#endif /* PRINTF_ADVANCED_ENABLE */ + if (ua == 0U) + { + *nstrp = '0'; + ++nlen; + return nlen; + } + while (ua != 0U) + { +#if PRINTF_ADVANCED_ENABLE + ub = (uint64_t)ua / (uint64_t)radix; + uc = (uint64_t)ua - ((uint64_t)ub * (uint64_t)radix); +#else + ub = ua / (uint32_t)radix; + uc = ua - (ub * (uint32_t)radix); +#endif /* PRINTF_ADVANCED_ENABLE */ + + if (uc < 10U) + { + uc = uc + (uint32_t)'0'; + } + else + { + uc = uc - 10U + (uint32_t)(use_caps ? 'A' : 'a'); + } + ua = ub; + *nstrp++ = (char)uc; + ++nlen; + } + } + return nlen; +} + +#if PRINTF_FLOAT_ENABLE +static int32_t ConvertFloatRadixNumToString(char *numstr, void *nump, int32_t radix, uint32_t precision_width) +{ + int32_t a; + int32_t b; + int32_t c; + int32_t i; + double fa; + double dc; + double fb; + double r; + double fractpart; + double intpart; + + int32_t nlen; + char *nstrp; + nlen = 0; + nstrp = numstr; + *nstrp++ = '\0'; + r = *(double *)nump; + if (0.0 == r) + { + *nstrp = '0'; + ++nlen; + return nlen; + } + fractpart = modf((double)r, (double *)&intpart); + /* Process fractional part. */ + for (i = 0; i < (int32_t)precision_width; i++) + { + fractpart *= (double)radix; + } + if (r >= (double)0.0) + { + fa = fractpart + (double)0.5; + if (fa >= pow((double)10, (double)precision_width)) + { + intpart++; + } + } + else + { + fa = fractpart - (double)0.5; + if (fa <= -pow((double)10, (double)precision_width)) + { + intpart--; + } + } + for (i = 0; i < (int32_t)precision_width; i++) + { + fb = fa / (double)radix; + dc = (fa - (double)(int64_t)fb * (double)radix); + c = (int32_t)dc; + if (c < 0) + { + c = (int32_t)'0' - c; + } + else + { + c = c + '0'; + } + fa = fb; + *nstrp++ = (char)c; + ++nlen; + } + *nstrp++ = (char)'.'; + ++nlen; + a = (int32_t)intpart; + if (a == 0) + { + *nstrp++ = '0'; + ++nlen; + } + else + { + while (a != 0) + { + b = (int32_t)a / (int32_t)radix; + c = (int32_t)a - ((int32_t)b * (int32_t)radix); + if (c < 0) + { + c = (int32_t)'0' - c; + } + else + { + c = c + '0'; + } + a = b; + *nstrp++ = (char)c; + ++nlen; + } + } + return nlen; +} +#endif /* PRINTF_FLOAT_ENABLE */ + +/*! + * 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); + * + * param[in] fmt_ptr Format string for printf. + * param[in] args_ptr Arguments to printf. + * param[in] buf pointer to the buffer + * param cb print callback function pointer + * + * return Number of characters to be print + */ +int StrFormatPrintf(const char *fmt, va_list ap, char *buf, printfCb cb) +{ + /* va_list ap; */ + const char *p; + char c; + + char vstr[33]; + char *vstrp = NULL; + int32_t vlen = 0; + + int32_t count = 0; + + uint32_t field_width; + uint32_t precision_width; + char *sval; + int32_t cval; + bool use_caps; + uint8_t radix = 0; + +#if PRINTF_ADVANCED_ENABLE + uint32_t flags_used; + char schar; + int64_t ival; + uint64_t uval = 0; + bool valid_precision_width; +#else + int32_t ival; + uint32_t uval = 0; +#endif /* PRINTF_ADVANCED_ENABLE */ + +#if PRINTF_FLOAT_ENABLE + double fval; +#endif /* PRINTF_FLOAT_ENABLE */ + + /* Start parsing apart the format string and display appropriate formats and data. */ + p = fmt; + while (true) + { + if ('\0' == *p) + { + break; + } + c = *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 != '%') + { + cb(buf, &count, c, 1); + p++; + /* By using 'continue', the next iteration of the loop is used, skipping the code that follows. */ + continue; + } + + use_caps = true; + +#if PRINTF_ADVANCED_ENABLE + /* First check for specification modifier flags. */ + flags_used = PrintCheckFlags(&p); +#endif /* PRINTF_ADVANCED_ENABLE */ + + /* Next check for minimum field width. */ + field_width = PrintGetWidth(&p, &ap); + + /* Next check for the width and precision field separator. */ +#if PRINTF_ADVANCED_ENABLE + precision_width = PrintGetPrecision(&p, &ap, &valid_precision_width); +#else + precision_width = PrintGetPrecision(&p, &ap, NULL); + (void)precision_width; +#endif + +#if PRINTF_ADVANCED_ENABLE + /* Check for the length modifier. */ + flags_used |= PrintGetLengthFlag(&p); +#else + /* Filter length modifier. */ + PrintFilterLengthFlag(&p); +#endif + + /* Now we're ready to examine the format. */ + c = *++p; + { + if (1U == PrintIsdi(c)) + { +#if PRINTF_ADVANCED_ENABLE + if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongLongInt)) + { + ival = (int64_t)va_arg(ap, int64_t); + } + else +#endif /* PRINTF_ADVANCED_ENABLE */ + { + ival = (int32_t)va_arg(ap, int32_t); + } + vlen = ConvertRadixNumToString(vstr, (void *)&ival, 1, 10, use_caps); + vstrp = &vstr[vlen]; +#if PRINTF_ADVANCED_ENABLE + vlen += (int32_t)PrintGetSignChar(ival, flags_used, &schar); + PrintOutputdifFobpu(flags_used, field_width, (uint32_t)vlen, schar, vstrp, cb, buf, &count); +#else + PrintOutputdifFobpu(0U, field_width, (uint32_t)vlen, '\0', vstrp, cb, buf, &count); +#endif + } + else if (1U == PrintIsfF(c)) + { +#if PRINTF_FLOAT_ENABLE + fval = (double)va_arg(ap, double); + vlen = ConvertFloatRadixNumToString(vstr, &fval, 10, precision_width); + vstrp = &vstr[vlen]; + +#if PRINTF_ADVANCED_ENABLE + vlen += (int32_t)PrintGetSignChar(((fval < 0.0) ? ((int64_t)-1) : ((int64_t)fval)), flags_used, &schar); + PrintOutputdifFobpu(flags_used, field_width, (uint32_t)vlen, schar, vstrp, cb, buf, &count); +#else + PrintOutputdifFobpu(0, field_width, (uint32_t)vlen, '\0', vstrp, cb, buf, &count); +#endif + +#else + (void)va_arg(ap, double); +#endif /* PRINTF_FLOAT_ENABLE */ + } + else if (1U == PrintIsxX(c)) + { + if (c == 'x') + { + use_caps = false; + } +#if PRINTF_ADVANCED_ENABLE + if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongLongInt)) + { + uval = (uint64_t)va_arg(ap, uint64_t); + } + else +#endif /* PRINTF_ADVANCED_ENABLE */ + { + uval = (uint32_t)va_arg(ap, uint32_t); + } + vlen = ConvertRadixNumToString(vstr, &uval, 0, 16, use_caps); + vstrp = &vstr[vlen]; +#if PRINTF_ADVANCED_ENABLE + PrintOutputxX(flags_used, field_width, (uint32_t)vlen, use_caps, vstrp, cb, buf, &count); +#else + PrintOutputxX(0U, field_width, (uint32_t)vlen, use_caps, vstrp, cb, buf, &count); +#endif + } + else if (1U == PrintIsobpu(c)) + { +#if PRINTF_ADVANCED_ENABLE + if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongLongInt)) + { + uval = (uint64_t)va_arg(ap, uint64_t); + } + else +#endif /* PRINTF_ADVANCED_ENABLE */ + { + uval = (uint32_t)va_arg(ap, uint32_t); + } + + radix = PrintGetRadixFromobpu(c); + + vlen = ConvertRadixNumToString(vstr, &uval, 0, (int32_t)radix, use_caps); + vstrp = &vstr[vlen]; +#if PRINTF_ADVANCED_ENABLE + PrintOutputdifFobpu(flags_used, field_width, (uint32_t)vlen, '\0', vstrp, cb, buf, &count); +#else + PrintOutputdifFobpu(0U, field_width, (uint32_t)vlen, '\0', vstrp, cb, buf, &count); +#endif + } + else if (c == 'c') + { + cval = (int32_t)va_arg(ap, uint32_t); + cb(buf, &count, cval, 1); + } + else if (c == 's') + { + sval = (char *)va_arg(ap, char *); + if (NULL != sval) + { +#if PRINTF_ADVANCED_ENABLE + if (valid_precision_width) + { + vlen = (int32_t)precision_width; + } + else + { + vlen = (int32_t)strlen(sval); + } +#else + vlen = (int32_t)strlen(sval); +#endif /* PRINTF_ADVANCED_ENABLE */ +#if PRINTF_ADVANCED_ENABLE + if (0U == (flags_used & (uint32_t)kPRINTF_Minus)) +#endif /* PRINTF_ADVANCED_ENABLE */ + { + cb(buf, &count, ' ', (int)field_width - (int)vlen); + } + +#if PRINTF_ADVANCED_ENABLE + if (valid_precision_width) + { + while (('\0' != *sval) && (vlen > 0)) + { + cb(buf, &count, *sval++, 1); + vlen--; + } + /* In case that vlen sval is shorter than vlen */ + vlen = (int32_t)precision_width - vlen; + } + else + { +#endif /* PRINTF_ADVANCED_ENABLE */ + while ('\0' != (*sval)) + { + cb(buf, &count, *sval++, 1); + } +#if PRINTF_ADVANCED_ENABLE + } +#endif /* PRINTF_ADVANCED_ENABLE */ + +#if PRINTF_ADVANCED_ENABLE + if (0U != (flags_used & (uint32_t)kPRINTF_Minus)) + { + cb(buf, &count, ' ', (int32_t)field_width - vlen); + } +#endif /* PRINTF_ADVANCED_ENABLE */ + } + } + else + { + cb(buf, &count, c, 1); + } + } + p++; + } + + return count; +} + +#if SCANF_FLOAT_ENABLE +static uint8_t StrFormatScanIsFloat(char *c) +{ + uint8_t ret = 0U; + if (('a' == (*c)) || ('A' == (*c)) || ('e' == (*c)) || ('E' == (*c)) || ('f' == (*c)) || ('F' == (*c)) || + ('g' == (*c)) || ('G' == (*c))) + { + ret = 1U; + } + return ret; +} +#endif + +static uint8_t StrFormatScanIsFormatStarting(char *c) +{ + uint8_t ret = 1U; + if ((*c != '%')) + { + ret = 0U; + } + else if (*(c + 1) == '%') + { + ret = 0U; + } + else + { + /*MISRA rule 15.7*/ + } + + return ret; +} + +static uint8_t StrFormatScanGetBase(uint8_t base, const char *s) +{ + if (base == 0U) + { + if (s[0] == '0') + { + if ((s[1] == 'x') || (s[1] == 'X')) + { + base = 16; + } + else + { + base = 8; + } + } + else + { + base = 10; + } + } + return base; +} + +static uint8_t StrFormatScanCheckSymbol(const char *p, int8_t *neg) +{ + uint8_t len; + switch (*p) + { + case '-': + *neg = -1; + len = 1; + break; + case '+': + *neg = 1; + len = 1; + break; + default: + *neg = 1; + len = 0; + break; + } + return len; +} + +static uint8_t StrFormatScanFillInteger(uint32_t flag, va_list *args_ptr, int32_t val) +{ +#if SCANF_ADVANCED_ENABLE + if (0U != (flag & (uint32_t)kSCANF_Suppress)) + { + return 0u; + } + + switch (flag & (uint32_t)kSCANF_LengthMask) + { + case (uint32_t)kSCANF_LengthChar: + if (0U != (flag & (uint32_t)kSCANF_TypeSinged)) + { + *va_arg(*args_ptr, signed char *) = (signed char)val; + } + else + { + *va_arg(*args_ptr, unsigned char *) = (unsigned char)val; + } + break; + case (uint32_t)kSCANF_LengthShortInt: + if (0U != (flag & (uint32_t)kSCANF_TypeSinged)) + { + *va_arg(*args_ptr, signed short *) = (signed short)val; + } + else + { + *va_arg(*args_ptr, unsigned short *) = (unsigned short)val; + } + break; + case (uint32_t)kSCANF_LengthLongInt: + if (0U != (flag & (uint32_t)kSCANF_TypeSinged)) + { + *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 (uint32_t)kSCANF_LengthLongLongInt: + if (0U != (flag & (uint32_t)kSCANF_TypeSinged)) + { + *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 (0U != (flag & (uint32_t)kSCANF_TypeSinged)) + { + *va_arg(*args_ptr, signed int *) = (signed int)val; + } + else + { + *va_arg(*args_ptr, unsigned int *) = (unsigned int)val; + } + break; + } +#else + /* The default type is the type int. */ + if (0U != (flag & (uint32_t)kSCANF_TypeSinged)) + { + *va_arg(*args_ptr, signed int *) = (signed int)val; + } + else + { + *va_arg(*args_ptr, unsigned int *) = (unsigned int)val; + } +#endif /* SCANF_ADVANCED_ENABLE */ + + return 1u; +} + +#if SCANF_FLOAT_ENABLE +static uint8_t StrFormatScanFillFloat(uint32_t flag, va_list *args_ptr, double fnum) +{ +#if SCANF_ADVANCED_ENABLE + if (0U != (flag & (uint32_t)kSCANF_Suppress)) + { + return 0u; + } + else +#endif /* SCANF_ADVANCED_ENABLE */ + { + if (0U != (flag & (uint32_t)kSCANF_LengthLongLongDouble)) + { + *va_arg(*args_ptr, double *) = fnum; + } + else + { + *va_arg(*args_ptr, float *) = (float)fnum; + } + return 1u; + } +} +#endif /* SCANF_FLOAT_ENABLE */ + +static uint8_t StrFormatScanfStringHandling(char **str, uint32_t *flag, uint32_t *field_width, uint8_t *base) +{ + uint8_t exitPending = 0U; + char *c = *str; + + /* Loop to get full conversion specification. */ + while (('\0' != (*c)) && (0U == (*flag & (uint32_t)kSCANF_DestMask))) + { +#if SCANF_ADVANCED_ENABLE + if ('*' == (*c)) + { + if (0U != ((*flag) & (uint32_t)kSCANF_Suppress)) + { + /* Match failure. */ + exitPending = 1U; + } + else + { + (*flag) |= (uint32_t)kSCANF_Suppress; + } + } + else if ('h' == (*c)) + { + if (0U != ((*flag) & (uint32_t)kSCANF_LengthMask)) + { + /* Match failure. */ + exitPending = 1U; + } + else + { + if (c[1] == 'h') + { + (*flag) |= (uint32_t)kSCANF_LengthChar; + c++; + } + else + { + (*flag) |= (uint32_t)kSCANF_LengthShortInt; + } + } + } + else if ('l' == (*c)) + { + if (0U != ((*flag) & (uint32_t)kSCANF_LengthMask)) + { + /* Match failure. */ + exitPending = 1U; + } + else + { + if (c[1] == 'l') + { + (*flag) |= (uint32_t)kSCANF_LengthLongLongInt; + c++; + } + else + { + (*flag) |= (uint32_t)kSCANF_LengthLongInt; + } + } + } + else +#endif /* SCANF_ADVANCED_ENABLE */ +#if SCANF_FLOAT_ENABLE + if ('L' == (*c)) + { + if (0U != ((*flag) & (uint32_t)kSCANF_LengthMask)) + { + /* Match failure. */ + exitPending = 1U; + } + else + { + (*flag) |= (uint32_t)kSCANF_LengthLongLongDouble; + } + } + else +#endif /* SCANF_FLOAT_ENABLE */ + if (((*c) >= '0') && ((*c) <= '9')) + { + { + char *p; + errno = 0; + (*field_width) = strtoul(c, &p, 10); + if (0 != errno) + { + *field_width = 0U; + } + c = p - 1; + } + } + else if ('d' == (*c)) + { + (*base) = 10U; + (*flag) |= (uint32_t)kSCANF_TypeSinged; + (*flag) |= (uint32_t)kSCANF_DestInt; + } + else if ('u' == (*c)) + { + (*base) = 10U; + (*flag) |= (uint32_t)kSCANF_DestInt; + } + else if ('o' == (*c)) + { + (*base) = 8U; + (*flag) |= (uint32_t)kSCANF_DestInt; + } + else if (('x' == (*c))) + { + (*base) = 16U; + (*flag) |= (uint32_t)kSCANF_DestInt; + } + else if ('X' == (*c)) + { + (*base) = 16U; + (*flag) |= (uint32_t)kSCANF_DestInt; + } + else if ('i' == (*c)) + { + (*base) = 0U; + (*flag) |= (uint32_t)kSCANF_DestInt; + } +#if SCANF_FLOAT_ENABLE + else if (1U == StrFormatScanIsFloat(c)) + { + (*flag) |= (uint32_t)kSCANF_DestFloat; + } +#endif /* SCANF_FLOAT_ENABLE */ + else if ('c' == (*c)) + { + (*flag) |= (uint32_t)kSCANF_DestChar; + if (MAX_FIELD_WIDTH == (*field_width)) + { + (*field_width) = 1; + } + } + else if ('s' == (*c)) + { + (*flag) |= (uint32_t)kSCANF_DestString; + } + else + { + exitPending = 1U; + } + + if (1U == exitPending) + { + break; + } + else + { + c++; + } + } + *str = c; + return exitPending; +} + +/*! + * 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. + * retval IO_EOF When line_ptr is empty string "". + */ +int StrFormatScanf(const char *line_ptr, char *format, va_list args_ptr) +{ + uint8_t base; + int8_t neg; + /* Identifier for the format string. */ + char *c = format; + char *buf; + /* 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; + + uint8_t added; + + uint8_t exitPending = 0; + + const char *s; +#if SCANF_FLOAT_ENABLE + char *s_temp; /* MISRA C-2012 Rule 11.3 */ +#endif + + /* Identifier for the input string. */ + const char *p = line_ptr; + +#if SCANF_FLOAT_ENABLE + double fnum = 0.0; +#endif /* SCANF_FLOAT_ENABLE */ + /* Return EOF error before any conversion. */ + if (*p == '\0') + { + return -1; + } + + /* Decode directives. */ + while (('\0' != (*c)) && ('\0' != (*p))) + { + /* Ignore all white-spaces in the format strings. */ + if (0U != ScanIgnoreWhiteSpace((const char **)((void *)&c))) + { + n_decode += ScanIgnoreWhiteSpace(&p); + } + else if (0U == StrFormatScanIsFormatStarting(c)) + { + /* Ordinary characters. */ + c++; + 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++; + /* Reset. */ + flag = 0; + field_width = MAX_FIELD_WIDTH; + base = 0; + added = 0U; + + exitPending = StrFormatScanfStringHandling(&c, &flag, &field_width, &base); + + if (1U == exitPending) + { + /* Format strings are exhausted. */ + break; + } + + /* Matching strings in input streams and assign to argument. */ + if ((flag & (uint32_t)kSCANF_DestMask) == (uint32_t)kSCANF_DestChar) + { + s = (const char *)p; + buf = va_arg(args_ptr, char *); + while ((0U != (field_width--)) +#if SCANF_ADVANCED_ENABLE + && ('\0' != (*p)) +#endif + ) + { +#if SCANF_ADVANCED_ENABLE + if (0U != (flag & (uint32_t)kSCANF_Suppress)) + { + p++; + } + else +#endif + { + *buf++ = *p++; +#if SCANF_ADVANCED_ENABLE + added = 1u; +#endif + } + n_decode++; + } + +#if SCANF_ADVANCED_ENABLE + if (1u == added) +#endif + { + nassigned++; + } + } + else if ((flag & (uint32_t)kSCANF_DestMask) == (uint32_t)kSCANF_DestString) + { + n_decode += ScanIgnoreWhiteSpace(&p); + s = p; + buf = va_arg(args_ptr, char *); + while ((0U != (field_width--)) && (*p != '\0') && (0U == ScanIsWhiteSpace(*p))) + { +#if SCANF_ADVANCED_ENABLE + if (0U != (flag & (uint32_t)kSCANF_Suppress)) + { + p++; + } + else +#endif + { + *buf++ = *p++; +#if SCANF_ADVANCED_ENABLE + added = 1u; +#endif + } + n_decode++; + } + +#if SCANF_ADVANCED_ENABLE + if (1u == added) +#endif + { + /* Add NULL to end of string. */ + *buf = '\0'; + nassigned++; + } + } + else if ((flag & (uint32_t)kSCANF_DestMask) == (uint32_t)kSCANF_DestInt) + { + n_decode += ScanIgnoreWhiteSpace(&p); + s = p; + val = 0; + base = StrFormatScanGetBase(base, s); + + added = StrFormatScanCheckSymbol(p, &neg); + n_decode += added; + p += added; + field_width -= added; + + s = p; + if (strlen(p) > field_width) + { + char temp[12]; + char *tempEnd; + (void)memcpy(temp, p, sizeof(temp) - 1U); + temp[sizeof(temp) - 1U] = '\0'; + errno = 0; + val = (int32_t)strtoul(temp, &tempEnd, (int)base); + if (0 != errno) + { + break; + } + p = p + (tempEnd - temp); + } + else + { + char *tempEnd; + val = 0; + errno = 0; + val = (int32_t)strtoul(p, &tempEnd, (int)base); + if (0 != errno) + { + break; + } + p = tempEnd; + } + n_decode += (uint32_t)p - (uint32_t)s; + + val *= neg; + + nassigned += StrFormatScanFillInteger(flag, &args_ptr, val); + } +#if SCANF_FLOAT_ENABLE + else if ((flag & (uint32_t)kSCANF_DestMask) == (uint32_t)kSCANF_DestFloat) + { + n_decode += ScanIgnoreWhiteSpace(&p); + fnum = 0.0; + errno = 0; + + fnum = strtod(p, (char **)&s_temp); + s = s_temp; /* MISRA C-2012 Rule 11.3 */ + + /* MISRA C-2012 Rule 22.9 */ + if (0 != errno) + { + break; + } + + if ((fnum < HUGE_VAL) && (fnum > -HUGE_VAL)) + { + n_decode = (uint32_t)n_decode + (uint32_t)s - (uint32_t)p; + p = s; + nassigned += StrFormatScanFillFloat(flag, &args_ptr, fnum); + } + } +#endif /* SCANF_FLOAT_ENABLE */ + else + { + break; + } + } + } + return (int)nassigned; +} |