1 /*
2  * Copyright 2017, 2020 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  */
9 #include <math.h>
10 #include <stdarg.h>
11 #include <stdlib.h>
12 #include <errno.h> /* MISRA C-2012 Rule 22.9 */
13 #include "fsl_str.h"
14 #include "fsl_debug_console_conf.h"
15 
16 /*******************************************************************************
17  * Definitions
18  ******************************************************************************/
19 
20 /*! @brief The overflow value.*/
21 #ifndef HUGE_VAL
22 #define HUGE_VAL (99.e99)
23 #endif /* HUGE_VAL */
24 
25 #ifndef MAX_FIELD_WIDTH
26 #define MAX_FIELD_WIDTH 99U
27 #endif
28 
29 #if PRINTF_ADVANCED_ENABLE
30 /*! @brief Specification modifier flags for printf. */
31 enum _debugconsole_printf_flag
32 {
33     kPRINTF_Minus             = 0x01U,  /*!< Minus FLag. */
34     kPRINTF_Plus              = 0x02U,  /*!< Plus Flag. */
35     kPRINTF_Space             = 0x04U,  /*!< Space Flag. */
36     kPRINTF_Zero              = 0x08U,  /*!< Zero Flag. */
37     kPRINTF_Pound             = 0x10U,  /*!< Pound Flag. */
38     kPRINTF_LengthChar        = 0x20U,  /*!< Length: Char Flag. */
39     kPRINTF_LengthShortInt    = 0x40U,  /*!< Length: Short Int Flag. */
40     kPRINTF_LengthLongInt     = 0x80U,  /*!< Length: Long Int Flag. */
41     kPRINTF_LengthLongLongInt = 0x100U, /*!< Length: Long Long Int Flag. */
42 };
43 #endif /* PRINTF_ADVANCED_ENABLE */
44 
45 /*! @brief Specification modifier flags for scanf. */
46 enum _debugconsole_scanf_flag
47 {
48     kSCANF_Suppress   = 0x2U,    /*!< Suppress Flag. */
49     kSCANF_DestMask   = 0x7cU,   /*!< Destination Mask. */
50     kSCANF_DestChar   = 0x4U,    /*!< Destination Char Flag. */
51     kSCANF_DestString = 0x8U,    /*!< Destination String FLag. */
52     kSCANF_DestSet    = 0x10U,   /*!< Destination Set Flag. */
53     kSCANF_DestInt    = 0x20U,   /*!< Destination Int Flag. */
54     kSCANF_DestFloat  = 0x30U,   /*!< Destination Float Flag. */
55     kSCANF_LengthMask = 0x1f00U, /*!< Length Mask Flag. */
56 #if SCANF_ADVANCED_ENABLE
57     kSCANF_LengthChar        = 0x100U, /*!< Length Char Flag. */
58     kSCANF_LengthShortInt    = 0x200U, /*!< Length ShortInt Flag. */
59     kSCANF_LengthLongInt     = 0x400U, /*!< Length LongInt Flag. */
60     kSCANF_LengthLongLongInt = 0x800U, /*!< Length LongLongInt Flag. */
61 #endif                                 /* SCANF_ADVANCED_ENABLE */
62 #if SCANF_FLOAT_ENABLE
63     kSCANF_LengthLongLongDouble = 0x1000U, /*!< Length LongLongDuoble Flag. */
64 #endif                                     /*PRINTF_FLOAT_ENABLE */
65     kSCANF_TypeSinged = 0x2000U,           /*!< TypeSinged Flag. */
66 };
67 
68 /*! @brief Keil: suppress ellipsis warning in va_arg usage below. */
69 #if defined(__CC_ARM)
70 #pragma diag_suppress 1256
71 #endif /* __CC_ARM */
72 
73 /*******************************************************************************
74  * Prototypes
75  ******************************************************************************/
76 /*!
77  * @brief Scanline function which ignores white spaces.
78  *
79  * @param[in]   s The address of the string pointer to update.
80  * @return      String without white spaces.
81  */
82 static uint32_t ScanIgnoreWhiteSpace(const char **s);
83 
84 /*!
85  * @brief Converts a radix number to a string and return its length.
86  *
87  * @param[in] numstr    Converted string of the number.
88  * @param[in] nump      Pointer to the number.
89  * @param[in] neg       Polarity of the number.
90  * @param[in] radix     The radix to be converted to.
91  * @param[in] use_caps  Used to identify %x/X output format.
92 
93  * @return Length of the converted string.
94  */
95 static int32_t ConvertRadixNumToString(char *numstr, void *nump, unsigned int neg, unsigned int radix, bool use_caps);
96 
97 #if PRINTF_FLOAT_ENABLE
98 /*!
99  * @brief Converts a floating radix number to a string and return its length.
100  *
101  * @param[in] numstr            Converted string of the number.
102  * @param[in] nump              Pointer to the number.
103  * @param[in] radix             The radix to be converted to.
104  * @param[in] precision_width   Specify the precision width.
105 
106  * @return Length of the converted string.
107  */
108 static int32_t ConvertFloatRadixNumToString(char *numstr, void *nump, int32_t radix, uint32_t precision_width);
109 
110 #endif /* PRINTF_FLOAT_ENABLE */
111 
112 /*************Code for process formatted data*******************************/
113 #if PRINTF_ADVANCED_ENABLE
PrintGetSignChar(long long int ival,uint32_t flags_used,char * schar)114 static uint8_t PrintGetSignChar(long long int ival, uint32_t flags_used, char *schar)
115 {
116     uint8_t len = 1U;
117     if (ival < 0)
118     {
119         *schar = '-';
120     }
121     else
122     {
123         if (0U != (flags_used & (uint32_t)kPRINTF_Plus))
124         {
125             *schar = '+';
126         }
127         else if (0U != (flags_used & (uint32_t)kPRINTF_Space))
128         {
129             *schar = ' ';
130         }
131         else
132         {
133             *schar = '\0';
134             len    = 0U;
135         }
136     }
137     return len;
138 }
139 #endif /* PRINTF_ADVANCED_ENABLE */
140 
PrintGetWidth(const char ** p,va_list * ap)141 static uint32_t PrintGetWidth(const char **p, va_list *ap)
142 {
143     uint32_t field_width = 0;
144     uint8_t done         = 0U;
145     char c;
146 
147     while (0U == done)
148     {
149         c = *(++(*p));
150         if ((c >= '0') && (c <= '9'))
151         {
152             (field_width) = ((field_width)*10U) + ((uint32_t)c - (uint32_t)'0');
153         }
154 #if PRINTF_ADVANCED_ENABLE
155         else if (c == '*')
156         {
157             (field_width) = (uint32_t)va_arg(*ap, uint32_t);
158         }
159 #endif /* PRINTF_ADVANCED_ENABLE */
160         else
161         {
162             /* We've gone one char too far. */
163             --(*p);
164             done = 1U;
165         }
166     }
167     return field_width;
168 }
169 
PrintGetPrecision(const char ** s,va_list * ap,bool * valid_precision_width)170 static uint32_t PrintGetPrecision(const char **s, va_list *ap, bool *valid_precision_width)
171 {
172     const char *p            = *s;
173     uint32_t precision_width = 6U;
174     uint8_t done             = 0U;
175 
176 #if PRINTF_ADVANCED_ENABLE
177     if (NULL != valid_precision_width)
178     {
179         *valid_precision_width = false;
180     }
181 #endif /* PRINTF_ADVANCED_ENABLE */
182     if (*++p == '.')
183     {
184         /* Must get precision field width, if present. */
185         precision_width = 0U;
186         done            = 0U;
187         while (0U == done)
188         {
189             char c = *++p;
190             if ((c >= '0') && (c <= '9'))
191             {
192                 precision_width = (precision_width * 10U) + ((uint32_t)c - (uint32_t)'0');
193 #if PRINTF_ADVANCED_ENABLE
194                 if (NULL != valid_precision_width)
195                 {
196                     *valid_precision_width = true;
197                 }
198 #endif /* PRINTF_ADVANCED_ENABLE */
199             }
200 #if PRINTF_ADVANCED_ENABLE
201             else if (c == '*')
202             {
203                 precision_width = (uint32_t)va_arg(*ap, uint32_t);
204                 if (NULL != valid_precision_width)
205                 {
206                     *valid_precision_width = true;
207                 }
208             }
209 #endif /* PRINTF_ADVANCED_ENABLE */
210             else
211             {
212                 /* We've gone one char too far. */
213                 --p;
214                 done = 1U;
215             }
216         }
217     }
218     else
219     {
220         /* We've gone one char too far. */
221         --p;
222     }
223     *s = p;
224     return precision_width;
225 }
226 
PrintIsobpu(const char c)227 static uint32_t PrintIsobpu(const char c)
228 {
229     uint32_t ret = 0U;
230     if ((c == 'o') || (c == 'b') || (c == 'p') || (c == 'u'))
231     {
232         ret = 1U;
233     }
234     return ret;
235 }
236 
PrintIsdi(const char c)237 static uint32_t PrintIsdi(const char c)
238 {
239     uint32_t ret = 0U;
240     if ((c == 'd') || (c == 'i'))
241     {
242         ret = 1U;
243     }
244     return ret;
245 }
246 
PrintOutputdifFobpu(uint32_t flags_used,uint32_t field_width,uint32_t vlen,char schar,char * vstrp,printfCb cb,char * buf,int32_t * count)247 static void PrintOutputdifFobpu(uint32_t flags_used,
248                                 uint32_t field_width,
249                                 uint32_t vlen,
250                                 char schar,
251                                 char *vstrp,
252                                 printfCb cb,
253                                 char *buf,
254                                 int32_t *count)
255 {
256 #if PRINTF_ADVANCED_ENABLE
257     /* Do the ZERO pad. */
258     if (0U != (flags_used & (uint32_t)kPRINTF_Zero))
259     {
260         if ('\0' != schar)
261         {
262             cb(buf, count, schar, 1);
263             schar = '\0';
264         }
265         cb(buf, count, '0', (int)field_width - (int)vlen);
266         vlen = field_width;
267     }
268     else
269     {
270         if (0U == (flags_used & (uint32_t)kPRINTF_Minus))
271         {
272             cb(buf, count, ' ', (int)field_width - (int)vlen);
273             if ('\0' != schar)
274             {
275                 cb(buf, count, schar, 1);
276                 schar = '\0';
277             }
278         }
279     }
280     /* The string was built in reverse order, now display in correct order. */
281     if ('\0' != schar)
282     {
283         cb(buf, count, schar, 1);
284     }
285 #else
286     cb(buf, count, ' ', (int)field_width - (int)vlen);
287 #endif /* PRINTF_ADVANCED_ENABLE */
288     while ('\0' != (*vstrp))
289     {
290         cb(buf, count, *vstrp--, 1);
291     }
292 #if PRINTF_ADVANCED_ENABLE
293     if (0U != (flags_used & (uint32_t)kPRINTF_Minus))
294     {
295         cb(buf, count, ' ', (int)field_width - (int)vlen);
296     }
297 #endif /* PRINTF_ADVANCED_ENABLE */
298 }
299 
PrintOutputxX(uint32_t flags_used,uint32_t field_width,uint32_t vlen,bool use_caps,char * vstrp,printfCb cb,char * buf,int32_t * count)300 static void PrintOutputxX(uint32_t flags_used,
301                           uint32_t field_width,
302                           uint32_t vlen,
303                           bool use_caps,
304                           char *vstrp,
305                           printfCb cb,
306                           char *buf,
307                           int32_t *count)
308 {
309 #if PRINTF_ADVANCED_ENABLE
310     uint8_t dschar = 0;
311     if (0U != (flags_used & (uint32_t)kPRINTF_Zero))
312     {
313         if (0U != (flags_used & (uint32_t)kPRINTF_Pound))
314         {
315             cb(buf, count, '0', 1);
316             cb(buf, count, (use_caps ? 'X' : 'x'), 1);
317             dschar = 1U;
318         }
319         cb(buf, count, '0', (int)field_width - (int)vlen);
320         vlen = field_width;
321     }
322     else
323     {
324         if (0U == (flags_used & (uint32_t)kPRINTF_Minus))
325         {
326             if (0U != (flags_used & (uint32_t)kPRINTF_Pound))
327             {
328                 vlen += 2U;
329             }
330             cb(buf, count, ' ', (int)field_width - (int)vlen);
331             if (0U != (flags_used & (uint32_t)kPRINTF_Pound))
332             {
333                 cb(buf, count, '0', 1);
334                 cb(buf, count, (use_caps ? 'X' : 'x'), 1);
335                 dschar = 1U;
336             }
337         }
338     }
339 
340     if ((0U != (flags_used & (uint32_t)kPRINTF_Pound)) && (0U == dschar))
341     {
342         cb(buf, count, '0', 1);
343         cb(buf, count, (use_caps ? 'X' : 'x'), 1);
344         vlen += 2U;
345     }
346 #else
347     cb(buf, count, ' ', (int)field_width - (int)vlen);
348 #endif /* PRINTF_ADVANCED_ENABLE */
349     while ('\0' != (*vstrp))
350     {
351         cb(buf, count, *vstrp--, 1);
352     }
353 #if PRINTF_ADVANCED_ENABLE
354     if (0U != (flags_used & (uint32_t)kPRINTF_Minus))
355     {
356         cb(buf, count, ' ', (int)field_width - (int)vlen);
357     }
358 #endif /* PRINTF_ADVANCED_ENABLE */
359 }
360 
PrintIsfF(const char c)361 static uint32_t PrintIsfF(const char c)
362 {
363     uint32_t ret = 0U;
364     if ((c == 'f') || (c == 'F'))
365     {
366         ret = 1U;
367     }
368     return ret;
369 }
370 
PrintIsxX(const char c)371 static uint32_t PrintIsxX(const char c)
372 {
373     uint32_t ret = 0U;
374     if ((c == 'x') || (c == 'X'))
375     {
376         ret = 1U;
377     }
378     return ret;
379 }
380 
381 #if PRINTF_ADVANCED_ENABLE
PrintCheckFlags(const char ** s)382 static uint32_t PrintCheckFlags(const char **s)
383 {
384     const char *p = *s;
385     /* First check for specification modifier flags. */
386     uint32_t flags_used = 0U;
387     bool done           = false;
388     while (false == done)
389     {
390         switch (*++p)
391         {
392             case '-':
393                 flags_used |= (uint32_t)kPRINTF_Minus;
394                 break;
395             case '+':
396                 flags_used |= (uint32_t)kPRINTF_Plus;
397                 break;
398             case ' ':
399                 flags_used |= (uint32_t)kPRINTF_Space;
400                 break;
401             case '0':
402                 flags_used |= (uint32_t)kPRINTF_Zero;
403                 break;
404             case '#':
405                 flags_used |= (uint32_t)kPRINTF_Pound;
406                 break;
407             default:
408                 /* We've gone one char too far. */
409                 --p;
410                 done = true;
411                 break;
412         }
413     }
414     *s = p;
415     return flags_used;
416 }
417 #endif /* PRINTF_ADVANCED_ENABLE */
418 
419 #if PRINTF_ADVANCED_ENABLE
420 /*
421  * Check for the length modifier.
422  */
PrintGetLengthFlag(const char ** s)423 static uint32_t PrintGetLengthFlag(const char **s)
424 {
425     const char *p = *s;
426     /* First check for specification modifier flags. */
427     uint32_t flags_used = 0U;
428 
429     switch (/* c = */ *++p)
430     {
431         case 'h':
432             if (*++p != 'h')
433             {
434                 flags_used |= (uint32_t)kPRINTF_LengthShortInt;
435                 --p;
436             }
437             else
438             {
439                 flags_used |= (uint32_t)kPRINTF_LengthChar;
440             }
441             break;
442         case 'l':
443             if (*++p != 'l')
444             {
445                 flags_used |= (uint32_t)kPRINTF_LengthLongInt;
446                 --p;
447             }
448             else
449             {
450                 flags_used |= (uint32_t)kPRINTF_LengthLongLongInt;
451             }
452             break;
453         default:
454             /* we've gone one char too far */
455             --p;
456             break;
457     }
458     *s = p;
459     return flags_used;
460 }
461 #else
PrintFilterLengthFlag(const char ** s)462 static void PrintFilterLengthFlag(const char **s)
463 {
464     const char *p = *s;
465     char ch;
466 
467     do
468     {
469         ch = *++p;
470     } while ((ch == 'h') || (ch == 'l'));
471 
472     *s = --p;
473 }
474 #endif /* PRINTF_ADVANCED_ENABLE */
475 
PrintGetRadixFromobpu(const char c)476 static uint8_t PrintGetRadixFromobpu(const char c)
477 {
478     uint8_t radix;
479 
480     if (c == 'o')
481     {
482         radix = 8U;
483     }
484     else if (c == 'b')
485     {
486         radix = 2U;
487     }
488     else if (c == 'p')
489     {
490         radix = 16U;
491     }
492     else
493     {
494         radix = 10U;
495     }
496     return radix;
497 }
498 
ScanIsWhiteSpace(const char c)499 static uint32_t ScanIsWhiteSpace(const char c)
500 {
501     uint32_t ret = 0U;
502     if ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r') || (c == '\v') || (c == '\f'))
503     {
504         ret = 1U;
505     }
506     return ret;
507 }
508 
ScanIgnoreWhiteSpace(const char ** s)509 static uint32_t ScanIgnoreWhiteSpace(const char **s)
510 {
511     uint32_t count = 0U;
512     char c;
513 
514     c = **s;
515     while (1U == ScanIsWhiteSpace(c))
516     {
517         count++;
518         (*s)++;
519         c = **s;
520     }
521     return count;
522 }
523 
ConvertRadixNumToString(char * numstr,void * nump,unsigned int neg,unsigned int radix,bool use_caps)524 static int32_t ConvertRadixNumToString(char *numstr, void *nump, unsigned int neg, unsigned int radix, bool use_caps)
525 {
526 #if PRINTF_ADVANCED_ENABLE
527     long long int a;
528     long long int b;
529     long long int c;
530 
531     unsigned long long int ua;
532     unsigned long long int ub;
533     unsigned long long int uc;
534     unsigned long long int uc_param;
535 #else
536     int a;
537     int b;
538     int c;
539 
540     unsigned int ua;
541     unsigned int ub;
542     unsigned int uc;
543     unsigned int uc_param;
544 #endif /* PRINTF_ADVANCED_ENABLE */
545 
546     int32_t nlen;
547     char *nstrp;
548 
549     nlen     = 0;
550     nstrp    = numstr;
551     *nstrp++ = '\0';
552 
553 #if !(PRINTF_ADVANCED_ENABLE > 0)
554     neg = 0U;
555 #endif
556 
557 #if PRINTF_ADVANCED_ENABLE
558     a        = 0;
559     b        = 0;
560     c        = 0;
561     ua       = 0ULL;
562     ub       = 0ULL;
563     uc       = 0ULL;
564     uc_param = 0ULL;
565 #else
566     a = 0;
567     b = 0;
568     c = 0;
569     ua = 0U;
570     ub = 0U;
571     uc = 0U;
572     uc_param = 0U;
573 #endif /* PRINTF_ADVANCED_ENABLE */
574 
575     (void)a;
576     (void)b;
577     (void)c;
578     (void)ua;
579     (void)ub;
580     (void)uc;
581     (void)uc_param;
582     (void)neg;
583     /*
584      * Fix MISRA issue: CID 15972928 (#15 of 15): MISRA C-2012 Control Flow Expressions (MISRA C-2012 Rule 14.3)
585      * misra_c_2012_rule_14_3_violation: Execution cannot reach this statement: a = *((int *)nump);
586      */
587 #if PRINTF_ADVANCED_ENABLE
588     if (0U != neg)
589     {
590 #if PRINTF_ADVANCED_ENABLE
591         a = *(long long int *)nump;
592 #else
593         a = *(int *)nump;
594 #endif /* PRINTF_ADVANCED_ENABLE */
595         if (a == 0)
596         {
597             *nstrp = '0';
598             ++nlen;
599             return nlen;
600         }
601         while (a != 0)
602         {
603 #if PRINTF_ADVANCED_ENABLE
604             b = (long long int)a / (long long int)radix;
605             c = (long long int)a - ((long long int)b * (long long int)radix);
606             if (c < 0)
607             {
608                 uc       = (unsigned long long int)c;
609                 uc_param = ~uc;
610                 c        = (long long int)uc_param + 1 + (long long int)'0';
611             }
612 #else
613             b = (int)a / (int)radix;
614             c = (int)a - ((int)b * (int)radix);
615             if (c < 0)
616             {
617                 uc       = (unsigned int)c;
618                 uc_param = ~uc;
619                 c        = (int)uc_param + 1 + (int)'0';
620             }
621 #endif /* PRINTF_ADVANCED_ENABLE */
622             else
623             {
624                 c = c + (int)'0';
625             }
626             a        = b;
627             *nstrp++ = (char)c;
628             ++nlen;
629         }
630     }
631     else
632 #endif /* PRINTF_ADVANCED_ENABLE */
633     {
634 #if PRINTF_ADVANCED_ENABLE
635         ua = *(unsigned long long int *)nump;
636 #else
637         ua = *(unsigned int *)nump;
638 #endif /* PRINTF_ADVANCED_ENABLE */
639         if (ua == 0U)
640         {
641             *nstrp = '0';
642             ++nlen;
643             return nlen;
644         }
645         while (ua != 0U)
646         {
647 #if PRINTF_ADVANCED_ENABLE
648             ub = (unsigned long long int)ua / (unsigned long long int)radix;
649             uc = (unsigned long long int)ua - ((unsigned long long int)ub * (unsigned long long int)radix);
650 #else
651             ub = ua / (unsigned int)radix;
652             uc = ua - (ub * (unsigned int)radix);
653 #endif /* PRINTF_ADVANCED_ENABLE */
654 
655             if (uc < 10U)
656             {
657                 uc = uc + (unsigned int)'0';
658             }
659             else
660             {
661                 uc = uc - 10U + (unsigned int)(use_caps ? 'A' : 'a');
662             }
663             ua       = ub;
664             *nstrp++ = (char)uc;
665             ++nlen;
666         }
667     }
668     return nlen;
669 }
670 
671 #if PRINTF_FLOAT_ENABLE
ConvertFloatRadixNumToString(char * numstr,void * nump,int32_t radix,uint32_t precision_width)672 static int32_t ConvertFloatRadixNumToString(char *numstr, void *nump, int32_t radix, uint32_t precision_width)
673 {
674     int32_t a;
675     int32_t b;
676     int32_t c;
677     int32_t i;
678     uint32_t uc;
679     double fa;
680     double dc;
681     double fb;
682     double r;
683     double fractpart;
684     double intpart;
685 
686     int32_t nlen;
687     char *nstrp;
688     nlen     = 0;
689     nstrp    = numstr;
690     *nstrp++ = '\0';
691     r        = *(double *)nump;
692     if (0.0 == r)
693     {
694         *nstrp = '0';
695         ++nlen;
696         return nlen;
697     }
698     fractpart = modf((double)r, (double *)&intpart);
699     /* Process fractional part. */
700     for (i = 0; i < (int32_t)precision_width; i++)
701     {
702         fractpart *= (double)radix;
703     }
704     if (r >= (double)0.0)
705     {
706         fa = fractpart + (double)0.5;
707         if (fa >= pow((double)10, (double)precision_width))
708         {
709             intpart++;
710         }
711     }
712     else
713     {
714         fa = fractpart - (double)0.5;
715         if (fa <= -pow((double)10, (double)precision_width))
716         {
717             intpart--;
718         }
719     }
720     for (i = 0; i < (int32_t)precision_width; i++)
721     {
722         fb = fa / (double)radix;
723         dc = (fa - (double)(long long int)fb * (double)radix);
724         c  = (int32_t)dc;
725         if (c < 0)
726         {
727             uc = (uint32_t)c;
728             uc = ~uc;
729             c  = (int32_t)uc;
730             c += (int32_t)1;
731             c += (int32_t)'0';
732         }
733         else
734         {
735             c = c + '0';
736         }
737         fa       = fb;
738         *nstrp++ = (char)c;
739         ++nlen;
740     }
741     *nstrp++ = (char)'.';
742     ++nlen;
743     a = (int32_t)intpart;
744     if (a == 0)
745     {
746         *nstrp++ = '0';
747         ++nlen;
748     }
749     else
750     {
751         while (a != 0)
752         {
753             b = (int32_t)a / (int32_t)radix;
754             c = (int32_t)a - ((int32_t)b * (int32_t)radix);
755             if (c < 0)
756             {
757                 uc = (uint32_t)c;
758                 uc = ~uc;
759                 c  = (int32_t)uc;
760                 c += (int32_t)1;
761                 c += (int32_t)'0';
762             }
763             else
764             {
765                 c = c + '0';
766             }
767             a        = b;
768             *nstrp++ = (char)c;
769             ++nlen;
770         }
771     }
772     return nlen;
773 }
774 #endif /* PRINTF_FLOAT_ENABLE */
775 
776 /*!
777  * brief This function outputs its parameters according to a formatted string.
778  *
779  * note I/O is performed by calling given function pointer using following
780  * (*func_ptr)(c);
781  *
782  * param[in] fmt   Format string for printf.
783  * param[in] ap    Arguments to printf.
784  * param[in] buf  pointer to the buffer
785  * param cb print callback function pointer
786  *
787  * return Number of characters to be print
788  */
StrFormatPrintf(const char * fmt,va_list ap,char * buf,printfCb cb)789 int StrFormatPrintf(const char *fmt, va_list ap, char *buf, printfCb cb)
790 {
791     /* va_list ap; */
792     const char *p;
793     char c;
794 
795     char vstr[33];
796     char *vstrp  = NULL;
797     int32_t vlen = 0;
798 
799     int32_t count = 0;
800 
801     uint32_t field_width;
802     uint32_t precision_width;
803     char *sval;
804     int32_t cval;
805     bool use_caps;
806     unsigned int radix = 0;
807 
808 #if PRINTF_ADVANCED_ENABLE
809     uint32_t flags_used;
810     char schar;
811     long long int ival;
812     unsigned long long int uval = 0;
813 #define STR_FORMAT_PRINTF_UVAL_TYPE unsigned long long int
814 #define STR_FORMAT_PRINTF_IVAL_TYPE long long int
815     bool valid_precision_width;
816 #else
817     int ival;
818     unsigned int uval = 0;
819 #define STR_FORMAT_PRINTF_UVAL_TYPE unsigned int
820 #define STR_FORMAT_PRINTF_IVAL_TYPE int
821 #endif /* PRINTF_ADVANCED_ENABLE */
822 
823 #if PRINTF_FLOAT_ENABLE
824     double fval;
825 #endif /* PRINTF_FLOAT_ENABLE */
826 
827     /* Start parsing apart the format string and display appropriate formats and data. */
828     p = fmt;
829     while (true)
830     {
831         if ('\0' == *p)
832         {
833             break;
834         }
835         c = *p;
836         /*
837          * All formats begin with a '%' marker.  Special chars like
838          * '\n' or '\t' are normally converted to the appropriate
839          * character by the __compiler__.  Thus, no need for this
840          * routine to account for the '\' character.
841          */
842         if (c != '%')
843         {
844             cb(buf, &count, c, 1);
845             p++;
846             /* By using 'continue', the next iteration of the loop is used, skipping the code that follows. */
847             continue;
848         }
849 
850         use_caps = true;
851 
852 #if PRINTF_ADVANCED_ENABLE
853         /* First check for specification modifier flags. */
854         flags_used = PrintCheckFlags(&p);
855 #endif /* PRINTF_ADVANCED_ENABLE */
856 
857         /* Next check for minimum field width. */
858         field_width = PrintGetWidth(&p, &ap);
859 
860         /* Next check for the width and precision field separator. */
861 #if PRINTF_ADVANCED_ENABLE
862         precision_width = PrintGetPrecision(&p, &ap, &valid_precision_width);
863 #else
864         precision_width = PrintGetPrecision(&p, &ap, NULL);
865         (void)precision_width;
866 #endif
867 
868 #if PRINTF_ADVANCED_ENABLE
869         /* Check for the length modifier. */
870         flags_used |= PrintGetLengthFlag(&p);
871 #else
872         /* Filter length modifier. */
873         PrintFilterLengthFlag(&p);
874 #endif
875 
876         /* Now we're ready to examine the format. */
877         c = *++p;
878         {
879             if (1U == PrintIsdi(c))
880             {
881 #if PRINTF_ADVANCED_ENABLE
882                 if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongLongInt))
883                 {
884                     ival = (long long int)va_arg(ap, long long int);
885                 }
886                 else if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongInt))
887                 {
888                     ival = (long long int)va_arg(ap, long int);
889                 }
890                 else
891 #endif /* PRINTF_ADVANCED_ENABLE */
892                 {
893                     ival = (STR_FORMAT_PRINTF_IVAL_TYPE)va_arg(ap, int);
894                 }
895 
896                 vlen  = ConvertRadixNumToString((char *)vstr, (void *)&ival, 1, 10, use_caps);
897                 vstrp = &vstr[vlen];
898 #if PRINTF_ADVANCED_ENABLE
899                 vlen += (int)PrintGetSignChar(ival, flags_used, &schar);
900                 PrintOutputdifFobpu(flags_used, field_width, (unsigned int)vlen, schar, vstrp, cb, buf, &count);
901 #else
902                 PrintOutputdifFobpu(0U, field_width, (unsigned int)vlen, '\0', vstrp, cb, buf, &count);
903 #endif
904             }
905             else if (1U == PrintIsfF(c))
906             {
907 #if PRINTF_FLOAT_ENABLE
908                 fval  = (double)va_arg(ap, double);
909                 vlen  = ConvertFloatRadixNumToString(vstr, &fval, 10, precision_width);
910                 vstrp = &vstr[vlen];
911 
912 #if PRINTF_ADVANCED_ENABLE
913                 vlen += (int32_t)PrintGetSignChar(((fval < 0.0) ? ((long long int)-1) : ((long long int)fval)),
914                                                   flags_used, &schar);
915                 PrintOutputdifFobpu(flags_used, field_width, (unsigned int)vlen, schar, vstrp, cb, buf, &count);
916 #else
917                 PrintOutputdifFobpu(0, field_width, (unsigned int)vlen, '\0', vstrp, cb, buf, &count);
918 #endif
919 
920 #else
921                 (void)va_arg(ap, double);
922 #endif /* PRINTF_FLOAT_ENABLE */
923             }
924             else if (1U == PrintIsxX(c))
925             {
926                 if (c == 'x')
927                 {
928                     use_caps = false;
929                 }
930 #if PRINTF_ADVANCED_ENABLE
931                 if (0U != (flags_used & (unsigned int)kPRINTF_LengthLongLongInt))
932                 {
933                     uval = (unsigned long long int)va_arg(ap, unsigned long long int);
934                 }
935                 else if (0U != (flags_used & (unsigned int)kPRINTF_LengthLongInt))
936                 {
937                     uval = (unsigned long long int)va_arg(ap, unsigned long int);
938                 }
939                 else
940 #endif /* PRINTF_ADVANCED_ENABLE */
941                 {
942                     uval = (STR_FORMAT_PRINTF_UVAL_TYPE)va_arg(ap, unsigned int);
943                 }
944 
945                 vlen  = ConvertRadixNumToString((char *)vstr, (void *)&uval, 0, 16, use_caps);
946                 vstrp = &vstr[vlen];
947 #if PRINTF_ADVANCED_ENABLE
948                 PrintOutputxX(flags_used, field_width, (unsigned int)vlen, use_caps, vstrp, cb, buf, &count);
949 #else
950                 PrintOutputxX(0U, field_width, (uint32_t)vlen, use_caps, vstrp, cb, buf, &count);
951 #endif
952             }
953             else if (1U == PrintIsobpu(c))
954             {
955                 if ('p' == c)
956                 {
957                     /*
958                      * Fix MISRA issue: CID 17205581 (#15 of 15): MISRA C-2012 Pointer Type Conversions (MISRA C-2012
959                      * Rule 11.6) 1.misra_c_2012_rule_11_6_violation: The expression va_arg (ap, void *) of type void *
960                      * is cast to type uint32_t.
961                      *
962                      * Orignal code: uval = (STR_FORMAT_PRINTF_UVAL_TYPE)(uint32_t)va_arg(ap, void *);
963                      */
964                     void *pval;
965                     pval = (void *)va_arg(ap, void *);
966                     (void)memcpy((void *)&uval, (void *)&pval, sizeof(void *));
967                 }
968                 else
969                 {
970 #if PRINTF_ADVANCED_ENABLE
971                     if (0U != (flags_used & (unsigned int)kPRINTF_LengthLongLongInt))
972                     {
973                         uval = (unsigned long long int)va_arg(ap, unsigned long long int);
974                     }
975                     else if (0U != (flags_used & (unsigned int)kPRINTF_LengthLongInt))
976                     {
977                         uval = (unsigned long long int)va_arg(ap, unsigned long int);
978                     }
979                     else
980                     {
981 #endif /* PRINTF_ADVANCED_ENABLE */
982                         uval = (STR_FORMAT_PRINTF_UVAL_TYPE)va_arg(ap, unsigned int);
983                     }
984 #if PRINTF_ADVANCED_ENABLE
985                 }
986 #endif /* PRINTF_ADVANCED_ENABLE */
987 
988                 radix = PrintGetRadixFromobpu(c);
989 
990                 vlen  = ConvertRadixNumToString((char *)vstr, (void *)&uval, 0, radix, use_caps);
991                 vstrp = &vstr[vlen];
992 #if PRINTF_ADVANCED_ENABLE
993                 PrintOutputdifFobpu(flags_used, field_width, (unsigned int)vlen, '\0', vstrp, cb, buf, &count);
994 #else
995                 PrintOutputdifFobpu(0U, field_width, (uint32_t)vlen, '\0', vstrp, cb, buf, &count);
996 #endif
997             }
998             else if (c == 'c')
999             {
1000                 cval = (int32_t)va_arg(ap, int);
1001                 cb(buf, &count, cval, 1);
1002             }
1003             else if (c == 's')
1004             {
1005                 sval = (char *)va_arg(ap, char *);
1006                 if (NULL != sval)
1007                 {
1008 #if PRINTF_ADVANCED_ENABLE
1009                     if (valid_precision_width)
1010                     {
1011                         vlen = (int)precision_width;
1012                     }
1013                     else
1014                     {
1015                         vlen = (int)strlen(sval);
1016                     }
1017 #else
1018                     vlen = (int32_t)strlen(sval);
1019 #endif /* PRINTF_ADVANCED_ENABLE */
1020 #if PRINTF_ADVANCED_ENABLE
1021                     if (0U == (flags_used & (unsigned int)kPRINTF_Minus))
1022 #endif /* PRINTF_ADVANCED_ENABLE */
1023                     {
1024                         cb(buf, &count, ' ', (int)field_width - (int)vlen);
1025                     }
1026 
1027 #if PRINTF_ADVANCED_ENABLE
1028                     if (valid_precision_width)
1029                     {
1030                         while (('\0' != *sval) && (vlen > 0))
1031                         {
1032                             cb(buf, &count, *sval++, 1);
1033                             vlen--;
1034                         }
1035                         /* In case that vlen sval is shorter than vlen */
1036                         vlen = (int)precision_width - vlen;
1037                     }
1038                     else
1039                     {
1040 #endif /* PRINTF_ADVANCED_ENABLE */
1041                         while ('\0' != (*sval))
1042                         {
1043                             cb(buf, &count, *sval++, 1);
1044                         }
1045 #if PRINTF_ADVANCED_ENABLE
1046                     }
1047 #endif /* PRINTF_ADVANCED_ENABLE */
1048 
1049 #if PRINTF_ADVANCED_ENABLE
1050                     if (0U != (flags_used & (unsigned int)kPRINTF_Minus))
1051                     {
1052                         cb(buf, &count, ' ', (int)field_width - vlen);
1053                     }
1054 #endif /* PRINTF_ADVANCED_ENABLE */
1055                 }
1056             }
1057             else
1058             {
1059                 cb(buf, &count, c, 1);
1060             }
1061         }
1062         p++;
1063     }
1064 
1065     return (int)count;
1066 }
1067 
1068 #if SCANF_FLOAT_ENABLE
StrFormatScanIsFloat(char * c)1069 static uint8_t StrFormatScanIsFloat(char *c)
1070 {
1071     uint8_t ret = 0U;
1072     if (('a' == (*c)) || ('A' == (*c)) || ('e' == (*c)) || ('E' == (*c)) || ('f' == (*c)) || ('F' == (*c)) ||
1073         ('g' == (*c)) || ('G' == (*c)))
1074     {
1075         ret = 1U;
1076     }
1077     return ret;
1078 }
1079 #endif
1080 
StrFormatScanIsFormatStarting(char * c)1081 static uint8_t StrFormatScanIsFormatStarting(char *c)
1082 {
1083     uint8_t ret = 1U;
1084     if ((*c != '%'))
1085     {
1086         ret = 0U;
1087     }
1088     else if (*(c + 1) == '%')
1089     {
1090         ret = 0U;
1091     }
1092     else
1093     {
1094         /*MISRA rule 15.7*/
1095     }
1096 
1097     return ret;
1098 }
1099 
StrFormatScanGetBase(uint8_t base,const char * s)1100 static uint8_t StrFormatScanGetBase(uint8_t base, const char *s)
1101 {
1102     if (base == 0U)
1103     {
1104         if (s[0] == '0')
1105         {
1106             if ((s[1] == 'x') || (s[1] == 'X'))
1107             {
1108                 base = 16;
1109             }
1110             else
1111             {
1112                 base = 8;
1113             }
1114         }
1115         else
1116         {
1117             base = 10;
1118         }
1119     }
1120     return base;
1121 }
1122 
StrFormatScanCheckSymbol(const char * p,int8_t * neg)1123 static uint8_t StrFormatScanCheckSymbol(const char *p, int8_t *neg)
1124 {
1125     uint8_t len;
1126     switch (*p)
1127     {
1128         case '-':
1129             *neg = -1;
1130             len  = 1;
1131             break;
1132         case '+':
1133             *neg = 1;
1134             len  = 1;
1135             break;
1136         default:
1137             *neg = 1;
1138             len  = 0;
1139             break;
1140     }
1141     return len;
1142 }
1143 
StrFormatScanFillInteger(uint32_t flag,va_list * args_ptr,int32_t val)1144 static uint8_t StrFormatScanFillInteger(uint32_t flag, va_list *args_ptr, int32_t val)
1145 {
1146 #if SCANF_ADVANCED_ENABLE
1147     if (0U != (flag & (uint32_t)kSCANF_Suppress))
1148     {
1149         return 0u;
1150     }
1151 
1152     switch (flag & (uint32_t)kSCANF_LengthMask)
1153     {
1154         case (uint32_t)kSCANF_LengthChar:
1155             if (0U != (flag & (uint32_t)kSCANF_TypeSinged))
1156             {
1157                 *va_arg(*args_ptr, signed char *) = (signed char)val;
1158             }
1159             else
1160             {
1161                 *va_arg(*args_ptr, unsigned char *) = (unsigned char)val;
1162             }
1163             break;
1164         case (uint32_t)kSCANF_LengthShortInt:
1165             if (0U != (flag & (uint32_t)kSCANF_TypeSinged))
1166             {
1167                 *va_arg(*args_ptr, signed short *) = (signed short)val;
1168             }
1169             else
1170             {
1171                 *va_arg(*args_ptr, unsigned short *) = (unsigned short)val;
1172             }
1173             break;
1174         case (uint32_t)kSCANF_LengthLongInt:
1175             if (0U != (flag & (uint32_t)kSCANF_TypeSinged))
1176             {
1177                 *va_arg(*args_ptr, signed long int *) = (signed long int)val;
1178             }
1179             else
1180             {
1181                 *va_arg(*args_ptr, unsigned long int *) = (unsigned long int)val;
1182             }
1183             break;
1184         case (uint32_t)kSCANF_LengthLongLongInt:
1185             if (0U != (flag & (uint32_t)kSCANF_TypeSinged))
1186             {
1187                 *va_arg(*args_ptr, signed long long int *) = (signed long long int)val;
1188             }
1189             else
1190             {
1191                 *va_arg(*args_ptr, unsigned long long int *) = (unsigned long long int)val;
1192             }
1193             break;
1194         default:
1195             /* The default type is the type int. */
1196             if (0U != (flag & (uint32_t)kSCANF_TypeSinged))
1197             {
1198                 *va_arg(*args_ptr, signed int *) = (signed int)val;
1199             }
1200             else
1201             {
1202                 *va_arg(*args_ptr, unsigned int *) = (unsigned int)val;
1203             }
1204             break;
1205     }
1206 #else
1207     /* The default type is the type int. */
1208     if (0U != (flag & (uint32_t)kSCANF_TypeSinged))
1209     {
1210         *va_arg(*args_ptr, signed int *) = (signed int)val;
1211     }
1212     else
1213     {
1214         *va_arg(*args_ptr, unsigned int *) = (unsigned int)val;
1215     }
1216 #endif /* SCANF_ADVANCED_ENABLE */
1217 
1218     return 1u;
1219 }
1220 
1221 #if SCANF_FLOAT_ENABLE
StrFormatScanFillFloat(uint32_t flag,va_list * args_ptr,double fnum)1222 static uint8_t StrFormatScanFillFloat(uint32_t flag, va_list *args_ptr, double fnum)
1223 {
1224 #if SCANF_ADVANCED_ENABLE
1225     if (0U != (flag & (uint32_t)kSCANF_Suppress))
1226     {
1227         return 0u;
1228     }
1229     else
1230 #endif /* SCANF_ADVANCED_ENABLE */
1231     {
1232         if (0U != (flag & (uint32_t)kSCANF_LengthLongLongDouble))
1233         {
1234             *va_arg(*args_ptr, double *) = fnum;
1235         }
1236         else
1237         {
1238             *va_arg(*args_ptr, float *) = (float)fnum;
1239         }
1240         return 1u;
1241     }
1242 }
1243 #endif /* SCANF_FLOAT_ENABLE */
1244 
StrFormatScanfStringHandling(char ** str,uint32_t * flag,uint32_t * field_width,uint8_t * base)1245 static uint8_t StrFormatScanfStringHandling(char **str, uint32_t *flag, uint32_t *field_width, uint8_t *base)
1246 {
1247     uint8_t exitPending = 0U;
1248     char *c             = *str;
1249 
1250     /* Loop to get full conversion specification. */
1251     while (('\0' != (*c)) && (0U == (*flag & (uint32_t)kSCANF_DestMask)))
1252     {
1253 #if SCANF_ADVANCED_ENABLE
1254         if ('*' == (*c))
1255         {
1256             if (0U != ((*flag) & (uint32_t)kSCANF_Suppress))
1257             {
1258                 /* Match failure. */
1259                 exitPending = 1U;
1260             }
1261             else
1262             {
1263                 (*flag) |= (uint32_t)kSCANF_Suppress;
1264             }
1265         }
1266         else if ('h' == (*c))
1267         {
1268             if (0U != ((*flag) & (uint32_t)kSCANF_LengthMask))
1269             {
1270                 /* Match failure. */
1271                 exitPending = 1U;
1272             }
1273             else
1274             {
1275                 if (c[1] == 'h')
1276                 {
1277                     (*flag) |= (uint32_t)kSCANF_LengthChar;
1278                     c++;
1279                 }
1280                 else
1281                 {
1282                     (*flag) |= (uint32_t)kSCANF_LengthShortInt;
1283                 }
1284             }
1285         }
1286         else if ('l' == (*c))
1287         {
1288             if (0U != ((*flag) & (uint32_t)kSCANF_LengthMask))
1289             {
1290                 /* Match failure. */
1291                 exitPending = 1U;
1292             }
1293             else
1294             {
1295                 if (c[1] == 'l')
1296                 {
1297                     (*flag) |= (uint32_t)kSCANF_LengthLongLongInt;
1298                     c++;
1299                 }
1300                 else
1301                 {
1302                     (*flag) |= (uint32_t)kSCANF_LengthLongInt;
1303                 }
1304             }
1305         }
1306         else
1307 #endif /* SCANF_ADVANCED_ENABLE */
1308 #if SCANF_FLOAT_ENABLE
1309             if ('L' == (*c))
1310         {
1311             if (0U != ((*flag) & (uint32_t)kSCANF_LengthMask))
1312             {
1313                 /* Match failure. */
1314                 exitPending = 1U;
1315             }
1316             else
1317             {
1318                 (*flag) |= (uint32_t)kSCANF_LengthLongLongDouble;
1319             }
1320         }
1321         else
1322 #endif /* SCANF_FLOAT_ENABLE */
1323             if (((*c) >= '0') && ((*c) <= '9'))
1324         {
1325             {
1326                 char *p;
1327                 errno          = 0;
1328                 (*field_width) = strtoul(c, &p, 10);
1329                 if (0 != errno)
1330                 {
1331                     *field_width = 0U;
1332                 }
1333                 c = p - 1;
1334             }
1335         }
1336         else if ('d' == (*c))
1337         {
1338             (*base) = 10U;
1339             (*flag) |= (uint32_t)kSCANF_TypeSinged;
1340             (*flag) |= (uint32_t)kSCANF_DestInt;
1341         }
1342         else if ('u' == (*c))
1343         {
1344             (*base) = 10U;
1345             (*flag) |= (uint32_t)kSCANF_DestInt;
1346         }
1347         else if ('o' == (*c))
1348         {
1349             (*base) = 8U;
1350             (*flag) |= (uint32_t)kSCANF_DestInt;
1351         }
1352         else if (('x' == (*c)))
1353         {
1354             (*base) = 16U;
1355             (*flag) |= (uint32_t)kSCANF_DestInt;
1356         }
1357         else if ('X' == (*c))
1358         {
1359             (*base) = 16U;
1360             (*flag) |= (uint32_t)kSCANF_DestInt;
1361         }
1362         else if ('i' == (*c))
1363         {
1364             (*base) = 0U;
1365             (*flag) |= (uint32_t)kSCANF_DestInt;
1366         }
1367 #if SCANF_FLOAT_ENABLE
1368         else if (1U == StrFormatScanIsFloat(c))
1369         {
1370             (*flag) |= (uint32_t)kSCANF_DestFloat;
1371         }
1372 #endif /* SCANF_FLOAT_ENABLE */
1373         else if ('c' == (*c))
1374         {
1375             (*flag) |= (uint32_t)kSCANF_DestChar;
1376             if (MAX_FIELD_WIDTH == (*field_width))
1377             {
1378                 (*field_width) = 1;
1379             }
1380         }
1381         else if ('s' == (*c))
1382         {
1383             (*flag) |= (uint32_t)kSCANF_DestString;
1384         }
1385         else
1386         {
1387             exitPending = 1U;
1388         }
1389 
1390         if (1U == exitPending)
1391         {
1392             break;
1393         }
1394         else
1395         {
1396             c++;
1397         }
1398     }
1399     *str = c;
1400     return exitPending;
1401 }
1402 
1403 /*!
1404  * brief Converts an input line of ASCII characters based upon a provided
1405  * string format.
1406  *
1407  * param[in] line_ptr The input line of ASCII data.
1408  * param[in] format   Format first points to the format string.
1409  * param[in] args_ptr The list of parameters.
1410  *
1411  * return Number of input items converted and assigned.
1412  * retval IO_EOF When line_ptr is empty string "".
1413  */
StrFormatScanf(const char * line_ptr,char * format,va_list args_ptr)1414 int StrFormatScanf(const char *line_ptr, char *format, va_list args_ptr)
1415 {
1416     uint8_t base;
1417     int8_t neg;
1418     /* Identifier for the format string. */
1419     char *c = format;
1420     char *buf;
1421     /* Flag telling the conversion specification. */
1422     uint32_t flag = 0;
1423     /* Filed width for the matching input streams. */
1424     uint32_t field_width;
1425     /* How many arguments are assigned except the suppress. */
1426     uint32_t nassigned = 0;
1427     /* How many characters are read from the input streams. */
1428     uint32_t n_decode = 0;
1429 
1430     int32_t val;
1431 
1432     uint8_t added;
1433 
1434     uint8_t exitPending = 0;
1435 
1436     const char *s;
1437 #if SCANF_FLOAT_ENABLE
1438     char *s_temp; /* MISRA C-2012 Rule 11.3 */
1439 #endif
1440 
1441     /* Identifier for the input string. */
1442     const char *p = line_ptr;
1443 
1444 #if SCANF_FLOAT_ENABLE
1445     double fnum = 0.0;
1446 #endif /* SCANF_FLOAT_ENABLE */
1447     /* Return EOF error before any conversion. */
1448     if (*p == '\0')
1449     {
1450         return -1;
1451     }
1452 
1453     /* Decode directives. */
1454     while (('\0' != (*c)) && ('\0' != (*p)))
1455     {
1456         /* Ignore all white-spaces in the format strings. */
1457         if (0U != ScanIgnoreWhiteSpace((const char **)((void *)&c)))
1458         {
1459             n_decode += ScanIgnoreWhiteSpace(&p);
1460         }
1461         else if (0U == StrFormatScanIsFormatStarting(c))
1462         {
1463             /* Ordinary characters. */
1464             c++;
1465             if (*p == *c)
1466             {
1467                 n_decode++;
1468                 p++;
1469                 c++;
1470             }
1471             else
1472             {
1473                 /* Match failure. Misalignment with C99, the unmatched characters need to be pushed back to stream.
1474                  * However, it is deserted now. */
1475                 break;
1476             }
1477         }
1478         else
1479         {
1480             /* convernsion specification */
1481             c++;
1482             /* Reset. */
1483             flag        = 0;
1484             field_width = MAX_FIELD_WIDTH;
1485             base        = 0;
1486             added       = 0U;
1487 
1488             exitPending = StrFormatScanfStringHandling(&c, &flag, &field_width, &base);
1489 
1490             if (1U == exitPending)
1491             {
1492                 /* Format strings are exhausted. */
1493                 break;
1494             }
1495 
1496             /* Matching strings in input streams and assign to argument. */
1497             if ((flag & (uint32_t)kSCANF_DestMask) == (uint32_t)kSCANF_DestChar)
1498             {
1499                 s   = (const char *)p;
1500                 buf = va_arg(args_ptr, char *);
1501                 while ((0U != (field_width--))
1502 #if SCANF_ADVANCED_ENABLE
1503                        && ('\0' != (*p))
1504 #endif
1505                 )
1506                 {
1507 #if SCANF_ADVANCED_ENABLE
1508                     if (0U != (flag & (uint32_t)kSCANF_Suppress))
1509                     {
1510                         p++;
1511                     }
1512                     else
1513 #endif
1514                     {
1515                         *buf++ = *p++;
1516 #if SCANF_ADVANCED_ENABLE
1517                         added = 1u;
1518 #endif
1519                     }
1520                     n_decode++;
1521                 }
1522 
1523 #if SCANF_ADVANCED_ENABLE
1524                 if (1u == added)
1525 #endif
1526                 {
1527                     nassigned++;
1528                 }
1529             }
1530             else if ((flag & (uint32_t)kSCANF_DestMask) == (uint32_t)kSCANF_DestString)
1531             {
1532                 n_decode += ScanIgnoreWhiteSpace(&p);
1533                 s   = p;
1534                 buf = va_arg(args_ptr, char *);
1535                 while ((0U != (field_width--)) && (*p != '\0') && (0U == ScanIsWhiteSpace(*p)))
1536                 {
1537 #if SCANF_ADVANCED_ENABLE
1538                     if (0U != (flag & (uint32_t)kSCANF_Suppress))
1539                     {
1540                         p++;
1541                     }
1542                     else
1543 #endif
1544                     {
1545                         *buf++ = *p++;
1546 #if SCANF_ADVANCED_ENABLE
1547                         added = 1u;
1548 #endif
1549                     }
1550                     n_decode++;
1551                 }
1552 
1553 #if SCANF_ADVANCED_ENABLE
1554                 if (1u == added)
1555 #endif
1556                 {
1557                     /* Add NULL to end of string. */
1558                     *buf = '\0';
1559                     nassigned++;
1560                 }
1561             }
1562             else if ((flag & (uint32_t)kSCANF_DestMask) == (uint32_t)kSCANF_DestInt)
1563             {
1564                 n_decode += ScanIgnoreWhiteSpace(&p);
1565                 s    = p;
1566                 val  = 0;
1567                 base = StrFormatScanGetBase(base, s);
1568 
1569                 added = StrFormatScanCheckSymbol(p, &neg);
1570                 n_decode += added;
1571                 p += added;
1572                 field_width -= added;
1573 
1574                 s = p;
1575                 if (strlen(p) > field_width)
1576                 {
1577                     char temp[12];
1578                     char *tempEnd;
1579                     (void)memcpy(temp, p, sizeof(temp) - 1U);
1580                     temp[sizeof(temp) - 1U] = '\0';
1581                     errno                   = 0;
1582                     val                     = (int32_t)strtoul(temp, &tempEnd, (int)base);
1583                     if (0 != errno)
1584                     {
1585                         break;
1586                     }
1587                     p = p + (tempEnd - temp);
1588                 }
1589                 else
1590                 {
1591                     char *tempEnd;
1592                     val   = 0;
1593                     errno = 0;
1594                     val   = (int32_t)strtoul(p, &tempEnd, (int)base);
1595                     if (0 != errno)
1596                     {
1597                         break;
1598                     }
1599                     p = tempEnd;
1600                 }
1601                 n_decode += (uintptr_t)p - (uintptr_t)s;
1602 
1603                 val *= neg;
1604 
1605                 nassigned += StrFormatScanFillInteger(flag, &args_ptr, val);
1606             }
1607 #if SCANF_FLOAT_ENABLE
1608             else if ((flag & (uint32_t)kSCANF_DestMask) == (uint32_t)kSCANF_DestFloat)
1609             {
1610                 n_decode += ScanIgnoreWhiteSpace(&p);
1611                 fnum  = 0.0;
1612                 errno = 0;
1613 
1614                 fnum = strtod(p, (char **)&s_temp);
1615                 s    = s_temp; /* MISRA C-2012 Rule 11.3 */
1616 
1617                 /* MISRA C-2012 Rule 22.9 */
1618                 if (0 != errno)
1619                 {
1620                     break;
1621                 }
1622 
1623                 if ((fnum < HUGE_VAL) && (fnum > -HUGE_VAL))
1624                 {
1625                     n_decode = (uint32_t)n_decode + (uint32_t)s - (uint32_t)p;
1626                     p        = s;
1627                     nassigned += StrFormatScanFillFloat(flag, &args_ptr, fnum);
1628                 }
1629             }
1630 #endif /* SCANF_FLOAT_ENABLE */
1631             else
1632             {
1633                 break;
1634             }
1635         }
1636     }
1637     return (int)nassigned;
1638 }
1639