📄 stdlib.c
字号:
{
void *np = base_realloc(p, nsz);
if (g_malloclog != NULL)
{
fprintf(g_malloclog, "r %#x %u %#x", (uInt)p, nsz, (uInt)np);
do_stk();
}
return np;
}
#endif /* LOG_MALLOC */
/* vbprintf is like vsprintf but only handles strings and ints,
with just a few formats and field options plus some custom extensions:
# alternate formatting - for hex, prepend 0x to output otherwise ignore
- right-pad output with blanks - only for strings right now
0 left-pad numbers with zero
0-9+ numeric field width - left-pad with blanks unless leading 0 specified
* numeric field width taken from next argument
lqL display following integer specification as a Long instead of an Int
C display following integer specification as a Cell - may be Int or Long
d display integer argument in decimal
u display unsigned integer argument in decimal
x display unsigned integer argument in hexadecimal - case HEX_A
X display unsigned integer argument in upper-case hexadecimal
p display pointer argument as hex with leading 0x - like %#x or %#lx
c display integer as a single character
s display C string (null-u08 terminated)
P display Pascal string (1st u08 is length)
S display Forth string (2 args - string & length)
*/
extern int vbprintf(char *buf, const char *fmt, va_list args);
int
vbprintf(char *buf, const char *fmt, va_list args)
{
char *sarg, *s;
u32 iarg;
int field, hex;
Int len;
Bool rpad, lzero, sign, larg, alt;
char nbuf[STR_SIZE];
if (fmt == NULL || buf == NULL)
return 0;
while (*fmt)
{
if (*fmt != '%')
{
*buf++ = *fmt++;
continue;
}
if (*++fmt == '%')
{
*buf++ = *fmt++;
continue;
}
field = 0;
rpad = FALSE;
lzero = FALSE;
sign = FALSE;
hex = 0;
larg = FALSE;
alt = FALSE;
if (*fmt == '#')
{
fmt++;
alt = TRUE;
}
if (*fmt == '-')
{
fmt++;
rpad = TRUE;
}
if (*fmt == '0')
{
fmt++;
lzero = TRUE;
}
if (*fmt == '*')
{
field = va_arg(args, Int);
fmt++;
}
else
for (; isdigit(*fmt); fmt++)
field = field * 10 + *fmt - '0';
/* following arg is long instead of int */
if (*fmt == 'l' || *fmt == 'L' || *fmt == 'q' || *fmt == 'C')
{
if (*fmt != 'C' || sizeof (Cell) > sizeof (Int))
larg = TRUE;
fmt++;
/* skip "%ll*" style formats */
if (*fmt == 'l')
fmt++;
}
/* used to be switch (*fmt++) but some gcc revs generate bad code */
iarg = *fmt++;
if (iarg == 'c') /* character */
{
iarg = va_arg(args, Int);
*buf++ = iarg;
}
else if (iarg == 'x' || iarg == 'X' || iarg == 'd' || iarg == 'u' ||
iarg == 'p')
{
if (iarg == 'x')
hex = HEX_A;
else if (iarg == 'X')
hex = 'A';
else if (iarg == 'p')
{
hex = HEX_A;
alt = TRUE;
}
if (larg || (iarg == 'p' && sizeof (Ptr) > sizeof (Int)))
iarg = va_arg(args, u32);
else if (hex || iarg == 'u')
{
iarg = va_arg(args, uInt);
/* work around for gcc ARM problem */
iarg &= 0xFFFFFFFF;
}
else
iarg = va_arg(args, Int);
s = nbuf + STR_SIZE - 1;
*s = '\0';
if (!hex && (Long)iarg < 0)
{
sign = TRUE;
iarg = -(Long)iarg;
field--;
}
else if (iarg == 0)
{
*--s = '0';
field--;
}
for (; iarg; field--)
{
if (hex)
{
int d = iarg & 0xF;
*--s = (d < 10) ? d + '0' : d - 10 + hex;
iarg >>= 4;
}
else
{
*--s = iarg % 10 + '0';
iarg /= 10;
}
}
while (field-- > 0)
*--s = (lzero) ? '0' : ' ';
if (hex && alt)
{
*--s = 'x';
*--s = '0';
}
if (sign)
*--s = '-';
while (*s)
*buf++ = *s++;
}
else if (iarg == 's' || iarg == 'S' || iarg == 'P') /* string */
{
sarg = va_arg(args, char*);
if (iarg == 'S') /* Forth-style string */
len = va_arg(args, Int);
else if (sarg == NULL) /* no string */
len = 0;
else if (iarg == 'P') /* Pascal-style string */
len = *(uu08*)sarg++;
else /* C string */
len = strlen(sarg);
if (!rpad)
{
while (field - len > 0)
{
*buf++ = ' ';
field--;
}
}
for (; len-- > 0; field--)
*buf++ = *sarg++;
if (rpad)
while (field-- > 0)
*buf++ = ' ';
}
}
*buf = '\0';
return strlen(buf);
}
/* this is like sprintf but renamed to avoid collision with standard libs */
int
bprintf(char *buf, const char *fmt, ...)
{
va_list args;
int ret;
va_start(args, fmt);
ret = vbprintf(buf, fmt, args);
va_end(args);
return ret;
}
/* this is like bprintf only it uses and returns a static buffer */
char *
rbprintf(const char *fmt, ...)
{
va_list args;
static char buf[STR_SIZE];
*buf = '\0';
va_start(args, fmt);
(void)vbprintf(buf, fmt, args);
va_end(args);
return buf;
}
/* hacks to speed up memset() and memmove() a little
- we assume that the integer type is at least 32 bits */
#ifdef BROKEN_64BIT_INTS
#define LSB_BITS (sizeof (uInt) - 1)
#define LONG_SIZE (sizeof (uInt))
#define LONG_TYPE uInt
#else
#define LSB_BITS (sizeof (u32) - 1)
#define LONG_SIZE (sizeof (u32))
#define LONG_TYPE u32
#endif
void *
memset(void *ptr, int val, size_t len)
{
unsigned char *p = (unsigned char *)ptr;
unsigned char b = val;
#if REALLY_SIMPLE
while (len-- > 0)
*p++ = b;
#else
while (((Ptr)p & LSB_BITS) && len > 0)
{
*p++ = b;
len--;
}
if (len)
{
LONG_TYPE *pl = (LONG_TYPE *)p;
size_t l = len / LONG_SIZE;
LONG_TYPE lval;
val &= u08_MASK;
lval = (val << u08_SIZE) | val;
lval = (lval << (u08_SIZE * 2)) | lval;
#if defined __LONGLONG && !defined BROKEN_64BIT_INTS
lval = (lval << (u08_SIZE * 4)) | lval;
#endif
len -= l * LONG_SIZE;
while (l--)
*pl++ = lval;
if (len)
{
p = (unsigned char *)pl;
while (len--)
*p++ = b;
}
}
#endif /* REALLY_SIMPLE */
return ptr;
}
void *
memmove(void *dst, const void *src, size_t len)
{
char *d = (char *)dst;
char *s = (char *)src;
#if REALLY_SIMPLE
if (d < s) /* assume src overlaps end of dst */
{
while (len-- > 0)
*d++ = *s++;
}
else
{
s += len;
d += len;
while (len-- > 0)
*--d = *--s;
}
#else
if (d < s) /* assume src overlaps end of dst */
{
if (len > LONG_SIZE * 3 && ((Ptr)d & LSB_BITS) == (((Ptr)s) & LSB_BITS))
{
while (((Ptr)s & LSB_BITS) && len > 0)
{
*d++ = *s++;
len--;
}
if (len)
{
LONG_TYPE *sl = (LONG_TYPE *)s;
LONG_TYPE *dl = (LONG_TYPE *)d;
size_t l = len / LONG_SIZE;
len -= l * LONG_SIZE;
while (l-- > 0)
*dl++ = *sl++;
if (len)
{
s = (char *)sl;
d = (char *)dl;
while (len-- > 0)
*d++ = *s++;
}
}
}
else
{
while (len-- > 0)
*d++ = *s++;
}
}
else /* assume dst overlaps end of src */
{
s += len;
d += len;
if (len > LONG_SIZE * 3 && ((Ptr)d & LSB_BITS) == (((Ptr)s) & LSB_BITS))
{
while (((Ptr)s & LSB_BITS) && len > 0)
{
*--d = *--s;
len--;
}
if (len)
{
LONG_TYPE *sl = (LONG_TYPE *)s;
LONG_TYPE *dl = (LONG_TYPE *)d;
size_t l = len / LONG_SIZE;
len -= l * LONG_SIZE;
while (l-- > 0)
*--dl = *--sl;
if (len)
{
s = (char *)sl;
d = (char *)dl;
while (len-- > 0)
*--d = *--s;
}
}
}
else
{
while (len-- > 0)
*--d = *--s;
}
}
#endif /* REALLY_SIMPLE */
return dst;
}
void *
memcpy(void *dst, const void *src, size_t len)
{
return memmove(dst, src, len);
}
#ifdef bcopy
#undef bcopy
#endif
void
bcopy(const void *src, void *dst, size_t len)
{
memmove(dst, src, len);
}
#ifdef bzero
#undef bzero
#endif
void
bzero(void *ptr, size_t len)
{
memset(ptr, '\0', len);
}
int
memcmp(const void *m1, const void *m2, size_t len)
{
const unsigned char *s1 = (const unsigned char*)m1;
const unsigned char *s2 = (const unsigned char*)m2;
for (; len > 0; s1++, s2++, len--)
if (*s1 != *s2)
break;
return (len == 0) ? 0 : *s2 - *s1;
}
size_t
strlen(const char *str)
{
size_t len = 0;
if (str)
while (*str++)
len++;
return len;
}
char *
strcat(char *str, const char *append)
{
char *ostr = str;
if (str == NULL || append == NULL)
return str;
str += strlen(str);
while (*append)
*str++ = *append++;
*str = '\0';
return ostr;
}
char *
strncat(char *str, const char *append, size_t count)
{
char *ostr = str;
if (str == NULL || append == NULL || count == 0)
return str;
str += strlen(str);
while (*append && count-- > 0)
*str++ = *append++;
*str = '\0';
return ostr;
}
char *
strcpy(char *dst, const char *src)
{
char *odst = dst;
if (dst == NULL || src == NULL)
return dst;
while (*src)
*dst++ = *src++;
*dst = '\0';
return odst;
}
char *
strncpy(char *dst, const char *src, size_t len)
{
char *odst = dst;
if (dst == NULL || src == NULL)
return dst;
while (*src && len-- > 0)
*dst++ = *src++;
if (len > 0)
*dst = '\0';
return odst;
}
char *
strchr(const char *str, int chr)
{
if (str == NULL)
return NULL;
while (*str && *str != chr)
str++;
return (*str == chr) ? (char*)str : NULL;
}
char *
strrchr(const char *str, int chr)
{
const char *ostr = str;
if (str == NULL)
return NULL;
str += strlen(str) - 1;
while (str >= ostr && *str != chr)
str--;
return (str >= ostr) ? (char*)str : NULL;
}
int
strcmp(const char *s1, const char *s2)
{
if (s1 == NULL)
s1 = "";
if (s2 == NULL)
s2 = "";
for (; *s1 && *s2; s1++, s2++)
if (*s1 != *s2)
break;
return (!*s1 && !*s2) ? 0 : *s2 - *s1;
}
int
strncmp(const char *s1, const char *s2, size_t len)
{
if (s1 == NULL)
s1 = "";
if (s2 == NULL)
s2 = "";
for (; *s1 && *s2 && len--; s1++, s2++)
if (*s1 != *s2)
break;
return (!len && !*s1 && !*s2) ? 0 : *s2 - *s1;
}
/* created using Knuth's Seminumerical Algorithms and tweaked a bit */
static unsigned long seed = 1262951413ul;
void
srand(unsigned s)
{
seed = s;
}
unsigned long
urand(void)
{
seed = seed * 3141592621ul + 1;
seed ^= seed >> 13;
return seed;
}
int
rand(void)
{
return (int)(urand() & 0x7FFFFFFFul);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -