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