1 /*
2
3 this is the c lib patch, It can help when the clib provided by IAR
4 does not work well.
5
6 How to use this:
7 1.You must include platform_stdlib.h in you source file。
8 2.There is a macro USE_CLIB_PATCH in platform_stdlib.h should be opened.
9
10 If there is some problems using this patch,
11 You'd better check if you code runs into these functions:
12
13 DiagSscanfPatch
14 DiagStrtokPatch
15 DiagStrstrPatch
16 DiagSnPrintfPatch
17 DiagPrintfPatch
18 DiagSPrintfPatch
19 DiagPrintfPatch
20 DiagSPrintfPatch
21 DiagSnPrintfPatch
22 DiagStrstrPatch
23 DiagStrtokPatch
24
25 */
26 #ifndef CONFIG_PLATFORM_8711B
27
28 #include <stdarg.h>
29
30 #define DiagPutChar HalSerialPutcRtl8195a
31
32 #define IN
33 #define NULL 0
34
35 typedef unsigned int size_t;
36 typedef unsigned int SIZE_T;
37 typedef unsigned long long u64;
38 typedef unsigned int u32;
39 typedef unsigned short int u16;
40 typedef unsigned char u8;
41 typedef signed long long s64;
42 typedef signed int s32;
43 typedef signed short int s16;
44 typedef unsigned char bool;
45
46
47 #define in_range(c, lo, up) ((u8)c >= lo && (u8)c <= up)
48 #define isprint(c) in_range(c, 0x20, 0x7f)
49 #define isdigit(c) in_range(c, '0', '9')
50 #define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
51 #define islower(c) in_range(c, 'a', 'z')
52 #define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == ',')
53 #define ULLONG_MAX (~0ULL)
54 #define USHRT_MAX ((u16)(~0U))
55 #define KSTRTOX_OVERFLOW (1U << 31)
56 #define SHRT_MAX ((s16)(USHRT_MAX>>1))
57
_tolower(const char c)58 static inline char _tolower(const char c)
59 {
60 return c | 0x20;
61 }
62
63
64 extern s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder);
65 extern s64 div_s64(s64 dividend, s32 divisor);
66 extern inline char _tolower(const char c);
67 extern u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder);
68 extern u64 div_u64(u64 dividend, u32 divisor);
69 extern unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p);
70 extern const char *_parse_integer_fixup_radix(const char *s, unsigned int *base);
71 extern char *skip_spaces(const char *str);
72 extern int skip_atoi(const char **s);
73 extern void HalSerialPutcRtl8195a(u8 c);
74
75
simple_strtoull_patch(const char * cp,char ** endp,unsigned int base)76 static unsigned long long simple_strtoull_patch(const char *cp, char **endp, unsigned int base)
77 {
78 unsigned long long result;
79 unsigned int rv;
80
81 cp = _parse_integer_fixup_radix(cp, &base);
82 rv = _parse_integer(cp, base, &result);
83
84 return result;
85 }
86
simple_strtoll_patch(const char * cp,char ** endp,unsigned int base)87 static long long simple_strtoll_patch(const char *cp, char **endp, unsigned int base)
88 {
89 if(*cp == '-')
90 return -simple_strtoull_patch(cp + 1, endp, base);
91
92 return simple_strtoull_patch(cp, endp, base);
93 }
simple_strtoul_patch(const char * cp,char ** endp,unsigned int base)94 static unsigned long simple_strtoul_patch(const char *cp, char **endp, unsigned int base)
95 {
96 return simple_strtoull_patch(cp, endp, base);
97 }
98
simple_strtol_patch(const char * cp,char ** endp,unsigned int base)99 static long simple_strtol_patch(const char *cp, char **endp, unsigned int base)
100 {
101 if(*cp == '-')
102 return -simple_strtoul_patch(cp + 1, endp, base);
103
104 return simple_strtoul_patch(cp, endp, base);
105 }
106
107
108
109
judge_digit_width(const char * str)110 static int judge_digit_width(const char *str)
111 {
112
113 int width = 0;
114
115 while(isdigit(*str)) {
116 width++;
117 str++;
118 }
119
120 return width;
121 }
122
123
_vsscanf_patch(const char * buf,const char * fmt,va_list args)124 static int _vsscanf_patch(const char *buf, const char *fmt, va_list args)
125 {
126 const char *str = buf;
127 char *next;
128 char digit;
129 int num = 0;
130 int i =0;
131 u8 qualifier;
132 unsigned int base;
133 union {
134 long long s;
135 unsigned long long u;
136 } val;
137 s16 field_width;
138 bool is_sign;
139
140 char str_store[20] = {0};
141
142
143
144 while(*fmt) {
145 /* skip any white space in format */
146 /* white space in format matchs any amount of
147 * white space, including none, in the input.
148 */
149 if(isspace(*fmt)) {
150 fmt = skip_spaces(++fmt);
151 str = skip_spaces(str);
152 }
153
154 /* anything that is not a conversion must match exactly */
155 if(*fmt != '%' && *fmt) {
156 if(*fmt++ != *str++) {
157 break;
158 }
159
160 continue;
161 }
162
163 if(!*fmt) {
164 break;
165 }
166
167 ++fmt;
168
169 /* skip this conversion.
170 * advance both strings to next white space
171 */
172 if(*fmt == '*') {
173 if(!*str) {
174 break;
175 }
176
177 while(!isspace(*fmt) && *fmt != '%' && *fmt)
178 fmt++;
179
180 while(!isspace(*str) && *str)
181 str++;
182
183 continue;
184 }
185
186 /* get field width */
187 field_width = -1;
188
189 if(isdigit(*fmt)) {
190
191 field_width = skip_atoi(&fmt);
192
193
194
195 if(field_width <= 0) {
196
197 break;
198 }
199 }
200
201 /* get conversion qualifier */
202 qualifier = -1;
203
204 if(*fmt == 'h' || _tolower(*fmt) == 'l' ||
205 _tolower(*fmt) == 'z') {
206 qualifier = *fmt++;
207
208 if(qualifier == *fmt) {
209 if(qualifier == 'h') {
210 qualifier = 'H';
211 fmt++;
212 } else if(qualifier == 'l') {
213 qualifier = 'L';
214 fmt++;
215 }
216 }
217 }
218
219 if(!*fmt) {
220 break;
221 }
222
223 if(*fmt == 'n') {
224 /* return number of characters read so far */
225 *va_arg(args, int *) = str - buf;
226 ++fmt;
227 continue;
228 }
229
230 if(!*str) {
231 break;
232 }
233
234 base = 10;
235 is_sign = 0;
236
237 switch(*fmt++) {
238 case 'c': {
239 char *s = (char *)va_arg(args, char*);
240
241 if(field_width == -1)
242 field_width = 1;
243
244 do {
245 *s++ = *str++;
246 } while(--field_width > 0 && *str);
247
248 num++;
249 }
250
251 continue;
252
253 case 's': {
254 char *s = (char *)va_arg(args, char *);
255
256 if(field_width == -1)
257 field_width = SHRT_MAX;
258
259 /* first, skip leading white space in buffer */
260 str = skip_spaces(str);
261
262 /* now copy until next white space */
263 while(*str && !isspace(*str) && field_width--) {
264 *s++ = *str++;
265 }
266
267 *s = '\0';
268 num++;
269 }
270
271 continue;
272
273 case 'o':
274 base = 8;
275 break;
276
277 case 'x':
278 case 'X':
279 base = 16;
280 break;
281
282 case 'i':
283 base = 0;
284
285 case 'd':
286 is_sign = 1;
287
288 case 'u':
289 break;
290
291 case '%':
292
293 /* looking for '%' in str */
294 if(*str++ != '%') {
295 return num;
296 }
297
298 continue;
299
300 default:
301 /* invalid format; stop here */
302 return num;
303 }
304
305 /* have some sort of integer conversion.
306 * first, skip white space in buffer.
307 */
308 str = skip_spaces(str);
309
310 digit = *str;
311
312 if(is_sign && digit == '-')
313 digit = *(str + 1);
314
315 if(!digit
316 || (base == 16 && !isxdigit(digit))
317 || (base == 10 && !isdigit(digit))
318 || (base == 8 && (!isdigit(digit) || digit > '7'))
319 || (base == 0 && !isdigit(digit))) {
320 break;
321 }
322
323 //here problem *******************************************
324
325
326
327 //troy add ,fix support %2d, but not support %d
328 if(field_width <= 0) {
329
330 field_width = judge_digit_width(str);
331 }
332
333
334 /////troy add, fix str passed inwidth wrong
335 for(i = 0; i<field_width ; i++)
336 str_store[i] = str[i];
337
338 next = (char*)str + field_width;
339
340
341
342 if(is_sign) {
343 val.s = qualifier != 'L' ?
344 simple_strtol_patch(str_store, &next, base) :
345 simple_strtoll_patch(str_store, &next, base);
346 } else {
347 val.u = qualifier != 'L' ?
348 simple_strtoul_patch(str_store, &next, base) :
349 simple_strtoull_patch(str_store, &next, base);
350 }
351
352
353 ////troy add
354 for(i = 0; i<20 ; i++)
355 str_store[i] = 0;
356
357
358 //判断转换的字符串的宽度是否大于 %2d
359 if(field_width > 0 && next - str > field_width) {
360 if(base == 0)
361 _parse_integer_fixup_radix(str, &base);
362
363 while(next - str > field_width) {
364 if(is_sign) {
365 val.s = div_s64(val.s, base);
366 } else {
367 val.u = div_u64(val.u, base);
368 }
369
370 --next;
371 }
372 }
373
374 switch(qualifier) {
375 case 'H': /* that's 'hh' in format */
376 if(is_sign)
377 *va_arg(args, signed char *) = val.s;
378 else
379 *va_arg(args, unsigned char *) = val.u;
380
381 break;
382
383 case 'h':
384 if(is_sign)
385 *va_arg(args, short *) = val.s;
386 else
387 *va_arg(args, unsigned short *) = val.u;
388
389 break;
390
391 case 'l':
392 if(is_sign)
393 *va_arg(args, long *) = val.s;
394 else
395 *va_arg(args, unsigned long *) = val.u;
396
397 break;
398
399 case 'L':
400 if(is_sign)
401 *va_arg(args, long long *) = val.s;
402 else
403 *va_arg(args, unsigned long long *) = val.u;
404
405 break;
406
407 case 'Z':
408 case 'z':
409 *va_arg(args, size_t *) = val.u;
410 break;
411
412 default:
413 if(is_sign)
414 *va_arg(args, int *) = val.s;
415 else
416 *va_arg(args, unsigned int *) = val.u;
417
418 break;
419 }
420
421 num++;
422
423 if(!next) {
424 break;
425 }
426
427 str = next;
428 }
429
430 return num;
431 }
432
433
DiagSscanfPatch(const char * buf,const char * fmt,...)434 int DiagSscanfPatch(const char *buf, const char *fmt, ...)
435 {
436 va_list args;
437 int i;
438
439 va_start(args, fmt);
440 i = _vsscanf_patch(buf, fmt, args);
441 va_end(args);
442
443 return i;
444 }
445
446
447
448 /*********************************************************/
449
450
451
DiagStrtokPatch(char * str,const char * delim)452 char* DiagStrtokPatch(char *str, const char* delim) {
453 static char* _buffer;
454
455 if(str != NULL) _buffer = str;
456
457 if(_buffer[0] == '\0') return NULL;
458
459 char *ret = _buffer, *b;
460 const char *d;
461
462 for(b = _buffer; *b !='\0'; b++) {
463 for(d = delim; *d != '\0'; d++) {
464 if(*b == *d) {
465 *b = '\0';
466 _buffer = b+1;
467
468 // skip the beginning delimiters
469 if(b == ret) {
470 ret++;
471 continue;
472 }
473
474 return ret;
475 }
476 }
477 }
478
479 return ret;
480 }
481
482
483
484 /*********************************************************/
485
486
487
DiagStrstrPatch(char * string,char * substring)488 char *DiagStrstrPatch(char *string, char *substring)
489 {
490 register char *a, *b;
491
492 /* First scan quickly through the two strings looking for a
493 * single-character match. When it's found, then compare the
494 * rest of the substring.
495 */
496
497 b = substring;
498
499 if(*b == 0) {
500 return string;
501 }
502
503 for(; *string != 0; string += 1) {
504 if(*string != *b) {
505 continue;
506 }
507
508 a = string;
509
510 while(1) {
511 if(*b == 0) {
512 return string;
513 }
514
515 if(*a++ != *b++) {
516 break;
517 }
518 }
519
520 b = substring;
521 }
522
523 return (char *) 0;
524 }
525
526
527
528
529
530 /*********************************************************/
531
532
533
534
DiagSnPrintfPatch(char * buf,size_t size,const char * fmt,...)535 int DiagSnPrintfPatch(char *buf, size_t size, const char *fmt, ...)
536 {
537
538 va_list ap;
539 char *p, *s, *buf_end = NULL;
540 const int *dp = ((const int *)&fmt)+1;
541
542 if(buf == NULL)
543 return 0;
544
545
546 va_start(ap, fmt);
547 s = buf;
548 buf_end = size? (buf + size):(char*)~0;
549
550 for(; *fmt != '\0'; ++fmt) {
551
552 if(*fmt != '%') {
553 *s++ = *fmt;
554
555 if(s >= buf_end) {
556 goto Exit;
557 }
558
559 continue;
560 }
561
562 if(*++fmt == 's') {
563 for(p = (char *)*dp++; *p != '\0'; p++) {
564 *s++ = *p;
565
566 if(s >= buf_end) {
567 goto Exit;
568 }
569 }
570 }
571 else { /* Length of item is bounded */
572 char tmp[20], *q = tmp;
573 int alt = 0;
574 int shift = 0;// = 12;
575 const long *lpforchk = (const long *)dp;
576
577 if((*lpforchk) < 0x10) {
578 shift = 0;
579 }
580 else if(((*lpforchk) >= 0x10) && ((*lpforchk) < 0x100)) {
581 shift = 4;
582 }
583 else if(((*lpforchk) >= 0x100) && ((*lpforchk) < 0x1000)) {
584 shift = 8;
585 }
586 else if(((*lpforchk) >= 0x1000) && ((*lpforchk) < 0x10000)) {
587 shift = 12;
588 }
589 else if(((*lpforchk) >= 0x10000) && ((*lpforchk) < 0x100000)) {
590 shift = 16;
591 }
592 else if(((*lpforchk) >= 0x100000) && ((*lpforchk) < 0x1000000)) {
593 shift = 20;
594 }
595 else if(((*lpforchk) >= 0x1000000) && ((*lpforchk) < 0x10000000)) {
596 shift = 24;
597 }
598 else if((*lpforchk) >= 0x10000000) {
599 shift = 28;
600 }
601 else {
602 shift = 28;
603 }
604
605 if((*fmt >= '0') && (*fmt <= '9'))
606 {
607 int width;
608 unsigned char fch = *fmt;
609
610 for(width=0; (fch>='0') && (fch<='9'); fch=*++fmt)
611 { width = width * 10 + fch - '0';
612 }
613
614 shift=(width-1)*4;
615 }
616
617 /*
618 * Before each format q points to tmp buffer
619 * After each format q points past end of item
620 */
621 if((*fmt == 'x')||(*fmt == 'X') || (*fmt == 'p') || (*fmt == 'P')) {
622 /* With x86 gcc, sizeof(long) == sizeof(int) */
623 const long *lp = (const long *)dp;
624 long h = *lp++;
625 int hex_count = 0;
626 unsigned long h_back = h;
627 int ncase = (*fmt & 0x20);
628 dp = (const int *)lp;
629
630 if((*fmt == 'p') || (*fmt == 'P'))
631 alt=1;
632
633 if(alt) {
634 *q++ = '0';
635 *q++ = 'X' | ncase;
636 }
637
638 while(h_back) {
639 hex_count += (h_back & 0xF) ? 1 : 0;
640 h_back = h_back >> 4;
641 }
642
643 if(shift < (hex_count - 1)*4)
644 shift = (hex_count - 1)*4;
645
646 for(; shift >= 0; shift -= 4)
647 *q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
648 }
649 else if(*fmt == 'd') {
650 int i = *dp++;
651 char *r;
652 int digit_space = 0;
653
654
655 if(i < 0) {
656 *q++ = '-';
657 i = -i;
658 digit_space++;
659 }
660
661 p = q; /* save beginning of digits */
662
663
664 do {
665 *q++ = '0' + (i % 10);
666 i /= 10;
667 digit_space++;
668 } while(i);
669
670
671 for(; shift >= 0; shift -= 4) {
672
673 if(digit_space-- > 0) {
674 ; //do nothing
675 } else {
676 *q++ = '0';
677 }
678 }
679
680 /* reverse digits, stop in middle */
681 r = q; /* don't alter q */
682
683 while(--r > p) {
684 i = *r;
685 *r = *p;
686 *p++ = i;
687 }
688 }
689 else if(*fmt == 'c')
690 *q++ = *dp++;
691 else
692 *q++ = *fmt;
693
694 /* now output the saved string */
695 for(p = tmp; p < q; ++p) {
696 *s++ = *p;
697
698 if(s >= buf_end) {
699 goto Exit;
700 }
701 }
702 }
703 }
704
705 Exit:
706
707 if(buf)
708 *s = '\0';
709
710 va_end(ap);
711 return(s-buf);
712
713 }
714
715
716
717
718
719
720 /*********************************************************/
721
VSprintfPatch(char * buf,const char * fmt,const int * dp)722 static int VSprintfPatch(char *buf, const char *fmt, const int *dp)
723 {
724 char *p, *s;
725 s = buf;
726
727 for(; *fmt != '\0'; ++fmt) {
728 if(*fmt != '%') {
729 if(buf) {
730 *s++ = *fmt;
731 } else {
732 DiagPutChar(*fmt);
733 }
734
735 continue;
736 }
737
738 if(*++fmt == 's') {
739 for(p = (char *)*dp++; *p != '\0'; p++) {
740 if(buf) {
741 *s++ = *p;
742 } else {
743 DiagPutChar(*p);
744 }
745 }
746 }
747 else { /* Length of item is bounded */
748 char tmp[20], *q = tmp;
749 int alt = 0;
750 int shift = 0;// = 12;
751 const long *lpforchk = (const long *)dp;
752
753 if((*lpforchk) < 0x10) {
754 shift = 0;
755 }
756 else if(((*lpforchk) >= 0x10) && ((*lpforchk) < 0x100)) {
757 shift = 4;
758 }
759 else if(((*lpforchk) >= 0x100) && ((*lpforchk) < 0x1000)) {
760 shift = 8;
761 }
762 else if(((*lpforchk) >= 0x1000) && ((*lpforchk) < 0x10000)) {
763 shift = 12;
764 }
765 else if(((*lpforchk) >= 0x10000) && ((*lpforchk) < 0x100000)) {
766 shift = 16;
767 }
768 else if(((*lpforchk) >= 0x100000) && ((*lpforchk) < 0x1000000)) {
769 shift = 20;
770 }
771 else if(((*lpforchk) >= 0x1000000) && ((*lpforchk) < 0x10000000)) {
772 shift = 24;
773 }
774 else if((*lpforchk) >= 0x10000000) {
775 shift = 28;
776 }
777 else {
778 shift = 28;
779 }
780
781 #if 1 //wei patch for %02x
782
783 if((*fmt >= '0') && (*fmt <= '9'))
784 {
785 int width;
786 unsigned char fch = *fmt;
787
788 for(width=0; (fch>='0') && (fch<='9'); fch=*++fmt)
789 { width = width * 10 + fch - '0';
790 }
791
792 shift=(width-1)*4;
793 }
794
795 #endif
796
797 /*
798 * Before each format q points to tmp buffer
799 * After each format q points past end of item
800 */
801
802 if((*fmt == 'x')||(*fmt == 'X') || (*fmt == 'p') || (*fmt == 'P')) {
803 /* With x86 gcc, sizeof(long) == sizeof(int) */
804 const long *lp = (const long *)dp;
805 long h = *lp++;
806 int hex_count = 0;
807 unsigned long h_back = h;
808 int ncase = (*fmt & 0x20);
809 dp = (const int *)lp;
810
811 if((*fmt == 'p') || (*fmt == 'P'))
812 alt=1;
813
814 if(alt) {
815 *q++ = '0';
816 *q++ = 'X' | ncase;
817 }
818
819 //hback 是实际得到的数据,hex_count是统计数据的HEX字符个数
820 while(h_back) {
821 hex_count += (h_back & 0xF) ? 1 : 0;
822 h_back = h_back >> 4;
823 }
824
825 //这里修复 example: 字符有4个,但是用了%02x导致字符被截断的情况
826 if(shift < (hex_count - 1)*4)
827 shift = (hex_count - 1)*4;
828
829 //printf("(%d,%d)", hex_count, shift);
830
831 for(; shift >= 0; shift -= 4) {
832
833 *q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
834 }
835
836 }
837 else if(*fmt == 'd') {
838 int i = *dp++;
839 char *r;
840 int digit_space = 0;
841
842 if(i < 0) {
843 *q++ = '-';
844 i = -i;
845 digit_space++;
846 }
847
848 p = q; /* save beginning of digits */
849
850 do {
851 *q++ = '0' + (i % 10);
852 i /= 10;
853 digit_space++;
854 } while(i);
855
856 //这里修复 example:用了%08d后,在数字前面没有0的情况
857 for(; shift >= 0; shift -= 4) {
858
859 if(digit_space-- > 0) {
860 ; //do nothing
861 } else {
862 *q++ = '0';
863 }
864 }
865
866 /* reverse digits, stop in middle */
867 r = q; /* don't alter q */
868
869 while(--r > p) {
870 i = *r;
871 *r = *p;
872 *p++ = i;
873 }
874 }
875 else if(*fmt == 'c')
876 *q++ = *dp++;
877 else
878 *q++ = *fmt;
879
880 /* now output the saved string */
881 for(p = tmp; p < q; ++p) {
882 if(buf) {
883 *s++ = *p;
884 } else {
885 DiagPutChar(*p);
886 }
887
888 if((*p) == '\n') {
889 DiagPutChar('\r');
890 }
891 }
892 }
893 }
894
895 if(buf)
896 *s = '\0';
897
898 return (s - buf);
899 }
900
901
DiagPrintfPatch(IN const char * fmt,...)902 u32 DiagPrintfPatch(
903 IN const char *fmt, ...
904 )
905 {
906 (void)VSprintfPatch(0, fmt, ((const int *)&fmt)+1);
907 return 1;
908 }
909
DiagSPrintfPatch(IN u8 * buf,IN const char * fmt,...)910 u32 DiagSPrintfPatch(
911 IN u8 *buf,
912 IN const char *fmt, ...
913 )
914 {
915 (void)VSprintfPatch((char*)buf, fmt, ((const int *)&fmt)+1);
916 return 1;
917 }
918 #endif
919