mirror of
https://github.com/drasko/open-ameba.git
synced 2024-11-27 16:50:29 +00:00
919 lines
16 KiB
C
919 lines
16 KiB
C
|
/*
|
|||
|
|
|||
|
this is the c lib patch, It can help when the clib provided by IAR
|
|||
|
does not work well.
|
|||
|
|
|||
|
How to use this:
|
|||
|
1.You must include platform_stdlib.h in you source file。
|
|||
|
2.There is a macro USE_CLIB_PATCH in platform_stdlib.h should be opened.
|
|||
|
|
|||
|
If there is some problems using this patch,
|
|||
|
You'd better check if you code runs into these functions:
|
|||
|
|
|||
|
DiagSscanfPatch
|
|||
|
DiagStrtokPatch
|
|||
|
DiagStrstrPatch
|
|||
|
DiagSnPrintfPatch
|
|||
|
DiagPrintfPatch
|
|||
|
DiagSPrintfPatch
|
|||
|
DiagPrintfPatch
|
|||
|
DiagSPrintfPatch
|
|||
|
DiagSnPrintfPatch
|
|||
|
DiagStrstrPatch
|
|||
|
DiagStrtokPatch
|
|||
|
|
|||
|
*/
|
|||
|
#ifndef CONFIG_PLATFORM_8711B
|
|||
|
|
|||
|
#include <stdarg.h>
|
|||
|
|
|||
|
#define DiagPutChar HalSerialPutcRtl8195a
|
|||
|
|
|||
|
#define IN
|
|||
|
#define NULL 0
|
|||
|
|
|||
|
typedef unsigned int size_t;
|
|||
|
typedef unsigned int SIZE_T;
|
|||
|
typedef unsigned long long u64;
|
|||
|
typedef unsigned int u32;
|
|||
|
typedef unsigned short int u16;
|
|||
|
typedef unsigned char u8;
|
|||
|
typedef signed long long s64;
|
|||
|
typedef signed int s32;
|
|||
|
typedef signed short int s16;
|
|||
|
typedef unsigned char bool;
|
|||
|
|
|||
|
|
|||
|
#define in_range(c, lo, up) ((u8)c >= lo && (u8)c <= up)
|
|||
|
#define isprint(c) in_range(c, 0x20, 0x7f)
|
|||
|
#define isdigit(c) in_range(c, '0', '9')
|
|||
|
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
|
|||
|
#define islower(c) in_range(c, 'a', 'z')
|
|||
|
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == ',')
|
|||
|
#define ULLONG_MAX (~0ULL)
|
|||
|
#define USHRT_MAX ((u16)(~0U))
|
|||
|
#define KSTRTOX_OVERFLOW (1U << 31)
|
|||
|
#define SHRT_MAX ((s16)(USHRT_MAX>>1))
|
|||
|
|
|||
|
static inline char _tolower(const char c)
|
|||
|
{
|
|||
|
return c | 0x20;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
extern s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder);
|
|||
|
extern s64 div_s64(s64 dividend, s32 divisor);
|
|||
|
extern inline char _tolower(const char c);
|
|||
|
extern u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder);
|
|||
|
extern u64 div_u64(u64 dividend, u32 divisor);
|
|||
|
extern unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p);
|
|||
|
extern const char *_parse_integer_fixup_radix(const char *s, unsigned int *base);
|
|||
|
extern char *skip_spaces(const char *str);
|
|||
|
extern int skip_atoi(const char **s);
|
|||
|
extern void HalSerialPutcRtl8195a(u8 c);
|
|||
|
|
|||
|
|
|||
|
static unsigned long long simple_strtoull_patch(const char *cp, char **endp, unsigned int base)
|
|||
|
{
|
|||
|
unsigned long long result;
|
|||
|
unsigned int rv;
|
|||
|
|
|||
|
cp = _parse_integer_fixup_radix(cp, &base);
|
|||
|
rv = _parse_integer(cp, base, &result);
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
static long long simple_strtoll_patch(const char *cp, char **endp, unsigned int base)
|
|||
|
{
|
|||
|
if(*cp == '-')
|
|||
|
return -simple_strtoull_patch(cp + 1, endp, base);
|
|||
|
|
|||
|
return simple_strtoull_patch(cp, endp, base);
|
|||
|
}
|
|||
|
static unsigned long simple_strtoul_patch(const char *cp, char **endp, unsigned int base)
|
|||
|
{
|
|||
|
return simple_strtoull_patch(cp, endp, base);
|
|||
|
}
|
|||
|
|
|||
|
static long simple_strtol_patch(const char *cp, char **endp, unsigned int base)
|
|||
|
{
|
|||
|
if(*cp == '-')
|
|||
|
return -simple_strtoul_patch(cp + 1, endp, base);
|
|||
|
|
|||
|
return simple_strtoul_patch(cp, endp, base);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
static int judge_digit_width(const char *str)
|
|||
|
{
|
|||
|
|
|||
|
int width = 0;
|
|||
|
|
|||
|
while(isdigit(*str)) {
|
|||
|
width++;
|
|||
|
str++;
|
|||
|
}
|
|||
|
|
|||
|
return width;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
static int _vsscanf_patch(const char *buf, const char *fmt, va_list args)
|
|||
|
{
|
|||
|
const char *str = buf;
|
|||
|
char *next;
|
|||
|
char digit;
|
|||
|
int num = 0;
|
|||
|
int i =0;
|
|||
|
u8 qualifier;
|
|||
|
unsigned int base;
|
|||
|
union {
|
|||
|
long long s;
|
|||
|
unsigned long long u;
|
|||
|
} val;
|
|||
|
s16 field_width;
|
|||
|
bool is_sign;
|
|||
|
|
|||
|
char str_store[20] = {0};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
while(*fmt) {
|
|||
|
/* skip any white space in format */
|
|||
|
/* white space in format matchs any amount of
|
|||
|
* white space, including none, in the input.
|
|||
|
*/
|
|||
|
if(isspace(*fmt)) {
|
|||
|
fmt = skip_spaces(++fmt);
|
|||
|
str = skip_spaces(str);
|
|||
|
}
|
|||
|
|
|||
|
/* anything that is not a conversion must match exactly */
|
|||
|
if(*fmt != '%' && *fmt) {
|
|||
|
if(*fmt++ != *str++) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if(!*fmt) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
++fmt;
|
|||
|
|
|||
|
/* skip this conversion.
|
|||
|
* advance both strings to next white space
|
|||
|
*/
|
|||
|
if(*fmt == '*') {
|
|||
|
if(!*str) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
while(!isspace(*fmt) && *fmt != '%' && *fmt)
|
|||
|
fmt++;
|
|||
|
|
|||
|
while(!isspace(*str) && *str)
|
|||
|
str++;
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
/* get field width */
|
|||
|
field_width = -1;
|
|||
|
|
|||
|
if(isdigit(*fmt)) {
|
|||
|
|
|||
|
field_width = skip_atoi(&fmt);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if(field_width <= 0) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* get conversion qualifier */
|
|||
|
qualifier = -1;
|
|||
|
|
|||
|
if(*fmt == 'h' || _tolower(*fmt) == 'l' ||
|
|||
|
_tolower(*fmt) == 'z') {
|
|||
|
qualifier = *fmt++;
|
|||
|
|
|||
|
if(qualifier == *fmt) {
|
|||
|
if(qualifier == 'h') {
|
|||
|
qualifier = 'H';
|
|||
|
fmt++;
|
|||
|
} else if(qualifier == 'l') {
|
|||
|
qualifier = 'L';
|
|||
|
fmt++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if(!*fmt) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if(*fmt == 'n') {
|
|||
|
/* return number of characters read so far */
|
|||
|
*va_arg(args, int *) = str - buf;
|
|||
|
++fmt;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if(!*str) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
base = 10;
|
|||
|
is_sign = 0;
|
|||
|
|
|||
|
switch(*fmt++) {
|
|||
|
case 'c': {
|
|||
|
char *s = (char *)va_arg(args, char*);
|
|||
|
|
|||
|
if(field_width == -1)
|
|||
|
field_width = 1;
|
|||
|
|
|||
|
do {
|
|||
|
*s++ = *str++;
|
|||
|
} while(--field_width > 0 && *str);
|
|||
|
|
|||
|
num++;
|
|||
|
}
|
|||
|
|
|||
|
continue;
|
|||
|
|
|||
|
case 's': {
|
|||
|
char *s = (char *)va_arg(args, char *);
|
|||
|
|
|||
|
if(field_width == -1)
|
|||
|
field_width = SHRT_MAX;
|
|||
|
|
|||
|
/* first, skip leading white space in buffer */
|
|||
|
str = skip_spaces(str);
|
|||
|
|
|||
|
/* now copy until next white space */
|
|||
|
while(*str && !isspace(*str) && field_width--) {
|
|||
|
*s++ = *str++;
|
|||
|
}
|
|||
|
|
|||
|
*s = '\0';
|
|||
|
num++;
|
|||
|
}
|
|||
|
|
|||
|
continue;
|
|||
|
|
|||
|
case 'o':
|
|||
|
base = 8;
|
|||
|
break;
|
|||
|
|
|||
|
case 'x':
|
|||
|
case 'X':
|
|||
|
base = 16;
|
|||
|
break;
|
|||
|
|
|||
|
case 'i':
|
|||
|
base = 0;
|
|||
|
|
|||
|
case 'd':
|
|||
|
is_sign = 1;
|
|||
|
|
|||
|
case 'u':
|
|||
|
break;
|
|||
|
|
|||
|
case '%':
|
|||
|
|
|||
|
/* looking for '%' in str */
|
|||
|
if(*str++ != '%') {
|
|||
|
return num;
|
|||
|
}
|
|||
|
|
|||
|
continue;
|
|||
|
|
|||
|
default:
|
|||
|
/* invalid format; stop here */
|
|||
|
return num;
|
|||
|
}
|
|||
|
|
|||
|
/* have some sort of integer conversion.
|
|||
|
* first, skip white space in buffer.
|
|||
|
*/
|
|||
|
str = skip_spaces(str);
|
|||
|
|
|||
|
digit = *str;
|
|||
|
|
|||
|
if(is_sign && digit == '-')
|
|||
|
digit = *(str + 1);
|
|||
|
|
|||
|
if(!digit
|
|||
|
|| (base == 16 && !isxdigit(digit))
|
|||
|
|| (base == 10 && !isdigit(digit))
|
|||
|
|| (base == 8 && (!isdigit(digit) || digit > '7'))
|
|||
|
|| (base == 0 && !isdigit(digit))) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//here problem *******************************************
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//troy add ,fix support %2d, but not support %d
|
|||
|
if(field_width <= 0) {
|
|||
|
|
|||
|
field_width = judge_digit_width(str);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/////troy add, fix str passed inwidth wrong
|
|||
|
for(i = 0; i<field_width ; i++)
|
|||
|
str_store[i] = str[i];
|
|||
|
|
|||
|
next = (char*)str + field_width;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if(is_sign) {
|
|||
|
val.s = qualifier != 'L' ?
|
|||
|
simple_strtol_patch(str_store, &next, base) :
|
|||
|
simple_strtoll_patch(str_store, &next, base);
|
|||
|
} else {
|
|||
|
val.u = qualifier != 'L' ?
|
|||
|
simple_strtoul_patch(str_store, &next, base) :
|
|||
|
simple_strtoull_patch(str_store, &next, base);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
////troy add
|
|||
|
for(i = 0; i<20 ; i++)
|
|||
|
str_store[i] = 0;
|
|||
|
|
|||
|
|
|||
|
//判断转换的字符串的宽度是否大于 %2d
|
|||
|
if(field_width > 0 && next - str > field_width) {
|
|||
|
if(base == 0)
|
|||
|
_parse_integer_fixup_radix(str, &base);
|
|||
|
|
|||
|
while(next - str > field_width) {
|
|||
|
if(is_sign) {
|
|||
|
val.s = div_s64(val.s, base);
|
|||
|
} else {
|
|||
|
val.u = div_u64(val.u, base);
|
|||
|
}
|
|||
|
|
|||
|
--next;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
switch(qualifier) {
|
|||
|
case 'H': /* that's 'hh' in format */
|
|||
|
if(is_sign)
|
|||
|
*va_arg(args, signed char *) = val.s;
|
|||
|
else
|
|||
|
*va_arg(args, unsigned char *) = val.u;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case 'h':
|
|||
|
if(is_sign)
|
|||
|
*va_arg(args, short *) = val.s;
|
|||
|
else
|
|||
|
*va_arg(args, unsigned short *) = val.u;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case 'l':
|
|||
|
if(is_sign)
|
|||
|
*va_arg(args, long *) = val.s;
|
|||
|
else
|
|||
|
*va_arg(args, unsigned long *) = val.u;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case 'L':
|
|||
|
if(is_sign)
|
|||
|
*va_arg(args, long long *) = val.s;
|
|||
|
else
|
|||
|
*va_arg(args, unsigned long long *) = val.u;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case 'Z':
|
|||
|
case 'z':
|
|||
|
*va_arg(args, size_t *) = val.u;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
if(is_sign)
|
|||
|
*va_arg(args, int *) = val.s;
|
|||
|
else
|
|||
|
*va_arg(args, unsigned int *) = val.u;
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
num++;
|
|||
|
|
|||
|
if(!next) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
str = next;
|
|||
|
}
|
|||
|
|
|||
|
return num;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int DiagSscanfPatch(const char *buf, const char *fmt, ...)
|
|||
|
{
|
|||
|
va_list args;
|
|||
|
int i;
|
|||
|
|
|||
|
va_start(args, fmt);
|
|||
|
i = _vsscanf_patch(buf, fmt, args);
|
|||
|
va_end(args);
|
|||
|
|
|||
|
return i;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*********************************************************/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
char* DiagStrtokPatch(char *str, const char* delim) {
|
|||
|
static char* _buffer;
|
|||
|
|
|||
|
if(str != NULL) _buffer = str;
|
|||
|
|
|||
|
if(_buffer[0] == '\0') return NULL;
|
|||
|
|
|||
|
char *ret = _buffer, *b;
|
|||
|
const char *d;
|
|||
|
|
|||
|
for(b = _buffer; *b !='\0'; b++) {
|
|||
|
for(d = delim; *d != '\0'; d++) {
|
|||
|
if(*b == *d) {
|
|||
|
*b = '\0';
|
|||
|
_buffer = b+1;
|
|||
|
|
|||
|
// skip the beginning delimiters
|
|||
|
if(b == ret) {
|
|||
|
ret++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*********************************************************/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
char *DiagStrstrPatch(char *string, char *substring)
|
|||
|
{
|
|||
|
register char *a, *b;
|
|||
|
|
|||
|
/* First scan quickly through the two strings looking for a
|
|||
|
* single-character match. When it's found, then compare the
|
|||
|
* rest of the substring.
|
|||
|
*/
|
|||
|
|
|||
|
b = substring;
|
|||
|
|
|||
|
if(*b == 0) {
|
|||
|
return string;
|
|||
|
}
|
|||
|
|
|||
|
for(; *string != 0; string += 1) {
|
|||
|
if(*string != *b) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
a = string;
|
|||
|
|
|||
|
while(1) {
|
|||
|
if(*b == 0) {
|
|||
|
return string;
|
|||
|
}
|
|||
|
|
|||
|
if(*a++ != *b++) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
b = substring;
|
|||
|
}
|
|||
|
|
|||
|
return (char *) 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*********************************************************/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
int DiagSnPrintfPatch(char *buf, size_t size, const char *fmt, ...)
|
|||
|
{
|
|||
|
|
|||
|
va_list ap;
|
|||
|
char *p, *s, *buf_end = NULL;
|
|||
|
const int *dp = ((const int *)&fmt)+1;
|
|||
|
|
|||
|
if(buf == NULL)
|
|||
|
return 0;
|
|||
|
|
|||
|
|
|||
|
va_start(ap, fmt);
|
|||
|
s = buf;
|
|||
|
buf_end = size? (buf + size):(char*)~0;
|
|||
|
|
|||
|
for(; *fmt != '\0'; ++fmt) {
|
|||
|
|
|||
|
if(*fmt != '%') {
|
|||
|
*s++ = *fmt;
|
|||
|
|
|||
|
if(s >= buf_end) {
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if(*++fmt == 's') {
|
|||
|
for(p = (char *)*dp++; *p != '\0'; p++) {
|
|||
|
*s++ = *p;
|
|||
|
|
|||
|
if(s >= buf_end) {
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else { /* Length of item is bounded */
|
|||
|
char tmp[20], *q = tmp;
|
|||
|
int alt = 0;
|
|||
|
int shift = 0;// = 12;
|
|||
|
const long *lpforchk = (const long *)dp;
|
|||
|
|
|||
|
if((*lpforchk) < 0x10) {
|
|||
|
shift = 0;
|
|||
|
}
|
|||
|
else if(((*lpforchk) >= 0x10) && ((*lpforchk) < 0x100)) {
|
|||
|
shift = 4;
|
|||
|
}
|
|||
|
else if(((*lpforchk) >= 0x100) && ((*lpforchk) < 0x1000)) {
|
|||
|
shift = 8;
|
|||
|
}
|
|||
|
else if(((*lpforchk) >= 0x1000) && ((*lpforchk) < 0x10000)) {
|
|||
|
shift = 12;
|
|||
|
}
|
|||
|
else if(((*lpforchk) >= 0x10000) && ((*lpforchk) < 0x100000)) {
|
|||
|
shift = 16;
|
|||
|
}
|
|||
|
else if(((*lpforchk) >= 0x100000) && ((*lpforchk) < 0x1000000)) {
|
|||
|
shift = 20;
|
|||
|
}
|
|||
|
else if(((*lpforchk) >= 0x1000000) && ((*lpforchk) < 0x10000000)) {
|
|||
|
shift = 24;
|
|||
|
}
|
|||
|
else if((*lpforchk) >= 0x10000000) {
|
|||
|
shift = 28;
|
|||
|
}
|
|||
|
else {
|
|||
|
shift = 28;
|
|||
|
}
|
|||
|
|
|||
|
if((*fmt >= '0') && (*fmt <= '9'))
|
|||
|
{
|
|||
|
int width;
|
|||
|
unsigned char fch = *fmt;
|
|||
|
|
|||
|
for(width=0; (fch>='0') && (fch<='9'); fch=*++fmt)
|
|||
|
{ width = width * 10 + fch - '0';
|
|||
|
}
|
|||
|
|
|||
|
shift=(width-1)*4;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Before each format q points to tmp buffer
|
|||
|
* After each format q points past end of item
|
|||
|
*/
|
|||
|
if((*fmt == 'x')||(*fmt == 'X') || (*fmt == 'p') || (*fmt == 'P')) {
|
|||
|
/* With x86 gcc, sizeof(long) == sizeof(int) */
|
|||
|
const long *lp = (const long *)dp;
|
|||
|
long h = *lp++;
|
|||
|
int hex_count = 0;
|
|||
|
unsigned long h_back = h;
|
|||
|
int ncase = (*fmt & 0x20);
|
|||
|
dp = (const int *)lp;
|
|||
|
|
|||
|
if((*fmt == 'p') || (*fmt == 'P'))
|
|||
|
alt=1;
|
|||
|
|
|||
|
if(alt) {
|
|||
|
*q++ = '0';
|
|||
|
*q++ = 'X' | ncase;
|
|||
|
}
|
|||
|
|
|||
|
while(h_back) {
|
|||
|
hex_count += (h_back & 0xF) ? 1 : 0;
|
|||
|
h_back = h_back >> 4;
|
|||
|
}
|
|||
|
|
|||
|
if(shift < (hex_count - 1)*4)
|
|||
|
shift = (hex_count - 1)*4;
|
|||
|
|
|||
|
for(; shift >= 0; shift -= 4)
|
|||
|
*q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
|
|||
|
}
|
|||
|
else if(*fmt == 'd') {
|
|||
|
int i = *dp++;
|
|||
|
char *r;
|
|||
|
int digit_space = 0;
|
|||
|
|
|||
|
|
|||
|
if(i < 0) {
|
|||
|
*q++ = '-';
|
|||
|
i = -i;
|
|||
|
digit_space++;
|
|||
|
}
|
|||
|
|
|||
|
p = q; /* save beginning of digits */
|
|||
|
|
|||
|
|
|||
|
do {
|
|||
|
*q++ = '0' + (i % 10);
|
|||
|
i /= 10;
|
|||
|
digit_space++;
|
|||
|
} while(i);
|
|||
|
|
|||
|
|
|||
|
for(; shift >= 0; shift -= 4) {
|
|||
|
|
|||
|
if(digit_space-- > 0) {
|
|||
|
; //do nothing
|
|||
|
} else {
|
|||
|
*q++ = '0';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* reverse digits, stop in middle */
|
|||
|
r = q; /* don't alter q */
|
|||
|
|
|||
|
while(--r > p) {
|
|||
|
i = *r;
|
|||
|
*r = *p;
|
|||
|
*p++ = i;
|
|||
|
}
|
|||
|
}
|
|||
|
else if(*fmt == 'c')
|
|||
|
*q++ = *dp++;
|
|||
|
else
|
|||
|
*q++ = *fmt;
|
|||
|
|
|||
|
/* now output the saved string */
|
|||
|
for(p = tmp; p < q; ++p) {
|
|||
|
*s++ = *p;
|
|||
|
|
|||
|
if(s >= buf_end) {
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Exit:
|
|||
|
|
|||
|
if(buf)
|
|||
|
*s = '\0';
|
|||
|
|
|||
|
va_end(ap);
|
|||
|
return(s-buf);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*********************************************************/
|
|||
|
|
|||
|
static int VSprintfPatch(char *buf, const char *fmt, const int *dp)
|
|||
|
{
|
|||
|
char *p, *s;
|
|||
|
s = buf;
|
|||
|
|
|||
|
for(; *fmt != '\0'; ++fmt) {
|
|||
|
if(*fmt != '%') {
|
|||
|
if(buf) {
|
|||
|
*s++ = *fmt;
|
|||
|
} else {
|
|||
|
DiagPutChar(*fmt);
|
|||
|
}
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if(*++fmt == 's') {
|
|||
|
for(p = (char *)*dp++; *p != '\0'; p++) {
|
|||
|
if(buf) {
|
|||
|
*s++ = *p;
|
|||
|
} else {
|
|||
|
DiagPutChar(*p);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else { /* Length of item is bounded */
|
|||
|
char tmp[20], *q = tmp;
|
|||
|
int alt = 0;
|
|||
|
int shift = 0;// = 12;
|
|||
|
const long *lpforchk = (const long *)dp;
|
|||
|
|
|||
|
if((*lpforchk) < 0x10) {
|
|||
|
shift = 0;
|
|||
|
}
|
|||
|
else if(((*lpforchk) >= 0x10) && ((*lpforchk) < 0x100)) {
|
|||
|
shift = 4;
|
|||
|
}
|
|||
|
else if(((*lpforchk) >= 0x100) && ((*lpforchk) < 0x1000)) {
|
|||
|
shift = 8;
|
|||
|
}
|
|||
|
else if(((*lpforchk) >= 0x1000) && ((*lpforchk) < 0x10000)) {
|
|||
|
shift = 12;
|
|||
|
}
|
|||
|
else if(((*lpforchk) >= 0x10000) && ((*lpforchk) < 0x100000)) {
|
|||
|
shift = 16;
|
|||
|
}
|
|||
|
else if(((*lpforchk) >= 0x100000) && ((*lpforchk) < 0x1000000)) {
|
|||
|
shift = 20;
|
|||
|
}
|
|||
|
else if(((*lpforchk) >= 0x1000000) && ((*lpforchk) < 0x10000000)) {
|
|||
|
shift = 24;
|
|||
|
}
|
|||
|
else if((*lpforchk) >= 0x10000000) {
|
|||
|
shift = 28;
|
|||
|
}
|
|||
|
else {
|
|||
|
shift = 28;
|
|||
|
}
|
|||
|
|
|||
|
#if 1 //wei patch for %02x
|
|||
|
|
|||
|
if((*fmt >= '0') && (*fmt <= '9'))
|
|||
|
{
|
|||
|
int width;
|
|||
|
unsigned char fch = *fmt;
|
|||
|
|
|||
|
for(width=0; (fch>='0') && (fch<='9'); fch=*++fmt)
|
|||
|
{ width = width * 10 + fch - '0';
|
|||
|
}
|
|||
|
|
|||
|
shift=(width-1)*4;
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
/*
|
|||
|
* Before each format q points to tmp buffer
|
|||
|
* After each format q points past end of item
|
|||
|
*/
|
|||
|
|
|||
|
if((*fmt == 'x')||(*fmt == 'X') || (*fmt == 'p') || (*fmt == 'P')) {
|
|||
|
/* With x86 gcc, sizeof(long) == sizeof(int) */
|
|||
|
const long *lp = (const long *)dp;
|
|||
|
long h = *lp++;
|
|||
|
int hex_count = 0;
|
|||
|
unsigned long h_back = h;
|
|||
|
int ncase = (*fmt & 0x20);
|
|||
|
dp = (const int *)lp;
|
|||
|
|
|||
|
if((*fmt == 'p') || (*fmt == 'P'))
|
|||
|
alt=1;
|
|||
|
|
|||
|
if(alt) {
|
|||
|
*q++ = '0';
|
|||
|
*q++ = 'X' | ncase;
|
|||
|
}
|
|||
|
|
|||
|
//hback 是实际得到的数据,hex_count是统计数据的HEX字符个数
|
|||
|
while(h_back) {
|
|||
|
hex_count += (h_back & 0xF) ? 1 : 0;
|
|||
|
h_back = h_back >> 4;
|
|||
|
}
|
|||
|
|
|||
|
//这里修复 example: 字符有4个,但是用了%02x导致字符被截断的情况
|
|||
|
if(shift < (hex_count - 1)*4)
|
|||
|
shift = (hex_count - 1)*4;
|
|||
|
|
|||
|
//printf("(%d,%d)", hex_count, shift);
|
|||
|
|
|||
|
for(; shift >= 0; shift -= 4) {
|
|||
|
|
|||
|
*q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
else if(*fmt == 'd') {
|
|||
|
int i = *dp++;
|
|||
|
char *r;
|
|||
|
int digit_space = 0;
|
|||
|
|
|||
|
if(i < 0) {
|
|||
|
*q++ = '-';
|
|||
|
i = -i;
|
|||
|
digit_space++;
|
|||
|
}
|
|||
|
|
|||
|
p = q; /* save beginning of digits */
|
|||
|
|
|||
|
do {
|
|||
|
*q++ = '0' + (i % 10);
|
|||
|
i /= 10;
|
|||
|
digit_space++;
|
|||
|
} while(i);
|
|||
|
|
|||
|
//这里修复 example:用了%08d后,在数字前面没有0的情况
|
|||
|
for(; shift >= 0; shift -= 4) {
|
|||
|
|
|||
|
if(digit_space-- > 0) {
|
|||
|
; //do nothing
|
|||
|
} else {
|
|||
|
*q++ = '0';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* reverse digits, stop in middle */
|
|||
|
r = q; /* don't alter q */
|
|||
|
|
|||
|
while(--r > p) {
|
|||
|
i = *r;
|
|||
|
*r = *p;
|
|||
|
*p++ = i;
|
|||
|
}
|
|||
|
}
|
|||
|
else if(*fmt == 'c')
|
|||
|
*q++ = *dp++;
|
|||
|
else
|
|||
|
*q++ = *fmt;
|
|||
|
|
|||
|
/* now output the saved string */
|
|||
|
for(p = tmp; p < q; ++p) {
|
|||
|
if(buf) {
|
|||
|
*s++ = *p;
|
|||
|
} else {
|
|||
|
DiagPutChar(*p);
|
|||
|
}
|
|||
|
|
|||
|
if((*p) == '\n') {
|
|||
|
DiagPutChar('\r');
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if(buf)
|
|||
|
*s = '\0';
|
|||
|
|
|||
|
return (s - buf);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
u32 DiagPrintfPatch(
|
|||
|
IN const char *fmt, ...
|
|||
|
)
|
|||
|
{
|
|||
|
(void)VSprintfPatch(0, fmt, ((const int *)&fmt)+1);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
u32 DiagSPrintfPatch(
|
|||
|
IN u8 *buf,
|
|||
|
IN const char *fmt, ...
|
|||
|
)
|
|||
|
{
|
|||
|
(void)VSprintfPatch((char*)buf, fmt, ((const int *)&fmt)+1);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
#endif
|