mirror of
https://github.com/pspdev/pspsdk.git
synced 2025-12-23 20:22:40 +00:00
Creation of the libpsplibc library:
- Implement callback functions needed by newlib - POSIX environment - Thread safe alloc/dealloc open/close files - Changed the way that HEAP is allocated, now by default it uses all available RAM except 512KB/ - Implement a lot of missing functions for having a real POSIX environment (some implementations are dummy because are impossible to do in the PSP OS) - Adding specific inet changes that previously where in the PSP newlib patch - Deleting the uncompleted & custom libc library - Create some weak functions during init of libc process to save some KB if we want to have tiny apps - Other I/O improvements
This commit is contained in:
@@ -1,180 +0,0 @@
|
||||
Stdlib:
|
||||
------
|
||||
|
||||
What should stdlib contain, and current status.
|
||||
|
||||
atof - ok
|
||||
atoi - ok
|
||||
atol - ok
|
||||
strtod - ok
|
||||
strtof - ok
|
||||
strtold - missing (do we want to support long double anyway?)
|
||||
strtol - ok
|
||||
strtoul - ok
|
||||
strtoq - missing
|
||||
strtouq - missing
|
||||
strtoll - missing (same as strtoq, different "standard")
|
||||
strtoull - missing (same as strtouq, different "standard")
|
||||
|
||||
|
||||
no locale function at all (__strtol_l, etc...)
|
||||
|
||||
|
||||
random - missing
|
||||
srandom - missing
|
||||
initstate - missing
|
||||
setstate - missing
|
||||
rand - ok (should be...)
|
||||
srand - ok
|
||||
drand48 - missing
|
||||
|
||||
all *rand48 missing
|
||||
|
||||
malloc, calloc, realloc, free, are defined in alloc.c.
|
||||
|
||||
abort - clean ? should call atexit functions ?
|
||||
atexit - ok
|
||||
exit - ok
|
||||
|
||||
getenv - ok
|
||||
setenv - ok
|
||||
|
||||
system - missing, and won't be here anyway I think...
|
||||
|
||||
bsearch - ok
|
||||
qsort - ok
|
||||
abs - ok
|
||||
labs - ok
|
||||
llabs - ok
|
||||
div - ok, but shouldn't it use some asm ?
|
||||
ldiv - ok, same
|
||||
lldiv - ok, same
|
||||
frexp - missing
|
||||
ldexp - missing
|
||||
|
||||
ecvt - missing
|
||||
fcvt - missing
|
||||
gcvt - won't compile
|
||||
|
||||
Multibyte function disabled... I don't trust them. Somebody please advice.
|
||||
mblen, mbtowc, wctomb, mbstowcs, wcstombs
|
||||
|
||||
|
||||
Stdio:
|
||||
-----
|
||||
|
||||
stdin, stdout, stderr, ok. Maybe some specific ps2 function to switch stderr
|
||||
to SIO could be an idea.
|
||||
|
||||
Also, should have buffering...
|
||||
|
||||
remove - missing
|
||||
rename - missing
|
||||
tmp* - missing
|
||||
fclose - ok
|
||||
fflush - ok (memory card)
|
||||
fcloseall - ok
|
||||
fopen - ok
|
||||
freopen - missing
|
||||
fdopen - ok
|
||||
setbuf - missing
|
||||
setvbuf - missing
|
||||
|
||||
*printf - ok (f, s, vf, v, vs, sn, vsn, vas, as)
|
||||
*dprintf - missing
|
||||
*scanf - missing
|
||||
*getc - ok
|
||||
getchar - ok
|
||||
*putc - ok
|
||||
putchar - ok
|
||||
{get,put}w - missing
|
||||
*gets - ok
|
||||
getdelim - missing, gnu replacement to gets
|
||||
getline - missing, gnu replacement to gets
|
||||
*puts - ok
|
||||
ungetc - missing, buffering needed
|
||||
fread - ok, buffering needed
|
||||
fwrite - ok, buffering needed
|
||||
fseek - ok
|
||||
ftell - ok
|
||||
rewind - ok
|
||||
fgetpos - ok
|
||||
fsetpos - ok
|
||||
clearerr - ok
|
||||
feof - ok
|
||||
ferror - ok
|
||||
|
||||
perror - ok
|
||||
fileno - ok
|
||||
pipe funcs - missing, can we make them ?
|
||||
lock funcs - missing, can we make them ?
|
||||
|
||||
|
||||
String:
|
||||
------
|
||||
|
||||
memcpy - ok, asm version
|
||||
memmove - ok, asm
|
||||
memset - ok, asm
|
||||
memcmp - ok, asm
|
||||
memchr - ok, asm
|
||||
|
||||
strcpy - ok, asm
|
||||
strncpy - ok, asm
|
||||
strcat - ok, asm
|
||||
strncat - ok, asm
|
||||
strcmp - ok, asm
|
||||
strncmp - ok, asm
|
||||
|
||||
strcoll - ok, binded to strcmp (will we ever support locales ?)
|
||||
strxfrm - ok, binded to strncpy (will we ever support locales ?)
|
||||
|
||||
strdup - ok
|
||||
|
||||
strchr - ok, asm
|
||||
strrchr - ok
|
||||
|
||||
strcspn - ok
|
||||
strspn - ok
|
||||
strpbrk - ok
|
||||
strstr - ok
|
||||
strcasestr - missing
|
||||
strtok - ok
|
||||
|
||||
strlen - ok
|
||||
strerror - ok (but in stdio)
|
||||
|
||||
bzero - ok (macro, in string.h)
|
||||
bcopy - ok (macro, in string.h)
|
||||
bcmp - ok (macro, in string.h)
|
||||
index - ok (macro, in string.h)
|
||||
rindex - ok (macro, in string.h)
|
||||
|
||||
stricmp - ok (macro)
|
||||
strcasecmp - ok
|
||||
strnicmp - ok (macro)
|
||||
strncasecmp - ok
|
||||
|
||||
isalnum - ok
|
||||
iscntrl - ok
|
||||
isdigit - ok
|
||||
isgraph - ok
|
||||
islower - ok
|
||||
isprint - ok
|
||||
ispunct - ok
|
||||
isspace - ok
|
||||
isupper - ok
|
||||
isxdigit - ok
|
||||
|
||||
asctime - missing
|
||||
clock - missing
|
||||
ctime - missing
|
||||
difftime - missing
|
||||
gmtime - missing
|
||||
localtime - missing
|
||||
mktime - missing
|
||||
|
||||
longjmp - ok
|
||||
setjmp - ok
|
||||
|
||||
raise - missing, can we build signals ?
|
||||
@@ -2,72 +2,119 @@
|
||||
libdir = @PSPSDK_LIBDIR@
|
||||
|
||||
CC = @PSP_CC@
|
||||
CXX = @PSP_CXX@
|
||||
CCAS = $(CC)
|
||||
AR = @PSP_AR@
|
||||
RANLIB = @PSP_RANLIB@
|
||||
|
||||
CPPFLAGS = -I$(top_srcdir)/src/libc/include -I$(top_srcdir)/src/base -I$(top_srcdir)/src/kernel -I$(top_srcdir)/src/user -I$(top_srcdir)/src/debug
|
||||
CPPFLAGS = -I$(top_srcdir)/src/base \
|
||||
-I$(top_srcdir)/src/debug \
|
||||
-I$(top_srcdir)/src/kernel \
|
||||
-I$(top_srcdir)/src/net \
|
||||
-I$(top_srcdir)/src/sdk \
|
||||
-I$(top_srcdir)/src/user \
|
||||
-I$(top_srcdir)/src/utility
|
||||
CFLAGS = @PSPSDK_CFLAGS@
|
||||
CXXFLAGS = @PSPSDK_CXXFLAGS@
|
||||
CCASFLAGS = $(CFLAGS)
|
||||
|
||||
EXTRA_DIST = LIB.status
|
||||
CWD_OBJS = __cwd.o getcwd.o __path_absolute.o __init_cwd.o
|
||||
|
||||
ERRNO_OBJS = __set_errno.o
|
||||
|
||||
FDMAN_OBJS = __descriptor_data_pool.o __descriptormap.o __fdman_init.o __fdman_get_new_descriptor.o __fdman_get_dup_descriptor.o \
|
||||
__fdman_release_descriptor.o
|
||||
|
||||
GLUE_OBJS = __fill_stat.o __psp_heap_blockid.o __psp_free_heap.o _fork.o _wait.o _open.o _close.o _read.o _write.o _fstat.o \
|
||||
_stat.o lstat.o access.o _fcntl.o _lseek.o chdir.o mkdir.o rmdir.o getdents.o _seekdir.o _link.o _unlink.o \
|
||||
_rename.o getcwd.o _getpid.o _kill.o _sbrk.o _gettimeofday.o _times.o _internal_malloc_lock.o _internal_malloc_unlock.o \
|
||||
_isatty.o symlink.o truncate.o chmod.o fchmod.o fchmodat.o pathconf.o readlink.o utime.o fchown.o getentropy.o
|
||||
|
||||
|
||||
INIT_OBJS = __psp_libc_init.o
|
||||
|
||||
MUTEXMAN_OBJS = __malloc_mutex.o __sbrk_mutex.o __fdman_mutex.o __init_mutex.o
|
||||
|
||||
NETDB_OBJS = h_errno.o gethostbyaddr.o gethostbyname.o
|
||||
|
||||
PIPE_OBJS = __pipe_peekmsgsize.o pipe.o __pipe_close.o __pipe_nonblocking_read.o __pipe_read.o __pipe_write.o \
|
||||
__pipe_nonblocking_write.o
|
||||
|
||||
SELECT_OBJS = select.o
|
||||
|
||||
SLEEP_OBJS = nanosleep.o
|
||||
|
||||
SOCKET_OBJS = socket.o __socket_close.o accept.o bind.o connect.o getsockopt.o listen.o recv.o recvfrom.o send.o sendto.o \
|
||||
setsockopt.o shutdown.o getpeername.o getsockname.o inet_ntoa.o sendmsg.o recvmsg.o
|
||||
|
||||
TERMINATE_OBJS = _exit.o abort.o exit.o
|
||||
|
||||
TIMEZONE_OBJS = __timezone_update.o
|
||||
|
||||
lib_LIBRARIES = libpsplibc.a
|
||||
|
||||
## libpsplibc.a sources.
|
||||
CORE_SOURCES = terminate.c setjmp.S qsort.c init.c cxx.cpp
|
||||
MULT_SOURCES = xprintf.c alloc.c string.c stdio.c stdlib.c libcglue.c
|
||||
netdb_nobase_includedir = @PSPSDK_INCLUDEDIR@
|
||||
netdb_nobase_include_HEADERS = netdb.h
|
||||
|
||||
ALLOC_OBJS = malloc.o realloc.o calloc.o memalign.o free.o __builtin_alloc.o __alloc_internals.o __mem_walk.o
|
||||
netinet_nobase_includedir = @PSPSDK_INCLUDEDIR@/netinet
|
||||
netinet_nobase_include_HEADERS = netinet/in.h netinet/tcp.h
|
||||
|
||||
STRING_C_OBJS = strdup.o strcasecmp.o strncasecmp.o strtok.o strrchr.o strstr.o \
|
||||
strupr.o strlwr.o _sjis_internals.o strcpy_ascii.o strcpy_sjis.o \
|
||||
strpbrk.o strspn.o strcspn.o memchr.o memcmp.o memcpy.o memmove.o \
|
||||
memset.o strcat.o strchr.o strcmp.o strcpy.o strlen.o strncat.o strncmp.o strncpy.o \
|
||||
tolower.o toupper.o isupper.o islower.o isalpha.o isdigit.o isalnum.o iscntrl.o \
|
||||
isgraph.o isprint.o ispunct.o isspace.o isxdigit.o
|
||||
arpa_nobase_includedir = @PSPSDK_INCLUDEDIR@/arpa
|
||||
arpa_nobase_include_HEADERS = arpa/inet.h
|
||||
|
||||
XPRINTF_OBJS = vxprintf.o _xprintf.o __sout.o vsnprintf.o snprintf.o vsprintf.o sprintf.o \
|
||||
__mout.o mprintf.o vmprintf.o __fout.o fprintf.o vfprintf.o printf.o vprintf.o putchar.o \
|
||||
asprintf.o vasprintf.o
|
||||
sys_nobase_includedir = @PSPSDK_INCLUDEDIR@/sys
|
||||
sys_nobase_include_HEADERS = sys/socket.h sys/ioctl.h
|
||||
|
||||
STDIO_OBJS = clearerr.o fclose.o fcloseall.o feof.o ferror.o fflush.o fflushall.o fgetc.o \
|
||||
fgetpos.o fgets.o fopen.o fputc.o fputs.o fread.o fseek.o fsetpos.o ftell.o fwrite.o fileno.o \
|
||||
getc.o getchar.o getfdtype.o gets.o perror.o putc.o puts.o remove.o rename.o fdopen.o \
|
||||
rewind.o skipatoi.o sscanf.o _stdio.o tmpfile.o tmpnam.o ungetc.o updatestdoutxy.o strerror.o \
|
||||
__stdio_internals.o
|
||||
libpsplibc_a_SOURCES = \
|
||||
cwd.o \
|
||||
errno.o \
|
||||
fdman.c \
|
||||
glue.c \
|
||||
init.c \
|
||||
netdb.c \
|
||||
pipe.c \
|
||||
select.c \
|
||||
sleep.c \
|
||||
socket.c \
|
||||
terminate.c \
|
||||
timezone.c
|
||||
|
||||
STDLIB_OBJS = abs.o atexit.o atof.o bsearch.o div.o exit.o getenv.o _itoa.o labs.o \
|
||||
ldiv.o llabs.o lldiv.o _lltoa.o _ltoa.o rand.o setenv.o srand.o \
|
||||
strtod.o strtol.o strtoul.o __assert_fail.o \
|
||||
__stdlib_internals.o
|
||||
libpsplibc_a_LIBADD = $(CWD_OBJS) $(ERRNO_OBJS) $(FDMAN_OBJS) $(INIT_OBJS) $(GLUE_OBJS) $(MUTEXMAN_OBJS) $(NETDB_OBJS) $(PIPE_OBJS) \
|
||||
$(SELECT_OBJS) $(SOCKET_OBJS) $(SLEEP_OBJS) $(TERMINATE_OBJS) $(TIMEZONE_OBJS)
|
||||
|
||||
## Use a few functions from libpspglue.a.
|
||||
GLUE_OBJS = glue__exit.o glue__sbrk.o glue_clock.o glue_gettimeofday.o glue_time.o glue___errno.o
|
||||
$(CWD_OBJS): cwd.c
|
||||
$(AM_V_CC)$(COMPILE) -DF_$* $< -c -o $@
|
||||
|
||||
MULT_OBJS = $(XPRINTF_OBJS) $(ALLOC_OBJS) $(STRING_C_OBJS) $(STDIO_OBJS) $(STDLIB_OBJS) $(GLUE_OBJS)
|
||||
$(ERRNO_OBJS): errno.c
|
||||
$(AM_V_CC)$(COMPILE) -DF_$* $< -c -o $@
|
||||
|
||||
libpsplibcincludedir = @PSPSDK_INCLUDEDIR@/libc
|
||||
libpsplibcinclude_HEADERS = assert.h ctype.h malloc.h stdio.h stdlib.h string.h time.h unistd.h
|
||||
libpsplibc_a_SOURCES = $(CORE_SOURCES) $(MULT_SOURCES)
|
||||
libpsplibc_a_LIBADD = $(MULT_OBJS)
|
||||
$(FDMAN_OBJS): fdman.c
|
||||
$(AM_V_CC)$(COMPILE) -DF_$* $< -c -o $@
|
||||
|
||||
$(XPRINTF_OBJS): xprintf.c
|
||||
$(AM_V_CPPAS)$(CPPASCOMPILE) -DF_$* $< -c -o $@
|
||||
$(INIT_OBJS): init.c
|
||||
$(AM_V_CC)$(COMPILE) -DF_$* $< -c -o $@
|
||||
|
||||
$(ALLOC_OBJS): alloc.c
|
||||
$(AM_V_CPPAS)$(CPPASCOMPILE) -DF_$* $< -c -o $@
|
||||
$(GLUE_OBJS): glue.c
|
||||
$(AM_V_CC)$(COMPILE) -DF_$* $< -c -o $@
|
||||
|
||||
$(STRING_C_OBJS): string.c
|
||||
$(AM_V_CPPAS)$(CPPASCOMPILE) -DF_$* $< -c -o $@
|
||||
$(MUTEXMAN_OBJS): mutexman.c
|
||||
$(AM_V_CC)$(COMPILE) -DF_$* $< -c -o $@
|
||||
|
||||
$(STDIO_OBJS): stdio.c
|
||||
$(AM_V_CPPAS)$(CPPASCOMPILE) -DF_$* $< -c -o $@
|
||||
$(NETDB_OBJS): netdb.c
|
||||
$(AM_V_CC)$(COMPILE) -DF_$* $< -c -o $@
|
||||
|
||||
$(STDLIB_OBJS): stdlib.c
|
||||
$(AM_V_CPPAS)$(CPPASCOMPILE) -DF_$* $< -c -o $@
|
||||
$(PIPE_OBJS): pipe.c
|
||||
$(AM_V_CC)$(COMPILE) -DF_$* $< -c -o $@
|
||||
|
||||
$(GLUE_OBJS): libcglue.c
|
||||
$(AM_V_CPPAS)$(CPPASCOMPILE) -DF_$* $< -c -o $@
|
||||
$(SELECT_OBJS): select.c
|
||||
$(AM_V_CC)$(COMPILE) -DF_$* $< -c -o $@
|
||||
|
||||
$(SLEEP_OBJS): sleep.c
|
||||
$(AM_V_CC)$(COMPILE) -DF_$* $< -c -o $@
|
||||
|
||||
$(SOCKET_OBJS): socket.c
|
||||
$(AM_V_CC)$(COMPILE) -DF_$* $< -c -o $@
|
||||
|
||||
$(TERMINATE_OBJS): terminate.c
|
||||
$(AM_V_CC)$(COMPILE) -DF_$* $< -c -o $@
|
||||
|
||||
$(TIMEZONE_OBJS): timezone.c
|
||||
$(AM_V_CC)$(COMPILE) -DF_$* $< -c -o $@
|
||||
|
||||
489
src/libc/alloc.c
489
src/libc/alloc.c
@@ -1,489 +0,0 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* alloc.c - Standard C library heap allocation routines.
|
||||
*
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
/* This code is based on code contributed by Philip Joaqiun (jenova0). */
|
||||
#include <psptypes.h>
|
||||
#include <pspkernel.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#ifdef DEBUG_ALLOC
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/* Use this to set the default malloc() alignment. */
|
||||
#define DEFAULT_ALIGNMENT 16
|
||||
|
||||
#ifndef ALIGN
|
||||
#define ALIGN(x, align) (((x)+((align)-1))&~((align)-1))
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
#define ALLOC_MAGIC 0xa110ca73
|
||||
#endif
|
||||
|
||||
extern void * _sbrk(ptrdiff_t incr);
|
||||
|
||||
void _pspsdk_alloc_init();
|
||||
void _pspsdk_alloc_deinit();
|
||||
void _pspsdk_alloc_lock();
|
||||
void _pspsdk_alloc_unlock();
|
||||
|
||||
#ifdef F___alloc_internals
|
||||
/*static vs32 alloc_sema = -1;*/
|
||||
void _pspsdk_alloc_init()
|
||||
{
|
||||
/* ee_sema_t alloc_sema_struct;*/
|
||||
/* alloc_sema_struct.init_count = 1;*/
|
||||
/* alloc_sema_struct.max_count = 1;*/
|
||||
/* alloc_sema = CreateSema(&alloc_sema_struct);*/
|
||||
}
|
||||
|
||||
void _pspsdk_alloc_deinit()
|
||||
{
|
||||
/* if (alloc_sema >= 0) {*/
|
||||
/* DeleteSema(alloc_sema);*/
|
||||
/* }*/
|
||||
}
|
||||
|
||||
void _pspsdk_alloc_lock()
|
||||
{
|
||||
/* if (alloc_sema >= 0) {*/
|
||||
/* WaitSema(alloc_sema);*/
|
||||
/* }*/
|
||||
}
|
||||
|
||||
void _pspsdk_alloc_unlock()
|
||||
{
|
||||
/* if (alloc_sema >= 0) {*/
|
||||
/* SignalSema(alloc_sema);*/
|
||||
/* }*/
|
||||
}
|
||||
#endif
|
||||
|
||||
/* _heap_mem_block_header structure. */
|
||||
typedef struct _heap_mem_header {
|
||||
#ifdef DEBUG_ALLOC
|
||||
u32 magic;
|
||||
#endif
|
||||
void * ptr;
|
||||
size_t size;
|
||||
struct _heap_mem_header * prev;
|
||||
struct _heap_mem_header * next;
|
||||
} heap_mem_header_t;
|
||||
|
||||
extern void * __alloc_heap_base;
|
||||
extern heap_mem_header_t *__alloc_heap_head;
|
||||
extern heap_mem_header_t *__alloc_heap_tail;
|
||||
|
||||
heap_mem_header_t * _heap_mem_fit(heap_mem_header_t *head, size_t size);
|
||||
|
||||
#ifdef F_malloc
|
||||
|
||||
void * __alloc_heap_base = NULL;
|
||||
heap_mem_header_t *__alloc_heap_head = NULL;
|
||||
heap_mem_header_t *__alloc_heap_tail = NULL;
|
||||
|
||||
/* Find a the lowest block that we can allocate AFTER, returning NULL if there
|
||||
are none. */
|
||||
heap_mem_header_t * _heap_mem_fit(heap_mem_header_t *head, size_t size)
|
||||
{
|
||||
heap_mem_header_t *prev_mem = head;
|
||||
u32 prev_top, next_bot;
|
||||
|
||||
while (prev_mem != NULL) {
|
||||
if (prev_mem->next != NULL) {
|
||||
prev_top = (u32)prev_mem->ptr + prev_mem->size;
|
||||
next_bot = (u32)prev_mem->next - prev_top;
|
||||
if (next_bot >= size)
|
||||
return prev_mem;
|
||||
}
|
||||
|
||||
prev_mem = prev_mem->next;
|
||||
}
|
||||
|
||||
return prev_mem;
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void * malloc(size_t size)
|
||||
{
|
||||
void *ptr = NULL, *mem_ptr;
|
||||
heap_mem_header_t *new_mem, *prev_mem;
|
||||
size_t mem_sz, heap_align_bytes;
|
||||
|
||||
mem_sz = size + sizeof(heap_mem_header_t);
|
||||
|
||||
if ((mem_sz & (DEFAULT_ALIGNMENT - 1)) != 0)
|
||||
mem_sz = ALIGN(mem_sz, DEFAULT_ALIGNMENT);
|
||||
|
||||
_pspsdk_alloc_lock();
|
||||
|
||||
/* If we don't have any allocated blocks, reserve the first block from
|
||||
the OS and initialize __alloc_heap_tail. */
|
||||
if (__alloc_heap_head == NULL) {
|
||||
/* Align the bottom of the heap to our default alignment. */
|
||||
if (__alloc_heap_base == NULL) {
|
||||
heap_align_bytes = (u32) _sbrk(0) & (DEFAULT_ALIGNMENT - 1);
|
||||
_sbrk(heap_align_bytes);
|
||||
__alloc_heap_base = _sbrk(0);
|
||||
}
|
||||
|
||||
/* Allocate the physical heap and setup the head block. */
|
||||
if ((mem_ptr = _sbrk(mem_sz)) == (void *)-1)
|
||||
return ptr; /* NULL */
|
||||
|
||||
ptr = (void *)((u32)mem_ptr + sizeof(heap_mem_header_t));
|
||||
|
||||
__alloc_heap_head = (heap_mem_header_t *)mem_ptr;
|
||||
#ifdef DEBUG_ALLOC
|
||||
__alloc_heap_head->magic = ALLOC_MAGIC;
|
||||
#endif
|
||||
__alloc_heap_head->ptr = ptr;
|
||||
__alloc_heap_head->size = mem_sz - sizeof(heap_mem_header_t);
|
||||
__alloc_heap_head->prev = NULL;
|
||||
__alloc_heap_head->next = NULL;
|
||||
|
||||
__alloc_heap_tail = __alloc_heap_head;
|
||||
|
||||
_pspsdk_alloc_unlock();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Check to see if there's free space at the bottom of the heap. */
|
||||
if ((__alloc_heap_base + mem_sz) < (void *)__alloc_heap_head) {
|
||||
new_mem = (heap_mem_header_t *)__alloc_heap_base;
|
||||
ptr = (void *)((u32)new_mem + sizeof(heap_mem_header_t));
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
new_mem->magic = ALLOC_MAGIC;
|
||||
#endif
|
||||
new_mem->ptr = ptr;
|
||||
new_mem->size = mem_sz - sizeof(heap_mem_header_t);
|
||||
new_mem->prev = NULL;
|
||||
new_mem->next = __alloc_heap_head;
|
||||
new_mem->next->prev = new_mem;
|
||||
__alloc_heap_head = new_mem;
|
||||
|
||||
_pspsdk_alloc_unlock();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* See if we can allocate the block without extending the heap. */
|
||||
prev_mem = _heap_mem_fit(__alloc_heap_head, mem_sz);
|
||||
if (prev_mem != NULL) {
|
||||
new_mem = (heap_mem_header_t *)((u32)prev_mem->ptr + prev_mem->size);
|
||||
ptr = (void *)((u32)new_mem + sizeof(heap_mem_header_t));
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
new_mem->magic = ALLOC_MAGIC;
|
||||
#endif
|
||||
new_mem->ptr = ptr;
|
||||
new_mem->size = mem_sz - sizeof(heap_mem_header_t);
|
||||
new_mem->prev = prev_mem;
|
||||
new_mem->next = prev_mem->next;
|
||||
new_mem->next->prev = new_mem;
|
||||
prev_mem->next = new_mem;
|
||||
|
||||
_pspsdk_alloc_unlock();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Extend the heap, but make certain the block is inserted in
|
||||
order. */
|
||||
if ((mem_ptr = _sbrk(mem_sz)) == (void *)-1) {
|
||||
_pspsdk_alloc_unlock();
|
||||
return ptr; /* NULL */
|
||||
}
|
||||
|
||||
ptr = (void *)((u32)mem_ptr + sizeof(heap_mem_header_t));
|
||||
|
||||
new_mem = (heap_mem_header_t *)mem_ptr;
|
||||
#ifdef DEBUG_ALLOC
|
||||
new_mem->magic = ALLOC_MAGIC;
|
||||
#endif
|
||||
new_mem->ptr = ptr;
|
||||
new_mem->size = mem_sz - sizeof(heap_mem_header_t);
|
||||
new_mem->prev = __alloc_heap_tail;
|
||||
new_mem->next = NULL;
|
||||
|
||||
__alloc_heap_tail->next = new_mem;
|
||||
__alloc_heap_tail = new_mem;
|
||||
|
||||
_pspsdk_alloc_unlock();
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_realloc
|
||||
__attribute__((weak))
|
||||
void * realloc(void *ptr, size_t size)
|
||||
{
|
||||
heap_mem_header_t *prev_mem;
|
||||
void *new_ptr = NULL;
|
||||
|
||||
if (!size && ptr != NULL) {
|
||||
free(ptr);
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
if (ptr == NULL)
|
||||
return malloc(size);
|
||||
|
||||
if ((size & (DEFAULT_ALIGNMENT - 1)) != 0)
|
||||
size = ALIGN(size, DEFAULT_ALIGNMENT);
|
||||
|
||||
_pspsdk_alloc_lock();
|
||||
prev_mem = (heap_mem_header_t *)((u32)ptr - sizeof(heap_mem_header_t));
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
if (prev_mem->magic != ALLOC_MAGIC) {
|
||||
fprintf(stderr, "realloc: Pointer at %p was not malloc()ed before, or got overwritten.\n", ptr);
|
||||
|
||||
_pspsdk_alloc_unlock();
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Don't do anything if asked for same sized block. */
|
||||
/* If the new size is shorter, let's just shorten the block. */
|
||||
if (prev_mem->size >= size) {
|
||||
/* However, if this is the last block, we have to shrink the heap. */
|
||||
if (!prev_mem->next)
|
||||
_sbrk(ptr + size - _sbrk(0));
|
||||
prev_mem->size = size;
|
||||
|
||||
_pspsdk_alloc_unlock();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
/* We are asked for a larger block of memory. */
|
||||
|
||||
/* Are we the last memory block ? */
|
||||
if (!prev_mem->next) {
|
||||
/* Yes, let's just extend the heap then. */
|
||||
if (_sbrk(size - prev_mem->size) == (void*) -1)
|
||||
return NULL;
|
||||
prev_mem->size = size;
|
||||
|
||||
_pspsdk_alloc_unlock();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Is the next block far enough so we can extend the current block ? */
|
||||
if ((prev_mem->next->ptr - ptr) > size) {
|
||||
prev_mem->size = size;
|
||||
|
||||
_pspsdk_alloc_unlock();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
_pspsdk_alloc_unlock();
|
||||
|
||||
/* We got out of luck, let's allocate a new block of memory. */
|
||||
if ((new_ptr = malloc(size)) == NULL)
|
||||
return new_ptr;
|
||||
|
||||
/* New block is larger, we only copy the old data. */
|
||||
memcpy(new_ptr, ptr, prev_mem->size);
|
||||
|
||||
free(ptr);
|
||||
return new_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_calloc
|
||||
__attribute__((weak))
|
||||
void * calloc(size_t n, size_t size)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
size_t sz = n * size;
|
||||
|
||||
if ((ptr = malloc(sz)) == NULL)
|
||||
return ptr;
|
||||
|
||||
memset(ptr, 0, sz);
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_memalign
|
||||
__attribute__((weak))
|
||||
void * memalign(size_t align, size_t size)
|
||||
{
|
||||
heap_mem_header_t new_mem;
|
||||
heap_mem_header_t *cur_mem;
|
||||
heap_mem_header_t *old_mem;
|
||||
void *ptr = NULL;
|
||||
|
||||
if (align <= DEFAULT_ALIGNMENT)
|
||||
return malloc(size);
|
||||
|
||||
/* Allocate with extra alignment bytes just in case it isn't aligned
|
||||
properly by malloc. */
|
||||
if ((ptr = malloc(size + align)) == NULL)
|
||||
return ptr; /* NULL */
|
||||
|
||||
/* If malloc returned it aligned for us we're fine. */
|
||||
if (((u32)ptr & (align - 1)) == 0)
|
||||
return ptr;
|
||||
|
||||
_pspsdk_alloc_lock();
|
||||
cur_mem = (heap_mem_header_t *)((u32)ptr - sizeof(heap_mem_header_t));
|
||||
cur_mem->size -= align;
|
||||
|
||||
/* Otherwise, align the pointer and fixup our hearder accordingly. */
|
||||
ptr = (void *)ALIGN((u32)ptr, align);
|
||||
|
||||
old_mem = cur_mem;
|
||||
|
||||
/* Copy the heap_mem_header_t locally, before repositioning (to make
|
||||
sure we don't overwrite ourselves. */
|
||||
memcpy(&new_mem, cur_mem, sizeof(heap_mem_header_t));
|
||||
cur_mem = (heap_mem_header_t *)((u32)ptr - sizeof(heap_mem_header_t));
|
||||
memcpy(cur_mem, &new_mem, sizeof(heap_mem_header_t));
|
||||
|
||||
if (cur_mem->prev)
|
||||
cur_mem->prev->next = cur_mem;
|
||||
if (cur_mem->next)
|
||||
cur_mem->next->prev = cur_mem;
|
||||
|
||||
if (__alloc_heap_head == old_mem)
|
||||
__alloc_heap_head = cur_mem;
|
||||
|
||||
if (__alloc_heap_tail == old_mem)
|
||||
__alloc_heap_tail = cur_mem;
|
||||
|
||||
cur_mem->ptr = ptr;
|
||||
|
||||
_pspsdk_alloc_unlock();
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_free
|
||||
__attribute__((weak))
|
||||
void free(void *ptr)
|
||||
{
|
||||
heap_mem_header_t *cur;
|
||||
void *heap_top;
|
||||
size_t size;
|
||||
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
_pspsdk_alloc_lock();
|
||||
|
||||
if (!__alloc_heap_head) {
|
||||
_pspsdk_alloc_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
cur = (heap_mem_header_t *)((u32)ptr - sizeof(heap_mem_header_t));
|
||||
if (cur->magic != ALLOC_MAGIC) {
|
||||
fprintf(stderr, "free: Pointer at %p was not malloc()ed before, or got overwritten.\n", ptr);
|
||||
|
||||
_pspsdk_alloc_unlock();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Freeing the head pointer is a special case. */
|
||||
if (ptr == __alloc_heap_head->ptr) {
|
||||
size = __alloc_heap_head->size +
|
||||
(size_t)(__alloc_heap_head->ptr - (void *)__alloc_heap_head);
|
||||
|
||||
__alloc_heap_head = __alloc_heap_head->next;
|
||||
|
||||
if (__alloc_heap_head != NULL) {
|
||||
__alloc_heap_head->prev = NULL;
|
||||
} else {
|
||||
__alloc_heap_tail = NULL;
|
||||
|
||||
_sbrk(-size);
|
||||
}
|
||||
|
||||
_pspsdk_alloc_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
cur = __alloc_heap_head;
|
||||
while (ptr != cur->ptr) {
|
||||
/* ptr isn't in our list */
|
||||
if (cur->next == NULL) {
|
||||
_pspsdk_alloc_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
/* Deallocate the block. */
|
||||
if (cur->next != NULL) {
|
||||
cur->next->prev = cur->prev;
|
||||
} else {
|
||||
/* If this block was the last one in the list, shrink the heap. */
|
||||
__alloc_heap_tail = cur->prev;
|
||||
|
||||
/* We need to free (heap top) - (prev->ptr + prev->size), or else
|
||||
we'll end up with an unallocatable block of heap. */
|
||||
heap_top = _sbrk(0);
|
||||
size = (u32)heap_top - (u32)(cur->prev->ptr + cur->prev->size);
|
||||
_sbrk(-size);
|
||||
}
|
||||
|
||||
cur->prev->next = cur->next;
|
||||
|
||||
_pspsdk_alloc_unlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* These are here in case C++ needs them. */
|
||||
#ifdef F___builtin_alloc
|
||||
__attribute__((weak))
|
||||
void * __builtin_new(size_t size) { return malloc(size); }
|
||||
|
||||
__attribute__((weak))
|
||||
void __builtin_delete(void *ptr) { free(ptr); }
|
||||
#endif
|
||||
|
||||
#ifdef F___mem_walk
|
||||
void * __mem_walk_begin() {
|
||||
return __alloc_heap_head;
|
||||
}
|
||||
|
||||
void __mem_walk_read(void * token, u32 * size, void ** ptr, int * valid) {
|
||||
heap_mem_header_t * cur = (heap_mem_header_t *) token;
|
||||
|
||||
#ifdef DEBUG_ALLOC
|
||||
if (cur->magic != ALLOC_MAGIC) {
|
||||
*valid = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
*valid = 1;
|
||||
|
||||
*size = cur->size;
|
||||
*ptr = cur->ptr;
|
||||
}
|
||||
|
||||
void * __mem_walk_inc(void * token) {
|
||||
heap_mem_header_t * cur = (heap_mem_header_t *) token;
|
||||
|
||||
return cur->next;
|
||||
}
|
||||
|
||||
int __mem_walk_end(void * token) {
|
||||
return token == NULL;
|
||||
}
|
||||
#endif
|
||||
26
src/libc/arpa/inet.h
Normal file
26
src/libc/arpa/inet.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* arpa/inet.h - Functions for converting IP addresses between strings and numbers */
|
||||
|
||||
#ifndef _ARPA_INET_H_
|
||||
#define _ARPA_INET_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
in_addr_t sceNetInetInetAddr(const char *ip);
|
||||
int sceNetInetInetAton(const char *ip, struct in_addr *in);
|
||||
const char* sceNetInetInetNtop(int af, const void *src, char *dst, socklen_t cnt);
|
||||
int sceNetInetInetPton(int af, const char *src, void *dst);
|
||||
|
||||
char *inet_ntoa(struct in_addr in);
|
||||
#define inet_addr sceNetInetInetAddr
|
||||
#define inet_aton sceNetInetInetAton
|
||||
#define inet_ntop sceNetInetInetNtop
|
||||
#define inet_pton sceNetInetInetPton
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _ARPA_INET_H_ */
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* assert.h
|
||||
*
|
||||
* Copyright (c) 2002-2004 PS2DEV
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
#ifndef __ASSERT_H__
|
||||
#define __ASSERT_H__
|
||||
|
||||
#include <pspkernel.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define assert(cond)
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int __assert_fail (const char *assertion, const char *file, unsigned int line) __attribute__((noreturn));
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#define assert(cond) (void)((cond)?0:__assert_fail(#cond, __FILE__, __LINE__))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* ctype.h
|
||||
*
|
||||
* Copyright (c) 2002-2004 PS2DEV
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CTYPE_H__
|
||||
#define __CTYPE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int isalnum(int);
|
||||
int isalpha(int);
|
||||
int iscntrl(int);
|
||||
int isdigit(int);
|
||||
int isgraph(int);
|
||||
int islower(int);
|
||||
int isprint(int);
|
||||
int ispunct(int);
|
||||
int isspace(int);
|
||||
int isupper(int);
|
||||
int isxdigit(int);
|
||||
int tolower(int);
|
||||
int toupper(int);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
|
||||
/* To be compatible with C++'s ctype_base.h */
|
||||
|
||||
namespace std {
|
||||
enum {
|
||||
_U = 01,
|
||||
_L = 02,
|
||||
_N = 04,
|
||||
_S = 010,
|
||||
_P = 020,
|
||||
_C = 040,
|
||||
_X = 0100,
|
||||
_B = 0200
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
192
src/libc/cwd.c
Normal file
192
src/libc/cwd.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* init.c - The global init/deinit code for our crt0.
|
||||
*
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef F___cwd
|
||||
/* the present working directory variable. */
|
||||
char __cwd[MAXNAMLEN + 1] = { 0 };
|
||||
#else
|
||||
extern char __cwd[MAXNAMLEN + 1];
|
||||
#endif
|
||||
|
||||
#ifdef F_getcwd
|
||||
char *getcwd(char *buf, size_t size)
|
||||
{
|
||||
if(!buf) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(strlen(__cwd) >= size) {
|
||||
errno = ERANGE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(buf, __cwd);
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F___path_absolute
|
||||
/* Like strcpy, but returns 0 if the string doesn't fit */
|
||||
static int __safe_strcpy(char *out, const char *in, int maxlen)
|
||||
{
|
||||
for( ; maxlen > 0 && *in ; maxlen-- )
|
||||
*(out++) = *(in++);
|
||||
if(maxlen < 1) return 0;
|
||||
*out = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Like strcat, but returns 0 if the string doesn't fit */
|
||||
static int __safe_strcat(char *out, const char *in, int maxlen)
|
||||
{
|
||||
for( ; *out ; out++,maxlen-- )
|
||||
continue;
|
||||
return __safe_strcpy(out, in, maxlen);
|
||||
}
|
||||
|
||||
/* Normalize a pathname (without leading "drive:") by removing
|
||||
. and .. components, duplicated /, etc. */
|
||||
static int __path_normalize(char *out, int len)
|
||||
{
|
||||
int i, j;
|
||||
int first, next;
|
||||
|
||||
/* First append "/" to make the rest easier */
|
||||
if(!__safe_strcat(out,"/",len)) return -10;
|
||||
|
||||
/* Convert "//" to "/" */
|
||||
for(i=0; out[i+1]; i++) {
|
||||
if(out[i]=='/' && out[i+1]=='/') {
|
||||
for(j=i+1; out[j]; j++)
|
||||
out[j] = out[j+1];
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert "/./" to "/" */
|
||||
for(i=0; out[i] && out[i+1] && out[i+2]; i++) {
|
||||
if(out[i]=='/' && out[i+1]=='.' && out[i+2]=='/') {
|
||||
for(j=i+1; out[j]; j++)
|
||||
out[j] = out[j+2];
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert "/asdf/../" to "/" until we can't anymore. Also
|
||||
* convert leading "/../" to "/" */
|
||||
first = next = 0;
|
||||
while(1) {
|
||||
/* If a "../" follows, remove it and the parent */
|
||||
if(out[next+1] && out[next+1]=='.' &&
|
||||
out[next+2] && out[next+2]=='.' &&
|
||||
out[next+3] && out[next+3]=='/') {
|
||||
for(j=0; out[first+j+1]; j++)
|
||||
out[first+j+1] = out[next+j+4];
|
||||
first = next = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find next slash */
|
||||
first = next;
|
||||
for(next=first+1; out[next] && out[next] != '/'; next++)
|
||||
continue;
|
||||
if(!out[next]) break;
|
||||
}
|
||||
|
||||
/* Remove trailing "/" */
|
||||
for(i=1; out[i]; i++)
|
||||
continue;
|
||||
if(i >= 1 && out[i-1] == '/')
|
||||
out[i-1] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the number of bytes taken up by the "drive:" prefix,
|
||||
or -1 if it's not found */
|
||||
static int __get_drive(const char *d)
|
||||
{
|
||||
int i;
|
||||
for(i=0; d[i]; i++) {
|
||||
if(! ((d[i] >= 'a' && d[i] <= 'z') ||
|
||||
(d[i] >= '0' && d[i] <= '9') ))
|
||||
break;
|
||||
}
|
||||
if(d[i] == ':') return i+1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert relative path to absolute path. */
|
||||
int __path_absolute(const char *in, char *out, int len)
|
||||
{
|
||||
int dr;
|
||||
|
||||
/* See what the relative URL starts with */
|
||||
dr = __get_drive(in);
|
||||
if(dr > 0 && in[dr] == '/') {
|
||||
/* It starts with "drive:/", so it's already absolute */
|
||||
if(!__safe_strcpy(out, in, len))
|
||||
return -1;
|
||||
} else if(in[0] == '/') {
|
||||
/* It's absolute, but missing the drive, so use cwd's drive */
|
||||
if(strlen(__cwd) >= len)
|
||||
return -2;
|
||||
strcpy(out, __cwd);
|
||||
dr = __get_drive(out);
|
||||
out[dr] = 0;
|
||||
if(!__safe_strcat(out, in, len))
|
||||
return -3;
|
||||
} else {
|
||||
/* It's not absolute, so append it to the current cwd */
|
||||
if(strlen(__cwd) >= len)
|
||||
return -4;
|
||||
strcpy(out, __cwd);
|
||||
if(!__safe_strcat(out, "/", len))
|
||||
return -6;
|
||||
if(!__safe_strcat(out, in, len))
|
||||
return -7;
|
||||
}
|
||||
|
||||
/* Now normalize the pathname portion */
|
||||
dr = __get_drive(out);
|
||||
if(dr < 0) dr = 0;
|
||||
return __path_normalize(out + dr, len - dr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F___init_cwd
|
||||
/* Set the current working directory (CWD) to the path where the module was launched. */
|
||||
void __init_cwd(char *argv_0)
|
||||
{
|
||||
if (argv_0 != NULL) {
|
||||
char base_path[MAXPATHLEN + 1];
|
||||
char *end;
|
||||
|
||||
strncpy(base_path, argv_0, sizeof(base_path) - 1);
|
||||
base_path[sizeof(base_path) - 1] = '\0';
|
||||
end = strrchr(base_path, '/');
|
||||
if (end != NULL) {
|
||||
*(end + 1) = '\0';
|
||||
chdir(base_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* cxx.cpp - Simple C++ memory allocation operators.
|
||||
*
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
|
||||
__attribute__((weak))
|
||||
void operator delete(void *ptr)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void* operator new(size_t len)
|
||||
{
|
||||
return malloc(len);
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void operator delete[](void *ptr)
|
||||
{
|
||||
::operator delete(ptr);
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void* operator new[](size_t len)
|
||||
{
|
||||
return ::operator new(len);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
__attribute__((weak))
|
||||
void __cxa_pure_virtual()
|
||||
{
|
||||
/* perror("Pure virtual method called"); */
|
||||
abort();
|
||||
}
|
||||
@@ -3,18 +3,24 @@
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* unistd.h
|
||||
* init.c - The global init/deinit code for our crt0.
|
||||
*
|
||||
* Copyright (c) 2002-2004 PS2DEV
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __UNISTD_H__
|
||||
#define __UNISTD_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#endif
|
||||
#ifdef F___set_errno
|
||||
int __set_errno(int code)
|
||||
{
|
||||
if ((code & 0x80010000) == 0x80010000) {
|
||||
errno = code & 0xFFFF;
|
||||
return -1;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
#endif
|
||||
142
src/libc/fdman.c
Normal file
142
src/libc/fdman.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* fdman.c - Manager for fd.
|
||||
*
|
||||
* Copyright (c) 2021 Francisco Javier Trujillo Mata <fjtrujy@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <pspstdio.h>
|
||||
#include <psptypes.h>
|
||||
#include <pspsdk.h>
|
||||
|
||||
#include "fdman.h"
|
||||
|
||||
/* Functions from mutexman.c */
|
||||
extern SceLwMutexWorkarea __fdman_mutex;
|
||||
|
||||
#ifdef F___descriptor_data_pool
|
||||
__descriptormap_type __descriptor_data_pool[__FILENO_MAX];
|
||||
#else
|
||||
extern __descriptormap_type __descriptor_data_pool[__FILENO_MAX];
|
||||
#endif
|
||||
|
||||
#ifdef F___descriptormap
|
||||
__descriptormap_type *__descriptormap[__FILENO_MAX];
|
||||
#else
|
||||
extern __descriptormap_type *__descriptormap[__FILENO_MAX];
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef F___fdman_init
|
||||
void __fdman_init()
|
||||
{
|
||||
int scefd;
|
||||
|
||||
/* Initialize descriptor data*/
|
||||
memset(__descriptor_data_pool, 0, sizeof(__descriptormap_type) *__FILENO_MAX);
|
||||
/* Initialize descriptor map*/
|
||||
memset(__descriptormap, 0, sizeof(__descriptormap_type*)*__FILENO_MAX);
|
||||
|
||||
scefd = sceKernelStdin();
|
||||
if (scefd >= 0) {
|
||||
__descriptormap[0] = &__descriptor_data_pool[0];
|
||||
__descriptormap[0]->descriptor = scefd;
|
||||
__descriptormap[0]->type = __DESCRIPTOR_TYPE_TTY;
|
||||
}
|
||||
scefd = sceKernelStdout();
|
||||
if (scefd >= 0) {
|
||||
__descriptormap[1] = &__descriptor_data_pool[1];
|
||||
__descriptormap[1]->descriptor = scefd;
|
||||
__descriptormap[1]->type = __DESCRIPTOR_TYPE_TTY;
|
||||
}
|
||||
scefd = sceKernelStderr();
|
||||
if (scefd >= 0) {
|
||||
__descriptormap[2] = &__descriptor_data_pool[2];
|
||||
__descriptormap[2]->descriptor = scefd;
|
||||
__descriptormap[2]->type = __DESCRIPTOR_TYPE_TTY;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef F___fdman_get_new_descriptor
|
||||
int __fdman_get_new_descriptor()
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
sceKernelLockLwMutex(&__fdman_mutex, 1, 0); /* lock here to make thread safe */
|
||||
for (i = 0; i < __FILENO_MAX; i++) {
|
||||
if (__descriptormap[i] == NULL) {
|
||||
__descriptormap[i] = &__descriptor_data_pool[i];
|
||||
__descriptormap[i]->ref_count++;
|
||||
sceKernelUnlockLwMutex(&__fdman_mutex, 1);; /* release lock */
|
||||
return i;
|
||||
}
|
||||
}
|
||||
sceKernelUnlockLwMutex(&__fdman_mutex, 1);; /* release lock */
|
||||
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef F___fdman_get_dup_descriptor
|
||||
int __fdman_get_dup_descriptor(int fd)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (!__IS_FD_VALID(fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceKernelLockLwMutex(&__fdman_mutex, 1, 0); /* lock here to make thread safe */
|
||||
for (i = 0; i < __FILENO_MAX; i++) {
|
||||
if (__descriptormap[i] == NULL) {
|
||||
__descriptormap[i] = &__descriptor_data_pool[fd];
|
||||
__descriptormap[i]->ref_count++;
|
||||
sceKernelUnlockLwMutex(&__fdman_mutex, 1);; /* release lock */
|
||||
return i;
|
||||
}
|
||||
}
|
||||
sceKernelUnlockLwMutex(&__fdman_mutex, 1);; /* release lock */
|
||||
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef F___fdman_release_descriptor
|
||||
void __fdman_release_descriptor(int fd)
|
||||
{
|
||||
if (!__IS_FD_VALID(fd)) {
|
||||
errno = EBADF;
|
||||
return;
|
||||
}
|
||||
|
||||
__descriptormap[fd]->ref_count--;
|
||||
|
||||
if (__descriptormap[fd]->ref_count == 0) {
|
||||
|
||||
if (__descriptormap[fd]->filename != NULL) {
|
||||
free(__descriptormap[fd]->filename);
|
||||
}
|
||||
__descriptormap[fd]->filename = NULL;
|
||||
__descriptormap[fd]->descriptor = 0;
|
||||
__descriptormap[fd]->type = 0;
|
||||
__descriptormap[fd]->flags = 0;
|
||||
|
||||
}
|
||||
__descriptormap[fd] = NULL;
|
||||
}
|
||||
#endif
|
||||
48
src/libc/fdman.h
Normal file
48
src/libc/fdman.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* PSP Software Development Kit - http://www.pspdev.org
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* fdman.h - File descriptor management.
|
||||
*
|
||||
* Copyright (c) 2006 Rafael Cabezas <rafpsp@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _FDMAN_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#define _FDMAN_H_
|
||||
|
||||
#define __FILENO_MAX 1024
|
||||
|
||||
#define __IS_FD_VALID(FD) \
|
||||
( (FD >= 0) && (FD < __FILENO_MAX) && (__descriptormap[FD] != NULL) )
|
||||
|
||||
#define __IS_FD_OF_TYPE(FD, TYPE) \
|
||||
( (__IS_FD_VALID(FD)) && (__descriptormap[FD]->type == TYPE) )
|
||||
|
||||
typedef enum {
|
||||
__DESCRIPTOR_TYPE_FILE,
|
||||
__DESCRIPTOR_TYPE_FOLDER,
|
||||
__DESCRIPTOR_TYPE_PIPE,
|
||||
__DESCRIPTOR_TYPE_SOCKET,
|
||||
__DESCRIPTOR_TYPE_TTY
|
||||
} __fdman_fd_types;
|
||||
|
||||
typedef struct {
|
||||
u_int32_t descriptor;
|
||||
u_int32_t flags;
|
||||
u_int32_t ref_count;
|
||||
char *filename;
|
||||
u_int8_t type;
|
||||
} __descriptormap_type;
|
||||
|
||||
extern __descriptormap_type *__descriptormap[__FILENO_MAX];
|
||||
|
||||
void __fdman_init();
|
||||
int __fdman_get_new_descriptor();
|
||||
int __fdman_get_dup_descriptor(int fd);
|
||||
void __fdman_release_descriptor(int fd);
|
||||
|
||||
#endif
|
||||
865
src/libc/glue.c
Normal file
865
src/libc/glue.c
Normal file
@@ -0,0 +1,865 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* libcglue.c - Newlib-compatible system calls.
|
||||
*
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
* Copyright (c) 2005 Jim Paris <jim@jtan.com>
|
||||
* Copyright (c) 2021 Francisco J Trujillo <fjtrujy@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <psptypes.h>
|
||||
#include <pspiofilemgr.h>
|
||||
#include <pspmodulemgr.h>
|
||||
#include <pspsysmem.h>
|
||||
#include <pspthreadman.h>
|
||||
#include <psputils.h>
|
||||
#include <pspsdk.h>
|
||||
|
||||
#include "fdman.h"
|
||||
|
||||
#define DEFAULT_PRX_HEAP_SIZE_KB 64
|
||||
#define DEFAULT_HEAP_THRESHOLD_SIZE_KB 512
|
||||
|
||||
/* If defined it specifies the desired size of the heap, in KB. */
|
||||
extern unsigned int sce_newlib_heap_kb_size __attribute__((weak));
|
||||
extern unsigned int sce_newlib_heap_threshold_kb_size __attribute__((weak));
|
||||
extern int __pspsdk_is_prx __attribute__((weak));
|
||||
|
||||
/* Functions from cwd.c */
|
||||
extern char __cwd[MAXNAMLEN + 1];
|
||||
int __path_absolute(const char *in, char *out, int len);
|
||||
|
||||
/* Functions from mutexman.c */
|
||||
extern SceLwMutexWorkarea __malloc_mutex;
|
||||
extern SceLwMutexWorkarea __sbrk_mutex;
|
||||
|
||||
/* Fuctions from errno.c */
|
||||
int __set_errno(int code);
|
||||
|
||||
/* Functions from pipe.c */
|
||||
int __pipe_read(int fd, void *buf, size_t len);
|
||||
int __pipe_close(int fd);
|
||||
int __pipe_write(int fd, const void *buf, size_t len);
|
||||
int __pipe_nonblocking_read(int fd, void *buf, size_t len);
|
||||
int __pipe_nonblocking_write(int fd, const void *buf, size_t len);
|
||||
|
||||
/* Functions from socket.c */
|
||||
int __socket_close(int sock);
|
||||
|
||||
#ifdef F___fill_stat
|
||||
static time_t psp_to_posix_time(ScePspDateTime psp_time)
|
||||
{
|
||||
struct tm conv_time;
|
||||
conv_time.tm_year = psp_time.year;
|
||||
conv_time.tm_mon = psp_time.month;
|
||||
conv_time.tm_mday = psp_time.day;
|
||||
conv_time.tm_hour = psp_time.hour;
|
||||
conv_time.tm_min = psp_time.minute;
|
||||
conv_time.tm_sec = psp_time.second;
|
||||
conv_time.tm_isdst = -1;
|
||||
return mktime(&conv_time);
|
||||
}
|
||||
|
||||
static mode_t io_to_posix_mode(SceMode sceMode)
|
||||
{
|
||||
mode_t posixmode = 0;
|
||||
if (sceMode & FIO_SO_IFREG) posixmode |= S_IFREG;
|
||||
if (sceMode & FIO_SO_IFDIR) posixmode |= S_IFDIR;
|
||||
if (sceMode & FIO_SO_IROTH) posixmode |= S_IRUSR|S_IRGRP|S_IROTH;
|
||||
if (sceMode & FIO_SO_IWOTH) posixmode |= S_IWUSR|S_IWGRP|S_IWOTH;
|
||||
if (sceMode & FIO_SO_IXOTH) posixmode |= S_IXUSR|S_IXGRP|S_IXOTH;
|
||||
return posixmode;
|
||||
}
|
||||
|
||||
|
||||
void __fill_stat(struct stat *stat, const SceIoStat *sce_stat)
|
||||
{
|
||||
stat->st_dev = 0;
|
||||
stat->st_ino = 0;
|
||||
stat->st_mode = io_to_posix_mode(sce_stat->st_attr);
|
||||
stat->st_nlink = 0;
|
||||
stat->st_uid = 0;
|
||||
stat->st_gid = 0;
|
||||
stat->st_rdev = 0;
|
||||
stat->st_size = sce_stat->st_size;
|
||||
stat->st_atime = psp_to_posix_time(sce_stat->sce_st_atime);
|
||||
stat->st_mtime = psp_to_posix_time(sce_stat->sce_st_mtime);
|
||||
stat->st_ctime = psp_to_posix_time(sce_stat->sce_st_ctime);
|
||||
stat->st_blksize = 16*1024;
|
||||
stat->st_blocks = stat->st_size / 512;
|
||||
}
|
||||
#else
|
||||
void __fill_stat(struct stat *stat, const SceIoStat *sce_stat);
|
||||
#endif
|
||||
|
||||
#ifdef F___psp_heap_blockid
|
||||
/* UID of the memory block that represents the heap. */
|
||||
SceUID __psp_heap_blockid;
|
||||
#else
|
||||
extern SceUID __psp_heap_blockid;
|
||||
#endif
|
||||
|
||||
#ifdef F___psp_free_heap
|
||||
/* Free the heap. */
|
||||
int __psp_free_heap(void)
|
||||
{
|
||||
if (__psp_heap_blockid > 0) {
|
||||
return sceKernelFreePartitionMemory(__psp_heap_blockid);
|
||||
}
|
||||
|
||||
return __psp_heap_blockid;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__open
|
||||
int _open(const char *buf, int flags, int mode) {
|
||||
int scefd, fd, sce_flags, is_dir;
|
||||
char dest[MAXNAMLEN + 1];
|
||||
|
||||
if(__path_absolute(buf, dest, MAXNAMLEN) < 0) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
is_dir = 0;
|
||||
/* O_RDONLY starts at 0, where PSP_O_RDONLY starts at 1, so remap the read/write
|
||||
flags by adding 1. */
|
||||
sce_flags = (flags & O_ACCMODE) + 1;
|
||||
|
||||
/* Translate standard open flags into the flags understood by the PSP kernel. */
|
||||
if (flags & O_APPEND) {
|
||||
sce_flags |= PSP_O_APPEND;
|
||||
}
|
||||
if (flags & O_CREAT) {
|
||||
sce_flags |= PSP_O_CREAT;
|
||||
}
|
||||
if (flags & O_TRUNC) {
|
||||
sce_flags |= PSP_O_TRUNC;
|
||||
}
|
||||
if (flags & O_EXCL) {
|
||||
sce_flags |= PSP_O_EXCL;
|
||||
}
|
||||
if (flags & O_NONBLOCK) {
|
||||
sce_flags |= PSP_O_NBLOCK;
|
||||
}
|
||||
if (flags & O_DIRECTORY) {
|
||||
sce_flags |= PSP_O_DIR;
|
||||
is_dir = 1;
|
||||
}
|
||||
|
||||
scefd = is_dir ? sceIoDopen(dest) : sceIoOpen(dest, sce_flags, mode);
|
||||
if (scefd >= 0) {
|
||||
fd = __fdman_get_new_descriptor();
|
||||
if (fd != -1) {
|
||||
__descriptormap[fd]->descriptor = scefd;
|
||||
__descriptormap[fd]->type = is_dir ? __DESCRIPTOR_TYPE_FOLDER : __DESCRIPTOR_TYPE_FILE;
|
||||
__descriptormap[fd]->flags = flags;
|
||||
__descriptormap[fd]->filename = strdup(dest);
|
||||
return fd;
|
||||
}
|
||||
else {
|
||||
is_dir ? sceIoDclose(scefd) : sceIoClose(scefd);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return __set_errno(scefd);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef F__close
|
||||
int _close(int fd) {
|
||||
int ret = 0;
|
||||
|
||||
if (!__IS_FD_VALID(fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(__descriptormap[fd]->type)
|
||||
{
|
||||
case __DESCRIPTOR_TYPE_FILE:
|
||||
case __DESCRIPTOR_TYPE_TTY:
|
||||
if (__descriptormap[fd]->ref_count == 1) {
|
||||
ret = __set_errno(sceIoClose(__descriptormap[fd]->descriptor));
|
||||
}
|
||||
__fdman_release_descriptor(fd);
|
||||
return ret;
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_FOLDER:
|
||||
if (__descriptormap[fd]->ref_count == 1) {
|
||||
ret = __set_errno(sceIoDclose(__descriptormap[fd]->descriptor));
|
||||
}
|
||||
__fdman_release_descriptor(fd);
|
||||
return ret;
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_PIPE:
|
||||
return __pipe_close(fd);
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_SOCKET:
|
||||
return __socket_close(fd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__read
|
||||
int _read(int fd, void *buf, size_t nbytes) {
|
||||
if (!__IS_FD_VALID(fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(__descriptormap[fd]->type)
|
||||
{
|
||||
case __DESCRIPTOR_TYPE_FILE:
|
||||
case __DESCRIPTOR_TYPE_TTY:
|
||||
return __set_errno(sceIoRead(__descriptormap[fd]->descriptor, buf, nbytes));
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_PIPE:
|
||||
if (__descriptormap[fd]->flags & O_NONBLOCK) {
|
||||
return __pipe_nonblocking_read(fd, buf, nbytes);
|
||||
}
|
||||
else {
|
||||
return __pipe_read(fd, buf, nbytes);
|
||||
}
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_SOCKET:
|
||||
return recv(fd, buf, nbytes, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__write
|
||||
int _write(int fd, const void *buf, size_t nbytes) {
|
||||
if (!__IS_FD_VALID(fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(__descriptormap[fd]->type)
|
||||
{
|
||||
case __DESCRIPTOR_TYPE_FILE:
|
||||
case __DESCRIPTOR_TYPE_TTY:
|
||||
return __set_errno(sceIoWrite(__descriptormap[fd]->descriptor, buf, nbytes));
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_PIPE:
|
||||
if (__descriptormap[fd]->flags & O_NONBLOCK) {
|
||||
return __pipe_nonblocking_write(fd, buf, nbytes);
|
||||
}
|
||||
else {
|
||||
return __pipe_write(fd, buf, nbytes);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_SOCKET:
|
||||
return send(fd, buf, nbytes, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__stat
|
||||
int _stat(const char *filename, struct stat *buf)
|
||||
{
|
||||
SceIoStat psp_stat;
|
||||
char dest[MAXNAMLEN + 1];
|
||||
int ret;
|
||||
|
||||
if(__path_absolute(filename, dest, MAXNAMLEN) < 0) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buf, '\0', sizeof(struct stat));
|
||||
ret = sceIoGetstat(dest, &psp_stat);
|
||||
if (ret < 0) {
|
||||
return __set_errno(ret);
|
||||
}
|
||||
|
||||
__fill_stat(buf, &psp_stat);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int _stat(const char *filename, struct stat *buf);
|
||||
#endif
|
||||
|
||||
#ifdef F_lstat
|
||||
int lstat(const char *filename, struct stat *buf)
|
||||
{
|
||||
return stat(filename, buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__fstat
|
||||
int _fstat(int fd, struct stat *buf) {
|
||||
int ret;
|
||||
SceOff oldpos;
|
||||
if (!__IS_FD_VALID(fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(__descriptormap[fd]->type)
|
||||
{
|
||||
case __DESCRIPTOR_TYPE_TTY:
|
||||
memset(buf, '\0', sizeof(struct stat));
|
||||
buf->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_FILE:
|
||||
if (__descriptormap[fd]->filename != NULL) {
|
||||
ret = _stat(__descriptormap[fd]->filename, buf);
|
||||
|
||||
/* Find true size of the open file */
|
||||
oldpos = sceIoLseek(__descriptormap[fd]->descriptor, 0, SEEK_CUR);
|
||||
if (oldpos != (off_t) -1) {
|
||||
buf->st_size = (off_t) sceIoLseek(__descriptormap[fd]->descriptor, 0, SEEK_END);
|
||||
sceIoLseek(__descriptormap[fd]->descriptor, oldpos, SEEK_SET);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_PIPE:
|
||||
case __DESCRIPTOR_TYPE_SOCKET:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_access
|
||||
int access(const char *fn, int flags)
|
||||
{
|
||||
struct stat s;
|
||||
if (stat(fn, &s))
|
||||
return -1;
|
||||
if (s.st_mode & S_IFDIR)
|
||||
return 0;
|
||||
if (flags & W_OK)
|
||||
{
|
||||
if (s.st_mode & S_IWRITE)
|
||||
return 0;
|
||||
errno = EACCES;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__fcntl
|
||||
int _fcntl(int fd, int cmd, ...)
|
||||
{
|
||||
if (!__IS_FD_VALID(fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case F_DUPFD:
|
||||
{
|
||||
return __fdman_get_dup_descriptor(fd);
|
||||
break;
|
||||
}
|
||||
case F_GETFL:
|
||||
{
|
||||
return __descriptormap[fd]->flags;
|
||||
break;
|
||||
}
|
||||
case F_SETFL:
|
||||
{
|
||||
int newfl;
|
||||
va_list args;
|
||||
|
||||
va_start (args, cmd); /* Initialize the argument list. */
|
||||
newfl = va_arg(args, int);
|
||||
va_end (args); /* Clean up. */
|
||||
|
||||
__descriptormap[fd]->flags = newfl;
|
||||
|
||||
switch(__descriptormap[fd]->type)
|
||||
{
|
||||
case __DESCRIPTOR_TYPE_FILE:
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_PIPE:
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_SOCKET:
|
||||
if (newfl & O_NONBLOCK)
|
||||
{
|
||||
int one = 1;
|
||||
return setsockopt(fd, SOL_SOCKET, SO_NONBLOCK, (char *)&one, sizeof(one));
|
||||
}
|
||||
else
|
||||
{
|
||||
int zero = 0;
|
||||
return setsockopt(fd, SOL_SOCKET, SO_NONBLOCK, (char *)&zero, sizeof(zero));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
#endif /* F__fcntl */
|
||||
|
||||
#ifdef F_getdents
|
||||
int getdents(int fd, void *dd_buf, int count)
|
||||
{
|
||||
struct dirent *dirp;
|
||||
int rv, read;
|
||||
SceIoDirent sceiode;
|
||||
|
||||
read = 0;
|
||||
// NEEDED otherwise it will crash!!!
|
||||
memset(&sceiode, 0, sizeof(SceIoDirent));
|
||||
rv = sceIoDread(__descriptormap[fd]->descriptor, &sceiode);
|
||||
if (rv < 0) {
|
||||
return __set_errno(rv);
|
||||
} else if (rv == 0) {
|
||||
return read;
|
||||
}
|
||||
|
||||
read += sizeof(struct dirent);
|
||||
dirp = (struct dirent *)dd_buf;
|
||||
|
||||
dirp->d_fileno = rv;
|
||||
strncpy(dirp->d_name, sceiode.d_name, MAXNAMLEN);
|
||||
dirp->d_name[MAXNAMLEN] = 0;
|
||||
dirp->d_reclen = count;
|
||||
|
||||
return read;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__seekdir
|
||||
void _seekdir(DIR *dirp, long loc)
|
||||
{
|
||||
int i;
|
||||
SceUID uid;
|
||||
SceIoDirent sceiode;
|
||||
|
||||
if (__descriptormap[dirp->dd_fd]->filename != NULL) {
|
||||
sceIoDclose(__descriptormap[dirp->dd_fd]->descriptor);
|
||||
uid = sceIoDopen(__descriptormap[dirp->dd_fd]->filename);
|
||||
__descriptormap[dirp->dd_fd]->descriptor = uid;
|
||||
for (i = 0; i < loc; i++) {
|
||||
// NEEDED otherwise it will crash!!!
|
||||
memset(&sceiode, 0, sizeof(SceIoDirent));
|
||||
sceIoDread(uid, &sceiode);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__lseek
|
||||
off_t _lseek(int fd, off_t offset, int whence)
|
||||
{
|
||||
if (!__IS_FD_VALID(fd)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(__descriptormap[fd]->type)
|
||||
{
|
||||
case __DESCRIPTOR_TYPE_FILE:
|
||||
/* We don't have to do anything with the whence argument because SEEK_* == PSP_SEEK_*. */
|
||||
return (off_t) __set_errno(sceIoLseek(__descriptormap[fd]->descriptor, offset, whence));
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_PIPE:
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_SOCKET:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_chdir
|
||||
int chdir(const char *path)
|
||||
{
|
||||
char dest[MAXNAMLEN + 1];
|
||||
SceUID uid;
|
||||
|
||||
if(__path_absolute(path, dest, MAXNAMLEN) < 0) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* sceIoChdir doesn't give an indication of whether it worked,
|
||||
so test for existence by attempting to open the dir */
|
||||
uid = sceIoDopen(dest);
|
||||
if(uid < 0) {
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
sceIoDclose(uid);
|
||||
|
||||
sceIoChdir(dest);
|
||||
strcpy(__cwd, dest);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_mkdir
|
||||
int mkdir(const char *pathname, mode_t mode)
|
||||
{
|
||||
char dest[MAXNAMLEN + 1];
|
||||
|
||||
if(__path_absolute(pathname, dest, MAXNAMLEN) < 0) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return __set_errno(sceIoMkdir(dest, mode));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_rmdir
|
||||
int rmdir(const char *pathname)
|
||||
{
|
||||
char dest[MAXNAMLEN + 1];
|
||||
|
||||
if(__path_absolute(pathname, dest, MAXNAMLEN) < 0) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return __set_errno(sceIoRmdir(dest));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__link
|
||||
int _link(const char *old, const char *new) {
|
||||
errno = ENOSYS;
|
||||
return -1; /* not supported */
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__unlink
|
||||
int _unlink(const char *path) {
|
||||
errno = ENOSYS;
|
||||
return -1; /* not supported */
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__rename
|
||||
int _rename(const char *old, const char *new)
|
||||
{
|
||||
char oldname[MAXNAMLEN + 1];
|
||||
char newname[MAXNAMLEN + 1];
|
||||
|
||||
if(__path_absolute(old, oldname, MAXNAMLEN) < 0) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(__path_absolute(new, newname, MAXNAMLEN) < 0) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return __set_errno(sceIoRename(oldname, newname));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_getcwd
|
||||
char *getcwd(char *buf, size_t len) {
|
||||
strncpy(buf, __cwd, len);
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__getpid
|
||||
pid_t _getpid(void)
|
||||
{
|
||||
return (pid_t)__set_errno(sceKernelGetThreadId());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__kill
|
||||
int _kill(pid_t pid, int sig)
|
||||
{
|
||||
return __set_errno(sceKernelDeleteThread((SceUID)pid));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__fork
|
||||
pid_t _fork(void)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return (pid_t) -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__wait
|
||||
pid_t _wait(int *unused)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return (pid_t) -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__sbrk
|
||||
#define TO_KB(value) (value * 1024)
|
||||
void * _sbrk(ptrdiff_t incr)
|
||||
{
|
||||
static void * heap_bottom = NULL;
|
||||
static void * heap_top = NULL;
|
||||
static void * heap_ptr = NULL;
|
||||
|
||||
sceKernelLockLwMutex(&__sbrk_mutex, 1, 0);
|
||||
|
||||
/* Has our heap been initialized? */
|
||||
if (heap_bottom == NULL) {
|
||||
/* No, initialize the heap. */
|
||||
SceSize heap_size = (SceSize) -1;
|
||||
|
||||
if (&sce_newlib_heap_kb_size != NULL) {
|
||||
heap_size = TO_KB(sce_newlib_heap_kb_size);
|
||||
} else if(&__pspsdk_is_prx != NULL) {
|
||||
heap_size = TO_KB(DEFAULT_PRX_HEAP_SIZE_KB);
|
||||
}
|
||||
|
||||
if ((int)heap_size < 0) {
|
||||
heap_size = sceKernelMaxFreeMemSize();
|
||||
if(&sce_newlib_heap_threshold_kb_size != NULL)
|
||||
heap_size -= TO_KB(sce_newlib_heap_threshold_kb_size);
|
||||
else
|
||||
heap_size -= TO_KB(DEFAULT_HEAP_THRESHOLD_SIZE_KB);
|
||||
}
|
||||
|
||||
if (heap_size != 0) {
|
||||
__psp_heap_blockid = sceKernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, "heap_block", PSP_SMEM_Low, heap_size, NULL);
|
||||
if (__psp_heap_blockid > 0) {
|
||||
heap_bottom = sceKernelGetBlockHeadAddr(__psp_heap_blockid);
|
||||
heap_ptr = heap_bottom;
|
||||
heap_top = (unsigned char *) heap_bottom + heap_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void * heap_addr = (void *) -1;
|
||||
void * next_heap_ptr = (void *) ((ptrdiff_t) heap_ptr + incr);
|
||||
if ((heap_bottom != NULL) && (next_heap_ptr >= heap_bottom) && (next_heap_ptr < heap_top)) {
|
||||
heap_addr = heap_ptr;
|
||||
heap_ptr = next_heap_ptr;
|
||||
}
|
||||
|
||||
sceKernelUnlockLwMutex(&__sbrk_mutex, 1);
|
||||
|
||||
return heap_addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__gettimeofday
|
||||
int _gettimeofday(struct timeval *tp, struct timezone *tzp)
|
||||
{
|
||||
return __set_errno(sceKernelLibcGettimeofday(tp, tzp));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__times
|
||||
clock_t _times(struct tms *buffer)
|
||||
{
|
||||
clock_t clk = sceKernelGetSystemTimeWide();
|
||||
|
||||
if (buffer != NULL) {
|
||||
buffer->tms_utime = clk;
|
||||
buffer->tms_stime = 0;
|
||||
buffer->tms_cutime = clk;
|
||||
buffer->tms_cstime = 0;
|
||||
}
|
||||
|
||||
return clk;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__internal_malloc_lock
|
||||
void _internal_malloc_lock(struct _reent *ptr)
|
||||
{
|
||||
sceKernelLockLwMutex(&__malloc_mutex, 1, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__internal_malloc_unlock
|
||||
void _internal_malloc_unlock(struct _reent *ptr)
|
||||
{
|
||||
sceKernelUnlockLwMutex(&__malloc_mutex, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Some POSIX functions that are missing in NEWLIB
|
||||
|
||||
#ifdef F_symlink
|
||||
int symlink(const char *path1, const char *path2)
|
||||
{
|
||||
return link(path1, path2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_truncate
|
||||
int truncate(const char *path, off_t length)
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
int fd;
|
||||
char buff[length];
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes_read = read(fd, &buff, length);
|
||||
close(fd);
|
||||
if (bytes_read < length) {
|
||||
errno = EFBIG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open (path, O_TRUNC|O_WRONLY);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
write(fd, &buff, length);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F__isatty
|
||||
int _isatty(int fd)
|
||||
{
|
||||
errno = ENOTTY;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_chmod
|
||||
int chmod(const char *pathname, mode_t mode)
|
||||
{
|
||||
// TODO: Implement proper functionality
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_fchmod
|
||||
int fchmod(int filedes, mode_t mode)
|
||||
{
|
||||
// TODO: Implement proper functionality
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_fchmodat
|
||||
int fchmodat(int fd, const char *path, mode_t mode, int flag)
|
||||
{
|
||||
// TODO: Implement proper functionality
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_pathconf
|
||||
long int pathconf(const char *path, int name) {
|
||||
// TODO: Implement proper functionality
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_readlink
|
||||
ssize_t readlink(const char *path, char *buf, size_t bufsiz) {
|
||||
// TODO: Implement proper functionality
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_utime
|
||||
struct utimbuf {
|
||||
time_t actime; /* Access time */
|
||||
time_t modtime; /* Modification time */
|
||||
};
|
||||
|
||||
int utime(const char *path, const struct utimbuf *times)
|
||||
{
|
||||
// TODO: Implement proper functionality
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_fchown
|
||||
int fchown(int fd, uid_t owner, gid_t group)
|
||||
{
|
||||
// TODO: Implement proper functionality
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_getentropy
|
||||
int getentropy(void *buffer, size_t length) {
|
||||
size_t i;
|
||||
SceKernelUtilsMt19937Context ctx;
|
||||
sceKernelUtilsMt19937Init(&ctx, time(NULL));
|
||||
uint8_t *source = (uint8_t *)buffer;
|
||||
for (i = 0; i < length; i++) {
|
||||
uint8_t rand_val = sceKernelUtilsMt19937UInt(&ctx) & 0xFF;
|
||||
source[i] = rand_val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -10,25 +10,38 @@
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
void _pspsdk_alloc_init();
|
||||
void _pspsdk_alloc_deinit();
|
||||
void _pspsdk_stdio_init();
|
||||
void _pspsdk_stdio_deinit();
|
||||
void _pspsdk_stdlib_init();
|
||||
void _pspsdk_stdlib_deinit();
|
||||
|
||||
__attribute__((weak, constructor))
|
||||
void _pspsdk_libc_init()
|
||||
{
|
||||
_pspsdk_alloc_init();
|
||||
_pspsdk_stdio_init();
|
||||
_pspsdk_stdlib_init();
|
||||
}
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
__attribute__((weak, destructor))
|
||||
void _pspsdk_libc_deinit()
|
||||
void __init_cwd(char *argv_0);
|
||||
void __timezone_update();
|
||||
void __fdman_init();
|
||||
void __init_mutex();
|
||||
|
||||
#ifdef F___psp_libc_init
|
||||
/* Note: This function is being called from crt0.c/crt0_prx.c.
|
||||
* It is a weak function because can be override by user program,
|
||||
* saving a lot of space in your binary, however you will loose
|
||||
all the basic libc operation
|
||||
*/
|
||||
__attribute__((weak))
|
||||
void __psp_libc_init(int argc, char *argv[])
|
||||
{
|
||||
_pspsdk_stdlib_deinit();
|
||||
_pspsdk_stdio_deinit();
|
||||
_pspsdk_alloc_deinit();
|
||||
(void) argc;
|
||||
|
||||
/* Initialize mutex used in malloc and fdman */
|
||||
__init_mutex();
|
||||
|
||||
/* Initialize filedescriptor management */
|
||||
__fdman_init();
|
||||
|
||||
/* Initialize cwd from this program's path */
|
||||
__init_cwd(argv[0]);
|
||||
|
||||
/* Initialize timezone */
|
||||
__timezone_update();
|
||||
}
|
||||
#endif
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* libcglue.c - Newlib-compatible system calls.
|
||||
*
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
* Copyright (c) 2005 Jim Paris <jim@jtan.com>
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <psptypes.h>
|
||||
#include <pspiofilemgr.h>
|
||||
#include <pspmodulemgr.h>
|
||||
#include <pspsysmem.h>
|
||||
#include <pspthreadman.h>
|
||||
#include <psputils.h>
|
||||
|
||||
/* These functions aren't exposed in any public headers, and they probably don't need to be. */
|
||||
int sceKernelStdin(void);
|
||||
int sceKernelStdout(void);
|
||||
int sceKernelStderr(void);
|
||||
|
||||
extern char * __psp_argv_0;
|
||||
extern int __psp_cwd_initialized;
|
||||
extern char __psp_cwd[MAXPATHLEN + 1];
|
||||
extern void __psp_init_cwd(void);
|
||||
extern int __psp_path_absolute(const char *in, char *out, int len);
|
||||
|
||||
/* If we're being built for PSPSDK's libc this function isn't defined. */
|
||||
#ifdef F_glue_gettimeofday
|
||||
int gettimeofday(struct timeval *tp, void *tzp)
|
||||
{
|
||||
return sceKernelLibcGettimeofday(tp, tzp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(F_clock) || defined(F_glue_clock)
|
||||
clock_t clock(void)
|
||||
{
|
||||
return sceKernelLibcClock();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(F_time) || defined(F_glue_time)
|
||||
time_t time(time_t *t)
|
||||
{
|
||||
return sceKernelLibcTime(t);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* PSP-compatible sbrk(). */
|
||||
#if defined(F__sbrk) || defined(F_glue__sbrk)
|
||||
|
||||
#define DEFAULT_PRX_HEAP_SIZE_KB 64
|
||||
|
||||
/* If defined it specifies the desired size of the heap, in KB. */
|
||||
extern unsigned int sce_newlib_heap_kb_size __attribute__((weak));
|
||||
extern int __pspsdk_is_prx __attribute__((weak));
|
||||
|
||||
/* UID of the memory block that represents the heap. */
|
||||
static SceUID __psp_heap_blockid;
|
||||
|
||||
void * _sbrk(ptrdiff_t incr)
|
||||
{
|
||||
static void * heap_bottom = NULL;
|
||||
static void * heap_top = NULL;
|
||||
static void * heap_ptr = NULL;
|
||||
|
||||
/* Has our heap been initialized? */
|
||||
if (heap_bottom == NULL) {
|
||||
/* No, initialize the heap. */
|
||||
SceSize heap_size = (SceSize) -1;
|
||||
|
||||
if (&sce_newlib_heap_kb_size != NULL) {
|
||||
heap_size = sce_newlib_heap_kb_size;
|
||||
} else if(&__pspsdk_is_prx != NULL) {
|
||||
heap_size = DEFAULT_PRX_HEAP_SIZE_KB;
|
||||
}
|
||||
|
||||
if (heap_size == (unsigned int) -1) {
|
||||
heap_size = sceKernelMaxFreeMemSize();
|
||||
} else {
|
||||
heap_size *= 1024;
|
||||
}
|
||||
|
||||
if (heap_size != 0) {
|
||||
__psp_heap_blockid = sceKernelAllocPartitionMemory(2, "block", PSP_SMEM_Low, heap_size, NULL);
|
||||
if (__psp_heap_blockid > 0) {
|
||||
heap_bottom = sceKernelGetBlockHeadAddr(__psp_heap_blockid);
|
||||
heap_ptr = heap_bottom;
|
||||
heap_top = (unsigned char *) heap_bottom + heap_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void * heap_addr = (void *) -1;
|
||||
void * next_heap_ptr = (void *) ((ptrdiff_t) heap_ptr + incr);
|
||||
if ((heap_bottom != NULL) && (next_heap_ptr >= heap_bottom) && (next_heap_ptr < heap_top)) {
|
||||
heap_addr = heap_ptr;
|
||||
heap_ptr = next_heap_ptr;
|
||||
}
|
||||
|
||||
return heap_addr;
|
||||
}
|
||||
|
||||
/* Free the heap. */
|
||||
int __psp_free_heap(void)
|
||||
{
|
||||
if (__psp_heap_blockid > 0) {
|
||||
return sceKernelFreePartitionMemory(__psp_heap_blockid);
|
||||
}
|
||||
|
||||
return __psp_heap_blockid;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(F__exit) || defined(F_glue__exit)
|
||||
extern int sce_newlib_nocreate_thread_in_start __attribute__((weak));
|
||||
|
||||
extern int __psp_free_heap(void);
|
||||
|
||||
void _exit(int status)
|
||||
{
|
||||
if (&sce_newlib_nocreate_thread_in_start != NULL) {
|
||||
/* Free the heap created by _sbrk(). */
|
||||
__psp_free_heap();
|
||||
|
||||
sceKernelSelfStopUnloadModule(1, 0, NULL);
|
||||
} else {
|
||||
if (status == 0) {
|
||||
/* Free the heap created by _sbrk(). */
|
||||
__psp_free_heap();
|
||||
}
|
||||
|
||||
sceKernelExitThread(status);
|
||||
}
|
||||
|
||||
while (1) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* newlib's errno.h wants a function that returns a pointer to errno. */
|
||||
#ifdef F_glue___errno
|
||||
#undef errno
|
||||
|
||||
int errno;
|
||||
|
||||
/* TODO: Should this be made reentrant (wrapping interrupt disable/enable
|
||||
around it should do it)? */
|
||||
int * __errno(void)
|
||||
{
|
||||
return &errno;
|
||||
}
|
||||
#endif
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* malloc.h
|
||||
*
|
||||
* Copyright (c) 2002-2004 PS2DEV
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MALLOC_H
|
||||
#define _MALLOC_H
|
||||
|
||||
#include <pspkernel.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* stdlib/malloc */
|
||||
void * malloc(size_t size);
|
||||
void * realloc(void *ptr, size_t size);
|
||||
void * calloc(size_t n, size_t size);
|
||||
void * memalign(size_t align, size_t size);
|
||||
void free(void * ptr);
|
||||
|
||||
/* Memory walkers. Used for debugging/profiling purposes. */
|
||||
void * __mem_walk_begin(void);
|
||||
void __mem_walk_read(void * token, u32 * size, void ** ptr, int * valid);
|
||||
void * __mem_walk_inc(void * token);
|
||||
int __mem_walk_end(void * token);
|
||||
|
||||
/* Example of use:
|
||||
|
||||
void * i;
|
||||
|
||||
for (i = __mem_walk_begin(); !__mem_walk_end(i); i = __mem_walk_inc(i)) {
|
||||
u32 block_size;
|
||||
void * block_ptr;
|
||||
int valid;
|
||||
|
||||
__mem_walk_read(i, &block_size, &block_ptr, &valid);
|
||||
if (!valid) {
|
||||
fprintf(stderr, "Block at token %p is invalid.\n", i);
|
||||
break;
|
||||
}
|
||||
printf("Block at token %p points at a memory block of %i bytes at %p.\n", i, block_size, block_ptr);
|
||||
}
|
||||
|
||||
note that 'valid' will be always true if DEBUG_ALLOC was not defined when alloc.c got compiled.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _MALLOC_H
|
||||
|
||||
45
src/libc/mutexman.c
Normal file
45
src/libc/mutexman.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* init.c - The global init/deinit code for our crt0.
|
||||
*
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <pspthreadman.h>
|
||||
|
||||
#ifdef F___malloc_mutex
|
||||
SceLwMutexWorkarea __malloc_mutex;
|
||||
#else
|
||||
extern SceLwMutexWorkarea __malloc_mutex;
|
||||
#endif
|
||||
|
||||
#ifdef F___sbrk_mutex
|
||||
SceLwMutexWorkarea __sbrk_mutex;
|
||||
#else
|
||||
extern SceLwMutexWorkarea __sbrk_mutex;
|
||||
#endif
|
||||
|
||||
#ifdef F___fdman_mutex
|
||||
SceLwMutexWorkarea __fdman_mutex;
|
||||
#else
|
||||
extern SceLwMutexWorkarea __fdman_mutex;
|
||||
#endif
|
||||
|
||||
#ifdef F___init_mutex
|
||||
/* Create mutex used for making thread safe mallock and get fd */
|
||||
void __init_mutex()
|
||||
{
|
||||
sceKernelCreateLwMutex(&__malloc_mutex, "malloc mutex", 0, 0, 0);
|
||||
sceKernelCreateLwMutex(&__sbrk_mutex, "sbrk mutex", 0, 0, 0);
|
||||
sceKernelCreateLwMutex(&__fdman_mutex, "fdman mutex", 0, 0, 0);
|
||||
}
|
||||
#endif
|
||||
115
src/libc/netdb.c
Normal file
115
src/libc/netdb.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* netdb.c - Simple gethostbyname and gethostbyaddr replacements using the resolver lib
|
||||
*
|
||||
* Copyright (c) 2021 Francisco Javier Trujillo Mata <fjtrujy@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <pspkerneltypes.h>
|
||||
#include <pspnet_resolver.h>
|
||||
|
||||
#define MAX_NAME 512
|
||||
|
||||
#ifdef F_h_errno
|
||||
int h_errno = NETDB_SUCCESS;
|
||||
#endif
|
||||
|
||||
#ifdef F_gethostbyaddr
|
||||
struct hostent *gethostbyaddr(const void *addr, int len, int type)
|
||||
{
|
||||
static struct hostent ent;
|
||||
static char * aliases[1] = { NULL };
|
||||
char buf[1024];
|
||||
static char sname[MAX_NAME] = "";
|
||||
static struct in_addr saddr = { 0 };
|
||||
static char *addrlist[2] = { (char *) &saddr, NULL };
|
||||
int rid;
|
||||
int err;
|
||||
|
||||
if((len != sizeof(struct in_addr)) || (type != AF_INET) || (addr == NULL))
|
||||
{
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(&saddr, addr, len);
|
||||
|
||||
if(sceNetResolverCreate(&rid, buf, sizeof(buf)) < 0)
|
||||
{
|
||||
h_errno = NO_RECOVERY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = sceNetResolverStartAtoN(rid, &saddr, sname, sizeof(sname), 2, 3);
|
||||
sceNetResolverStop(rid);
|
||||
sceNetResolverDelete(rid);
|
||||
if(err < 0)
|
||||
{
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ent.h_name = sname;
|
||||
ent.h_aliases = aliases;
|
||||
ent.h_addrtype = AF_INET;
|
||||
ent.h_length = sizeof(struct in_addr);
|
||||
ent.h_addr_list = addrlist;
|
||||
ent.h_addr = (char *) &saddr;
|
||||
|
||||
return &ent;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_gethostbyname
|
||||
struct hostent *gethostbyname(const char *name)
|
||||
{
|
||||
static struct hostent ent;
|
||||
char buf[1024];
|
||||
static char sname[MAX_NAME] = "";
|
||||
static struct in_addr saddr = { 0 };
|
||||
static char *addrlist[2] = { (char *) &saddr, NULL };
|
||||
int rid;
|
||||
|
||||
if(sceNetInetInetAton(name, &saddr) == 0)
|
||||
{
|
||||
int err;
|
||||
|
||||
if(sceNetResolverCreate(&rid, buf, sizeof(buf)) < 0)
|
||||
{
|
||||
h_errno = NO_RECOVERY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = sceNetResolverStartNtoA(rid, name, &saddr, 2, 3);
|
||||
sceNetResolverDelete(rid);
|
||||
if(err < 0)
|
||||
{
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
snprintf(sname, MAX_NAME, "%s", name);
|
||||
ent.h_name = sname;
|
||||
ent.h_aliases = 0;
|
||||
ent.h_addrtype = AF_INET;
|
||||
ent.h_length = sizeof(struct in_addr);
|
||||
ent.h_addr_list = addrlist;
|
||||
ent.h_addr = (char *) &saddr;
|
||||
|
||||
return &ent;
|
||||
}
|
||||
|
||||
#endif
|
||||
36
src/libc/netdb.h
Normal file
36
src/libc/netdb.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* Simple gethostbyname and gethostbyaddr replacements, note not thread safe */
|
||||
#ifndef __NETDB_H__
|
||||
#define __NETDB_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NETDB_INTERNAL -1 /* see errno */
|
||||
#define NETDB_SUCCESS 0 /* no problem */
|
||||
#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */
|
||||
#define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL */
|
||||
#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
|
||||
#define NO_DATA 4 /* Valid name, no data record of requested type */
|
||||
#define NO_ADDRESS NO_DATA /* no address, look for MX record */
|
||||
|
||||
extern int h_errno;
|
||||
|
||||
struct hostent
|
||||
{
|
||||
char *h_name;
|
||||
char **h_aliases;
|
||||
int h_addrtype;
|
||||
int h_length;
|
||||
char **h_addr_list;
|
||||
char *h_addr;
|
||||
};
|
||||
|
||||
struct hostent *gethostbyaddr(const void *addr, int len, int type);
|
||||
struct hostent *gethostbyname(const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
280
src/libc/netinet/in.h
Normal file
280
src/libc/netinet/in.h
Normal file
@@ -0,0 +1,280 @@
|
||||
/* $NetBSD: in.h,v 1.71 2005/08/05 09:21:25 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)in.h 8.3 (Berkeley) 1/3/94
|
||||
*/
|
||||
|
||||
/*
|
||||
* Constants and structures defined by the internet system,
|
||||
* Per RFC 790, September 1981, and numerous additions.
|
||||
*/
|
||||
|
||||
#ifndef _NETINET_IN_H_
|
||||
#define _NETINET_IN_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
typedef uint32_t in_addr_t;
|
||||
typedef uint16_t in_port_t;
|
||||
|
||||
/*
|
||||
* Protocols
|
||||
*/
|
||||
#define IPPROTO_IP 0 /* dummy for IP */
|
||||
#define IPPROTO_HOPOPTS 0 /* IP6 hop-by-hop options */
|
||||
#define IPPROTO_ICMP 1 /* control message protocol */
|
||||
#define IPPROTO_IGMP 2 /* group mgmt protocol */
|
||||
#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */
|
||||
#define IPPROTO_IPV4 4 /* IP header */
|
||||
#define IPPROTO_IPIP 4 /* IP inside IP */
|
||||
#define IPPROTO_TCP 6 /* tcp */
|
||||
#define IPPROTO_EGP 8 /* exterior gateway protocol */
|
||||
#define IPPROTO_PUP 12 /* pup */
|
||||
#define IPPROTO_UDP 17 /* user datagram protocol */
|
||||
#define IPPROTO_IDP 22 /* xns idp */
|
||||
#define IPPROTO_TP 29 /* tp-4 w/ class negotiation */
|
||||
#define IPPROTO_IPV6 41 /* IP6 header */
|
||||
#define IPPROTO_ROUTING 43 /* IP6 routing header */
|
||||
#define IPPROTO_FRAGMENT 44 /* IP6 fragmentation header */
|
||||
#define IPPROTO_RSVP 46 /* resource reservation */
|
||||
#define IPPROTO_GRE 47 /* GRE encaps RFC 1701 */
|
||||
#define IPPROTO_ESP 50 /* encap. security payload */
|
||||
#define IPPROTO_AH 51 /* authentication header */
|
||||
#define IPPROTO_MOBILE 55 /* IP Mobility RFC 2004 */
|
||||
#define IPPROTO_IPV6_ICMP 58 /* IPv6 ICMP */
|
||||
#define IPPROTO_ICMPV6 58 /* ICMP6 */
|
||||
#define IPPROTO_NONE 59 /* IP6 no next header */
|
||||
#define IPPROTO_DSTOPTS 60 /* IP6 destination option */
|
||||
#define IPPROTO_EON 80 /* ISO cnlp */
|
||||
#define IPPROTO_ETHERIP 97 /* Ethernet-in-IP */
|
||||
#define IPPROTO_ENCAP 98 /* encapsulation header */
|
||||
#define IPPROTO_PIM 103 /* Protocol indep. multicast */
|
||||
#define IPPROTO_IPCOMP 108 /* IP Payload Comp. Protocol */
|
||||
#define IPPROTO_VRRP 112 /* VRRP RFC 2338 */
|
||||
|
||||
#define IPPROTO_RAW 255 /* raw IP packet */
|
||||
#define IPPROTO_MAX 256
|
||||
|
||||
/* last return value of *_input(), meaning "all job for this pkt is done". */
|
||||
#define IPPROTO_DONE 257
|
||||
|
||||
/* sysctl placeholder for (FAST_)IPSEC */
|
||||
#define CTL_IPPROTO_IPSEC 258
|
||||
|
||||
|
||||
/*
|
||||
* Local port number conventions:
|
||||
*
|
||||
* Ports < IPPORT_RESERVED are reserved for privileged processes (e.g. root),
|
||||
* unless a kernel is compiled with IPNOPRIVPORTS defined.
|
||||
*
|
||||
* When a user does a bind(2) or connect(2) with a port number of zero,
|
||||
* a non-conflicting local port address is chosen.
|
||||
*
|
||||
* The default range is IPPORT_ANONMIN to IPPORT_ANONMAX, although
|
||||
* that is settable by sysctl(3); net.inet.ip.anonportmin and
|
||||
* net.inet.ip.anonportmax respectively.
|
||||
*
|
||||
* A user may set the IPPROTO_IP option IP_PORTRANGE to change this
|
||||
* default assignment range.
|
||||
*
|
||||
* The value IP_PORTRANGE_DEFAULT causes the default behavior.
|
||||
*
|
||||
* The value IP_PORTRANGE_HIGH is the same as IP_PORTRANGE_DEFAULT,
|
||||
* and exists only for FreeBSD compatibility purposes.
|
||||
*
|
||||
* The value IP_PORTRANGE_LOW changes the range to the "low" are
|
||||
* that is (by convention) restricted to privileged processes.
|
||||
* This convention is based on "vouchsafe" principles only.
|
||||
* It is only secure if you trust the remote host to restrict these ports.
|
||||
* The range is IPPORT_RESERVEDMIN to IPPORT_RESERVEDMAX.
|
||||
*/
|
||||
|
||||
#define IPPORT_RESERVED 1024
|
||||
#define IPPORT_ANONMIN 49152
|
||||
#define IPPORT_ANONMAX 65535
|
||||
#define IPPORT_RESERVEDMIN 600
|
||||
#define IPPORT_RESERVEDMAX (IPPORT_RESERVED-1)
|
||||
|
||||
/*
|
||||
* Internet address (a structure for historical reasons)
|
||||
*/
|
||||
struct in_addr {
|
||||
in_addr_t s_addr;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define __IPADDR(x) ((uint32_t)(x))
|
||||
|
||||
#define IN_CLASSA(i) (((uint32_t)(i) & __IPADDR(0x80000000)) == \
|
||||
__IPADDR(0x00000000))
|
||||
#define IN_CLASSA_NET __IPADDR(0xff000000)
|
||||
#define IN_CLASSA_NSHIFT 24
|
||||
#define IN_CLASSA_HOST __IPADDR(0x00ffffff)
|
||||
#define IN_CLASSA_MAX 128
|
||||
|
||||
#define IN_CLASSB(i) (((uint32_t)(i) & __IPADDR(0xc0000000)) == \
|
||||
__IPADDR(0x80000000))
|
||||
#define IN_CLASSB_NET __IPADDR(0xffff0000)
|
||||
#define IN_CLASSB_NSHIFT 16
|
||||
#define IN_CLASSB_HOST __IPADDR(0x0000ffff)
|
||||
#define IN_CLASSB_MAX 65536
|
||||
|
||||
#define IN_CLASSC(i) (((uint32_t)(i) & __IPADDR(0xe0000000)) == \
|
||||
__IPADDR(0xc0000000))
|
||||
#define IN_CLASSC_NET __IPADDR(0xffffff00)
|
||||
#define IN_CLASSC_NSHIFT 8
|
||||
#define IN_CLASSC_HOST __IPADDR(0x000000ff)
|
||||
|
||||
#define IN_CLASSD(i) (((uint32_t)(i) & __IPADDR(0xf0000000)) == \
|
||||
__IPADDR(0xe0000000))
|
||||
/* These ones aren't really net and host fields, but routing needn't know. */
|
||||
#define IN_CLASSD_NET __IPADDR(0xf0000000)
|
||||
#define IN_CLASSD_NSHIFT 28
|
||||
#define IN_CLASSD_HOST __IPADDR(0x0fffffff)
|
||||
#define IN_MULTICAST(i) IN_CLASSD(i)
|
||||
|
||||
#define IN_EXPERIMENTAL(i) (((uint32_t)(i) & __IPADDR(0xf0000000)) == \
|
||||
__IPADDR(0xf0000000))
|
||||
#define IN_BADCLASS(i) (((uint32_t)(i) & __IPADDR(0xf0000000)) == \
|
||||
__IPADDR(0xf0000000))
|
||||
|
||||
#define IN_LOCAL_GROUP(i) (((uint32_t)(i) & __IPADDR(0xffffff00)) == \
|
||||
__IPADDR(0xe0000000))
|
||||
|
||||
#define INADDR_ANY __IPADDR(0x00000000)
|
||||
#define INADDR_LOOPBACK __IPADDR(0x7f000001)
|
||||
#define INADDR_BROADCAST __IPADDR(0xffffffff) /* must be masked */
|
||||
|
||||
#define INADDR_UNSPEC_GROUP __IPADDR(0xe0000000) /* 224.0.0.0 */
|
||||
#define INADDR_ALLHOSTS_GROUP __IPADDR(0xe0000001) /* 224.0.0.1 */
|
||||
#define INADDR_ALLRTRS_GROUP __IPADDR(0xe0000002) /* 224.0.0.2 */
|
||||
#define INADDR_MAX_LOCAL_GROUP __IPADDR(0xe00000ff) /* 224.0.0.255 */
|
||||
|
||||
#define IN_LOOPBACKNET 127 /* official! */
|
||||
|
||||
/*
|
||||
* Socket address, internet style.
|
||||
*/
|
||||
struct sockaddr_in {
|
||||
uint8_t sin_len;
|
||||
sa_family_t sin_family;
|
||||
in_port_t sin_port;
|
||||
struct in_addr sin_addr;
|
||||
int8_t sin_zero[8];
|
||||
};
|
||||
|
||||
#define INET_ADDRSTRLEN 16
|
||||
|
||||
/*
|
||||
* Structure used to describe IP options.
|
||||
* Used to store options internally, to pass them to a process,
|
||||
* or to restore options retrieved earlier.
|
||||
* The ip_dst is used for the first-hop gateway when using a source route
|
||||
* (this gets put into the header proper).
|
||||
*/
|
||||
struct ip_opts {
|
||||
struct in_addr ip_dst; /* first hop, 0 w/o src rt */
|
||||
#if defined(__cplusplus)
|
||||
int8_t Ip_opts[40]; /* actually variable in size */
|
||||
#else
|
||||
int8_t ip_opts[40]; /* actually variable in size */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Options for use with [gs]etsockopt at the IP level.
|
||||
* First word of comment is data type; bool is stored in int.
|
||||
*/
|
||||
#define IP_OPTIONS 1 /* buf/ip_opts; set/get IP options */
|
||||
#define IP_HDRINCL 2 /* int; header is included with data */
|
||||
#define IP_TOS 3 /* int; IP type of service and preced. */
|
||||
#define IP_TTL 4 /* int; IP time to live */
|
||||
#define IP_RECVOPTS 5 /* bool; receive all IP opts w/dgram */
|
||||
#define IP_RECVRETOPTS 6 /* bool; receive IP opts for response */
|
||||
#define IP_RECVDSTADDR 7 /* bool; receive IP dst addr w/dgram */
|
||||
#define IP_RETOPTS 8 /* ip_opts; set/get IP options */
|
||||
#define IP_MULTICAST_IF 9 /* in_addr; set/get IP multicast i/f */
|
||||
#define IP_MULTICAST_TTL 10 /* u_char; set/get IP multicast ttl */
|
||||
#define IP_MULTICAST_LOOP 11 /* u_char; set/get IP multicast loopback */
|
||||
#define IP_ADD_MEMBERSHIP 12 /* ip_mreq; add an IP group membership */
|
||||
#define IP_DROP_MEMBERSHIP 13 /* ip_mreq; drop an IP group membership */
|
||||
#define IP_PORTRANGE 19 /* int; range to use for ephemeral port */
|
||||
#define IP_RECVIF 20 /* bool; receive reception if w/dgram */
|
||||
#define IP_ERRORMTU 21 /* int; get MTU of last xmit = EMSGSIZE */
|
||||
#if 1 /*IPSEC*/
|
||||
#define IP_IPSEC_POLICY 22 /* struct; get/set security policy */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Defaults and limits for options
|
||||
*/
|
||||
#define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */
|
||||
#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
|
||||
#define IP_MAX_MEMBERSHIPS 20 /* per socket; must fit in one mbuf */
|
||||
|
||||
/*
|
||||
* Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP.
|
||||
*/
|
||||
struct ip_mreq {
|
||||
struct in_addr imr_multiaddr; /* IP multicast address of group */
|
||||
struct in_addr imr_interface; /* local IP address of interface */
|
||||
};
|
||||
|
||||
/*
|
||||
* Argument for IP_PORTRANGE:
|
||||
* - which range to search when port is unspecified at bind() or connect()
|
||||
*/
|
||||
#define IP_PORTRANGE_DEFAULT 0 /* default range */
|
||||
#define IP_PORTRANGE_HIGH 1 /* same as DEFAULT (FreeBSD compat) */
|
||||
#define IP_PORTRANGE_LOW 2 /* use privileged range */
|
||||
|
||||
|
||||
#if 0
|
||||
// FIXME: These are optimized (one instruction), but currently not part of psp-gcc
|
||||
#define ntohs(x) __builtin_allegrex_wsbh(x)
|
||||
#define ntohl(x) __builtin_allegrex_wsbw(x)
|
||||
#define htons(x) __builtin_allegrex_wsbh(x)
|
||||
#define htonl(x) __builtin_allegrex_wsbw(x)
|
||||
#else
|
||||
#define ntohs(x) __builtin_bswap16(x)
|
||||
#define ntohl(x) __builtin_bswap32(x)
|
||||
#define htons(x) __builtin_bswap16(x)
|
||||
#define htonl(x) __builtin_bswap32(x)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_NETINET_IN_H_ */
|
||||
12
src/libc/netinet/tcp.h
Normal file
12
src/libc/netinet/tcp.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef __NETINET_TCP_H__
|
||||
#define __NETINET_TCP_H__
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define SOL_TCP IPPROTO_TCP
|
||||
|
||||
/* Socket options */
|
||||
#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
|
||||
#define TCP_MAXSEG 0x02 /* set maximum segment size */
|
||||
|
||||
#endif
|
||||
324
src/libc/pipe.c
Normal file
324
src/libc/pipe.c
Normal file
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* PSP Software Development Kit - http://www.pspdev.org
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* pipe.c - Socket wrappers to provide similar functions to normal unix
|
||||
*
|
||||
* Copyright (c) 2006 Rafael Cabezas <rafpsp@gmail.com>
|
||||
*
|
||||
* - 20070630 Alper Akcan "anhanguera" <distchx@yahoo.com>
|
||||
* [non]blocking read/write() fix
|
||||
* illegal size fix for read/write()
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/syslimits.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <psptypes.h>
|
||||
#include <pspthreadman.h>
|
||||
#include <pspmodulemgr.h>
|
||||
#include <pspkerror.h>
|
||||
#include "fdman.h"
|
||||
|
||||
int __set_errno(int code);
|
||||
|
||||
#ifdef F___pipe_peekmsgsize
|
||||
/* Pipe functions */
|
||||
/* Returns how many bytes are in the pipe -- waiting to be read */
|
||||
size_t __pipe_peekmsgsize(int fd)
|
||||
{
|
||||
SceKernelMppInfo info;
|
||||
info.size = sizeof(info);
|
||||
|
||||
if (!__IS_FD_OF_TYPE(fd, __DESCRIPTOR_TYPE_PIPE)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sceKernelReferMsgPipeStatus(__descriptormap[fd]->descriptor, &info) == 0) {
|
||||
return (info.bufSize - info.freeSize);
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
size_t __pipe_peekmsgsize(int fd);
|
||||
#endif
|
||||
|
||||
#ifdef D_pipe
|
||||
int pipe(int fildes[2])
|
||||
{
|
||||
static int iIndex = 0;
|
||||
char name[32];
|
||||
iIndex++;
|
||||
|
||||
sprintf(name, "__pipe_%02d", iIndex);
|
||||
|
||||
SceUID uid = sceKernelCreateMsgPipe(name, PSP_MEMORY_PARTITION_USER, 0, (void *)PIPE_BUF, NULL);
|
||||
|
||||
if (uid >= 0) {
|
||||
fildes[0] = __fdman_get_new_descriptor();
|
||||
if (fildes[0] != -1) {
|
||||
__descriptormap[fildes[0]]->descriptor = uid;
|
||||
__descriptormap[fildes[0]]->type = __DESCRIPTOR_TYPE_PIPE;
|
||||
}
|
||||
else {
|
||||
sceKernelDeleteMsgPipe(uid);
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fildes[1] = __fdman_get_dup_descriptor(fildes[0]);
|
||||
if (fildes[1] != -1) {
|
||||
__descriptormap[fildes[1]]->descriptor = uid;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
sceKernelDeleteMsgPipe(uid);
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F___pipe_close
|
||||
int __pipe_close(int fd)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(fd, __DESCRIPTOR_TYPE_PIPE)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if ( __descriptormap[fd]->ref_count == 1 ) {
|
||||
/**
|
||||
* Delete a message pipe
|
||||
*
|
||||
* @param uid - The UID of the pipe
|
||||
*
|
||||
* @return 0 on success, < 0 on error
|
||||
*/
|
||||
ret = sceKernelDeleteMsgPipe(__descriptormap[fd]->descriptor);
|
||||
}
|
||||
|
||||
__fdman_release_descriptor(fd);
|
||||
|
||||
if(ret < 0) {
|
||||
return __set_errno(ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F___pipe_nonblocking_read
|
||||
int __pipe_nonblocking_read(int fd, void *buf, size_t len)
|
||||
{
|
||||
int ret;
|
||||
int sceuid;
|
||||
int size;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(fd, __DESCRIPTOR_TYPE_PIPE)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceuid = __descriptormap[fd]->descriptor;
|
||||
|
||||
size = __pipe_peekmsgsize(fd);
|
||||
if (size > 0) {
|
||||
if (size < len) {
|
||||
len = size;
|
||||
}
|
||||
}
|
||||
else if (size == 0) {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive a message from a pipe
|
||||
*
|
||||
* @param uid - The UID of the pipe
|
||||
* @param message - Pointer to the message
|
||||
* @param size - Size of the message
|
||||
* @param unk1 - Unknown
|
||||
* @param unk2 - Unknown
|
||||
* @param timeout - Timeout for receive
|
||||
*
|
||||
* @return 0 on success, < 0 on error
|
||||
*/
|
||||
ret = sceKernelTryReceiveMsgPipe(sceuid, buf, len, 0, 0);
|
||||
|
||||
if (ret == 0) {/* Success - Data */
|
||||
return len;
|
||||
}
|
||||
else if (ret == SCE_KERNEL_ERROR_MPP_EMPTY) {/* No data */
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
else {/* Error */
|
||||
return __set_errno(ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F___pipe_read
|
||||
int __pipe_read(int fd, void *buf, size_t len)
|
||||
{
|
||||
int ret;
|
||||
int sceuid;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(fd, __DESCRIPTOR_TYPE_PIPE)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceuid = __descriptormap[fd]->descriptor;
|
||||
|
||||
#if 0
|
||||
int size;
|
||||
|
||||
/* we should block until there is some data (or maybe for enough data),
|
||||
* peeking the msg size should be only for nonblocking reads
|
||||
*/
|
||||
size = __pipe_peekmsgsize(fd);
|
||||
if (size > 0) {
|
||||
if (size < len) {
|
||||
len = size;
|
||||
}
|
||||
}
|
||||
else {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
/* if len is greater than PIPE_BUF then, MsgPipe functions returns
|
||||
* SCE_KERNEL_ERROR_ILLEGAL_SIZE, but it should read at least
|
||||
* PIPE_BUF bytes, and return the number of bytes read.
|
||||
*/
|
||||
if (len > PIPE_BUF) {
|
||||
len = PIPE_BUF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive a message from a pipe
|
||||
*
|
||||
* @param uid - The UID of the pipe
|
||||
* @param message - Pointer to the message
|
||||
* @param size - Size of the message
|
||||
* @param unk1 - Unknown
|
||||
* @param unk2 - Unknown
|
||||
* @param timeout - Timeout for receive
|
||||
*
|
||||
* @return 0 on success, < 0 on error
|
||||
*/
|
||||
ret = sceKernelReceiveMsgPipe(sceuid, buf, len, 0, NULL, NULL);
|
||||
|
||||
if (ret == 0) {/* Success - Data */
|
||||
return len;
|
||||
}
|
||||
else {/* Error */
|
||||
return __set_errno(ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F___pipe_write
|
||||
int __pipe_write(int fd, const void *buf, size_t len)
|
||||
{
|
||||
int ret;
|
||||
int sceuid;
|
||||
char *cbuf;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(fd, __DESCRIPTOR_TYPE_PIPE)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceuid = __descriptormap[fd]->descriptor;
|
||||
|
||||
/* if len is greater than PIPE_BUF then, MsgPipe functions returns
|
||||
* SCE_KERNEL_ERROR_ILLEGAL_SIZE, but it should write at least
|
||||
* PIPE_BUF bytes, and return the number of bytes written.
|
||||
*/
|
||||
if (len > PIPE_BUF) {
|
||||
len = PIPE_BUF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to a pipe
|
||||
*
|
||||
* @param uid - The UID of the pipe
|
||||
* @param message - Pointer to the message
|
||||
* @param size - Size of the message
|
||||
* @param unk1 - Unknown
|
||||
* @param unk2 - Unknown
|
||||
* @param timeout - Timeout for send
|
||||
*
|
||||
* @return 0 on success, < 0 on error
|
||||
*/
|
||||
cbuf = (char *)buf;
|
||||
ret = sceKernelSendMsgPipe(sceuid, cbuf, len, 0, NULL, NULL);
|
||||
if (ret == 0) {/* Success - Data */
|
||||
return len;
|
||||
}
|
||||
else {/* Error */
|
||||
return __set_errno(ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F___pipe_nonblocking_write
|
||||
int __pipe_nonblocking_write(int fd, const void *buf, size_t len)
|
||||
{
|
||||
int ret;
|
||||
int sceuid;
|
||||
char *cbuf;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(fd, __DESCRIPTOR_TYPE_PIPE)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceuid = __descriptormap[fd]->descriptor;
|
||||
|
||||
/* if len is greater than PIPE_BUF then, MsgPipe functions returns
|
||||
* SCE_KERNEL_ERROR_ILLEGAL_SIZE, but it should write at least
|
||||
* PIPE_BUF bytes, and return the number of bytes written.
|
||||
*/
|
||||
if (len > PIPE_BUF) {
|
||||
len = PIPE_BUF;
|
||||
}
|
||||
|
||||
cbuf = (char *)buf;
|
||||
ret = sceKernelTrySendMsgPipe(sceuid, cbuf, len, 0, 0);
|
||||
|
||||
if (ret == 0) {/* Success - Data */
|
||||
return len;
|
||||
}
|
||||
else if (ret == SCE_KERNEL_ERROR_MPP_FULL) {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
else {/* Error */
|
||||
return __set_errno(ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
176
src/libc/qsort.c
176
src/libc/qsort.c
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* qsort.c - QSort algorithm implementation.
|
||||
*
|
||||
* Copyright (c) 1992, 1993 The Regents of the University of California.
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef int cmp_t(const void *, const void *);
|
||||
static __inline char *med3(char *, char *, char *, cmp_t *, void *);
|
||||
static __inline void swapfunc(char *, char *, int, int);
|
||||
|
||||
#define min(a, b) (a) < (b) ? (a) : (b)
|
||||
|
||||
/*
|
||||
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
|
||||
*/
|
||||
#define swapcode(TYPE, parmi, parmj, n) { \
|
||||
long i = (n) / sizeof (TYPE); \
|
||||
register TYPE *pi = (TYPE *) (parmi); \
|
||||
register TYPE *pj = (TYPE *) (parmj); \
|
||||
do { \
|
||||
register TYPE t = *pi; \
|
||||
*pi++ = *pj; \
|
||||
*pj++ = t; \
|
||||
} while (--i > 0); \
|
||||
}
|
||||
|
||||
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
|
||||
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
|
||||
|
||||
static __inline void
|
||||
swapfunc(char *a, char *b, int n, int swaptype)
|
||||
{
|
||||
if(swaptype <= 1)
|
||||
swapcode(long, a, b, n)
|
||||
else
|
||||
swapcode(char, a, b, n)
|
||||
}
|
||||
|
||||
#define swap(a, b) \
|
||||
if (swaptype == 0) { \
|
||||
long t = *(long *)(a); \
|
||||
*(long *)(a) = *(long *)(b); \
|
||||
*(long *)(b) = t; \
|
||||
} else \
|
||||
swapfunc(a, b, es, swaptype)
|
||||
|
||||
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
|
||||
|
||||
#define CMP(t, x, y) (cmp((x), (y)))
|
||||
|
||||
static __inline char *
|
||||
med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk
|
||||
)
|
||||
{
|
||||
return CMP(thunk, a, b) < 0 ?
|
||||
(CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
|
||||
:(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
|
||||
}
|
||||
|
||||
#define thunk NULL
|
||||
void
|
||||
qsort(void *a, size_t n, size_t es, cmp_t *cmp)
|
||||
{
|
||||
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
|
||||
int d, r, swaptype, swap_cnt;
|
||||
|
||||
loop: SWAPINIT(a, es);
|
||||
swap_cnt = 0;
|
||||
if (n < 7) {
|
||||
for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
|
||||
for (pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
|
||||
pl -= es)
|
||||
swap(pl, pl - es);
|
||||
return;
|
||||
}
|
||||
pm = (char *)a + (n / 2) * es;
|
||||
if (n > 7) {
|
||||
pl = a;
|
||||
pn = (char *)a + (n - 1) * es;
|
||||
if (n > 40) {
|
||||
d = (n / 8) * es;
|
||||
pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
|
||||
pm = med3(pm - d, pm, pm + d, cmp, thunk);
|
||||
pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
|
||||
}
|
||||
pm = med3(pl, pm, pn, cmp, thunk);
|
||||
}
|
||||
swap(a, pm);
|
||||
pa = pb = (char *)a + es;
|
||||
|
||||
pc = pd = (char *)a + (n - 1) * es;
|
||||
for (;;) {
|
||||
while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) {
|
||||
if (r == 0) {
|
||||
swap_cnt = 1;
|
||||
swap(pa, pb);
|
||||
pa += es;
|
||||
}
|
||||
pb += es;
|
||||
}
|
||||
while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) {
|
||||
if (r == 0) {
|
||||
swap_cnt = 1;
|
||||
swap(pc, pd);
|
||||
pd -= es;
|
||||
}
|
||||
pc -= es;
|
||||
}
|
||||
if (pb > pc)
|
||||
break;
|
||||
swap(pb, pc);
|
||||
swap_cnt = 1;
|
||||
pb += es;
|
||||
pc -= es;
|
||||
}
|
||||
if (swap_cnt == 0) { /* Switch to insertion sort */
|
||||
for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
|
||||
for (pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
|
||||
pl -= es)
|
||||
swap(pl, pl - es);
|
||||
return;
|
||||
}
|
||||
|
||||
pn = (char *)a + n * es;
|
||||
r = min(pa - (char *)a, pb - pa);
|
||||
vecswap(a, pb - r, r);
|
||||
r = min(pd - pc, pn - pd - es);
|
||||
vecswap(pb, pn - r, r);
|
||||
if ((r = pb - pa) > es)
|
||||
qsort(a, r / es, es, cmp);
|
||||
if ((r = pd - pc) > es) {
|
||||
/* Iterate rather than recurse to save stack space */
|
||||
a = pn - r;
|
||||
n = r / es;
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
200
src/libc/select.c
Normal file
200
src/libc/select.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* PSP Software Development Kit - http://www.pspdev.org
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* select.c - Socket wrappers to provide similar functions to normal unix
|
||||
*
|
||||
* Copyright (c) 2006 Rafael Cabezas <rafpsp@gmail.com>
|
||||
*
|
||||
* - 20070701 Alper Akcan "anhanguera" <distchx@yahoo.com>
|
||||
* select EBADF fix
|
||||
*
|
||||
*/
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/select.h>
|
||||
#include <psptypes.h>
|
||||
#include <pspthreadman.h>
|
||||
#include <pspnet_inet.h>
|
||||
|
||||
#include "fdman.h"
|
||||
|
||||
#define SELECT_POLLING_DELAY_IN_us 100
|
||||
#define SCE_FD_SET(n, p) \
|
||||
((p)->fds_bits[((n) & 0xFF) /_NFDBITS] |= (1 << ((n) % _NFDBITS)))
|
||||
|
||||
#ifdef F_select
|
||||
static int __poll_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
|
||||
{
|
||||
int fd, count;
|
||||
fd_set ready_readfds, ready_writefds, ready_exceptfds;
|
||||
fd_set scereadfds, scewritefds;
|
||||
SceKernelMppInfo info;
|
||||
struct timeval scetv;
|
||||
|
||||
FD_ZERO(&ready_readfds);
|
||||
FD_ZERO(&ready_writefds);
|
||||
FD_ZERO(&ready_exceptfds);
|
||||
|
||||
info.size = sizeof(info);
|
||||
scetv.tv_sec = 0;
|
||||
scetv.tv_usec = 0;
|
||||
count = 0;
|
||||
|
||||
for (fd = 0; fd < n; fd++)
|
||||
{
|
||||
if (__descriptormap[fd] != NULL) {
|
||||
switch(__descriptormap[fd]->type)
|
||||
{
|
||||
case __DESCRIPTOR_TYPE_PIPE:
|
||||
if (readfds && FD_ISSET(fd, readfds)) {
|
||||
if (sceKernelReferMsgPipeStatus(__descriptormap[fd]->descriptor, &info) == 0) {
|
||||
if (info.bufSize != info.freeSize) {
|
||||
FD_SET(fd, &ready_readfds);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
FD_SET(fd, &ready_exceptfds);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (writefds && FD_ISSET(fd, writefds)) {
|
||||
if (sceKernelReferMsgPipeStatus(__descriptormap[fd]->descriptor, &info) == 0) {
|
||||
if (info.freeSize > 0) {
|
||||
FD_SET(fd, &ready_writefds);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
FD_SET(fd, &ready_exceptfds);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_FILE:
|
||||
if (readfds && FD_ISSET(fd, readfds)) {
|
||||
if (readfds && FD_ISSET(fd, readfds)) {
|
||||
/** Just set it for now */
|
||||
FD_SET(fd, &ready_readfds);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case __DESCRIPTOR_TYPE_SOCKET:
|
||||
if (readfds && FD_ISSET(fd, readfds)) {
|
||||
int sce_ret, sce_fd;
|
||||
sce_fd = __descriptormap[fd]->descriptor;
|
||||
FD_ZERO(&scereadfds);
|
||||
SCE_FD_SET(sce_fd, &scereadfds);
|
||||
errno = 0;
|
||||
sce_ret = sceNetInetSelect (sce_fd+1, &scereadfds, NULL, NULL, &scetv);
|
||||
if (sce_ret>0) {
|
||||
FD_SET(fd, &ready_readfds);
|
||||
count++;
|
||||
}
|
||||
else if (sce_ret == -1) {
|
||||
errno = sceNetInetGetErrno();
|
||||
if (exceptfds && FD_ISSET(fd, exceptfds)) {
|
||||
FD_SET(fd, &ready_exceptfds);
|
||||
count++;
|
||||
} else {
|
||||
count = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (writefds && FD_ISSET(fd, writefds)) {
|
||||
int sce_ret;
|
||||
FD_ZERO(&scewritefds);
|
||||
SCE_FD_SET(__descriptormap[fd]->descriptor, &scewritefds);
|
||||
sce_ret = sceNetInetSelect (__descriptormap[fd]->descriptor+1, NULL, &scewritefds, NULL, &scetv);
|
||||
if (sce_ret>0) {
|
||||
FD_SET(fd, &ready_writefds);
|
||||
count++;
|
||||
}
|
||||
else if (sce_ret == -1) {
|
||||
if (exceptfds && FD_ISSET(fd, exceptfds)) {
|
||||
FD_SET(fd, &ready_exceptfds);
|
||||
count++;
|
||||
}
|
||||
else {
|
||||
count = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* anhanguera - 20070701
|
||||
*
|
||||
* here we know that, system has no idea about 'fd'. if caller requested
|
||||
* information about 'fd', return '-1' and set errno to 'EBADF'. we should
|
||||
* increse the count and set exceptfd for fd, but it is safe to obey select
|
||||
* manual.
|
||||
*
|
||||
* from manual;
|
||||
* On error, -1 is returned, and errno is set appropriately; the sets and
|
||||
* timeout become undefined, so do not rely on their contents after an error.
|
||||
*/
|
||||
if ((readfds && FD_ISSET(fd, readfds)) ||
|
||||
(writefds && FD_ISSET(fd, writefds)) ||
|
||||
(exceptfds && FD_ISSET(fd, exceptfds))) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
if (readfds)
|
||||
*readfds = ready_readfds;
|
||||
if (writefds)
|
||||
*writefds = ready_writefds;
|
||||
if (exceptfds)
|
||||
*exceptfds = ready_exceptfds;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int select(int n, fd_set *readfds, fd_set *writefds,
|
||||
fd_set *exceptfds, struct timeval *timeout)
|
||||
{
|
||||
int count;
|
||||
clock_t start_time, time;
|
||||
|
||||
start_time = clock();
|
||||
|
||||
count = 0;
|
||||
|
||||
if (timeout) {
|
||||
time = (timeout->tv_sec * CLOCKS_PER_SEC) + (timeout->tv_usec * (1*1000*1000/CLOCKS_PER_SEC));
|
||||
}
|
||||
else {
|
||||
time = 0;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
count = __poll_select(n, readfds, writefds, exceptfds);
|
||||
/* If timeout == NULL, then don't timeout! */
|
||||
if ( (count > 0) || ((timeout != NULL) && ((clock() - start_time) >= time)) ) {
|
||||
break;
|
||||
}
|
||||
if (count < 0) {
|
||||
/* anhanguera - 20070701
|
||||
* error, lets let the caller to handle error state
|
||||
*/
|
||||
break;
|
||||
}
|
||||
else {
|
||||
/* Nothing found, and not timed-out yet; let's yield for SELECT_POLLING_DELAY_IN_us, so we're not in a busy loop */
|
||||
sceKernelDelayThread(SELECT_POLLING_DELAY_IN_us);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
# _____ ___ ____ ___ ____
|
||||
# ____| | ____| | | |____|
|
||||
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
|
||||
# Licenced under Academic Free License version 2.0
|
||||
# Review ps2sdk README & LICENSE files for further details.
|
||||
#
|
||||
# This is a simple version of setjmp and longjmp.
|
||||
# Floating point support in.
|
||||
*/
|
||||
|
||||
#include <as_reg_compat.h>
|
||||
|
||||
#define O_S0 0x00
|
||||
#define O_S1 0x04
|
||||
#define O_S2 0x08
|
||||
#define O_S3 0x0c
|
||||
#define O_S4 0x10
|
||||
#define O_S5 0x14
|
||||
#define O_S6 0x18
|
||||
#define O_S7 0x1c
|
||||
#define O_FP 0x20
|
||||
#define O_SP 0x24
|
||||
#define O_RA 0x28
|
||||
#define O_F20 0x2c
|
||||
#define O_F21 0x30
|
||||
#define O_F22 0x34
|
||||
#define O_F23 0x38
|
||||
#define O_F24 0x3c
|
||||
#define O_F25 0x40
|
||||
#define O_F26 0x44
|
||||
#define O_F27 0x48
|
||||
#define O_F28 0x4c
|
||||
#define O_F29 0x50
|
||||
#define O_F30 0x54
|
||||
#define O_F31 0x58
|
||||
|
||||
/* int setjmp (jmp_buf); */
|
||||
.globl setjmp
|
||||
.ent setjmp
|
||||
setjmp:
|
||||
.frame $sp,0,$31
|
||||
|
||||
sw $s0, O_S0($a0)
|
||||
sw $s1, O_S1($a0)
|
||||
sw $s2, O_S2($a0)
|
||||
sw $s3, O_S3($a0)
|
||||
sw $s4, O_S4($a0)
|
||||
sw $s5, O_S5($a0)
|
||||
sw $s6, O_S6($a0)
|
||||
sw $s7, O_S7($a0)
|
||||
sw $fp, O_FP($a0)
|
||||
sw $sp, O_SP($a0)
|
||||
sw $ra, O_RA($a0)
|
||||
|
||||
swc1 $f20, O_F20($a0)
|
||||
swc1 $f21, O_F21($a0)
|
||||
swc1 $f22, O_F22($a0)
|
||||
swc1 $f23, O_F23($a0)
|
||||
swc1 $f24, O_F24($a0)
|
||||
swc1 $f25, O_F25($a0)
|
||||
swc1 $f26, O_F26($a0)
|
||||
swc1 $f27, O_F27($a0)
|
||||
swc1 $f28, O_F28($a0)
|
||||
swc1 $f29, O_F29($a0)
|
||||
swc1 $f30, O_F30($a0)
|
||||
swc1 $f31, O_F31($a0)
|
||||
|
||||
|
||||
move $v0, $0
|
||||
|
||||
jr $ra
|
||||
|
||||
.end setjmp
|
||||
|
||||
/* volatile void longjmp (jmp_buf, int); */
|
||||
.globl longjmp
|
||||
.ent longjmp
|
||||
longjmp:
|
||||
.frame $sp,0,$31
|
||||
|
||||
lw $s0, O_S0($a0)
|
||||
lw $s1, O_S1($a0)
|
||||
lw $s2, O_S2($a0)
|
||||
lw $s3, O_S3($a0)
|
||||
lw $s4, O_S4($a0)
|
||||
lw $s5, O_S5($a0)
|
||||
lw $s6, O_S6($a0)
|
||||
lw $s7, O_S7($a0)
|
||||
lw $fp, O_FP($a0)
|
||||
lw $sp, O_SP($a0)
|
||||
lw $ra, O_RA($a0)
|
||||
|
||||
lwc1 $f20, O_F20($a0)
|
||||
lwc1 $f21, O_F21($a0)
|
||||
lwc1 $f22, O_F22($a0)
|
||||
lwc1 $f23, O_F23($a0)
|
||||
lwc1 $f24, O_F24($a0)
|
||||
lwc1 $f25, O_F25($a0)
|
||||
lwc1 $f26, O_F26($a0)
|
||||
lwc1 $f27, O_F27($a0)
|
||||
lwc1 $f28, O_F28($a0)
|
||||
lwc1 $f29, O_F29($a0)
|
||||
lwc1 $f30, O_F30($a0)
|
||||
lwc1 $f31, O_F31($a0)
|
||||
|
||||
bne $a0, $0, 1f
|
||||
li $a0, 1
|
||||
1:
|
||||
move $v0, $a0
|
||||
|
||||
jr $ra
|
||||
|
||||
.end longjmp
|
||||
31
src/libc/sleep.c
Normal file
31
src/libc/sleep.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* sleep.c - Sleep functions needed by newlib.
|
||||
*
|
||||
* Copyright (c) 2021 Francisco Javier Trujillo Mata <fjtrujy@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <pspthreadman.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef F_nanosleep
|
||||
/* note: we don't use rem as we have no signals */
|
||||
int nanosleep(const struct timespec *req, struct timespec *rem)
|
||||
{
|
||||
sceKernelDelayThreadCB( 1000000 * req->tv_sec + (req->tv_nsec / 1000) );
|
||||
|
||||
if( rem != NULL ) {
|
||||
rem->tv_sec = 0;
|
||||
rem->tv_nsec = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
446
src/libc/socket.c
Normal file
446
src/libc/socket.c
Normal file
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
* PSP Software Development Kit - http://www.pspdev.org
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* socket.c - Socket wrappers to provide similar functions to normal unix
|
||||
*
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <psptypes.h>
|
||||
#include <pspnet_inet.h>
|
||||
#include "fdman.h"
|
||||
|
||||
// To avoid warnings
|
||||
int sceNetInetAccept(int s, struct sockaddr *addr, socklen_t *addrlen);
|
||||
int sceNetInetBind(int s, const struct sockaddr *my_addr, socklen_t addrlen);
|
||||
int sceNetInetConnect(int s, const struct sockaddr *serv_addr, socklen_t addrlen);
|
||||
int sceNetInetGetsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);
|
||||
int sceNetInetListen(int s, int backlog);
|
||||
size_t sceNetInetRecv(int s, void *buf, size_t len, int flags);
|
||||
size_t sceNetInetRecvfrom(int s, void *buf, size_t flags, int, struct sockaddr *from, socklen_t *fromlen);
|
||||
size_t sceNetInetSend(int s, const void *buf, size_t len, int flags);
|
||||
size_t sceNetInetSendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
|
||||
int sceNetInetSetsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
|
||||
int sceNetInetShutdown(int s, int how);
|
||||
int sceNetInetSocket(int domain, int type, int protocol);
|
||||
int sceNetInetClose(int s);
|
||||
int sceNetInetGetErrno(void);
|
||||
int sceNetInetGetpeername(int s, struct sockaddr *name, socklen_t *namelen);
|
||||
int sceNetInetGetsockname(int s, struct sockaddr *name, socklen_t *namelen);
|
||||
ssize_t sceNetInetSendmsg(int s, const struct msghdr *msg, int flags);
|
||||
ssize_t sceNetInetRecvmsg(int s, struct msghdr *msg, int flags);
|
||||
|
||||
#ifdef F_socket
|
||||
int socket(int domain, int type, int protocol)
|
||||
{
|
||||
int sock, scesock;
|
||||
|
||||
scesock = sceNetInetSocket(domain, type, protocol);
|
||||
if(scesock < 0) {
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sock = __fdman_get_new_descriptor();
|
||||
if( sock != -1 ) {
|
||||
__descriptormap[sock]->descriptor = scesock;
|
||||
__descriptormap[sock]->type = __DESCRIPTOR_TYPE_SOCKET;
|
||||
}
|
||||
else {
|
||||
sceNetInetClose(scesock);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* These are glue routines that are called from _close(), _read(), and
|
||||
_write(). They are here so that any program that uses socket() will pull
|
||||
them in and have expanded socket capability. */
|
||||
|
||||
#ifdef F___socket_close
|
||||
int __socket_close(int sock)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (__descriptormap[sock]->ref_count == 1) {
|
||||
ret = sceNetInetClose(__descriptormap[sock]->descriptor);
|
||||
}
|
||||
|
||||
__fdman_release_descriptor(sock);
|
||||
|
||||
if(ret < 0)
|
||||
{
|
||||
/* If close is defined likely errno is */
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_accept
|
||||
int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
int newscesock, newsock;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
newscesock = sceNetInetAccept(__descriptormap[s]->descriptor, addr, addrlen);
|
||||
if( (newscesock >= 0) ) {
|
||||
newsock = __fdman_get_new_descriptor();
|
||||
if ( newsock != -1 ) {
|
||||
__descriptormap[newsock]->descriptor = newscesock;
|
||||
__descriptormap[newsock]->type = __DESCRIPTOR_TYPE_SOCKET;
|
||||
}
|
||||
else {
|
||||
sceNetInetClose(newscesock);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return newsock;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_bind
|
||||
int bind(int s, const struct sockaddr *my_addr, socklen_t addrlen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetBind(__descriptormap[s]->descriptor, my_addr, addrlen);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_connect
|
||||
int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetConnect(__descriptormap[s]->descriptor, serv_addr, addrlen);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_listen
|
||||
int listen(int s, int backlog)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetListen(__descriptormap[s]->descriptor, backlog);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_recv
|
||||
ssize_t recv(int s, void *buf, size_t len, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetRecv(__descriptormap[s]->descriptor, buf, len, flags);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_recvfrom
|
||||
ssize_t recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetRecvfrom(__descriptormap[s]->descriptor, buf, len, flags, from, fromlen);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_send
|
||||
ssize_t send(int s, const void *buf, size_t len, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetSend(__descriptormap[s]->descriptor, buf, len, flags);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_sendto
|
||||
ssize_t sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetSendto(__descriptormap[s]->descriptor, buf, len, flags, to, tolen);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_getsockopt
|
||||
int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetGetsockopt(__descriptormap[s]->descriptor, level, optname, optval, optlen);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_setsockopt
|
||||
int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetSetsockopt(__descriptormap[s]->descriptor, level, optname, optval, optlen);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (level == SOL_SOCKET) && (optname == SO_NONBLOCK) ) {
|
||||
if (*((int*)optval) == 1) {
|
||||
__descriptormap[s]->flags |= O_NONBLOCK;
|
||||
}
|
||||
else {
|
||||
__descriptormap[s]->flags &= ~O_NONBLOCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_shutdown
|
||||
int shutdown(int s, int how)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetShutdown(__descriptormap[s]->descriptor, how);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_getpeername
|
||||
int getpeername(int s, struct sockaddr *name, socklen_t *namelen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetGetpeername(__descriptormap[s]->descriptor, name, namelen);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_getsockname
|
||||
int getsockname(int s, struct sockaddr *name, socklen_t *namelen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetGetsockname(__descriptormap[s]->descriptor, name, namelen);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_inet_ntoa
|
||||
char *inet_ntoa(struct in_addr in)
|
||||
{
|
||||
static char ip_addr[INET_ADDRSTRLEN+1];
|
||||
|
||||
if(sceNetInetInetNtop(AF_INET, &in, ip_addr, INET_ADDRSTRLEN) == NULL)
|
||||
{
|
||||
strcpy(ip_addr, "Invalid");
|
||||
}
|
||||
|
||||
return ip_addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_sendmsg
|
||||
ssize_t sendmsg(int s, const struct msghdr *msg, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetSendmsg(__descriptormap[s]->descriptor, msg, flags);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_recvmsg
|
||||
ssize_t recvmsg(int s, struct msghdr *msg, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!__IS_FD_OF_TYPE(s, __DESCRIPTOR_TYPE_SOCKET)) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sceNetInetRecvmsg(__descriptormap[s]->descriptor, msg, flags);
|
||||
if(ret < 0)
|
||||
{
|
||||
errno = sceNetInetGetErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
1443
src/libc/stdio.c
1443
src/libc/stdio.c
File diff suppressed because it is too large
Load Diff
214
src/libc/stdio.h
214
src/libc/stdio.h
@@ -1,214 +0,0 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* stdio.h
|
||||
*
|
||||
* Copyright (c) 2002-2004 PS2DEV
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __STDIO_H__
|
||||
#define __STDIO_H__
|
||||
|
||||
#include <pspkernel.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#define STDIN_FILENO 0
|
||||
#define STDOUT_FILENO 1
|
||||
#define STDERR_FILENO 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Some aliases for the unix 'unistd' functions */
|
||||
static __inline__ int open(const char *fname, int flags, ...) { return sceIoOpen(fname, flags, 0777); }
|
||||
static __inline__ int close(int handle) { return sceIoClose(handle); }
|
||||
static __inline__ ssize_t read(int handle, void * buffer, size_t size) { return sceIoRead(handle, buffer, size); }
|
||||
static __inline__ ssize_t write(int handle, const void * buffer, size_t size) { return sceIoWrite(handle, buffer, size); }
|
||||
static __inline__ off_t lseek(int handle, off_t position, int wheel) { return sceIoLseek(handle, position, wheel); }
|
||||
static __inline__ off_t tell(int handle) { return sceIoLseek(handle, 0, 1); }
|
||||
|
||||
/* Some win32 equivalents... baaah */
|
||||
#define _open open
|
||||
#define _close close
|
||||
#define _read read
|
||||
#define _write write
|
||||
#define _lseek lseek
|
||||
|
||||
#define _O_APPEND O_APPEND
|
||||
#define _O_BINARY O_BINARY
|
||||
#define _O_CREAT O_CREAT
|
||||
#define _O_RDONKY O_RDONKY
|
||||
#define _O_RDWR O_RDWR
|
||||
#define _O_TEXT O_TEXT
|
||||
#define _O_TRUNC O_TRUNC
|
||||
#define _O_WRONLY O_WRONLY
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#ifndef O_TEXT
|
||||
#define O_TEXT 0
|
||||
#endif
|
||||
|
||||
|
||||
#define BUFSIZ 1024
|
||||
|
||||
#define _NFILE 16
|
||||
|
||||
|
||||
#define _IOFBF 0x0000
|
||||
#define _IOLBF 0x0100
|
||||
#define _IONBF 0x0004
|
||||
#define _IOEOF 0x0020
|
||||
#define _IOERR 0x0040
|
||||
|
||||
#define _IOREAD 0x0001
|
||||
#define _IOWRT 0x0002
|
||||
#define _IORW 0x0200
|
||||
#define _IOMYBUF 0x0010
|
||||
|
||||
|
||||
/* ensure EOF is defined. */
|
||||
#ifndef EOF
|
||||
#define EOF (-1)
|
||||
#endif
|
||||
|
||||
|
||||
#define FOPEN_MAX _NFILE
|
||||
#define FILENAME_MAX 1024
|
||||
|
||||
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
|
||||
|
||||
/* ensure fpos_t is defined. */
|
||||
#ifndef __FPOS_T_DEFINED
|
||||
#define __FPOS_T_DEFINED
|
||||
typedef long fpos_t;
|
||||
#endif // __FPOS_T_DEFINED
|
||||
|
||||
|
||||
/* ensure FILE is defined. */
|
||||
#ifndef __FILE_DEFINED
|
||||
#define __FILE_DEFINED
|
||||
typedef struct {
|
||||
int type;
|
||||
int fd;
|
||||
int cnt;
|
||||
int flag;
|
||||
int has_putback;
|
||||
u8 putback;
|
||||
} FILE;
|
||||
#endif // __FILE_DEFINED
|
||||
|
||||
|
||||
extern FILE __iob[_NFILE];
|
||||
|
||||
|
||||
#define stdin (&__iob[0])
|
||||
#define stdout (&__iob[1])
|
||||
#define stderr (&__iob[2])
|
||||
|
||||
|
||||
/* function declarations. */
|
||||
void clearerr(FILE *);
|
||||
int feof(FILE *);
|
||||
int ferror(FILE *);
|
||||
FILE *fopen(const char *, const char *);
|
||||
FILE *fopen64(const char *, const char *);
|
||||
FILE *fdopen(int, const char *);
|
||||
int fclose(FILE *);
|
||||
int fflush(FILE *);
|
||||
int fgetc(FILE *);
|
||||
int fgetpos(FILE *, fpos_t *);
|
||||
int fgetpos64(FILE *, int64_t *);
|
||||
char *fgets(char *, int, FILE *);
|
||||
int fileno(FILE *);
|
||||
int fputc(int, FILE *);
|
||||
int fputs(const char *, FILE *);
|
||||
size_t fread(void *, size_t, size_t, FILE *);
|
||||
FILE *freopen(const char *, const char *, FILE *);
|
||||
int fscanf(FILE *, const char *, ...);
|
||||
int fseek(FILE *, long, int);
|
||||
int fseeko64(FILE *, int64_t, int);
|
||||
int fsetpos(FILE *, const fpos_t *);
|
||||
long ftell(FILE *);
|
||||
int64_t ftello64(FILE *);
|
||||
size_t fwrite(const void *, size_t, size_t, FILE *);
|
||||
int getc(FILE *);
|
||||
int getchar(void);
|
||||
char *gets(char *);
|
||||
void perror(const char *);
|
||||
int putc(int, FILE *);
|
||||
int puts(const char *);
|
||||
int remove(const char *);
|
||||
int rename(const char *, const char *);
|
||||
void rewind(FILE *);
|
||||
int scanf(const char *, ...);
|
||||
int setbuf(FILE *, char *);
|
||||
int setvbuf(FILE *, char *, int, size_t);
|
||||
int sscanf(const char *, const char *, ...);
|
||||
FILE *tmpfile(void);
|
||||
char *tmpnam(char *);
|
||||
int vfscanf(FILE *, const char *, va_list);
|
||||
int vscanf(const char *, va_list);
|
||||
int vsscanf(const char *, const char *, va_list);
|
||||
int vxscanf(int (*xgetc)(void **), void (*xungetc)(int, void **), void *stream, const char *, va_list);
|
||||
int xscanf(int (*xgetc)(void **), void (*xungetc)(int, void **), void *stream, const char *, ...);
|
||||
|
||||
int ungetc(int, FILE *);
|
||||
|
||||
int _fcloseall(void);
|
||||
int _fflushall(void);
|
||||
|
||||
int chdir(const char *path);
|
||||
|
||||
|
||||
/* from xprintf */
|
||||
int vxprintf(void (*func)(char*, int, void *), void * arg, const char * format, va_list ap);
|
||||
int vsnprintf(char *buf, size_t n, const char *fmt, va_list ap);
|
||||
int vsprintf(char *buf, const char *fmt, va_list ap);
|
||||
char *vmprintf(const char *zFormat, va_list ap);
|
||||
int vfprintf(FILE *pOut, const char *zFormat, va_list ap);
|
||||
int vprintf(const char *format, va_list ap);
|
||||
int vasprintf(char **strp, const char *format, va_list ap);
|
||||
|
||||
int xprintf(void (*func)(char*, int, void *), void * arg, const char * format, ...)
|
||||
__attribute__((format(printf,3,4)));
|
||||
int snprintf(char *str, size_t sz, const char *format, ...)
|
||||
__attribute__((format(printf,3,4)));
|
||||
int sprintf(char *buf, const char *fmt, ...)
|
||||
__attribute__((format(printf,2,3)));
|
||||
char *mprintf(const char *zFormat, ...)
|
||||
__attribute__((format(printf,1,2)));
|
||||
int fprintf(FILE *pOut, const char *zFormat, ...)
|
||||
__attribute__((format(printf,2,3)));
|
||||
int printf(const char *format, ...)
|
||||
__attribute__((format(printf,1,2)));
|
||||
int asprintf(char **strp, const char *format, ...)
|
||||
__attribute__((format(printf,2,3)));
|
||||
|
||||
int putchar(int);
|
||||
|
||||
int npmPuts(const char *buf);
|
||||
int nprintf(const char *format, ...);
|
||||
int vnprintf(const char *format, va_list args);
|
||||
int sio_printf(const char *format, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // __STDIO_H__
|
||||
1238
src/libc/stdlib.c
1238
src/libc/stdlib.c
File diff suppressed because it is too large
Load Diff
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* stdlib.h
|
||||
*
|
||||
* Copyright (c) 2002-2004 PS2DEV
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __STDLIB_H__
|
||||
#define __STDLIB_H__
|
||||
|
||||
#include <pspkernel.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* ensure NULL is defined. */
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif
|
||||
|
||||
|
||||
/* exit status constants. */
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_FAILURE 1
|
||||
|
||||
|
||||
/* multibyte maximum character constant. */
|
||||
#define MB_CUR_MAX 1
|
||||
|
||||
/* ensure div_t is defined. */
|
||||
#ifndef __DIV_T_DEFINED
|
||||
#define __DIV_T_DEFINED
|
||||
typedef struct {
|
||||
int quot;
|
||||
int rem;
|
||||
} div_t;
|
||||
#endif // __DIV_T_DEFINED
|
||||
|
||||
|
||||
/* ensure ldiv_t is defined. */
|
||||
#ifndef __LDIV_T_DEFINED
|
||||
#define __LDIV_T_DEFINED
|
||||
typedef struct {
|
||||
long quot;
|
||||
long rem;
|
||||
} ldiv_t;
|
||||
#endif // __LDIV_T_DEFINED
|
||||
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#ifndef __LLDIV_T_DEFINED
|
||||
#define __LLDIV_T_DEFINED
|
||||
typedef struct {
|
||||
long long quot;
|
||||
long long rem;
|
||||
} lldiv_t;
|
||||
#endif // __LLDIV_T_DEFINED
|
||||
#endif // __STRICT_ANSI__
|
||||
|
||||
/* we don't check for any previously defined value. This HAS to be that. */
|
||||
#define RAND_MAX 2147483647
|
||||
|
||||
|
||||
/* function declarations. */
|
||||
void abort(void) __attribute__ ((noreturn));
|
||||
int abs(int);
|
||||
int atexit(void (*)(void));
|
||||
double atof(const char *);
|
||||
void exit(int);
|
||||
//int atoi(const char *);
|
||||
//long atol(const char *);
|
||||
//#define atoi(x) strtol(x, NULL, 10)
|
||||
//#define atol atoi
|
||||
void *bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *));
|
||||
div_t div(int, int);
|
||||
char *getenv(const char *);
|
||||
long labs(long);
|
||||
ldiv_t ldiv(long, long);
|
||||
#ifndef __STRICT_ANSI__
|
||||
long long llabs(long long);
|
||||
lldiv_t lldiv(long long, long long);
|
||||
#endif
|
||||
int rand(void);
|
||||
int setenv(const char *, const char *, int);
|
||||
void srand(unsigned int);
|
||||
double strtod(const char *, char **);
|
||||
long strtol(const char *, char **, int);
|
||||
unsigned long strtoul(const char *, char **, int);
|
||||
static __inline__ int atoi(const char * x) { return strtol(x, NULL, 10); }
|
||||
static __inline__ long atol(const char * x) { return strtol(x, NULL, 10); }
|
||||
|
||||
|
||||
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
|
||||
|
||||
|
||||
/* Multibyte disabled, but prototyped for C++... */
|
||||
int mblen(const char *, size_t);
|
||||
size_t mbstowcs(wchar_t *, const char *, size_t);
|
||||
int mbtowc(wchar_t *, const char *, size_t);
|
||||
size_t wcstombs(char *, const wchar_t *, size_t);
|
||||
int wctomb(char *, wchar_t);
|
||||
|
||||
//char *_gcvt(double, size_t, char *);
|
||||
char *_itoa(int, char *, int);
|
||||
char *_ltoa(long, char *, int);
|
||||
#ifndef __STRICT_ANSI__
|
||||
char *_lltoa(long long, char *, int);
|
||||
#endif
|
||||
|
||||
// blah! C++ is evil.
|
||||
int system (const char * string);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
/* C++ is evil, let's defeat it... */
|
||||
#define _CPP_CSTDLIB 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif // __STDLIB_H__
|
||||
@@ -1,839 +0,0 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* string.c - Standard ANSI string functions to complement the ASM funcs
|
||||
*
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
#include <psptypes.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
/* Until a _ctype_ array exists in psplibc, don't include ctype.h and declare ctype.h
|
||||
function prototypes. */
|
||||
int isalnum(int);
|
||||
int isalpha(int);
|
||||
int iscntrl(int);
|
||||
int isdigit(int);
|
||||
int isgraph(int);
|
||||
int islower(int);
|
||||
int isprint(int);
|
||||
int ispunct(int);
|
||||
int isspace(int);
|
||||
int isupper(int);
|
||||
int isxdigit(int);
|
||||
int tolower(int);
|
||||
int toupper(int);
|
||||
|
||||
#ifdef F_strlen
|
||||
unsigned int strlen(const char *s)
|
||||
{
|
||||
int len = 0;
|
||||
while(*s)
|
||||
{
|
||||
s++;
|
||||
len++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strcat
|
||||
char *strcat(char *s, const char *append)
|
||||
{
|
||||
char *pRet = s;
|
||||
while(*s)
|
||||
{
|
||||
s++;
|
||||
}
|
||||
|
||||
while(*append)
|
||||
{
|
||||
*s++ = *append++;
|
||||
}
|
||||
|
||||
*s = 0;
|
||||
|
||||
return pRet;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strncat
|
||||
char *strncat(char *s, const char *append, size_t count)
|
||||
{
|
||||
char *pRet = s;
|
||||
|
||||
while(*s)
|
||||
{
|
||||
s++;
|
||||
}
|
||||
|
||||
while((*append) && (count > 0))
|
||||
{
|
||||
*s++ = *append++;
|
||||
count--;
|
||||
}
|
||||
|
||||
*s = 0;
|
||||
|
||||
return pRet;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strcmp
|
||||
int strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
int val = 0;
|
||||
const unsigned char *u1, *u2;
|
||||
|
||||
u1 = (unsigned char *) s1;
|
||||
u2 = (unsigned char *) s2;
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(*u1 != *u2)
|
||||
{
|
||||
val = (int) *u1 - (int) *u2;
|
||||
break;
|
||||
}
|
||||
|
||||
if((*u1 == 0) && (*u2 == 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
u1++;
|
||||
u2++;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strncmp
|
||||
int strncmp(const char *s1, const char *s2, size_t count)
|
||||
{
|
||||
int val = 0;
|
||||
const unsigned char *u1, *u2;
|
||||
|
||||
u1 = (unsigned char *) s1;
|
||||
u2 = (unsigned char *) s2;
|
||||
|
||||
while(count > 0)
|
||||
{
|
||||
if(*u1 != *u2)
|
||||
{
|
||||
val = (int) *u1 - (int) *u2;
|
||||
break;
|
||||
}
|
||||
|
||||
if((*u1 == 0) && (*u2 == 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
u1++;
|
||||
u2++;
|
||||
count--;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strcpy
|
||||
char *strcpy(char *dst, const char *src)
|
||||
{
|
||||
char *pRet = dst;
|
||||
|
||||
while(*src)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
*dst = 0;
|
||||
|
||||
return pRet;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strncpy
|
||||
char *strncpy(char *dst, const char *src, size_t count)
|
||||
{
|
||||
char *pRet = dst;
|
||||
|
||||
while(count > 0)
|
||||
{
|
||||
if(*src)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst++ = 0;
|
||||
}
|
||||
|
||||
count--;
|
||||
}
|
||||
|
||||
return pRet;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_memcmp
|
||||
int memcmp(const void *b1, const void *b2, size_t len)
|
||||
{
|
||||
int val = 0;
|
||||
const unsigned char *u1, *u2;
|
||||
|
||||
u1 = (const unsigned char *) b1;
|
||||
u2 = (const unsigned char *) b2;
|
||||
|
||||
while(len > 0)
|
||||
{
|
||||
if(*u1 != *u2)
|
||||
{
|
||||
val = (int) *u1 - (int) *u2;
|
||||
break;
|
||||
}
|
||||
u1++;
|
||||
u2++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_memcpy
|
||||
void *memcpy(void *dst, const void *src, size_t len)
|
||||
{
|
||||
void *pRet = dst;
|
||||
const char *usrc = (const char *) src;
|
||||
char *udst = (char *) dst;
|
||||
|
||||
while(len > 0)
|
||||
{
|
||||
*udst++ = *usrc++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return pRet;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_memmove
|
||||
void *memmove(void *dst, const void* src, size_t len)
|
||||
{
|
||||
void *pRet = dst;
|
||||
char *udst;
|
||||
const char *usrc;
|
||||
|
||||
if(dst < src)
|
||||
{
|
||||
/* Copy forwards */
|
||||
udst = (char *) dst;
|
||||
usrc = (const char *) src;
|
||||
while(len > 0)
|
||||
{
|
||||
*udst++ = *usrc++;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy backwards */
|
||||
udst = ((char *) dst) + len;
|
||||
usrc = ((const char *) src) + len;
|
||||
while(len > 0)
|
||||
{
|
||||
*--udst = *--usrc;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
|
||||
return pRet;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_memset
|
||||
void *memset(void *b, int c, size_t len)
|
||||
{
|
||||
void *pRet = b;
|
||||
unsigned char *ub = (unsigned char *) b;
|
||||
|
||||
while(len > 0)
|
||||
{
|
||||
*ub++ = (unsigned char) c;
|
||||
len--;
|
||||
}
|
||||
|
||||
return pRet;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_memchr
|
||||
void *memchr(const void *b, int c, size_t len)
|
||||
{
|
||||
void *pRet = NULL;
|
||||
const unsigned char *ub;
|
||||
|
||||
ub = (void *) b;
|
||||
while(len > 0)
|
||||
{
|
||||
if(*ub == (unsigned char) c)
|
||||
{
|
||||
pRet = (void *) &ub[0];
|
||||
break;
|
||||
}
|
||||
|
||||
ub++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return pRet;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strchr
|
||||
char *strchr(const char *s, int c)
|
||||
{
|
||||
char *pRet = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
if(*s == (char) c)
|
||||
{
|
||||
pRet = (char *) &s[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(*s++);
|
||||
|
||||
return pRet;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strdup
|
||||
char *strdup(const char *s) {
|
||||
size_t str_size = strlen(s);
|
||||
char * r = (char *)malloc(str_size + 1);
|
||||
|
||||
return strcpy(r, s);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strcasecmp
|
||||
int strcasecmp(const char * string1, const char * string2)
|
||||
{
|
||||
while (*string1 != '\0' && tolower(*string1) == tolower(*string2))
|
||||
{
|
||||
string1++;
|
||||
string2++;
|
||||
}
|
||||
|
||||
return tolower(*(unsigned char *) string1) - tolower(*(unsigned char *) string2);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef F_strncasecmp
|
||||
int strncasecmp(const char * string1, const char * string2, size_t n)
|
||||
{
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
while ((n-- != 0) && (tolower(*string1) == tolower(*string2)))
|
||||
{
|
||||
if ((n == 0) || (*string1 == '\0') || (*string2 == '\0'))
|
||||
break;
|
||||
|
||||
string1++;
|
||||
string2++;
|
||||
}
|
||||
|
||||
return tolower(*(unsigned char *) string1) - tolower(*(unsigned char *) string2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strtok
|
||||
char* strtok(char * strToken, const char * strDelimit)
|
||||
{
|
||||
static char* start;
|
||||
static char* end;
|
||||
|
||||
if (strToken != NULL)
|
||||
start = strToken;
|
||||
else
|
||||
{
|
||||
if (*end == 0)
|
||||
return 0;
|
||||
|
||||
start=end;
|
||||
}
|
||||
|
||||
if(*start == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Strip out any leading delimiters
|
||||
while (strchr(strDelimit, *start))
|
||||
{
|
||||
// If a character from the delimiting string
|
||||
// then skip past it
|
||||
|
||||
start++;
|
||||
|
||||
if (*start == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*start == 0)
|
||||
return 0;
|
||||
|
||||
end=start;
|
||||
|
||||
|
||||
while (*end != 0)
|
||||
{
|
||||
if (strchr(strDelimit, *end))
|
||||
{
|
||||
// if we find a delimiting character
|
||||
// before the end of the string, then
|
||||
// terminate the token and move the end
|
||||
// pointer to the next character
|
||||
*end = 0;
|
||||
end++;
|
||||
return start;
|
||||
}
|
||||
|
||||
end++;
|
||||
}
|
||||
|
||||
|
||||
// reached the end of the string before finding a delimiter
|
||||
// so dont move on to the next character
|
||||
return start;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strrchr
|
||||
char* strrchr(const char * string, int c)
|
||||
{
|
||||
/* use the asm strchr to do strrchr */
|
||||
char* lastmatch;
|
||||
char* result;
|
||||
|
||||
/* if char is never found then this will return 0 */
|
||||
/* if char is found then this will return the last matched location
|
||||
before strchr returned 0 */
|
||||
|
||||
lastmatch = 0;
|
||||
result = strchr(string,c);
|
||||
|
||||
while ((int)result != 0)
|
||||
{
|
||||
lastmatch=result;
|
||||
result = strchr(lastmatch+1,c);
|
||||
}
|
||||
|
||||
return lastmatch;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strstr
|
||||
char * strstr(const char * string, const char * substring)
|
||||
{
|
||||
char* strpos;
|
||||
|
||||
if (*string == 0)
|
||||
return 0;
|
||||
|
||||
if (strlen(substring)==0)
|
||||
return (char*)string;
|
||||
|
||||
strpos = (char*)string;
|
||||
|
||||
while (*strpos != 0)
|
||||
{
|
||||
if (strncmp(strpos, substring, strlen(substring)) == 0)
|
||||
{
|
||||
return strpos;
|
||||
}
|
||||
|
||||
strpos++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef F_strupr
|
||||
char * strupr(char *str)
|
||||
{
|
||||
char * strptr = str;
|
||||
|
||||
// loop thru each char in string
|
||||
while (*strptr != '\0')
|
||||
{
|
||||
// if char is lowercase, convert to uppercase
|
||||
if(islower(*strptr))
|
||||
*strptr = toupper(*strptr);
|
||||
strptr++;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strlwr
|
||||
char * strlwr(char *str)
|
||||
{
|
||||
char * strptr = str;
|
||||
|
||||
// loop thru each char in string
|
||||
while (*strptr != '\0')
|
||||
{
|
||||
// if char is uppercase, convert to lowercase
|
||||
if(isupper(*strptr))
|
||||
*strptr = tolower(*strptr);
|
||||
strptr++;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef F_tolower
|
||||
int tolower(int c)
|
||||
{
|
||||
if (isupper(c))
|
||||
c+=32;
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_toupper
|
||||
int toupper(int c)
|
||||
{
|
||||
if (islower(c))
|
||||
c-=32;
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_isupper
|
||||
int isupper(int c)
|
||||
{
|
||||
if (c < 'A')
|
||||
return 0;
|
||||
|
||||
if (c > 'Z')
|
||||
return 0;
|
||||
|
||||
// passed both criteria, so it
|
||||
// is an upper case alpha char
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_islower
|
||||
int islower(int c)
|
||||
{
|
||||
if (c < 'a')
|
||||
return 0;
|
||||
|
||||
if (c > 'z')
|
||||
return 0;
|
||||
|
||||
// passed both criteria, so it
|
||||
// is a lower case alpha char
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_isalpha
|
||||
int isalpha(int c)
|
||||
{
|
||||
if (islower(c) || isupper(c))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_isdigit
|
||||
int isdigit(int c)
|
||||
{
|
||||
if (c < '0')
|
||||
return 0;
|
||||
|
||||
if (c > '9')
|
||||
return 0;
|
||||
|
||||
// passed both criteria, so it
|
||||
// is a numerical char
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_isalnum
|
||||
int isalnum(int c)
|
||||
{
|
||||
if (isalpha(c) || isdigit(c))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_iscntrl
|
||||
int iscntrl(int c)
|
||||
{
|
||||
if (c < 0x20)
|
||||
return 1;
|
||||
|
||||
if (c == 0x7F)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_isgraph
|
||||
int isgraph(int c)
|
||||
{
|
||||
if (iscntrl(c))
|
||||
return 0;
|
||||
|
||||
if (isspace(c))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_isprint
|
||||
int isprint(int c)
|
||||
{
|
||||
if (iscntrl(c))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_ispunct
|
||||
int ispunct(int c)
|
||||
{
|
||||
if (iscntrl(c))
|
||||
return 0;
|
||||
|
||||
if (isalnum(c))
|
||||
return 0;
|
||||
|
||||
if (isspace(c))
|
||||
return 0;
|
||||
|
||||
// It's a printable character
|
||||
// thats not alpha-numeric, or a space
|
||||
// so its a punctuation character
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_isspace
|
||||
int isspace(int c)
|
||||
{
|
||||
if ((c>=0x09) && (c<=0x0D))
|
||||
return 1;
|
||||
|
||||
if (c==0x20)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_isxdigit
|
||||
int isxdigit(int c)
|
||||
{
|
||||
if (isdigit(c))
|
||||
return 1;
|
||||
|
||||
if ((c>='a') && (c<='f'))
|
||||
return 1;
|
||||
|
||||
if ((c>='A') && (c<='F'))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// sjis<->ascii conversion routines by Peter Sandstr<74>m
|
||||
|
||||
struct charmap_t {
|
||||
unsigned short sjis;
|
||||
unsigned char ascii;
|
||||
};
|
||||
|
||||
#ifdef F__sjis_internals
|
||||
struct charmap_t sjis_conversion[] = {
|
||||
{ 0x4081, ' ' },
|
||||
{ 0x6d81, '[' },
|
||||
{ 0x6e81, ']' },
|
||||
{ 0x7c81, '-' },
|
||||
{ 0x5b81, '<EFBFBD>' },
|
||||
{ 0x4581, '<EFBFBD>' },
|
||||
{ 0x4481, '.' },
|
||||
{ 0x7B81, '+' },
|
||||
{ 0x9681, '*' },
|
||||
{ 0x5E81, '/' },
|
||||
{ 0x4981, '!' },
|
||||
{ 0x6881, '"' },
|
||||
{ 0x9481, '#' },
|
||||
{ 0x9081, '$' },
|
||||
{ 0x9381, '%' },
|
||||
{ 0x9581, '&' },
|
||||
{ 0x6681, '\'' },
|
||||
{ 0x6981, '(' },
|
||||
{ 0x6a81, ')' },
|
||||
{ 0x8181, '=' },
|
||||
{ 0x6281, '|' },
|
||||
{ 0x8f81, '\\' },
|
||||
{ 0x4881, '?' },
|
||||
{ 0x5181, '_' },
|
||||
{ 0x6f81, '{' },
|
||||
{ 0x7081, '}' },
|
||||
{ 0x9781, '@' },
|
||||
{ 0x4781, ';' },
|
||||
{ 0x4681, ':' },
|
||||
{ 0x8381, '<' },
|
||||
{ 0x8481, '>' },
|
||||
{ 0x4d81, '`' },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
unsigned char isSpecialSJIS(short sjis)
|
||||
{
|
||||
struct charmap_t *s = &sjis_conversion[0];
|
||||
do {
|
||||
if (s->sjis == sjis) return s->ascii;
|
||||
s++;
|
||||
} while (s->sjis != 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
short isSpecialASCII(unsigned char ascii)
|
||||
{
|
||||
struct charmap_t *s = &sjis_conversion[0];
|
||||
do {
|
||||
if (s->ascii == ascii) return s->sjis;
|
||||
s++;
|
||||
} while (s->ascii != 0);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
extern struct charmap_t * sjis_conversion;
|
||||
unsigned char isSpecialSJIS(short sjis);
|
||||
short isSpecialASCII(unsigned char ascii);
|
||||
#endif
|
||||
|
||||
#ifdef F_strcpy_ascii
|
||||
int strcpy_ascii(char* ascii_buff, const short* sjis_buff)
|
||||
{
|
||||
int i;
|
||||
short ascii, sjis;
|
||||
|
||||
int len = strlen((const char *)sjis_buff)/2;
|
||||
|
||||
for (i=0;i<len;i++) {
|
||||
sjis = sjis_buff[i];
|
||||
if ((ascii = isSpecialSJIS(sjis)) != 0) {
|
||||
} else {
|
||||
ascii = ((sjis & 0xFF00) >> 8) - 0x1f;
|
||||
if (ascii>96) ascii--;
|
||||
}
|
||||
ascii_buff[i] = ascii;
|
||||
}
|
||||
ascii_buff[i+1]=0;
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strcpy_sjis
|
||||
int strcpy_sjis(short* sjis_buff, const char* ascii_buff)
|
||||
{
|
||||
int i;
|
||||
short ascii, sjis;
|
||||
|
||||
int len = strlen(ascii_buff);
|
||||
|
||||
for (i=0;i<len;i++) {
|
||||
ascii = ascii_buff[i];
|
||||
if ((sjis = isSpecialASCII(ascii)) != 0) {
|
||||
} else {
|
||||
if (ascii>96) ascii++;
|
||||
sjis = ((ascii + 0x1f) << 8) | 0x82;
|
||||
}
|
||||
sjis_buff[i] = sjis;
|
||||
}
|
||||
sjis_buff[i+1]=0;
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strpbrk
|
||||
char *strpbrk(const char *s, const char *accept)
|
||||
{
|
||||
const char *needle;
|
||||
for (; *s; s++) {
|
||||
for (needle = accept; *needle; needle++) {
|
||||
if (*s == *needle)
|
||||
return (char *) s;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strspn
|
||||
size_t strspn(const char *s, const char *accept) {
|
||||
const char *c;
|
||||
|
||||
for (c = s; *c; c++) {
|
||||
if (!strchr(accept, *c))
|
||||
return c - s;
|
||||
}
|
||||
|
||||
return c - s;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_strcspn
|
||||
size_t strcspn(const char *s, const char *reject) {
|
||||
const char *c;
|
||||
|
||||
for (c = s; *c; c++) {
|
||||
if (strchr(reject, *c))
|
||||
return c - s;
|
||||
}
|
||||
|
||||
return c - s;
|
||||
}
|
||||
#endif
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* string.h
|
||||
*
|
||||
* Copyright (c) 2002-2004 PS2DEV
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _STRING_H
|
||||
#define _STRING_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* ASM String functions by Jeff Johnston of Cygnus Solutions */
|
||||
void * memchr(const void *, int, size_t);
|
||||
void * memcpy(void *, const void *, size_t);
|
||||
void * memmove(void *, const void *, size_t);
|
||||
void * memset(void *, int, size_t);
|
||||
|
||||
int memcmp(const void *, const void *, size_t);
|
||||
|
||||
int strcmp(const char *, const char *);
|
||||
int strncmp(const char *, const char *, size_t);
|
||||
|
||||
unsigned int strlen(const char *);
|
||||
|
||||
char * strdup(const char *s);
|
||||
|
||||
char * strcat(char *, const char *);
|
||||
char * strchr(const char *, int);
|
||||
char * strcpy(char *, const char *);
|
||||
char * strncat(char *, const char *, size_t);
|
||||
char * strncpy(char *, const char *, size_t);
|
||||
|
||||
char * strpbrk(const char *s, const char *accept);
|
||||
size_t strspn(const char *s, const char *accept);
|
||||
size_t strcspn(const char *s, const char *reject);
|
||||
|
||||
static __inline__ int strcoll(const char *s1, const char *s2) { return strcmp(s1, s2); }
|
||||
static __inline__ size_t strxfrm(char *dest, const char *src, size_t n) { strncpy(dest, src, n); return n; }
|
||||
|
||||
char * strerror(int);
|
||||
|
||||
// copies ascii string to sjis string
|
||||
//
|
||||
// args: dest sjis string buffer
|
||||
// source ascii string buffer
|
||||
// returns: length of ascii string copied
|
||||
int strcpy_sjis(short* sjis_buff, const char* ascii_buff);
|
||||
|
||||
// copies sjis string to ascii string
|
||||
//
|
||||
// args: dest ascii string buffer
|
||||
// source sjis string buffer
|
||||
// returns: length of sjis string copied
|
||||
int strcpy_ascii(char* ascii_buff, const short* sjis_buff);
|
||||
|
||||
|
||||
/* C String functions by Hiryu (A.Lee) */
|
||||
#define stricmp strcasecmp
|
||||
#define strnicmp strncasecmp
|
||||
|
||||
int strcasecmp(const char *, const char *);
|
||||
int strncasecmp(const char *, const char *, size_t);
|
||||
|
||||
char * strtok(char *, const char *);
|
||||
char * strrchr(const char *, int);
|
||||
|
||||
char * strstr(const char *, const char *);
|
||||
|
||||
char * strupr(char *);
|
||||
char * strlwr(char *);
|
||||
|
||||
static __inline__ void bzero(void * p, size_t n) { memset(p, 0, n); }
|
||||
static __inline__ void bcopy(const void * s, void * d, size_t n) { memcpy(d, s, n); }
|
||||
static __inline__ int bcmp(const void * s1, const void * s2, size_t n) { return memcmp(s1, s2, n); }
|
||||
static __inline__ char * index(const char * s, int c) { return strchr(s, c); }
|
||||
static __inline__ char * rindex(const char * s, int c) { return strrchr(s, c); }
|
||||
|
||||
/* Backward compatibility... */
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _STRING_H
|
||||
1
src/libc/sys/ioctl.h
Normal file
1
src/libc/sys/ioctl.h
Normal file
@@ -0,0 +1 @@
|
||||
/* Empty file, here for compatibility */
|
||||
279
src/libc/sys/socket.h
Normal file
279
src/libc/sys/socket.h
Normal file
@@ -0,0 +1,279 @@
|
||||
/* $NetBSD: socket.h,v 1.77 2005/11/29 03:12:16 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1985, 1986, 1988, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)socket.h 8.6 (Berkeley) 5/3/95
|
||||
*/
|
||||
|
||||
#ifndef _SYS_SOCKET_H_
|
||||
#define _SYS_SOCKET_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef uint8_t sa_family_t;
|
||||
typedef uint32_t socklen_t;
|
||||
|
||||
/*
|
||||
* Socket types.
|
||||
*/
|
||||
#define SOCK_STREAM 1 /* stream socket */
|
||||
#define SOCK_DGRAM 2 /* datagram socket */
|
||||
#define SOCK_RAW 3 /* raw-protocol interface */
|
||||
#define SOCK_RDM 4 /* reliably-delivered message */
|
||||
#define SOCK_SEQPACKET 5 /* sequenced packet stream */
|
||||
|
||||
/*
|
||||
* Option flags per-socket.
|
||||
*/
|
||||
#define SO_DEBUG 0x0001 /* turn on debugging info recording */
|
||||
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
|
||||
#define SO_REUSEADDR 0x0004 /* allow local address reuse */
|
||||
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
|
||||
#define SO_DONTROUTE 0x0010 /* just use interface addresses */
|
||||
#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
|
||||
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
|
||||
#define SO_LINGER 0x0080 /* linger on close if data present */
|
||||
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
|
||||
#define SO_REUSEPORT 0x0200 /* allow local address & port reuse */
|
||||
#define SO_TIMESTAMP 0x0400 /* timestamp received dgram traffic */
|
||||
|
||||
/*
|
||||
* Additional options, not kept in so_options.
|
||||
*/
|
||||
#define SO_SNDBUF 0x1001 /* send buffer size */
|
||||
#define SO_RCVBUF 0x1002 /* receive buffer size */
|
||||
#define SO_SNDLOWAT 0x1003 /* send low-water mark */
|
||||
#define SO_RCVLOWAT 0x1004 /* receive low-water mark */
|
||||
#define SO_SNDTIMEO 0x1005 /* send timeout */
|
||||
#define SO_RCVTIMEO 0x1006 /* receive timeout */
|
||||
#define SO_ERROR 0x1007 /* get error status and clear */
|
||||
#define SO_TYPE 0x1008 /* get socket type */
|
||||
#define SO_OVERFLOWED 0x1009 /* datagrams: return packets dropped */
|
||||
#define SO_NONBLOCK 0x1009 /* non-blocking I/O */
|
||||
|
||||
/*
|
||||
* Structure used for manipulating linger option.
|
||||
*/
|
||||
struct linger {
|
||||
int l_onoff; /* option on/off */
|
||||
int l_linger; /* linger time in seconds */
|
||||
};
|
||||
|
||||
/*
|
||||
* Level number for (get/set)sockopt() to apply to socket itself.
|
||||
*/
|
||||
#define SOL_SOCKET 0xffff /* options for socket level */
|
||||
|
||||
/*
|
||||
* Address families.
|
||||
*/
|
||||
#define AF_UNSPEC 0 /* unspecified */
|
||||
#define AF_LOCAL 1 /* local to host (pipes, portals) */
|
||||
#define AF_UNIX AF_LOCAL /* backward compatibility */
|
||||
#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
|
||||
#define AF_IMPLINK 3 /* arpanet imp addresses */
|
||||
#define AF_PUP 4 /* pup protocols: e.g. BSP */
|
||||
#define AF_CHAOS 5 /* mit CHAOS protocols */
|
||||
#define AF_NS 6 /* XEROX NS protocols */
|
||||
#define AF_ISO 7 /* ISO protocols */
|
||||
#define AF_OSI AF_ISO
|
||||
#define AF_ECMA 8 /* european computer manufacturers */
|
||||
#define AF_DATAKIT 9 /* datakit protocols */
|
||||
#define AF_CCITT 10 /* CCITT protocols, X.25 etc */
|
||||
#define AF_SNA 11 /* IBM SNA */
|
||||
#define AF_DECnet 12 /* DECnet */
|
||||
#define AF_DLI 13 /* DEC Direct data link interface */
|
||||
#define AF_LAT 14 /* LAT */
|
||||
#define AF_HYLINK 15 /* NSC Hyperchannel */
|
||||
#define AF_APPLETALK 16 /* Apple Talk */
|
||||
#define AF_ROUTE 17 /* Internal Routing Protocol */
|
||||
#define AF_LINK 18 /* Link layer interface */
|
||||
#define AF_COIP 20 /* connection-oriented IP, aka ST II */
|
||||
#define AF_CNT 21 /* Computer Network Technology */
|
||||
#define AF_IPX 23 /* Novell Internet Protocol */
|
||||
#define AF_INET6 24 /* IP version 6 */
|
||||
#define AF_ISDN 26 /* Integrated Services Digital Network*/
|
||||
#define AF_E164 AF_ISDN /* CCITT E.164 recommendation */
|
||||
#define AF_NATM 27 /* native ATM access */
|
||||
#define AF_ARP 28 /* (rev.) addr. res. prot. (RFC 826) */
|
||||
#define AF_MAX 31
|
||||
|
||||
/*
|
||||
* Structure used by kernel to store most
|
||||
* addresses.
|
||||
*/
|
||||
struct sockaddr {
|
||||
uint8_t sa_len; /* total length */
|
||||
sa_family_t sa_family; /* address family */
|
||||
char sa_data[14]; /* actually longer; address value */
|
||||
};
|
||||
|
||||
/*
|
||||
* Protocol families, same as address families for now.
|
||||
*/
|
||||
#define PF_UNSPEC AF_UNSPEC
|
||||
#define PF_LOCAL AF_LOCAL
|
||||
#define PF_UNIX PF_LOCAL /* backward compatibility */
|
||||
#define PF_INET AF_INET
|
||||
#define PF_IMPLINK AF_IMPLINK
|
||||
#define PF_PUP AF_PUP
|
||||
#define PF_CHAOS AF_CHAOS
|
||||
#define PF_NS AF_NS
|
||||
#define PF_ISO AF_ISO
|
||||
#define PF_OSI AF_ISO
|
||||
#define PF_ECMA AF_ECMA
|
||||
#define PF_DATAKIT AF_DATAKIT
|
||||
#define PF_CCITT AF_CCITT
|
||||
#define PF_SNA AF_SNA
|
||||
#define PF_DECnet AF_DECnet
|
||||
#define PF_DLI AF_DLI
|
||||
#define PF_LAT AF_LAT
|
||||
#define PF_HYLINK AF_HYLINK
|
||||
#define PF_APPLETALK AF_APPLETALK
|
||||
#define PF_ROUTE AF_ROUTE
|
||||
#define PF_LINK AF_LINK
|
||||
#if defined(_NETBSD_SOURCE)
|
||||
#define PF_XTP pseudo_AF_XTP /* really just proto family, no AF */
|
||||
#endif
|
||||
#define PF_COIP AF_COIP
|
||||
#define PF_CNT AF_CNT
|
||||
#define PF_INET6 AF_INET6
|
||||
#define PF_IPX AF_IPX /* same format as AF_NS */
|
||||
#if defined(_NETBSD_SOURCE)
|
||||
#define PF_RTIP pseudo_AF_RTIP /* same format as AF_INET */
|
||||
#define PF_PIP pseudo_AF_PIP
|
||||
#endif
|
||||
#define PF_ISDN AF_ISDN /* same as E164 */
|
||||
#define PF_E164 AF_E164
|
||||
#define PF_NATM AF_NATM
|
||||
#define PF_ARP AF_ARP
|
||||
#if defined(_NETBSD_SOURCE)
|
||||
#define PF_KEY pseudo_AF_KEY /* like PF_ROUTE, only for key mgmt */
|
||||
#endif
|
||||
|
||||
#define PF_MAX AF_MAX
|
||||
|
||||
#define MSG_OOB 0x1 /* process out-of-band data */
|
||||
#define MSG_PEEK 0x2 /* peek at incoming message */
|
||||
#define MSG_DONTROUTE 0x4 /* send without using routing tables */
|
||||
#define MSG_EOR 0x8 /* data completes record */
|
||||
#define MSG_TRUNC 0x10 /* data discarded before delivery */
|
||||
#define MSG_CTRUNC 0x20 /* control data lost before delivery */
|
||||
#define MSG_WAITALL 0x40 /* wait for full request or error */
|
||||
#define MSG_DONTWAIT 0x80 /* this message should be nonblocking */
|
||||
#define MSG_BCAST 0x100 /* this message was rcvd using link-level brdcst */
|
||||
#define MSG_MCAST 0x200 /* this message was rcvd using link-level mcast */
|
||||
|
||||
/*
|
||||
* Types of socket shutdown(2).
|
||||
*/
|
||||
#define SHUT_RD 0 /* Disallow further receives. */
|
||||
#define SHUT_WR 1 /* Disallow further sends. */
|
||||
#define SHUT_RDWR 2 /* Disallow further sends/receives. */
|
||||
|
||||
struct iovec {
|
||||
void *iov_base; /* Base address. */
|
||||
size_t iov_len; /* Length. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Maximum queue length specifiable by listen.
|
||||
*/
|
||||
#define SOMAXCONN 128
|
||||
|
||||
struct msghdr {
|
||||
void *msg_name; /* optional address */
|
||||
socklen_t msg_namelen; /* size of address */
|
||||
struct iovec *msg_iov; /* scatter/gather array */
|
||||
int msg_iovlen; /* # elements in msg_iov */
|
||||
void *msg_control; /* ancillary data, see below */
|
||||
socklen_t msg_controllen; /* ancillary data buffer len */
|
||||
int msg_flags; /* flags on received message */
|
||||
};
|
||||
|
||||
/* BSD-compatible socket API. */
|
||||
int accept(int, struct sockaddr * __restrict, socklen_t * __restrict);
|
||||
int bind(int, const struct sockaddr *, socklen_t);
|
||||
int connect(int, const struct sockaddr *, socklen_t);
|
||||
int getpeername(int, struct sockaddr * __restrict, socklen_t * __restrict);
|
||||
int getsockname(int, struct sockaddr * __restrict, socklen_t * __restrict);
|
||||
int getsockopt(int, int, int, void * __restrict, socklen_t * __restrict);
|
||||
int listen(int, int);
|
||||
ssize_t recv(int, void *, size_t, int);
|
||||
ssize_t recvfrom(int, void * __restrict, size_t, int,
|
||||
struct sockaddr * __restrict, socklen_t * __restrict);
|
||||
ssize_t recvmsg(int s, struct msghdr *msg, int flags);
|
||||
ssize_t send(int, const void *, size_t, int);
|
||||
ssize_t sendto(int, const void *,
|
||||
size_t, int, const struct sockaddr *, socklen_t);
|
||||
ssize_t sendmsg(int s, const struct msghdr *msg, int flags);
|
||||
int setsockopt(int, int, int, const void *, socklen_t);
|
||||
int shutdown(int, int);
|
||||
int socket(int, int, int);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_SYS_SOCKET_H_ */
|
||||
@@ -14,18 +14,47 @@
|
||||
#include <psptypes.h>
|
||||
#include <pspkernel.h>
|
||||
|
||||
extern void _exit(int code);
|
||||
#ifdef F__exit
|
||||
extern int sce_newlib_nocreate_thread_in_start __attribute__((weak));
|
||||
|
||||
int __psp_free_heap(void);
|
||||
|
||||
void _exit(int status)
|
||||
{
|
||||
if (&sce_newlib_nocreate_thread_in_start != NULL) {
|
||||
/* Free the heap created by _sbrk(). */
|
||||
__psp_free_heap();
|
||||
|
||||
sceKernelSelfStopUnloadModule(1, 0, NULL);
|
||||
} else {
|
||||
if (status == 0) {
|
||||
/* Free the heap created by _sbrk(). */
|
||||
__psp_free_heap();
|
||||
}
|
||||
|
||||
sceKernelExitThread(status);
|
||||
}
|
||||
|
||||
while (1) ;
|
||||
}
|
||||
#else
|
||||
void _exit(int status);
|
||||
#endif
|
||||
|
||||
#ifdef F_abort
|
||||
__attribute__((weak))
|
||||
void abort()
|
||||
{
|
||||
while (1)
|
||||
_exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_exit
|
||||
__attribute__((weak))
|
||||
void _Exit(int retval)
|
||||
void exit(int retval)
|
||||
{
|
||||
while (1)
|
||||
_exit(retval);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* time.h
|
||||
*
|
||||
* Copyright (c) 2002-2004 PS2DEV
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TIME_H
|
||||
#define _TIME_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef __clock_t_defined
|
||||
typedef unsigned long clock_t;
|
||||
#define __clock_t_defined
|
||||
#endif
|
||||
|
||||
#ifndef __time_t_defined
|
||||
typedef unsigned long time_t;
|
||||
#define __time_t_defined
|
||||
#endif
|
||||
|
||||
struct tm
|
||||
{
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
clock_t clock();
|
||||
time_t time(time_t *t);
|
||||
|
||||
// to be implemented...
|
||||
double difftime(time_t time1, time_t time0);
|
||||
time_t mktime(struct tm *timeptr);
|
||||
char *asctime(const struct tm *timeptr);
|
||||
char *ctime(const time_t *timep);
|
||||
struct tm *gmtime(const time_t *timep);
|
||||
struct tm *localtime(const time_t *timep);
|
||||
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TIME_H
|
||||
34
src/libc/timezone.c
Normal file
34
src/libc/timezone.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* timezon.c - Set proper timezone needed by newlib.
|
||||
*
|
||||
* Copyright (c) 2021 Francisco Javier Trujillo Mata <fjtrujy@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <psputility_sysparam.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef F___timezone_update
|
||||
__attribute__((weak))
|
||||
void __timezone_update()
|
||||
{
|
||||
/* Initialize timezone from PSP configuration */
|
||||
int tzOffset = 0;
|
||||
sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_TIMEZONE, &tzOffset);
|
||||
int tzOffsetAbs = tzOffset < 0 ? -tzOffset : tzOffset;
|
||||
int hours = tzOffsetAbs / 60;
|
||||
int minutes = tzOffsetAbs - hours * 60;
|
||||
int pspDaylight = 0;
|
||||
sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_DAYLIGHTSAVINGS, &pspDaylight);
|
||||
static char tz[18];
|
||||
sprintf(tz, "GMT%s%02i:%02i%s", tzOffset < 0 ? "+" : "-", hours, minutes, pspDaylight ? "daylight" : "");
|
||||
setenv("TZ", tz, 1);
|
||||
}
|
||||
#endif
|
||||
@@ -1,987 +0,0 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* xprintf.c - Various *printf functions.
|
||||
*
|
||||
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
|
||||
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
|
||||
* Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
|
||||
*
|
||||
*/
|
||||
/* Code borrowed from mysql's xprintf.c, by Richard Hipp */
|
||||
/* This xprintf.c file on which this one is based is in public domain. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <psptypes.h>
|
||||
#include <pspkernel.h>
|
||||
#include <pspiofilemgr.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
** The maximum number of digits of accuracy in a floating-point conversion.
|
||||
*/
|
||||
#define MAXDIG 20
|
||||
|
||||
/* The maximum string length. */
|
||||
#define PS2LIB_STR_MAX 4096
|
||||
|
||||
/* Instead of including ctype.h, use the isdigit() prototype because psplibc doesn't
|
||||
know about newlib, and newlib defines isdigit as a macro that uses _ctype_. */
|
||||
int isdigit(int __c);
|
||||
|
||||
int vxprintf(void (*func)(char *, int, void *), void *arg, const char *format, va_list ap);
|
||||
|
||||
#ifdef F_vxprintf
|
||||
/*
|
||||
** Conversion types fall into various categories as defined by the
|
||||
** following enumeration.
|
||||
*/
|
||||
|
||||
enum e_type { /* The type of the format field */
|
||||
RADIX, /* Integer types. %d, %x, %o, and so forth */
|
||||
FLOAT, /* Floating point. %f */
|
||||
EXP, /* Exponentional notation. %e and %E */
|
||||
GENERIC, /* Floating or exponential, depending on exponent. %g */
|
||||
SIZE, /* Return number of characters processed so far. %n */
|
||||
STRING, /* Strings. %s */
|
||||
PERCENT, /* Percent symbol. %% */
|
||||
CHAR, /* Characters. %c */
|
||||
ERROR, /* Used to indicate no such conversion type */
|
||||
/* The rest are extensions, not normally found in printf() */
|
||||
CHARLIT, /* Literal characters. %' */
|
||||
SEEIT, /* Strings with visible control characters. %S */
|
||||
MEM_STRING, /* A string which should be deleted after use. %z */
|
||||
ORDINAL, /* 1st, 2nd, 3rd and so forth */
|
||||
};
|
||||
|
||||
/*
|
||||
** Each builtin conversion character (ex: the 'd' in "%d") is described
|
||||
** by an instance of the following structure
|
||||
*/
|
||||
typedef struct s_info { /* Information about each format field */
|
||||
int fmttype; /* The format field code letter */
|
||||
int base; /* The base for radix conversion */
|
||||
char *charset; /* The character set for conversion */
|
||||
int flag_signed; /* Is the quantity signed? */
|
||||
char *prefix; /* Prefix on non-zero values in alt format */
|
||||
enum e_type type; /* Conversion paradigm */
|
||||
} info;
|
||||
|
||||
/*
|
||||
** The following table is searched linearly, so it is good to put the
|
||||
** most frequently used conversion types first.
|
||||
*/
|
||||
static info fmtinfo[] = {
|
||||
{ 'd', 10, "0123456789", 1, 0, RADIX, },
|
||||
{ 's', 0, 0, 0, 0, STRING, },
|
||||
{ 'S', 0, 0, 0, 0, SEEIT, },
|
||||
{ 'z', 0, 0, 0, 0, MEM_STRING, },
|
||||
{ 'c', 0, 0, 0, 0, CHAR, },
|
||||
{ 'o', 8, "01234567", 0, "0", RADIX, },
|
||||
{ 'u', 10, "0123456789", 0, 0, RADIX, },
|
||||
{ 'x', 16, "0123456789abcdef", 0, "x0", RADIX, },
|
||||
{ 'X', 16, "0123456789ABCDEF", 0, "X0", RADIX, },
|
||||
{ 'r', 10, "0123456789", 0, 0, ORDINAL, },
|
||||
{ 'f', 0, 0, 1, 0, FLOAT, },
|
||||
{ 'e', 0, "e", 1, 0, EXP, },
|
||||
{ 'E', 0, "E", 1, 0, EXP, },
|
||||
{ 'g', 0, "e", 1, 0, GENERIC, },
|
||||
{ 'G', 0, "E", 1, 0, GENERIC, },
|
||||
{ 'i', 10, "0123456789", 1, 0, RADIX, },
|
||||
{ 'n', 0, 0, 0, 0, SIZE, },
|
||||
{ 'S', 0, 0, 0, 0, SEEIT, },
|
||||
{ '%', 0, 0, 0, 0, PERCENT, },
|
||||
{ 'b', 2, "01", 0, "b0", RADIX, }, /* Binary notation */
|
||||
{ 'p', 16, "0123456789ABCDEF", 0, "x0", RADIX, }, /* Pointers */
|
||||
{ '\'', 0, 0, 0, 0, CHARLIT, }, /* Literal char */
|
||||
};
|
||||
#define NINFO (sizeof(fmtinfo)/sizeof(info)) /* Size of the fmtinfo table */
|
||||
|
||||
/*
|
||||
** If NOFLOATINGPOINT is defined, then none of the floating point
|
||||
** conversions will work.
|
||||
*/
|
||||
#ifndef NOFLOATINGPOINT
|
||||
/*
|
||||
** "*val" is a double such that 0.1 <= *val < 10.0
|
||||
** Return the ascii code for the leading digit of *val, then
|
||||
** multiply "*val" by 10.0 to renormalize.
|
||||
**
|
||||
** Example:
|
||||
** input: *val = 3.14159
|
||||
** output: *val = 1.4159 function return = '3'
|
||||
**
|
||||
** The counter *cnt is incremented each time. After counter exceeds
|
||||
** 16 (the number of significant digits in a 64-bit float) '0' is
|
||||
** always returned.
|
||||
*/
|
||||
static int getdigit(long double *val, int *cnt){
|
||||
int digit;
|
||||
long double d;
|
||||
if( (*cnt)++ >= MAXDIG ) return '0';
|
||||
digit = (int)*val;
|
||||
d = digit;
|
||||
digit += '0';
|
||||
*val = (*val - d)*10.0;
|
||||
return digit;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Setting the size of the BUFFER involves trade-offs. No %d or %f
|
||||
** conversion can have more than BUFSIZE characters. If the field
|
||||
** width is larger than BUFSIZE, it is silently shortened. On the
|
||||
** other hand, this routine consumes more stack space with larger
|
||||
** BUFSIZEs. If you have some threads for which you want to minimize
|
||||
** stack space, you should keep BUFSIZE small.
|
||||
*/
|
||||
#define BUFSIZE 100 /* Size of the output buffer */
|
||||
|
||||
/*
|
||||
** The root program. All variations call this core.
|
||||
**
|
||||
** INPUTS:
|
||||
** func This is a pointer to a function taking three arguments
|
||||
** 1. A pointer to the list of characters to be output
|
||||
** (Note, this list is NOT null terminated.)
|
||||
** 2. An integer number of characters to be output.
|
||||
** (Note: This number might be zero.)
|
||||
** 3. A pointer to anything. Same as the "arg" parameter.
|
||||
**
|
||||
** arg This is the pointer to anything which will be passed as the
|
||||
** third argument to "func". Use it for whatever you like.
|
||||
**
|
||||
** fmt This is the format string, as in the usual print.
|
||||
**
|
||||
** ap This is a pointer to a list of arguments. Same as in
|
||||
** vfprint.
|
||||
**
|
||||
** OUTPUTS:
|
||||
** The return value is the total number of characters sent to
|
||||
** the function "func". Returns -1 on a error.
|
||||
**
|
||||
** Note that the order in which automatic variables are declared below
|
||||
** seems to make a big difference in determining how fast this beast
|
||||
** will run.
|
||||
*/
|
||||
|
||||
int vxprintf(func,arg,format,ap)
|
||||
void (*func)(char*,int,void*);
|
||||
void *arg;
|
||||
const char *format;
|
||||
va_list ap;
|
||||
{
|
||||
register const char *fmt; /* The format string. */
|
||||
register int c; /* Next character in the format string */
|
||||
register char *bufpt; /* Pointer to the conversion buffer */
|
||||
register int precision; /* Precision of the current field */
|
||||
register int length; /* Length of the field */
|
||||
register int idx; /* A general purpose loop counter */
|
||||
int count; /* Total number of characters output */
|
||||
int width; /* Width of the current field */
|
||||
int flag_leftjustify; /* True if "-" flag is present */
|
||||
int flag_plussign; /* True if "+" flag is present */
|
||||
int flag_blanksign; /* True if " " flag is present */
|
||||
int flag_alternateform; /* True if "#" flag is present */
|
||||
int flag_zeropad; /* True if field width constant starts with zero */
|
||||
int flag_long; /* True if "l" flag is present */
|
||||
int flag_center; /* True if "=" flag is present */
|
||||
unsigned long long longvalue; /* Value for integer types */
|
||||
|
||||
long double realvalue; /* Value for real types */
|
||||
info *infop; /* Pointer to the appropriate info structure */
|
||||
char buf[BUFSIZE]; /* Conversion buffer */
|
||||
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
|
||||
int errorflag = 0; /* True if an error is encountered */
|
||||
enum e_type xtype; /* Conversion paradigm */
|
||||
char *zMem = 0; /* String to be freed */
|
||||
static char spaces[] =
|
||||
" ";
|
||||
#define SPACESIZE (sizeof(spaces)-1)
|
||||
#ifndef NOFLOATINGPOINT
|
||||
int exp; /* exponent of real numbers */
|
||||
long double rounder; /* Used for rounding floating point values */
|
||||
int flag_dp; /* True if decimal point should be shown */
|
||||
int flag_rtz; /* True if trailing zeros should be removed */
|
||||
int flag_exp; /* True to force display of the exponent */
|
||||
int nsd; /* Number of significant digits returned */
|
||||
#endif
|
||||
|
||||
fmt = format; /* Put in a register for speed */
|
||||
count = length = 0;
|
||||
bufpt = 0;
|
||||
for(; (c=(*fmt))!=0; ++fmt){
|
||||
if( c!='%' ){
|
||||
register int amt;
|
||||
bufpt = (char *)fmt;
|
||||
amt = 1;
|
||||
while( (c=(*++fmt))!='%' && c!=0 ) amt++;
|
||||
(*func)(bufpt,amt,arg);
|
||||
count += amt;
|
||||
if( c==0 ) break;
|
||||
}
|
||||
if( (c=(*++fmt))==0 ){
|
||||
errorflag = 1;
|
||||
(*func)("%",1,arg);
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
/* Find out what flags are present */
|
||||
flag_leftjustify = flag_plussign = flag_blanksign =
|
||||
flag_alternateform = flag_zeropad = flag_center = 0;
|
||||
do{
|
||||
switch( c ){
|
||||
case '-': flag_leftjustify = 1; c = 0; break;
|
||||
case '+': flag_plussign = 1; c = 0; break;
|
||||
case ' ': flag_blanksign = 1; c = 0; break;
|
||||
case '#': flag_alternateform = 1; c = 0; break;
|
||||
case '0': flag_zeropad = 1; c = 0; break;
|
||||
case '=': flag_center = 1; c = 0; break;
|
||||
default: break;
|
||||
}
|
||||
}while( c==0 && (c=(*++fmt))!=0 );
|
||||
if( flag_center ) flag_leftjustify = 0;
|
||||
/* Get the field width */
|
||||
width = 0;
|
||||
if( c=='*' ){
|
||||
width = va_arg(ap,int);
|
||||
if( width<0 ){
|
||||
flag_leftjustify = 1;
|
||||
width = -width;
|
||||
}
|
||||
c = *++fmt;
|
||||
}else{
|
||||
while( isdigit(c) ){
|
||||
width = width*10 + c - '0';
|
||||
c = *++fmt;
|
||||
}
|
||||
}
|
||||
if( width > BUFSIZE-10 ){
|
||||
width = BUFSIZE-10;
|
||||
}
|
||||
/* Get the precision */
|
||||
if( c=='.' ){
|
||||
precision = 0;
|
||||
c = *++fmt;
|
||||
if( c=='*' ){
|
||||
precision = va_arg(ap,int);
|
||||
#ifndef COMPATIBILITY
|
||||
/* This is sensible, but SUN OS 4.1 doesn't do it. */
|
||||
if( precision<0 ) precision = -precision;
|
||||
#endif
|
||||
c = *++fmt;
|
||||
}else{
|
||||
while( isdigit(c) ){
|
||||
precision = precision*10 + c - '0';
|
||||
c = *++fmt;
|
||||
}
|
||||
}
|
||||
/* Limit the precision to prevent overflowing buf[] during conversion */
|
||||
if( precision>BUFSIZE-40 ) precision = BUFSIZE-40;
|
||||
}else{
|
||||
precision = -1;
|
||||
}
|
||||
/* Get the conversion type modifier */
|
||||
if( c=='l' ){
|
||||
flag_long = 1;
|
||||
c = *++fmt;
|
||||
if( c == 'l' ){
|
||||
flag_long = 2;
|
||||
c = *++fmt;
|
||||
}
|
||||
}else{
|
||||
flag_long = 0;
|
||||
}
|
||||
/* Fetch the info entry for the field */
|
||||
infop = 0;
|
||||
for(idx=0; idx<NINFO; idx++){
|
||||
if( c==fmtinfo[idx].fmttype ){
|
||||
infop = &fmtinfo[idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* No info entry found. It must be an error. */
|
||||
if( infop==0 ){
|
||||
xtype = ERROR;
|
||||
}else{
|
||||
xtype = infop->type;
|
||||
}
|
||||
|
||||
/*
|
||||
** At this point, variables are initialized as follows:
|
||||
**
|
||||
** flag_alternateform TRUE if a '#' is present.
|
||||
** flag_plussign TRUE if a '+' is present.
|
||||
** flag_leftjustify TRUE if a '-' is present or if the
|
||||
** field width was negative.
|
||||
** flag_zeropad TRUE if the width began with 0.
|
||||
** flag_long TRUE if the letter 'l' (ell) prefixed
|
||||
** the conversion character.
|
||||
** flag_blanksign TRUE if a ' ' is present.
|
||||
** width The specified field width. This is
|
||||
** always non-negative. Zero is the default.
|
||||
** precision The specified precision. The default
|
||||
** is -1.
|
||||
** xtype The class of the conversion.
|
||||
** infop Pointer to the appropriate info struct.
|
||||
*/
|
||||
switch( xtype ){
|
||||
case ORDINAL:
|
||||
case RADIX:
|
||||
if(( flag_long>1 )&&( infop->flag_signed )){
|
||||
signed long long t = va_arg(ap,signed long long);
|
||||
longvalue = t;
|
||||
}else if(( flag_long>1 )&&( !infop->flag_signed )){
|
||||
unsigned long long t = va_arg(ap,unsigned long long);
|
||||
longvalue = t;
|
||||
}else if(( flag_long )&&( infop->flag_signed )){
|
||||
signed long t = va_arg(ap,signed long);
|
||||
longvalue = t;
|
||||
}else if(( flag_long )&&( !infop->flag_signed )){
|
||||
unsigned long t = va_arg(ap,unsigned long);
|
||||
longvalue = t;
|
||||
}else if(( !flag_long )&&( infop->flag_signed )){
|
||||
signed int t = va_arg(ap,signed int) & ((unsigned long) 0xffffffff);
|
||||
longvalue = t;
|
||||
}else{
|
||||
unsigned int t = va_arg(ap,unsigned int) & ((unsigned long) 0xffffffff);
|
||||
longvalue = t;
|
||||
}
|
||||
#ifdef COMPATIBILITY
|
||||
/* For the format %#x, the value zero is printed "0" not "0x0".
|
||||
** I think this is stupid. */
|
||||
if( longvalue==0 ) flag_alternateform = 0;
|
||||
#else
|
||||
/* More sensible: turn off the prefix for octal (to prevent "00"),
|
||||
** but leave the prefix for hex. */
|
||||
if( longvalue==0 && infop->base==8 ) flag_alternateform = 0;
|
||||
#endif
|
||||
if( infop->flag_signed ){
|
||||
if( *(long long*)&longvalue<0 ){
|
||||
longvalue = -*(long long*)&longvalue;
|
||||
prefix = '-';
|
||||
}else if( flag_plussign ) prefix = '+';
|
||||
else if( flag_blanksign ) prefix = ' ';
|
||||
else prefix = 0;
|
||||
}else prefix = 0;
|
||||
if( flag_zeropad && precision<width-(prefix!=0) ){
|
||||
precision = width-(prefix!=0);
|
||||
}
|
||||
bufpt = &buf[BUFSIZE];
|
||||
if( xtype==ORDINAL ){
|
||||
long a,b;
|
||||
a = longvalue%10;
|
||||
b = longvalue%100;
|
||||
bufpt -= 2;
|
||||
if( a==0 || a>3 || (b>10 && b<14) ){
|
||||
bufpt[0] = 't';
|
||||
bufpt[1] = 'h';
|
||||
}else if( a==1 ){
|
||||
bufpt[0] = 's';
|
||||
bufpt[1] = 't';
|
||||
}else if( a==2 ){
|
||||
bufpt[0] = 'n';
|
||||
bufpt[1] = 'd';
|
||||
}else if( a==3 ){
|
||||
bufpt[0] = 'r';
|
||||
bufpt[1] = 'd';
|
||||
}
|
||||
}
|
||||
{
|
||||
register char *cset; /* Use registers for speed */
|
||||
register int base;
|
||||
cset = infop->charset;
|
||||
base = infop->base;
|
||||
do{ /* Convert to ascii */
|
||||
*(--bufpt) = cset[longvalue%base];
|
||||
longvalue = longvalue/base;
|
||||
}while( longvalue>0 );
|
||||
}
|
||||
length = (int)(&buf[BUFSIZE]-bufpt);
|
||||
if(infop->fmttype == 'p')
|
||||
{
|
||||
precision = 8;
|
||||
flag_alternateform = 1;
|
||||
}
|
||||
|
||||
for(idx=precision-length; idx>0; idx--){
|
||||
*(--bufpt) = '0'; /* Zero pad */
|
||||
}
|
||||
if( prefix ) *(--bufpt) = prefix; /* Add sign */
|
||||
if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
|
||||
char *pre, x;
|
||||
pre = infop->prefix;
|
||||
if( *bufpt!=pre[0] ){
|
||||
for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x;
|
||||
}
|
||||
}
|
||||
|
||||
length = (int)(&buf[BUFSIZE]-bufpt);
|
||||
break;
|
||||
case FLOAT:
|
||||
case EXP:
|
||||
case GENERIC:
|
||||
realvalue = va_arg(ap,double);
|
||||
#ifndef NOFLOATINGPOINT
|
||||
if( precision<0 ) precision = 6; /* Set default precision */
|
||||
if( precision>BUFSIZE-10 ) precision = BUFSIZE-10;
|
||||
if( realvalue<0.0 ){
|
||||
realvalue = -realvalue;
|
||||
prefix = '-';
|
||||
}else{
|
||||
if( flag_plussign ) prefix = '+';
|
||||
else if( flag_blanksign ) prefix = ' ';
|
||||
else prefix = 0;
|
||||
}
|
||||
if( infop->type==GENERIC && precision>0 ) precision--;
|
||||
rounder = 0.0;
|
||||
#ifdef COMPATIBILITY
|
||||
/* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
|
||||
for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
|
||||
#else
|
||||
/* It makes more sense to use 0.5 */
|
||||
if( precision>MAXDIG-1 ) idx = MAXDIG-1;
|
||||
else idx = precision;
|
||||
for(rounder=0.5; idx>0; idx--, rounder*=0.1);
|
||||
#endif
|
||||
if( infop->type==FLOAT ) realvalue += rounder;
|
||||
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
|
||||
exp = 0;
|
||||
if( realvalue>0.0 ){
|
||||
int k = 0;
|
||||
while( realvalue>=1e8 && k++<100 ){ realvalue *= 1e-8; exp+=8; }
|
||||
while( realvalue>=10.0 && k++<100 ){ realvalue *= 0.1; exp++; }
|
||||
while( realvalue<1e-8 && k++<100 ){ realvalue *= 1e8; exp-=8; }
|
||||
while( realvalue<1.0 && k++<100 ){ realvalue *= 10.0; exp--; }
|
||||
if( k>=100 ){
|
||||
bufpt = "NaN";
|
||||
length = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bufpt = buf;
|
||||
/*
|
||||
** If the field type is GENERIC, then convert to either EXP
|
||||
** or FLOAT, as appropriate.
|
||||
*/
|
||||
flag_exp = xtype==EXP;
|
||||
if( xtype!=FLOAT ){
|
||||
realvalue += rounder;
|
||||
if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
|
||||
}
|
||||
if( xtype==GENERIC ){
|
||||
flag_rtz = !flag_alternateform;
|
||||
if( exp<-4 || exp>precision ){
|
||||
xtype = EXP;
|
||||
}else{
|
||||
precision = precision - exp;
|
||||
xtype = FLOAT;
|
||||
}
|
||||
}else{
|
||||
flag_rtz = 0;
|
||||
}
|
||||
/*
|
||||
** The "exp+precision" test causes output to be of type EXP if
|
||||
** the precision is too large to fit in buf[].
|
||||
*/
|
||||
nsd = 0;
|
||||
if( xtype==FLOAT && exp+precision<BUFSIZE-30 ){
|
||||
flag_dp = (precision>0 || flag_alternateform);
|
||||
if( prefix ) *(bufpt++) = prefix; /* Sign */
|
||||
if( exp<0 ) *(bufpt++) = '0'; /* Digits before "." */
|
||||
else for(; exp>=0; exp--) *(bufpt++) = getdigit(&realvalue,&nsd);
|
||||
if( flag_dp ) *(bufpt++) = '.'; /* The decimal point */
|
||||
for(exp++; exp<0 && precision>0; precision--, exp++){
|
||||
*(bufpt++) = '0';
|
||||
}
|
||||
while( (precision--)>0 ) *(bufpt++) = getdigit(&realvalue,&nsd);
|
||||
*(bufpt--) = 0; /* Null terminate */
|
||||
if( flag_rtz && flag_dp ){ /* Remove trailing zeros and "." */
|
||||
while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
|
||||
if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
|
||||
}
|
||||
bufpt++; /* point to next free slot */
|
||||
}else{ /* EXP or GENERIC */
|
||||
flag_dp = (precision>0 || flag_alternateform);
|
||||
if( prefix ) *(bufpt++) = prefix; /* Sign */
|
||||
*(bufpt++) = getdigit(&realvalue,&nsd); /* First digit */
|
||||
if( flag_dp ) *(bufpt++) = '.'; /* Decimal point */
|
||||
while( (precision--)>0 ) *(bufpt++) = getdigit(&realvalue,&nsd);
|
||||
bufpt--; /* point to last digit */
|
||||
if( flag_rtz && flag_dp ){ /* Remove tail zeros */
|
||||
while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
|
||||
if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
|
||||
}
|
||||
bufpt++; /* point to next free slot */
|
||||
if( exp || flag_exp ){
|
||||
*(bufpt++) = infop->charset[0];
|
||||
if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */
|
||||
else { *(bufpt++) = '+'; }
|
||||
if( exp>=100 ){
|
||||
*(bufpt++) = (exp/100)+'0'; /* 100's digit */
|
||||
exp %= 100;
|
||||
}
|
||||
*(bufpt++) = exp/10+'0'; /* 10's digit */
|
||||
*(bufpt++) = exp%10+'0'; /* 1's digit */
|
||||
}
|
||||
}
|
||||
/* The converted number is in buf[] and zero terminated. Output it.
|
||||
** Note that the number is in the usual order, not reversed as with
|
||||
** integer conversions. */
|
||||
length = (int)(bufpt-buf);
|
||||
bufpt = buf;
|
||||
|
||||
/* Special case: Add leading zeros if the flag_zeropad flag is
|
||||
** set and we are not left justified */
|
||||
if( flag_zeropad && !flag_leftjustify && length < width){
|
||||
int i;
|
||||
int nPad = width - length;
|
||||
for(i=width; i>=nPad; i--){
|
||||
bufpt[i] = bufpt[i-nPad];
|
||||
}
|
||||
i = prefix!=0;
|
||||
while( nPad-- ) bufpt[i++] = '0';
|
||||
length = width;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case SIZE:
|
||||
*(va_arg(ap,int*)) = count;
|
||||
length = width = 0;
|
||||
break;
|
||||
case PERCENT:
|
||||
buf[0] = '%';
|
||||
bufpt = buf;
|
||||
length = 1;
|
||||
break;
|
||||
case CHARLIT:
|
||||
case CHAR:
|
||||
c = buf[0] = (xtype==CHAR ? va_arg(ap,int) : *++fmt);
|
||||
if( precision>=0 ){
|
||||
for(idx=1; idx<precision; idx++) buf[idx] = c;
|
||||
length = precision;
|
||||
}else{
|
||||
length =1;
|
||||
}
|
||||
bufpt = buf;
|
||||
break;
|
||||
case STRING:
|
||||
case MEM_STRING:
|
||||
zMem = bufpt = va_arg(ap,char*);
|
||||
if( bufpt==0 ) bufpt = "(null)";
|
||||
length = strlen(bufpt);
|
||||
if( precision>=0 && precision<length ) length = precision;
|
||||
break;
|
||||
case SEEIT:
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
char *arg = va_arg(ap,char*);
|
||||
for(i=0; i<BUFSIZE-1 && (c = *arg++)!=0; i++){
|
||||
if( c<0x20 || c>=0x7f ){
|
||||
buf[i++] = '^';
|
||||
buf[i] = (c&0x1f)+0x40;
|
||||
}else{
|
||||
buf[i] = c;
|
||||
}
|
||||
}
|
||||
bufpt = buf;
|
||||
length = i;
|
||||
if( precision>=0 && precision<length ) length = precision;
|
||||
}
|
||||
break;
|
||||
case ERROR:
|
||||
buf[0] = '%';
|
||||
buf[1] = c;
|
||||
errorflag = 0;
|
||||
idx = 1+(c!=0);
|
||||
(*func)("%",idx,arg);
|
||||
count += idx;
|
||||
if( c==0 ) fmt--;
|
||||
break;
|
||||
}/* End switch over the format type */
|
||||
/*
|
||||
** The text of the conversion is pointed to by "bufpt" and is
|
||||
** "length" characters long. The field width is "width". Do
|
||||
** the output.
|
||||
*/
|
||||
if( !flag_leftjustify ){
|
||||
register int nspace;
|
||||
nspace = width-length;
|
||||
if( nspace>0 ){
|
||||
if( flag_center ){
|
||||
nspace = nspace/2;
|
||||
width -= nspace;
|
||||
flag_leftjustify = 1;
|
||||
}
|
||||
count += nspace;
|
||||
while( nspace>=SPACESIZE ){
|
||||
(*func)(spaces,SPACESIZE,arg);
|
||||
nspace -= SPACESIZE;
|
||||
}
|
||||
if( nspace>0 ) (*func)(spaces,nspace,arg);
|
||||
}
|
||||
}
|
||||
if( length>0 ){
|
||||
(*func)(bufpt,length,arg);
|
||||
count += length;
|
||||
}
|
||||
if( xtype==MEM_STRING && zMem ){
|
||||
free(zMem);
|
||||
}
|
||||
if( flag_leftjustify ){
|
||||
register int nspace;
|
||||
nspace = width-length;
|
||||
if( nspace>0 ){
|
||||
count += nspace;
|
||||
while( nspace>=SPACESIZE ){
|
||||
(*func)(spaces,SPACESIZE,arg);
|
||||
nspace -= SPACESIZE;
|
||||
}
|
||||
if( nspace>0 ) (*func)(spaces,nspace,arg);
|
||||
}
|
||||
}
|
||||
}/* End for loop over the format string */
|
||||
return errorflag ? -1 : count;
|
||||
} /* End of function */
|
||||
#endif
|
||||
|
||||
#ifdef F__xprintf
|
||||
/*
|
||||
** This non-standard function is still occasionally useful....
|
||||
*/
|
||||
int xprintf(
|
||||
void (*func)(char*,int,void*),
|
||||
void *arg,
|
||||
const char *format,
|
||||
...
|
||||
){
|
||||
va_list ap;
|
||||
va_start(ap,format);
|
||||
return vxprintf(func,arg,format,ap);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Now for string-print, also as found in any standard library.
|
||||
** Add to this the snprint function which stops added characters
|
||||
** to the string at a given length.
|
||||
**
|
||||
** Note that snprint returns the length of the string as it would
|
||||
** be if there were no limit on the output.
|
||||
*/
|
||||
struct s_strargument { /* Describes the string being written to */
|
||||
char *next; /* Next free slot in the string */
|
||||
char *last; /* Last available slot in the string */
|
||||
};
|
||||
|
||||
void __sout(char *, int, void *);
|
||||
#ifdef F___sout
|
||||
void __sout(txt,amt,arg)
|
||||
char *txt;
|
||||
int amt;
|
||||
void *arg;
|
||||
{
|
||||
register char *head;
|
||||
register const char *t;
|
||||
register int a;
|
||||
register char *tail;
|
||||
a = amt;
|
||||
t = txt;
|
||||
head = ((struct s_strargument*)arg)->next;
|
||||
tail = ((struct s_strargument*)arg)->last;
|
||||
if( tail ){
|
||||
while( a-- >0 && head<tail ) *(head++) = *(t++);
|
||||
}else{
|
||||
while( a-- >0 ) *(head++) = *(t++);
|
||||
}
|
||||
*head = 0;
|
||||
((struct s_strargument*)arg)->next = head;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_vsnprintf
|
||||
int vsnprintf(char *buf, size_t n, const char *fmt, va_list ap){
|
||||
struct s_strargument arg;
|
||||
arg.next = buf;
|
||||
arg.last = &buf[n-1];
|
||||
*buf = 0;
|
||||
return vxprintf(__sout,&arg,fmt,ap);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_snprintf
|
||||
int snprintf(char *str, size_t sz, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
struct s_strargument arg;
|
||||
int ret;
|
||||
|
||||
arg.next = str;
|
||||
arg.last = &str[sz-1];
|
||||
|
||||
va_start(args, format);
|
||||
ret = vxprintf(__sout, &arg, format, args);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_vsprintf
|
||||
int vsprintf(char *buf, const char *fmt, va_list ap){
|
||||
struct s_strargument arg;
|
||||
arg.next = buf;
|
||||
arg.last = NULL;
|
||||
*buf = 0;
|
||||
return vxprintf(__sout,&arg,fmt,ap);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_sprintf
|
||||
__attribute__((weak))
|
||||
int sprintf (char *str, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
struct s_strargument arg;
|
||||
int ret;
|
||||
|
||||
arg.next = str;
|
||||
arg.last = NULL;
|
||||
|
||||
va_start(args, format);
|
||||
ret = vxprintf(__sout, &arg, format, args);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The following section of code handles the mprintf routine, that
|
||||
** writes to memory obtained from malloc().
|
||||
*/
|
||||
|
||||
/* This structure is used to store state information about the
|
||||
** write in progress
|
||||
*/
|
||||
__attribute__((weak))
|
||||
struct sgMprintf {
|
||||
char *zBase; /* A base allocation */
|
||||
char *zText; /* The string collected so far */
|
||||
int nChar; /* Length of the string so far */
|
||||
int nAlloc; /* Amount of space allocated in zText */
|
||||
};
|
||||
|
||||
void __mout(char *, int, void*);
|
||||
|
||||
#ifdef F___mout
|
||||
/* The xprintf callback function. */
|
||||
void __mout(zNewText,nNewChar,arg)
|
||||
char *zNewText;
|
||||
int nNewChar;
|
||||
void *arg;
|
||||
{
|
||||
struct sgMprintf *pM = (struct sgMprintf*)arg;
|
||||
if( pM->nChar + nNewChar + 1 > pM->nAlloc ){
|
||||
pM->nAlloc = pM->nChar + nNewChar*2 + 1;
|
||||
if( pM->zText==pM->zBase ){
|
||||
pM->zText = malloc(pM->nAlloc);
|
||||
if( pM->zText && pM->nChar ) memcpy(pM->zText,pM->zBase,pM->nChar);
|
||||
}else{
|
||||
pM->zText = realloc(pM->zText, pM->nAlloc);
|
||||
}
|
||||
}
|
||||
if( pM->zText ){
|
||||
memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
|
||||
pM->nChar += nNewChar;
|
||||
pM->zText[pM->nChar] = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** mprintf() works like printf(), but allocations memory to hold the
|
||||
** resulting string and returns a pointer to the allocated memory.
|
||||
**
|
||||
** We changed the name to TclMPrint() to conform with the Tcl private
|
||||
** routine naming conventions.
|
||||
*/
|
||||
|
||||
#ifdef F_mprintf
|
||||
char *mprintf(const char *zFormat, ...){
|
||||
va_list ap;
|
||||
struct sgMprintf sMprintf;
|
||||
char *zNew;
|
||||
char zBuf[200];
|
||||
|
||||
va_start(ap,zFormat);
|
||||
sMprintf.nChar = 0;
|
||||
sMprintf.nAlloc = sizeof(zBuf);
|
||||
sMprintf.zText = zBuf;
|
||||
sMprintf.zBase = zBuf;
|
||||
vxprintf(__mout,&sMprintf,zFormat,ap);
|
||||
va_end(ap);
|
||||
if( sMprintf.zText==sMprintf.zBase ){
|
||||
zNew = malloc( sMprintf.nChar+1 );
|
||||
if( zNew ) strcpy(zNew,zBuf);
|
||||
}else{
|
||||
zNew = realloc(sMprintf.zText,sMprintf.nChar+1);
|
||||
}
|
||||
|
||||
return zNew;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This is the varargs version of mprintf.
|
||||
**
|
||||
** The name is changed to TclVMPrintf() to conform with Tcl naming
|
||||
** conventions.
|
||||
*/
|
||||
#ifdef F_vmprintf
|
||||
char *vmprintf(const char *zFormat,va_list ap){
|
||||
struct sgMprintf sMprintf;
|
||||
char zBuf[200];
|
||||
sMprintf.nChar = 0;
|
||||
sMprintf.zText = zBuf;
|
||||
sMprintf.nAlloc = sizeof(zBuf);
|
||||
sMprintf.zBase = zBuf;
|
||||
vxprintf(__mout,&sMprintf,zFormat,ap);
|
||||
if( sMprintf.zText==sMprintf.zBase ){
|
||||
sMprintf.zText = malloc( strlen(zBuf)+1 );
|
||||
if( sMprintf.zText ) strcpy(sMprintf.zText,zBuf);
|
||||
}else{
|
||||
sMprintf.zText = realloc(sMprintf.zText,sMprintf.nChar+1);
|
||||
}
|
||||
return sMprintf.zText;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_asprintf
|
||||
int asprintf(char ** strp, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
struct sgMprintf sMprintf;
|
||||
char *zNew;
|
||||
char zBuf[200];
|
||||
|
||||
va_start(ap,zFormat);
|
||||
sMprintf.nChar = 0;
|
||||
sMprintf.nAlloc = sizeof(zBuf);
|
||||
sMprintf.zText = zBuf;
|
||||
sMprintf.zBase = zBuf;
|
||||
vxprintf(__mout,&sMprintf,zFormat,ap);
|
||||
va_end(ap);
|
||||
if( sMprintf.zText==sMprintf.zBase ){
|
||||
zNew = malloc( sMprintf.nChar+1 );
|
||||
if( zNew ) strcpy(zNew,zBuf);
|
||||
}else{
|
||||
zNew = realloc(sMprintf.zText,sMprintf.nChar+1);
|
||||
}
|
||||
|
||||
*strp = zNew;
|
||||
|
||||
return sMprintf.nChar+1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_vasprintf
|
||||
int vasprintf(char **strp, const char *format, va_list ap) {
|
||||
struct sgMprintf sMprintf;
|
||||
char zBuf[200];
|
||||
sMprintf.nChar = 0;
|
||||
sMprintf.zText = zBuf;
|
||||
sMprintf.nAlloc = sizeof(zBuf);
|
||||
sMprintf.zBase = zBuf;
|
||||
vxprintf(__mout,&sMprintf,format,ap);
|
||||
if( sMprintf.zText==sMprintf.zBase ){
|
||||
sMprintf.zText = malloc( strlen(zBuf)+1 );
|
||||
if( sMprintf.zText ) strcpy(sMprintf.zText,zBuf);
|
||||
}else{
|
||||
sMprintf.zText = realloc(sMprintf.zText,sMprintf.nChar+1);
|
||||
}
|
||||
*strp = sMprintf.zText;
|
||||
return sMprintf.nChar;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The following section of code handles the standard fprintf routines
|
||||
** for pthreads.
|
||||
*/
|
||||
|
||||
void __fout(char *, int, void *);
|
||||
|
||||
#ifdef F___fout
|
||||
void __fout(zNewText,nNewChar,arg)
|
||||
char *zNewText;
|
||||
int nNewChar;
|
||||
void *arg;
|
||||
{
|
||||
fwrite(zNewText,1,nNewChar,(FILE*)arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_fprintf
|
||||
/* The public interface routines */
|
||||
int fprintf(FILE *pOut, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int retc;
|
||||
|
||||
va_start(ap,zFormat);
|
||||
retc = vxprintf(__fout,pOut,zFormat,ap);
|
||||
va_end(ap);
|
||||
return retc;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_vfprintf
|
||||
int vfprintf(FILE *pOut, const char *zFormat, va_list ap){
|
||||
return vxprintf(__fout,pOut,zFormat,ap);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef F_printf
|
||||
int printf(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
int ret;
|
||||
|
||||
va_start(args, format);
|
||||
ret = vprintf(format, args);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_vprintf
|
||||
int vprintf(const char *format, va_list args)
|
||||
{
|
||||
static char buf[PS2LIB_STR_MAX];
|
||||
int ret;
|
||||
|
||||
ret = vsnprintf(buf, PS2LIB_STR_MAX, format, args);
|
||||
|
||||
sceIoWrite(1, buf, ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef F_putchar
|
||||
/* Get rid of the newlib macro definition. */
|
||||
#ifdef putchar
|
||||
#undef putchar
|
||||
#endif
|
||||
int putchar( int chr )
|
||||
{
|
||||
sceIoWrite(1, &chr, 1);
|
||||
return chr;
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user