diff options
| author | Xavi Del Campo <xavi.dcr@tutanota.com> | 2020-01-31 10:32:23 +0100 |
|---|---|---|
| committer | Xavi Del Campo <xavi.dcr@tutanota.com> | 2020-01-31 10:32:23 +0100 |
| commit | 7c24e9a9b02b04dcaf9507acb94091ea70a2c02d (patch) | |
| tree | c28d0748652ad4b4222309e46e6cfc82c0906220 /libpsx/src/libc | |
| parent | a2b7b6bb1cc2f4a3258b7b2dbc92399d151f864d (diff) | |
| download | psxsdk-7c24e9a9b02b04dcaf9507acb94091ea70a2c02d.tar.gz | |
Imported pristine psxsdk-20190410 from official repo
Diffstat (limited to 'libpsx/src/libc')
| -rw-r--r-- | libpsx/src/libc/error.c | 19 | ||||
| -rw-r--r-- | libpsx/src/libc/misc.c | 106 | ||||
| -rw-r--r-- | libpsx/src/libc/printf.c | 899 | ||||
| -rw-r--r-- | libpsx/src/libc/qsort.c | 65 | ||||
| -rw-r--r-- | libpsx/src/libc/scanf.c | 425 | ||||
| -rw-r--r-- | libpsx/src/libc/stat.c | 31 | ||||
| -rw-r--r-- | libpsx/src/libc/string.c | 706 | ||||
| -rw-r--r-- | libpsx/src/libc/strings.c | 41 | ||||
| -rw-r--r-- | libpsx/src/libc/unistd.c | 17 |
9 files changed, 2309 insertions, 0 deletions
diff --git a/libpsx/src/libc/error.c b/libpsx/src/libc/error.c new file mode 100644 index 0000000..6863b2f --- /dev/null +++ b/libpsx/src/libc/error.c @@ -0,0 +1,19 @@ +#include <stdio.h> +#include <string.h> + +static char strerror_not_implemented[64]; + +char *strerror(int errnum) +{ + strerror_r(errnum, strerror_not_implemented, 64); + + return strerror_not_implemented; +} + +int strerror_r(int errnum, char *strerrbuf, size_t buflen) +{ + snprintf(strerrbuf, buflen, + "strerror(%d)", errnum); + + return 0; +} diff --git a/libpsx/src/libc/misc.c b/libpsx/src/libc/misc.c new file mode 100644 index 0000000..f3a1326 --- /dev/null +++ b/libpsx/src/libc/misc.c @@ -0,0 +1,106 @@ +#include <stdio.h> +#include <stdlib.h> + +static unsigned int rand_seed = 0; +static unsigned int rand_next = 0; + +int abs(int x) +{ + if(x<0)return -x; + + return x; +} + +void srand(unsigned int seed) +{ + rand_seed = seed; +} + +int rand() +{ + rand_next = (rand_next ^ 0x98765432)*0x1357; + + return rand_next % RAND_MAX; +} + +static char *__ulltoa_internal__(unsigned long long value, char *str, int base, int minus_sign, + unsigned long long maxp ) +{ + unsigned long long p; + unsigned long long p3; + int c; + int a; + + p = 1; + + do + { + p3 = p; + p *= base; + + if(maxp && p > maxp) + break; + }while((p >= p3) && !(p % p3)); + + if(minus_sign) + *(str++) = '-'; + + for(a = 0;p3 > 0;p3/=base) + { + c = value / p3; + value %= p3; + + if(c) + a = 1; + + if(a) + { + if(c <= 9) + c += '0'; + else + c = (c - 10) + 'A'; + + *(str++) = c; + } + } + + *str = '\0'; + + return str; +} + +char *ulltoa(unsigned long long value, char *str, int base) +{ + return __ulltoa_internal__(value, str, base, 0, 0); +} + +char *ultoa(unsigned long value, char *str, int base) +{ + return __ulltoa_internal__(value, str, base, 0, (sizeof(long)==8)?0:0xFFFFFFFF); +} + +char *utoa(unsigned int value, char *str, int base) +{ + return __ulltoa_internal__(value, str, base, 0, 0xFFFFFFFF); +} + +char *lltoa(long long value, char *str, int base) +{ + return __ulltoa_internal__((value<0)?-value:value, str, base, value<0, 0); +} + +char *ltoa(long value, char *str, int base) +{ + return __ulltoa_internal__((value<0)?-value:value, str, base, value<0, (sizeof(long)==8)?0:0xFFFFFFFF); +} + +char *itoa(int value, char *str, int base) +{ + return __ulltoa_internal__((value<0)?-value:value, str, base, value<0, 0xFFFFFFFF); +} + +void abort(void) +{ + printf("abort(): Abnormal program termination\n"); + exit(1); +} diff --git a/libpsx/src/libc/printf.c b/libpsx/src/libc/printf.c new file mode 100644 index 0000000..ce8ffcd --- /dev/null +++ b/libpsx/src/libc/printf.c @@ -0,0 +1,899 @@ +/* + * printf.c + * + * Part of the PSXSDK C library + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define SPRINTF_ALT_FLAG (1<<0) +#define SPRINTF_ZERO_FLAG (1<<1) +#define SPRINTF_NEGFIELD_FLAG (1<<2) +#define SPRINTF_SPACE_FLAG (1<<3) +#define SPRINTF_SIGN_FLAG (1<<4) + +// sprintf() macros to calculate the real padding and to write it +// these were made to not repeat the code in the function +// they can only be used in sprintf() + +// sprintf macros START + +#define calculate_real_padding() \ + y = 1; \ + \ + for(x=0;x<=19;x++) \ + { \ + if(x == 0) \ + pad_quantity--; \ + else \ + { \ + if(arg / y) \ + pad_quantity--; \ + } \ + \ + y *= 10; \ + } \ + \ + if(pad_quantity < 0) pad_quantity = 0; + +/*#define calculate_real_padding_hex() \ + for (x = 0; x < 8; x++) \ + { \ + if(x == 0) \ + pad_quantity--; \ + else \ + { \ + if((arg >> (x * 4)) & 0xf) \ + pad_quantity--; \ + } \ + }*/ + +#define calculate_real_padding_hex() \ + last = 0; \ + for (x = 0; x < 16; x++) \ + if((arg >> (x * 4)) & 0xf) \ + last = x; \ + \ + pad_quantity = (pad_quantity - 1) - last; \ + if(pad_quantity < 0) pad_quantity = 0; + +#define write_padding() \ + if(!(flags & SPRINTF_NEGFIELD_FLAG)) \ + for(x = 0; x < pad_quantity; x++) \ + { \ + if(flags & SPRINTF_ZERO_FLAG) \ + put_in_string(string, ssz, '0', string_pos++); \ + else \ + put_in_string(string, ssz, ' ', string_pos++); \ + } + +#define write_neg_padding() \ + if(flags & SPRINTF_NEGFIELD_FLAG) \ + { \ + for(x = 0; x < pad_quantity; x++) \ + put_in_string(string, ssz, ' ', string_pos++);\ + } + +// sprintf macros END + +enum +{ + SPRINTF_SIZE_CHAR, + SPRINTF_SIZE_SHORT, + SPRINTF_SIZE_INT, + SPRINTF_SIZE_LONG, + SPRINTF_SIZE_LONG_LONG, +}; + +static unsigned int get_arg_in_size(int size, unsigned long long *arg, unsigned int check_sign) +{ + int s = 0; + + switch(size) + { + case SPRINTF_SIZE_CHAR: + *arg &= 0xff; + + if(check_sign) + { + if(*arg & (1<<7)) + { + *arg |= 0xffffff00; + *arg = ~(*arg - 1); + s = 1; + } + } + break; + case SPRINTF_SIZE_SHORT: + *arg &= 0xffff; + + if(check_sign) + { + if(*arg & (1<<15)) + { + *arg |= 0xffff0000; + *arg = ~(*arg - 1); + s = 1; + } + } + break; + +// sizeof(long) == sizeof(int) on 32bit, so this will suffice for the psx + + case SPRINTF_SIZE_INT: + case SPRINTF_SIZE_LONG: + *arg &= 0xffffffff; + + if(check_sign) + { + if(*arg & (1<<31)) + { + *arg |= (long long)0xffffffff00000000; + *arg = ~(*arg - 1); + s = 1; + } + } + break; + + case SPRINTF_SIZE_LONG_LONG: + if(check_sign) + { + if(*arg & ((long long)1<<63)) + { + *arg = ~(*arg - 1); + s = 1; + } + } + break; + } + + return s; +} + +static int libc_ulltoa(unsigned long long i, char *dst, int n, int nopad) +{ + int x, y; + unsigned long long a, b; + int empty_digit = 1; + int sp=0; + int n2=0; + + if(n<=0) + return 0; + + for(x=18;x>=0;x--) + { + a = 1; + for(y = 0; y<x; y++) + a *= 10; + + b = (i/a); + + if(b>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0 || nopad == 1) + { + i -= b*a; + + //put_in_string(string, ssz, b + '0', string_pos++); + if(n2!=(n-1)) + { + //printf("n2=%d\n",n2); + dst[sp++] = b + '0'; + n2++; + } + } + } + + dst[sp] = 0; + + return n2; +} + +/*static void libc_float_to_string(float fl, char *dst, int n) +{ + unsigned int *p = (unsigned int*)&fl; + unsigned long long i = 0; + unsigned long long f = 0; + int e, m, s; + int x, y; + unsigned long long z; + + s = *p >> 31; + + e = (*p >> 23) & 0xff; + + m = *p & 0x7fffff; + + if(e == 255 && m == 0) // Infinity + { + if(s) strncpy(dst, "-inf", n); + else strncpy(dst, "inf", n); + }else if(e == 255 && m != 0) // NaN + { + strncpy(dst, "nan", n); + } + else + { + e -= 127; + m |= 1<<23; + + + + for(x = 23; x >= 0; x--) + { + if(m & (1<<x)) + { + if(e >= 0) + { + z = 1; + for(y=0;y<e;y++) + z*=2; + + i+=z; + } + else + { + z = 5000000000000000000; + for(y = 1; y < -e; y++) + z /= 2; + + f+=z; + } + } + e--; + } + + if(s && (n>0)) + { + *(dst++) = '-'; + n--; + } + + x = libc_ulltoa(i, dst, n, 0); + n-=x+1; + dst+=x; + + if(n>0) + { + *(dst++) = '.'; + n--; + if(n>0) + { + x = libc_ulltoa(f, dst, n<6?n:6, 1); + n-=x; + dst+=x; + + if(n>0) + *dst=0; + } + } + } +}*/ + +static void libc_double_to_string(double fl, char *dst, int n, int prec) +{ + unsigned long long *p = (unsigned long long *)&fl; + unsigned long long i = 0; + unsigned long long f = 0; + unsigned long long m, s; + long long e; + int x; + unsigned long long z; + + s = *p >> 63; + + e = (*p >> 52) & 0x7ff; + //printf("%d\n", e); + + m = *p & 0xfffffffffffff; + + for(x=0;x<52;x++) + if(m&((unsigned long long)1<<(52-x))) putchar('1'); else putchar('0'); + + if(e == 255 && m == 0) // Infinity + { + if(s) strncpy(dst, "-inf", n); + else strncpy(dst, "inf", n); + }else if(e == 255 && m != 0) // NaN + { + strncpy(dst, "nan", n); + } + else + { + e -= 1023; + m |= (unsigned long long)1<<52; + + for(x = 52; x >= 0; x--) + { + if(m & ((unsigned long long)1<<x)) + { + if(e >= 0) + { + z = (long long)1<<e; + + i+=z; + } + else + { + z = 5000000000000000000; + z >>= -(e + 1); + + f+=z; + } + } + e--; + } + + if(s && (n>0)) + { + *(dst++) = '-'; + n--; + } + + x = libc_ulltoa(i, dst, n, 0); + n-=x+1; + dst+=x; + + dprintf("N = %d\n", n); + + if(n>0) + { + *(dst++) = '.'; + + if(n>0) + libc_ulltoa(f, dst, (n<(prec+1))?n:(prec+1), 1); + } + } +} + +static char libc_sprintf_floatbuf[64]; + +static int __vsnprintf_internal(char *string, size_t size, const char *fmt, va_list ap, int (put_in_string(char *string, unsigned int sz, char c, int pos))) +{ + int string_pos,fmt_pos; + int l; + unsigned long long arg; + char *argcp; + char *argcp_tmp; + int directive_coming = 0; + int flags = 0; + int argsize = 2; // int + int x, y; + unsigned long long a, b; + int empty_digit; + int ssz = size - 1; + int zero_flag_imp = 0; + int pad_quantity = 0; + int pad_quantity_f = -1; + int last; + + if(size == 0) + ssz = 0; + + l = strlen(fmt); + + string_pos = 0; + + for(fmt_pos=0;fmt_pos<l;fmt_pos++) + { + if(directive_coming) + { + switch(fmt[fmt_pos]) + { + case '%': + put_in_string(string, ssz, '%', string_pos++); + directive_coming = 0; + break; + case ' ': + flags |= SPRINTF_SPACE_FLAG; + break; + case '#': // Specify alternate form + flags |= SPRINTF_ALT_FLAG; + break; + case '+': // Specify sign in signed conversions + flags |= SPRINTF_SIGN_FLAG; + break; + case '0': // Padding with zeros... + if(zero_flag_imp == 0) + { + flags |= SPRINTF_ZERO_FLAG; + zero_flag_imp = 1; + //printf("Zero padding enabled!\n"); + } + else + { + pad_quantity *= 10; + //printf("pad_quantity = %d\n", pad_quantity); + } + break; + case '1' ... '9': // '...' cases are a GNU extension, + // but they simplify a lot + + pad_quantity *= 10; + pad_quantity += fmt[fmt_pos] - '0'; + zero_flag_imp = 1; + + //printf("pad_quantity = %d\n", pad_quantity); + break; + case '-': // Negative field flag + if(flags & SPRINTF_ZERO_FLAG) + flags &= ~SPRINTF_ZERO_FLAG; + + flags |= SPRINTF_NEGFIELD_FLAG; + break; + case '.': // Floating point precision + pad_quantity_f = pad_quantity; + pad_quantity = 0; + break; + case 'h': // Half argument size + if(argsize) argsize--; + break; + case 'l': // Double argument size + if(argsize < 2) argsize = 2; + else if(argsize < SPRINTF_SIZE_LONG_LONG) argsize++; + break; + +// 'j', 't', 'z', 'q' added 2013-10-26 by nextvolume + + case 'j': // Maximum integer size + argsize = SPRINTF_SIZE_LONG_LONG; + break; + + case 't': // Size of ptrdiff_t (i.e. long on 32-bit, long long on 64-bit) + argsize = (sizeof(void*)==8)? + SPRINTF_SIZE_LONG_LONG:SPRINTF_SIZE_LONG; + break; + + case 'z': // Size of size_t (int) + argsize = SPRINTF_SIZE_INT; + break; + + case 'q': // Size of quad_t + argsize = SPRINTF_SIZE_LONG_LONG; + break; + + case 'd': // signed decimal + case 'i': + empty_digit = 1; + + //printf("argsize = %d\n", argsize); + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long); + + if(flags & SPRINTF_SPACE_FLAG) + put_in_string(string, ssz, ' ', string_pos++); + + if(get_arg_in_size(argsize, &arg, 1)) + { + put_in_string(string, ssz, '-', string_pos++); + pad_quantity--; + } + else + { + if(flags & SPRINTF_SIGN_FLAG) + { + put_in_string(string, ssz, '+', string_pos++); + pad_quantity--; + } + } + + /* Calculate how much padding we have to write */ + + /*y = 1; + + for(x=0;x<=9;x++) + { + if(x == 0) + pad_quantity--; + else + { + if(arg / y) + pad_quantity--; + } + + y *= 10; + } + if(pad_quantity < 0) pad_quantity = 0;*/ + + calculate_real_padding(); + + //printf("Actual pad quantity = %d\n", pad_quantity); + + + + /*if(!(flags & SPRINTF_NEGFIELD_FLAG)) + { + for(x = 0; x < pad_quantity; x++) + { + if(flags & SPRINTF_ZERO_FLAG) + put_in_string(string, ssz, '0', string_pos++); + else + put_in_string(string, ssz, ' ', string_pos++); + } + }*/ + + write_padding(); + + for(x=19;x>=0;x--) + { + a = 1; + for(y = 0; y<x; y++) + a *= 10; + + b = (arg/a); + + if(b>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + arg -= b*a; + + put_in_string(string, ssz, b + '0', string_pos++); + } + } + + /*if(flags & SPRINTF_NEGFIELD_FLAG) + { + for(x = 0; x < pad_quantity; x++) + put_in_string(string, ssz, ' ', string_pos++); + }*/ + write_neg_padding(); + + directive_coming = 0; + break; + case 'u': // unsigned decimal + empty_digit = 1; + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long); + + get_arg_in_size(argsize, &arg, 0); + + calculate_real_padding(); + write_padding(); + + for(x=19;x>=0;x--) + { + a = 1; + for(y = 0; y<x; y++) + a *= 10; + + + + b = (arg/a); + + if(b>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + arg -= b*a; + + put_in_string(string, ssz, b + '0', string_pos++); + } + } + + write_neg_padding(); + + directive_coming = 0; + break; + case 'x': // Hexadecimal + case 'X': // Hexadecimal with big letters + case 'p': // Hexadecimal with small letters with '0x' prefix + empty_digit = 1; + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long int); + + get_arg_in_size(argsize, &arg, 0); + + if(fmt_pos == 'p') + flags |= SPRINTF_ALT_FLAG; + + if(flags & SPRINTF_ALT_FLAG) + { + put_in_string(string, ssz, '0', string_pos++); + + if(fmt[fmt_pos] == 'X') + put_in_string(string, ssz, 'X', string_pos++); + else + put_in_string(string, ssz, 'x', string_pos++); + } + + calculate_real_padding_hex(); + write_padding(); + + for(x=15;x>=0;x--) + { + y = arg >> (x << 2); + y &= 0xf; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + if(y>=0 && y<=9) + put_in_string(string, ssz, y + '0', string_pos++); + else if(y>=0xA && y<=0xF) + { + if(fmt[fmt_pos] == 'X') + put_in_string(string, ssz, (y - 0xa) + 'A', string_pos++); + else + put_in_string(string, ssz, (y - 0xa) + 'a', string_pos++); + } + } + } + + write_neg_padding(); + + directive_coming = 0; + break; + case 'c': // character + arg = va_arg(ap, int); + + put_in_string(string, ssz, arg & 0xff, string_pos++); + + directive_coming = 0; + break; + case 's': // string + argcp = va_arg(ap, char *); + argcp_tmp = argcp; + + if(argcp == NULL) + { + // Non standard extension, but supported by Linux and the BSDs. + + put_in_string(string, ssz, '(', string_pos++); + put_in_string(string, ssz, 'n', string_pos++); + put_in_string(string, ssz, 'u', string_pos++); + put_in_string(string, ssz, 'l', string_pos++); + put_in_string(string, ssz, 'l', string_pos++); + put_in_string(string, ssz, ')', string_pos++); + + directive_coming = 0; + break; + } + + while(*argcp_tmp) + { + if(pad_quantity > 0) pad_quantity--; + argcp_tmp++; + } + + if(!(flags & SPRINTF_NEGFIELD_FLAG)) + { + while(pad_quantity > 0) + { + put_in_string(string,ssz, ' ', string_pos++); + pad_quantity--; + } + } + + while(*argcp) + { + put_in_string(string, ssz, *argcp, string_pos++); + + argcp++; + } + + if(flags & SPRINTF_NEGFIELD_FLAG) + { + while(pad_quantity > 0) + { + put_in_string(string,ssz, ' ', string_pos++); + pad_quantity--; + } + } + + directive_coming = 0; + break; + case 'o': // Octal + empty_digit = 1; + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long); + + for(x=21;x>=0;x--) + { + y = arg >> (x * 3); + y &= 0x7; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + put_in_string(string, ssz, y + '0', string_pos++); + } + + directive_coming = 0; + break; + case '@': // Binary + empty_digit = 1; + + if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long long)va_arg(ap, unsigned int); + else + arg = va_arg(ap, unsigned long long); + + for(x=63;x>=0;x--) + { + y = (arg >> x); + y &= 1; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + put_in_string(string, ssz, y + '0', string_pos++); + } + + directive_coming = 0; + break; + + case 'f': + if(pad_quantity_f == -1) + pad_quantity_f = 6; + else + { + x = pad_quantity_f; + pad_quantity_f = pad_quantity; + pad_quantity = x; + } + + dprintf("PRECISION = %d\n", pad_quantity_f); + + libc_double_to_string(va_arg(ap, double), libc_sprintf_floatbuf, 64, pad_quantity_f); + + // calculate padding + pad_quantity -= strlen(libc_sprintf_floatbuf); + + write_padding(); + + for(x=0;libc_sprintf_floatbuf[x]!=0;x++) + put_in_string(string, ssz, libc_sprintf_floatbuf[x], string_pos++); + + write_neg_padding(); + + directive_coming = 0; + break; + case 'n': // Number of characters written + *(va_arg(ap,unsigned int*)) = string_pos; + + directive_coming = 0; + break; + + default: + put_in_string(string, ssz, fmt[fmt_pos], string_pos++); + directive_coming = 0; + } + } + else + { + if(fmt[fmt_pos] == '%') + { + directive_coming = 1; + flags = 0; + argsize = 2; + pad_quantity = 0; + pad_quantity_f = -1; + zero_flag_imp = 0; + } + else + { + put_in_string(string, ssz, fmt[fmt_pos], string_pos++); + } + } + } + + /*if(((size-1) < string_pos) && (size>0)) + string[size - 1] = 0; + else + string[string_pos] = 0;*/ + put_in_string(string, ssz, '\0', string_pos); + + return string_pos; +} + +static int vsnprintf_put_in_string(char *string, unsigned int sz, char c, int pos) +{ + if(pos>=sz) + return 0; + else + string[pos] = c; + + return 1; +} + +int vsnprintf(char *string, size_t size, const char *fmt, va_list ap) +{ + return __vsnprintf_internal(string, size, fmt, ap, vsnprintf_put_in_string); +} + +static int sio_put_in_string(char *string, unsigned int sz, char c, int pos) +{ + sio_putchar(c); + + return 1; +} + +int sio_vprintf(const char *fmt, va_list ap) +{ + return __vsnprintf_internal(NULL, -1, fmt, ap, sio_put_in_string); +} + +static int out_put_in_string(char *string, unsigned int sz, char c, int pos) +{ + putchar(c); + + return 1; +} + +int vprintf(char *fmt, va_list ap) +{ + return __vsnprintf_internal(NULL, -1, fmt, ap, out_put_in_string); +} + +int vsprintf(char *string, const char *fmt, va_list ap) +{ + return vsnprintf(string, 0xffffffff, fmt, ap); +} + +int sprintf(char *string, const char *fmt, ...) +{ + int r; + + va_list ap; + + va_start(ap, fmt); + + r = vsprintf(string, fmt, ap); + + va_end(ap); + + return r; +} + +int snprintf(char *string, size_t size, const char *fmt, ...) +{ + int r; + + va_list ap; + + va_start(ap, fmt); + + r = vsnprintf(string, size, fmt, ap); + + va_end(ap); + + return r; +} + +int sio_printf(const char *fmt, ...) +{ + int r; + + va_list ap; + + va_start(ap, fmt); + + r = sio_vprintf(fmt, ap); + + va_end(ap); + + return r; +} diff --git a/libpsx/src/libc/qsort.c b/libpsx/src/libc/qsort.c new file mode 100644 index 0000000..0cb1d24 --- /dev/null +++ b/libpsx/src/libc/qsort.c @@ -0,0 +1,65 @@ +// quickSort +// +// This public-domain C implementation by Darel Rex Finley. +// +// Modified by Giuseppe Gatta + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) +{ + #define QSORT_MAX_LEVELS 300 + + + int beg[QSORT_MAX_LEVELS], end[QSORT_MAX_LEVELS], i=0, L, R, swap ; + char piv[size]; + + beg[0]=0; end[0]=nmemb; + + while (i>=0) + { + L=beg[i]; R=end[i]-1; + + if (L<R) + { + memcpy(piv, base + (size * L), size); + + while (L<R) + { + while(compar(base + (R*size), piv) > 0 && L<R) R--; + + if (L<R) + { + memcpy(base + (size *L), base + (size * R), size); + L++; + } + + while(compar(base + (L*size), piv) <= 0 && L<R) L++; + + if (L<R) + { + memcpy(base + (size *R), base + (size * L), size); + R--; + } + } + + memcpy(base + (size*L), piv, size); + + beg[i+1]=L+1; + end[i+1]=end[i]; + end[i++]=L; + + if (end[i]-beg[i]>end[i-1]-beg[i-1]) + { + swap=beg[i]; beg[i]=beg[i-1]; beg[i-1]=swap; + swap=end[i]; end[i]=end[i-1]; end[i-1]=swap; + } + } + else + { + i--; + } + } +} diff --git a/libpsx/src/libc/scanf.c b/libpsx/src/libc/scanf.c new file mode 100644 index 0000000..d419030 --- /dev/null +++ b/libpsx/src/libc/scanf.c @@ -0,0 +1,425 @@ +// vsscanf +// Programmed by Giuseppe Gatta, 2011 + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +char libc_vsscanf_buf[512]; +char libc_vsscanf_allow[256]; + +enum +{ + elem_skip_space = 1, +}; + +int libc_vsscanf_get_element(char *dst, const char *src, int flag, int s) +{ + int i; + const char *osrc = src; + + if(flag & elem_skip_space) + { + while(*src == ' ') + src++; + } + + for(i=0;i<s;i++) + { + if((flag & elem_skip_space) && *src == ' ') + break; + + if(*src != 0) + *(dst++) = *(src++); + else + break; + } + + *dst = 0; + + return src - osrc; +} + +enum +{ + scanf_s_char, scanf_s_short, scanf_s_int, + scanf_s_long, + scanf_s_long_long +}; + +int vsscanf(const char *str, const char *format, va_list ap) +{ + int fp = 0; + int sp = 0; + int conv = 0; + int sz = scanf_s_int; // size for numbers defaults to 32-bit + int i,x,y,z;// h; + int suppress = 0; +// int neg = 0; + int fsz = 512; + int def_fsz = 1; + int exspace = 0; +// int alt = 0; + int r = 0; + int exit_loop=0; + char *ep; + long long buf; + double fbuf; + + + while(format[fp] && str[sp] && !exit_loop) + { + if(conv) + { + switch(format[fp]) + { + case '%': // Percent, assignment does not occur + conv = 0; + break; + + case 'h': // Halve size + sz--; + break; + + case 'l': // Double size + sz++; + break; + + case '*': // Suppress + suppress = 1; + break; + + case ' ': // Explicit space + exspace = 1; + break; + + case '#': // Alternate format + //alt = 1; + break; + + case '0' ... '9': // '0' ... '9' is a GNU C extension! + if(def_fsz) + { + def_fsz = 0; + fsz = 0; + } + + fsz *= 10; + fsz+=format[fp]-'0'; + + if(fsz > 512) + fsz = 512; // 512 is the maximum. + break; + + case '@': // Binary. Non-standard extension + libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + buf = strtoll(libc_vsscanf_buf, &ep, 2); + sp += ep - libc_vsscanf_buf; + + if(!suppress) + { + switch(sz) + { + case scanf_s_char: *(va_arg(ap, signed char*)) = (signed char)buf;break; + case scanf_s_short: *(va_arg(ap, short*)) = (short)buf; break; + case scanf_s_int: *(va_arg(ap, int*)) = (int)buf; break; + case scanf_s_long: *(va_arg(ap, long*)) = (long)buf; break; + case scanf_s_long_long: *(va_arg(ap, long long*)) = buf; break; + } + r++; + } + + conv = 0; + break; + + case 'D': + sz++; + case 'd': // Decimal + case 'u': + libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + buf = strtoll(libc_vsscanf_buf, &ep, 10); + sp += ep - libc_vsscanf_buf; + + if(!suppress) + { + switch(sz) + { + case scanf_s_char: *(va_arg(ap, signed char*)) = (signed char)buf;break; + case scanf_s_short: *(va_arg(ap, short*)) = (short)buf; break; + case scanf_s_int: *(va_arg(ap, int*)) = (int)buf; break; + case scanf_s_long: *(va_arg(ap, long*)) = (long)buf; break; + case scanf_s_long_long: *(va_arg(ap, long long*)) = buf; break; + } + r++; + } + + conv = 0; + break; + + case 's': // String + sp += libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + + if(!suppress) + { + strcpy(va_arg(ap, char*), libc_vsscanf_buf); + r++; + } + + conv = 0; + break; + + case 'c': + if(def_fsz) + fsz = 1; + + sp += (i = libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], (exspace ? elem_skip_space : 0), fsz)); + if(!suppress) + { + memcpy(va_arg(ap, char*), libc_vsscanf_buf, (fsz>i)?i:fsz); + r++; + } + break; + + case 'n': + if(!suppress) + { + *(va_arg(ap, int*)) = sp; + r++; + } + break; + + case 'p': + case 'x': + case 'X': + libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + buf = strtoll(libc_vsscanf_buf, &ep, 16); + sp += ep - libc_vsscanf_buf; + + if(!suppress) + { + switch(sz) + { + case scanf_s_char: *(va_arg(ap, unsigned char*)) = (unsigned char)buf; break; + case scanf_s_short: *(va_arg(ap, unsigned short*)) = (unsigned short)buf; break; + case scanf_s_int: *(va_arg(ap, unsigned int*)) = (unsigned int)buf; break; + case scanf_s_long: *(va_arg(ap, unsigned long*)) = (unsigned long)buf; break; + case scanf_s_long_long: *(va_arg(ap, unsigned long long*)) = (unsigned long long)buf; break; + } + r++; + } + + conv = 0; + break; + + case 'O': + sz++; + case 'o': // Octal integer + libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + buf = strtoll(libc_vsscanf_buf, &ep, 8); + sp += ep - libc_vsscanf_buf; + + if(!suppress) + { + switch(sz) + { + case scanf_s_char: *(va_arg(ap, unsigned char*)) = (unsigned char)buf;break; + case scanf_s_short: *(va_arg(ap, unsigned short*)) = (unsigned short)buf; break; + case scanf_s_int: *(va_arg(ap, unsigned int*)) = (unsigned int)buf;break; + case scanf_s_long: *(va_arg(ap, unsigned long*)) = (unsigned long)buf; break; + case scanf_s_long_long: *(va_arg(ap, unsigned long long*)) = (unsigned long long)buf;break; + } + r++; + } + + conv = 0; + break; + + case 'i': + libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + + if(libc_vsscanf_buf[0] == '0') + { + if(libc_vsscanf_buf[1] == 'x' || libc_vsscanf_buf[1] == 'X') + i = 16; + else + i = 8; + } + else + i = 10; + + buf = strtoll(libc_vsscanf_buf, &ep, i); + sp += ep - libc_vsscanf_buf; + + if(!suppress) + { + switch(sz) + { + case scanf_s_char: *(va_arg(ap, signed char*)) = (signed char)buf; break; + case scanf_s_short: *(va_arg(ap, short*)) = (short)buf; break; + case scanf_s_int: *(va_arg(ap, int*)) = (int)buf; break; + case scanf_s_long: *(va_arg(ap, long*)) = (long)buf; break; + case scanf_s_long_long: *(va_arg(ap, long long*)) = (long long)buf; break; + } + r++; + } + + conv = 0; + break; + + case '[': + i=0; + x=0; // Exclusion? + //h=0; // Hyphen? + + fp++; + i++; + + while(format[fp]) + { + if(format[fp] == '^' && i==1) + { + memset(libc_vsscanf_allow, 1, 256); + x = 1; + fp++; i++; continue; + } + + if(x) + { + if(format[fp] == ']' && i>=3) + break; + } + else + { + if(format[fp] == ']' && i>=2) + break; + } + + if(format[fp] == '-') + { + if(format[fp+1] != ']') + y = 1; + else + libc_vsscanf_allow['-'] = x^1; + } + else + { + if(y == 1) + { + if(format[fp] < format[fp-2]) + libc_vsscanf_allow[(unsigned char)format[fp]] = x^1; + else + for(z = format[fp-2]; z <= format[fp]; z++) + libc_vsscanf_allow[z] = x^1; + + y = 0; + + //printf("%s all chars from %c to %c\n", x?"Excluding":"Including",format[fp-2], format[fp]); + } + else + libc_vsscanf_allow[(unsigned char)format[fp]] = x^1; + } + + fp++; + i++; + } + +// Now as we know what our character set is, let's get data from the string + /* puts("Character set:"); + + for(y=0;y<16;y++) + { + for(x=0;x<16;x++) + if(libc_vsscanf_allow[(y*16) + x]) + putchar((y*16)+x); + else + putchar('*'); + + putchar('\n'); + } + */ + i = 0; + + while(libc_vsscanf_allow[(unsigned char)str[sp]] && i<512) + libc_vsscanf_buf[i++] = str[sp++]; + + libc_vsscanf_buf[i] = 0; + + if(!suppress) + { + strcpy(va_arg(ap, char*), libc_vsscanf_buf); + r++; + } + break; + + case 'f': // Floating point number + libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz); + fbuf = strtod(libc_vsscanf_buf, &ep); + sp += ep - libc_vsscanf_buf; + + if(!suppress) + { + switch(sz) + { + case scanf_s_char: + case scanf_s_short: + case scanf_s_int: + *(va_arg(ap, float*)) = (float)fbuf; + break; + + case scanf_s_long: + case scanf_s_long_long: + *(va_arg(ap, double*)) = fbuf; + break; + } + r++; + } + + conv = 0; + break; + + } + } + else + { + if(format[fp] == '%') + { + // conv = 1; + // neg = 0; + suppress = 0; + sz = scanf_s_int; + fsz = 512; + def_fsz = 1; + exspace = 0; + // alt = 0; + bzero(libc_vsscanf_allow, 256); + //chset = 0; + } + else if(format[fp] != ' ') + { + if(format[fp] != str[sp]) + exit_loop=1; + + sp++; + } + + } + + fp++; + } + + return r; +} + +int sscanf(const char *str, const char *fmt, ...) +{ + int r; + va_list ap; + + va_start(ap, fmt); + r = vsscanf(str, fmt, ap); + + va_end(ap); + return r; +} diff --git a/libpsx/src/libc/stat.c b/libpsx/src/libc/stat.c new file mode 100644 index 0000000..1c43b92 --- /dev/null +++ b/libpsx/src/libc/stat.c @@ -0,0 +1,31 @@ +#include <psx.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> + +int stat(const char *path, struct stat *sb) +{ + struct DIRENTRY dir_e; + + if(firstfile((char*)path, &dir_e) == NULL) + return -1; + + sb->st_size = dir_e.size; + + if(strncmp(path, "cdrom:", 6) == 0) + sb->st_blksize = 2048; + else if(strncmp(path, "bu00:", 5) == 0 || + strncmp(path, "bu10:", 5) == 0) + sb->st_blksize = 128; + else +// not a real blocksize, will be there just as a placeholder + sb->st_blksize = 1024; + + sb->st_blocks = + sb->st_size / sb->st_blksize; + + if(sb->st_size % sb->st_blksize) + sb->st_blocks++; + + return 0; +} diff --git a/libpsx/src/libc/string.c b/libpsx/src/libc/string.c new file mode 100644 index 0000000..ea59b91 --- /dev/null +++ b/libpsx/src/libc/string.c @@ -0,0 +1,706 @@ +/* + * string.c + * + * Part of the PSXSDK C library + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <ctype.h> + +void *memcpy(void *dst, const void *src, size_t len) +{ + void *dst2 = dst; + + while(len--) + *(((unsigned char*)dst++)) = *(((unsigned char*)src++)); + + return dst2; +} + +void *memccpy(void *dst, const void *src, int c, size_t len) +{ + unsigned char c2; + + while(len--) + { + *(((unsigned char*)dst++)) = ( c2 = *(((unsigned char*)src++)) ); + + if(c2 == c) + return (void*)src; + } + + return NULL; +} + +void *memset(void *dst , char c , size_t n) +{ + unsigned char *dstc = (unsigned char*)dst; + int x; + + for(x = 0; x < n; x++) + dstc[x] = c; + + return dst; +} + +int memcmp(const void *b1, const void *b2, size_t n) +{ + int x; + unsigned char *bp1 = (unsigned char*)b1; + unsigned char *bp2 = (unsigned char*)b2; + + for(x = 0; x < n; x++) + if(bp1[x] != bp2[x]) + return (bp1[x] - bp2[x]); + + return 0; +} + +void *memmove(void *dst, const void *src, size_t len) +{ + void *dst2 = dst; + + dst+=len-1; + src+=len-1; + + while(len--) + *(((unsigned char*)dst--)) = *(((unsigned char*)src--)); + + return dst2; +} + +void *memchr(void *s , int c , size_t n) +{ + while(n--) + { + if(*((unsigned char*)s) == (unsigned char)c) + return s; + + s++; + } + + return NULL; +} + +char *strncpy(char *dst, const char *src, size_t len) +{ + char *odst=dst; + + while(*src && len) + { + *(dst++) = *(src++); + len--; + } + + if(len)*dst = 0; + + return odst; +} + +char *strcpy(char *dst, const char *src) +{ + char *odst = dst; + + while((*(dst++) = *(src++))); + return odst; +} + +int strlen(const char *str) +{ + int i = 0; + while(*(str++))i++; + return i; +} + +char *strchr(const char *s, int c) +{ + int x; + int l = strlen(s); + + for(x = 0; x <= l; x++) + if(s[x] == c) return (char*)&s[x]; + + return NULL; +} + +char *strrchr(const char *s, int c) +{ + int x; + int l = strlen(s); + + for(x = l; x>=0; x--) + if(s[x] == c) return (char*)&s[x]; + + return NULL; +} + +char *strpbrk(const char *s, const char *charset) +{ + int x,y; + + for(x = 0; s[x] != 0; x++) + for(y = 0; charset[y] != 0; y++) + if(s[x] == charset[y]) return (char*)&s[x]; + + return NULL; +} + +char *strstr(const char *big, const char *little) +{ + int ls = strlen(little); + int bs = strlen(big); + int x; + + if(ls == 0) + return (char*)big; + + if(ls > bs) + return NULL; + + for(x = 0; x <= bs-ls; x++) + if(memcmp(little, &big[x], ls) == 0) + return (char*)&big[x]; + + return NULL; +} + +int strcmp(const char *s1, const char *s2) +{ + while(*s1 && *s2 && (*s1 == *s2)) + { + s1++; + s2++; + } + + return *s1-*s2; +} + +int strncmp(const char *s1, const char *s2, size_t len) +{ + int p = 0; + + while(*s1 && *s2 && (*s1 == *s2) && p<len) + { + p++; + + if(p<len) + { + s1++; + s2++; + } + } + + return *s1-*s2; +} + +int strcoll(const char *s1, const char *s2) +{ + return strcmp(s1, s2); +} + +char *strdup(const char *str) +{ + char *ns = (void*)malloc(strlen(str) + 1); + + if(ns == NULL) + return NULL; + + strcpy(ns, str); + return ns; +} + +char *strndup(const char *str, size_t len) +{ + int n=strlen(str); + char *ns = (void*)malloc((n+1)>len?len:(n+1)); + + if(ns == NULL) + return NULL; + + strncpy(ns, str, (n+1)>len?len:(n+1)); + return ns; +} + +long long strtoll(const char *nptr, char **endptr, int base) +{ + int r = 0; + int t = 0; + int n = 0; + + while(*nptr && isspace(*nptr)) + nptr++; + + if(*nptr == '-') + { + nptr++; + n = 1; + } + + if(base == 0) + { + if(*nptr == '0') + base = 8; + else + base = 10; + } + + if(!(base >= 2 && base <= 36)) + return 0; + + if(base == 16 && *nptr == '0') + { + if(*(nptr+1) == 'x' || *(nptr+1) == 'X') + nptr+=2; + } + + while(*nptr) + { + switch(*nptr) + { + case '0'...'9': + t = *nptr - '0'; + break; + case 'a' ... 'z': + t = (*nptr - 'a') + 10; + break; + case 'A' ... 'Z': + t = (*nptr - 'A') + 10; + break; + default: + t = 1000; + break; + } + + if(t>=base) + break; + + r*=base; + r+=t; + nptr++; + } + + if(endptr)*endptr = (char*)nptr; + return n?-r:r; +} + +long strtol(const char *nptr, char **endptr, int base) +{ + return (long)strtoll(nptr, endptr, base); +} + +double strtod(const char *nptr, char **endptr) +{ + char strbuf[64]; + int x = 0; + int y; + double i=0, d=0; + int s=1; + + if(*nptr == '-') + { + nptr++; + s=-1; + } + + while(*nptr >= '0' && *nptr <= '9' && x < 18) + strbuf[x++] = *(nptr++); + + strbuf[x] = 0; + + i = (double)strtoll(strbuf, NULL, 10); + + if(*nptr == '.') + { + nptr++; + x = 0; + + while(*nptr >= '0' && *nptr <= '9' && x < 7) + strbuf[x++] = *(nptr++); + + strbuf[x] = 0; + + if(endptr != NULL) *endptr = (char*)nptr; + + y=1; + + for(x=0;strbuf[x]!=0;x++) + y*=10; + + d = (double)strtoll(strbuf, NULL, 10); + d /= y; + } + else + { + if(endptr != NULL) + *endptr = (char*)nptr; + } + + return (i + d)*s; +} + +long double strtold(const char *nptr, char **endptr) +{ + return (long double)strtod(nptr, endptr); +} + +float strtof(const char *nptr, char **endptr) +{ + return (float)strtod(nptr, endptr); +} + +char *strcat(char *s, const char *append) +{ + strcpy(&s[strlen(s)], append); + + return s; +} + +char *strncat(char *s, const char *append, size_t count) +{ + strncpy(&s[strlen(s)], append, count); + + return s; +} + +int strcasecmp(const char *s1, const char *s2) +{ + while(tolower(*s1) && tolower(*s2) && (tolower(*s1) == tolower(*s2))) + { + s1++; + s2++; + } + + return tolower(*s1)-tolower(*s2); +} + +int strncasecmp(const char *s1, const char *s2, size_t len) +{ + int p = 0; + + while(tolower(*s1) && tolower(*s2) && (tolower(*s1) == tolower(*s2)) && p<len) + { + p++; + + if(p<len) + { + s1++; + s2++; + } + } + + return tolower(*s1)-tolower(*s2); +} + +int stricmp(const char *s1, const char *s2) +{ + return strcasecmp(s1,s2); +} + +int strnicmp(const char *s1, const char *s2, size_t len) +{ + return strncasecmp(s1, s2, len); +} + +//static char *strtok_string; + +char *strsep(char **stringp, const char *delim) +{ + //int x,y; + char *old = *stringp; + const char *s; + int ok = 0; + + while(**stringp && !ok) + { + s = delim; + + while(*delim) + { + if(**stringp == *delim) + { + **stringp = 0; + ok = 1; + break; + } + + delim++; + } + + delim = s; + + *stringp+=1; + } + + if(!ok)*stringp = NULL; + + return old; +} + +char *strtok(char *str, const char *sep) +{ + int x, y; + static char *strtok_string; + static int strtok_len; + static int strtok_pos; + //int strtok_oldpos = 0; + + if(str != NULL) + { + strtok_string = str; + strtok_len = strlen(str); + + for(x = 0; x < strtok_len; x++) + { + for(y = 0; sep[y] != 0; y++) + { + if(strtok_string[x] == sep[y]) + { + strtok_string[x] = 0; + break; + } + } + } + + strtok_pos = 0; + + while(strtok_pos < strtok_len) + { + if(strtok_string[strtok_pos]) + return &strtok_string[strtok_pos]; + + strtok_pos++; + } + } + + while(strtok_pos < strtok_len) + { + if(!strtok_string[strtok_pos]) + { + strtok_pos++; + break; + } + + strtok_pos++; + } + + while(strtok_pos < strtok_len) + { + + if(strtok_string[strtok_pos]) + return &strtok_string[strtok_pos]; + + strtok_pos++; + } + + return NULL; +} + +int strspn(const char *s, const char *charset) +{ + int x, y; + int appears; + + for(x = 0; s[x] != 0; x++) + { + appears = 0; + + for(y = 0; charset[y] != 0; y++) + { + if(s[x] == charset[y]) + { + appears = 1; + break; + } + } + + if(!appears)break; + } + + return x; +} + +int strcspn(const char *s, const char *charset) +{ + int x, y; + int appears; + + for(x = 0; s[x] != 0; x++) + { + appears = 0; + + for(y = 0; charset[y] != 0; y++) + { + if(s[x] == charset[y]) + { + appears = 1; + break; + } + } + + if(appears)break; + } + + return x; +} + +char *strlwr(char *string) +{ + char *old = string; + + while(*string) + { + *string = tolower(*string); + string++; + } + + return old; +} + +char *strupr(char *string) +{ + char *old = string; + + while(*string) + { + *string = toupper(*string); + string++; + } + + return old; +} + +int atoi(const char *string) +{ + return (int)strtol(string, NULL, 10); +} + +long atol(const char *string) +{ + return strtol(string, NULL, 10); +} + +int strnlen(const char *s, size_t maxlen) +{ + int l=0; + + while(*(s++) && l<maxlen) + l++; + + return l; +} + +void *memrchr(void *b, int c, size_t len) +{ + int i = len - 1; + unsigned char *p = b; + + for(i = len - 1; p[i] != (unsigned char)c && i >= 0;i--); + + return (i>=0)?&p[i]:NULL; +} + +char *stpcpy(char *dst, const char *src) +{ + do + { + *(dst++) = *src; + }while(*(src++)); + + return dst-1; +} + +char *stpncpy(char *dst, const char *src, int len) +{ + int c = 0; + + do + { + if(c < len) + *(dst++) = *src; + + c++; + }while(*(src++) && c < len); + + return dst-1; +} + +char *strcasestr(const char *big, const char *little) +{ + while(*big) + { + const char *pbig = big; + const char *plittle = little; + int ok = 1; + + while(*pbig) + { + if(tolower(*pbig) != tolower(*plittle)) + { + ok = 0; + break; + } + + pbig++; + plittle++; + } + + if(ok) + return (char*)big; + + big++; + } + + return NULL; +} + +int strlcpy(char *dst, const char *src, size_t size) +{ + char *src_end = memchr((void*)src, '\0', size); + + if(src_end == NULL) + return 0; + + memcpy(dst, src, src_end - src); + + return (src_end - src); +} + +int strlcat(char *dst, const char *src, size_t size) +{ + int dstl = strlen(dst); + char *q = dst + dstl; + int real_size = size; + + if(memchr((void*)src, '\0', size)) + real_size = strlen(src); + + memcpy(q, src, real_size-dstl-1); + if(real_size != size) q[real_size-dstl-1] = '\0'; + + return size-dstl; +} + +void *memmem(const void *big, size_t big_len, const void *little, + size_t little_len) +{ + int i, j, l; + unsigned char *bigp = (unsigned char*)big; + unsigned char *littlep = (unsigned char*)little; + + for(i = 0, l = (int)(big_len - little_len); i <= l; i++, bigp++) + { + for(j = 0; j < little_len; j++) + { + if(littlep[j] != bigp[j]) + break; + } + + if(j == little_len) + return bigp; + } + + return NULL; +} diff --git a/libpsx/src/libc/strings.c b/libpsx/src/libc/strings.c new file mode 100644 index 0000000..76a5f9f --- /dev/null +++ b/libpsx/src/libc/strings.c @@ -0,0 +1,41 @@ +#include <stdlib.h> +#include <strings.h> +#include <stdint.h> + +#define ffs_func(func_name, type) \ +\ +int func_name(type value) \ +{ \ + int i; \ + int nbits = sizeof(type) * 8;\ + \ + for(i = 0; i < nbits && !(value & ((type)1 << i) ); i++);\ + \ + return (i == nbits) ? 0 : (i + 1);\ +} + +ffs_func(ffs, int); +ffs_func(ffsl, long); +ffs_func(ffsll, long long); + +#define popcount_func(func_name, type) \ +\ +unsigned int func_name(type value) \ +{ \ + int i, bitcnt; \ + int nbits = sizeof(type) * 8; \ + \ + for(i = 0, bitcnt = 0; i < nbits; i++) \ + {\ + if( value & ((type)1 << i) )\ + bitcnt++;\ + }\ + \ + return bitcnt;\ +} + +popcount_func(popcount, unsigned int); +popcount_func(popcountl, unsigned long); +popcount_func(popcountll, unsigned long long); +popcount_func(popcount32, uint32_t); +popcount_func(popcount64, uint64_t); diff --git a/libpsx/src/libc/unistd.c b/libpsx/src/libc/unistd.c new file mode 100644 index 0000000..f64096b --- /dev/null +++ b/libpsx/src/libc/unistd.c @@ -0,0 +1,17 @@ +#include <stdlib.h> +#include <unistd.h> + +void swab(const void *src, void *dst, ssize_t len) +{ + ssize_t x; + const unsigned char *srcp = src; + unsigned char *dstp = dst; + + for(x = 0; x < len; x+=2) + { + dstp[x] = srcp[x + 1]; + + if( (x+1) < len ) + dstp[x+1] = srcp[x]; + } +} |
