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 |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 |
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 | */ |
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 |
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 | |
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 | |
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 | |
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 | |
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 |
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 | */ |
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 count; |
1066 | } |
1067 | |
1068 | #if SCANF_FLOAT_ENABLE |
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 | |
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 | |
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 | |
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 | |
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 |
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 | |
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 | */ |
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 | |