399 lines
8.2 KiB
C
399 lines
8.2 KiB
C
|
/* Copyright (C) 2004 David Decotigny (with INSA Rennes for vsnprintf)
|
||
|
Copyright (C) 2003 The KOS Team
|
||
|
Copyright (C) 1999 Free Software Foundation
|
||
|
|
||
|
This program is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU General Public License
|
||
|
as published by the Free Software Foundation; either version 2
|
||
|
of the License, or (at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||
|
USA.
|
||
|
*/
|
||
|
#include "klibc.h"
|
||
|
|
||
|
/* For an optimized version, see BSD sources ;) */
|
||
|
void *memcpy(void *dst0, const void *src0, register unsigned int size)
|
||
|
{
|
||
|
char *dst;
|
||
|
const char *src;
|
||
|
for (dst = (char*)dst0, src = (const char*)src0 ;
|
||
|
size > 0 ;
|
||
|
dst++, src++, size--)
|
||
|
*dst = *src;
|
||
|
return dst0;
|
||
|
}
|
||
|
|
||
|
/* ditto */
|
||
|
void *memset(void *dst0, register int c, register unsigned int length)
|
||
|
{
|
||
|
char *dst;
|
||
|
for (dst = (char*) dst0 ;
|
||
|
length > 0 ;
|
||
|
dst++, length --)
|
||
|
*dst = (char)c;
|
||
|
return dst0;
|
||
|
}
|
||
|
|
||
|
int memcmp(const void *s1, const void *s2, sos_size_t len)
|
||
|
{
|
||
|
const unsigned char *c1, *c2;
|
||
|
unsigned int i;
|
||
|
|
||
|
for (i = 0, c1 = s1, c2 = s2; i < len; i++, c1++, c2++)
|
||
|
{
|
||
|
if(*c1 != *c2)
|
||
|
return *c1 - *c2;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
unsigned int strlen(register const char *str)
|
||
|
{
|
||
|
unsigned int retval = 0;
|
||
|
|
||
|
while (*str++)
|
||
|
retval++;
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
|
||
|
unsigned int strnlen(const char * s, sos_size_t count)
|
||
|
{
|
||
|
const char *sc;
|
||
|
|
||
|
for (sc = s; count-- && *sc != '\0'; ++sc)
|
||
|
/* nothing */continue;
|
||
|
|
||
|
return sc - s;
|
||
|
}
|
||
|
|
||
|
|
||
|
char *strzcpy(register char *dst, register const char *src, register int len)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
if (len <= 0)
|
||
|
return dst;
|
||
|
|
||
|
for (i = 0; i < len; i++)
|
||
|
{
|
||
|
dst[i] = src[i];
|
||
|
if(src[i] == '\0')
|
||
|
return dst;
|
||
|
}
|
||
|
|
||
|
dst[len-1] = '\0';
|
||
|
return dst;
|
||
|
}
|
||
|
|
||
|
|
||
|
char *strzcat (char *dest, const char *src, sos_size_t n)
|
||
|
{
|
||
|
char *res = dest;
|
||
|
|
||
|
for ( ; *dest ; dest++);
|
||
|
|
||
|
for ( ; *src ; src++, dest++) {
|
||
|
*dest = *src;
|
||
|
n--;
|
||
|
if (n <= 0)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
*dest = '\0';
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
int strcmp(register const char *s1, register const char *s2)
|
||
|
{
|
||
|
while (*s1 == *s2++)
|
||
|
if (*s1++ == 0)
|
||
|
return (0);
|
||
|
|
||
|
return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
|
||
|
}
|
||
|
|
||
|
|
||
|
int strncmp(register const char *s1, register const char *s2, register int len)
|
||
|
{
|
||
|
char c1 = '\0', c2 = '\0';
|
||
|
|
||
|
while (len > 0)
|
||
|
{
|
||
|
c1 = (unsigned char) *s1++;
|
||
|
c2 = (unsigned char) *s2++;
|
||
|
if (c1 == '\0' || c1 != c2)
|
||
|
return c1 - c2;
|
||
|
len--;
|
||
|
}
|
||
|
|
||
|
return c1 - c2;
|
||
|
}
|
||
|
|
||
|
|
||
|
static unsigned long int _random_seed = 93186752;
|
||
|
|
||
|
/**
|
||
|
* The following code is borrowed from Glenn Rhoads.
|
||
|
* http://remus.rutgers.edu/~rhoads/Code/code.html
|
||
|
* License to be defined...
|
||
|
*/
|
||
|
unsigned long int random (void)
|
||
|
{
|
||
|
/* The following parameters are recommended settings based on research
|
||
|
uncomment the one you want. */
|
||
|
|
||
|
/* For RAND_MAX == 4294967291 */
|
||
|
static unsigned int a = 1588635695, q = 2, r = 1117695901;
|
||
|
/* static unsigned int a = 1223106847, m = 4294967291U, q = 3, r = 625646750;*/
|
||
|
/* static unsigned int a = 279470273, m = 4294967291U, q = 15, r = 102913196;*/
|
||
|
|
||
|
/* For RAND_MAX == 2147483647 */
|
||
|
/* static unsigned int a = 1583458089, m = 2147483647, q = 1, r = 564025558; */
|
||
|
/* static unsigned int a = 784588716, m = 2147483647, q = 2, r = 578306215; */
|
||
|
/* static unsigned int a = 16807, m = 2147483647, q = 127773, r = 2836; */
|
||
|
/* static unsigned int a = 950706376, m = 2147483647, q = 2, r = 246070895; */
|
||
|
|
||
|
_random_seed = a*(_random_seed % q) - r*(_random_seed / q);
|
||
|
return _random_seed;
|
||
|
}
|
||
|
|
||
|
|
||
|
void srandom (unsigned long int seed)
|
||
|
{
|
||
|
_random_seed = seed;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* I (d2) borrowed and rewrote this for Nachos/INSA Rennes. Thanks to
|
||
|
them for having kindly allowed me to do so. */
|
||
|
int vsnprintf(char *buff, sos_size_t len, const char * format, va_list ap)
|
||
|
{
|
||
|
sos_size_t i, result;
|
||
|
sos_bool_t fmt_modifiers = FALSE;
|
||
|
sos_bool_t prefix_long = FALSE;
|
||
|
sos_bool_t prefix_long_long = FALSE;
|
||
|
|
||
|
if (!buff || !format || (len <= 0))
|
||
|
return -1;
|
||
|
|
||
|
#define PUTCHAR(thechar) \
|
||
|
do { \
|
||
|
if (result < len-1) \
|
||
|
*buff++ = (thechar); \
|
||
|
result++; \
|
||
|
} while (0)
|
||
|
|
||
|
result = 0;
|
||
|
for(i=0 ; format[i] != '\0' ; i++)
|
||
|
{
|
||
|
if (!fmt_modifiers && (format[i] != '%'))
|
||
|
{
|
||
|
PUTCHAR(format[i]);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
switch (format[i])
|
||
|
{
|
||
|
case '%':
|
||
|
if (fmt_modifiers)
|
||
|
{
|
||
|
PUTCHAR('%');
|
||
|
fmt_modifiers = FALSE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
fmt_modifiers = TRUE;
|
||
|
prefix_long = FALSE;
|
||
|
prefix_long_long = FALSE;
|
||
|
break;
|
||
|
|
||
|
case 'l':
|
||
|
if (prefix_long)
|
||
|
prefix_long_long = TRUE;
|
||
|
else
|
||
|
prefix_long = TRUE;
|
||
|
break;
|
||
|
|
||
|
case 'u':
|
||
|
{
|
||
|
if (! prefix_long_long)
|
||
|
{
|
||
|
unsigned int integer = va_arg(ap,unsigned int);
|
||
|
int cpt2 = 0;
|
||
|
char buff_int[16];
|
||
|
|
||
|
do {
|
||
|
int m10 = integer%10;
|
||
|
buff_int[cpt2++]=(char)('0'+ m10);
|
||
|
integer=integer/10;
|
||
|
} while(integer!=0);
|
||
|
|
||
|
for(cpt2 = cpt2 - 1 ; cpt2 >= 0 ; cpt2--)
|
||
|
PUTCHAR(buff_int[cpt2]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
unsigned long long int integer
|
||
|
= va_arg(ap,unsigned long long int);
|
||
|
int cpt2 = 0;
|
||
|
char buff_int[32];
|
||
|
|
||
|
do {
|
||
|
int m10 = integer%10;
|
||
|
buff_int[cpt2++]=(char)('0'+ m10);
|
||
|
integer=integer/10;
|
||
|
} while(integer!=0);
|
||
|
|
||
|
for(cpt2 = cpt2 - 1 ; cpt2 >= 0 ; cpt2--)
|
||
|
PUTCHAR(buff_int[cpt2]);
|
||
|
}
|
||
|
}
|
||
|
fmt_modifiers = FALSE;
|
||
|
break;
|
||
|
|
||
|
case 'i':
|
||
|
case 'd':
|
||
|
{
|
||
|
if (! prefix_long_long)
|
||
|
{
|
||
|
int integer = va_arg(ap,int);
|
||
|
int cpt2 = 0;
|
||
|
char buff_int[16];
|
||
|
|
||
|
if (integer<0)
|
||
|
PUTCHAR('-');
|
||
|
/* Ne fait pas integer = -integer ici parce que INT_MIN
|
||
|
n'a pas d'equivalent positif (int = [-2^31, 2^31-1]) */
|
||
|
|
||
|
do {
|
||
|
int m10 = integer%10;
|
||
|
m10 = (m10 < 0)? -m10:m10;
|
||
|
buff_int[cpt2++]=(char)('0'+ m10);
|
||
|
integer=integer/10;
|
||
|
} while(integer!=0);
|
||
|
|
||
|
for(cpt2 = cpt2 - 1 ; cpt2 >= 0 ; cpt2--)
|
||
|
PUTCHAR(buff_int[cpt2]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
long long int integer = va_arg(ap,long long int);
|
||
|
int cpt2 = 0;
|
||
|
char buff_int[32];
|
||
|
|
||
|
if (integer<0)
|
||
|
PUTCHAR('-');
|
||
|
/* Ne fait pas integer = -integer ici parce que INT_MIN
|
||
|
n'a pas d'equivalent positif (int = [-2^63, 2^63-1]) */
|
||
|
|
||
|
do {
|
||
|
int m10 = integer%10;
|
||
|
m10 = (m10 < 0)? -m10:m10;
|
||
|
buff_int[cpt2++]=(char)('0'+ m10);
|
||
|
integer=integer/10;
|
||
|
} while(integer!=0);
|
||
|
|
||
|
for(cpt2 = cpt2 - 1 ; cpt2 >= 0 ; cpt2--)
|
||
|
PUTCHAR(buff_int[cpt2]);
|
||
|
}
|
||
|
}
|
||
|
fmt_modifiers = FALSE;
|
||
|
break;
|
||
|
|
||
|
case 'c':
|
||
|
{
|
||
|
int value = va_arg(ap,int);
|
||
|
PUTCHAR((char)value);
|
||
|
fmt_modifiers = FALSE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case 's':
|
||
|
{
|
||
|
char const*string = va_arg(ap,char const*);
|
||
|
if (! string)
|
||
|
string = "(null)";
|
||
|
for( ; *string != '\0' ; string++)
|
||
|
PUTCHAR(*string);
|
||
|
fmt_modifiers = FALSE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case 'p':
|
||
|
PUTCHAR('0');
|
||
|
PUTCHAR('x');
|
||
|
case 'x':
|
||
|
{
|
||
|
unsigned long long int hexa;
|
||
|
unsigned long long int nb;
|
||
|
int x, had_nonzero = 0;
|
||
|
|
||
|
if (prefix_long_long)
|
||
|
hexa = va_arg(ap,unsigned long long int);
|
||
|
else
|
||
|
hexa = va_arg(ap,unsigned int);
|
||
|
|
||
|
for(x=0 ; x < 16 ; x++)
|
||
|
{
|
||
|
nb = (unsigned long long int)(hexa << (x*4));
|
||
|
nb = (nb >> 60) & 0xf;
|
||
|
// Skip the leading zeros
|
||
|
if (nb == 0)
|
||
|
{
|
||
|
if (had_nonzero)
|
||
|
PUTCHAR('0');
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
had_nonzero = 1;
|
||
|
if (nb < 10)
|
||
|
PUTCHAR('0'+nb);
|
||
|
else
|
||
|
PUTCHAR('a'+(nb-10));
|
||
|
}
|
||
|
}
|
||
|
if (! had_nonzero)
|
||
|
PUTCHAR('0');
|
||
|
}
|
||
|
fmt_modifiers = FALSE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
PUTCHAR('%');
|
||
|
if (prefix_long)
|
||
|
PUTCHAR('l');
|
||
|
if (prefix_long_long)
|
||
|
PUTCHAR('l');
|
||
|
PUTCHAR(format[i]);
|
||
|
fmt_modifiers = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*buff = '\0';
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
int snprintf(char * buff, sos_size_t len, const char *format, ...)
|
||
|
{
|
||
|
va_list ap;
|
||
|
|
||
|
va_start(ap, format);
|
||
|
len = vsnprintf(buff, len, format, ap);
|
||
|
va_end(ap);
|
||
|
|
||
|
return len;
|
||
|
}
|